interpolate.con commit diff-format.txt: Combined diff format documentation supplement (0074aba)
   1/*
   2 * Copyright 2006 Jon Loeliger
   3 */
   4
   5#include <string.h>
   6
   7#include "git-compat-util.h"
   8#include "interpolate.h"
   9
  10
  11void interp_set_entry(struct interp *table, int slot, const char *value)
  12{
  13        char *oldval = table[slot].value;
  14        char *newval = NULL;
  15
  16        if (oldval)
  17                free(oldval);
  18
  19        if (value)
  20                newval = xstrdup(value);
  21
  22        table[slot].value = newval;
  23}
  24
  25
  26void interp_clear_table(struct interp *table, int ninterps)
  27{
  28        int i;
  29
  30        for (i = 0; i < ninterps; i++) {
  31                interp_set_entry(table, i, NULL);
  32        }
  33}
  34
  35
  36/*
  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.
  41 *
  42 * Example interps:
  43 *    {
  44 *        { "%H", "example.org"},
  45 *        { "%port", "123"},
  46 *        { "%%", "%"},
  47 *    }
  48 *
  49 * Returns 1 on a successful substitution pass that fits in result,
  50 * Returns 0 on a failed or overflowing substitution pass.
  51 */
  52
  53int interpolate(char *result, int reslen,
  54                const char *orig,
  55                const struct interp *interps, int ninterps)
  56{
  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;
  64
  65        memset(result, 0, reslen);
  66
  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;
  75                                }
  76                        }
  77
  78                        /* Check for valid interpolation. */
  79                        if (i < ninterps) {
  80                                value = interps[i].value;
  81                                valuelen = strlen(value);
  82
  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;
  92                                }
  93
  94                        } else {
  95                                /* Skip bogus interpolation. */
  96                                *dest++ = *src++;
  97                                newlen++;
  98                        }
  99
 100                } else {
 101                        /* Straight copy one non-interpolation character. */
 102                        *dest++ = *src++;
 103                        newlen++;
 104                }
 105        }
 106
 107        return newlen < reslen - 1;
 108}