Browse Source

tal/str: move tal string functions here from tal.

They don't need anything internal to tal, they're just helpers.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 13 years ago
parent
commit
5582b01194

+ 15 - 12
ccan/tal/_info

@@ -12,27 +12,29 @@
  * This allows you to build complex objects based on their lifetimes, eg:
  * This allows you to build complex objects based on their lifetimes, eg:
  *
  *
  *  struct foo *X = tal(NULL, struct foo);
  *  struct foo *X = tal(NULL, struct foo);
- *  X->name = tal_strdup(X, "foo");
+ *  X->val = tal(X, int);
  *
  *
- * and the pointer X->name would be a "child" of the tal context "X";
- * tal_free(X->name) would free X->name as expected, by tal_free(X) would
- * free X and X->name.
+ * and the pointer X->val would be a "child" of the tal context "X";
+ * tal_free(X->val) would free X->val as expected, by tal_free(X) would
+ * free X and X->val.
  *
  *
  * With an overhead of approximately 4 pointers per object
  * With an overhead of approximately 4 pointers per object
  * (vs. talloc's 12 pointers), it uses dynamic allocation for
  * (vs. talloc's 12 pointers), it uses dynamic allocation for
  * destructors and child lists, so those operations can fail.  It does
  * destructors and child lists, so those operations can fail.  It does
  * not support talloc's references or failing destructors.
  * not support talloc's references or failing destructors.
  *
  *
+ * See Also:
+ *	ccan/tal/str (useful string helpers)
+ *
  * Example:
  * Example:
  *	#include <stdio.h>
  *	#include <stdio.h>
- *	#include <stdarg.h>
  *	#include <err.h>
  *	#include <err.h>
  *	#include <ccan/talloc/talloc.h>
  *	#include <ccan/talloc/talloc.h>
  *
  *
  *	// A structure containing a popened command.
  *	// A structure containing a popened command.
  *	struct command {
  *	struct command {
  *		FILE *f;
  *		FILE *f;
- *		const char *command;
+ *		char *command;
  *	};
  *	};
  *
  *
  *	// When struct command is freed, we also want to pclose pipe.
  *	// When struct command is freed, we also want to pclose pipe.
@@ -43,21 +45,22 @@
  *
  *
  *	// This function opens a writable pipe to the given command.
  *	// This function opens a writable pipe to the given command.
  *	static struct command *open_output_cmd(const tal_t *ctx,
  *	static struct command *open_output_cmd(const tal_t *ctx,
- *					       const char *fmt, ...)
+ *					       const char *a0, const char *a1)
  *	{
  *	{
- *		va_list ap;
  *		struct command *cmd = tal(ctx, struct command);
  *		struct command *cmd = tal(ctx, struct command);
  *
  *
  *		if (!cmd)
  *		if (!cmd)
  *			return NULL;
  *			return NULL;
  *
  *
- *		va_start(ap, fmt);
- *		cmd->command = tal_vasprintf(cmd, fmt, ap);
- *		va_end(ap);
+ *		// Note that tal/str has helpers to make this much easier!
+ *		cmd->command = tal_arrz(cmd, char, strlen(a0) + strlen(a1) + 2);
  *		if (!cmd->command) {
  *		if (!cmd->command) {
  *			tal_free(cmd);
  *			tal_free(cmd);
  *			return NULL;
  *			return NULL;
  *		}
  *		}
+ *		strcat(cmd->command, a0);
+ *		strcat(cmd->command, " ");
+ *		strcat(cmd->command, a1);
  *
  *
  *		cmd->f = popen(cmd->command, "w");
  *		cmd->f = popen(cmd->command, "w");
  *		if (!cmd->f) {
  *		if (!cmd->f) {
@@ -75,7 +78,7 @@
  *		if (argc != 2)
  *		if (argc != 2)
  *			errx(1, "Usage: %s <command>\n", argv[0]);
  *			errx(1, "Usage: %s <command>\n", argv[0]);
  *
  *
- *		cmd = open_output_cmd(NULL, "%s hello", argv[1]);
+ *		cmd = open_output_cmd(NULL, argv[1], "hello");
  *		if (!cmd)
  *		if (!cmd)
  *			err(1, "Running '%s hello'", argv[1]);
  *			err(1, "Running '%s hello'", argv[1]);
  *		fprintf(cmd->f, "This is a test\n");
  *		fprintf(cmd->f, "This is a test\n");

+ 68 - 0
ccan/tal/str/str.c

@@ -9,10 +9,78 @@
 #include <regex.h>
 #include <regex.h>
 #include <stdarg.h>
 #include <stdarg.h>
 #include <unistd.h>
 #include <unistd.h>
+#include <stdio.h>
 #include <ccan/str/str.h>
 #include <ccan/str/str.h>
 #include <ccan/tal/tal.h>
 #include <ccan/tal/tal.h>
 #include <ccan/take/take.h>
 #include <ccan/take/take.h>
 
 
+char *tal_strdup(const tal_t *ctx, const char *p)
+{
+	/* We have to let through NULL for take(). */
+	return tal_dup_(ctx, p, 1, p ? strlen(p) + 1: 1, 0, false,
+			TAL_LABEL(char, "[]"));
+}
+
+char *tal_strndup(const tal_t *ctx, const char *p, size_t n)
+{
+	size_t len;
+	char *ret;
+
+	/* We have to let through NULL for take(). */
+	if (likely(p)) {
+		len = strlen(p);
+		if (len > n)
+			len = n;
+	} else
+		len = n;
+
+	ret = tal_dup_(ctx, p, 1, len, 1, false, TAL_LABEL(char, "[]"));
+	if (ret)
+		ret[len] = '\0';
+	return ret;
+}
+
+char *tal_asprintf(const tal_t *ctx, const char *fmt, ...)
+{
+	va_list ap;
+	char *ret;
+
+	va_start(ap, fmt);
+	ret = tal_vasprintf(ctx, fmt, ap);
+	va_end(ap);
+
+	return ret;
+}
+
+char *tal_vasprintf(const tal_t *ctx, 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) {
+		va_list ap2;
+
+		va_copy(ap2, ap);
+		ret = vsnprintf(buf, max, fmt, ap2);
+		va_end(ap2);
+
+		if (ret < max)
+			break;
+		if (!tal_resize(&buf, max *= 2))
+			buf = tal_free(buf);
+	}
+	if (taken(fmt))
+		tal_free(fmt);
+	return buf;
+}
+
 char **tal_strsplit(const tal_t *ctx,
 char **tal_strsplit(const tal_t *ctx,
 		    const char *string, const char *delims, enum strsplit flags)
 		    const char *string, const char *delims, enum strsplit flags)
 {
 {

+ 33 - 0
ccan/tal/str/str.h

@@ -6,6 +6,39 @@
 #include <string.h>
 #include <string.h>
 #include <stdbool.h>
 #include <stdbool.h>
 
 
+/**
+ * tal_strdup - duplicate a string
+ * @ctx: NULL, or tal allocated object to be parent.
+ * @p: the string to copy (can be take()).
+ */
+char *tal_strdup(const tal_t *ctx, const char *p);
+
+/**
+ * tal_strndup - duplicate a limited amount of a string.
+ * @ctx: NULL, or tal allocated object to be parent.
+ * @p: the string to copy (can be take()).
+ * @n: the maximum length to copy.
+ *
+ * Always gives a nul-terminated string, with strlen() <= @n.
+ */
+char *tal_strndup(const tal_t *ctx, const char *p, size_t n);
+
+/**
+ * tal_asprintf - allocate a formatted string
+ * @ctx: NULL, or tal allocated object to be parent.
+ * @fmt: the printf-style format (can be take()).
+ */
+char *tal_asprintf(const tal_t *ctx, const char *fmt, ...) PRINTF_FMT(2,3);
+
+/**
+ * tal_vasprintf - allocate a formatted string (va_list version)
+ * @ctx: NULL, or tal allocated object to be parent.
+ * @fmt: the printf-style format (can be take()).
+ * @va: the va_list containing the format args.
+ */
+char *tal_vasprintf(const tal_t *ctx, const char *fmt, va_list ap)
+	PRINTF_FMT(2,0);
+
 enum strsplit {
 enum strsplit {
 	STR_EMPTY_OK,
 	STR_EMPTY_OK,
 	STR_NO_EMPTY
 	STR_NO_EMPTY

+ 2 - 2
ccan/tal/test/run-string.c → ccan/tal/str/test/run-string.c

@@ -1,5 +1,5 @@
-#include <ccan/tal/tal.h>
-#include <ccan/tal/tal.c>
+#include <ccan/tal/str/str.h>
+#include <ccan/tal/str/str.c>
 #include <ccan/tap/tap.h>
 #include <ccan/tap/tap.h>
 
 
 int main(void)
 int main(void)

+ 47 - 0
ccan/tal/str/test/run-take.c

@@ -0,0 +1,47 @@
+#include <ccan/tal/str/str.h>
+#include <ccan/tal/str/str.c>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+	char *parent, *c;
+
+	plan_tests(14);
+
+	parent = tal(NULL, char);
+	ok1(parent);
+
+	c = tal_strdup(parent, "hello");
+
+	c = tal_strdup(parent, take(c));
+	ok1(strcmp(c, "hello") == 0);
+	ok1(tal_parent(c) == parent);
+
+	c = tal_strndup(parent, take(c), 5);
+	ok1(strcmp(c, "hello") == 0);
+	ok1(tal_parent(c) == parent);
+
+	c = tal_strndup(parent, take(c), 3);
+	ok1(strcmp(c, "hel") == 0);
+	ok1(tal_parent(c) == parent);
+	tal_free(c);
+
+	c = tal_strdup(parent, "hello %s");
+	c = tal_asprintf(parent, take(c), "there");
+	ok1(strcmp(c, "hello there") == 0);
+	ok1(tal_parent(c) == parent);
+	/* No leftover allocations. */
+	tal_free(c);
+	ok1(tal_first(parent) == NULL);
+
+	tal_free(parent);
+	ok1(!taken_any());
+
+	/* NULL pass-through. */
+	c = NULL;
+	ok1(tal_strdup(NULL, take(c)) == NULL);
+	ok1(tal_strndup(NULL, take(c), 5) == NULL);
+	ok1(tal_asprintf(NULL, take(c), 0) == NULL);
+
+	return exit_status();
+}

+ 0 - 68
ccan/tal/tal.c

@@ -5,7 +5,6 @@
 #include <ccan/take/take.h>
 #include <ccan/take/take.h>
 #include <assert.h>
 #include <assert.h>
 #include <stdio.h>
 #include <stdio.h>
-#include <stdarg.h>
 #include <stddef.h>
 #include <stddef.h>
 #include <string.h>
 #include <string.h>
 #include <limits.h>
 #include <limits.h>
@@ -713,32 +712,6 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count)
 	return true;
 	return true;
 }
 }
 
 
-char *tal_strdup(const tal_t *ctx, const char *p)
-{
-	/* We have to let through NULL for take(). */
-	return tal_dup_(ctx, p, 1, p ? strlen(p) + 1: 1, 0, false,
-			TAL_LABEL(char, "[]"));
-}
-
-char *tal_strndup(const tal_t *ctx, const char *p, size_t n)
-{
-	size_t len;
-	char *ret;
-
-	/* We have to let through NULL for take(). */
-	if (likely(p)) {
-		len = strlen(p);
-		if (len > n)
-			len = n;
-	} else
-		len = n;
-
-	ret = tal_dup_(ctx, p, 1, len, 1, false, TAL_LABEL(char, "[]"));
-	if (ret)
-		ret[len] = '\0';
-	return ret;
-}
-
 void *tal_dup_(const tal_t *ctx, const void *p, size_t size,
 void *tal_dup_(const tal_t *ctx, const void *p, size_t size,
 	       size_t n, size_t extra, bool add_count,
 	       size_t n, size_t extra, bool add_count,
 	       const char *label)
 	       const char *label)
@@ -776,47 +749,6 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size,
 	return ret;
 	return ret;
 }
 }
 
 
-char *tal_asprintf(const tal_t *ctx, const char *fmt, ...)
-{
-	va_list ap;
-	char *ret;
-
-	va_start(ap, fmt);
-	ret = tal_vasprintf(ctx, fmt, ap);
-	va_end(ap);
-
-	return ret;
-}
-
-char *tal_vasprintf(const tal_t *ctx, 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) {
-		va_list ap2;
-
-		va_copy(ap2, ap);
-		ret = vsnprintf(buf, max, fmt, ap2);
-		va_end(ap2);
-
-		if (ret < max)
-			break;
-		if (!tal_resize(&buf, max *= 2))
-			buf = tal_free(buf);
-	}
-	if (taken(fmt))
-		tal_free(fmt);
-	return buf;
-}
-
 void tal_set_backend(void *(*alloc_fn)(size_t size),
 void tal_set_backend(void *(*alloc_fn)(size_t size),
 		     void *(*resize_fn)(void *, size_t size),
 		     void *(*resize_fn)(void *, size_t size),
 		     void (*free_fn)(void *),
 		     void (*free_fn)(void *),

+ 0 - 33
ccan/tal/tal.h

@@ -286,39 +286,6 @@ tal_t *tal_parent(const tal_t *ctx);
 			  sizeof(type), (n), (extra),		\
 			  sizeof(type), (n), (extra),		\
 			  true, TAL_LABEL(type, "[]")))
 			  true, TAL_LABEL(type, "[]")))
 
 
