* Declaration of <<struct_cf_section,`cf_section`>>
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
- * These macros can be used to configure the top-level <<struct_cf_section,`cf_section`>>
+ * These macros can be used to configure the <<struct_cf_section,`cf_section`>>
* 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. <<conf_multi,array or list>>).
+ *
+ * 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 <<def_CF_STATIC,`def_CF_STATIC`>> or <<def_CF_DYNAMIC,`def_CF_DYNAMIC`>>
+ * macros to create arrays.
+ */
+#define CF_TYPE(s) .size = sizeof(s)
#define CF_INIT(f) .init = (cf_hook*) f /** Init <<hooks,hook>>. **/
#define CF_COMMIT(f) .commit = (cf_hook*) f /** Commit <<hooks,hook>>. **/
#define CF_COPY(f) .copy = (cf_copier*) f /** <<hooks,Copy function>>. **/
* Each of these describe single <<struct_cf_item,configuration item>>. 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. **/
**/
#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
* <<ex_structure,The structure>>
* <<ex_load,Loading>>
- <<deep,Getting deeper>>
+ * <<conf_multi,Arrays and lists>>
* <<reload,Reloading configuration>>
* <<custom_parser,Creating custom parsers>>
* <<hooks,Hooks>>
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 <<def_DARY_LEN,`DARY_LEN`>> 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 <<clist:>>. You provide description
+ of single node and pointer to the
+ <<clist:struct_clist,`struct clist`>> variable. All the nodes will
+ be created dynamically and put there.
++
+First element of your structure must be <<clist:type_cnode,`cnode`>>.
++
+The first example is list of strings and uses <<clist:simple,simple
+lists>>:
+ 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 <<def_CF_TYPE,`CF_TYPE`>> macro.
+
[[reload]]
Reloading configuration
~~~~~~~~~~~~~~~~~~~~~~~