Browse Source

tal/str: add tal_strcat().

Useful for joining two strings.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 13 years ago
parent
commit
a5ebf3146a
3 changed files with 69 additions and 1 deletions
  1. 25 0
      ccan/tal/str/str.c
  2. 8 0
      ccan/tal/str/str.h
  3. 36 1
      ccan/tal/str/test/run-string.c

+ 25 - 0
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)
 {

+ 8 - 0
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

+ 36 - 1
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();