]> mj.ucw.cz Git - libucw.git/commitdiff
implemented a few functions of the new configuration mechanism:
authorRobert Spalek <robert@ucw.cz>
Wed, 19 Apr 2006 10:02:37 +0000 (12:02 +0200)
committerRobert Spalek <robert@ucw.cz>
Wed, 19 Apr 2006 10:02:37 +0000 (12:02 +0200)
- memory allocation
- skeleton of future journal functions
- parsers of all basic types and arrays of these types

lib/Makefile
lib/conf2.c [new file with mode: 0644]

index 757d2149f6de0eba440260589caedbf5050eaaef..39885a9ff4b8c30052eba804477ab434eb827e20 100644 (file)
@@ -6,15 +6,12 @@ ifdef CONFIG_UCW_DBTOOL
 PROGS+=$(o)/lib/db-tool
 endif
 
-# hey dude, I'm Robert!
-PROGS+=$(o)/lib/conf2-test
-
 LIBUCW_MODS= \
        alloc alloc_str realloc mempool mempool-str mempool-fmt \
        mmap pagecache partmap hashfunc \
        lists slists sorter bitsig kmp \
        log log-file proctitle \
-       conf ipaccess \
+       conf conf2 ipaccess \
        profile \
        fastbuf ff-printf ff-utf8 \
        fb-file carefulio fb-mem fb-temp fb-mmap fb-limfd fb-buffer fb-grow \