-/**
- * tal_strdup - duplicate a string
- * @ctx: NULL, or tal allocated object to be parent.
- * @p: the string to copy (can be take()).
- */
-char *tal_strdup(const tal_t *ctx, const char *p);
-
-/**
- * tal_strndup - duplicate a limited amount of a string.
- * @ctx: NULL, or tal allocated object to be parent.
- * @p: the string to copy (can be take()).
- * @n: the maximum length to copy.
- *
- * Always gives a nul-terminated string, with strlen() <= @n.
- */
-char *tal_strndup(const tal_t *ctx, const char *p, size_t n);
-
-/**
- * tal_asprintf - allocate a formatted string
- * @ctx: NULL, or tal allocated object to be parent.
- * @fmt: the printf-style format (can be take()).
- */
-char *tal_asprintf(const tal_t *ctx, const char *fmt, ...) PRINTF_FMT(2,3);
-
-/**
- * tal_vasprintf - allocate a formatted string (va_list version)
- * @ctx: NULL, or tal allocated object to be parent.
- * @fmt: the printf-style format (can be take()).
- * @va: the va_list containing the format args.
- */
-char *tal_vasprintf(const tal_t *ctx, const char *fmt, va_list ap)
-	PRINTF_FMT(2,0);
-
 
 
 /**
 /**
  * tal_set_backend - set the allocation or error functions to use
  * tal_set_backend - set the allocation or error functions to use

+ 4 - 26
ccan/tal/test/run-take.c

@@ -6,7 +6,7 @@ int main(void)
 {
 {
 	char *parent, *c;
 	char *parent, *c;
 
 
-	plan_tests(32);
+	plan_tests(21);
 
 
 	/* We can take NULL. */
 	/* We can take NULL. */
 	ok1(take(NULL) == NULL);
 	ok1(take(NULL) == NULL);
