]> mj.ucw.cz Git - libucw.git/commitdiff
significant simplifications of the interface
authorRobert Spalek <robert@ucw.cz>
Tue, 18 Apr 2006 12:37:31 +0000 (14:37 +0200)
committerRobert Spalek <robert@ucw.cz>
Tue, 18 Apr 2006 12:37:31 +0000 (14:37 +0200)
- instead of letting the user to set cf_section.{size,init,commit}
  directly, macros CF_{TYPE,INIT,COMMIT} should be used
- another macro CF_ITEMS creates a CT_END-delimited list of cf_items
- all these macros automatically add commas so that declaring a list of
  cf_items behaves similarly to other preprocessor-made lists
- removed parameter name from parser hooks, because either the parser
  doesn't care and only uses *ptr, or it does and then it should be set up
  to pass the name in ptr
- no need to define hooks using _void_ *ptr; one can use any pointers
  according to his taste and the hook-function is automatically retyped
- renamed (to make it shorter) some enumerations and macros
- CHECK_VAR_TYPE and CF_FIELD renamed to CHECK_PTR_TYPE and PTR_TO, and
  moved to lib/lib.h

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

index 8c91a6c790491ad99916587749fd9ef57663e565..8794bf7b14c439d1a3bff9222a15385cc066bc08 100644 (file)
@@ -18,9 +18,8 @@ struct sub_sect_1 {
 };
 
 static byte *
-init_sec_1(void *ptr)
+init_sec_1(struct sub_sect_1 *s)
 {
-  struct sub_sect_1 *s = ptr;
   s->name = "unknown";
   s->level = "default";
   s->confidence = 5;
@@ -28,26 +27,24 @@ init_sec_1(void *ptr)
 }
 
 static byte *
-commit_sec_1(void *ptr)
+commit_sec_1(struct sub_sect_1 *s)
 {
-  struct sub_sect_1 *s = ptr;
   if (s->confidence < 0 || s->confidence > 10)
     return "Well, this can't be";
   return NULL;
 }
 
 static struct cf_section cf_sec_1 = {
-  .size = sizeof(struct sub_sect_1),
-  .init = init_sec_1,
-  .commit = commit_sec_1,
-  .cfg = (struct cf_item[]) {
-#define F(x)   CF_FIELD(struct sub_sect_1, x)
-    CF_STRING("name", F(name)),
-    CF_STRING("level", F(level)),
-    CF_INT("confidence", F(confidence)),
-    CF_END
+  CF_TYPE(struct sub_sect_1)
+  CF_INIT(init_sec_1)
+  CF_COMMIT(commit_sec_1)
+#define F(x)   PTR_TO(struct sub_sect_1, x)
+  CF_ITEMS(
+    CF_STRING("name", F(name))
+    CF_STRING("level", F(level))
+    CF_INT("confidence", F(confidence))
+  )
 #undef F
-  }
 };
 
 static int nr1 = 15;
@@ -70,28 +67,27 @@ commit_top(void *ptr UNUSED)
 }
 
 static byte *
-time_parser(byte *name UNUSED, uns number, byte **pars, void *ptr)
+time_parser(uns number, byte **pars, time_t *ptr)
 {
-  * (time_t*) ptr = number ? atoi(pars[0]) : time(NULL);
+  *ptr = number ? atoi(pars[0]) : time(NULL);
   return NULL;
 }
 
 static struct cf_section cf_top = {
-  .commit = commit_top,
-  .cfg = (struct cf_item []) {
-    CF_INT("nr1", &nr1),
-    CF_INT_AR("nrs1", &nrs1, 5),
-    CF_INT_AR("nrs2", &nrs2, -1000),
-    CF_STRING("str1", &str1),
-    CF_STRING_AR("str2", &str2, 2),
-    CF_U64("u1", &u1),
-    CF_DOUBLE("d1", &d1),
-    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
-  }
+  CF_COMMIT(commit_top)
+  CF_ITEMS(
+    CF_INT("nr1", &nr1)
+    CF_INT_ARY("nrs1", &nrs1, 5)
+    CF_INT_ARY("nrs2", &nrs2, -1000)
+    CF_STRING("str1", &str1)
+    CF_STRING_ARY("str2", &str2, 2)
+    CF_U64("u1", &u1)
+    CF_DOUBLE("d1", &d1)
+    CF_PARSER("FirstTime", &t1, time_parser, -1)
+    CF_PARSER("SecondTime", &t2, time_parser, 1)
+    CF_SECTION("master", &sec1, &cf_sec_1)
+    CF_LIST("slaves", &secs, &cf_sec_1)
+  )
 };
 
 int
