ref locking: allow 'foo' when 'foo/bar' used to exist but not anymore.
[git/dscho.git] / interpolate.c
blob4570c123dce811bab8a89efe4c3b4a9a977e6c5a
1 /*
2 * Copyright 2006 Jon Loeliger
3 */
5 #include <string.h>
7 #include "interpolate.h"
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.
16 * Example interps:
17 * {
18 * { "%H", "example.org"},
19 * { "%port", "123"},
20 * { "%%", "%"},
21 * }
23 * Returns 1 on a successful substitution pass that fits in result,
24 * Returns 0 on a failed or overflowing substitution pass.
27 int interpolate(char *result, int reslen,
28 const char *orig,
29 const struct interp *interps, int ninterps)
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;
39 memset(result, 0, reslen);
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;
52 /* Check for valid interpolation. */
53 if (i < ninterps) {
54 value = interps[i].value;
55 valuelen = strlen(value);
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;
68 } else {
69 /* Skip bogus interpolation. */
70 *dest++ = *src++;
71 newlen++;
74 } else {
75 /* Straight copy one non-interpolation character. */
76 *dest++ = *src++;
77 newlen++;
81 return newlen < reslen - 1;