From: Michael Zucchi Date: Mon, 29 Apr 2019 22:34:12 +0000 (+0930) Subject: Added a LIST type to the blob descriptor. X-Git-Url: https://code.zedzone.au/cvs?a=commitdiff_plain;h=4b81d6771a3360f9da77d93c8599ca707b2f8394;p=libeze Added a LIST type to the blob descriptor. Made ez-blob-print public. --- diff --git a/Makefile b/Makefile index 3d0b6ce..0a828bf 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,14 @@ CPPFLAGS=-I. -CFLAGS=-O2 -fPIC -Wall -mtune=native +CFLAGS=-Og -g -fPIC -Wall -mtune=native test_LDLIBS=-lpthread -lrt ARFLAGS=rvsUc -VERSION=2.0 +VERSION=2.1.99 SRCS= \ ez-bitset.c \ ez-blob.c \ + ez-blob-print.c \ ez-port.c \ ez-set.c \ ez-tree.c @@ -41,7 +42,7 @@ test-%: test-%.o $(CC) $(CFLAGS) -o $@ $< libeze.a $(test_LDLIBS) test-bitset: libeze.a(ez-bitset.o) -test-blob: libeze.a(ez-blob.o) +test-blob: libeze.a(ez-blob.o) libeze.a(ez-blob-print.o) test-port: libeze.a(ez-port.o) test-set: libeze.a(ez-set.o) test-tree: libeze.a(ez-tree.o) diff --git a/ez-blob-print.c b/ez-blob-print.c new file mode 100644 index 0000000..8fa94dc --- /dev/null +++ b/ez-blob-print.c @@ -0,0 +1,121 @@ +/* ez-blob.h: Serialising description and serialiser. + + Copyright (C) 2019 Michael Zucchi + + This program is free software: you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + . +*/ + +#include +#include +#include + +#include +#include +#include + +#include "ez-blob.h" +#include "ez-list.h" + +static void dumphex(const char *data, size_t size, const char *prefix) { + for (int i=0;ibd_type != EZ_BLOB_END);d++) { + const void *u = a + d->bd_offset; + + printf("%s [type=$%02x, offset=$%04x]", x, d->bd_type, d->bd_offset); + + switch (d->bd_type) { + case EZ_BLOB_INT8: + printf(" .%d = %d\n", d->bd_id, *(uint8_t *)u); + break; + case EZ_BLOB_INT16: + printf(" .%d = %d\n", d->bd_id, *(uint16_t *)u); + break; + case EZ_BLOB_INT32: + printf(" .%d = %d\n", d->bd_id, *(uint32_t *)u); + break; + case EZ_BLOB_INT64: + printf(" .%d = %ld\n", d->bd_id, *(uint64_t *)u); + break; + case EZ_BLOB_FLOAT32: + printf(" .%d = %f\n", d->bd_id, *(float *)u); + break; + case EZ_BLOB_FLOAT64: + printf(" .%d = %f\n", d->bd_id, *(double *)u); + break; + case EZ_BLOB_STRING: + printf(" .%d %p = `%s'\n", d->bd_id, *((char **)u), *((char **)u)); + break; + case EZ_BLOB_BLOB: { + const struct ez_blob *ua = u; + + printf(" .%d %p [%zd] = {\n", d->bd_id, ua->data, ua->size); + dumphex(ua->data, ua->size, x); + printf("%s }\n", x); + break; } + case EZ_BLOB_POINTER: { + void *up = *((void **)u); + if (up) { + printf(" .%d %p = {\n", d->bd_id, up); + ez_blob_print(d->bd_table, up, depth+4); + printf("%s }\n", x); + } else { + printf(" .%d %p\n", d->bd_id, up); + } + break; } + case EZ_BLOB_LIST: { + ez_list *l = (void *)u; + + printf(" .%d %p [] = {\n", d->bd_id, l); + for (ez_node *w = ez_list_head(l), *n = ez_node_next(w); + n; + w = n, n=ez_node_next(n)) { + printf("%s{\n", x); + ez_blob_print(d->bd_table, w, depth+4); + printf("%s},\n", x); + } + printf("%s }\n", x); + break; } + default: + printf("\n"); + } + } +} + diff --git a/ez-blob.c b/ez-blob.c index c6a914e..be6ddc0 100644 --- a/ez-blob.c +++ b/ez-blob.c @@ -24,6 +24,7 @@ #include #include "ez-blob.h" +#include "ez-list.h" /* This implements a basic 'high performance' serialisation based on the @@ -70,8 +71,8 @@ size_t ez_blob_size(const ez_blob_desc *d, const void *p) { char *s = ((char **)v)[0]; size += s ? 4 + strlen(s) : 4; break; } - case EZ_BLOB_ARRAY: - size += 4 + ((const struct ez_blob_array *)v)->size; + case EZ_BLOB_BLOB: + size += 4 + ((const struct ez_blob *)v)->size; break; case EZ_BLOB_STRUCT: { const void *sp = v; @@ -81,6 +82,16 @@ size_t ez_blob_size(const ez_blob_desc *d, const void *p) { const void *s = ((const void * const *)v)[0]; size += s ? 4 + ez_blob_size(d->bd_table, s) : 4; break; } + case EZ_BLOB_LIST: { + ez_list *l = (ez_list *)v; + + size += 4; + for (ez_node *w = ez_list_head(l), *n = ez_node_succ(w); + n; + w = n, n=ez_node_succ(n)) { + size += 4 + ez_blob_size(d->bd_table, w); + } + break; } default: break; } @@ -98,8 +109,8 @@ void ez_blob_free_raw(const ez_blob_desc *d, void *p) { case EZ_BLOB_STRING: free(((char **)v)[0]); break; - case EZ_BLOB_ARRAY: - free(((struct ez_blob_array *)v)->data); + case EZ_BLOB_BLOB: + free(((struct ez_blob *)v)->data); break; case EZ_BLOB_STRUCT: ez_blob_free_raw(d->bd_table, v); @@ -107,6 +118,14 @@ void ez_blob_free_raw(const ez_blob_desc *d, void *p) { case EZ_BLOB_POINTER: ez_blob_free(d->bd_table, ((void **)v)[0]); break; + case EZ_BLOB_LIST: { + ez_list *l = (ez_list *)v; + for (ez_node *w = ez_list_head(l), *n = ez_node_succ(w); + n; + w = n, n=ez_node_succ(n)) { + ez_blob_free(d->bd_table, w); + } + break; } default: break; } @@ -120,8 +139,9 @@ void ez_blob_free(const ez_blob_desc *d, void *p) { } } -void *ez_blob_decode_raw(const ez_blob_desc *d, const char *b, size_t size, void *p) { - const char *be = b + size; +void *ez_blob_decode_raw(const ez_blob_desc *d, const ez_blob *blob, void *p) { + const char *b = blob->data; + const char *be = b + blob->size; memset(p, 0, d->bd_offset); @@ -135,14 +155,52 @@ void *ez_blob_decode_raw(const ez_blob_desc *d, const char *b, size_t size, void goto fail; memcpy(v, b, psize); b += psize; + } else if (d->bd_type == EZ_BLOB_LIST) { + uint32_t count; + ez_list *l = v; + + if (b + 4 > be) + goto fail; + memcpy(&count, b, 4); + b += 4; + + ez_list_init(l); + for (int i=0;i be) + goto fail; + memcpy(&ss, b, 4); + b += 4; + + sub.size = ss; + sub.data = (void *)b; + + if (b + ss > be) + goto fail; + if ((s = calloc(d->bd_table->bd_offset, 1)) == NULL) + goto fail; + if (ez_blob_decode_raw(d->bd_table, &sub, s) == NULL) { + free(s); + goto fail; + } + ez_list_addtail(l, s); + b+=ss; + } } else if (d->bd_type <= EZ_BLOB_LAST) { uint32_t ss; + ez_blob sub; if (b + 4 > be) goto fail; memcpy(&ss, b, 4); b += 4; + sub.size = ss; + sub.data = (char *)b; + switch (d->bd_type) { case EZ_BLOB_STRING: { char *s = NULL; @@ -158,8 +216,8 @@ void *ez_blob_decode_raw(const ez_blob_desc *d, const char *b, size_t size, void } ((char **)v)[0] = s; break; } - case EZ_BLOB_ARRAY: { - struct ez_blob_array *a = v; + case EZ_BLOB_BLOB: { + struct ez_blob *a = v; if (b + ss > be) goto fail; @@ -173,7 +231,7 @@ void *ez_blob_decode_raw(const ez_blob_desc *d, const char *b, size_t size, void if (b + ss > be) goto fail; - if (ez_blob_decode_raw(d->bd_table, b, ss, v) == NULL) + if (ez_blob_decode_raw(d->bd_table, &sub, v) == NULL) goto fail; b += ss; break; @@ -185,7 +243,7 @@ void *ez_blob_decode_raw(const ez_blob_desc *d, const char *b, size_t size, void goto fail; if ((s = calloc(d->bd_table->bd_offset, 1)) == NULL) goto fail; - if (ez_blob_decode_raw(d->bd_table, b, ss, s) == NULL) { + if (ez_blob_decode_raw(d->bd_table, &sub, s) == NULL) { free(s); goto fail; } @@ -207,10 +265,10 @@ void *ez_blob_decode_raw(const ez_blob_desc *d, const char *b, size_t size, void return NULL; } -void *ez_blob_decode(const ez_blob_desc *d, const char *b, size_t size) { +void *ez_blob_decode(const ez_blob_desc *d, const ez_blob *blob) { void *p = calloc(d->bd_offset, 1); - if (ez_blob_decode_raw(d, b, size, p) == NULL) { + if (ez_blob_decode_raw(d, blob, p) == NULL) { free(p); return NULL; } @@ -218,8 +276,10 @@ void *ez_blob_decode(const ez_blob_desc *d, const char *b, size_t size) { return p; } -void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, char *b, size_t size) { - char *be = b+size; +void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, ez_blob *blob) { + char *b = blob->data; + char *be = b+blob->size; + for (;(d->bd_type != EZ_BLOB_END);d++) { const void *v = (p + d->bd_offset); @@ -229,8 +289,29 @@ void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, char *b, size_t si assert(b+psize <= be); memcpy(b, v, psize); b += psize; + } else if (d->bd_type == EZ_BLOB_LIST) { + ez_list *l = (void *)v; + uint32_t ss = ez_list_size(l); + + memcpy(b, &ss, 4); + b += 4; + for (ez_node *w = ez_list_head(l), *n = ez_node_succ(w); + n; + w = n, n=ez_node_succ(n)) { + ez_blob sub; + + ss = ez_blob_size(d->bd_table, w); + + assert(b+4+ss <= be); + memcpy(b, &ss, 4); + sub.data = b+4; + sub.size = ss; + ez_blob_encode_raw(d->bd_table, w, &sub); + b += 4 + ss; + } } else if (d->bd_type <= EZ_BLOB_LAST) { uint32_t ss; + struct ez_blob sub; switch (d->bd_type) { case EZ_BLOB_STRING: { @@ -248,8 +329,8 @@ void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, char *b, size_t si b += 4; } break; } - case EZ_BLOB_ARRAY: { - const struct ez_blob_array *a = v; + case EZ_BLOB_BLOB: { + const struct ez_blob *a = v; ss = a->size; assert(b+4+ss <= be); @@ -262,7 +343,9 @@ void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, char *b, size_t si assert(b+4+ss <= be); memcpy(b, &ss, 4); - ez_blob_encode_raw(d->bd_table, v, b+4, ss); + sub.data = b+4; + sub.size = ss; + ez_blob_encode_raw(d->bd_table, v, &sub); b += 4 + ss; break; case EZ_BLOB_POINTER: { @@ -272,7 +355,9 @@ void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, char *b, size_t si ss = ez_blob_size(d->bd_table, s); assert(b+4+ss <= be); memcpy(b, &ss, 4); - ez_blob_encode_raw(d->bd_table, s, b+4, ss); + sub.data = b+4; + sub.size = ss; + ez_blob_encode_raw(d->bd_table, s, &sub); b += 4 + ss; } else { ss = ~0; @@ -289,20 +374,15 @@ void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, char *b, size_t si assert(b == be); } -/** - * Encode blob to new buffer. - * - * @param p object to serialise. - * @param sizep size of encoded blob return pointer. - * @return a newly allocated blob of the correct size. - */ -char *ez_blob_encode(const ez_blob_desc *d, const void *p, size_t *sizep) { - size_t size = ez_blob_size(d, p); - char *b = malloc(size); - - ez_blob_encode_raw(d, p, b, size); - - *sizep = size; - return b; +int ez_blob_encode(const ez_blob_desc *d, const void *p, ez_blob *blob) { + blob->size = ez_blob_size(d, p); + blob->data = malloc(blob->size); + + if (blob->data) { + ez_blob_encode_raw(d, p, blob); + return 0; + } + + return -1; } diff --git a/ez-blob.h b/ez-blob.h index e162f0b..9dfad2f 100644 --- a/ez-blob.h +++ b/ez-blob.h @@ -84,18 +84,22 @@ typedef enum ez_blob_desc_type { EZ_BLOB_FLOAT32, EZ_BLOB_FLOAT64, EZ_BLOB_STRING, // normall c strring - EZ_BLOB_ARRAY, // embedded ez_blob_array for arbitrary bytes. + EZ_BLOB_BLOB, // embedded ez_blob for arbitrary bytes. EZ_BLOB_STRUCT, // bd_table points to another descriptor list, object embedded EZ_BLOB_POINTER, // bd_table points to another descriptor list, object pointer - EZ_BLOB_LAST = EZ_BLOB_POINTER, + EZ_BLOB_LIST, // ez_list nodes. + EZ_BLOB_LAST = EZ_BLOB_LIST, EZ_BLOB_PK = 16, // MUST always be first element in descriptor and occur only once EZ_BLOB_END } ez_blob_desc_type; -typedef struct ez_blob_array { - unsigned int size; +/** + * This is compatible with lmdb MDB_val + */ +typedef struct ez_blob { + size_t size; void *data; -} ez_blob_array; +} ez_blob; #define EZ_BLOB_START(s) { EZ_BLOB_PK, 0, sizeof(s) } #define EZ_BLOB_INT8(s, id, f) { EZ_BLOB_INT8, id, offsetof(s, f) } @@ -105,9 +109,10 @@ typedef struct ez_blob_array { #define EZ_BLOB_FLOAT32(s, id, f) { EZ_BLOB_FLOAT32, id, offsetof(s, f) } #define EZ_BLOB_FLOAT64(s, id, f) { EZ_BLOB_FLOAT64, id, offsetof(s, f) } #define EZ_BLOB_STRING(s, id, f) { EZ_BLOB_STRING, id, offsetof(s, f) } -#define EZ_BLOB_ARRAY(s, id, f) { EZ_BLOB_ARRAY, id, offsetof(s, f) } +#define EZ_BLOB_BLOB(s, id, f) { EZ_BLOB_BLOB, id, offsetof(s, f) } #define EZ_BLOB_STRUCT(s, id, f, other) { EZ_BLOB_STRUCT, id, offsetof(s, f), .u.table = other } #define EZ_BLOB_POINTER(s, id, f, other) { EZ_BLOB_POINTER, id, offsetof(s, f), .u.table = other } +#define EZ_BLOB_LIST(s, id, f, other) { EZ_BLOB_LIST, id, offsetof(s, f), .u.table = other } #define EZ_BLOB_END(s) { EZ_BLOB_END } /** @@ -124,20 +129,19 @@ size_t ez_blob_size(const ez_blob_desc *d, const void *p); * @param d descriptor table matching the struct. * @param p structure. * @param sizep return pointer for blob size, must not be null. - * @return the blob, it must be freed with free() when complete. + * @param blob return, the data pointer must be freed with free() when complete. + * @return non-zero on failure. */ -char *ez_blob_encode(const ez_blob_desc *d, const void *p, size_t *sizep); +int ez_blob_encode(const ez_blob_desc *d, const void *p, ez_blob *blob); /** * Marshal a struct to a blob directly * * @param d descriptor table matching the struct. * @param p structure. - * @param b target memory, must be as large as size - * @param size size of target memory, must be exactly ez_blob_size(). - * @return the blob, it must be freed with free() when complete. + * @param blob available target memory, size must be exactly ez_blob_size(). */ -void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, char *b, size_t size); +void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, ez_blob *blob); /** * Unmarshall a blob into a struct. @@ -147,7 +151,7 @@ void ez_blob_encode_raw(const ez_blob_desc *d, const void *p, char *b, size_t si * @param size blob size. * @return the decoded struct. May be freed using ez_blob_free(). */ -void *ez_blob_decode(const ez_blob_desc *d, const char *blob, size_t size); +void *ez_blob_decode(const ez_blob_desc *d, const ez_blob *blob); /** * Decode to pre-allocated buffer. @@ -156,7 +160,7 @@ void *ez_blob_decode(const ez_blob_desc *d, const char *blob, size_t size); * @param size blob size * @return p is returned on success. On failure NULL is returned and any internal pointers are freed. */ -void *ez_blob_decode_raw(const ez_blob_desc *d, const char *b, size_t size, void *p); +void *ez_blob_decode_raw(const ez_blob_desc *d, const ez_blob *blob, void *p); /** * Free struct unmarshalled by ez_blob_decode(). @@ -174,4 +178,9 @@ void ez_blob_free(const ez_blob_desc *d, void *p); */ void ez_blob_free_raw(const ez_blob_desc *d, void *p); +/** + * Debug function to dump blob contents. + */ +void ez_blob_print(const ez_blob_desc *d, const void *a, int depth); + #endif diff --git a/test-blob.c b/test-blob.c index 1024cb9..bce25d4 100644 --- a/test-blob.c +++ b/test-blob.c @@ -8,6 +8,7 @@ #include #include "ez-blob.h" +#include "ez-list.h" struct simple { char b; @@ -30,13 +31,13 @@ static const ez_blob_desc simple_DESC[] = { struct arrays { uint32_t count; char *string; - ez_blob_array array; + ez_blob array; }; static const ez_blob_desc array_DESC[] = { EZ_BLOB_START(struct arrays), EZ_BLOB_STRING(struct arrays, 1, string), - EZ_BLOB_ARRAY(struct arrays, 2, array), + EZ_BLOB_BLOB(struct arrays, 2, array), EZ_BLOB_END(struct arrays) }; @@ -67,6 +68,31 @@ static const ez_blob_desc tree_DESC[] = { EZ_BLOB_END(struct tree) }; +struct listnode { + ez_node ln; + char *name; + ez_blob value; +}; + +static const ez_blob_desc listnode_DESC[] = { + EZ_BLOB_START(struct listnode), + EZ_BLOB_STRING(struct listnode, 1, name), + EZ_BLOB_BLOB(struct listnode, 2, value), + EZ_BLOB_END(struct listnode) +}; + +struct list { + char *name; + ez_list list; +}; + +static const ez_blob_desc list_DESC[] = { + EZ_BLOB_START(struct list), + EZ_BLOB_STRING(struct list, 1, name), + EZ_BLOB_LIST(struct list, 2, list, listnode_DESC), + EZ_BLOB_END(struct list) +}; + static void dumphex(const char *data, size_t size, const char *prefix) { for (int i=0;ibd_type != EZ_BLOB_END);d++) { - const void *u = a + d->bd_offset; - - printf("%s [type=$%02x, offset=$%04x]", x, d->bd_type, d->bd_offset); - - switch (d->bd_type) { - case EZ_BLOB_INT8: - printf(" .%d = %d\n", d->bd_id, *(uint8_t *)u); - break; - case EZ_BLOB_INT16: - printf(" .%d = %d\n", d->bd_id, *(uint16_t *)u); - break; - case EZ_BLOB_INT32: - printf(" .%d = %d\n", d->bd_id, *(uint32_t *)u); - break; - case EZ_BLOB_INT64: - printf(" .%d = %ld\n", d->bd_id, *(uint64_t *)u); - break; - case EZ_BLOB_FLOAT32: - printf(" .%d = %f\n", d->bd_id, *(float *)u); - break; - case EZ_BLOB_FLOAT64: - printf(" .%d = %f\n", d->bd_id, *(double *)u); - break; - case EZ_BLOB_STRING: - printf(" .%d %p = `%s'\n", d->bd_id, *((char **)u), *((char **)u)); - break; - case EZ_BLOB_ARRAY: { - const struct ez_blob_array *ua = u; - - printf(" .%d %p [%d] = {\n", d->bd_id, ua->data, ua->size); - dumphex(ua->data, ua->size, x); - printf("%s }\n", x); - break; } - case EZ_BLOB_POINTER: { - void *up = *((void **)u); - if (up) { - printf(" .%d %p = {\n", d->bd_id, up); - blob_print(d->bd_table, up, depth+4); - printf("%s }\n", x); - } else { - printf(" .%d %p\n", d->bd_id, up); - } - break; - } - default: - printf("\n"); - } - } - - return e; +static void blob_print(const ez_blob_desc *d, const void *a, int depth) { + ez_blob_print(d, a, depth); } static int blob_equals(const ez_blob_desc *d, const void *a, const void *b) { @@ -173,13 +143,27 @@ static int blob_equals(const ez_blob_desc *d, const void *a, const void *b) { case EZ_BLOB_STRING: e &= strcmp((*(char **)u), (*(char **)v)) == 0; break; - case EZ_BLOB_ARRAY: { - const struct ez_blob_array *ua = u; - const struct ez_blob_array *va = v; + case EZ_BLOB_BLOB: { + const struct ez_blob *ua = u; + const struct ez_blob *va = v; e &= ua->size == va->size && memcmp(ua->data, va->data, ua->size) == 0; break; } + case EZ_BLOB_LIST: { + ez_list *ul = (void *)u; + ez_list *vl = (void *)v; + + e &= ez_list_size(ul) == ez_list_size(vl); + for (ez_node *uw = ez_list_head(ul), *un = ez_node_succ(uw), + *vw = ez_list_head(vl), *vn = ez_node_succ(uw); + un && vn; + uw = un, un = ez_node_succ(un), + vw = vn, vn = ez_node_succ(vn)) { + e &= blob_equals(d->bd_table, uw, vw); + } + + break; } } } @@ -187,38 +171,36 @@ static int blob_equals(const ez_blob_desc *d, const void *a, const void *b) { } static void test_basics(const ez_blob_desc *d, void *src) { - void *blob, *blob2; + ez_blob blob, blob2; void *t; - size_t size, size2; size_t dsize = d->bd_offset; char tmp[dsize + 64] __attribute__ ((aligned(64))); - + printf("source\n"); blob_print(d, src, 4); - blob = ez_blob_encode(d, src, &size); + ez_blob_encode(d, src, &blob); + dumphex(blob.data, blob.size, "serial: "); // check decode equals - t = ez_blob_decode(d, blob, size); + t = ez_blob_decode(d, &blob); assert(t != NULL); assert(blob_equals(d, t, src)); - dumphex(blob, size, "serial: "); - printf("decoded\n"); blob_print(d, t, 4); // check encode-decoded equals source - blob2 = ez_blob_encode(d, t, &size2); - assert(size == size2); - assert(memcmp(blob, blob2, size) == 0); - free(blob2); + ez_blob_encode(d, t, &blob2); + assert(blob.size == blob2.size); + assert(memcmp(blob.data, blob2.data, blob2.size) == 0); + free(blob2.data); ez_blob_free(d, t); // check raw decode stays within bounds of struct memset(tmp, 0xbe, sizeof(tmp)); - t = ez_blob_decode_raw(d, blob, size, &tmp[32]); + t = ez_blob_decode_raw(d, &blob, &tmp[32]); //assert(t != NULL); //assert(blob_equals(d, tmp+32, src)); dumphex(tmp, sizeof(tmp), "object: "); @@ -228,7 +210,7 @@ static void test_basics(const ez_blob_desc *d, void *src) { assert((tmp[i + 32 + dsize] & 0xff) == 0xbe); } ez_blob_free_raw(d, tmp+32); - free(blob); + free(blob.data); } static void test_simple(void) { @@ -253,7 +235,7 @@ static void test_arrays(void) { test_basics(d, &src); } -static void test_tree(void) { +static void test_rawtree(void) { struct tree src[6] = { { &src[1], &src[3], "root" }, { NULL, &src[2], "left" }, @@ -267,8 +249,30 @@ static void test_tree(void) { test_basics(d, &src); } +static void test_list(void) { + struct list list = { + .name = "a list", + .list = EZ_INIT_LIST(list.list) + }; + struct listnode nodes[3] = { + { .name = "node 0", .value.size = 5, .value.data = "data0" }, + { .name = "node 1", .value.size = 5, .value.data = "data1" }, + { .name = "node 2", .value.size = 5, .value.data = "data2" }, + }; + + list.name = "a list"; + // ez_list_init(&list. + for (int i=0;i<3;i++) + ez_list_addtail(&list.list, &nodes[i]); + + const ez_blob_desc *d = list_DESC; + + test_basics(d, &list); +} + int main(int argc, char **argv) { test_simple(); test_arrays(); - test_tree(); + test_rawtree(); + test_list(); }