diff options
Diffstat (limited to 'interpolate.c')
-rw-r--r-- | interpolate.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/interpolate.c b/interpolate.c new file mode 100644 index 0000000000..00826778fc --- /dev/null +++ b/interpolate.c @@ -0,0 +1,102 @@ +/* + * Copyright 2006 Jon Loeliger + */ + +#include "git-compat-util.h" +#include "interpolate.h" + + +void interp_set_entry(struct interp *table, int slot, const char *value) +{ + char *oldval = table[slot].value; + char *newval = NULL; + + if (oldval) + free(oldval); + + if (value) + newval = xstrdup(value); + + table[slot].value = newval; +} + + +void interp_clear_table(struct interp *table, int ninterps) +{ + int i; + + for (i = 0; i < ninterps; i++) { + interp_set_entry(table, i, NULL); + } +} + + +/* + * Convert a NUL-terminated string in buffer orig + * into the supplied buffer, result, whose length is reslen, + * performing substitutions on %-named sub-strings from + * the table, interps, with ninterps entries. + * + * Example interps: + * { + * { "%H", "example.org"}, + * { "%port", "123"}, + * { "%%", "%"}, + * } + * + * Returns 0 on a successful substitution pass that fits in result, + * Returns a number of bytes needed to hold the full substituted + * string otherwise. + */ + +unsigned long interpolate(char *result, unsigned long reslen, + const char *orig, + const struct interp *interps, int ninterps) +{ + const char *src = orig; + char *dest = result; + unsigned long newlen = 0; + const char *name, *value; + unsigned long namelen, valuelen; + int i; + char c; + + memset(result, 0, reslen); + + while ((c = *src)) { + if (c == '%') { + /* Try to match an interpolation string. */ + for (i = 0; i < ninterps; i++) { + name = interps[i].name; + namelen = strlen(name); + if (strncmp(src, name, namelen) == 0) + break; + } + + /* Check for valid interpolation. */ + if (i < ninterps) { + value = interps[i].value; + valuelen = strlen(value); + + if (newlen + valuelen + 1 < reslen) { + /* Substitute. */ + strncpy(dest, value, valuelen); + dest += valuelen; + } + newlen += valuelen; + src += namelen; + continue; + } + } + /* Straight copy one non-interpolation character. */ + if (newlen + 1 < reslen) + *dest++ = *src; + src++; + newlen++; + } + + if (newlen + 1 < reslen) + return 0; + else + return newlen + 2; +} |