80583c0ef6
Traditionally we had 16kB limit when formatting log messages for output, because it was easier to arrange for the caller to have a reasonably big buffer and pass it down without ever worrying about reallocating. This changes the calling convention of pretty_print_commit() to lift this limit. Instead of the buffer and remaining length, it now takes a pointer to the pointer that points at the allocated buffer, and another pointer to the location that stores the allocated length, and reallocates the buffer as necessary. To support the user format, the error return of interpolate() needed to be changed. It used to return a bool telling "Ok the result fits", or "Sorry, I had to truncate it". Now it returns 0 on success, and returns the size of the buffer it wants in order to fit the whole result. Signed-off-by: Junio C Hamano <gitster@pobox.com>
103 lines
2.0 KiB
C
103 lines
2.0 KiB
C
/*
|
|
* Copyright 2006 Jon Loeliger
|
|
*/
|
|
|
|
#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,
|
|
* performing substitutions on %-named sub-strings from
|
|
* the table, interps, with ninterps entries.
|
|
*
|
|
* Example interps:
|
|
* {
|
|
* { "%H", "example.org"},
|
|
* { "%port", "123"},
|
|
* { "%%", "%"},
|
|
* }
|
|
*
|
|
* Returns 0 on a successful substitution pass that fits in result,
|
|
* Returns a number of bytes needed to hold the full substituted
|
|
* string otherwise.
|
|
*/
|
|
|
|
unsigned long interpolate(char *result, unsigned long reslen,
|
|
const char *orig,
|
|
const struct interp *interps, int ninterps)
|
|
{
|
|
const char *src = orig;
|
|
char *dest = result;
|
|
unsigned long newlen = 0;
|
|
const char *name, *value;
|
|
unsigned long namelen, valuelen;
|
|
int i;
|
|
char c;
|
|
|
|
memset(result, 0, reslen);
|
|
|
|
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)
|
|
break;
|
|
}
|
|
|
|
/* Check for valid interpolation. */
|
|
if (i < ninterps) {
|
|
value = interps[i].value;
|
|
valuelen = strlen(value);
|
|
|
|
if (newlen + valuelen + 1 < reslen) {
|
|
/* Substitute. */
|
|
strncpy(dest, value, valuelen);
|
|
dest += valuelen;
|
|
}
|
|
newlen += valuelen;
|
|
src += namelen;
|
|
continue;
|
|
}
|
|
}
|
|
/* Straight copy one non-interpolation character. */
|
|
if (newlen + 1 < reslen)
|
|
*dest++ = *src;
|
|
src++;
|
|
newlen++;
|
|
}
|
|
|
|
if (newlen + 1 < reslen)
|
|
return 0;
|
|
else
|
|
return newlen + 2;
|
|
}
|