Mechanism for configuration variables that can alter the behavior of the code for the purpose of debugging and experimenting, with very little performance overhead. The default (initial) values are defined in the code and lead to the nominal behavior, which can be overridden by creating .ini files (with name=value lines) in the directory determined by the platform:
- Windows: "%NX_INI_DIR%\" (if NX_INI_DIR env var is defined), or "%LOCALAPPDATA%\nx_ini\" (otherwise). ATTENTION: If LOCALAPPDATA env var contains non-ASCII chars, it will yield a non-existing path.
- Linux, MacOS: "$NX_INI_DIR/" (if NX_INI_DIR env var is defined), or "$HOME/.config/nx_ini/" (if HOME env var is defined), "/etc/nx_ini/" (otherwise).
- Android: "/sdcard/".
- iOS: Not supported yet.
Each derived class represents a dedicated .ini file. If, on attempt to load a file, it is found empty, the file is filled with default values and descriptions. The names of .ini files and their values are printed to stderr (configurable), overridden values marked with "*".
The format of a .ini file is as follows: lines beginning with #
are ignored (treated as comments); whitespace around the name, the equals sign, and the value is ignored; the value can be surrounded with quotes ("
), in which case it is parsed using a C-style-escaping, supporting concatenation of consecutive enquoted strings, but not supporting \uXXXX
and \UXXXXXXXX
.
Usage example:
struct Ini: nx::kit::IniConfig
{
// NOTE: Omit `reload();` if load-on-start is not needed.
Ini(): IniConfig("my_module.ini") { reload(); }
NX_INI_FLAG(0, myFlag, "Here 0 stands for 'false' as the default value.");
NX_INI_INT(7, myInt, "Here 7 is the default value.");
NX_INI_STRING("Default value", myStr, "Description.");
NX_INI_FLOAT(1.0, myFloat, "Here 1.0 is the default value.");
NX_INI_DOUBLE(1.0, myDouble, "Here 1.0 is the default value.");
};
inline Ini& ini()
{
static Ini ini;
return ini;
}
In the code, use ini().<param-name> to access the values. Call ini().reload() when needed, e.g. when certain activity starts or at regular intervals.
ATTENTION: Inline functions with static variables are safe to use only when the header is local to a single dynamic library or executable. Otherwise (if the header is included into more than one dynamic library or executable), due to compiler/linker limitations, such variables may have duplicate instances, thus, the function definition must be moved to a .cpp.
Allows to tweak IniConfig values for the duration defined by this object life time. Re-reading the values is disabled while at least one Tweaks instance exists. Intended for tests.
Usage:
{
IniConfig::Tweaks tweaks;
tweaks.set(&
ini().parameter, value);
}