Commit e7ae27d6 authored by Rusty Russell's avatar Rusty Russell

tal/str: add tal_append_fmt() and tal_append_vfmt() helpers.

They are far too convenient, despite their inefficiency.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 4710a928
......@@ -52,35 +52,71 @@ char *tal_fmt(const tal_t *ctx, const char *fmt, ...)
return ret;
}
char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap)
static bool do_vfmt(char **buf, size_t off, const char *fmt, va_list ap)
{
size_t max;
char *buf;
int ret;
if (!fmt && taken(fmt))
return NULL;
/* A decent guess to start. */
max = strlen(fmt) * 2;
buf = tal_arr(ctx, char, max);
while (buf) {
size_t max = strlen(fmt) * 2;
bool ok;
for (;;) {
va_list ap2;
int ret;
if (!tal_resize(buf, off + max)) {
ok = false;
break;
}
va_copy(ap2, ap);
ret = vsnprintf(buf, max, fmt, ap2);
ret = vsnprintf(*buf + off, max, fmt, ap2);
va_end(ap2);
if (ret < max)
if (ret < max) {
ok = true;
break;
if (!tal_resize(&buf, max *= 2))
buf = tal_free(buf);
}
max *= 2;
}
if (taken(fmt))
tal_free(fmt);
return ok;
}
char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap)
{
char *buf;
if (!fmt && taken(fmt))
return NULL;
/* A decent guess to start. */
buf = tal_arr(ctx, char, strlen(fmt) * 2);
if (!do_vfmt(&buf, 0, fmt, ap))
buf = tal_free(buf);
return buf;
}
bool tal_append_vfmt(char **baseptr, const char *fmt, va_list ap)
{
if (!fmt && taken(fmt))
return false;
return do_vfmt(baseptr, strlen(*baseptr), fmt, ap);
}
bool tal_append_fmt(char **baseptr, const char *fmt, ...)
{
va_list ap;
bool ret;
va_start(ap, fmt);
ret = tal_append_vfmt(baseptr, fmt, ap);
va_end(ap);
return ret;
}
char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2)
{
size_t len1, len2;
......
......@@ -39,6 +39,25 @@ char *tal_fmt(const tal_t *ctx, const char *fmt, ...) PRINTF_FMT(2,3);
char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap)
PRINTF_FMT(2,0);
/**
* tal_append_fmt - append a formatted string to a talloc string.
* @baseptr: a pointer to the tal string to be appended to.
* @fmt: the printf-style format (can be take()).
*
* Returns false on allocation failure.
*/
bool tal_append_fmt(char **baseptr, const char *fmt, ...) PRINTF_FMT(2,3);
/**
* tal_append_vfmt - append a formatted string to a talloc string (va_list)
* @baseptr: a pointer to the tal string to be appended to.
* @fmt: the printf-style format (can be take()).
* @va: the va_list containing the format args.
*
* Returns false on allocation failure.
*/
bool tal_append_vfmt(char **baseptr, const char *fmt, va_list ap);
/**
* tal_strcat - join two strings together
* @ctx: NULL, or tal allocated object to be parent.
......
......@@ -6,7 +6,7 @@ int main(void)
{
char *parent, *c;
plan_tests(27);
plan_tests(32);
parent = tal(NULL, char);
ok1(parent);
......@@ -70,6 +70,15 @@ int main(void)
ok1(!c);
ok1(!tal_first(parent));
/* Appending formatted strings. */
c = tal_strdup(parent, "hi");
ok1(tal_append_fmt(&c, "%s %s", "there", "world"));
ok1(strcmp(c, "hithere world") == 0);
ok1(tal_parent(c) == parent);
ok1(!tal_append_fmt(&c, take(NULL), "there", "world"));
ok1(strcmp(c, "hithere world") == 0);
tal_free(parent);
return exit_status();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment