From 8d14165ac039a97617f2b63ee70754b855776013 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sun, 8 Sep 2013 16:23:02 +0930 Subject: [PATCH 1/1] tal: add tal_resizez for zero-padded expansion. Signed-off-by: Rusty Russell --- ccan/tal/tal.c | 17 ++++++++++++----- ccan/tal/tal.h | 19 +++++++++++++++++-- ccan/tal/test/run-array.c | 1 + ccan/tal/test/run-resizez.c | 27 +++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 ccan/tal/test/run-resizez.c diff --git a/ccan/tal/tal.c b/ccan/tal/tal.c index 1934a013..1eaa5749 100644 --- a/ccan/tal/tal.c +++ b/ccan/tal/tal.c @@ -670,13 +670,13 @@ tal_t *tal_parent(const tal_t *ctx) return from_tal_hdr(ignore_destroying_bit(t->parent_child)->parent); } -bool tal_resize_(tal_t **ctxp, size_t size, size_t count) +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; + size_t extra = 0, elemsize = size; old_t = debug_tal(to_tal_hdr(*ctxp)); @@ -688,7 +688,8 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count) /* 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); if (!t) { @@ -700,6 +701,12 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count) if (lenp) { struct length *new_len; + /* Clear between old end and new end. */ + if (clear && count > len.count) { + char *old_end = (char *)(t + 1) + len.count * elemsize; + memset(old_end, 0, elemsize * (count - len.count)); + } + new_len = (struct length *)((char *)(t + 1) + size); len.count = count; *new_len = len; @@ -753,7 +760,7 @@ bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count) assert(src < *ctxp || (char *)src >= (char *)(*ctxp) + (size * old_count)); - if (!tal_resize_(ctxp, size, old_count + count)) + if (!tal_resize_(ctxp, size, old_count + count, false)) goto out; memcpy((char *)*ctxp + size * old_count, src, count * size); @@ -789,7 +796,7 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size, if (taken(p)) { if (unlikely(!p)) return NULL; - if (unlikely(!tal_resize_((void **)&p, size, n + extra))) + if (unlikely(!tal_resize_((void **)&p, size, n + extra, false))) return tal_free(p); if (unlikely(!tal_steal(ctx, p))) return tal_free(p); diff --git a/ccan/tal/tal.h b/ccan/tal/tal.h index 86b56d35..0b050759 100644 --- a/ccan/tal/tal.h +++ b/ccan/tal/tal.h @@ -110,7 +110,22 @@ void *tal_free(const tal_t *p); * tal_resize(&p, 100); */ #define tal_resize(p, count) \ - tal_resize_((void **)(p), sizeof**(p), (count)) + tal_resize_((void **)(p), sizeof**(p), (count), false) + +/** + * tal_resizez - enlarge or reduce a tal_arr[z]; 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); + */ +#define tal_resizez(p, count) \ + tal_resize_((void **)(p), sizeof**(p), (count), true) /** * tal_steal - change the parent of a tal-allocated pointer. @@ -406,7 +421,7 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size, tal_t *tal_steal_(const tal_t *new_parent, const tal_t *t); -bool tal_resize_(tal_t **ctxp, size_t size, size_t count); +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); bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me)); diff --git a/ccan/tal/test/run-array.c b/ccan/tal/test/run-array.c index d3001faf..5cab66e9 100644 --- a/ccan/tal/test/run-array.c +++ b/ccan/tal/test/run-array.c @@ -40,6 +40,7 @@ int main(void) strcpy(c[0], "hello"); tal_free(c[0]); ok1(tal_first(parent) == NULL); + tal_free(parent); tal_cleanup(); diff --git a/ccan/tal/test/run-resizez.c b/ccan/tal/test/run-resizez.c new file mode 100644 index 00000000..ddf66828 --- /dev/null +++ b/ccan/tal/test/run-resizez.c @@ -0,0 +1,27 @@ +#include +#include +#include + +int main(void) +{ + char *parent, *c; + int i; + + plan_tests(1 + 3 * 100 + 98); + + parent = tal(NULL, char); + ok1(parent); + + for (i = 0; i < 100; i++) { + c = tal_arr(parent, char, 1); + ok1(tal_resizez(&c, i)); + ok1(tal_count(c) == i); + ok1(tal_parent(c) == parent); + if (i > 1) + ok1(c[i-1] == '\0'); + } + tal_free(parent); + + tal_cleanup(); + return exit_status(); +} -- 2.39.2