Search code examples
boostiniboost-propertytree

how to get properties within subsections of a ini file with boost property tree?


I am trying to use the Boost property trees to read INIfiles containing properties within sections have a "composed" path name.

For example my INIfile looks like this:

[my.section.subsection1]
someProp1=0

[my.section.subsection2]
anotherProp=1

I read it with the following code:

namespace pt = boost::property_tree;

pt::ptree propTree;
pt::read_ini(filePath, propTree);
boost::optional<uint32_t> someProp1 = pt.get_optional<uint32_t>("my.section.subsection1.someProp1");

The problem is that I never get the value of someProp1...

When I iterate over the first tree level I see the the entire section name my.section.subsection1 as a key. Is there a way to make the read_ini function to parse section names with dots as a tree hierarchy?


Solution

  • If you want the property tree to reflect the hierarchy, then it requires writing a custom parser. Per the INI parser documentation:

    INI is a simple key-value format with a single level of sectioning. [...] not all property trees can be serialized as INI files.

    Because of the single level sectioning, my.section.subsection1 must be treated as a key, rather than a hierarchy path. For example, the my.section.subsection1.someProp1 path could be broken down into:

               key    separator  value 
     .----------^---------. ^ .---^---.
    |my.section.subsection1|.|someProp1|
    

    Because "." is part of the key, the boost::property_tree::string_path type must be explicitly instantiated with a different separator. It is available as a path_type typedef on ptree. In this case, I have opted to use "/":

     ptree::path_type("my.section.subsection1/someProp1", '/')
    

    With example.ini containing:

    [my.section.subsection1]
    someProp1=0
    
    [my.section.subsection2]
    anotherProp=1
    

    The following program:

    #include <iostream>
    
    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/ini_parser.hpp>
    
    int main()
    {
      namespace pt = boost::property_tree;
      pt::ptree propTree;
    
      read_ini("example.ini", propTree);
    
      boost::optional<uint32_t> someProp1 = propTree.get_optional<uint32_t>(
        pt::ptree::path_type( "my.section.subsection1/someProp1", '/'));
      boost::optional<uint32_t> anotherProp = propTree.get_optional<uint32_t>(
        pt::ptree::path_type( "my.section.subsection2/anotherProp", '/'));
      std::cout << "someProp1 = " << *someProp1 
              << "\nanotherProp = " << *anotherProp
              << std::endl;
    }
    

    Produces the following output:

    someProp1 = 0
    anotherProp = 1