* One such context is automatically created during initialization of the library
* and you need not care about more, as long as you use a single configuration file.
*
- * In full generality, you can define as many context as you wish and switch
+ * In full generality, you can define as many contexts as you wish and switch
* between them. Each thread has its own pointer to the current context, which
* must not be shared with other threads.
***/
* reloaded or rolled back, or the context is deleted, it gets lost).
*
* Memory allocated from within custom parsers should be allocated from the pools.
+ *
+ * Please note that the pool is not guaranteed to exist before you call cf_load(),
+ * cf_set(), or cf_getopt() on the particular context.
***/
struct mempool *cf_get_pool(void); /** Return a pointer to the current configuration pool. **/
void *cf_malloc(uns size); /** Returns @size bytes of memory allocated from the current configuration pool. **/
* Undo journal
* ~~~~~~~~~~~~
*
- * The configuration system uses journaling to safely reload
- * configuration. It begins a transaction and tries to load the
- * configuration. If it fails, it restores the original state.
+ * The configuration system uses a simple journaling mechanism, which makes
+ * it possible to undo changes to configuration. A typical example is loading
+ * of configuration by cf_load(): internally, it creates a transaction, applies
+ * all changes specified by the configuration and if one of them fails, the whole
+ * journal is replayed to restore the whole original state. Similarly, cf_reload()
+ * uses the journal to switch between configurations.
*
- * The behaviour of journal is described in <<reload,reloading configuration>>.
+ * In most cases, you need not care about the journal, except when you need
+ * to change some data from a <<hooks,hook>>, or if you want to call cf_modify_item() and then
+ * undo the changes.
***/
/**
- * By default, the configuration mechanism remembers all changes in a journal,
- * so that the configuration can be rolled back or reloaded. This function
- * can be used to disable journalling, which saves some memory.
+ * This function can be used to disable the whole journalling mechanism.
+ * It saves some memory, but it makes undoing of configuration changes impossible,
+ * which breaks for example cf_reload().
**/
void cf_set_journalling(int enable);
/**
* before them.
**/
void cf_journal_block(void *ptr, uns len);
-#define CF_JOURNAL_VAR(var) cf_journal_block(&(var), sizeof(var)) // Store single value into journal.
+#define CF_JOURNAL_VAR(var) cf_journal_block(&(var), sizeof(var)) // Store a single value into the journal
struct cf_journal_item; /** Opaque identifier of the journal state. **/
/**
* ~~~~~~~~~~~~~
*
* Direct access to configuration items.
- * You probably should not need this.
+ * You probably should not need this, but in your do, you have to handle
+ * <<journal,journalling>> yourself.
***/
/**
struct fastbuf;
/**
- * Take everything and write it into @fb.
+ * Write the current state of all configuration items into @fb.
**/
void cf_dump_sections(struct fastbuf *fb);
Configuration and command line parser
=====================================
-Libucw contains a parser for configuration files described in
-<<config:>>.
+Libucw contains a parser for configuration files. The syntax of the
+configuration files is described in <<config:>>, here we explain the
+interface of the parser.
-The principle is you specify the structure of the configuration file,
-the section names, variable names and types and your C variables that
-are assigned to them. Then you run the parser and it fills your
-variables with the values from the configuration file.
+Basically, you write a description of the configuration file syntax,
+which maps configuration items to variables of your program. Then
+Then you run the parser and it fills your variables with the values
+from the configuration file.
-It is modular. It means you do not have to write all configuration at
-the same place, you just declare the parts you need locally and do not
-care about the other parts.
+The descriptions are modular. The configuration can be split to sections,
+each section declared at a separate place. You can also define your own
+data types.
-The command line parser has the same interface as unix getopt_long(),
-but handles setting of configuration files and configuration values
-from command line.
+There is also a simple wrapper around getopt_long(), which processes
+options related to selection of a configuration file, overriding of
+configuration variables and loading of the default configuration.
- <<example,Example>>
* <<ex_structure,The structure>>
* <<custom_parser,Creating custom parsers>>
* <<hooks,Hooks>>
- <<conf_h,ucw/conf.h>>
+ * <<conf_ctxt,Configuration contexts>>
+ * <<conf_load,Safe configuration loading>>
* <<conf_types,Data types>>
* <<conf_macros,Convenience macros>>
* <<alloc,Memory allocation>>
* <<journal,Undo journal>>
* <<declare,Section declaration>>
* <<bparser,Parsers for basic types>>
-- <<getopt_h,ucw/getopt.h>>
- * <<conf_load,Safe configuration loading>>
* <<conf_direct,Direct access>>
* <<conf_dump,Debug dumping>>
- * <<conf_journal,Journaling control>>
+- <<getopt_h,ucw/getopt.h>>
* <<conf_getopt,Loading by cf_getopt()>>
[[example]]
-------
If you want to just load simple configuration, this is the part you
want to read. This simple example should give you the overview. Look
-into the <<conf_macros,convenience macros>> section to see list of
+at the <<conf_macros,convenience macros>> section to see list of
supported data types, sections, etc.
[[ex_cfile]]
-Let's say you have configuration file with this content and want to
-load it:
+Suppose you have configuration file with the following content and you
+want to load it:
HelloWorld {
Text "Hello planet"
}
The variables are used to store the loaded values. Their initial
-values work as default, if nothing else is loaded. The hw_config()
+values work as defaults, if nothing else is loaded. The hw_config()
structure assigns the variables to configuration names. The hw_init()
function (because of the `CONSTRUCTOR` macro) is run before main()
-is called and it plugs in the whole section to the parser (alternatively,
+is called and it tells the parser that the section exists (alternatively,
you can call @cf_declare_section() at the start of your main()).
You can plug in as many configuration sections as you like, from
~~~~~~~~~~~~~~~~~~~~~
Suppose you need to parse the command line arguments and load the
configuration. Then @cf_getopt() is there for you: it works like
-the the traditional @getopt() from the C library, but it also handles
+the traditional @getopt_long() from the C library, but it also handles
configuration files.
#include <ucw/lib.h>
Furthermore, if the loading of a new configuration fails, the current
configuration is preserved.
-All this is done with <<journal,config journaling>>. The load of the
+All this is done with <<journal,config journalling>>. The load of the
first config creates a journal entry. If you try to load some new
configuration, it is partially rolled back to defaults (the rollback
happens, but instead of removing the journal entry, another journal
handle, you can write your own parser. But before you start, you
should know a few things.
-The parser needs to support <<journal,journaling>>. To accomplish that,
+The parser needs to support <<journal,journalling>>. To accomplish that,
you have to use the <<alloc,configuration mempool>> for memory allocation.
Now, you need a function with the same signature as
The hooks should follow similar guidelines as custom parsers (well,
init hooks do not need to call @cf_journal_block()) to support
-journaling. If you change nothing in the commit hook, you do not need
-to care about the journaling either.
+journalling. If you change nothing in the commit hook, you do not need
+to care about the journalling either.
You may use the return value to inform about errors. Just return the
error message, or NULL if everything went well.
ucw/conf.h
----------
-Use this file if you want define a configuration section, request
-loading of some variables or create new item type.
+This header file contains the public interface of the configuration module.
!!ucw/conf.h
------------
This header contains routines for parsing command line arguments and
-loading the configuration.
+loading the default configuration.
!!ucw/getopt.h