Skip to content

c-w-m/miniconf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

miniconf

miniconf is a minimalist C++ configuration manager.

miniconf only contains one C++ header file. It is not meant to be fast, but it is designed to make C++ programs simpler and more flexible for prototyping, research, and development in general.

main features

  • It is a smart argument parser: format checking, input validation, default values, etc.
  • It is also a config file reader: It supports reading from JSON and CSV.
  • It can serialize settings to JSON or CSV files and reuses them later.
  • It generates help and usage message automatically

One Minute Quick Start

An Example

miniconf uses a very simple API for configuring for an application, a working example is shown below:

int main(int argc, char** argv)
{
    /* create a Config object */
    miniconf::Config conf;

    /* Setup config options */
    /* Option properties, e.g. shortened flag, default values... */
    conf.option("numOpt").shortflag("n").defaultValue(3.14).required(false).description("A number value");
    conf.option("boolOpt").shortflag("b").defaultValue(false).required(true).description("A boolean value");
    conf.option("strOpt").shortflag("s").defaultValue("string").required(true).description("A string value");

    /* parse */
    bool success = conf.parse(argc, argv);
    if (success){
        /* processing the configuration here ... */
    } 
    else 
    {
        /* report error here ... */
    }
    return 0;
}

Configuring an application via command line / input file

User can modify the configuration settings by command line, for example:

$ ./program --numOpt 6.28 --boolOpt true -s "another string"

Alternatively, a config file can also be used, both JSON and CSV formats are supported, the file format is determined by the input file's extension, for example:

$ ./program --config settings.json -s "overwritten"

or

$ ./program --config settings.csv -s "overwritten"

Where the content of config file "settings.json" is:

{
   "numOpt": 6.28,
   "boolOpt": true, 
   "stringOpt": "this will be overwritten"
}

and in settings.csv, the content will be:

numOpt,6.28
boolOpt,true
stringOpt,this will be overwritten

Note that command-line arguments has a higher priority so the attribute "stringOpt" in the json file will be overwritten by "-s/--stringOpt" in the command-line.

The configurations in the above two examples should be the same when parsed by miniconf:

  • numOpt = 6.28
  • boolOpt = true
  • stringOpt = "overwritten"

A configuration file can also be loaded programmatically using the C++ Config::config() function, for example:

// create a Config object
miniconf::Config conf;

/* ... some parsing here if necessary ... */

// load (and possibly overwrite) the current config with the input json file
conf.config("settings.json");

The miniconf::Config::parse() function returns a boolean which indicates whether the parsing process is performed successfully.


Accessing configuration settings

Configuration values can be read by specifying their type implicitly, if output data type can be determined, for example:

double n = conf["numOpt"];
bool b = conf["boolOpt"];
std::string s = conf["strOpt"];

or, user may also define the configuration value explicitly:

double n = conf["numOpt"].getNumber();
bool b = conf["boolOpt"].getBoolean();
std::string s = conf["strOpt"].getString();

Advanced Features

Nested configuration

Nested configuration is support in miniconf with JSON, for example:

   // Setup config options 
   // Option properties, e.g. short flag
   conf.option("a.b.c").shortflag("c").defaultValue("c_val").required(false).description("A nested value");
   conf.option("a.b.d").shortflag("d").defaultValue("d_val").required(false).description("A nested value");
   conf.option("a.e").shortflag("e").defaultValue("e_val").required(false).description("A nested value");

With the command line arguments which overrides the original default values:

./program --a.b.c overwritten_c_val

the parsed configuration is:

  • a.b.c = "overwritten_c_val"
  • a.b.d = "d"
  • a.e = "e"

and the exported JSON file it will become:

{
    "a": {
        "b" : {
            "c" : "overwritten_c_val",
            "d" : "d" 
        },
        "e" : "e"
    }
}

Modifying Configuration Settings

Configuration values can also be modified during runtime:

conf["numOpt"] = 9.42;
conf["strOpt"] = "fourth string";
conf["boolOpt"] = false;

Or one can also do explicitly

conf["numOpt"] = mimiconf::Value(12.56);

Print current configuration summary

User may print the current configuration settings using the Config::print() function:

