c++ - ¿Cómo fusiono/actualizo un boost:: property_tree:: ptree?
boost-propertytree (2)
Creo que tienes que recorrer recursivamente el property_tree.
Puede definir una función que itera recursivamente en cada nodo y llama a un método para cada nodo:
template<typename T>
void traverse_recursive(const boost::property_tree::ptree &parent, const boost::property_tree::ptree::path_type &childPath, const boost::property_tree::ptree &child, T &method)
{
using boost::property_tree::ptree;
method(parent, childPath, child);
for(ptree::const_iterator it=child.begin();it!=child.end();++it) {
ptree::path_type curPath = childPath / ptree::path_type(it->first);
traverse_recursive(parent, curPath, it->second, method);
}
}
Podemos definir una función más simple para llamar a la anterior:
template<typename T>
void traverse(const boost::property_tree::ptree &parent, T &method)
{
traverse_recursive(parent, "", parent, method);
}
Ahora puede modificar la clase A para agregar un método para fusionar solo un nodo y completar el método update_ptree:
#include <boost/bind.hpp>
class A {
ptree pt_;
public:
void set_ptree(const ptree &pt) {
pt_ = pt;
}
void update_ptree(const ptree &pt) {
using namespace boost;
traverse(pt, bind(&A::merge, this, _1, _2, _3));
}
ptree get_ptree() {
return pt_;
}
protected:
void merge(const ptree &parent, const ptree::path_type &childPath, const ptree &child) {
pt_.put(childPath, child.data());
}
};
La única limitación es que es posible tener varios nodos con la misma ruta. Cada uno de ellos sería utilizado, pero solo el último se fusionará.
He leído la documentación de boost :: property_tree y no he encontrado una manera de actualizar o fusionar un preeree con otro preeree. ¿Cómo hago esto?
Dado el siguiente código, ¿cómo se vería la función update_ptree?
#include <iostream>
#include <boost/property_tree/ptree.hpp>
using boost::property_tree::ptree;
class A
{
ptree pt_;
public:
void set_ptree(const ptree &pt)
{
pt_ = pt;
};
void update_ptree(const ptree &pt)
{
//How do I merge/update a ptree?
};
ptree get_ptree()
{
return pt_;
};
};
int main()
{
A a;
ptree pt;
pt.put<int>("first.number",0);
pt.put<int>("second.number",1);
pt.put<int>("third.number",2);
a.set_ptree(pt);
ptree pta = a.get_ptree();
//prints "0 1 2"
std::cout << pta.get<int>("first.number") << " "
<< pta.get<int>("second.number") << " "
<< pta.get<int>("third.number") << "/n";
ptree updates;
updates.put<int>("first.number",7);
a.update_ptree(updates);
pta = a.get_ptree();
//Because the update_tree function doesn''t do anything it just prints "0 1 2".
//I would like to see "7 1 2"
std::cout << pta.get<int>("first.number") << " "
<< pta.get<int>("second.number") << " "
<< pta.get<int>("third.number") << "/n";
return 0;
}
He pensado en iterar sobre el nuevo ptree y usar "put" para insertar valores. Pero "poner" requiere un tipo y no sé cómo obtener esa información del nuevo pree y usarlo como argumento para el antiguo pree.
Una cosa que he intentado en la función update_ptree es usar:
pt_.add_child(".",pt);
Básicamente trato de agregar pt como un niño a la raíz de pt_. Lamentablemente, esto no parece funcionar.
¿Algunas ideas?
Estoy agradecido por cualquier ayuda.
Gracias.
(Intenté agregar las etiquetas property_tree y pree a esta pregunta, pero no me fue permitido)
El árbol Boost.Property aún no es compatible con esto: boost.org/doc/libs/1_48_0/doc/html/property_tree/appendices.html . Mira la sección de trabajo futuro.
Relaciones matemáticas: diferencia libre, unión, intersección.
Una actualización es simplemente una diferencia seguida de una unión. a = (a - b) + b
.
La solución general requeriría un recorrido de actualización recurrente y poner cada hoja.
Sin embargo, una buena solución se puede construir con put_child
. Esto puede hacer todo lo que necesite, sin la complejidad de una solución general.
void merge( ptree& pt, const ptree& updates )
{
BOOST_FOREACH( auto& update, updates )
{
pt.put_child( update.first, update.second );
}
}
La solución lo suficientemente buena tiene dos limitaciones, por coincidencia son las mismas limitaciones que el ini_parser.
- el árbol solo puede tener dos capas (por ejemplo, "first.number", pero no "first.again.number")
- los valores solo se pueden almacenar en nodos hoja.