tal: take implies NULL passthrough.
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 21 Nov 2012 23:37:50 +0000 (10:07 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 21 Nov 2012 23:37:50 +0000 (10:07 +1030)
This makes error handling much more convenient, since take is usually
used for chaining functions.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/tal/tal.c
ccan/tal/tal.h
ccan/tal/test/run-take.c

index 0b5e8e445674720f288819c9d2370e1a80d14c64..dce9d233a076733f636f42fbc2e02f0956cd364a 100644 (file)
@@ -718,18 +718,26 @@ bool tal_resize_(tal_t **ctxp, size_t size)
 
 char *tal_strdup(const tal_t *ctx, const char *p)
 {
-       return tal_dup(ctx, char, p, strlen(p)+1, 0);
+       /* We have to let through NULL for take(). */
+       return tal_dup(ctx, char, p, p ? strlen(p) + 1: 1, 0);
 }
 
 char *tal_strndup(const tal_t *ctx, const char *p, size_t n)
 {
+       size_t len;
        char *ret;
 
-       if (strlen(p) < n)
-               n = strlen(p);
-       ret = tal_dup(ctx, char, p, n, 1);
+       /* 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, char, p, len, 1);
        if (ret)
-               ret[n] = '\0';
+               ret[len] = '\0';
        return ret;
 }
 
@@ -779,10 +787,15 @@ char *tal_asprintf(const tal_t *ctx, const char *fmt, ...)
 
 char *tal_vasprintf(const tal_t *ctx, const char *fmt, va_list ap)
 {
-       size_t max = strlen(fmt) * 2;
+       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;
index 3a0481455ae1da5356a8905820190d03702d47eb..1ed15c75f46fd664b6f57b10c65bcd8eb9790406 100644 (file)
@@ -304,7 +304,7 @@ static inline size_t tal_sizeof_(size_t size, size_t count)
 #if HAVE_STATEMENT_EXPR
 /* Careful: ptr can be const foo *, ptype is foo *.  Also, ptr could
  * be an array, eg "hello". */
-#define tal_typechk_(ptr, ptype) ({ __typeof__(&*(ptr)) _p = (ptype)(ptr); _p; })
+#define tal_typechk_(ptr, ptype) ({ __typeof__((ptr)+0) _p = (ptype)(ptr); _p; })
 #else
 #define tal_typechk_(ptr, ptype) (ptr)
 #endif
index a6e667bbae0875104725d36f676a95083d31d388..9f0a22c6c4ea24bf6cae5b0701564573b7bdb347 100644 (file)
@@ -6,18 +6,22 @@ int main(void)
 {
        char *parent, *c;
 
-       plan_tests(24);
+       plan_tests(32);
 
        /* We can take NULL. */
        ok1(take(NULL) == NULL);
+       ok1(is_taken(NULL));
        ok1(taken(NULL)); /* Undoes take() */
+       ok1(!is_taken(NULL));
        ok1(!taken(NULL));
 
        parent = tal(NULL, char);
        ok1(parent);
 
        ok1(take(parent) == parent);
+       ok1(is_taken(parent));
        ok1(taken(parent)); /* Undoes take() */
+       ok1(!is_taken(parent));
        ok1(!taken(parent));
 
        c = tal_strdup(parent, "hello");
@@ -63,5 +67,12 @@ int main(void)
        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);
+
        return exit_status();
 }