diff --git a/ccan/README b/ccan/README index 22c932a03..df4af7c9c 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2435-g92be2eff +CCAN version: init-2440-g55d81423 diff --git a/ccan/ccan/structeq/test/compile_fail-expect-any-padding.c b/ccan/ccan/structeq/test/compile_fail-expect-any-padding.c new file mode 100644 index 000000000..321aef3a3 --- /dev/null +++ b/ccan/ccan/structeq/test/compile_fail-expect-any-padding.c @@ -0,0 +1,19 @@ +#include + +struct mydata { + int start, end; +}; +#ifdef FAIL +#define PADDING -1 +#else +#define PADDING 0 +#endif + +STRUCTEQ_DEF(mydata, PADDING, start, end); + +int main(void) +{ + struct mydata a = { 0, 100 }; + + return mydata_eq(&a, &a); +} diff --git a/ccan/ccan/structeq/test/compile_fail-expect-padding.c b/ccan/ccan/structeq/test/compile_fail-expect-padding.c new file mode 100644 index 000000000..cec9f8465 --- /dev/null +++ b/ccan/ccan/structeq/test/compile_fail-expect-padding.c @@ -0,0 +1,19 @@ +#include + +struct mydata { + int start, end; +}; +#ifdef FAIL +#define PADDING 1 +#else +#define PADDING 0 +#endif + +STRUCTEQ_DEF(mydata, PADDING, start, end); + +int main(void) +{ + struct mydata a = { 0, 100 }; + + return mydata_eq(&a, &a); +} diff --git a/ccan/ccan/structeq/test/compile_fail-unexpceted-padding.c b/ccan/ccan/structeq/test/compile_fail-unexpceted-padding.c new file mode 100644 index 000000000..af926ce1c --- /dev/null +++ b/ccan/ccan/structeq/test/compile_fail-unexpceted-padding.c @@ -0,0 +1,20 @@ +#include + +struct mydata { + int start, end; + int pad; +}; +#ifdef FAIL +#define PADDING 0 +#else +#define PADDING sizeof(int) +#endif + +STRUCTEQ_DEF(mydata, PADDING, start, end); + +int main(void) +{ + struct mydata a = { 0, 100 }; + + return mydata_eq(&a, &a); +} diff --git a/ccan/ccan/structeq/test/run-with-padding.c b/ccan/ccan/structeq/test/run-with-padding.c new file mode 100644 index 000000000..d18b3e55d --- /dev/null +++ b/ccan/ccan/structeq/test/run-with-padding.c @@ -0,0 +1,32 @@ +#include +#include + +/* In theory, this could be generated without padding, if alignof(int) were 0, + * and test would fail. Call me when that happens. */ +struct mydata { + char start; + int end; +}; + +STRUCTEQ_DEF(mydata, sizeof(int) - sizeof(char), start, end); + +int main(void) +{ + struct mydata a, b; + + /* This is how many tests you plan to run */ + plan_tests(3); + + a.start = 0; + a.end = 100; + ok1(mydata_eq(&a, &a)); + + b = a; + ok1(mydata_eq(&a, &b)); + + b.end++; + ok1(!mydata_eq(&a, &b)); + + /* This exits depending on whether all tests passed */ + return exit_status(); +} diff --git a/ccan/ccan/tal/benchmark/samba-allocs.c b/ccan/ccan/tal/benchmark/samba-allocs.c index f2259a4e3..4bed1b2a2 100644 --- a/ccan/ccan/tal/benchmark/samba-allocs.c +++ b/ccan/ccan/tal/benchmark/samba-allocs.c @@ -178,15 +178,8 @@ static void do_tals(struct node *node) unsigned int i; static int count; - /* Tal pays a penalty for arrays, but we can't tell which is an array - * and which isn't. Grepping samba source gives 1221 talloc_array of - * 33137 talloc occurrences, so conservatively assume 1 in 16 */ - if (count++ % 16 == 0) - node->n = tal_arr(node->parent ? node->parent->n : NULL, - char, node->len); - else - node->n = tal_alloc_(node->parent ? node->parent->n : NULL, - node->len, false, false, TAL_LABEL(type, "")); + node->n = tal_arr(node->parent ? node->parent->n : NULL, + char, node->len); if (node->destructor) tal_add_destructor(node->n, unused_tal_destructor); diff --git a/ccan/ccan/tal/str/_info b/ccan/ccan/tal/str/_info index 3037cfde2..9b9c70b6b 100644 --- a/ccan/ccan/tal/str/_info +++ b/ccan/ccan/tal/str/_info @@ -7,7 +7,9 @@ * * This is a grab bag of functions for string operations, designed to enhance * the standard string.h; these are separated from the non-tal-needing - * string utilities in "str.h". + * string utilities in "str.h". Each string created by this library + * will have tal_count() equal to strlen() + 1 (assuming you didn't create + * a string containing a NUL, such as using tal_fmt("%c", 0)). * * Example: * #include diff --git a/ccan/ccan/tal/str/str.c b/ccan/ccan/tal/str/str.c index 4b3b11aa6..cec31c752 100644 --- a/ccan/ccan/tal/str/str.c +++ b/ccan/ccan/tal/str/str.c @@ -12,14 +12,13 @@ #include #include -char *tal_strdup(const tal_t *ctx, const char *p) +char *tal_strdup_(const tal_t *ctx, const char *p, const char *label) { /* We have to let through NULL for take(). */ - return tal_dup_(ctx, p, 1, p ? strlen(p) + 1: 1, 0, false, - TAL_LABEL(char, "[]")); + return tal_dup_arr_label(ctx, char, p, p ? strlen(p) + 1: 1, 0, label); } -char *tal_strndup(const tal_t *ctx, const char *p, size_t n) +char *tal_strndup_(const tal_t *ctx, const char *p, size_t n, const char *label) { size_t len; char *ret; @@ -30,19 +29,19 @@ char *tal_strndup(const tal_t *ctx, const char *p, size_t n) else len = n; - ret = tal_dup_(ctx, p, 1, len, 1, false, TAL_LABEL(char, "[]")); + ret = tal_dup_arr_label(ctx, char, p, len, 1, label); if (ret) ret[len] = '\0'; return ret; } -char *tal_fmt(const tal_t *ctx, const char *fmt, ...) +char *tal_fmt_(const tal_t *ctx, const char *label, const char *fmt, ...) { va_list ap; char *ret; va_start(ap, fmt); - ret = tal_vfmt(ctx, fmt, ap); + ret = tal_vfmt_(ctx, fmt, ap, label); va_end(ap); return ret; @@ -69,6 +68,8 @@ static bool do_vfmt(char **buf, size_t off, const char *fmt, va_list ap) if (ret < max) { ok = true; + /* Make sure tal_count() is correct! */ + tal_resize(buf, off + ret + 1); break; } max *= 2; @@ -79,7 +80,7 @@ static bool do_vfmt(char **buf, size_t off, const char *fmt, va_list ap) return ok; } -char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap) +char *tal_vfmt_(const tal_t *ctx, const char *fmt, va_list ap, const char *label) { char *buf; @@ -87,7 +88,7 @@ char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap) return NULL; /* A decent guess to start. */ - buf = tal_arr(ctx, char, strlen(fmt) * 2); + buf = tal_arr_label(ctx, char, strlen(fmt) * 2, label); if (!do_vfmt(&buf, 0, fmt, ap)) buf = tal_free(buf); return buf; @@ -113,7 +114,8 @@ bool tal_append_fmt(char **baseptr, const char *fmt, ...) return ret; } -char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2) +char *tal_strcat_(const tal_t *ctx, const char *s1, const char *s2, + const char *label) { size_t len1, len2; char *ret; @@ -127,9 +129,7 @@ char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2) len1 = s1 ? strlen(s1) : 0; len2 = strlen(s2); - /* We use tal_dup_ here to avoid attaching a length property. */ - ret = tal_dup_(ctx, s1, 1, len1, len2 + 1, false, - TAL_LABEL(char, "[]")); + ret = tal_dup_arr_label(ctx, char, s1, len1, len2 + 1, label); if (likely(ret)) memcpy(ret + len1, s2, len2 + 1); @@ -138,8 +138,9 @@ char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2) return ret; } -char **tal_strsplit(const tal_t *ctx, - const char *string, const char *delims, enum strsplit flags) +char **tal_strsplit_(const tal_t *ctx, + const char *string, const char *delims, enum strsplit flags, + const char *label) { char **parts, *str; size_t max = 64, num = 0; @@ -190,8 +191,9 @@ fail: return NULL; } -char *tal_strjoin(const tal_t *ctx, - char *strings[], const char *delim, enum strjoin flags) +char *tal_strjoin_(const tal_t *ctx, + char *strings[], const char *delim, enum strjoin flags, + const char *label) { unsigned int i; char *ret = NULL; @@ -204,7 +206,7 @@ char *tal_strjoin(const tal_t *ctx, goto fail; dlen = strlen(delim); - ret = tal_arr(ctx, char, dlen*2+1); + ret = tal_arr_label(ctx, char, dlen*2+1, label); if (!ret) goto fail; @@ -222,6 +224,8 @@ char *tal_strjoin(const tal_t *ctx, totlen += dlen; } ret[totlen] = '\0'; + /* Make sure tal_count() is correct! */ + tal_resize(&ret, totlen+1); out: if (taken(strings)) tal_free(strings); @@ -255,7 +259,8 @@ static size_t count_open_braces(const char *string) #endif } -bool tal_strreg(const tal_t *ctx, const char *string, const char *regex, ...) +bool tal_strreg_(const tal_t *ctx, const char *string, const char *label, + const char *regex, ...) { size_t nmatch = 1 + count_open_braces(regex); regmatch_t matches[nmatch]; @@ -285,10 +290,11 @@ bool tal_strreg(const tal_t *ctx, const char *string, const char *regex, ...) if (matches[i].rm_so == -1) *arg = NULL; else { - *arg = tal_strndup(ctx, - string + matches[i].rm_so, - matches[i].rm_eo - - matches[i].rm_so); + *arg = tal_strndup_(ctx, + string + matches[i].rm_so, + matches[i].rm_eo + - matches[i].rm_so, + label); /* FIXME: If we fail, we set some and leak! */ if (!*arg) { ret = false; diff --git a/ccan/ccan/tal/str/str.h b/ccan/ccan/tal/str/str.h index ec853defc..f93948440 100644 --- a/ccan/ccan/tal/str/str.h +++ b/ccan/ccan/tal/str/str.h @@ -13,8 +13,11 @@ * tal_strdup - duplicate a string * @ctx: NULL, or tal allocated object to be parent. * @p: the string to copy (can be take()). + * + * The returned string will have tal_count() == strlen() + 1. */ -char *tal_strdup(const tal_t *ctx, const char *p TAKES); +#define tal_strdup(ctx, p) tal_strdup_(ctx, p, TAL_LABEL(char, "[]")) +char *tal_strdup_(const tal_t *ctx, const char *p TAKES, const char *label); /** * tal_strndup - duplicate a limited amount of a string. @@ -23,23 +26,36 @@ char *tal_strdup(const tal_t *ctx, const char *p TAKES); * @n: the maximum length to copy. * * Always gives a nul-terminated string, with strlen() <= @n. + * The returned string will have tal_count() == strlen() + 1. */ -char *tal_strndup(const tal_t *ctx, const char *p TAKES, size_t n); +#define tal_strndup(ctx, p, n) tal_strndup_(ctx, p, n, TAL_LABEL(char, "[]")) +char *tal_strndup_(const tal_t *ctx, const char *p TAKES, size_t n, + const char *label); /** * tal_fmt - allocate a formatted string * @ctx: NULL, or tal allocated object to be parent. * @fmt: the printf-style format (can be take()). + * + * The returned string will have tal_count() == strlen() + 1. */ -char *tal_fmt(const tal_t *ctx, const char *fmt TAKES, ...) PRINTF_FMT(2,3); +#define tal_fmt(ctx, ...) \ + tal_fmt_(ctx, TAL_LABEL(char, "[]"), __VA_ARGS__) +char *tal_fmt_(const tal_t *ctx, const char *label, const char *fmt TAKES, + ...) PRINTF_FMT(3,4); /** * tal_vfmt - 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. + * + * The returned string will have tal_count() == strlen() + 1. */ -char *tal_vfmt(const tal_t *ctx, const char *fmt TAKES, va_list ap) +#define tal_vfmt(ctx, fmt, va) \ + tal_vfmt_(ctx, fmt, va, TAL_LABEL(char, "[]")) +char *tal_vfmt_(const tal_t *ctx, const char *fmt TAKES, va_list ap, + const char *label) PRINTF_FMT(2,0); /** @@ -48,6 +64,7 @@ char *tal_vfmt(const tal_t *ctx, const char *fmt TAKES, va_list ap) * @fmt: the printf-style format (can be take()). * * Returns false on allocation failure. + * Otherwise tal_count(*@baseptr) == strlen(*@baseptr) + 1. */ bool tal_append_fmt(char **baseptr, const char *fmt TAKES, ...) PRINTF_FMT(2,3); @@ -58,6 +75,7 @@ bool tal_append_fmt(char **baseptr, const char *fmt TAKES, ...) PRINTF_FMT(2,3); * @va: the va_list containing the format args. * * Returns false on allocation failure. + * Otherwise tal_count(*@baseptr) == strlen(*@baseptr) + 1. */ bool tal_append_vfmt(char **baseptr, const char *fmt TAKES, va_list ap); @@ -66,8 +84,12 @@ bool tal_append_vfmt(char **baseptr, const char *fmt TAKES, va_list ap); * @ctx: NULL, or tal allocated object to be parent. * @s1: the first string (can be take()). * @s2: the second string (can be take()). + * + * The returned string will have tal_count() == strlen() + 1. */ -char *tal_strcat(const tal_t *ctx, const char *s1 TAKES, const char *s2 TAKES); +#define tal_strcat(ctx, s1, s2) tal_strcat_(ctx, s1, s2, TAL_LABEL(char, "[]")) +char *tal_strcat_(const tal_t *ctx, const char *s1 TAKES, const char *s2 TAKES, + const char *label); enum strsplit { STR_EMPTY_OK, @@ -109,10 +131,13 @@ enum strsplit { * return long_lines; * } */ -char **tal_strsplit(const tal_t *ctx, - const char *string TAKES, - const char *delims TAKES, - enum strsplit flag); +#define tal_strsplit(ctx, string, delims, flag) \ + tal_strsplit_(ctx, string, delims, flag, TAL_LABEL(char *, "[]")) +char **tal_strsplit_(const tal_t *ctx, + const char *string TAKES, + const char *delims TAKES, + enum strsplit flag, + const char *label); enum strjoin { STR_TRAIL, @@ -130,6 +155,8 @@ enum strjoin { * return value is allocated using tal. Each string in @strings is * followed by a copy of @delim. * + * The returned string will have tal_count() == strlen() + 1. + * * Example: * // Append the string "--EOL" to each line. * static char *append_to_all_lines(const char *string) @@ -142,10 +169,13 @@ enum strjoin { * return ret; * } */ -char *tal_strjoin(const void *ctx, - char *strings[] TAKES, - const char *delim TAKES, - enum strjoin flags); +#define tal_strjoin(ctx, strings, delim, flags) \ + tal_strjoin_(ctx, strings, delim, flags, TAL_LABEL(char, "[]")) +char *tal_strjoin_(const void *ctx, + char *strings[] TAKES, + const char *delim TAKES, + enum strjoin flags, + const char *label); /** * tal_strreg - match/extract from a string via (extended) regular expressions. @@ -163,6 +193,7 @@ char *tal_strjoin(const void *ctx, * non-existent matches (eg "([a-z]*)?") the pointer is set to NULL. * * Allocation failures or malformed regular expressions return false. + * The allocated strings will have tal_count() == strlen() + 1. * * See Also: * regcomp(3), regex(3). @@ -187,6 +218,8 @@ char *tal_strjoin(const void *ctx, * return 0; * } */ -bool tal_strreg(const void *ctx, const char *string TAKES, - const char *regex TAKES, ...); +#define tal_strreg(ctx, string, ...) \ + tal_strreg_(ctx, string, TAL_LABEL(char, "[]"), __VA_ARGS__) +bool tal_strreg_(const void *ctx, const char *string TAKES, + const char *label, const char *regex, ...); #endif /* CCAN_STR_TAL_H */ diff --git a/ccan/ccan/tal/str/test/run-fmt-terminate.c b/ccan/ccan/tal/str/test/run-fmt-terminate.c index 374ca03a1..3474cdfa1 100644 --- a/ccan/ccan/tal/str/test/run-fmt-terminate.c +++ b/ccan/ccan/tal/str/test/run-fmt-terminate.c @@ -11,11 +11,12 @@ int main(void) char *str; const char *fmt = ""; - plan_tests(1); + plan_tests(2); /* GCC complains about empty format string, complains about non-literal * with no args... */ str = tal_fmt(NULL, fmt, ""); ok1(!strcmp(str, "")); + ok1(tal_count(str) == strlen(str) + 1); tal_free(str); return exit_status(); diff --git a/ccan/ccan/tal/str/test/run-string.c b/ccan/ccan/tal/str/test/run-string.c index 533ad0128..03d4eb51b 100644 --- a/ccan/ccan/tal/str/test/run-string.c +++ b/ccan/ccan/tal/str/test/run-string.c @@ -7,7 +7,7 @@ int main(void) { char *parent, *c; - plan_tests(32); + plan_tests(43); parent = tal(NULL, char); ok1(parent); @@ -15,11 +15,13 @@ int main(void) c = tal_strdup(parent, "hello"); ok1(strcmp(c, "hello") == 0); ok1(tal_parent(c) == parent); + ok1(tal_count(c) == strlen(c) + 1); tal_free(c); c = tal_strndup(parent, "hello", 3); ok1(strcmp(c, "hel") == 0); ok1(tal_parent(c) == parent); + ok1(tal_count(c) == strlen(c) + 1); tal_free(c); #ifdef TAL_USE_TALLOC @@ -30,6 +32,7 @@ int main(void) c = tal_dup_arr(parent, char, "hello", 6, 0); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); + ok1(tal_count(c) == 6); ok1(tal_parent(c) == parent); tal_free(c); @@ -37,26 +40,31 @@ int main(void) c = tal_dup_arr(parent, char, "hello", 6, 1); ok1(strcmp(c, "hello") == 0); ok1(strcmp(tal_name(c), "char[]") == 0); + ok1(tal_count(c) == 7); ok1(tal_parent(c) == parent); strcat(c, "x"); tal_free(c); c = tal_fmt(parent, "hello %s", "there"); ok1(strcmp(c, "hello there") == 0); + ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); tal_free(c); c = tal_strcat(parent, "hello ", "there"); ok1(strcmp(c, "hello there") == 0); + ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); /* Make sure take works correctly. */ c = tal_strcat(parent, take(c), " again"); ok1(strcmp(c, "hello there again") == 0); + ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); ok1(single_child(parent, c)); c = tal_strcat(parent, "And ", take(c)); + ok1(tal_count(c) == strlen(c) + 1); ok1(strcmp(c, "And hello there again") == 0); ok1(tal_parent(c) == parent); ok1(single_child(parent, c)); @@ -77,12 +85,15 @@ int main(void) /* Appending formatted strings. */ c = tal_strdup(parent, "hi"); + ok1(tal_count(c) == strlen(c) + 1); ok1(tal_append_fmt(&c, "%s %s", "there", "world")); ok1(strcmp(c, "hithere world") == 0); + ok1(tal_count(c) == strlen(c) + 1); ok1(tal_parent(c) == parent); ok1(!tal_append_fmt(&c, take(NULL), "there", "world")); ok1(strcmp(c, "hithere world") == 0); + ok1(tal_count(c) == strlen(c) + 1); tal_free(parent); diff --git a/ccan/ccan/tal/str/test/run-strndup.c b/ccan/ccan/tal/str/test/run-strndup.c index 55e35fd4b..94689d8c6 100644 --- a/ccan/ccan/tal/str/test/run-strndup.c +++ b/ccan/ccan/tal/str/test/run-strndup.c @@ -9,12 +9,13 @@ int main(void) { char *str, *copy; - plan_tests(1); + plan_tests(2); str = malloc(5); memcpy(str, "hello", 5); /* We should be fine to strndup src without nul terminator. */ copy = tal_strndup(NULL, str, 5); ok1(!strcmp(copy, "hello")); + ok1(tal_count(copy) == strlen(copy) + 1); tal_free(copy); free(str); diff --git a/ccan/ccan/tal/str/test/run-strreg.c b/ccan/ccan/tal/str/test/run-strreg.c index 93b8602a3..55e244c61 100644 --- a/ccan/ccan/tal/str/test/run-strreg.c +++ b/ccan/ccan/tal/str/test/run-strreg.c @@ -21,7 +21,7 @@ int main(void) /* If it accesses this, it will crash. */ char **invalid = (char **)1L; - plan_tests(41); + plan_tests(54); /* Simple matching. */ ok1(tal_strreg(ctx, "hello world!", "hello") == true); ok1(tal_strreg(ctx, "hello world!", "hi") == false); @@ -36,12 +36,15 @@ int main(void) ok1(streq(a, "hello")); /* Allocated off ctx */ ok1(find_parent(a, ctx)); + ok1(tal_count(a) == strlen(a) + 1); tal_free(a); ok1(tal_strreg(ctx, "hello world!", "([a-z]*) ([a-z]+)", &a, &b, invalid) == true); ok1(streq(a, "hello")); ok1(streq(b, "world")); + ok1(tal_count(a) == strlen(a) + 1); + ok1(tal_count(b) == strlen(b) + 1); ok1(find_parent(a, ctx)); ok1(find_parent(b, ctx)); tal_free(a); @@ -52,6 +55,8 @@ int main(void) &a, &b, invalid) == true); ok1(streq(a, "o")); ok1(streq(b, "world")); + ok1(tal_count(a) == strlen(a) + 1); + ok1(tal_count(b) == strlen(b) + 1); tal_free(a); tal_free(b); @@ -60,6 +65,8 @@ int main(void) &a, &b, invalid) == true); ok1(streq(a, "hello world")); ok1(streq(b, "hello")); + ok1(tal_count(a) == strlen(a) + 1); + ok1(tal_count(b) == strlen(b) + 1); tal_free(a); tal_free(b); @@ -68,6 +75,8 @@ int main(void) &a, &b, invalid) == true); ok1(streq(a, "hello world")); ok1(streq(b, "hello")); + ok1(tal_count(a) == strlen(a) + 1); + ok1(tal_count(b) == strlen(b) + 1); tal_free(a); tal_free(b); @@ -75,6 +84,7 @@ int main(void) ok1(tal_strreg(ctx, "hello world!", "((hello|goodbye) world)", &a, NULL, invalid) == true); ok1(streq(a, "hello world")); + ok1(tal_count(a) == strlen(a) + 1); tal_free(a); /* No leaks! */ @@ -88,6 +98,7 @@ int main(void) a = tal_strdup(ctx, "hello world!"); ok1(tal_strreg(ctx, take(a), "([a-z]+)", &b, invalid) == true); ok1(streq(b, "hello")); + ok1(tal_count(b) == strlen(b) + 1); ok1(tal_parent(b) == ctx); tal_free(b); ok1(no_children(ctx)); @@ -96,6 +107,7 @@ int main(void) a = tal_strdup(ctx, "([a-z]+)"); ok1(tal_strreg(ctx, "hello world!", take(a), &b, invalid) == true); ok1(streq(b, "hello")); + ok1(tal_count(b) == strlen(b) + 1); ok1(tal_parent(b) == ctx); tal_free(b); ok1(no_children(ctx)); @@ -105,6 +117,7 @@ int main(void) ok1(tal_strreg(ctx, take(tal_strdup(ctx, "hello world!")), take(a), &b, invalid) == true); ok1(streq(b, "hello")); + ok1(tal_count(b) == strlen(b) + 1); ok1(tal_parent(b) == ctx); tal_free(b); ok1(no_children(ctx)); diff --git a/ccan/ccan/tal/str/test/run.c b/ccan/ccan/tal/str/test/run.c index a59d94008..626434c31 100644 --- a/ccan/ccan/tal/str/test/run.c +++ b/ccan/ccan/tal/str/test/run.c @@ -15,7 +15,7 @@ int main(void) char **split, *str; void *ctx; - plan_tests(69); + plan_tests(78); split = tal_strsplit(NULL, "hello world", " ", STR_EMPTY_OK); ok1(!strcmp(split[0], "hello")); ok1(!strcmp(split[1], "")); @@ -54,16 +54,20 @@ int main(void) str = tal_strjoin(NULL, (char **)substrings, ", ", STR_TRAIL); ok1(!strcmp(str, "far, bar, baz, b, ba, z, ar, ")); + ok1(tal_count(str) == strlen(str) + 1); ctx = str; str = tal_strjoin(ctx, (char **)substrings, "", STR_TRAIL); ok1(!strcmp(str, "farbarbazbbazar")); + ok1(tal_count(str) == strlen(str) + 1); ok1(tal_parent(str) == ctx); str = tal_strjoin(ctx, (char **)substrings, ", ", STR_NO_TRAIL); ok1(tal_parent(str) == ctx); ok1(!strcmp(str, "far, bar, baz, b, ba, z, ar")); + ok1(tal_count(str) == strlen(str) + 1); str = tal_strjoin(ctx, (char **)substrings, "", STR_NO_TRAIL); ok1(!strcmp(str, "farbarbazbbazar")); ok1(tal_parent(str) == ctx); + ok1(tal_count(str) == strlen(str) + 1); tal_free(ctx); ctx = tal_strdup(NULL, "context"); @@ -77,6 +81,7 @@ int main(void) str = tal_strdup(ctx, "hello world"); ok1(tal_check(ctx, NULL)); ok1(tal_check(str, NULL)); + ok1(tal_count(str) == strlen(str) + 1); split = tal_strsplit(ctx, take(str), " ", STR_EMPTY_OK); ok1(tal_parent(split) == ctx); ok1(!strcmp(split[0], "hello")); @@ -90,6 +95,7 @@ int main(void) /* tal_strsplit take delims */ str = tal_strdup(ctx, " "); + ok1(tal_count(str) == strlen(str) + 1); split = tal_strsplit(ctx, "hello world", take(str), STR_EMPTY_OK); ok1(tal_parent(split) == ctx); ok1(!strcmp(split[0], "hello")); @@ -124,6 +130,7 @@ int main(void) split = tal_strsplit(ctx, "hello world", " ", STR_EMPTY_OK); str = tal_strjoin(ctx, take(split), " there ", STR_NO_TRAIL); ok1(!strcmp(str, "hello there world")); + ok1(tal_count(str) == strlen(str) + 1); ok1(tal_parent(str) == ctx); /* split is gone... */ ok1(single_child(ctx, str)); @@ -136,6 +143,7 @@ int main(void) STR_NO_TRAIL); ok1(!strcmp(str, "hello there world")); ok1(tal_parent(str) == ctx); + ok1(tal_count(str) == strlen(str) + 1); tal_free(split); /* tmp alloc is gone, str is only remainder. */ ok1(single_child(ctx, str)); @@ -147,6 +155,7 @@ int main(void) STR_EMPTY_OK)), take(tal_strdup(ctx, " there ")), STR_NO_TRAIL); ok1(!strcmp(str, "hello there world")); + ok1(tal_count(str) == strlen(str) + 1); ok1(tal_parent(str) == ctx); /* tmp allocs are gone, str is only remainder. */ ok1(single_child(ctx, str)); diff --git a/ccan/ccan/tal/tal.c b/ccan/ccan/tal/tal.c index 0e3c97b39..3fac61129 100644 --- a/ccan/ccan/tal/tal.c +++ b/ccan/ccan/tal/tal.c @@ -24,7 +24,6 @@ enum prop_type { CHILDREN = 0x00c1d500, NAME = 0x00111100, NOTIFIER = 0x00071f00, - LENGTH = 0x00515300 }; struct tal_hdr { @@ -32,6 +31,7 @@ struct tal_hdr { struct prop_hdr *prop; /* XOR with TAL_PTR_OBFUSTICATOR */ intptr_t parent_child; + size_t bytelen; }; struct prop_hdr { @@ -50,11 +50,6 @@ struct name { char name[]; }; -struct length { - struct prop_hdr hdr; /* LENGTH */ - size_t len; -}; - struct notifier { struct prop_hdr hdr; /* NOTIFIER */ enum tal_notify_type types; @@ -77,7 +72,7 @@ static struct { struct tal_hdr hdr; struct children c; } null_parent = { { { &null_parent.hdr.list, &null_parent.hdr.list }, - &null_parent.c.hdr, TAL_PTR_OBFUSTICATOR }, + &null_parent.c.hdr, TAL_PTR_OBFUSTICATOR, 0 }, { { CHILDREN, NULL }, &null_parent.hdr, { { &null_parent.c.children.n, @@ -414,50 +409,23 @@ static void del_tree(struct tal_hdr *t, const tal_t *orig, int saved_errno) /* Finally free our properties. */ for (p = t->prop; p && !is_literal(p); p = next) { next = p->next; - /* LENGTH is appended, so don't free separately! */ - if (p->type != LENGTH) - freefn(p); + freefn(p); } freefn(t); } -static size_t extra_for_length(size_t size) -{ - size_t extra; - const size_t align = ALIGNOF(struct length); - - /* Round up size, and add tailer. */ - extra = ((size + align-1) & ~(align-1)) - size; - extra += sizeof(struct length); - return extra; -} - -void *tal_alloc_(const tal_t *ctx, size_t size, - bool clear, bool add_length, const char *label) +void *tal_alloc_(const tal_t *ctx, size_t size, bool clear, const char *label) { - size_t req_size = size; struct tal_hdr *child, *parent = debug_tal(to_tal_hdr_or_null(ctx)); -#ifdef CCAN_TAL_DEBUG - /* Always record length if debugging. */ - add_length = true; -#endif - if (add_length) - size += extra_for_length(size); - child = allocate(sizeof(struct tal_hdr) + size); if (!child) return NULL; if (clear) - memset(from_tal_hdr(child), 0, req_size); + memset(from_tal_hdr(child), 0, size); child->prop = (void *)label; + child->bytelen = size; - if (add_length) { - struct length *lprop; - lprop = (struct length *)((char *)(child+1) + size) - 1; - init_property(&lprop->hdr, child, LENGTH); - lprop->len = req_size; - } if (!add_child(parent, child)) { freefn(child); return NULL; @@ -470,7 +438,7 @@ void *tal_alloc_(const tal_t *ctx, size_t size, static bool adjust_size(size_t *size, size_t count) { - const size_t extra = sizeof(struct tal_hdr) + sizeof(struct length)*2; + const size_t extra = sizeof(struct tal_hdr); /* Multiplication wrap */ if (count && unlikely(*size * count / *size != count)) @@ -478,7 +446,7 @@ static bool adjust_size(size_t *size, size_t count) *size *= count; - /* Make sure we don't wrap adding header/tailer. */ + /* Make sure we don't wrap adding header. */ if (*size + extra < extra) goto overflow; return true; @@ -488,12 +456,12 @@ overflow: } void *tal_alloc_arr_(const tal_t *ctx, size_t size, size_t count, bool clear, - bool add_length, const char *label) + const char *label) { if (!adjust_size(&size, count)) return NULL; - return tal_alloc_(ctx, size, clear, add_length, label); + return tal_alloc_(ctx, size, clear, label); } void *tal_free(const tal_t *ctx) @@ -656,17 +624,12 @@ const char *tal_name(const tal_t *t) return n->name; } -size_t tal_len(const tal_t *ptr) +size_t tal_bytelen(const tal_t *ptr) { - struct length *l; + /* NULL -> null_parent which has bytelen 0 */ + struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ptr)); - if (!ptr) - return 0; - - l = find_property(debug_tal(to_tal_hdr(ptr)), LENGTH); - if (!l) - return 0; - return l->len; + return t->bytelen; } /* Start one past first child: make stopping natural in circ. list. */ @@ -720,52 +683,27 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear) { struct tal_hdr *old_t, *t; struct children *child; - struct prop_hdr **lenp; - struct length len; - size_t extra = 0; old_t = debug_tal(to_tal_hdr(*ctxp)); if (!adjust_size(&size, count)) return false; - lenp = find_property_ptr(old_t, LENGTH); - if (lenp) { - /* Copy here, in case we're shrinking! */ - len = *(struct length *)*lenp; - extra = extra_for_length(size); - } else /* If we don't have an old length, we can't clear! */ - assert(!clear); - - t = resizefn(old_t, sizeof(struct tal_hdr) + size + extra); + t = resizefn(old_t, sizeof(struct tal_hdr) + size); if (!t) { call_error("Reallocation failure"); return false; } - /* Copy length to end. */ - if (lenp) { - struct length *new_len; - - /* Clear between old end and new end. */ - if (clear && size > len.len) { - char *old_end = (char *)(t + 1) + len.len; - memset(old_end, 0, size - len.len); - } - - new_len = (struct length *)((char *)(t + 1) + size - + extra - sizeof(len)); - len.len = size; - *new_len = len; - - /* Be careful replacing next ptr; could be old hdr. */ - if (lenp == &old_t->prop) - t->prop = &new_len->hdr; - else - *lenp = &new_len->hdr; + /* Clear between old end and new end. */ + if (clear && size > t->bytelen) { + char *old_end = (char *)(t + 1) + t->bytelen; + memset(old_end, 0, size - t->bytelen); } - update_bounds(t, sizeof(struct tal_hdr) + size + extra); + /* Update length. */ + t->bytelen = size; + update_bounds(t, sizeof(struct tal_hdr) + size); /* If it didn't move, we're done! */ if (t != old_t) { @@ -790,12 +728,10 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear) bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count) { - struct length *l; size_t old_len; bool ret = false; - l = find_property(debug_tal(to_tal_hdr(*ctxp)), LENGTH); - old_len = l->len; + old_len = debug_tal(to_tal_hdr(*ctxp))->bytelen; /* Check for additive overflow */ if (old_len + count * size < old_len) { @@ -820,8 +756,7 @@ out: } void *tal_dup_(const tal_t *ctx, const void *p, size_t size, - size_t n, size_t extra, bool add_length, - const char *label) + size_t n, size_t extra, const char *label) { void *ret; size_t nbytes = size; @@ -850,7 +785,7 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size, return (void *)p; } - ret = tal_alloc_arr_(ctx, size, n + extra, false, add_length, label); + ret = tal_alloc_arr_(ctx, size, n + extra, false, label); if (ret) memcpy(ret, p, nbytes); return ret; @@ -879,12 +814,11 @@ static void dump_node(unsigned int indent, const struct tal_hdr *t) for (i = 0; i < indent; i++) printf(" "); - printf("%p", t); + printf("%p len=%zu", t, t->bytelen); for (p = t->prop; p; p = p->next) { struct children *c; struct name *n; struct notifier *no; - struct length *l; if (is_literal(p)) { printf(" \"%s\"", (const char *)p); break; @@ -904,10 +838,6 @@ static void dump_node(unsigned int indent, const struct tal_hdr *t) no = (struct notifier *)p; printf(" NOTIFIER(%p):fn=%p", p, no->u.notifyfn); break; - case LENGTH: - l = (struct length *)p; - printf(" LENGTH(%p):len=%zu", p, l->len); - break; default: printf(" **UNKNOWN(%p):%i**", p, p->type); } @@ -955,7 +885,6 @@ static bool check_node(struct children *parent_child, struct prop_hdr *p; struct name *name = NULL; struct children *children = NULL; - struct length *length = NULL; if (!in_bounds(t)) return check_err(t, errorstr, "invalid pointer"); @@ -981,12 +910,6 @@ static bool check_node(struct children *parent_child, "has two child nodes"); children = (struct children *)p; break; - case LENGTH: - if (length) - return check_err(t, errorstr, - "has two lengths"); - length = (struct length *)p; - break; case NOTIFIER: break; case NAME: diff --git a/ccan/ccan/tal/tal.h b/ccan/ccan/tal/tal.h index 30c8e7bb9..54318e1fa 100644 --- a/ccan/ccan/tal/tal.h +++ b/ccan/ccan/tal/tal.h @@ -28,12 +28,14 @@ typedef void tal_t; * of the object is a string of the type, but if CCAN_TAL_DEBUG is * defined it also contains the file and line which allocated it. * + * tal_count() of the return will be 1. + * * Example: * int *p = tal(NULL, int); * *p = 1; */ #define tal(ctx, type) \ - ((type *)tal_alloc_((ctx), sizeof(type), false, false, TAL_LABEL(type, ""))) + tal_label(ctx, type, TAL_LABEL(type, "")) /** * talz - zeroing allocator function @@ -47,7 +49,7 @@ typedef void tal_t; * assert(*p == 0); */ #define talz(ctx, type) \ - ((type *)tal_alloc_((ctx), sizeof(type), true, false, TAL_LABEL(type, ""))) + talz_label(ctx, type, TAL_LABEL(type, "")) /** * tal_free - free a tal-allocated pointer. @@ -71,8 +73,7 @@ void *tal_free(const tal_t *p); * @type: the type to allocate. * @count: the number to allocate. * - * Note that an object allocated with tal_arr() has a length property; - * see tal_count(). + * tal_count() of the returned pointer will be @count. * * Example: * p = tal_arr(NULL, int, 2); @@ -80,8 +81,7 @@ void *tal_free(const tal_t *p); * p[1] = 1; */ #define tal_arr(ctx, type, count) \ - ((type *)tal_alloc_arr_((ctx), sizeof(type), (count), false, \ - true, TAL_LABEL(type, "[]"))) + tal_arr_label(ctx, type, count, TAL_LABEL(type, "[]")) /** * tal_arrz - allocate an array of zeroed objects. @@ -89,24 +89,22 @@ void *tal_free(const tal_t *p); * @type: the type to allocate. * @count: the number to allocate. * - * Note that an object allocated with tal_arrz() has a length property; - * see tal_count(). + * Equivalent to tal_arr() followed by memset() to zero. * * Example: * p = tal_arrz(NULL, int, 2); * assert(p[0] == 0 && p[1] == 0); */ #define tal_arrz(ctx, type, count) \ - ((type *)tal_alloc_arr_((ctx), sizeof(type), (count), true, \ - true, TAL_LABEL(type, "[]"))) + tal_arrz_label(ctx, type, count, TAL_LABEL(type, "[]")) /** - * tal_resize - enlarge or reduce a tal_arr[z]. + * tal_resize - enlarge or reduce a tal object. * @p: A pointer to the tal allocated array to resize. * @count: the number to allocate. * * This returns true on success (and may move *@p), or false on failure. - * If @p has a length property, it is updated on success. + * On success, tal_count() of *@p will be @count. * * Example: * tal_resize(&p, 100); @@ -115,13 +113,11 @@ void *tal_free(const tal_t *p); tal_resize_((void **)(p), sizeof**(p), (count), false) /** - * tal_resizez - enlarge or reduce a tal_arr[z]; zero out extra. + * tal_resizez - enlarge or reduce a tal object; zero out extra. * @p: A pointer to the tal allocated array to resize. * @count: the number to allocate. * * This returns true on success (and may move *@p), or false on failure. - * If @p has a length property, it is updated on success. - * On expand, new elements are memset to 0 bytes. * * Example: * tal_resizez(&p, 200); @@ -304,22 +300,22 @@ enum tal_notify_type { const char *tal_name(const tal_t *ptr); /** - * tal_count - get the count of objects in a tal_arr. - * @ptr: The tal allocated object array (or NULL) + * tal_count - get the count of objects in a tal object. + * @ptr: The tal allocated object (or NULL) * - * Returns 0 if @ptr has no length property or is NULL, but be aware - * that that is also a valid size! + * Returns 0 if @ptr is NULL. Note that if the allocation was done as a + * different type to @ptr, the result may not match the @count argument + * (or implied 1) of that allocation! */ -#define tal_count(p) (tal_len(p) / sizeof(*p)) +#define tal_count(p) (tal_bytelen(p) / sizeof(*p)) /** - * tal_len - get the count of bytes in a tal_arr. - * @ptr: The tal allocated object array (or NULL) + * tal_bytelen - get the count of bytes in a tal object. + * @ptr: The tal allocated object (or NULL) * - * Returns 0 if @ptr has no length property or NULL, but be aware that that is - * also a valid size! + * Returns 0 if @ptr is NULL. */ -size_t tal_len(const tal_t *ptr); +size_t tal_bytelen(const tal_t *ptr); /** * tal_first - get the first immediate tal object child. @@ -353,9 +349,7 @@ tal_t *tal_parent(const tal_t *ctx); * @p: the object to copy (or reparented if take()) */ #define tal_dup(ctx, type, p) \ - ((type *)tal_dup_((ctx), tal_typechk_(p, type *), \ - sizeof(type), 1, 0, \ - false, TAL_LABEL(type, ""))) + tal_dup_label(ctx, type, p, TAL_LABEL(type, "")) /** * tal_dup_arr - duplicate an array. @@ -366,10 +360,27 @@ tal_t *tal_parent(const tal_t *ctx); * @extra: the number of extra sizeof(type) entries to allocate. */ #define tal_dup_arr(ctx, type, p, n, extra) \ + tal_dup_arr_label(ctx, type, p, n, extra, TAL_LABEL(type, "[]")) + + + +/* Lower-level interfaces, where you want to supply your own label string. */ +#define tal_label(ctx, type, label) \ + ((type *)tal_alloc_((ctx), sizeof(type), false, label)) +#define talz_label(ctx, type, label) \ + ((type *)tal_alloc_((ctx), sizeof(type), true, label)) +#define tal_arr_label(ctx, type, count, label) \ + ((type *)tal_alloc_arr_((ctx), sizeof(type), (count), false, label)) +#define tal_arrz_label(ctx, type, count, label) \ + ((type *)tal_alloc_arr_((ctx), sizeof(type), (count), true, label)) +#define tal_dup_label(ctx, type, p, label) \ + ((type *)tal_dup_((ctx), tal_typechk_(p, type *), \ + sizeof(type), 1, 0, \ + label)) +#define tal_dup_arr_label(ctx, type, p, n, extra, label) \ ((type *)tal_dup_((ctx), tal_typechk_(p, type *), \ sizeof(type), (n), (extra), \ - true, TAL_LABEL(type, "[]"))) - + label)) /** * tal_set_backend - set the allocation or error functions to use @@ -483,14 +494,12 @@ bool tal_set_name_(tal_t *ctx, const char *name, bool literal); #define tal_typechk_(ptr, ptype) (ptr) #endif -void *tal_alloc_(const tal_t *ctx, size_t bytes, bool clear, - bool add_length, const char *label); +void *tal_alloc_(const tal_t *ctx, size_t bytes, bool clear, const char *label); void *tal_alloc_arr_(const tal_t *ctx, size_t bytes, size_t count, bool clear, - bool add_length, const char *label); + const char *label); void *tal_dup_(const tal_t *ctx, const void *p TAKES, size_t size, - size_t n, size_t extra, bool add_length, - const char *label); + size_t n, size_t extra, const char *label); tal_t *tal_steal_(const tal_t *new_parent, const tal_t *t); diff --git a/ccan/ccan/tal/test/run-count.c b/ccan/ccan/tal/test/run-count.c index 33049b9f7..a621e1d8b 100644 --- a/ccan/ccan/tal/test/run-count.c +++ b/ccan/ccan/tal/test/run-count.c @@ -46,7 +46,7 @@ int main(void) plan_tests(2 + 19 * 3); p1 = NULL; - ok1(tal_len(p1) == 0); + ok1(tal_bytelen(p1) == 0); ok1(tal_count(p1) == 0); for (i = 0; i < 3; i++) { @@ -54,7 +54,7 @@ int main(void) p1 = tal(NULL, char); ok1(p1); - ok1(tal_count(p1) == 0); + ok1(tal_count(p1) == 1); p2 = tal_arr(p1, char, 1); ok1(p2); diff --git a/ccan_compat.h b/ccan_compat.h index 1c648dabe..f0337f33f 100644 --- a/ccan_compat.h +++ b/ccan_compat.h @@ -16,12 +16,4 @@ #define sha256_be16(ctx, v) ccan_sha256_be16(ctx, v) #define sha256_be32(ctx, v) ccan_sha256_be32(ctx, v) #define sha256_be64(ctx, v) ccan_sha256_be64(ctx, v) - -/* Transition for ccan update. */ -#define tal_bytelen(x) tal_len(x) -#define tal_arr_label(ctx, type, len, label) \ - ((type *)tal_alloc_arr_(ctx, sizeof(type), len, false, true, label)) -#define tal_arrz_label(ctx, type, len, label) \ - ((type *)tal_alloc_arr_(ctx, sizeof(type), len, true, true, label)) - #endif /* LIGHTNING_CCAN_COMPAT_H */