]> mj.ucw.cz Git - libucw.git/commitdiff
ucw docs: Generic headers
authorMichal Vaner <vorner@ucw.cz>
Sun, 2 Nov 2008 13:48:38 +0000 (14:48 +0100)
committerMichal Vaner <vorner@ucw.cz>
Sun, 2 Nov 2008 13:48:38 +0000 (14:48 +0100)
ucw/doc/Makefile
ucw/doc/generic.txt [new file with mode: 0644]

index 53d3eed79dccb6f72caf5a1e28a8cd9cf1be730e..b404bf93add869469796dc44f47476b20a24f642 100644 (file)
@@ -2,7 +2,7 @@
 
 DIRS+=ucw/doc
 
-UCW_DOCS=fastbuf index config configure install basecode hash docsys conf mempool mainloop
+UCW_DOCS=fastbuf index config configure install basecode hash docsys conf mempool mainloop generic
 UCW_INDEX=$(o)/ucw/doc/def_index.html
 UCW_DOCS_HTML=$(addprefix $(o)/ucw/doc/,$(addsuffix .html,$(UCW_DOCS)))
 
diff --git a/ucw/doc/generic.txt b/ucw/doc/generic.txt
new file mode 100644 (file)
index 0000000..7f59ca1
--- /dev/null
@@ -0,0 +1,101 @@
+Generic data structures and algorithms
+======================================
+
+The C preprocessor is a very powerful tool. One handy way to use it
+can be generating generic data structures and algorithms. You can find
+some conventions how they are written in libUCW and hints how to use
+them.
+
+- <<idea,General idea>>
+- <<use,How to use them>>
+- <<implement,How it is implemented>>
+- Modules with generics
+
+// TODO The module list
+
+[[idea]]
+General idea
+------------
+
+The idea is simple. If you have some code, you can customize it a
+little by preprocessor macros. You can change constants, data types it
+operates on, whole expressions, or you can exclude parts of the code
+from compilation. You can generate new function names using macros.
+
+So if you provide few macros for data types, function names and
+parameters and include some code using them, it gets modified by it
+and a code for a specific data type is created. Then you can provide
+new macros and include it again, to get another version of the code,
+with different function names and types.
+
+[[use]]
+How to use them
+---------------
+
+The use is best explained with an example, so we will suppose there
+is a header file `array.h`, which contains a generic array data type
+and an indexing function, which returns a pointer to n'th element.
+
+To get an array of integers, we need to provide macro for used data
+type and macro that will provide prefixes for identifier names. Then
+we include the file. Then we could get another array with unsigned
+integers, so we will do the same.
+
+  #define ARRAY_TYPE int
+  #define ARRAY_PREFIX(suffix) intarray_##suffix
+  #include <array.h>
+
+  #define ARRAY_TYPE uns
+  #define ARRAY_PREFIX(suffix) unsarray_##suffix
+  #include <array.h>
+
+This will generate the data types (presumably `intarray_t` and
+`unsarray_t`) and the index functions (`intarray_index` and
+`unsarray_index`). We can use them like anything else.
+
+Maybe the `ARRAY_PREFIX` deserves some attention. When the header file
+wants to generate a name of some identifier, it uses this macro with
+some suffix. Then the macro takes the suffix, adds a prefix to it and
+returns the new identifier, so `ARRAY_PREFIX(t)` will generate
+`intarray_t` in the first case and `unsarray_t` in the second. This
+allows having more than one instance of the same data structure or
+algorithm, because it generates different names for them.
+
+Similar macro is needed for every generic header in libUCW.
+
+[[implement]]
+How it is implemented
+---------------------
+
+For those who want to write their own or are just interested, how it
+works, here is the `array.h` header and some description to it.
+
+  #define ARRAY_A_TYPE ARRAY_PREFIX(t)
+  typedef ARRAY_TYPE *ARRAY_A_TYPE
+
+  static ARRAY_TYPE *ARRAY_PREFIX(index)(ARRAY_A_TYPE array, uns index)
+  {
+    return array + index;
+  }
+
+  #undef ARRAY_A_TYPE
+  #undef ARRAY_TYPE
+  #undef ARRAY_PREFIX
+
+There are few thinks that are worth noticing. The first two lines
+define the data type. The macro (`ARRAY_A_TYPE`) is only for
+convenience inside the header, since such type names can be used quite
+often inside the header (if it is large).
+
+Then there is the function with its name generated (do not get scared
+by the double parenthesis, ones will be eaten by the macro, the second
+ones are real function parameters). The function is static, since more
+than one `.c` file might want to use the same header with the same
+prefix -- each one generates it's own instance.
+
+And the end just undefines all the macros, so user may define them
+again and get another instance of the data structure.
+
+Also note it is not protected against multiple inclusion in the usual
+way (eg. `#ifndef ARRAY_H` ...), since multiple inclusion is desired
+-- it generates multiple versions of the data structure.