From 525cfaad2da3938626887e6543f43fc4618721a1 Mon Sep 17 00:00:00 2001 From: Michal Vaner Date: Wed, 22 Oct 2008 13:34:05 +0200 Subject: [PATCH] ucw docs: multiple configuration items arrays and lists of configuration items. --- ucw/conf.h | 60 +++++++++++++++++++++++++++++++++++++++------ ucw/doc/conf.txt | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/ucw/conf.h b/ucw/conf.h index bef2ddee..42bf0c94 100644 --- a/ucw/conf.h +++ b/ucw/conf.h @@ -113,10 +113,45 @@ struct cf_section { /** A section. **/ * Declaration of <> * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * - * These macros can be used to configure the top-level <> + * These macros can be used to configure the <> * structure. ***/ -#define CF_TYPE(s) .size = sizeof(s) /** Type of the section. **/ + +/** + * Data type of a section. + * If you store the section into a structure, use this macro. + * + * Storing a section into a structure is useful mostly when you may have multiple instances of the + * section (eg. <>). + * + * Example: + * + * struct list_node { + * cnode n; // This one is for the list itself + * char *name; + * uns value; + * }; + * + * struct clist nodes; + * + * static struct cf_section node = { + * CF_TYPE(struct list_node), + * CF_ITEMS { + * CF_STRING("name", PTR_TO(struct list_node, name)), + * CF_UNS("value", PTR_TO(struct list_node, value)), + * CF_END + * } + * }; + * + * static struct cf_section section = { + * CF_LIST("node", &nodes, &node), + * CF_END + * }; + * + * You could use <> or <> + * macros to create arrays. + */ +#define CF_TYPE(s) .size = sizeof(s) #define CF_INIT(f) .init = (cf_hook*) f /** Init <>. **/ #define CF_COMMIT(f) .commit = (cf_hook*) f /** Commit <>. **/ #define CF_COPY(f) .copy = (cf_copier*) f /** <>. **/ @@ -129,8 +164,18 @@ struct cf_section { /** A section. **/ * Each of these describe single <>. They are mostly * for internal use, do not use them directly unless you really know what you are doing. ***/ -#define CF_STATIC(n,p,T,t,c) { .cls = CC_STATIC, .type = CT_##T, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,t*) } /** Static array of items. **/ -#define CF_DYNAMIC(n,p,T,t,c) { .cls = CC_DYNAMIC, .type = CT_##T, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,t**) } /** Dynamic array of items. **/ + +/** + * Static array of items. + * Expects you to allocate the memory and provide pointer to it. + **/ +#define CF_STATIC(n,p,T,t,c) { .cls = CC_STATIC, .type = CT_##T, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,t*) } +/** + * Dynamic array of items. + * Expects you to provide pointer to your pointer to data and it will allocate new memory for it + * and set your pointer to it. + **/ +#define CF_DYNAMIC(n,p,T,t,c) { .cls = CC_DYNAMIC, .type = CT_##T, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,t**) } #define CF_PARSER(n,p,f,c) { .cls = CC_PARSER, .name = n, .number = c, .ptr = p, .u.par = (cf_parser*) f } /** A low-level parser. **/ #define CF_SECTION(n,p,s) { .cls = CC_SECTION, .name = n, .number = 1, .ptr = p, .u.sec = s } /** A sub-section. **/ #define CF_LIST(n,p,s) { .cls = CC_LIST, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,clist*), .u.sec = s } /** A list with sub-items. **/ @@ -199,11 +244,12 @@ struct cf_section { /** A section. **/ **/ #define CF_USER_DYN(n,p,t,c) { .cls = CC_DYNAMIC, .type = CT_USER, .name = n, .number = c, .ptr = p, .u.utype = t } -/* If you aren't picky about the number of parameters */ +/** + * Any number of dynamic array elements + **/ #define CF_ANY_NUM -0x7fffffff -#define DARY_LEN(a) ((uns*)a)[-1] - // length of a dynamic array +#define DARY_LEN(a) ((uns*)a)[-1] /** Length of an dynamic array. **/ #define DARY_ALLOC(type,len,val...) ((struct { uns l; type a[len]; }) { .l = len, .a = { val } }).a // creates a static instance of a dynamic array diff --git a/ucw/doc/conf.txt b/ucw/doc/conf.txt index e71a1e50..c8913608 100644 --- a/ucw/doc/conf.txt +++ b/ucw/doc/conf.txt @@ -21,6 +21,7 @@ from command line. * <> * <> - <> + * <> * <> * <> * <> @@ -136,6 +137,69 @@ Getting deeper Since the configuration system is somehow complicated, this part gives you a little overview of what you can find and where. +[[conf_multi]] +Arrays and lists +~~~~~~~~~~~~~~~~ + +It is sometime needed to have multiple items of the same type. There +are three ways to do that: + +*Static arrays*:: + An array with fixed maximum length. You provide + the length and already allocated array which is filled with items. + The configuration may contain less than the maximum length items. ++ +For example, you can have an static array of five unsigned integers: ++ + static uns array = { 1, 2, 3, 4, 5 }; ++ + static struct cf_section section = { + CF_ITEMS { + CF_UNS_ARY("array", array, 5), + CF_END + } + }; + +*Dynamic arrays*:: + Similar to static array, but you provide pointer + to pointer to the given item (eg. if you want dynamic array of + `int` s, you give `**int`). The parser allocates an array of needed + size. You can use the <> macro to find out + the number of elements actually loaded. ++ +If you want dynamic array of strings, you would use: ++ + static char *array[]; ++ + static struct cf_section section = { + CF_ITEMS { + CF_STRING_DYN("array", &array, CF_ANY_NUM), + CF_END + } + }; + +*Lists*:: + Linked lists based on <>. You provide description + of single node and pointer to the + <> variable. All the nodes will + be created dynamically and put there. ++ +First element of your structure must be <>. ++ +The first example is list of strings and uses <>: + struct clist list; ++ + static struct cf_section section = { + CF_ITEMS { + CF_LIST("list", &list, &cf_string_list_cofnig), + CF_END + } + }; ++ +Another example, describing how to create more complicated list node +than just a string can be found at the <> macro. + [[reload]] Reloading configuration ~~~~~~~~~~~~~~~~~~~~~~~ -- 2.39.2