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