name_value - acfr/comma GitHub Wiki
name_value library is unfinished, but stable and useful.
- name_value::parser, name_value::map: parsing name-value pairs at one level, e.g. a=5;b=6, but not a={b=10;c=20}"; it is very useful for structured command line options
- various functions for serialization/deserialization of arbitrary C++ structures as json, XML, path-value pairs, etc.
- name-value-convert: utility that converts between json, XML, ini files, path-value pairs, etc
- name-value-get: utility that gets value by name from json, XML, ini files, path-value pairs, etc
- name-value-from-csv: convert csv stream to indexed path-value pairs
- name-value-to-csv: convert indexed path-value pairs to csv stream
The purpose of the name_value parser is to serialize / deserialize plain data structures to / from a name-value format:
"name1=value1;name2=value2;nested/name=value3"
Let's declare a struct containing some configuration:
struct config { config() : size(0), alpha(0), beta(0) {} config( const std::string& name, int s, double a, double b ): filename( name ), size( s ), alpha( a ), beta( b ) {} std::string filename; int size; double alpha; double beta; };
As usual (see visiting), we need to define the visiting traits for config:
template < typename key, class visitor > static void visit( Key, const config& config, Visitor& v ) { v.apply( "filename", config.filename ); v.apply( "size", config.size ); v.apply( "alpha", config.alpha ); v.apply( "beta", config.beta ); } }; } } // namespace comma { namespace visiting {
Now we can deserialize an instance of config from a string:
std::string s = "filename=data.csv;size=100;alpha=0.1;beta=0.3"; comma::name_value::parser parser; config c = parser.get< config >( s );
We can serialize the structure back into a string using name_value::put():
config c( "test.txt", 10, 1, 2 ); comma::name_value::parser parser; std::string s = parser.put( c );
Now s equals "filename=test.txt;size=10;alpha=1;beta=2".
name_value::parser also supports nested structures.
struct config { std::string filename; int size; double alpha; nested nested; double beta; };
The nested values can be accessed via comma::xpath:
std::string s = "filename=data.csv;size=100;alpha=0.1;nested/a=1;nested/b=2;beta=0.3"; comma::name_value::parser parser; config c = parser.get< config >( s );
If full_path_as_name is set to false in the constructor and there is no name conflict between the nested structures, we can use only the leaf of the xpath:
std::string s = "filename=data.csv;size=100;alpha=0.1;a=1;b=2;beta=0.3"; comma::name_value::Parser nameValue( ';', '=', false ); config c = nameValue.get< c >( s );
Sometimes we may want to have values without names, for example to write shorter command line options.
For example, if we would like to specify properties of an input file, we might write: "test.txt;size=10;alpha=1;beta=2", omitting that test.txt is the file name.
In that case, we can pass default names to the name_value::parser, which will be added to the nameless values:
std::string s = "data.csv;size=100;alpha=0.1;beta=0.3"; comma::name_value::parser parser( "filename" ); config c = nameValue.get< config >( s );
The default names can be passed as comma separated fields. For example, if we also don't want to write the name "alpha", we can do:
std::string s = "data.csv;size=100;0.1;beta=0.3"; comma::name_value::parser parser( "filename,,alpha" ); config c = parser.get< Config >( s );
struct properties { bool verbose; int num; }; // define visiting traits for properties... comma::name_value::parser parser;
std::string s = "num=5"; properties p = parser.get< properties >( s ); // verbose untouched
std::string s = "num=5;verbose=false"; properties p = parser.get< properties >( s ); // verbose == false
std::string s = "num=5;verbose=true"; properties p = parser.get< properties >( s ); // verbose == true
std::string s = "num=5;verbose=1"; properties p = parser.get< properties >( s ); // verbose == true
std::string s = "num=5;verbose"; properties p = parser.get< properties >( s ); // verbose == true
The purpose of name_value::map is to extract name-value pairs out of a string in name-value format: "name1=value1;name2=value2;nested/name=value3"
On construction, name_value::map parses the input string and constructs a map of name-value pairs. This map can be queried with the exists() and value() functions. The value() method supports default values.
std::string s = "filename=data.csv;size=100;alpha=0.1;beta=0.3"; comma::name_value::map map( s ); bool has_filename = map.exists( "filename" ); // will be true bool has_type = map.exists( "type" ); // will be false double alpha = map.value<double>( "alpha" ); // will be 0.1 double gamma = map.value<double>( "gamma", 0.2 ); // will be 0.2
name_value::map supports names without values:
std::string s = "filename=data;binary"; comma::name_value::map map( s ); bool binary = map.exists( "binary" ); // will be true
todo