]> mj.ucw.cz Git - libucw.git/commitdiff
Conf: Dynamic arrays re-implemented as gary's
authorMartin Mares <mj@ucw.cz>
Tue, 28 Jan 2014 20:18:48 +0000 (21:18 +0100)
committerMartin Mares <mj@ucw.cz>
Tue, 28 Jan 2014 20:18:48 +0000 (21:18 +0100)
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
ucw/conf-intr.c
ucw/conf-section.c
ucw/conf-test.c
ucw/conf.h
ucw/doc/conf.txt
ucw/gary.c
ucw/gary.h

index 9d7e31c926b9e7bcdbd735f822adc6e377add00f..b3c737005eb82b26cc069c2e215ccc58869f5c26 100644 (file)
@@ -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; i<real_nr; i++)
        dump_basic(fb, ptr + i * size, type, &item->u);
index a5d323253a42a3eedc06e71f0f7b77622fdde358..79a9e8da48dd7d45ab4582151b7c018e2ecd536e 100644 (file)
@@ -2,7 +2,7 @@
  *     UCW Library -- Configuration files: interpreter
  *
  *     (c) 2001--2006 Robert Spalek <robert@ucw.cz>
- *     (c) 2003--2012 Martin Mares <mj@ucw.cz>
+ *     (c) 2003--2014 Martin Mares <mj@ucw.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
@@ -13,6 +13,7 @@
 #include <ucw/getopt.h>
 #include <ucw/conf-internal.h>
 #include <ucw/clists.h>
+#include <ucw/gary.h>
 
 #include <string.h>
 #include <stdio.h>
@@ -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*));
index f25657d287c7448f1d5744f269c22fd27e0d9f55..1289f928923213cdb45de6f1d4017d710709f0b6 100644 (file)
@@ -2,7 +2,7 @@
  *     UCW Library -- Configuration files: sections
  *
  *     (c) 2001--2006 Robert Spalek <robert@ucw.cz>
- *     (c) 2003--2012 Martin Mares <mj@ucw.cz>
+ *     (c) 2003--2014 Martin Mares <mj@ucw.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
@@ -13,6 +13,7 @@
 #include <ucw/conf-internal.h>
 #include <ucw/clists.h>
 #include <ucw/binsearch.h>
+#include <ucw/gary.h>
 
 #include <string.h>
 
@@ -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);
index e8ba0458c568e90045ff948b56ee709b81d89e77..b484e10e3b378664c61f281cccf2a0a79d11211f 100644 (file)
@@ -2,7 +2,7 @@
  *     Insane tester of reading configuration files
  *
  *     (c) 2006 Robert Spalek <robert@ucw.cz>
- *     (c) 2012 Martin Mares <mj@ucw.cz>
+ *     (c) 2012--2014 Martin Mares <mj@ucw.cz>
  */
 
 #include <ucw/lib.h>
@@ -10,6 +10,7 @@
 #include <ucw/getopt.h>
 #include <ucw/clists.h>
 #include <ucw/fastbuf.h>
+#include <ucw/gary.h>
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -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) {
index 2e8a5ca8889e77066556234f584feaf5d2bb8afe..29808510918749703505905dfcc61790cc37df76 100644 (file)
@@ -2,7 +2,7 @@
  *     UCW Library -- Configuration files
  *
  *     (c) 2001--2006 Robert Spalek <robert@ucw.cz>
- *     (c) 2003--2012 Martin Mares <mj@ucw.cz>
+ *     (c) 2003--2014 Martin Mares <mj@ucw.cz>
  *
  *     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 <ucw/clists.h>
+#include <ucw/gary.h>
 
 #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]]
index 43f838ec22a92aaadac5fde721e8edbc6b590bad..fbfa642970cc7febf61a70459216e5c79f73773d 100644 (file)
@@ -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 <<def_DARY_LEN,`DARY_LEN`>> 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:
 +
index 5f62f9932051c8c5365ef73675d5adab4ec74482..a4a457066b2a82faea6091158d6fc1b1369fbb24 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <string.h>
 
+struct gary_hdr gary_empty_hdr;
+
 void *
 gary_init(size_t elt_size, size_t num_elts, struct gary_allocator *allocator)
 {
index e2e295201e85038409e17bcecf1854befef1eb7c..aa82855c712de1fd3f953f3ef01c383584e9577a 100644 (file)
@@ -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) ({                                      \