]> mj.ucw.cz Git - libucw.git/commitdiff
interface simplified and a few bugs removed
authorRobert Spalek <robert@ucw.cz>
Tue, 18 Apr 2006 09:57:57 +0000 (11:57 +0200)
committerRobert Spalek <robert@ucw.cz>
Tue, 18 Apr 2006 09:57:57 +0000 (11:57 +0200)
- array macros renamed and extended
- CF_FUNCTION renamed to CF_PARSER, and a number of parameters and a
  pointer to the target variable are passed into the parser function
- init-, commit-, and parser-hooks only get parameters that they need and
  they get it in a nice way so that they don't have to work much
- fixed CHECK_VAR_TYPE and a few other thingies

lib/conf2-test.c
lib/conf2.h

index 540ffed3dcfbe2de5baaf0394bed11075ecf61f0..8c91a6c790491ad99916587749fd9ef57663e565 100644 (file)
@@ -18,7 +18,7 @@ struct sub_sect_1 {
 };
 
 static byte *
-init_sec_1(void *ptr, struct cf_section *sec UNUSED)
+init_sec_1(void *ptr)
 {
   struct sub_sect_1 *s = ptr;
   s->name = "unknown";
@@ -28,7 +28,7 @@ init_sec_1(void *ptr, struct cf_section *sec UNUSED)
 }
 
 static byte *
