From: Rusty Russell Date: Mon, 3 Dec 2012 08:59:39 +0000 (+1030) Subject: tal/str: add tal_strcat(). X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=a5ebf3146a57b7db05f6b6e2de0f2689a1b06751 tal/str: add tal_strcat(). Useful for joining two strings. Signed-off-by: Rusty Russell --- diff --git a/ccan/tal/str/str.c b/ccan/tal/str/str.c index b7df54c4..4606b47e 100644 --- a/ccan/tal/str/str.c +++ b/ccan/tal/str/str.c @@ -81,6 +81,31 @@ char *tal_vasprintf(const tal_t *ctx, const char *fmt, va_list ap) return buf; } +char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2) +{ + size_t len1, len2; + char *ret; + + if (unlikely(!s2) && taken(s2)) { + if (taken(s1)) + tal_free(s1); + return NULL; + } + /* We have to let through NULL for take(). */ + len1 = s1 ? strlen(s1) : 0; + len2 = strlen(s2); + + /* We use tal_dup_ here to avoid attaching a length property. */ + ret = tal_dup_(ctx, s1, 1, len1, len2 + 1, false, + TAL_LABEL(char, "[]")); + if (likely(ret)) + memcpy(ret + len1, s2, len2 + 1); + + if (taken(s2)) + tal_free(s2); + return ret; +} + char **tal_strsplit(const tal_t *ctx, const char *string, const char *delims, enum strsplit flags) { diff --git a/ccan/tal/str/str.h b/ccan/tal/str/str.h index ab776e92..4bb06b70 100644 --- a/ccan/tal/str/str.h +++ b/ccan/tal/str/str.h @@ -39,6 +39,14 @@ char *tal_asprintf(const tal_t *ctx, const char *fmt, ...) PRINTF_FMT(2,3); char *tal_vasprintf(const tal_t *ctx, const char *fmt, va_list ap) PRINTF_FMT(2,0); +/** + * tal_strcat - join two strings together + * @ctx: NULL, or tal allocated object to be parent. + * @s1: the first string (can be take()). + * @s2: the second string (can be take()). + */ +char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2); + enum strsplit { STR_EMPTY_OK, STR_NO_EMPTY diff --git a/ccan/tal/str/test/run-string.c b/ccan/tal/str/test/run-string.c index 4f8899de..5246a8aa 100644 --- a/ccan/tal/str/test/run-string.c +++ b/ccan/tal/str/test/run-string.c @@ -6,7 +6,7 @@ int main(void) { char *parent, *c; - plan_tests(13); + plan_tests(27); parent = tal(NULL, char); ok1(parent); @@ -14,16 +14,19 @@ int main(void) c = tal_strdup(parent, "hello"); ok1(strcmp(c, "hello") == 0); ok1(tal_parent(c) == parent); + tal_free(c); c = tal_strndup(parent, "hello", 3); ok1(strcmp(c, "hel") == 0); ok1(tal_parent(c) == parent); + tal_free(c); c = tal_typechk_(parent, char *); c = tal_dup(parent, char, "hello", 6, 0); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); ok1(tal_parent(c) == parent); + tal_free(c); /* Now with an extra byte. */ c = tal_dup(parent, char, "hello", 6, 1); @@ -31,10 +34,42 @@ int main(void) ok1(strcmp(tal_name(c), "char[]") == 0); ok1(tal_parent(c) == parent); strcat(c, "x"); + tal_free(c); c = tal_asprintf(parent, "hello %s", "there"); ok1(strcmp(c, "hello there") == 0); ok1(tal_parent(c) == parent); + tal_free(c); + + c = tal_strcat(parent, "hello ", "there"); + ok1(strcmp(c, "hello there") == 0); + ok1(tal_parent(c) == parent); + + /* Make sure take works correctly. */ + c = tal_strcat(parent, take(c), " again"); + ok1(strcmp(c, "hello there again") == 0); + ok1(tal_parent(c) == parent); + ok1(tal_first(parent) == c && !tal_next(parent, c)); + + c = tal_strcat(parent, "And ", take(c)); + ok1(strcmp(c, "And hello there again") == 0); + ok1(tal_parent(c) == parent); + ok1(tal_first(parent) == c && !tal_next(parent, c)); + + /* NULL pass through works... */ + c = tal_strcat(parent, take(NULL), take(c)); + ok1(!c); + ok1(!tal_first(parent)); + + c = tal_strcat(parent, take(tal_strdup(parent, "hi")), + take(NULL)); + ok1(!c); + ok1(!tal_first(parent)); + + c = tal_strcat(parent, take(NULL), take(NULL)); + ok1(!c); + ok1(!tal_first(parent)); + tal_free(parent); return exit_status();