tal: add tal_resizez for zero-padded expansion.
authorRusty Russell <rusty@rustcorp.com.au>
Sun, 8 Sep 2013 06:53:02 +0000 (16:23 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Sun, 8 Sep 2013 06:53:02 +0000 (16:23 +0930)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/tal/tal.c
ccan/tal/tal.h
ccan/tal/test/run-array.c
ccan/tal/test/run-resizez.c [new file with mode: 0644]

index 1934a01318a3f09060614e144d189fff8467469b..1eaa5749476aa3abd23992c16167b031c47175f6 100644 (file)
@@ -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);
index 86b56d35a3c26280a9915216a5443ebef78626e1..0b050759f74ed97829661de5dc2488af74264fe9 100644 (file)
@@ -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));
index d3001faff84178746ff9dced2768b2f3ed296412..5cab66e9f9e4c50d46b31c1684691a6493274bf8 100644 (file)
@@ -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 (file)
index 0000000..ddf6682
--- /dev/null
@@ -0,0 +1,27 @@
+#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();
+}