From 3deedb47a9bebd043a61900cdd912e92a68f414a Mon Sep 17 00:00:00 2001 From: Alastair Rankine Date: Sun, 18 Apr 2021 17:48:00 +1000 Subject: [PATCH] add printer for boost::property_tree::basic_ptree --- SUPPORTED.org | 1 + boost/multi_index_1_42.py | 52 +++++++++++++++++++++++++++++++++++++++ tests/testsuite.cpp | 15 +++++++++++ tests/testsuite.py | 27 ++++++++++++++++++++ 4 files changed, 95 insertions(+) diff --git a/SUPPORTED.org b/SUPPORTED.org index e54b204..a32c417 100644 --- a/SUPPORTED.org +++ b/SUPPORTED.org @@ -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 diff --git a/boost/multi_index_1_42.py b/boost/multi_index_1_42.py index deb5c26..e3eefa7 100644 --- a/boost/multi_index_1_42.py +++ b/boost/multi_index_1_42.py @@ -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"] diff --git a/tests/testsuite.cpp b/tests/testsuite.cpp index a3ea2ff..c0da8d9 100644 --- a/tests/testsuite.cpp +++ b/tests/testsuite.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -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(); @@ -1037,5 +1050,7 @@ int main() test_wave(); + test_property_tree(); + return EXIT_SUCCESS; } diff --git a/tests/testsuite.py b/tests/testsuite.py index 7c563ed..c3fcfdb 100644 --- a/tests/testsuite.py +++ b/tests/testsuite.py @@ -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