Browse Source

tal: add tal_resizez for zero-padded expansion.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 12 years ago
parent
commit
8d14165ac0
4 changed files with 57 additions and 7 deletions
  1. 12 5
      ccan/tal/tal.c
  2. 17 2
      ccan/tal/tal.h
  3. 1 0
      ccan/tal/test/run-array.c
  4. 27 0
      ccan/tal/test/run-resizez.c

+ 12 - 5
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);

+ 17 - 2
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));

+ 1 - 0
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();

+ 27 - 0
ccan/tal/test/run-resizez.c

@@ -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();
+}