refs: minor restructuring of cached refs data.
[git] / interpolate.c
1 /*
2  * Copyright 2006 Jon Loeliger
3  */
4
5 #include <string.h>
6
7 #include "interpolate.h"
8
9
10 /*
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.
15  *
16  * Example interps:
17  *    {
18  *        { "%H", "example.org"},
19  *        { "%port", "123"},
20  *        { "%%", "%"},
21  *    }
22  *
23  * Returns 1 on a successful substitution pass that fits in result,
24  * Returns 0 on a failed or overflowing substitution pass.
25  */
26
27 int interpolate(char *result, int reslen,
28                 const char *orig,
29                 const struct interp *interps, int ninterps)
30 {
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;
38
39         memset(result, 0, reslen);
40
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;
49                                 }
50                         }
51
52                         /* Check for valid interpolation. */
53                         if (i < ninterps) {
54                                 value = interps[i].value;
55                                 valuelen = strlen(value);
56
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;
66                                 }
67
68                         } else {
69                                 /* Skip bogus interpolation. */
70                                 *dest++ = *src++;
71                                 newlen++;
72                         }
73
74                 } else {
75                         /* Straight copy one non-interpolation character. */
76                         *dest++ = *src++;
77                         newlen++;
78                 }
79         }
80
81         return newlen < reslen - 1;
82 }