In the core of libcfg+ is a single, carefully designed structure, which makes the uniform and consistent API possible.
The basic unit of libcfg+ is an option. An option is
defined by the cfg_option
structure, whose definition
is presented below:
structcfg_option
{ const char *cmdline_long_name
; const charcmdline_short_name
; const char *cfgfile_name
; const enum cfg_option_typetype
; void *value
; intval
; };
The first two members of the cfg_option
structure,
cmdline_long_name
and
cmdline_short_name
, specify the long and short name
of the option when parsing the command line. The third member,
cfgfile_name
, specifies the name of the option in a
configuration file. Setting the first two fields to NULL
and '\0'
respectively will effectively eliminate the
option from taking part in command line parsing. Setting
cfgfile_name
to NULL
will
eliminate this option from taking part in configuration file parsing.
Note also that if cmdline_long_name
or
cfgfile_name
point to a string containing at least
one whitespace character, any non-zero number of whitespace characters will be
matched during parsing. For example, if the separator is a space, a tab
character will also match, as will two spaces and a tab, two tabs and a space,
and so on. This simplifies the configuration for the user because one does not
have to pay attention to the number of spaces used in a configuration option.
For example, debug level,
debug\tlevel and
debug \tlevel will match the same option.
The variable type
is an enumeration defining the
type of an option with each member of the enumeration being either a type or a
flag. The possible values of type
are summarized in
tables Option types and Option type flags
The variable value
is a pointer to the argument(s)
of an option. The argument(s) must be of the type stored in the
type
member of the
cfg_option
structure. Note that
value
could also contain a
NULL
value, which would suggest that the option arguments
will not be stored.
The last field of the structure is val
. It defines
the exit code of parsing function when this option is found in the token
stream. Setting this field to 0
will cause
cfg_get_next_opt()
to proceed to the next option instead
of returning. Also, since cfg_get_next_opt()
also
returns negative integers to signal an error, it is a good idea to keep the
value of this field in the positive range. You can read more about this in the
Parsing section.
Table 2-1. Option types
Value | value type | Description |
---|---|---|
CFG_BOOL , CFG_BOOLEAN | int | No argument for an option is expected. Boolean datatype with two states. |
CFG_INT , CFG_INTEGER | int | Integer argument |
CFG_UINT , CFG_UNSIGNED ,
CFG_UNSIGNED_INT | unsigned int | Unsigned integer argument |
CFG_LONG | long int | Long integer argument |
CFG_ULONG ,
CFG_UNSIGNED_LONG | unsigned long int | Unsigned long integer argument |
CFG_FLOAT | float | Float argument |
CFG_DOUBLE | double | Double argument |
CFG_STR , CFG_STRING | char * | String argument |
The next table describes the possible "type flags" of an option. The purpose
of the flags is to add more variety and thus flexibility to the basic data
types presented in the previous table. By combining one of the flags with one
of the basic types, a completely new data type can be produced. For example,
to define an array of strings, one would use the
CFG_MULTI
flag in addition to the
CFG_STRING
data type. One of the obvious rules of this
data type combining is that the flags must always be used in conjunction with
the basic types since a flag is only a data type modifier and not a
self-contained data type.
Table 2-2. Option type flags
Flag | value type | Description |
---|---|---|
CFG_MULTI , CFG_MULTI_ARRAY | <type> ** | The Option can be specified more than once and the result is a dynamic array of the defined type. |
CFG_MULTI_SEPARATED | <type> ** | Same as CFG_MULTI_ARRAY , but a dynamic array
is also created by splitting the option value according to the defined
separators. See the Properties section for more information about the
separators that can be used and ways to change them. |
CFG_LAST_ARGS ,
CFG_LAST_ARGUMENTS ,
CFG_LEFTOVER_ARGS ,
CFG_LEFTOVER_ARGUMENTS
| <type> ** | Leftover arguments are stored here. |
Of the basic data types, only strings are dynamically allocated and in that
case value
points to a portion of memory allocated
with malloc()
function. Do not forget to free that memory
when you do not need it anymore using the free()
function. If the CFG_MULTI_ARRAY
or the
CFG_MULTI_SEPARATED
flag was used,
value
will point to a NULL
terminated array of a basic type. It can be freed using
cfg_strdyn_free()
.
The constants CFG_END_OPTION
and
CFG_END_OF_LIST
are used to mark the end of an option
set. They set all pointer values to NULL
and all numeric
values to 0
.
Example 2-1. Example of options set definition
#include <cfg+.h> /* Option variables */ int help, verbose, nice; char *cfg_file; char **command; /* Option set */ struct cfg_option options[] = { {"help", 'h', NULL, CFG_BOOL, (void *) &help, 0}, {"nice", 'n', "nice", CFG_INT, (void *) &nice, 0}, {"verbose", 'v', "verbose", CFG_BOOL+CFG_MULTI,(void *) &verbose, 0}, {NULL, 'f', NULL, CFG_STR, (void *) &cfg_file, 0}, {NULL, '\0', "command", CFG_STR+CFG_MULTI_SEPARATED+CFG_LEFTOVER_ARGS, (void *) &command, 0}, CFG_END_OF_LIST };