-commit_sec_1(void *ptr, struct cf_section *sec UNUSED)
+commit_sec_1(void *ptr)
 {
   struct sub_sect_1 *s = ptr;
   if (s->confidence < 0 || s->confidence > 10)
@@ -51,33 +51,28 @@ static struct cf_section cf_sec_1 = {
 };
 
 static int nr1 = 15;
-static int *nrs1 = DEFAULT_ARRAY(int, 5, 5, 4, 3, 2, 1);
+static int *nrs1 = ARRAY_ALLOC(int, 5, 5, 4, 3, 2, 1);
 static int *nrs2;
 static byte *str1 = "no worries";
-static byte **str2 = DEFAULT_ARRAY(byte *, 2, "Alice", "Bob");
+static byte **str2 = ARRAY_ALLOC(byte *, 2, "Alice", "Bob");
 static u64 u1 = 0xCafeBeefDeadC00ll;
 static double d1 = -1.1;
-static struct sub_sect_1 sec_1 = { "Charlie", "WBAFC", 0 };
-static struct cnode secs;
+static struct sub_sect_1 sec1 = { "Charlie", "WBAFC", 0 };
+static struct clist secs;
 static time_t t1, t2;
 
 static byte *
-commit_top(void *ptr UNUSED, struct cf_section *sec UNUSED)
+commit_top(void *ptr UNUSED)
 {
+  if (nr1 != 15)
+    return "Don't touch my variable!";
   return NULL;
 }
 
 static byte *
-time_parser(uns nr_pars, byte **pars, void *sec_ptr, struct cf_section *sec, uns index)
+time_parser(byte *name UNUSED, uns number, byte **pars, void *ptr)
 {
-  if (nr_pars != 0 && nr_pars != 1)
-    return "Either now or 1 parameter!";
-  ASSERT(!sec_ptr);
-  time_t t = nr_pars ? atoi(pars[0]) : time(NULL);
-  if (sec->cfg[index].name[0] == 'F')
-    t1 = t;
-  else
-    t2 = t;
+  * (time_t*) ptr = number ? atoi(pars[0]) : time(NULL);
   return NULL;
 }
 
@@ -91,9 +86,9 @@ static struct cf_section cf_top = {
     CF_STRING_AR("str2", &str2, 2),
     CF_U64("u1", &u1),
     CF_DOUBLE("d1", &d1),
-    CF_FUNCTION("FirstTime", time_parser),
-    CF_FUNCTION("SecondTime", time_parser),
-    CF_SUB_SECTION("master", &sec_1, &cf_sec_1),
+    CF_PARSER("FirstTime", &t1, time_parser, -1),
+    CF_PARSER("SecondTime", &t2, time_parser, 1),
+    CF_SUB_SECTION("master", &sec1, &cf_sec_1),
     CF_LINK_LIST("slaves", &secs, &cf_sec_1),
     CF_END
   }
index dfb024d31c7dd35bfc2ba18dde74c454ebd81a58..9f5de68d7355624d1c4208fdada273164bbb3e64 100644 (file)
@@ -14,29 +14,30 @@ enum cf_type {
   CT_END,                              // end of list
   CT_INT, CT_U64, CT_DOUBLE,           // number types
   CT_STRING,                           // string type
-  CT_FUNCTION,                         // arbitrary parser function
+  CT_PARSER,                           // arbitrary parser function
   CT_SUB_SECTION,                      // sub-section appears exactly once
   CT_LINK_LIST                         // link-list with 0..many nodes
 };
 
 struct cf_section;
-typedef byte *cf_hook(void *sec_ptr, struct cf_section *sec);
+typedef byte *cf_hook(void *ptr);
   /* An init- or commit-hook gets a pointer to the sub-section or NULL if this
-   * is the global section, and a declaration of the section it is called on.
-   * It returns an error message or NULL if everything is all right.  */
-typedef byte *cf_parser(uns nr_pars, byte **pars, void *sec_ptr, struct cf_section *sec, uns index);
-  /* A parser function gets an array of strings and stores it in any way it
-   * likes into its own data structures.  It gets a pointer to the sub-section
-   * or NULL if this is the global section, a declaration of the section it is
-   * called in, and the index of the item it is called on.  It returns an error
-   * message or NULL if everything is all right.  */
+   * is the global section.  It returns an error message or NULL if everything
+   * is all right.  */
+typedef byte *cf_parser(byte *name, uns number, byte **pars, void *ptr);
+  /* A parser function gets a name of the attribute and an array of strings,
+   * and stores the parsed value in any way it likes into *ptr.  It returns an
+   * error message or NULL if everything is all right.  */
 
 struct cf_item {
   enum cf_type type;
   byte *name;
-  int number;                          // number of values: k>0 means exactly k, k<0 means at most k
+  int number;                          // number of values: k>=0 means exactly k, k<0 means at most -k
   void *ptr;                           // pointer to a global variable or an offset in a sub-section
-  struct cf_section *sub;              // declaration of a sub-section or link-list
+  union {
+    struct cf_section *sub;            // declaration of a sub-section or a link-list
+    cf_parser *par;                    // parser function
+  } ptr2;
 };
 
 struct cf_section {
@@ -46,10 +47,12 @@ struct cf_section {
   struct cf_item *cfg;                 // CT_END-terminated array of items
 };
 
-#define CHECK_VAR_TYPE(x,type) ((x)-(type)0 + (type)0)
+#define CHECK_VAR_TYPE(x,type) ((x)-(type)(x) + (type)(x))
   // for a pointer x it returns x, and performs a compile-time check whether typeof(x)==type
-#define DEFAULT_ARRAY(type,len,val...) (type[]) { (type)len, ##val } + 1
+#define ARRAY_ALLOC(type,len,val...) (type[]) { (type)len, ##val } + 1
   // creates an array with an allocated space in the front for the (Pascal-like) length
+#define ARRAY_LEN(a) *(uns*)(a-1)
+  // length of the array
 #define CF_FIELD(str,f)        &((str*)0)->f
   // returns a pointer to a field inside a structure suitable for passing as cf_item->ptr
 
@@ -59,14 +62,15 @@ struct cf_section {
 #define CF_U64(n,p)    { .type = CT_U64, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,u64*) }
 #define CF_DOUBLE(n,p) { .type = CT_DOUBLE, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,double*) }
 #define CF_STRING(n,p) { .type = CT_STRING, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,byte**) }
-#define CF_FUNCTION(n,p)       { .type = CT_FUNCTION, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,cf_parser*) }
-#define CF_SUB_SECTION(n,p,s)  { .type = CT_SUB_SECTION, .name = n, .number = 1, .ptr = p, .sub = s }
-#define CF_LINK_LIST(n,p,s)    { .type = CT_LINK_LIST, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,struct cnode*), .sub = s }
   // use the macros above to declare configuration items for single variables
 #define CF_INT_AR(n,p,c)       { .type = CT_INT, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,int**) }
 #define CF_U64_AR(n,p,c)       { .type = CT_U64, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,u64**) }
 #define CF_DOUBLE_AR(n,p,c)    { .type = CT_DOUBLE, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,double**) }
 #define CF_STRING_AR(n,p,c)    { .type = CT_STRING, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,byte***) }
   // use the macros above to declare configuration items for arrays of variables
+struct clist;
+#define CF_PARSER(n,p,f,c)     { .type = CT_PARSER, .name = n, .number = c, .ptr = p, .ptr2.par = f }
+#define CF_SUB_SECTION(n,p,s)  { .type = CT_SUB_SECTION, .name = n, .number = 1, .ptr = p, .ptr2.sub = s }
+#define CF_LINK_LIST(n,p,s)    { .type = CT_LINK_LIST, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,struct clist*), .ptr2.sub = s }
 
 #endif