@@ -24,20 +24,8 @@ int main(void)
 	ok1(!is_taken(parent));
 	ok1(!is_taken(parent));
 	ok1(!taken(parent));
 	ok1(!taken(parent));
 
 
-	c = tal_strdup(parent, "hello");
-
-	c = tal_strdup(parent, take(c));
-	ok1(strcmp(c, "hello") == 0);
-	ok1(tal_parent(c) == parent);
-
-	c = tal_strndup(parent, take(c), 5);
-	ok1(strcmp(c, "hello") == 0);
-	ok1(tal_parent(c) == parent);
-
-	c = tal_strndup(parent, take(c), 3);
-	ok1(strcmp(c, "hel") == 0);
-	ok1(tal_parent(c) == parent);
-
+	c = tal(parent, char);
+	*c = 'h';
 	c = tal_dup(parent, char, take(c), 1, 0);
 	c = tal_dup(parent, char, take(c), 1, 0);
 	ok1(c[0] == 'h');
 	ok1(c[0] == 'h');
 	ok1(tal_parent(c) == parent);
 	ok1(tal_parent(c) == parent);
@@ -56,23 +44,13 @@ int main(void)
 	tal_free(c);
 	tal_free(c);
 	ok1(tal_first(parent) == NULL);
 	ok1(tal_first(parent) == NULL);
 
 
