git-commit: partial commit of paths only removed from the index
[gitweb.git] / interpolate.c
index d82f1b51bbff4a545a2d5a0aebb91612cacd3d69..00826778fc3d760a9b001423cd9c26e7972c126f 100644 (file)
@@ -2,11 +2,35 @@
  * Copyright 2006 Jon Loeliger
  */
 
-#include <string.h>
-
+#include "git-compat-util.h"
 #include "interpolate.h"
 
 
+void interp_set_entry(struct interp *table, int slot, const char *value)
+{
+       char *oldval = table[slot].value;
+       char *newval = NULL;
+
+       if (oldval)
+               free(oldval);
+
+       if (value)
+               newval = xstrdup(value);
+
+       table[slot].value = newval;
+}
+
+
+void interp_clear_table(struct interp *table, int ninterps)
+{
+       int i;
+
+       for (i = 0; i < ninterps; i++) {
+               interp_set_entry(table, i, NULL);
+       }
+}
+
+
 /*
  * Convert a NUL-terminated string in buffer orig
  * into the supplied buffer, result, whose length is reslen,
  *        { "%%", "%"},
  *    }
  *
- * Returns 1 on a successful substitution pass that fits in result,
- * Returns 0 on a failed or overflowing substitution pass.
+ * Returns 0 on a successful substitution pass that fits in result,
+ * Returns a number of bytes needed to hold the full substituted
+ * string otherwise.
  */
 
-int interpolate(char *result, int reslen,
-               char *orig,
-               struct interp *interps, int ninterps)
+unsigned long interpolate(char *result, unsigned long reslen,
+               const char *orig,
+               const struct interp *interps, int ninterps)
 {
-       char *src = orig;
+       const char *src = orig;
        char *dest = result;
-       int newlen = 0;
-       char *name, *value;
-       int namelen, valuelen;
+       unsigned long newlen = 0;
+       const char *name, *value;
+       unsigned long namelen, valuelen;
        int i;
        char c;
 
         memset(result, 0, reslen);
 
-       while ((c = *src) && newlen < reslen - 1) {
+       while ((c = *src)) {
                if (c == '%') {
                        /* Try to match an interpolation string. */
                        for (i = 0; i < ninterps; i++) {
                                name = interps[i].name;
                                namelen = strlen(name);
-                               if (strncmp(src, name, namelen) == 0) {
+                               if (strncmp(src, name, namelen) == 0)
                                        break;
-                               }
                        }
 
                        /* Check for valid interpolation. */
@@ -54,29 +78,25 @@ int interpolate(char *result, int reslen,
                                value = interps[i].value;
                                valuelen = strlen(value);
 
-                               if (newlen + valuelen < reslen - 1) {
+                               if (newlen + valuelen + 1 < reslen) {
                                        /* Substitute. */
                                        strncpy(dest, value, valuelen);
-                                       newlen += valuelen;
                                        dest += valuelen;
-                                       src += namelen;
-                               } else {
-                                       /* Something's not fitting. */
-                                       return 0;
                                }
-
-                       } else {
-                               /* Skip bogus interpolation. */
-                               *dest++ = *src++;
-                               newlen++;
+                               newlen += valuelen;
+                               src += namelen;
+                               continue;
                        }
-
-               } else {
-                       /* Straight copy one non-interpolation character. */
-                       *dest++ = *src++;
-                       newlen++;
                }
+               /* Straight copy one non-interpolation character. */
+               if (newlen + 1 < reslen)
+                       *dest++ = *src;
+               src++;
+               newlen++;
        }
 
-       return newlen < reslen - 1;
+       if (newlen + 1 < reslen)
+               return 0;
+       else
+               return newlen + 2;
 }