From b2e520371195bba5827fa19c824a5e2636a9e211 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 28 Jan 2014 21:18:48 +0100 Subject: [PATCH] Conf: Dynamic arrays re-implemented as gary's To the outside world, almost nothing changes as DARY_LEN is emulated. However, static initializers are no longer possible, so DARY_ALLOC is gone. The current implementation is not elegant. It will be improved soon. --- ucw/conf-dump.c | 2 +- ucw/conf-intr.c | 20 +++++++++----------- ucw/conf-section.c | 9 ++++----- ucw/conf-test.c | 23 ++++++++++++++++++----- ucw/conf.h | 7 +++---- ucw/doc/conf.txt | 5 ++--- ucw/gary.c | 2 ++ ucw/gary.h | 5 +++++ 8 files changed, 44 insertions(+), 29 deletions(-) diff --git a/ucw/conf-dump.c b/ucw/conf-dump.c index 9d7e31c9..b3c73700 100644 --- a/ucw/conf-dump.c +++ b/ucw/conf-dump.c @@ -74,7 +74,7 @@ dump_item(struct fastbuf *fb, struct cf_item *item, int level, void *ptr) } else if (item->cls == CC_DYNAMIC) { ptr = * (void**) ptr; if (ptr) { - int real_nr = DARY_LEN(ptr); + int real_nr = GARY_SIZE(ptr); bprintf(fb, "N%d ", real_nr); for (i=0; iu); diff --git a/ucw/conf-intr.c b/ucw/conf-intr.c index a5d32325..79a9e8da 100644 --- a/ucw/conf-intr.c +++ b/ucw/conf-intr.c @@ -2,7 +2,7 @@ * UCW Library -- Configuration files: interpreter * * (c) 2001--2006 Robert Spalek - * (c) 2003--2012 Martin Mares + * (c) 2003--2014 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -102,17 +103,15 @@ char *cf_op_names[] = { CF_OPERATIONS }; #undef T char *cf_type_names[] = { "int", "u64", "double", "ip", "string", "lookup", "user" }; -#define DARY_HDR_SIZE ALIGN_TO(sizeof(uns), CPU_STRUCT_ALIGN) - static char * interpret_set_dynamic(struct cf_item *item, int number, char **pars, void **ptr) { enum cf_type type = item->type; + uns size = cf_type_size(type, item->u.utype); cf_journal_block(ptr, sizeof(void*)); // boundary checks done by the caller - uns size = cf_type_size(item->type, item->u.utype); - *ptr = cf_malloc(DARY_HDR_SIZE + number * size) + DARY_HDR_SIZE; - DARY_LEN(*ptr) = number; + struct gary_allocator *a = gary_new_allocator_mp(cf_get_pool()); // FIXME: One copy should be enough + *ptr = gary_init(size, number, a); return cf_parse_ary(number, pars, *ptr, type, &item->u); } @@ -123,12 +122,12 @@ interpret_add_dynamic(struct cf_item *item, int number, char **pars, int *proces void *old_p = *ptr; uns size = cf_type_size(item->type, item->u.utype); ASSERT(size >= sizeof(uns)); - int old_nr = old_p ? DARY_LEN(old_p) : 0; + int old_nr = old_p ? GARY_SIZE(old_p) : 0; int taken = MIN(number, ABS(item->number)-old_nr); *processed = taken; // stretch the dynamic array - void *new_p = cf_malloc(DARY_HDR_SIZE + (old_nr + taken) * size) + DARY_HDR_SIZE; - DARY_LEN(new_p) = old_nr + taken; + struct gary_allocator *a = gary_new_allocator_mp(cf_get_pool()); // FIXME: One copy should be enough + void *new_p = gary_init(size, old_nr + taken, a); cf_journal_block(ptr, sizeof(void*)); *ptr = new_p; if (op == OP_APPEND) { @@ -321,8 +320,7 @@ interpret_set_all(struct cf_item *item, void *ptr, enum cf_operation op) clist_init(ptr); } else if (item->cls == CC_DYNAMIC) { cf_journal_block(ptr, sizeof(void *)); - static uns zero = 0; - * (void**) ptr = (&zero) + 1; + * (void**) ptr = GARY_FOREVER_EMPTY; } else if (item->cls == CC_STATIC && item->type == CT_STRING) { cf_journal_block(ptr, item->number * sizeof(char*)); bzero(ptr, item->number * sizeof(char*)); diff --git a/ucw/conf-section.c b/ucw/conf-section.c index f25657d2..1289f928 100644 --- a/ucw/conf-section.c +++ b/ucw/conf-section.c @@ -2,7 +2,7 @@ * UCW Library -- Configuration files: sections * * (c) 2001--2006 Robert Spalek - * (c) 2003--2012 Martin Mares + * (c) 2003--2014 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -140,10 +141,8 @@ cf_init_section(const char *name, struct cf_section *sec, void *ptr, uns do_bzer clist_init(ptr + (uintptr_t) ci->ptr); else if (ci->cls == CC_DYNAMIC) { void **dyn = ptr + (uintptr_t) ci->ptr; - if (!*dyn) { // replace NULL by an empty array - static uns zero = 0; - *dyn = (&zero) + 1; - } + if (!*dyn) // replace NULL by an empty array + *dyn = GARY_FOREVER_EMPTY; } if (sec->init) { char *msg = sec->init(ptr); diff --git a/ucw/conf-test.c b/ucw/conf-test.c index e8ba0458..b484e10e 100644 --- a/ucw/conf-test.c +++ b/ucw/conf-test.c @@ -2,7 +2,7 @@ * Insane tester of reading configuration files * * (c) 2006 Robert Spalek - * (c) 2012 Martin Mares + * (c) 2012--2014 Martin Mares */ #include @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -27,7 +28,7 @@ struct sub_sect_1 { double *list; }; -static struct sub_sect_1 sec1 = { {}, "Charlie", 0, "WBAFC", { 0, -1}, DARY_ALLOC(double, 3, 1e4, -1e-4, 8) }; +static struct sub_sect_1 sec1 = { {}, "Charlie", 0, "WBAFC", { 0, -1}, NULL }; static char * init_sec_1(struct sub_sect_1 *s) @@ -74,16 +75,16 @@ static struct cf_section cf_sec_1 = { }; static uns nr1 = 15; -static int *nrs1 = DARY_ALLOC(int, 5, 5, 4, 3, 2, 1); +static int *nrs1; static int nrs2[5]; static char *str1 = "no worries"; -static char **str2 = DARY_ALLOC(char *, 2, "Alice", "Bob"); +static char **str2; static u64 u1 = 0xCafeBeefDeadC00ll; static double d1 = -1.1; static clist secs; static time_t t1, t2; static u32 ip; -static int *look = DARY_ALLOC(int, 2, 2, 1); +static int *look; static u16 numbers[10] = { 2, 100, 1, 5 }; static u32 bitmap1 = 0xff; static u32 bitmap2 = 3; @@ -213,6 +214,18 @@ main(int argc, char *argv[]) cf_declare_section("top", &cf_top, 0); cf_def_file = "ucw/conf-test.cf"; + // Create and initialize dynamic arrays + GARY_INIT(nrs1, 6); + memcpy(nrs1, (int []) { 5, 5, 4, 3, 2, 1 }, 6 * sizeof(int)); + GARY_INIT(str2, 2); + str2[0] = "Alice"; + str2[1] = "Bob"; + GARY_INIT(look, 2); + look[0] = 2; + look[1] = 1; + GARY_INIT(sec1.list, 3); + memcpy(sec1.list, (double []) { 1e4, -1e-4, 8 }, 3 * sizeof(double)); + int opt; while ((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0) switch (opt) { diff --git a/ucw/conf.h b/ucw/conf.h index 2e8a5ca8..29808510 100644 --- a/ucw/conf.h +++ b/ucw/conf.h @@ -2,7 +2,7 @@ * UCW Library -- Configuration files * * (c) 2001--2006 Robert Spalek - * (c) 2003--2012 Martin Mares + * (c) 2003--2014 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -12,6 +12,7 @@ #define _UCW_CONF_H #include +#include #ifdef CONFIG_UCW_CLEAN_ABI #define cf_close_group ucw_cf_close_group @@ -423,9 +424,7 @@ struct cf_section { /** A section. **/ **/ #define CF_ANY_NUM -0x7fffffff -#define DARY_LEN(a) ((uns*)a)[-1] /** Length of an dynamic array. **/ -#define DARY_ALLOC(type,len,val...) ((struct { byte pad[ALIGN_TO(sizeof(uns), CPU_STRUCT_ALIGN) - sizeof(uns)]; uns l; type a[len]; }) { .l = len, .a = { val } }).a - // creates a static instance of a dynamic array +#define DARY_LEN(a) GARY_SIZE(a) /** Length of an dynamic array. An alias for `GARY_SIZE`. **/ /*** * [[alloc]] diff --git a/ucw/doc/conf.txt b/ucw/doc/conf.txt index 43f838ec..fbfa6429 100644 --- a/ucw/doc/conf.txt +++ b/ucw/doc/conf.txt @@ -153,9 +153,8 @@ For example, you can have an static array of five unsigned integers: *Dynamic arrays*:: Similar to static array, but you provide pointer to pointer to the given item (eg. if you want dynamic array of - integers, you give `**int`). The parser allocates an array of needed - size. You can use the <> macro to find out - the number of elements actually loaded. + integers, you give `**int`). The parser allocates a growing array + (see `gary.h`) of the required size. + If you want dynamic array of strings, you would use: + diff --git a/ucw/gary.c b/ucw/gary.c index 5f62f993..a4a45706 100644 --- a/ucw/gary.c +++ b/ucw/gary.c @@ -11,6 +11,8 @@ #include +struct gary_hdr gary_empty_hdr; + void * gary_init(size_t elt_size, size_t num_elts, struct gary_allocator *allocator) { diff --git a/ucw/gary.h b/ucw/gary.h index e2e29520..aa82855c 100644 --- a/ucw/gary.h +++ b/ucw/gary.h @@ -77,6 +77,11 @@ static inline void gary_free(void *ptr) } } +/* A forever empty gary. Used internally. */ + +extern struct gary_hdr gary_empty_hdr; +#define GARY_FOREVER_EMPTY GARY_BODY(&gary_empty_hdr) + /* Type-agnostic interface. Currently it's recommended for internal use only. */ #define GARY_PUSH_GENERIC(ptr) ({ \ -- 2.39.2