conf.print(); // print current settings

The output will be (The default output file is stdout):

[[[  CONFIGURATION  ]]]

|-------------------------|------------|--------------------------------------------------|
|           NAME          |    TYPE    |                     VALUE                        |
|-------------------------|------------|--------------------------------------------------|
| boolOpt                 | BOOLEAN    | false                                            |
| intOpt                  | INT        | 122                                              |
| numOpt                  | NUMBER     | 3.140000                                         |
| strOpt                  | STRING     | "string"                                         |
|-------------------------|------------|--------------------------------------------------|

Automated Help / Usage Message Generation

The function Config::help() generates and displays a help message, which looks like the message below:

[[[  USAGE  ]]]

    example -b <BOOLEAN> [-cfg <STRING>] [-h <BOOLEAN>] [-n <NUMBER>] -s <STRING> 


[[[  HELP  ]]]

    -b, --boolOpt <REQUIRED>
        A boolean value  ( DEFAULT = false ) 

    -cfg, --config 
        Load the config file. Config format is determined by the file's extenion. If no file extension is found, default JSON loader is used  ( DEFAULT = "" ) 

    -h, --help 
        Display the help message  ( DEFAULT = false ) 

    -n, --numOpt 
        A number value  ( DEFAULT = 3.140000 ) 

    -s, --strOpt <REQUIRED>
        A string value  ( DEFAULT = "string" ) 

The upper "usage" section can be displayed indepdently using the Config::usage() function.

The "auto-help" feature is enabled in miniconf by default, which means that an extra hidden option "--help/-h" is added to the configuration by default. The help message will be displayed to stdout when "--help/-h" is true. One can change the auto-help features by Config::enableHelp().


Serialization / programmatic config file loading

miniconf supports serialization to JSON / CSV formats:

// serialize current settings
conf.serialize("output_settings.json", Config::ExportFormat::JSON);

Two file formats, Config::ExportFormat::JSON and Config::ExportFormat::CSV are supported. The exported config files can be loaded back by using the "--config" argument, or the "Config::config()" function.

Vanilla version: JSON-less version

mimiconf requires a json parser to support JSON export and import, currently we are using picojson GITHUB as the backend JSON parser.

If one wants to remove the JSON dependency (to reduce code size, to remove the BSD license, etc.), one might need to uncomment the line

#define MINICONF_JSON_SUPPORT

in miniconf.h

Extra configuration values

Unrecognized option flags are treated as "extra configuration values", they will not be neglected and are processed according to how the setting is given to the miniconfig parser:

If it is given as a command line argument, or CSV file, it will be parsed as a string value, for example:

./program --extra 123

The option value of flag "extra" will be a string of "123".

Alternatively if it is given as a JSON file, it will try to parse the default data type interpreted by the JSON file:

{
    "extra1" : 123,
    "extra2" : "extra string"
}

The option value of flag "extra1" will be a number of value 123.0, and the option value of flag "extra2" will be a string of "extra string".

Note:

  • Shortened flags are not supported and will be ignored.
  • Values without any flag are not supported and will be ignored.

validation and logging

By default, the configuration settings and the option values given by the user will be automatically checked and validated in the miniconf::Config::parse() function. Before parsing the argument, user can set the logging level of config checker using the miniconf::Config::log() function.

For example, if the user wants to log all the messages:

conf.log(miniconf::Config::LogLevel::INFO);

On the other hand, if the user wants to log fatel errors only:

conf.log(miniconf::Config::LogLevel::ERROR);

The with the return value of parse() function, user might want to write a simple error checker like this:

/* set log level to "warning" which logs non-fatal warning as well */
conf.log(miniconf::Config::LogLevel::WARNING); 
/* parse the arguments, if error, print log and quit */
if (conf.parse(argc, argv)){
    // perform normal tasks...
} else {
    /* display erorr log */
    conf.log();
    exit(1);
}

About miniconf

miniconf is licensed under the unlicense license. :)

Please also visit the project's website: https://thyu.github.io/miniconf/

Author: Tsz-Ho Yu ([email protected])

Website: https://www.tszho.net/

About

A minimalist C++ configuration manager

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published