Documentation/git-commit: rewrite to make it more end-user friendly.
[git/dscho.git] / interpolate.c
blob5d9d1889f088c64131cd3c116e6a16876ce95db8
1 /*
2 * Copyright 2006 Jon Loeliger
3 */
5 #include <string.h>
7 #include "git-compat-util.h"
8 #include "interpolate.h"
11 void interp_set_entry(struct interp *table, int slot, const char *value)
13 char *oldval = table[slot].value;
14 char *newval = NULL;
16 if (oldval)
17 free(oldval);
19 if (value)
20 newval = xstrdup(value);
22 table[slot].value = newval;
26 void interp_clear_table(struct interp *table, int ninterps)
28 int i;
30 for (i = 0; i < ninterps; i++) {
31 interp_set_entry(table, i, NULL);
37 * Convert a NUL-terminated string in buffer orig
38 * into the supplied buffer, result, whose length is reslen,
39 * performing substitutions on %-named sub-strings from
40 * the table, interps, with ninterps entries.
42 * Example interps:
43 * {
44 * { "%H", "example.org"},
45 * { "%port", "123"},
46 * { "%%", "%"},
47 * }
49 * Returns 1 on a successful substitution pass that fits in result,
50 * Returns 0 on a failed or overflowing substitution pass.
53 int interpolate(char *result, int reslen,
54 const char *orig,
55 const struct interp *interps, int ninterps)
57 const char *src = orig;
58 char *dest = result;
59 int newlen = 0;
60 char *name, *value;
61 int namelen, valuelen;
62 int i;
63 char c;
65 memset(result, 0, reslen);
67 while ((c = *src) && newlen < reslen - 1) {
68 if (c == '%') {
69 /* Try to match an interpolation string. */
70 for (i = 0; i < ninterps; i++) {
71 name = interps[i].name;
72 namelen = strlen(name);
73 if (strncmp(src, name, namelen) == 0) {
74 break;
78 /* Check for valid interpolation. */
79 if (i < ninterps) {
80 value = interps[i].value;
81 valuelen = strlen(value);
83 if (newlen + valuelen < reslen - 1) {
84 /* Substitute. */
85 strncpy(dest, value, valuelen);
86 newlen += valuelen;
87 dest += valuelen;
88 src += namelen;
89 } else {
90 /* Something's not fitting. */
91 return 0;
94 } else {
95 /* Skip bogus interpolation. */
96 *dest++ = *src++;
97 newlen++;
100 } else {
101 /* Straight copy one non-interpolation character. */
102 *dest++ = *src++;
103 newlen++;
107 return newlen < reslen - 1;