]> mj.ucw.cz Git - libucw.git/commitdiff
ucw docs: multiple configuration items
authorMichal Vaner <vorner@ucw.cz>
Wed, 22 Oct 2008 11:34:05 +0000 (13:34 +0200)
committerMichal Vaner <vorner@ucw.cz>
Wed, 22 Oct 2008 11:34:05 +0000 (13:34 +0200)
arrays and lists of configuration items.

ucw/conf.h
ucw/doc/conf.txt

index bef2ddee9c558206cb8c9e53db6792143d4326e1..42bf0c9493ca08410794729e7de15f3875a21a01 100644 (file)
@@ -113,10 +113,45 @@ struct cf_section {                       /** A section. **/
  * 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>>. **/
@@ -129,8 +164,18 @@ struct cf_section {                        /** A section. **/
  * 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. **/
@@ -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
 
index e71a1e50fc45bd04732b53fb16e8560249778301..c89136082a98fada89556b61f93d9df5bd0459d1 100644 (file)
@@ -21,6 +21,7 @@ from command line.
   * <<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>>
@@ -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 <<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
 ~~~~~~~~~~~~~~~~~~~~~~~