name_value - acfr/comma GitHub Wiki

name_value library is unfinished, but stable and useful.

Table of Contents

artifacts

  1. 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
  2. various functions for serialization/deserialization of arbitrary C++ structures as json, XML, path-value pairs, etc.
  3. name-value-convert: utility that converts between json, XML, ini files, path-value pairs, etc
  4. name-value-get: utility that gets value by name from json, XML, ini files, path-value pairs, etc
  5. name-value-from-csv: convert csv stream to indexed path-value pairs
  6. name-value-to-csv: convert indexed path-value pairs to csv stream
todo:: merge 1 and 2.

name_value::parser

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"

getting a structure from a string

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 );

putting a structure into a string

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".

nested structures

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 );

nameless values

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 );

boolean values

 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

name_value::map

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

property tree conversion functions

todo

⚠️ **GitHub.com Fallback** ⚠️