Boost property_tree: multiple values ​​per key

The Boost property tree looks like a great library for parsing configuration files. However, I cannot figure out how to handle situations where there are multiple values ​​for each key. For example, suppose I specify a field like this:

box { x -1 1 y -1 1 z -1 1 } 

where x , y and z are field boundaries on the x , y and z axes, respectively, specified using the property_tree INFO format. I see the reference to using quotation marks for values ​​that use spaces, but I don't see that I can import these values ​​as numbers. I will have to parse the string in numbers, which, apparently, first of all deprives the purpose of using the_tree property. I could give each number a key:

 box { xlo -1 xhi 1 ylo -1 yhi 1 zlo -1 zhi 1 } 

but it seems bulky and inflates my configuration file. I also noted that I can handle this situation in program_options, but I am losing the possibility of nested configuration files (yes, I know that I can use dotted notation for the "socket", but this is not the same).

Is there any way to import, for example. x how is a list of numbers like this?

+3
source share
1 answer

The standard_tree property processes only one string value for each key, because it is defined as:

 typedef basic_ptree<std::string, std::string> ptree; 

So, the only option is to use the strings and parse them. I believe that the best method is to define a new class that stores low and high values, and then create a translator class for the get and set methods. For instance:

 struct low_high_value { low_high_value() : m_low(0), m_high(0) { } low_high_value(double low, double high) : m_low(low), m_high(high) { } double m_low; double m_high; }; 

The translator will:

 struct low_high_value_translator { typedef std::string internal_type; typedef low_high_value external_type; // Get a low_high_value from a string boost::optional<external_type> get_value(const internal_type& str) { if (!str.empty()) { low_high_value val; std::stringstream s(str); s >> val.m_high >> val.m_low; return boost::optional<external_type>(val); } else return boost::optional<external_type>(boost::none); } // Create a string from a low_high_value boost::optional<internal_type> put_value(const external_type& b) { std::stringstream ss; ss << b.m_low << " " << b.m_high; return boost::optional<internal_type>(ss.str()); } }; 

The previous get_value method is very simple. It should be improved if the file can be written by the user.

This class must be registered using:

 namespace boost { namespace property_tree { template<typename Ch, typename Traits, typename Alloc> struct translator_between<std::basic_string< Ch, Traits, Alloc >, low_high_value> { typedef low_high_value_translator type; }; } } 

After including the previous code, you can use property_tree as:

  pt.get<low_high_value>("box.x") pt.put("box.u", low_high_value(-110, 200)); 
+5
source

All Articles