summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2012-12-03 19:29:39 +1030
committerRusty Russell <rusty@rustcorp.com.au>2012-12-03 19:29:39 +1030
commita5ebf3146a57b7db05f6b6e2de0f2689a1b06751 (patch)
treed4ab4ddde556db8644e98c62f651c27f461ea239
parent680aa496521811e7c60afb940bcae5024f4c6adb (diff)
tal/str: add tal_strcat().
Useful for joining two strings. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--ccan/tal/str/str.c25
-rw-r--r--ccan/tal/str/str.h8
-rw-r--r--ccan/tal/str/test/run-string.c37
3 files changed, 69 insertions, 1 deletions
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();