Skip to content

Configuration file parser

Joshua Z. Zhang edited this page Oct 22, 2015 · 3 revisions

Config/INI Parser

zz::cfg::cfgParser

First of all, zupply cfgParser is compatible with the common configuration file(Wikipedia), INI is commonly used in Windows, CFG is more widely used in unix. Whatever, they are most likely compatible with each other(Some ini parser may not support '#' as comment syntax).

How to write a config file

Config files are simple, the very basic stuff is key-value pair:

param = the_value_string # comment

Standard support sections:

[main]
a = 1 # main.a = 1
[section2]
a = 2 ; here a belong to section2, section2.a = 2

Standard INI only define level-0 sections, however, to make it more universal, zupply cfgParser support hierarchical sections:

# split stuff in sections
[level1]
a = 1 
[level1]
level2.a = 2 
level2.b = 3
[a]
b.c.d.e = 4

equivalent to

[level1]
a = 1 
[level1.level2]
a = 2 
b = 3
[a.b.c.d]
e = 4

equivalent to

# you can get rid of [] before any section
level1.a = 1
level1.level2.a = 2
level1.level2.b = 3
a.b.c.d.e = 4

How to parse config file

#include "zupply.hpp" 
zz::cfg::cfgParser parser("/config/config.txt");

Now configurations are stored in parser.

How to retrieve the values

Use () to strip down sections, use [] to get the value.

Example config file: config.txt

# deep section
a.b.c.d = -1

[section1]
name = zupply
index = 1

[section2]
param1 = 2.5
param2 : true ; use ':' is also good for key-value pair
param_vector = 0.1 1.5 2.3 9.4 # a vector of string with whitespaces

Example code:

cfg::cfgParser parser("config.txt");
std::string name = parser("section1")["name"].str(); // return string
int index = parser("section1")["index"].load<int>(); // parse as int
float param1 = parser("section2")["param1"].load<float>(); // parse as float
bool flag = parser("section2")["param2"].load<bool>(); // parse as bool, support true/false string
std::vector<double> v; 
parser("section2")["param_vector"].load(v); // put v as argument is supported.
// now v = {0.1, 1.5, 2.3, 9.4}
int d = parser("a")("b")("c")["d"].load<int>();
Note
  • If not [section] specified, everything is in global space
  • Unless another [] section appeared, keys belong the the last appeared section
  • Returned value by parser()()[] is actually cfg::Value which support conversion to many formats, such as int, float...
cfg::Value v = "0.123";
v.str() = "0.123";
double value = v.load<double>(); // value ~= 0.123
  • Value.str() is stored string, you can always get it without conversion
  • Value.load<type>() will return type, if failed due to some reason, it will throw.
  • Value.load(dst) will put the converted value into dst, again, it fail, throw.
  • Value support loading a vector of values, as shown in the example.