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
27int 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}