ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
No Matches
ALib Module Configuration - Programmer's Manual
It may be helpful to read this module documentation and understand the concepts - even if you are not planning to use configuration variables in your own code. The reason is that with the knowledge of the principles described here, it is possible to influence the behavior of "3rd party code", namely code that uses configuration variables, as for example module ALox does.

1. Introduction

This module provides tools to read and write configuration data using different mechanisms. In short, the features are:

  • Central class Configuration used to retrieve and store external configuration data using arbitrary sources.
  • Abstract plug-in interface ConfigurationPlugin to read from (and optionally store into) custom external storage.
  • Predefined plug-ins for command line parameters, environment variables, in-memory storage and simple INI files.
  • The possibility to set default values 'in code' (if no external plug-in finds a value) and doing this "out of scope" which means independent from the code that finally uses a variable.
  • The possibility to protect variables 'in code' from being modified (to block modification of variables exposed by 3rd party code).
  • Automatic resolving of nested variables: Define a value once and pass it as a variable to other variables ("variable substitution").
  • With the combination of variable substitution and protection of variable values, it is possible to hide, rename or even redefine the syntax and behavior of variables exposed by third party code (e.g. libraries).
  • In this C++ version of the module, declarations of configuration variables (which defines the category and name, the default value, the comment and other fields) can optionally be "externalized" by using a ALib Enum Records.
    Of-course, all variables used by ALib Modules are resourced and hence can be renamed by users of those libraries.

1.1 Central Classes

The plug-ins, derived from abstract class ConfigurationPlugin are plugged into an object of type Configuration and are responsible for reading (and optionally writing) variables from dedicated sources.

Class Configuration offers an interface to retrieve and store configuration variables using the plug-ins. The plug-ins are attached to the Configuration instance along with a unique priority. Values are retrieved and stored by looping through the plug-ins sorted by priority. As soon as one plug-in confirms to have found (or stored) the variable, the loop ends. This way, plug-ins may "overrule" each other in respect to retrieving configuration data.

Class Camp holds a pointer to an instance of this class, which is created during library bootstrap. This instance by default is shared among all library modules and the application itself, and is usually all that is needed!

1.2 Naming Scheme

Configuration variables are addressed by two strings: The category and the name. In the case of INI files, the category is translated to the section and the name to variables within the section. Other plug-ins, for example CLIArgs or Environment, are prepending the category name to the variable name separated by an underscore character '_'. For example, a variable in category "ALIB" named "WAIT_FOR_KEY_PRESS", in an INI file would be stated like this:


To define the same variable and value on the command-line, the parameter needs to be:


The anonymous, empty category is allowed. For convenience, with variables of this category, no underscore is prepended by the plug-ins. The little drawback of this is, that variables in the anonymous category that contain an underscore character, for some plug-ins can get ambiguous. For example, variable MY_VARIABLE in the anonymous category, on the command line would be uniquely addressed by:

    --MY_VARIABLE=my value

In an INI file, two ways of specifying the variable are possible (and therefore ambiguous). In the anonymous section:

    MY_VARIABLE  =       my value

or, in section MY:

    VARIABLE     =       my value

2. Command-Line parameters, Environment Variables and INI files

Three different standard plug-ins that collect external configuration variables are provided with ALib already:

The proposed priorities to be used when attaching the plug-ins to the Configuration object, are enumerated in Priorities , which is an arithmetical enumeration .

With these default priorities set, whatever is stored in an INI file, can be overwritten by setting an environment variable. Both settings can in turn be overwritten by specifying a corresponding command line parameter when launching the process!

3. Default Variables

In addition to the three plug-ins described above, ALib implements a fourth one, class InMemoryPlugin. As the name indicates, this class keeps configuration variables in memory. The special thing about it is that it does not read any external data source! The reason for having it, is twofold. The first use case are Default variables: An instance is plugged into class Configuration with a (low) priority of Priorities::DefaultValues. This plug-in serves as a storage for default values. The only way to set these default values is programatically, which means "with program code".

The advantages of having such default variables are:

  • Code that checks whether a variable is set can be omitted (there is always a value found).
  • Code that sets default values if no variable is set can be omitted.
  • All default settings can be made in one place (in the resource pool or in a in custom bootstrap section of a process or library).

4. Protecting Variables

Class InMemoryPlugin is by default used a second time by plugging an instance into class Configuration with the highest possible priority Priorities::ProtectedValues .

When setting a variable within this plug-in, no other plug-in can 'overrule' this value. This way, it is possible to protect values against external modification.

