Renato Garcia

Extensões para a biblioteca Boost Property Tree

Dentro de um projeto maior, estou usando a biblioteca Boost Property Tree como uma forma de ler os arquivos de configuração e passá-los para as classes. Por conta disso, acabei criando algumas extensões à biblioteca.

Abaixo descreverei um pouco das principais extensões, e todo o código pode ser encontrado aqui.

Assign

Suponha que se queira criar dentro do código C++ uma boost::ptree como:

key1 value1
key2
{
    key3 12345
    {
        key4 "value4 with spaces"
    }
    key5 value5
    "" 10
    "" 11
    "" 12
}
Text only

Usando somente os métodos da classe boost::basic_ptree, o código resultante seria algo como:

ptree pt;
pt.add("key1", "value1");

ptree tmpPt1;
tmpPt1.add("key3", 12345);

ptree tmpPt2;
tmpPt2.add("key4", "value4 with spaces");

tmpPt1.push_back(std::make_pair("", tmpPt2));
tmpPt1.add("key5", "value5");

ptree tmpPt3;
tmpPt3.put_value(10);
tmpPt1.push_back(std::make_pair("", tmpPt3));

ptree tmpPt4;
tmpPt4.put_value(11);
tmpPt1.push_back(std::make_pair("", tmpPt4));

ptree tmpPt5;
tmpPt5.put_value(12);
tmpPt1.push_back(std::make_pair("", tmpPt5));

pt.add_child("key2", tmpPt1);
C++

Um tanto quanto verboso. Uma alternativa legal seria usar alguma coisa como a biblioteca Boost Assign, e é isto que vem a ser esta extensão. Usando a classe tree, esta mesma boost::ptree poderia ser construída com o código:

ptree pt =
    tree()
    ("key1", "value1")
    ("key2", tree()
        ("key3", 12345)
        (tree()
            ("key4", "value4 with spaces"))
        ("key5", "value5")
        (10)(11)(12));
C++

Lua parser

Dependendo da complexidade dos arquivos de configuração, escrevê-los como um código Lua pode facilitar bastante as coisas. O que esta extensão permite é que um script Lua possa ser usado para construir uma boost::ptree. A ideia é que um código Lua:

function func(w)
    return "hello " .. w
end

root = {
    array = { 10, 11, 12, 13, 14, 15,},
    hi = func("world"),
    subtree = {
        one = 1,
        two = 2,
    },
}
Lua

Possa ser interpretado e carregado como uma boost::ptree usando:

ptree pt;
read_lua("test.lua", "root", pt);
C++

Python API

O projeto dentro do qual estas extensões foram criadas possui uma interface Python, e quase todas classes recebem no construtor uma boost::ptree como argumento. Então, foi necessário criar uma interface Python também para a biblioteca Boost Property Tree.

Particularmente, caso você esteja usando o SWIG para gerar a interface Python, o arquivo ptree.i contém todo o código para transparentemente converter uma boost::ptree em Python para C++. Caso contrário, a interface ainda pode ser usada, pois ela não foi construída usando o SWIG. No código Python, uma ptree seria construída e usada:

pt1 = (tree()
         ('key1', 1)
         ('key2', 2)
         ('subtree', tree()(1)(2)(3))
     ).ptree
pt2 = read_json('tree.json')
pt1.add('aaa', 'bbb')
print pt1
Python