interpolate.con commit Merge branch 'master' into lj/refs (2958d9b)
   1/*
   2 * Copyright 2006 Jon Loeliger
   3 */
   4
   5#include <string.h>
   6
   7#include "interpolate.h"
   8
   9
  10/*
  11 * Convert a NUL-terminated string in buffer orig
  12 * into the supplied buffer, result, whose length is reslen,
  13 * performing substitutions on %-named sub-strings from
  14 * the table, interps, with ninterps entries.
  15 *
  16 * Example interps:
  17 *    {
  18 *        { "%H", "example.org"},
  19 *        { "%port", "123"},
  20 *        { "%%", "%"},
  21 *    }
  22 *
  23 * Returns 1 on a successful substitution pass that fits in result,
  24 * Returns 0 on a failed or overflowing substitution pass.
  25 */
  26
  27int interpolate(char *result, int reslen,
  28                const char *orig,
  29                const struct interp *interps, int ninterps)
  30{
  31        const char *src = orig;
  32        char *dest = result;
  33        int newlen = 0;
  34        char *name, *value;
  35        int namelen, valuelen;
  36        int i;
  37        char c;
  38
  39        memset(result, 0, reslen);
  40
  41        while ((c = *src) && newlen < reslen - 1) {
  42                if (c == '%') {
  43                        /* Try to match an interpolation string. */
  44                        for (i = 0; i < ninterps; i++) {
  45                                name = interps[i].name;
  46                                namelen = strlen(name);
  47                                if (strncmp(src, name, namelen) == 0) {
  48                                        break;
  49                                }
  50                        }
  51
  52                        /* Check for valid interpolation. */
  53                        if (i < ninterps) {
  54                                value = interps[i].value;
  55                                valuelen = strlen(value);
  56
  57                                if (newlen + valuelen < reslen - 1) {
  58                                        /* Substitute. */
  59                                        strncpy(dest, value, valuelen);
  60                                        newlen += valuelen;
  61                                        dest += valuelen;
  62                                        src += namelen;
  63                                } else {
  64                                        /* Something's not fitting. */
  65                                        return 0;
  66                                }
  67
  68                        } else {
  69                                /* Skip bogus interpolation. */
  70                                *dest++ = *src++;
  71                                newlen++;
  72                        }
  73
  74                } else {
  75                        /* Straight copy one non-interpolation character. */
  76                        *dest++ = *src++;
  77                        newlen++;
  78                }
  79        }
  80
  81        return newlen < reslen - 1;
  82}