One might think: "If I do not want to allow external modification, I rather hard-code everything". This of-course is true for code under control. However, for 3rd party code using ALib , this offers an easy way to disallow users of your software (which incorporates that 3rd party code) to configure things that you do not want to be configurable.

5. Using Class Configuration

In normal use cases, there is no need to create an instance of class Configuration, as a singleton is provided with Camp::GetConfig for every module. The command line parameters found with global ALib variables ArgC , ArgVN and ArgVW (if set by the user's main()-function properly), are passed to the command-line plug-in of this singleton by function Bootstrap . Dependent libraries will receive the same singleton instance, unless they are explicitly initialized prior to initializing the library that builds upon them. (For details on this, see chapter Bootstrapping ALib of the library's Programmer's Manual.)

Class Configuration in the constructor by default sets up four plug-ins automatically: CLIArgs for parsing command-line arguments as variables, Environment for environment variables and two plug-ins of type InMemoryPlugin used for default and protected values.

If an application wants to suppress the use of one of the plug-ins, the plug-ins can be removed using method RemovePlugin.
On the other hand, a plug-in of type IniFile may be attached on bootstrap of a process (or later) using Priorities::Standard .

In addition (or alternatively), custom plug-ins may be written and installed using arbitrary priorities.

Class IniFile is designed for simplicity and smaller applications. Instead of using this class, it is recommended to use application/platform specific mechanisms for writing configuration data. In this case, write your own plug-in to grant ALib and other libraries which rely on ALib , access to your application's configuration data. Again, ALib here follows its design principle to be "least intrusive": The plug-in concept allows a programmer that uses ALib enabled libraries (or ALib itself) to expose any external configuration source to these libraries. This way, the programmer can stick to his/her preferred way of implementation.

6. Loading and Storing Variables

Values of variables are loaded and received using instances of class Variable . Instances of this class can be passed to the interface of class Configuration or directly to specific ConfigurationPlugin objects. Simple access methods allow to read or set the values of a variable.

By consequently using optional struct VariableDecl for declaring all variables of an application or library, all attributes of variables can be maintained in one place. This includes categories, names, comments, value delimiters and default values of variables. Class Variable accepts instances of VariableDecl in the constructor as well as in overloaded method Variable::Declare.

Moreover, variable declaration values can be defined using "externalized" resource strings. For more information on this topic see

7. Variable Substitution

Method Configuration::Load by default substitutes references to other configuration variables found in the value of the requested variable.

For example, if two variables are defined as follows:


then, with the retrieval of variable MYCAT_MYVARIABLE, variable MYCAT_RESULT is read and the sub-string "$MYCAT_RESULT" is substituted by "42".

Substitutions are performed repeatedly until all variables are resolved. Therefore, nested substitutions may be defined as well. To avoid an endless loop in case of circular dependencies, a simple threshold applies: A maximum of 50 replacements are done.

The dollar sign '$' used to recognize variables is the default and can be modified. It is also possible to specify a prefix and a suffix for the identification of substitutable variables in other variable's values. For example, the syntax can be adjusted to


See documentation of fields SubstitutionVariableStart, SubstitutionVariableEnd and SubstitutionVariableDelimiters for more information.

When parsing a variable's category and name, method Configuration::Load searches for an underscore character '_'. The first underscore found serves as a delimiter of category from the name. If no underscore character is found, the category is left empty (anonymous category) and the name is set to what is given as a variable name.

This implies that variables which have no category but have an underscore in their name, need to be specified with a leading underscore. For example:
    TEXT= Welcome to $_HOME_LOCATION
refers to a variable name HOME_LOCATION in the anonymous category "".
For clarification:
  • This is not needed (but is also no fault) for variables that do not contain an underscore in their name.
  • This must not be done if a variable belongs to a named category.

8. In- and Externalizing Variable Values

Variable values provided via command line parameters, environment variables or textual configuration files need to be converted when loading and storing them. This has two reasons:

  • Certain characters of variables have to be "escaped", e.g. '\n' or '\t' within strings
  • Multiple values defined in variables need to be separated when storing - and parsed back when loading a variable.

For this task, class XTernalizer is used. Each ConfigurationPlugin owns an instance of this class (which is exchangeable). Conversion is done internally and there is no need to interface with this class directly when using variables. A huge benefit of this API design is that variable values look the same in an INI-file as if passed as a command line parameter.

But it is important to understand that values provided with interface methods to store variables expect "externalized" strings (only). In simple cases this is not relevant. But if a variable contains multiple values or special characters, it has to be understood that an 'internalization' of the value takes place.

Normal, internal string values need to be added to the variable in code prior to invoking a store method. If an externalized string is provided with the store methods, then previously added variable values are cleared!