From: Robert Spalek Date: Tue, 18 Apr 2006 12:37:31 +0000 (+0200) Subject: significant simplifications of the interface X-Git-Tag: holmes-import~645^2~11^2~109 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=80ca78f1c50aeaaa1483719127a6b31b39c11510;p=libucw.git significant simplifications of the interface - 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 --- diff --git a/lib/conf2-test.c b/lib/conf2-test.c index 8c91a6c7..8794bf7b 100644 --- a/lib/conf2-test.c +++ b/lib/conf2-test.c @@ -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 diff --git a/lib/conf2.h b/lib/conf2.h index 9f5de68d..20daf32a 100644 --- a/lib/conf2.h +++ b/lib/conf2.h @@ -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