Skip to content

Commit

Permalink
add printer for boost::property_tree::basic_ptree
Browse files Browse the repository at this point in the history
  • Loading branch information
randomphrase committed Apr 18, 2021
1 parent 60da4b4 commit 3deedb4
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions SUPPORTED.org
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
| =boost::wave::util::flex_string= | 1.71 | =wave_1_71= | yes | Jeff Trull | |
| =boost::wave::util::file_position= | " | " | yes | " | |
| =boost::wave::cpplexer::lex_token= | " | " | yes | " | |
| =boost::property_tree::ptree= | 1.42 | =multi_index_1_42= | yes | Alastair Rankine (randomphrase) | |

***** Notes

Expand Down
52 changes: 52 additions & 0 deletions boost/multi_index_1_42.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,55 @@ def to_string(self):
if self.empty_cont():
return 'empty %s' % self.type_name
return '%s' % self.type_name


@add_printer
class Boost_Property_Tree:
"Printer for boost::property_tree::basic_ptree"
printer_name = 'boost::property_tree'
min_supported_version = (1, 42, 0)
max_supported_version = last_supported_boost_version
template_name = 'boost::property_tree::basic_ptree'

def __init__(self, v):
self._value = v
subs_type = get_inner_type(self._value.type, "subs");
container_type = get_inner_type(subs_type, "base_container");
self._container_value_type = get_inner_type(container_type, "value_type");

container = v['m_children'].cast(container_type.pointer()).dereference()
self._node_count = container['node_count']
#message('node count: ' + str(self._node_count))

ptr_size = gdb.lookup_type('void').pointer().sizeof
elem_size = self._container_value_type.sizeof + (self._container_value_type.sizeof % ptr_size)
#message('elem_size: ' + str(elem_size))

header_holder_subtype = container_type.fields()[1].type
assert str(header_holder_subtype).strip().startswith('boost::multi_index::detail::header_holder')
head_node = container.cast(header_holder_subtype)['member'].dereference()
#message('head_node.type.sizeof: ' + str(head_node.type.sizeof))

self._index_offset = head_node.type.sizeof - 2 * ptr_size
#message('index_offset: ' + str(self._index_offset))
self._head_index_ptr = intptr(head_node.address) + self._index_offset
#message('head_index_ptr: ' + hex(self._head_index_ptr))

def children(self):
if not self._node_count:
return Boost_Multi_Index.empty_iterator()

get_next_ptr = Boost_Multi_Index.sequenced_iterator.get_next_ptr
node = get_next_ptr(self._head_index_ptr)
while node != self._head_index_ptr:
val_ptr = Boost_Multi_Index.get_val_ptr(node, self._index_offset)
val = parse_and_eval('*(' + str(self._container_value_type) + '*)' + str(val_ptr))
yield ('key', val["first"])
yield ('val', val["second"])
node = get_next_ptr(node)

def display_hint(self):
return 'map'

def to_string(self):
return self._value["m_data"]
15 changes: 15 additions & 0 deletions tests/testsuite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/property_tree/ptree.hpp>

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
Expand Down Expand Up @@ -994,6 +995,18 @@ void test_wave()

}

void test_property_tree()
{
boost::property_tree::ptree empty;
boost::property_tree::ptree pt;
pt.put_value("val");
pt.put("node_a", "val_a");
pt.put("node_a.sub_1", "val_a1");
pt.put("node_a.sub_2", "val_a2");

dummy_function();
}

int main()
{
test_iterator_range();
Expand Down Expand Up @@ -1037,5 +1050,7 @@ int main()

test_wave();

test_property_tree();

return EXIT_SUCCESS;
}
27 changes: 27 additions & 0 deletions tests/testsuite.py
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,33 @@ def test_token(self):
self.assertIsNone(children)
self.assertIsNone(display_hint)

class PropertyTreeTest(PrettyPrinterTest):
@classmethod
def setUpClass(cls):
execute_cpp_function('test_property_tree')

def test_empty(self):
string, children, display_hint = self.get_printer_result('empty')
self.assertEqual(string,'""')
self.assertEqual(children, [])

def test_pt(self):
string, children, display_hint = self.get_printer_result('pt')
self.assertEqual(string,'"val"')
def _to_str(val):
# FIXME: remove this dependency on the std::string pretty-printer
return gdb.default_visualizer(val).to_string().value().string('utf-8')
def _to_str_subtree(val):
# returns a tuple of (value, children)
v=gdb.default_visualizer(val)
return (_to_str(v.to_string()), as_map(list(v.children()), _to_str, _to_str_subtree))
self.assertEqual(as_map(children, _to_str, _to_str_subtree),
[("node_a", ("val_a", [
( "sub_1", ( "val_a1", [] )),
( "sub_2", ( "val_a2", [] ))
]))])
self.assertEqual(display_hint, 'map')


# TODO: More intrusive tests:
# 1. Non-raw pointers
Expand Down

0 comments on commit 3deedb4

Please sign in to comment.