From 06e7243a62d4668883fc28d193030d175a6e9258 Mon Sep 17 00:00:00 2001 From: Brian Chrisman Date: Mon, 7 Jun 2021 17:57:57 -0700 Subject: [PATCH 1/7] handle xml writing of null keys boost::property_tree can have nulls as keys. In particular, json read typically generates child nodes with null keys as part of array processing. Place a nonce (3cb6534e-d358-4705-9e74-fee06453661e) as a unique tag name for null keys in write_xml. --- include/boost/property_tree/detail/xml_parser_write.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/property_tree/detail/xml_parser_write.hpp b/include/boost/property_tree/detail/xml_parser_write.hpp index f31825ee84..f41dfea8a1 100644 --- a/include/boost/property_tree/detail/xml_parser_write.hpp +++ b/include/boost/property_tree/detail/xml_parser_write.hpp @@ -72,6 +72,7 @@ namespace boost { namespace property_tree { namespace xml_parser typedef typename Ptree::key_type::value_type Ch; typedef typename Ptree::key_type Str; typedef typename Ptree::const_iterator It; + const char* nullkey = R"nullkey(nullkey-3cb6534e-d358-4705-9e74-fee06453661e)nullkey"; bool want_pretty = settings.indent_count > 0; // Find if elements present @@ -96,7 +97,7 @@ namespace boost { namespace property_tree { namespace xml_parser if (indent >= 0) { write_xml_indent(stream,indent,settings); - stream << Ch('<') << key << + stream << Ch('<') << (key.empty() ? nullkey : key) << Ch('/') << Ch('>'); if (want_pretty) stream << Ch('\n'); @@ -109,7 +110,7 @@ namespace boost { namespace property_tree { namespace xml_parser { // Write opening brace and key write_xml_indent(stream,indent,settings); - stream << Ch('<') << key; + stream << Ch('<') << (key.empty() ? nullkey : key); // Write attributes if (optional attribs = pt.get_child_optional(xmlattr())) @@ -167,7 +168,7 @@ namespace boost { namespace property_tree { namespace xml_parser { if (has_elements) write_xml_indent(stream,indent,settings); - stream << Ch('<') << Ch('/') << key << Ch('>'); + stream << Ch('<') << Ch('/') << (key.empty() ? nullkey : key) << Ch('>'); if (want_pretty) stream << Ch('\n'); } From e41d766e55aedb484fd82ee9276817197b65caae Mon Sep 17 00:00:00 2001 From: Brian Chrisman Date: Tue, 8 Jun 2021 08:41:52 -0700 Subject: [PATCH 2/7] Use literal expression compatible with c++03. --- include/boost/property_tree/detail/xml_parser_write.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/property_tree/detail/xml_parser_write.hpp b/include/boost/property_tree/detail/xml_parser_write.hpp index f41dfea8a1..0056734c90 100644 --- a/include/boost/property_tree/detail/xml_parser_write.hpp +++ b/include/boost/property_tree/detail/xml_parser_write.hpp @@ -72,7 +72,7 @@ namespace boost { namespace property_tree { namespace xml_parser typedef typename Ptree::key_type::value_type Ch; typedef typename Ptree::key_type Str; typedef typename Ptree::const_iterator It; - const char* nullkey = R"nullkey(nullkey-3cb6534e-d358-4705-9e74-fee06453661e)nullkey"; + const char* nullkey = "nullkey-3cb6534e-d358-4705-9e74-fee06453661e"; bool want_pretty = settings.indent_count > 0; // Find if elements present From fb975d8655180b6a84e9b39bc5bff8fb641f1b83 Mon Sep 17 00:00:00 2001 From: Brian Chrisman Date: Tue, 8 Jun 2021 17:25:21 -0700 Subject: [PATCH 3/7] nonce tag name demarcates null ptree key --- .../boost/property_tree/detail/xml_parser_read_rapidxml.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp b/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp index 9c04219189..cca6488dd6 100644 --- a/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp +++ b/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp @@ -31,7 +31,8 @@ namespace boost { namespace property_tree { namespace xml_parser case node_element: { // Create node - Ptree &pt_node = pt.push_back(std::make_pair(node->name(), + Ptree &pt_node = pt.push_back(std::make_pair( + (node->name() == "nullkey-3cb6534e-d358-4705-9e74-fee06453661e" ? "" : node->name()), Ptree()))->second; // Copy attributes From 7ede0d5ee1e2767b1fa0830c66196470f5da5a29 Mon Sep 17 00:00:00 2001 From: Brian Chrisman Date: Tue, 8 Jun 2021 17:25:42 -0700 Subject: [PATCH 4/7] test nullkey xml implementation --- test/test_xml_parser_common.hpp | 6 ++++++ test/xml_parser_test_data.hpp | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp index 019773bb65..5863c05cb6 100644 --- a/test/test_xml_parser_common.hpp +++ b/test/test_xml_parser_common.hpp @@ -107,6 +107,12 @@ void test_xml_parser() 3, umlautsize(), 12 ); + generic_parser_test_ok + ( + ReadFuncWS(), WriteFuncWS(), ok_data_6, NULL, + "testok6a.xml", NULL, "testok6aout.xml", 15, 23, 89 + ); + generic_parser_test_error ( ReadFuncWS(), WriteFuncWS(), error_data_1, NULL, diff --git a/test/xml_parser_test_data.hpp b/test/xml_parser_test_data.hpp index d0b4c071c0..453e8de3ab 100644 --- a/test/xml_parser_test_data.hpp +++ b/test/xml_parser_test_data.hpp @@ -747,6 +747,13 @@ const char ok_data_5[] = "\n" /*39 chars*/ "\xC3\xA4"; +const char *ok_data_6 = + "" + "" + "c" + "" + ""; + // Erroneous const char *error_data_1 = "a"; // bogus character From dfd8e6b4a31ade25c945048c247f7f3af4b9a330 Mon Sep 17 00:00:00 2001 From: Brian Chrisman Date: Tue, 8 Jun 2021 18:14:03 -0700 Subject: [PATCH 5/7] measured data counts with nullkey elision --- test/test_xml_parser_common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp index 5863c05cb6..a8ed8389f0 100644 --- a/test/test_xml_parser_common.hpp +++ b/test/test_xml_parser_common.hpp @@ -110,7 +110,7 @@ void test_xml_parser() generic_parser_test_ok ( ReadFuncWS(), WriteFuncWS(), ok_data_6, NULL, - "testok6a.xml", NULL, "testok6aout.xml", 15, 23, 89 + "testok6a.xml", NULL, "testok6aout.xml", 4, 1, 2 ); generic_parser_test_error From e9340807c20d1adb71b5496b6dc4a31f2d8f7d68 Mon Sep 17 00:00:00 2001 From: Brian Chrisman Date: Tue, 15 Jun 2021 14:08:20 -0700 Subject: [PATCH 6/7] align type of nullkey with key --- include/boost/property_tree/detail/xml_parser_write.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/property_tree/detail/xml_parser_write.hpp b/include/boost/property_tree/detail/xml_parser_write.hpp index 0056734c90..4d040a75b7 100644 --- a/include/boost/property_tree/detail/xml_parser_write.hpp +++ b/include/boost/property_tree/detail/xml_parser_write.hpp @@ -72,7 +72,7 @@ namespace boost { namespace property_tree { namespace xml_parser typedef typename Ptree::key_type::value_type Ch; typedef typename Ptree::key_type Str; typedef typename Ptree::const_iterator It; - const char* nullkey = "nullkey-3cb6534e-d358-4705-9e74-fee06453661e"; + const typename Ptree::key_type &nullkey = "nullkey-3cb6534e-d358-4705-9e74-fee06453661e"; bool want_pretty = settings.indent_count > 0; // Find if elements present From 871079ffd4afd97d44262ffa9a80bcb7040db5bf Mon Sep 17 00:00:00 2001 From: Brian Chrisman Date: Fri, 27 Aug 2021 22:49:35 -0700 Subject: [PATCH 7/7] cast const only for nullkey --- .../property_tree/detail/xml_parser_read_rapidxml.hpp | 6 ++++-- .../boost/property_tree/detail/xml_parser_write.hpp | 10 +++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp b/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp index cca6488dd6..269b57d006 100644 --- a/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp +++ b/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp @@ -32,8 +32,10 @@ namespace boost { namespace property_tree { namespace xml_parser { // Create node Ptree &pt_node = pt.push_back(std::make_pair( - (node->name() == "nullkey-3cb6534e-d358-4705-9e74-fee06453661e" ? "" : node->name()), - Ptree()))->second; + (node->name() == const_cast( + "nullkey-3cb6534e-d358-4705-9e74-fee06453661e") + ? const_cast("") : node->name()), + Ptree()))->second; // Copy attributes if (node->first_attribute()) diff --git a/include/boost/property_tree/detail/xml_parser_write.hpp b/include/boost/property_tree/detail/xml_parser_write.hpp index 4d040a75b7..49bc956593 100644 --- a/include/boost/property_tree/detail/xml_parser_write.hpp +++ b/include/boost/property_tree/detail/xml_parser_write.hpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -97,7 +98,8 @@ namespace boost { namespace property_tree { namespace xml_parser if (indent >= 0) { write_xml_indent(stream,indent,settings); - stream << Ch('<') << (key.empty() ? nullkey : key) << + stream << Ch('<') << (key.empty() ? + lexical_cast(nullkey) : key) << Ch('/') << Ch('>'); if (want_pretty) stream << Ch('\n'); @@ -110,7 +112,8 @@ namespace boost { namespace property_tree { namespace xml_parser { // Write opening brace and key write_xml_indent(stream,indent,settings); - stream << Ch('<') << (key.empty() ? nullkey : key); + stream << Ch('<') << (key.empty() ? + lexical_cast(nullkey) : key); // Write attributes if (optional attribs = pt.get_child_optional(xmlattr())) @@ -168,7 +171,8 @@ namespace boost { namespace property_tree { namespace xml_parser { if (has_elements) write_xml_indent(stream,indent,settings); - stream << Ch('<') << Ch('/') << (key.empty() ? nullkey : key) << Ch('>'); + stream << Ch('<') << Ch('/') << (key.empty() ? + lexical_cast(nullkey) : key) << Ch('>'); if (want_pretty) stream << Ch('\n'); }