C++ Boost Property Tree

Da Andreabont's Wiki.

Il property tree è una struttura dati fornita dalle librerie BOOST per memorizzare un albero di nodi chiave-valore destinato a contenere dei valori di configurazione. Questa struttura dati può essere facilmente salvata su disco in formato INI, INFO, XML o JSON.

Utilizzo come contenitore

Il property tree non è nient'altro che un un contenitore di std::pair che contengono una stringa nel primo slot, e un altro property tree o il valore finale nel secondo slot. Possiamo quindi dire che un nodo intermedio conterrà un altro albero, mentre i nodi foglia conterranno i nostri dati. Il contenitore fornisce dei metodi per l'accesso rapido ai valori sui nodi foglia, specificandone il path.

Inserimento e lettura di valori

boost::property_tree::ptree pt;
pt.put("path.pi", 3.14159);
double pi = pt.get<double>("path.pi"); // Da notare che devo fornire il tipo

Lettura di valori opzionali

Un particolare valore potrebbe non esistere, se fosse letto nel modo classico, la sua assenza provocherebbe un errore a run-time. Per evitarlo è possibile usare una lettura che tenga conto del fatto che il valore è opzionale.

boost::property_tree::ptree pt;
pt.put("path.pi", 3.14159);
boost::optional<double> pi_optional = pt.get_optional<double>("path.pi");

Iterare sui nodi

Poniamo di avere un file XML (più avanti si vedrà come compilare un property tree partendo da un file XML) di questo tipo:

<Path>
   <items>
      <value>ciao1</value>
      <value>ciao2</value>
      <value>ciao3</value>
   </items>
</Path>

E' possibile leggere tutti i valori contenuti in item iterando in questo modo:

for(auto i : pt.get_child("Path.items")) {
   std::string input = i.second.data();
   std::cout << "Input: " << input << std::endl;
}

Nel nostro caso andiamo a leggere direttamente lo std::pair del nodo foglia contenente il valore finale, è ovviamente possibile farlo anche con nodi intermedi.

Lettura da un file

File INI

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>

int main() {
    boost::property_tree::ptree pt;
    boost::property_tree::ini_parser::read_ini("config.ini", pt);
    std::string input = pt.get<std::string>("Path.value");
    std::cout << "Input: " << input << std::endl;
}

File XML

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

int main() {
    boost::property_tree::ptree pt;
    boost::property_tree::xml_parser::read_xml("config.xml", pt);
    std::string input = pt.get<std::string>("Path.value");
    std::cout << "Input: " << input << std::endl;
}

File JSON

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

int main() {
    boost::property_tree::ptree pt;
    boost::property_tree::json_parser::read_json("config.json", pt);
    std::string input = pt.get<std::string>("Path.value");
    std::cout << "Input: " << input << std::endl;
}

File INFO

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>

int main() {
    boost::property_tree::ptree pt;
    boost::property_tree::info_parser::read_info("config.info", pt);
    std::string input = pt.get<std::string>("Path.value");
    std::cout << "Input: " << input << std::endl;
}

Scrittura su un file

File INI

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>

int main() {
    boost::property_tree::ptree pt;
    pt.put("Path.value", "mio_valore");
    boost::property_tree::ini_parser::write_ini("config.ini", pt);
}

File XML

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

int main() {
    boost::property_tree::ptree pt;
    pt.put("Path.value", "mio_valore");
    boost::property_tree::ini_parser::write_xml("config.xml", pt);
}

File JSON

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

int main() {
    boost::property_tree::ptree pt;
    pt.put("Path.value", "mio_valore");
    boost::property_tree::ini_parser::write_json("config.json", pt);
}

File INFO

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>

int main() {
    boost::property_tree::ptree pt;
    pt.put("Path.value", "mio_valore");
    boost::property_tree::ini_parser::write_info("config.info", pt);
}