Commit 8d14165a authored by Rusty Russell's avatar Rusty Russell

tal: add tal_resizez for zero-padded expansion.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent daf621ae
...@@ -670,13 +670,13 @@ tal_t *tal_parent(const tal_t *ctx) ...@@ -670,13 +670,13 @@ tal_t *tal_parent(const tal_t *ctx)
return from_tal_hdr(ignore_destroying_bit(t->parent_child)->parent); 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 tal_hdr *old_t, *t;
struct children *child; struct children *child;
struct prop_hdr **lenp; struct prop_hdr **lenp;
struct length len; struct length len;
size_t extra = 0; size_t extra = 0, elemsize = size;
old_t = debug_tal(to_tal_hdr(*ctxp)); old_t = debug_tal(to_tal_hdr(*ctxp));
...@@ -688,7 +688,8 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count) ...@@ -688,7 +688,8 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count)
/* Copy here, in case we're shrinking! */ /* Copy here, in case we're shrinking! */
len = *(struct length *)*lenp; len = *(struct length *)*lenp;
extra = extra_for_length(size); 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 + extra);
if (!t) { if (!t) {
...@@ -700,6 +701,12 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count) ...@@ -700,6 +701,12 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count)
if (lenp) { if (lenp) {
struct length *new_len; 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); new_len = (struct length *)((char *)(t + 1) + size);
len.count = count; len.count = count;
*new_len = len; *new_len = len;
...@@ -753,7 +760,7 @@ bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count) ...@@ -753,7 +760,7 @@ bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count)
assert(src < *ctxp assert(src < *ctxp
|| (char *)src >= (char *)(*ctxp) + (size * old_count)); || (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; goto out;
memcpy((char *)*ctxp + size * old_count, src, count * size); 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, ...@@ -789,7 +796,7 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size,
if (taken(p)) { if (taken(p)) {
if (unlikely(!p)) if (unlikely(!p))
return NULL; 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); return tal_free(p);
if (unlikely(!tal_steal(ctx, p))) if (unlikely(!tal_steal(ctx, p)))
return tal_free(p); return tal_free(p);
......
...@@ -110,7 +110,22 @@ void *tal_free(const tal_t *p); ...@@ -110,7 +110,22 @@ void *tal_free(const tal_t *p);
* tal_resize(&p, 100); * tal_resize(&p, 100);
*/ */
#define tal_resize(p, count) \ #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. * 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, ...@@ -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); 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_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)); bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me));
......
...@@ -40,6 +40,7 @@ int main(void) ...@@ -40,6 +40,7 @@ int main(void)
strcpy(c[0], "hello"); strcpy(c[0], "hello");
tal_free(c[0]); tal_free(c[0]);
ok1(tal_first(parent) == NULL); ok1(tal_first(parent) == NULL);
tal_free(parent); tal_free(parent);
tal_cleanup(); tal_cleanup();
......
#include <ccan/tal/tal.h>
#include <ccan/tal/tal.c>
#include <ccan/tap/tap.h>
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();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment