]> mj.ucw.cz Git - libucw.git/blob - lib/conf2.h
designed the interface of the new configuration reader. no code has been
[libucw.git] / lib / conf2.h
1 /*
2  *      UCW Library -- Reading of configuration files
3  *
4  *      (c) 2006 Robert Spalek <robert@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #ifndef _LIB_CONF2_H
11 #define _LIB_CONF2_H
12
13 enum cf_type {
14   CT_END,                               // end of list
15   CT_INT, CT_U64, CT_DOUBLE,            // number types
16   CT_STRING,                            // string type
17   CT_FUNCTION,                          // arbitrary parser function
18   CT_SUB_SECTION,                       // sub-section appears exactly once
19   CT_LINK_LIST                          // link-list with 0..many nodes
20 };
21
22 struct cf_section;
23 typedef byte *cf_hook(void *sec_ptr, struct cf_section *sec);
24   /* An init- or commit-hook gets a pointer to the sub-section or NULL if this
25    * is the global section, and a declaration of the section it is called on.
26    * It returns an error message or NULL if everything is all right.  */
27 typedef byte *cf_parser(uns nr_pars, byte **pars, void *sec_ptr, struct cf_section *sec, uns index);
28   /* A parser function gets an array of strings and stores it in any way it
29    * likes into its own data structures.  It gets a pointer to the sub-section
30    * or NULL if this is the global section, a declaration of the section it is
31    * called in, and the index of the item it is called on.  It returns an error
32    * message or NULL if everything is all right.  */
33
34 struct cf_item {
35   enum cf_type type;
36   byte *name;
37   int number;                           // number of values: k>0 means exactly k, k<0 means at most k
38   void *ptr;                            // pointer to a global variable or an offset in a sub-section
39   struct cf_section *sub;               // declaration of a sub-section or link-list
40 };
41
42 struct cf_section {
43   uns size;                             // 0 for a global block, sizeof(struct) for a sub-section
44   cf_hook *init;                        // fills in default values
45   cf_hook *commit;                      // verifies parsed data and checks ranges (optional)
46   struct cf_item *cfg;                  // CT_END-terminated array of items
47 };
48
49 #define CHECK_VAR_TYPE(x,type) ((x)-(type)0 + (type)0)
50   // for a pointer x it returns x, and performs a compile-time check whether typeof(x)==type
51 #define DEFAULT_ARRAY(type,len,val...) (type[]) { (type)len, ##val } + 1
52   // creates an array with an allocated space in the front for the (Pascal-like) length
53 #define CF_FIELD(str,f) &((str*)0)->f
54   // returns a pointer to a field inside a structure suitable for passing as cf_item->ptr
55
56 #define CF_END          { .type = CT_END }
57   // please better put this at the end of each section
58 #define CF_INT(n,p)     { .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,int*) }
59 #define CF_U64(n,p)     { .type = CT_U64, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,u64*) }
60 #define CF_DOUBLE(n,p)  { .type = CT_DOUBLE, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,double*) }
61 #define CF_STRING(n,p)  { .type = CT_STRING, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,byte**) }
62 #define CF_FUNCTION(n,p)        { .type = CT_FUNCTION, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,cf_parser*) }
63 #define CF_SUB_SECTION(n,p,s)   { .type = CT_SUB_SECTION, .name = n, .number = 1, .ptr = p, .sub = s }
64 #define CF_LINK_LIST(n,p,s)     { .type = CT_LINK_LIST, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,struct cnode*), .sub = s }
65   // use the macros above to declare configuration items for single variables
66 #define CF_INT_AR(n,p,c)        { .type = CT_INT, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,int**) }
67 #define CF_U64_AR(n,p,c)        { .type = CT_U64, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,u64**) }
68 #define CF_DOUBLE_AR(n,p,c)     { .type = CT_DOUBLE, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,double**) }
69 #define CF_STRING_AR(n,p,c)     { .type = CT_STRING, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,byte***) }
70   // use the macros above to declare configuration items for arrays of variables
71
72 #endif