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;
}
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;
#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
{
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");
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();
}