From 025fe3436d497926e2a3cb2138f9974d5f513549 Mon Sep 17 00:00:00 2001 From: Michal Vaner Date: Sun, 2 Nov 2008 14:48:38 +0100 Subject: [PATCH] ucw docs: Generic headers --- ucw/doc/Makefile | 2 +- ucw/doc/generic.txt | 101 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 ucw/doc/generic.txt diff --git a/ucw/doc/Makefile b/ucw/doc/Makefile index 53d3eed7..b404bf93 100644 --- a/ucw/doc/Makefile +++ b/ucw/doc/Makefile @@ -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 index 00000000..7f59ca1c --- /dev/null +++ b/ucw/doc/generic.txt @@ -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. + +- <> +- <> +- <> +- 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 + + #define ARRAY_TYPE uns + #define ARRAY_PREFIX(suffix) unsarray_##suffix + #include + +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. -- 2.39.5