Reputation: 533
I have a config file like this, where properties1
can have 1 or more values:
[OBJECT]
properties1=val1, val2, val3
porperty2=Blah
property3=Blah
property4=Blah
porperty5=Bla bla bla
[OBJECT]
properties1=val1
porperty2=Blah
property3=Blah
property4=Blah
porperty5=Bla bla bla
And I am parsing it using boost::program_options
. However it does not work properly because for example properties1
gets stored into one vector, and so it is not possible to get a mapping between each OBJECT and its properties. So I think boost::property_map
might be a good solution. Here is the current solution:
namespace po = boost::program_options;
std::vector<std::string> properties1_all;
std::vector<std::string> property2_all;
std::vector<std::string> property3_all;
std::vector<std::string> property4_all;
std::vector<std::string> property5_all;
po::options_description desc;
desc.add_options()
("OBJECT.properties1",
po::value<std::vector<std::string> >(&properties1_all))
("OBJECT.property2",
po::value<std::vector<std::string> >(&property2_all))
("OBJECT.property3",
po::value<std::vector<std::string> >(&property3_all))
("OBJECT.property4",
po::value<std::vector<std::string> >(&property4_all))
("OBJECT.property5",
po::value<std::vector<std::string> >(&property5_all));
po::variables_map vm;
std::ifstream settings_file("config.ini", std::ifstream::in);
po::store(po::parse_config_file(settings_file, desc), vm);
settings_file.close();
po::notify(vm);
And my attempt with property map, but it does not seem to work... I think making each OBJECT a node and then an edge to 5 vertices, which are its properties, would be a good solution:
typedef adjacency_list<vecS, vecS, bidirectionalS,
no_property, property<edge_index_t, std::size_t> > Graph;
const int num_vertices = 5;
Graph G(num_vertices);
int propertyarray[] = { 1, 2, 3, 4, 5 };
int objectarray[] = { 1, 2, 3 };
// Add edges to the graph, and assign each edge an ID number.
add_edge(0, 1, 0, G);
// ...
typedef graph_traits<Graph>::edge_descriptor Edge;
typedef property_map<Graph, edge_index_t>::type EdgeID_Map;
EdgeID_Map edge_id = get(edge_index, G);
Upvotes: 1
Views: 1981
Reputation: 393789
You've got the library wrong. Property Map is a generic "lense"-like library for accessing (read/write) properties based on some kind of input parameter.
To add insult to injury the code sample is (obviously?) from Boost Graph, the mother library that Boost Propery Map was born from.
Now, you wanted Boost Property Tree. The samples are pretty easy to find, and here's one more:
#include <iostream>
#include <map>
#include <boost/property_tree/ini_parser.hpp>
static std::string const sample = R"(
[BLA]
properties1=val1, val2, val3
property2=Blah
property3=Blah
property4=Blah
property5=Bla bla bla
[BLO]
properties1=val1
property2=Blah
property3=Blah
property4=Blah
property5=Bla bla bla
)";
struct Object {
std::string properties1, property2, property3, property4, property5;
};
using boost::property_tree::ptree;
void read(ptree const& pt, std::string& s) {
s = pt.get_value(s);
}
void read(ptree const& pt, Object& object) {
read(pt.get_child("properties1"), object.properties1);
read(pt.get_child("property2"), object.property2);
read(pt.get_child("property3"), object.property3);
read(pt.get_child("property4"), object.property4);
read(pt.get_child("property5"), object.property5);
}
template <typename T>
T read_as(ptree const& pt) {
T v;
read(pt, v);
return v;
}
int main() {
std::istringstream iss(sample);
boost::property_tree::ptree config;
read_ini(iss, config);
std::map<std::string, Object> parsed;
for (auto& section : config) {
parsed[section.first] = read_as<Object>(section.second);
}
for (auto& object : parsed) {
std::cout << "Parsed object named " << object.first << " (e.g. property5 is '" << object.second.property5 << "')\n";
}
}
Printing:
Parsed object named BLA (e.g. property5 is 'Bla bla bla')
Parsed object named BLO (e.g. property5 is 'Bla bla bla')
Upvotes: 3