interpolate.con commit Merge branch 'master' of git://git.kernel.org/pub/scm/gitk/gitk (f8db788)
   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 0 on a successful substitution pass that fits in result,
  48 * Returns a number of bytes needed to hold the full substituted
  49 * string otherwise.
  50 */
  51
  52unsigned long interpolate(char *result, unsigned long reslen,
  53                const char *orig,
  54                const struct interp *interps, int ninterps)
  55{
  56        const char *src = orig;
  57        char *dest = result;
  58        unsigned long newlen = 0;
  59        const char *name, *value;
  60        unsigned long namelen, valuelen;
  61        int i;
  62        char c;
  63
  64        memset(result, 0, reslen);
  65
  66        while ((c = *src)) {
  67                if (c == '%') {
  68                        /* Try to match an interpolation string. */
  69                        for (i = 0; i < ninterps; i++) {
  70                                name = interps[i].name;
  71                                namelen = strlen(name);
  72                                if (strncmp(src, name, namelen) == 0)
  73                                        break;
  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 + 1 < reslen) {
  82                                        /* Substitute. */
  83                                        strncpy(dest, value, valuelen);
  84                                        dest += valuelen;
  85                                }
  86                                newlen += valuelen;
  87                                src += namelen;
  88                                continue;
  89                        }
  90                }
  91                /* Straight copy one non-interpolation character. */
  92                if (newlen + 1 < reslen)
  93                        *dest++ = *src;
  94                src++;
  95                newlen++;
  96        }
  97
  98        if (newlen + 1 < reslen)
  99                return 0;
 100        else
 101                return newlen + 2;
 102}