From: Rusty Russell Date: Wed, 21 Nov 2012 23:37:50 +0000 (+1030) Subject: tal: take implies NULL passthrough. X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=bb480e553f9d204b85a2e42de0be42c7b80eebda tal: take implies NULL passthrough. This makes error handling much more convenient, since take is usually used for chaining functions. Signed-off-by: Rusty Russell --- diff --git a/ccan/tal/tal.c b/ccan/tal/tal.c index 0b5e8e44..dce9d233 100644 --- a/ccan/tal/tal.c +++ b/ccan/tal/tal.c @@ -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; diff --git a/ccan/tal/tal.h b/ccan/tal/tal.h index 3a048145..1ed15c75 100644 --- a/ccan/tal/tal.h +++ b/ccan/tal/tal.h @@ -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 diff --git a/ccan/tal/test/run-take.c b/ccan/tal/test/run-take.c index a6e667bb..9f0a22c6 100644 --- a/ccan/tal/test/run-take.c +++ b/ccan/tal/test/run-take.c @@ -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(); }