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
commit5582b011948769779b0d839d35873c2bc557f9cb (patch)
treebcb123706a3a760cff5e44ec51d3cd756bb545fd
parent15ed4f453713f1a7bdeec22b53704819fa3d447f (diff)
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>
-rw-r--r--ccan/tal/_info27
-rw-r--r--ccan/tal/str/str.c68
-rw-r--r--ccan/tal/str/str.h33
-rw-r--r--ccan/tal/str/test/run-string.c (renamed from ccan/tal/test/run-string.c)4
-rw-r--r--ccan/tal/str/test/run-take.c47
-rw-r--r--ccan/tal/tal.c68
-rw-r--r--ccan/tal/tal.h33
-rw-r--r--ccan/tal/test/run-take.c30
-rw-r--r--ccan/tal/test/run-test-backend.c3
9 files changed, 171 insertions, 142 deletions
diff --git a/ccan/tal/_info b/ccan/tal/_info
index 3f7c22c7..853c6985 100644
--- a/ccan/tal/_info
+++ b/ccan/tal/_info
@@ -12,27 +12,29 @@
* This allows you to build complex objects based on their lifetimes, eg:
*
* 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
* (vs. talloc's 12 pointers), it uses dynamic allocation for
* destructors and child lists, so those operations can fail. It does
* not support talloc's references or failing destructors.
*
+ * See Also:
+ * ccan/tal/str (useful string helpers)
+ *
* Example:
* #include <stdio.h>
- * #include <stdarg.h>
* #include <err.h>
* #include <ccan/talloc/talloc.h>
*
* // A structure containing a popened command.
* struct command {
* FILE *f;
- * const char *command;
+ * char *command;
* };
*
* // 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.
* 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);
*
* if (!cmd)
* 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) {
* tal_free(cmd);
* return NULL;
* }
+ * strcat(cmd->command, a0);
+ * strcat(cmd->command, " ");
+ * strcat(cmd->command, a1);
*
* cmd->f = popen(cmd->command, "w");
* if (!cmd->f) {
@@ -75,7 +78,7 @@
* if (argc != 2)
* 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)
* err(1, "Running '%s hello'", argv[1]);
* fprintf(cmd->f, "This is a test\n");
diff --git a/ccan/tal/str/str.c b/ccan/tal/str/str.c
index cafb04bb..b7df54c4 100644
--- a/ccan/tal/str/str.c
+++ b/ccan/tal/str/str.c
@@ -9,10 +9,78 @@
#include <regex.h>
#include <stdarg.h>
#include <unistd.h>
+#include <stdio.h>
#include <ccan/str/str.h>
#include <ccan/tal/tal.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,
const char *string, const char *delims, enum strsplit flags)
{
diff --git a/ccan/tal/str/str.h b/ccan/tal/str/str.h
index f30911e2..ab776e92 100644
--- a/ccan/tal/str/str.h
+++ b/ccan/tal/str/str.h
@@ -6,6 +6,39 @@
#include <string.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 {
STR_EMPTY_OK,
STR_NO_EMPTY
diff --git a/ccan/tal/test/run-string.c b/ccan/tal/str/test/run-string.c
index 0155ecbe..4f8899de 100644
--- a/ccan/tal/test/run-string.c
+++ b/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>
int main(void)
diff --git a/ccan/tal/str/test/run-take.c b/ccan/tal/str/test/run-take.c
new file mode 100644
index 00000000..0cbab9e0
--- /dev/null
+++ b/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();
+}
diff --git a/ccan/tal/tal.c b/ccan/tal/tal.c
index c78185be..4f7d5678 100644
--- a/ccan/tal/tal.c
+++ b/ccan/tal/tal.c
@@ -5,7 +5,6 @@
#include <ccan/take/take.h>
#include <assert.h>
#include <stdio.h>
-#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <limits.h>
@@ -713,32 +712,6 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count)
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,
size_t n, size_t extra, bool add_count,
const char *label)
@@ -776,47 +749,6 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size,
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 *(*resize_fn)(void *, size_t size),
void (*free_fn)(void *),
diff --git a/ccan/tal/tal.h b/ccan/tal/tal.h
index efe21bc5..091eb034 100644
--- a/ccan/tal/tal.h
+++ b/ccan/tal/tal.h
@@ -286,39 +286,6 @@ tal_t *tal_parent(const tal_t *ctx);
sizeof(type), (n), (extra), \
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
diff --git a/ccan/tal/test/run-take.c b/ccan/tal/test/run-take.c
index 9f0a22c6..72d2e8e3 100644
--- a/ccan/tal/test/run-take.c
+++ b/ccan/tal/test/run-take.c
@@ -6,7 +6,7 @@ int main(void)
{
char *parent, *c;
- plan_tests(32);
+ plan_tests(21);
/* We can take NULL. */
ok1(take(NULL) == NULL);
@@ -24,20 +24,8 @@ int main(void)
ok1(!is_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);
ok1(c[0] == 'h');
ok1(tal_parent(c) == parent);
@@ -56,23 +44,13 @@ int main(void)
tal_free(c);
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);
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_dup(NULL, char, take(c), 5, 5) == NULL);
- ok1(tal_asprintf(NULL, take(c), 0) == NULL);
+ ok1(!taken_any());
return exit_status();
}
diff --git a/ccan/tal/test/run-test-backend.c b/ccan/tal/test/run-test-backend.c
index 4663a566..66144cb3 100644
--- a/ccan/tal/test/run-test-backend.c
+++ b/ccan/tal/test/run-test-backend.c
@@ -53,7 +53,8 @@ int main(void)
tal_add_destructor(p, destroy_p);
tal_set_name(p, "test");
- name = tal_asprintf(NULL, "test2");
+ name = tal_arr(NULL, char, 6);
+ strcpy(name, "test2");
tal_set_name(p, name);
/* makes us free old name */
tal_set_name(p, name);