diff --git a/lib/conf2.c b/lib/conf2.c
new file mode 100644 (file)
index 0000000..90483d4
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ *     UCW Library -- Reading of configuration files
+ *
+ *     (c) 2001--2006 Robert Spalek <robert@ucw.cz>
+ *     (c) 2003--2006 Martin Mares <mj@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#include "lib/lib.h"
+#include "lib/conf2.h"
+#include "lib/mempool.h"
+
+#include <stdlib.h>
+#include <errno.h>
+
+/* Memory allocation */
+
+static struct mempool *cf_pool;
+
+void *
+cf_malloc(uns size)
+{
+  return mp_alloc(cf_pool, size);
+}
+
+void *
+cf_malloc_zero(uns size)
+{
+  return mp_alloc_zero(cf_pool, size);
+}
+
+byte *
+cf_strdup(byte *s)
+{
+  return mp_strdup(cf_pool, s);
+}
+
+byte *
+cf_printf(char *fmt, ...)
+{
+  va_list args;
+  va_start(args, fmt);
+  byte *res = mp_vprintf(cf_pool, fmt, args);
+  va_end(args);
+  return res;
+}
+
+/* Undo journal */
+
+static uns journal_active;
+
+uns
+cf_journal_active(uns flag)
+{
+  uns f = journal_active;
+  journal_active = flag;
+  return f;
+}
+
+void
+cf_journal_block(void *ptr UNUSED, uns len UNUSED)
+{
+}
+
+/* Parsers for standard types */
+
+struct unit {
+  uns name;                    // one-letter name of the unit
+  uns num, den;                        // fraction
+};
+
+static const struct unit units[] = {
+  { 'd', 86400, 1 },
+  { 'h', 3600, 1 },
+  { 'k', 1000, 1 },
+  { 'm', 1000000, 1 },
+  { 'g', 1000000000, 1 },
+  { 'K', 1024, 1 },
+  { 'M', 1048576, 1 },
+  { 'G', 1073741824, 1 },
+  { '%', 1, 100 },
+  { 0, 0, 0 }
+};
+
+static const struct unit *
+lookup_unit(byte *value, byte *end, byte **msg)
+{
+  if (end && *end) {
+    if (end == value || end[1] || *end >= '0' && *end <= '9')
+      *msg = "Invalid number";
+    else {
+      for (const struct unit *u=units; u->name; u++)
+       if (u->name == *end)
+         return u;
+      *msg = "Invalid unit";
+    }
+  }
+  return NULL;
+}
+
+static char cf_rngerr[] = "Number out of range";
+
+static byte *
+cf_parse_int(uns number, byte **pars, int *ptr)
+{
+  cf_journal_block(ptr, number * sizeof(int));
+  for (uns i=0; i<number; i++)
+  {
+    byte *msg = NULL;
+    if (!*pars[i])
+      msg = "Missing number";
+    else {
+      const struct unit *u;
+      char *end;
+      errno = 0;
+      uns x = strtoul(pars[i], &end, 0);
+      if (errno == ERANGE)
+       msg = cf_rngerr;
+      else if (u = lookup_unit(pars[i], end, &msg)) {
+       u64 y = (u64)x * u->num;
+       if (y % u->den)
+         msg = "Number is not an integer";
+       else {
+         y /= u->den;
+         if (y > 0xffffffff)
+           msg = cf_rngerr;
+         ptr[i] = y;
+       }
+      } else
+       ptr[i] = x;
+    }
+    if (msg)
+      return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
+  }
+  return NULL;
+}
+
+static byte *
+cf_parse_u64(uns number, byte **pars, u64 *ptr)
+{
+  cf_journal_block(ptr, number * sizeof(u64));
+  for (uns i=0; i<number; i++)
+  {
+    byte *msg = NULL;
+    if (!*pars[i])
+      msg = "Missing number";
+    else {
+      const struct unit *u;
+      char *end;
+      errno = 0;
+      u64 x = strtoull(pars[i], &end, 0);
+      if (errno == ERANGE)
+       msg = cf_rngerr;
+      else if (u = lookup_unit(pars[i], end, &msg)) {
+       if (x > ~(u64)0 / u->num)
+         msg = "Number out of range";
+       else {
+         x *= u->num;
+         if (x % u->den)
+           msg = "Number is not an integer";
+         else
+           ptr[i] = x / u->den;
+       }
+      } else
+       ptr[i] = x;
+    }
+    if (msg)
+      return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
+  }
+  return NULL;
+}
+
+static byte *
+cf_parse_double(uns number, byte **pars, double *ptr)
+{
+  cf_journal_block(ptr, number * sizeof(double));
+  for (uns i=0; i<number; i++)
+  {
+    byte *msg = NULL;
+    if (!*pars[i])
+      msg = "Missing number";
+    else {
+      const struct unit *u;
+      char *end;
+      errno = 0;
+      double x = strtoul(pars[i], &end, 0);
+      if (errno == ERANGE)
+       msg = cf_rngerr;
+      else if (u = lookup_unit(pars[i], end, &msg))
+       ptr[i] = x * u->num / u->den;
+      else
+       ptr[i] = x;
+    }
+    if (msg)
+      return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
+  }
+  return NULL;
+}
+
+static byte *
+cf_parse_string(uns number, byte **pars, byte **ptr)
+{
+  cf_journal_block(ptr, number * sizeof(byte*));
+  for (uns i=0; i<number; i++)
+    ptr[i] = cf_strdup(pars[i]);
+  return NULL;
+}
+
+static byte *
+cf_parse_int_ary(uns number, byte **pars, int **ptr)
+{
+  cf_journal_block(ptr, sizeof(int**));
+  *ptr = (int*) cf_malloc((number+1) * sizeof(int*)) + 1;
+  ARRAY_LEN(*ptr) = number;
+  uns old_flag = cf_journal_active(0);
+  byte *msg = cf_parse_int(number, pars, *ptr);
+  cf_journal_active(old_flag);
+  return msg;
+}
+
+static byte *
+cf_parse_u64_ary(uns number, byte **pars, u64 **ptr)
+{
+  cf_journal_block(ptr, sizeof(u64**));
+  *ptr = (u64*) cf_malloc((number+1) * sizeof(u64*)) + 1;
+  ARRAY_LEN(*ptr) = number;
+  uns old_flag = cf_journal_active(0);
+  byte *msg = cf_parse_u64(number, pars, *ptr);
+  cf_journal_active(old_flag);
+  return msg;
+}
+
+static byte *
+cf_parse_double_ary(uns number, byte **pars, double **ptr)
+{
+  cf_journal_block(ptr, sizeof(double**));
+  *ptr = (double*) cf_malloc((number+1) * sizeof(double*)) + 1;
+  ARRAY_LEN(*ptr) = number;
+  uns old_flag = cf_journal_active(0);
+  byte *msg = cf_parse_double(number, pars, *ptr);
+  cf_journal_active(old_flag);
+  return msg;
+}
+
+static byte *
+cf_parse_string_ary(uns number, byte **pars, byte ***ptr)
+{
+  cf_journal_block(ptr, sizeof(byte***));
+  *ptr = (byte**) cf_malloc((number+1) * sizeof(byte**)) + 1;
+  ARRAY_LEN(*ptr) = number;
+  uns old_flag = cf_journal_active(0);
+  byte *msg = cf_parse_string(number, pars, *ptr);
+  cf_journal_active(old_flag);
+  return msg;
+}