index 9f5de68d7355624d1c4208fdada273164bbb3e64..20daf32a7f839148c9930e8c1deace2d82956dd9 100644 (file)
@@ -7,70 +7,70 @@
  *     of the GNU Lesser General Public License.
  */
 
-#ifndef        _LIB_CONF2_H
-#define        _LIB_CONF2_H
+#ifndef        _UCW_CONF2_H
+#define        _UCW_CONF2_H
 
 enum cf_type {
   CT_END,                              // end of list
   CT_INT, CT_U64, CT_DOUBLE,           // number types
   CT_STRING,                           // string type
   CT_PARSER,                           // arbitrary parser function
-  CT_SUB_SECTION,                      // sub-section appears exactly once
-  CT_LINK_LIST                         // link-list with 0..many nodes
+  CT_SECTION,                          // section appears exactly once
+  CT_LIST                              // list with 0..many nodes
 };
 
 struct cf_section;
 typedef byte *cf_hook(void *ptr);
-  /* An init- or commit-hook gets a pointer to the sub-section or NULL if this
+  /* An init- or commit-hook gets a pointer to the section or NULL if this
    * 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.  */
+typedef byte *cf_parser(uns number, byte **pars, void *ptr);
+  /* A parser function 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
-  void *ptr;                           // pointer to a global variable or an offset in a sub-section
+  void *ptr;                           // pointer to a global variable or an offset in a section
   union {
-    struct cf_section *sub;            // declaration of a sub-section or a link-list
+    struct cf_section *sub;            // declaration of a section or a list
     cf_parser *par;                    // parser function
   } ptr2;
 };
 
 struct cf_section {
-  uns size;                            // 0 for a global block, sizeof(struct) for a sub-section
+  uns size;                            // 0 for a global block, sizeof(struct) for a section
   cf_hook *init;                       // fills in default values
   cf_hook *commit;                     // verifies parsed data and checks ranges (optional)
   struct cf_item *cfg;                 // CT_END-terminated array of items
 };
 
-#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 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
 
-#define CF_END         { .type = CT_END }
-  // please better put this at the end of each section
-#define CF_INT(n,p)    { .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,int*) }
-#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**) }
-  // 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
+/* Declaration of cf_items */
+#define CF_TYPE(s)     .size = sizeof(s),
+#define CF_INIT(f)     .init = (cf_hook*) f,
+#define CF_COMMIT(f)   .commit = (cf_hook*) f,
+#define CF_ITEMS(i)    .cfg = ( struct cf_item[] ) { i { .type = CT_END } },
+/* Configuration items for single variables */
+#define CF_INT(n,p)    { .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,int*) },
+#define CF_U64(n,p)    { .type = CT_U64, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u64*) },
+#define CF_DOUBLE(n,p) { .type = CT_DOUBLE, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,double*) },
+#define CF_STRING(n,p) { .type = CT_STRING, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,byte**) },
+/* Configuration items for arrays of variables */
+#define CF_INT_ARY(n,p,c)      { .type = CT_INT, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,int**) },
+#define CF_U64_ARY(n,p,c)      { .type = CT_U64, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,u64**) },
+#define CF_DOUBLE_ARY(n,p,c)   { .type = CT_DOUBLE, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,double**) },
+#define CF_STRING_ARY(n,p,c)   { .type = CT_STRING, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,byte***) },
+/* Configuration items for sections, lists, and parsed items */
 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 }
+#define CF_PARSER(n,p,f,c)     { .type = CT_PARSER, .name = n, .number = c, .ptr = p, .ptr2.par = (cf_parser*) f },
+#define CF_SECTION(n,p,s)      { .type = CT_SECTION, .name = n, .number = 1, .ptr = p, .ptr2.sub = s },
+#define CF_LIST(n,p,s)         { .type = CT_LIST, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,struct clist*), .ptr2.sub = s },
 
 #endif