-	c = tal_strdup(parent, "hello %s");
-	c = tal_asprintf(parent, take(c), "there");
-	ok1(strcmp(c, "hello there") == 0);
-	ok1(tal_parent(c) == parent);
-	/* No leftover allocations. */
-	tal_free(c);
-	ok1(tal_first(parent) == NULL);
-
 	tal_free(parent);
 	tal_free(parent);
 	ok1(!taken_any());
 	ok1(!taken_any());
 
 
 	/* NULL pass-through. */
 	/* NULL pass-through. */
 	c = NULL;
 	c = NULL;
-	ok1(tal_strdup(NULL, take(c)) == NULL);
-	ok1(tal_strndup(NULL, take(c), 5) == NULL);
 	ok1(tal_dup(NULL, char, take(c), 5, 5) == NULL);
 	ok1(tal_dup(NULL, char, take(c), 5, 5) == NULL);
-	ok1(tal_asprintf(NULL, take(c), 0) == NULL);
+	ok1(!taken_any());
 
 
 	return exit_status();
 	return exit_status();
 }
 }

+ 2 - 1
ccan/tal/test/run-test-backend.c

@@ -53,7 +53,8 @@ int main(void)
 	tal_add_destructor(p, destroy_p);
 	tal_add_destructor(p, destroy_p);
 
 
 	tal_set_name(p, "test");
 	tal_set_name(p, "test");
-	name = tal_asprintf(NULL, "test2");
+	name = tal_arr(NULL, char, 6);
+	strcpy(name, "test2");
 	tal_set_name(p, name);
 	tal_set_name(p, name);
 	/* makes us free old name */
 	/* makes us free old name */
 	tal_set_name(p, name);
 	tal_set_name(p, name);