From 7adb2428e915e99470e5b86090bfe57988297f1b Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:07:19 +0000 Subject: [PATCH 01/23] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41369] --- examples/custom_data_type.cpp | 80 -- examples/debug_settings.cpp | 109 -- examples/debug_settings.xml | 10 - examples/empty_ptree_trick.cpp | 71 - examples/info_grammar_spirit.cpp | 152 -- examples/settings_fully-existent.info | 6 - examples/settings_non-existent.info | 6 - examples/settings_partially-existent.info | 6 - examples/speed_test.cpp | 134 -- index.html | 12 - test/Jamfile.v2 | 17 - test/custom-build/Makefile | 5 - test/custom-build/Makefile-Common | 80 -- test/custom-build/debug_settings.xml | 10 - test/custom-build/gcc.mak | 6 - test/custom-build/icc.mak | 6 - test/custom-build/sandbox.vcproj | 330 ----- .../custom-build/settings_fully-existent.info | 6 - test/custom-build/settings_non-existent.info | 6 - .../settings_partially-existent.info | 6 - .../test_example_custom_data_type.vcproj | 189 --- .../test_example_debug_settings.vcproj | 189 --- .../test_example_empty_ptree_trick.vcproj | 189 --- .../test_info_grammar_spirit.vcproj | 189 --- test/custom-build/test_info_parser.vcproj | 189 --- test/custom-build/test_ini_parser.vcproj | 189 --- test/custom-build/test_json_parser.vcproj | 189 --- test/custom-build/test_multi_module.vcproj | 193 --- test/custom-build/test_property_tree.vcproj | 194 --- test/custom-build/test_xml_parser.vcproj | 197 --- test/custom-build/tests.sln | 80 -- test/custom-build/vc.mak | 7 - test/sandbox.cpp | 13 - test/test_cmdline_parser.cpp | 116 -- test/test_info_parser.cpp | 249 ---- test/test_ini_parser.cpp | 198 --- test/test_json_parser.cpp | 384 ----- test/test_multi_module1.cpp | 21 - test/test_multi_module2.cpp | 18 - test/test_property_tree.cpp | 263 ---- test/test_property_tree.hpp | 1263 ----------------- test/test_registry_parser.cpp | 110 -- test/test_utils.hpp | 227 --- test/test_xml_parser_common.hpp | 79 -- test/test_xml_parser_pugxml.cpp | 25 - test/test_xml_parser_rapidxml.cpp | 23 - test/test_xml_parser_spirit.cpp | 24 - test/test_xml_parser_tinyxml.cpp | 26 - test/xml_parser_test_data.hpp | 743 ---------- 49 files changed, 6834 deletions(-) delete mode 100644 examples/custom_data_type.cpp delete mode 100644 examples/debug_settings.cpp delete mode 100644 examples/debug_settings.xml delete mode 100644 examples/empty_ptree_trick.cpp delete mode 100644 examples/info_grammar_spirit.cpp delete mode 100644 examples/settings_fully-existent.info delete mode 100644 examples/settings_non-existent.info delete mode 100644 examples/settings_partially-existent.info delete mode 100644 examples/speed_test.cpp delete mode 100644 index.html delete mode 100644 test/Jamfile.v2 delete mode 100644 test/custom-build/Makefile delete mode 100644 test/custom-build/Makefile-Common delete mode 100644 test/custom-build/debug_settings.xml delete mode 100644 test/custom-build/gcc.mak delete mode 100644 test/custom-build/icc.mak delete mode 100644 test/custom-build/sandbox.vcproj delete mode 100644 test/custom-build/settings_fully-existent.info delete mode 100644 test/custom-build/settings_non-existent.info delete mode 100644 test/custom-build/settings_partially-existent.info delete mode 100644 test/custom-build/test_example_custom_data_type.vcproj delete mode 100644 test/custom-build/test_example_debug_settings.vcproj delete mode 100644 test/custom-build/test_example_empty_ptree_trick.vcproj delete mode 100644 test/custom-build/test_info_grammar_spirit.vcproj delete mode 100644 test/custom-build/test_info_parser.vcproj delete mode 100644 test/custom-build/test_ini_parser.vcproj delete mode 100644 test/custom-build/test_json_parser.vcproj delete mode 100644 test/custom-build/test_multi_module.vcproj delete mode 100644 test/custom-build/test_property_tree.vcproj delete mode 100644 test/custom-build/test_xml_parser.vcproj delete mode 100644 test/custom-build/tests.sln delete mode 100644 test/custom-build/vc.mak delete mode 100644 test/sandbox.cpp delete mode 100644 test/test_cmdline_parser.cpp delete mode 100644 test/test_info_parser.cpp delete mode 100644 test/test_ini_parser.cpp delete mode 100644 test/test_json_parser.cpp delete mode 100644 test/test_multi_module1.cpp delete mode 100644 test/test_multi_module2.cpp delete mode 100644 test/test_property_tree.cpp delete mode 100644 test/test_property_tree.hpp delete mode 100644 test/test_registry_parser.cpp delete mode 100644 test/test_utils.hpp delete mode 100644 test/test_xml_parser_common.hpp delete mode 100644 test/test_xml_parser_pugxml.cpp delete mode 100644 test/test_xml_parser_rapidxml.cpp delete mode 100644 test/test_xml_parser_spirit.cpp delete mode 100644 test/test_xml_parser_tinyxml.cpp delete mode 100644 test/xml_parser_test_data.hpp diff --git a/examples/custom_data_type.cpp b/examples/custom_data_type.cpp deleted file mode 100644 index 86097e9aa4..0000000000 --- a/examples/custom_data_type.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -// This example shows what need to be done to customize data_type of ptree. -// -// It creates my_ptree type, which is a basic_ptree having boost::any as its data -// container (instead of std::string that standard ptree has). - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Custom translator that works with boost::any instead of std::string -struct my_translator -{ - - // Custom extractor - converts data from boost::any to T - template - bool get_value(const Ptree &pt, T &value) const - { - value = boost::any_cast(pt.data()); - return true; // Success - } - - // Custom inserter - converts data from T to boost::any - template - bool put_value(Ptree &pt, const T &value) const - { - pt.data() = value; - return true; - } - -}; - -int main() -{ - - using namespace boost::property_tree; - - // Property_tree with boost::any as data type - // Key comparison: std::less - // Key type: std::string - // Path type: path - // Data type: boost::any - // Translator type: my_translator - typedef basic_ptree, std::string, path, boost::any, my_translator> my_ptree; - my_ptree pt; - - // Put/get int value - pt.put("int value", 3); - int int_value = pt.get("int value"); - std::cout << "Int value: " << int_value << "\n"; - - // Put/get string value - pt.put("string value", "foo bar"); - std::string string_value = pt.get("string value"); - std::cout << "String value: " << string_value << "\n"; - - // Put/get list value - int list_data[] = { 1, 2, 3, 4, 5 }; - pt.put >("list value", std::list(list_data, list_data + sizeof(list_data) / sizeof(*list_data))); - std::list list_value = pt.get >("list value"); - std::cout << "List value: "; - for (std::list::iterator it = list_value.begin(); it != list_value.end(); ++it) - std::cout << *it << ' '; - std::cout << '\n'; -} diff --git a/examples/debug_settings.cpp b/examples/debug_settings.cpp deleted file mode 100644 index f7bcef74d8..0000000000 --- a/examples/debug_settings.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include -#include -//#include -#include -#include -#include -#include - -struct debug_settings -{ - std::string m_file; // log filename - int m_level; // debug level - std::set m_modules; // modules where logging is enabled - void load(const std::string &filename); - void save(const std::string &filename); -}; - -void debug_settings::load(const std::string &filename) -{ - - // Create empty property tree object - using boost::property_tree::ptree; - ptree pt; - - // Load XML file and put its contents in property tree. - // No namespace qualification is needed, because of Koenig - // lookup on the second argument. If reading fails, exception - // is thrown. - read_xml(filename, pt); - - // Get filename and store it in m_file variable. Note that - // we specify a path to the value using notation where keys - // are separated with dots (different separator may be used - // if keys themselves contain dots). If debug.filename key is - // not found, exception is thrown. - m_file = pt.get("debug.filename"); - - // Get debug level and store it in m_level variable. This is - // another version of get method: if debug.level key is not - // found, it will return default value (specified by second - // parameter) instead of throwing. Type of the value extracted - // is determined by type of second parameter, so we can simply - // write get(...) instead of get(...). - m_level = pt.get("debug.level", 0); - - // Iterate over debug.modules section and store all found - // modules in m_modules set. get_child() function returns a - // reference to child at specified path; if there is no such - // child, it throws. Property tree iterator can be used in - // the same way as standard container iterator. Category - // is bidirectional_iterator. - //BOOST_FOREACH(ptree::value_type &v, pt.get_child("debug.modules")) - // m_modules.insert(v.second.data()); - -} - -void debug_settings::save(const std::string &filename) -{ - - // Create empty property tree object - using boost::property_tree::ptree; - ptree pt; - - // Put log filename in property tree - pt.put("debug.filename", m_file); - - // Put debug level in property tree - pt.put("debug.level", m_level); - - // Iterate over modules in set and put them in property - // tree. Note that put function places new key at the - // end of list of keys. This is fine in most of the - // situations. If you want to place item at some other - // place (i.e. at front or somewhere in the middle), - // this can be achieved using combination of insert - // and put_value functions - //BOOST_FOREACH(const std::string &name, m_modules) - // pt.put("debug.modules.module", name, true); - - // Write property tree to XML file - write_xml(filename, pt); - -} - -int main() -{ - try - { - debug_settings ds; - ds.load("debug_settings.xml"); - ds.save("debug_settings_out.xml"); - std::cout << "Success\n"; - } - catch (std::exception &e) - { - std::cout << "Error: " << e.what() << "\n"; - } - return 0; -} diff --git a/examples/debug_settings.xml b/examples/debug_settings.xml deleted file mode 100644 index 9b8524a4c2..0000000000 --- a/examples/debug_settings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - debug.log - - Finance - Admin - HR - - 2 - diff --git a/examples/empty_ptree_trick.cpp b/examples/empty_ptree_trick.cpp deleted file mode 100644 index 37285b24a2..0000000000 --- a/examples/empty_ptree_trick.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include -#include -#include -#include -#include - -using namespace boost::property_tree; - -// Process settings using empty ptree trick. Note that it is considerably simpler -// than version which does not use the "trick" -void process_settings(const std::string &filename) -{ - ptree pt; - read_info(filename, pt); - const ptree &settings = pt.get_child("settings", empty_ptree()); - std::cout << "\n Processing " << filename << std::endl; - std::cout << " Setting 1 is " << settings.get("setting1", 0) << std::endl; - std::cout << " Setting 2 is " << settings.get("setting2", 0.0) << std::endl; - std::cout << " Setting 3 is " << settings.get("setting3", "default") << std::endl; -} - -// Process settings not using empty ptree trick. This one must duplicate much of the code. -void process_settings_without_trick(const std::string &filename) -{ - ptree pt; - read_info(filename, pt); - if (boost::optional settings = pt.get_child_optional("settings")) - { - std::cout << "\n Processing " << filename << std::endl; - std::cout << " Setting 1 is " << settings.get().get("setting1", 0) << std::endl; - std::cout << " Setting 2 is " << settings.get().get("setting2", 0.0) << std::endl; - std::cout << " Setting 3 is " << settings.get().get("setting3", "default") << std::endl; - } - else - { - std::cout << "\n Processing " << filename << std::endl; - std::cout << " Setting 1 is " << 0 << std::endl; - std::cout << " Setting 2 is " << 0.0 << std::endl; - std::cout << " Setting 3 is " << "default" << std::endl; - } -} - -int main() -{ - try - { - std::cout << "Processing settings with empty-ptree-trick:\n"; - process_settings("settings_fully-existent.info"); - process_settings("settings_partially-existent.info"); - process_settings("settings_non-existent.info"); - std::cout << "\nProcessing settings without empty-ptree-trick:\n"; - process_settings_without_trick("settings_fully-existent.info"); - process_settings_without_trick("settings_partially-existent.info"); - process_settings_without_trick("settings_non-existent.info"); - } - catch (std::exception &e) - { - std::cout << "Error: " << e.what() << "\n"; - } - return 0; -} diff --git a/examples/info_grammar_spirit.cpp b/examples/info_grammar_spirit.cpp deleted file mode 100644 index 07025341b6..0000000000 --- a/examples/info_grammar_spirit.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -/* This is grammar of INFO file format written in form of boost::spirit rules. - For simplicity, it does not parse #include directive. Note that INFO parser - included in property_tree library does not use Spirit. -*/ - -//#define BOOST_SPIRIT_DEBUG // uncomment to enable debug output -#include - -struct info_grammar: public boost::spirit::grammar -{ - - template - struct definition - { - - boost::spirit::rule::type> chr, qchr, escape_seq; - boost::spirit::rule string, qstring, cstring, key, value, entry, info; - - definition(const info_grammar &self) - { - - using namespace boost::spirit; - - escape_seq = chset_p("0abfnrtv\"\'\\"); - chr = (anychar_p - space_p - '\\' - '{' - '}' - '#' - '"') | ('\\' >> escape_seq); - qchr = (anychar_p - '"' - '\n' - '\\') | ('\\' >> escape_seq); - string = lexeme_d[+chr]; - qstring = lexeme_d['"' >> *qchr >> '"']; - cstring = lexeme_d['"' >> *qchr >> '"' >> '\\']; - key = string | qstring; - value = string | qstring | (+cstring >> qstring) | eps_p; - entry = key >> value >> !('{' >> *entry >> '}'); - info = *entry >> end_p; - - // Debug nodes - BOOST_SPIRIT_DEBUG_NODE(escape_seq); - BOOST_SPIRIT_DEBUG_NODE(chr); - BOOST_SPIRIT_DEBUG_NODE(qchr); - BOOST_SPIRIT_DEBUG_NODE(string); - BOOST_SPIRIT_DEBUG_NODE(qstring); - BOOST_SPIRIT_DEBUG_NODE(key); - BOOST_SPIRIT_DEBUG_NODE(value); - BOOST_SPIRIT_DEBUG_NODE(entry); - BOOST_SPIRIT_DEBUG_NODE(info); - - } - - const boost::spirit::rule &start() const - { - return info; - } - - }; -}; - -void info_parse(const char *s) -{ - - using namespace boost::spirit; - - // Parse and display result - info_grammar g; - parse_info pi = parse(s, g, space_p | comment_p(";")); - std::cout << "Parse result: " << (pi.hit ? "Success" : "Failure") << "\n"; - -} - -int main() -{ - - // Sample data 1 - const char *data1 = - "\n" - "key1 data1\n" - "{\n" - "\tkey data\n" - "}\n" - "key2 \"data2 \" {\n" - "\tkey data\n" - "}\n" - "key3 \"data\"\n" - "\t \"3\" {\n" - "\tkey data\n" - "}\n" - "\n" - "\"key4\" data4\n" - "{\n" - "\tkey data\n" - "}\n" - "\"key.5\" \"data.5\" { \n" - "\tkey data \n" - "}\n" - "\"key6\" \"data\"\n" - "\t \"6\" {\n" - "\tkey data\n" - "}\n" - " \n" - "key1 data1\n" - "{\n" - "\tkey data\n" - "}\n" - "key2 \"data2 \" {\n" - "\tkey data\n" - "}\n" - "key3 \"data\"\n" - "\t \"3\" {\n" - "\tkey data\n" - "}\n" - "\n" - "\"key4\" data4\n" - "{\n" - "\tkey data\n" - "}\n" - "\"key.5\" \"data.5\" {\n" - "\tkey data\n" - "}\n" - "\"key6\" \"data\"\n" - "\t \"6\" {\n" - "\tkey data\n" - "}\n" - "\\\\key\\t7 data7\\n\\\"data7\\\"\n" - "{\n" - "\tkey data\n" - "}\n" - "\"\\\\key\\t8\" \"data8\\n\\\"data8\\\"\"\n" - "{\n" - "\tkey data\n" - "}\n" - "\n"; - - // Sample data 2 - const char *data2 = - "key1\n" - "key2\n" - "key3\n" - "key4\n"; - - // Parse sample data - info_parse(data1); - info_parse(data2); - -} diff --git a/examples/settings_fully-existent.info b/examples/settings_fully-existent.info deleted file mode 100644 index bec7a64b3c..0000000000 --- a/examples/settings_fully-existent.info +++ /dev/null @@ -1,6 +0,0 @@ -settings -{ - setting1 15 - setting2 9.876 - setting3 Alice in Wonderland -} diff --git a/examples/settings_non-existent.info b/examples/settings_non-existent.info deleted file mode 100644 index 4f76b2a459..0000000000 --- a/examples/settings_non-existent.info +++ /dev/null @@ -1,6 +0,0 @@ -;settings // non-existent -;{ -; setting1 15 -; setting2 9.876 -; setting3 Alice in Wonderland -;} diff --git a/examples/settings_partially-existent.info b/examples/settings_partially-existent.info deleted file mode 100644 index ed5e8c225d..0000000000 --- a/examples/settings_partially-existent.info +++ /dev/null @@ -1,6 +0,0 @@ -settings -{ - setting1 15 - ;setting2 9.876 // non-existent - ;setting3 Alice in Wonderland // non-existent -} diff --git a/examples/speed_test.cpp b/examples/speed_test.cpp deleted file mode 100644 index 176b79e613..0000000000 --- a/examples/speed_test.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#define _HAS_ITERATOR_DEBUGGING 0 - -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace boost; -using namespace boost::property_tree; - -string dummy; -vector keys; -vector shuffled_keys; - -void prepare_keys(int size) -{ - // Prepare keys - keys.clear(); - for (int i = 0; i < size; ++i) - keys.push_back((format("%d") % i).str()); - shuffled_keys = keys; - srand(0); - random_shuffle(shuffled_keys.begin(), shuffled_keys.end()); -} - -void clock_push_back(int size) -{ - - prepare_keys(size); - int max_repeats = 1000000 / size; - shared_array pt_array(new ptree[max_repeats]); - - int n = 0; - clock_t t1 = clock(), t2; - do - { - if (n >= max_repeats) - break; - ptree &pt = pt_array[n]; - for (int i = 0; i < size; ++i) - pt.push_back(ptree::value_type(shuffled_keys[i], empty_ptree())); - t2 = clock(); - ++n; - } while (t2 - t1 < CLOCKS_PER_SEC); - - cout << " push_back (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n"; - -} - -void clock_find(int size) -{ - - prepare_keys(size); - - ptree pt; - for (int i = 0; i < size; ++i) - pt.push_back(ptree::value_type(keys[i], ptree("data"))); - - int n = 0; - clock_t t1 = clock(), t2; - do - { - for (int i = 0; i < size; ++i) - pt.find(shuffled_keys[i]); - t2 = clock(); - ++n; - } while (t2 - t1 < CLOCKS_PER_SEC); - - cout << " find (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n"; - -} - -void clock_erase(int size) -{ - - prepare_keys(size); - - int max_repeats = 100000 / size; - shared_array pt_array(new ptree[max_repeats]); - - ptree pt; - for (int n = 0; n < max_repeats; ++n) - for (int i = 0; i < size; ++i) - pt_array[n].push_back(ptree::value_type(keys[i], ptree("data"))); - - int n = 0; - clock_t t1 = clock(), t2; - do - { - if (n >= max_repeats) - break; - ptree &pt = pt_array[n]; - for (int i = 0; i < size; ++i) - pt.erase(shuffled_keys[i]); - t2 = clock(); - ++n; - } while (t2 - t1 < CLOCKS_PER_SEC); - - cout << " erase (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n"; - -} - -int main() -{ - - // push_back - clock_push_back(10); - clock_push_back(100); - clock_push_back(1000); - - // erase - clock_erase(10); - clock_erase(100); - clock_erase(1000); - - // find - clock_find(10); - clock_find(100); - clock_find(1000); - -} diff --git a/index.html b/index.html deleted file mode 100644 index 7974904d47..0000000000 --- a/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - -

- Docs for Property Tree library not available yet.

- - diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 deleted file mode 100644 index 2db2829295..0000000000 --- a/test/Jamfile.v2 +++ /dev/null @@ -1,17 +0,0 @@ -subproject libs/property_tree/test ; - -# bring in rules for testing -import testing ; - -# Make tests run by default. -DEPENDS all : property_tree ; - -{ - test-suite "property_tree" - : [ run test_property_tree.cpp ] - [ run test_info_parser.cpp ] - [ run test_json_parser.cpp ] - [ run test_ini_parser.cpp ] - [ run test_xml_parser_rapidxml.cpp ] - ; -} diff --git a/test/custom-build/Makefile b/test/custom-build/Makefile deleted file mode 100644 index e2dd24cff9..0000000000 --- a/test/custom-build/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -all: - -clean: - rm -f *_dbg.exe - rm -f *_rel.exe diff --git a/test/custom-build/Makefile-Common b/test/custom-build/Makefile-Common deleted file mode 100644 index fcf9f36d51..0000000000 --- a/test/custom-build/Makefile-Common +++ /dev/null @@ -1,80 +0,0 @@ -CCINCLUDE=-I../../../../../boost -I../../../.. - -all: test - --include Makefile - -test: build - ./ptree_dbg.exe - ./ptree_rel.exe - ./cmdline_dbg.exe - ./cmdline_rel.exe - ./ini_dbg.exe - ./ini_rel.exe - ./info_dbg.exe - ./info_rel.exe - ./json_dbg.exe - ./json_rel.exe - ./xml_dbg.exe - ./xml_rel.exe - ./multi_module_dbg.exe - ./multi_module_rel.exe - ./example_custom_data_type_dbg.exe - ./example_custom_data_type_rel.exe - ./example_debug_settings_dbg.exe - ./example_debug_settings_rel.exe - ./example_empty_ptree_trick_dbg.exe - ./example_empty_ptree_trick_rel.exe - ./example_info_grammar_spirit_dbg.exe - ./example_info_grammar_spirit_rel.exe - -build: debug release - -debug: ptree_dbg.exe cmdline_dbg.exe ini_dbg.exe info_dbg.exe json_dbg.exe xml_dbg.exe multi_module_dbg.exe example_custom_data_type_dbg.exe example_debug_settings_dbg.exe example_empty_ptree_trick_dbg.exe example_info_grammar_spirit_dbg.exe - -release: ptree_rel.exe cmdline_rel.exe ini_rel.exe info_rel.exe json_rel.exe xml_rel.exe multi_module_rel.exe example_custom_data_type_rel.exe example_debug_settings_rel.exe example_empty_ptree_trick_rel.exe example_info_grammar_spirit_rel.exe - -ptree_dbg.exe: ../test_property_tree.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -ptree_rel.exe: ../test_property_tree.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -cmdline_dbg.exe: ../test_cmdline_parser.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -cmdline_rel.exe: ../test_cmdline_parser.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -ini_dbg.exe: ../test_ini_parser.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -ini_rel.exe: ../test_ini_parser.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -info_dbg.exe: ../test_info_parser.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -info_rel.exe: ../test_info_parser.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -json_dbg.exe: ../test_json_parser.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -json_rel.exe: ../test_json_parser.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -xml_dbg.exe: ../test_xml_parser_spirit.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -xml_rel.exe: ../test_xml_parser_spirit.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -multi_module_dbg.exe: ../test_multi_module1.cpp ../test_multi_module2.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $? -o $@ $(EXTLIBS) -multi_module_rel.exe: ../test_multi_module1.cpp ../test_multi_module2.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $? -o $@ $(EXTLIBS) -example_custom_data_type_dbg.exe: ../../examples/custom_data_type.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -example_custom_data_type_rel.exe: ../../examples/custom_data_type.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -example_debug_settings_dbg.exe: ../../examples/debug_settings.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -example_debug_settings_rel.exe: ../../examples/debug_settings.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -example_empty_ptree_trick_dbg.exe: ../../examples/empty_ptree_trick.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -example_empty_ptree_trick_rel.exe: ../../examples/empty_ptree_trick.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -example_info_grammar_spirit_dbg.exe: ../../examples/info_grammar_spirit.cpp - $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) -example_info_grammar_spirit_rel.exe: ../../examples/info_grammar_spirit.cpp - $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) diff --git a/test/custom-build/debug_settings.xml b/test/custom-build/debug_settings.xml deleted file mode 100644 index 9b8524a4c2..0000000000 --- a/test/custom-build/debug_settings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - debug.log - - Finance - Admin - HR - - 2 - diff --git a/test/custom-build/gcc.mak b/test/custom-build/gcc.mak deleted file mode 100644 index bc2660b05f..0000000000 --- a/test/custom-build/gcc.mak +++ /dev/null @@ -1,6 +0,0 @@ -CC=g++ -CFLAGSREL=-Wall -pedantic -ftemplate-depth-255 -O3 -CFLAGSDBG=-Wall -pedantic -ftemplate-depth-255 -O0 -INCLUDE=-I../../../../../boost -I../../../.. - --include Makefile-Common diff --git a/test/custom-build/icc.mak b/test/custom-build/icc.mak deleted file mode 100644 index 98d9d948b3..0000000000 --- a/test/custom-build/icc.mak +++ /dev/null @@ -1,6 +0,0 @@ -CC=icc -CFLAGSREL=-O3 -static -CFLAGSDBG=-O0 -static -INCLUDE=-I../../../../../boost -I../../../.. - --include Makefile-Common diff --git a/test/custom-build/sandbox.vcproj b/test/custom-build/sandbox.vcproj deleted file mode 100644 index b7bbd5c2a1..0000000000 --- a/test/custom-build/sandbox.vcproj +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/settings_fully-existent.info b/test/custom-build/settings_fully-existent.info deleted file mode 100644 index bec7a64b3c..0000000000 --- a/test/custom-build/settings_fully-existent.info +++ /dev/null @@ -1,6 +0,0 @@ -settings -{ - setting1 15 - setting2 9.876 - setting3 Alice in Wonderland -} diff --git a/test/custom-build/settings_non-existent.info b/test/custom-build/settings_non-existent.info deleted file mode 100644 index 4f76b2a459..0000000000 --- a/test/custom-build/settings_non-existent.info +++ /dev/null @@ -1,6 +0,0 @@ -;settings // non-existent -;{ -; setting1 15 -; setting2 9.876 -; setting3 Alice in Wonderland -;} diff --git a/test/custom-build/settings_partially-existent.info b/test/custom-build/settings_partially-existent.info deleted file mode 100644 index ed5e8c225d..0000000000 --- a/test/custom-build/settings_partially-existent.info +++ /dev/null @@ -1,6 +0,0 @@ -settings -{ - setting1 15 - ;setting2 9.876 // non-existent - ;setting3 Alice in Wonderland // non-existent -} diff --git a/test/custom-build/test_example_custom_data_type.vcproj b/test/custom-build/test_example_custom_data_type.vcproj deleted file mode 100644 index e7f240ce2d..0000000000 --- a/test/custom-build/test_example_custom_data_type.vcproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_example_debug_settings.vcproj b/test/custom-build/test_example_debug_settings.vcproj deleted file mode 100644 index b91c196257..0000000000 --- a/test/custom-build/test_example_debug_settings.vcproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_example_empty_ptree_trick.vcproj b/test/custom-build/test_example_empty_ptree_trick.vcproj deleted file mode 100644 index 946c23ec22..0000000000 --- a/test/custom-build/test_example_empty_ptree_trick.vcproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_info_grammar_spirit.vcproj b/test/custom-build/test_info_grammar_spirit.vcproj deleted file mode 100644 index 9f02d63bff..0000000000 --- a/test/custom-build/test_info_grammar_spirit.vcproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_info_parser.vcproj b/test/custom-build/test_info_parser.vcproj deleted file mode 100644 index d490f80ed7..0000000000 --- a/test/custom-build/test_info_parser.vcproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_ini_parser.vcproj b/test/custom-build/test_ini_parser.vcproj deleted file mode 100644 index 1129c52209..0000000000 --- a/test/custom-build/test_ini_parser.vcproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_json_parser.vcproj b/test/custom-build/test_json_parser.vcproj deleted file mode 100644 index 6930190acd..0000000000 --- a/test/custom-build/test_json_parser.vcproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_multi_module.vcproj b/test/custom-build/test_multi_module.vcproj deleted file mode 100644 index 812bf501e9..0000000000 --- a/test/custom-build/test_multi_module.vcproj +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_property_tree.vcproj b/test/custom-build/test_property_tree.vcproj deleted file mode 100644 index 2ce8fd3cd4..0000000000 --- a/test/custom-build/test_property_tree.vcproj +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/test_xml_parser.vcproj b/test/custom-build/test_xml_parser.vcproj deleted file mode 100644 index bf0e110f4a..0000000000 --- a/test/custom-build/test_xml_parser.vcproj +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/custom-build/tests.sln b/test/custom-build/tests.sln deleted file mode 100644 index 6becf5bae6..0000000000 --- a/test/custom-build/tests.sln +++ /dev/null @@ -1,80 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_property_tree", "test_property_tree.vcproj", "{DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_ini_parser", "test_ini_parser.vcproj", "{20D5FE87-9284-4B1A-8505-7B913474C4AA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_info_parser", "test_info_parser.vcproj", "{03A81E3E-895A-4E1D-A42C-EB155A2868E1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_xml_parser", "test_xml_parser.vcproj", "{02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sandbox", "sandbox.vcproj", "{85FA9AEF-966B-4D93-9431-F507754B0431}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_json_parser", "test_json_parser.vcproj", "{CDDC4697-F51B-4B9A-A029-C2EB5271848F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_example_custom_data_type", "test_example_custom_data_type.vcproj", "{87516DC2-FDF4-4ECC-8713-D6D955100D86}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_example_debug_settings", "test_example_debug_settings.vcproj", "{16D41CBD-3C58-4631-B4D4-29A42E47D619}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_example_empty_ptree_trick", "test_example_empty_ptree_trick.vcproj", "{A242FE56-D039-4CEC-9FD3-AACABEA684C9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_info_grammar_spirit", "test_info_grammar_spirit.vcproj", "{305891FE-2572-4F6A-A52B-3A1964A3CA76}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_multi_module", "test_multi_module.vcproj", "{4B88BAC5-5CA8-403A-83E7-0F758405AB2D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}.Debug|Win32.ActiveCfg = Debug|Win32 - {DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}.Debug|Win32.Build.0 = Debug|Win32 - {DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}.Release|Win32.ActiveCfg = Release|Win32 - {DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}.Release|Win32.Build.0 = Release|Win32 - {20D5FE87-9284-4B1A-8505-7B913474C4AA}.Debug|Win32.ActiveCfg = Debug|Win32 - {20D5FE87-9284-4B1A-8505-7B913474C4AA}.Debug|Win32.Build.0 = Debug|Win32 - {20D5FE87-9284-4B1A-8505-7B913474C4AA}.Release|Win32.ActiveCfg = Release|Win32 - {20D5FE87-9284-4B1A-8505-7B913474C4AA}.Release|Win32.Build.0 = Release|Win32 - {03A81E3E-895A-4E1D-A42C-EB155A2868E1}.Debug|Win32.ActiveCfg = Debug|Win32 - {03A81E3E-895A-4E1D-A42C-EB155A2868E1}.Debug|Win32.Build.0 = Debug|Win32 - {03A81E3E-895A-4E1D-A42C-EB155A2868E1}.Release|Win32.ActiveCfg = Release|Win32 - {03A81E3E-895A-4E1D-A42C-EB155A2868E1}.Release|Win32.Build.0 = Release|Win32 - {02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}.Debug|Win32.ActiveCfg = Debug|Win32 - {02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}.Debug|Win32.Build.0 = Debug|Win32 - {02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}.Release|Win32.ActiveCfg = Release|Win32 - {02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}.Release|Win32.Build.0 = Release|Win32 - {85FA9AEF-966B-4D93-9431-F507754B0431}.Debug|Win32.ActiveCfg = Debug|Win32 - {85FA9AEF-966B-4D93-9431-F507754B0431}.Debug|Win32.Build.0 = Debug|Win32 - {85FA9AEF-966B-4D93-9431-F507754B0431}.Release|Win32.ActiveCfg = Release|Win32 - {85FA9AEF-966B-4D93-9431-F507754B0431}.Release|Win32.Build.0 = Release|Win32 - {CDDC4697-F51B-4B9A-A029-C2EB5271848F}.Debug|Win32.ActiveCfg = Debug|Win32 - {CDDC4697-F51B-4B9A-A029-C2EB5271848F}.Debug|Win32.Build.0 = Debug|Win32 - {CDDC4697-F51B-4B9A-A029-C2EB5271848F}.Release|Win32.ActiveCfg = Release|Win32 - {CDDC4697-F51B-4B9A-A029-C2EB5271848F}.Release|Win32.Build.0 = Release|Win32 - {87516DC2-FDF4-4ECC-8713-D6D955100D86}.Debug|Win32.ActiveCfg = Debug|Win32 - {87516DC2-FDF4-4ECC-8713-D6D955100D86}.Debug|Win32.Build.0 = Debug|Win32 - {87516DC2-FDF4-4ECC-8713-D6D955100D86}.Release|Win32.ActiveCfg = Release|Win32 - {87516DC2-FDF4-4ECC-8713-D6D955100D86}.Release|Win32.Build.0 = Release|Win32 - {16D41CBD-3C58-4631-B4D4-29A42E47D619}.Debug|Win32.ActiveCfg = Debug|Win32 - {16D41CBD-3C58-4631-B4D4-29A42E47D619}.Debug|Win32.Build.0 = Debug|Win32 - {16D41CBD-3C58-4631-B4D4-29A42E47D619}.Release|Win32.ActiveCfg = Release|Win32 - {16D41CBD-3C58-4631-B4D4-29A42E47D619}.Release|Win32.Build.0 = Release|Win32 - {A242FE56-D039-4CEC-9FD3-AACABEA684C9}.Debug|Win32.ActiveCfg = Debug|Win32 - {A242FE56-D039-4CEC-9FD3-AACABEA684C9}.Debug|Win32.Build.0 = Debug|Win32 - {A242FE56-D039-4CEC-9FD3-AACABEA684C9}.Release|Win32.ActiveCfg = Release|Win32 - {A242FE56-D039-4CEC-9FD3-AACABEA684C9}.Release|Win32.Build.0 = Release|Win32 - {305891FE-2572-4F6A-A52B-3A1964A3CA76}.Debug|Win32.ActiveCfg = Debug|Win32 - {305891FE-2572-4F6A-A52B-3A1964A3CA76}.Debug|Win32.Build.0 = Debug|Win32 - {305891FE-2572-4F6A-A52B-3A1964A3CA76}.Release|Win32.ActiveCfg = Release|Win32 - {305891FE-2572-4F6A-A52B-3A1964A3CA76}.Release|Win32.Build.0 = Release|Win32 - {4B88BAC5-5CA8-403A-83E7-0F758405AB2D}.Debug|Win32.ActiveCfg = Debug|Win32 - {4B88BAC5-5CA8-403A-83E7-0F758405AB2D}.Debug|Win32.Build.0 = Debug|Win32 - {4B88BAC5-5CA8-403A-83E7-0F758405AB2D}.Release|Win32.ActiveCfg = Release|Win32 - {4B88BAC5-5CA8-403A-83E7-0F758405AB2D}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/test/custom-build/vc.mak b/test/custom-build/vc.mak deleted file mode 100644 index 2ff7349a96..0000000000 --- a/test/custom-build/vc.mak +++ /dev/null @@ -1,7 +0,0 @@ -CC=cl -CFLAGSREL=-O2 -Ox -EHsc -DBOOST_DISABLE_WIN32 -nologo -CFLAGSDBG=-EHsc -DBOOST_DISABLE_WIN32 -nologo -EXTINCLUDE= -EXTLIBS= - --include Makefile-Common diff --git a/test/sandbox.cpp b/test/sandbox.cpp deleted file mode 100644 index 2c1c97e4ff..0000000000 --- a/test/sandbox.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#define _CRT_SECURE_NO_DEPRECATE -//#define BOOST_PROPERTY_TREE_XML_PARSER_PUGXML -#include -#include -#include - -int main() -{ - using namespace boost::property_tree; - ptree pt; - read_xml("simple_all.xml", pt); - write_info(std::cout, pt); -} diff --git a/test/test_cmdline_parser.cpp b/test/test_cmdline_parser.cpp deleted file mode 100644 index 03b5d46400..0000000000 --- a/test/test_cmdline_parser.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include "test_utils.hpp" -#include -#include -#include -#include - -namespace -{ - - // Test arguments - char *argv[] = - { - "c:\\program.exe", - "-Isrc/include1", - " file2.cc ", - "/L src/lib1", - "-Lsrc/lib2", - "/ooutput", - "file1.cc", - "-g", - "-", - "/", - " /Isrc/include2 ", - " file3.cc ", - "-I src/include3 " - }; - - // Test arguments count - const int argc = sizeof(argv) / sizeof(*argv); - -} - -template -void test_cmdline_parser() -{ - - using namespace boost::property_tree; - typedef typename Ptree::key_type::value_type Ch; - typedef std::basic_string Str; - - // Prepare arguments of proper char type - std::vector p; - std::vector strings; - strings.reserve(argc); - for (int i = 0; i < argc; ++i) - { - strings.push_back(detail::widen(argv[i])); - p.push_back(const_cast(strings.back().c_str())); - } - - Ptree pt1; - read_cmdline(argc, &p.front(), detail::widen("-/"), pt1); - - // Check indices - BOOST_CHECK(pt1.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib1")); - BOOST_CHECK(pt1.template get_optional(detail::widen("L.1")).get() == detail::widen("src/lib2")); - BOOST_CHECK(!pt1.template get_optional(detail::widen("L.2"))); - BOOST_CHECK(pt1.template get_optional(detail::widen(".0")).get() == detail::widen("c:\\program.exe")); - BOOST_CHECK(pt1.template get_optional(detail::widen(".1")).get() == detail::widen("file2.cc")); - BOOST_CHECK(pt1.template get_optional(detail::widen(".2")).get() == detail::widen("file1.cc")); - BOOST_CHECK(pt1.template get_optional(detail::widen(".3")).get() == detail::widen("file3.cc")); - BOOST_CHECK(!pt1.template get_optional(detail::widen(".4"))); - - // Check total sizes - //std::cerr << total_size(pt1) << " " << total_data_size(pt1) << " " << total_keys_size(pt1) << "\n"; - BOOST_CHECK(total_size(pt1) == 21); - BOOST_CHECK(total_data_size(pt1) == 130); - BOOST_CHECK(total_keys_size(pt1) == 19); - - Ptree pt2; - read_cmdline(argc, &p.front(), detail::widen("-"), pt2); - - // Check indices - BOOST_CHECK(pt2.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib2")); - BOOST_CHECK(!pt2.template get_optional(detail::widen("L.1"))); - - // Check total sizes - //std::cerr << total_size(pt2) << " " << total_data_size(pt2) << " " << total_keys_size(pt2) << "\n"; - BOOST_CHECK(total_size(pt2) == 19); - BOOST_CHECK(total_data_size(pt2) == 135); - BOOST_CHECK(total_keys_size(pt2) == 17); - - Ptree pt3; - read_cmdline(argc, &p.front(), detail::widen("/"), pt3); - - // Check indices - BOOST_CHECK(pt3.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib1")); - BOOST_CHECK(!pt3.template get_optional(detail::widen("L.1"))); - - // Check total sizes - //std::cerr << total_size(pt3) << " " << total_data_size(pt3) << " " << total_keys_size(pt3) << "\n"; - BOOST_CHECK(total_size(pt3) == 19); - BOOST_CHECK(total_data_size(pt3) == 149); - BOOST_CHECK(total_keys_size(pt3) == 17); - -} - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_cmdline_parser(); -#ifndef BOOST_NO_CWCHAR - test_cmdline_parser(); -#endif - return 0; -} diff --git a/test/test_info_parser.cpp b/test/test_info_parser.cpp deleted file mode 100644 index 3c28a077c6..0000000000 --- a/test/test_info_parser.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include "test_utils.hpp" -#include - -/////////////////////////////////////////////////////////////////////////////// -// Test data - -const char *ok_data_1 = - ";Test file for info_parser\n" - "\n" - "key1 data1\n" - "{\n" - "\tkey data\n" - "}\n" - "#include \"testok1_inc.info\"\n" - "key2 \"data2 \" {\n" - "\tkey data\n" - "}\n" - "#\tinclude \"testok1_inc.info\"\n" - "key3 \"data\"\n" - "\t \"3\" {\n" - "\tkey data\n" - "}\n" - "\t#include \"testok1_inc.info\"\n" - "\n" - "\"key4\" data4\n" - "{\n" - "\tkey data\n" - "}\n" - "#include \"testok1_inc.info\"\n" - "\"key.5\" \"data.5\" { \n" - "\tkey data \n" - "}\n" - "#\tinclude \"testok1_inc.info\"\n" - "\"key6\" \"data\"\n" - "\t \"6\" {\n" - "\tkey data\n" - "}\n" - "\t#include \"testok1_inc.info\"\n" - " \n" - "key1 data1; comment\n" - "{; comment\n" - "\tkey data; comment\n" - "}; comment\n" - "#include \"testok1_inc.info\"\n" - "key2 \"data2 \" {; comment\n" - "\tkey data; comment\n" - "}; comment\n" - "#\tinclude \"testok1_inc.info\"\n" - "key3 \"data\"; comment\n" - "\t \"3\" {; comment\n" - "\tkey data; comment\n" - "}; comment\n" - "\t#include \"testok1_inc.info\"\n" - "\n" - "\"key4\" data4; comment\n" - "{; comment\n" - "\tkey data; comment\n" - "}; comment\n" - "#include \"testok1_inc.info\"\n" - "\"key.5\" \"data.5\" {; comment\n" - "\tkey data; comment\n" - "}; comment\n" - "#\tinclude \"testok1_inc.info\"\n" - "\"key6\" \"data\"; comment\n" - "\t \"6\" {; comment\n" - "\tkey data; comment\n" - "}; comment\n" - "\t#include \"testok1_inc.info\"\n" - "\\\\key\\t7 data7\\n\\\"data7\\\"\n" - "{\n" - "\tkey data\n" - "}\n" - "\"\\\\key\\t8\" \"data8\\n\\\"data8\\\"\"\n" - "{\n" - "\tkey data\n" - "}\n" - "\n"; - -const char *ok_data_1_inc = - ";Test file for info_parser\n" - "\n" - "inc_key inc_data ;;; comment\\"; - -const char *ok_data_2 = - ""; - -const char *ok_data_3 = - "key1 \"\"\n" - "key2 \"\"\n" - "key3 \"\"\n" - "key4 \"\"\n"; - -const char *ok_data_4 = - "key1 data key2 data"; - -const char *ok_data_5 = - "key { key \"\" key \"\" }\n"; - -const char *ok_data_6 = - "\"key with spaces\" \"data with spaces\"\n" - "\"key with spaces\" \"multiline data\"\\\n" - "\"cont\"\\\n" - "\"cont\""; - -const char *error_data_1 = - ";Test file for info_parser\n" - "#include \"bogus_file\"\n"; // Nonexistent include file - -const char *error_data_2 = - ";Test file for info_parser\n" - "key \"data with bad escape: \\q\"\n"; // Bad escape - -const char *error_data_3 = - ";Test file for info_parser\n" - "{\n"; // Opening brace without key - -const char *error_data_4 = - ";Test file for info_parser\n" - "}\n"; // Closing brace without opening brace - -const char *error_data_5 = - ";Test file for info_parser\n" - "key data\n" - "{\n" - ""; // No closing brace - -struct ReadFunc -{ - template - void operator()(const std::string &filename, Ptree &pt) const - { - boost::property_tree::read_info(filename, pt); - } -}; - -struct WriteFunc -{ - template - void operator()(const std::string &filename, const Ptree &pt) const - { - boost::property_tree::write_info(filename, pt); - } -}; - -template -void test_info_parser() -{ - - using namespace boost::property_tree; - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_1, ok_data_1_inc, - "testok1.info", "testok1_inc.info", "testok1out.info", 45, 240, 192 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_2, NULL, - "testok2.info", NULL, "testok2out.info", 1, 0, 0 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_3, NULL, - "testok3.info", NULL, "testok3out.info", 5, 0, 16 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_4, NULL, - "testok4.info", NULL, "testok4out.info", 3, 8, 8 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_5, NULL, - "testok5.info", NULL, "testok5out.info", 4, 0, 9 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_6, NULL, - "testok6.info", NULL, "testok6out.info", 3, 38, 30 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_1, NULL, - "testerr1.info", NULL, "testerr1out.info", 2 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_2, NULL, - "testerr2.info", NULL, "testerr2out.info", 2 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_3, NULL, - "testerr3.info", NULL, "testerr3out.info", 2 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_4, NULL, - "testerr4.info", NULL, "testerr4out.info", 2 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_5, NULL, - "testerr5.info", NULL, "testerr5out.info", 4 - ); - - // Test read with default ptree - { - Ptree pt, default_pt; - pt.put_value(1); - default_pt.put_value(2); - BOOST_CHECK(pt != default_pt); - read_info("nonexisting file.nonexisting file", pt, default_pt); - BOOST_CHECK(pt == default_pt); - } - -} - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_info_parser(); - test_info_parser(); -#ifndef BOOST_NO_CWCHAR - test_info_parser(); - test_info_parser(); -#endif - return 0; -} diff --git a/test/test_ini_parser.cpp b/test/test_ini_parser.cpp deleted file mode 100644 index 36c5ba22f6..0000000000 --- a/test/test_ini_parser.cpp +++ /dev/null @@ -1,198 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include "test_utils.hpp" -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// Test data - -// Correct data -const char *ok_data_1 = - "\n" - "; Comment\n" - "[Section1]\n" - "\t \t; Comment\n" - " Key1=Data1\n" - " \n" - " Key2 = Data2\n" - "Key 3 = Data 3 \n" - "Key4=Data4\n" - "[Section2] ;Comment\n" - "\t \t; Comment\n" - " \t [ Section 3 ];Comment \n"; - -// Correct data -const char *ok_data_2 = - "[Section1]\n" - "Key1=Data1"; // No eol - -// Correct data -const char *ok_data_3 = - ""; - -// Correct data -const char *ok_data_4 = - ";Comment"; - -// Erroneous data -const char *error_data_1 = - "[Section1]\n" - "Key1\n" // No equals sign - "Key2=Data2"; - -// Erroneous data -const char *error_data_2 = - "Key1=Data1\n" // No section - "Key2=Data2\n"; - -// Erroneous data -const char *error_data_3 = - "[Section1]\n" - "Key1=Data1\n" - "=Data2\n"; // No key - -struct ReadFunc -{ - template - void operator()(const std::string &filename, Ptree &pt) const - { - boost::property_tree::read_ini(filename, pt); - } -}; - -struct WriteFunc -{ - template - void operator()(const std::string &filename, const Ptree &pt) const - { - boost::property_tree::write_ini(filename, pt); - } -}; - -void test_erroneous_write(const boost::property_tree::ptree &pt) -{ - using namespace boost::property_tree; - std::stringstream stream; - try - { - write_ini(stream, pt); - BOOST_ERROR("No required exception thrown"); - } - catch (ini_parser_error &e) - { - (void)e; - } - catch (...) - { - BOOST_ERROR("Wrong exception type thrown"); - } -} - -template -void test_ini_parser() -{ - - using namespace boost::property_tree; - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_1, NULL, - "testok1.ini", NULL, "testok1out.ini", 8, 21, 42 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_2, NULL, - "testok2.ini", NULL, "testok2out.ini", 3, 5, 12 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_3, NULL, - "testok3.ini", NULL, "testok3out.ini", 1, 0, 0 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_4, NULL, - "testok4.ini", NULL, "testok4out.ini", 1, 0, 0 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_1, NULL, - "testerr1.ini", NULL, "testerr1out.ini", 2 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_2, NULL, - "testerr2.ini", NULL, "testerr2out.ini", 1 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_3, NULL, - "testerr3.ini", NULL, "testerr3out.ini", 3 - ); - -} - -int test_main(int argc, char *argv[]) -{ - - using namespace boost::property_tree; - - test_ini_parser(); - test_ini_parser(); -#ifndef BOOST_NO_CWCHAR - test_ini_parser(); - test_ini_parser(); -#endif - - /////////////////////////////////////////////////////////////////////////// - // Too rich property tree tests - - // Test too deep ptrees - { - ptree pt; - pt.put_child("section.key.bogus", empty_ptree()); - test_erroneous_write(pt); - } - - // Test data in sections - { - ptree pt; - pt.put("section", 1); - test_erroneous_write(pt); - } - - // Test duplicate sections - { - ptree pt; - pt.push_back(std::make_pair("section", ptree())); - pt.push_back(std::make_pair("section", ptree())); - test_erroneous_write(pt); - } - - // Test duplicate keys - { - ptree pt; - ptree &child = pt.put_child("section", empty_ptree()); - child.push_back(std::make_pair("key", ptree())); - child.push_back(std::make_pair("key", ptree())); - test_erroneous_write(pt); - } - - return 0; - -} diff --git a/test/test_json_parser.cpp b/test/test_json_parser.cpp deleted file mode 100644 index c41917d935..0000000000 --- a/test/test_json_parser.cpp +++ /dev/null @@ -1,384 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include "test_utils.hpp" -#include - -/////////////////////////////////////////////////////////////////////////////// -// Test data - -const char *ok_data_1 = - "{}"; - -const char *ok_data_2 = - " \t {\n" - " \t \"name 0\" : \"value\", \t // comment \n" - " \t \"name 1\" : \"\", // comment \n" - " \t \"name 2\" : true, // comment \n" - " \t \"name 3\" : false, // comment \n" - " \t \"name 4\" : null, // comment \n" - " \t \"name 5\" : 0, // comment \n" - " \t \"name 6\" : -5, // comment \n" - " \t \"name 7\" : 1.1, // comment \n" - " \t \"name 8\" : -956.45e+4, // comment \n" - " \t \"name 8\" : 5956.45E-11, // comment \n" - " \t \"name 9\" : [1,2,3,4], // comment \n" - " \t \"name 10\" : {\"a\":\"b\"} // comment \n" - " \t } // comment \n"; - -const char *ok_data_3 = - "{\"a\":{\"b\":\"c\"}}"; - -const char *ok_data_4 = - "{\"a\":[{\"b\":\"c\"},{\"d\":\"e\"},1,2,3,4],\"f\":null}"; - -const char *ok_data_5 = - "{/* \n\n//{}//{}{\n{//\n}//{}{\n */}"; - -const char *ok_data_6 = - "{\"menu\": {\n" - " \"header\": \"SVG Viewer\",\n" - " \"items\": [\n" - " {\"id\": \"Open\"},\n" - " {\"id\": \"OpenNew\", \"label\": \"Open New\"},\n" - " null,\n" - " {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},\n" - " {\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},\n" - " {\"id\": \"OriginalView\", \"label\": \"Original View\"},\n" - " null,\n" - " {\"id\": \"Quality\"},\n" - " {\"id\": \"Pause\"},\n" - " {\"id\": \"Mute\"},\n" - " null,\n" - " {\"id\": \"Find\", \"label\": \"Find...\"},\n" - " {\"id\": \"FindAgain\", \"label\": \"Find Again\"},\n" - " {\"id\": \"Copy\"},\n" - " {\"id\": \"CopyAgain\", \"label\": \"Copy Again\"},\n" - " {\"id\": \"CopySVG\", \"label\": \"Copy SVG\"},\n" - " {\"id\": \"ViewSVG\", \"label\": \"View SVG\"},\n" - " {\"id\": \"ViewSource\", \"label\": \"View Source\"},\n" - " {\"id\": \"SaveAs\", \"label\": \"Save As\"},\n" - " null,\n" - " {\"id\": \"Help\"},\n" - " {\"id\": \"About\", \"label\": \"About Adobe CVG Viewer...\"}\n" - " ]\n" - "}}\n"; - -const char *ok_data_7 = - "{\"web-app\": {\n" - " \"servlet\": [ // Defines the CDSServlet\n" - " {\n" - " \"servlet-name\": \"cofaxCDS\",\n" - " \"servlet-class\": \"org.cofax.cds.CDSServlet\",\n" - " \"init-param\": {\n" - " \"configGlossary:installationAt\": \"Philadelphia, PA\",\n" - " \"configGlossary:adminEmail\": \"ksm@pobox.com\",\n" - " \"configGlossary:poweredBy\": \"Cofax\",\n" - " \"configGlossary:poweredByIcon\": \"/images/cofax.gif\",\n" - " \"configGlossary:staticPath\": \"/content/static\",\n" - " \"templateProcessorClass\": \"org.cofax.WysiwygTemplate\",\n" - " \"templateLoaderClass\": \"org.cofax.FilesTemplateLoader\",\n" - " \"templatePath\": \"templates\",\n" - " \"templateOverridePath\": \"\",\n" - " \"defaultListTemplate\": \"listTemplate.htm\",\n" - " \"defaultFileTemplate\": \"articleTemplate.htm\",\n" - " \"useJSP\": false,\n" - " \"jspListTemplate\": \"listTemplate.jsp\",\n" - " \"jspFileTemplate\": \"articleTemplate.jsp\",\n" - " \"cachePackageTagsTrack\": 200,\n" - " \"cachePackageTagsStore\": 200,\n" - " \"cachePackageTagsRefresh\": 60,\n" - " \"cacheTemplatesTrack\": 100,\n" - " \"cacheTemplatesStore\": 50,\n" - " \"cacheTemplatesRefresh\": 15,\n" - " \"cachePagesTrack\": 200,\n" - " \"cachePagesStore\": 100,\n" - " \"cachePagesRefresh\": 10,\n" - " \"cachePagesDirtyRead\": 10,\n" - " \"searchEngineListTemplate\": \"forSearchEnginesList.htm\",\n" - " \"searchEngineFileTemplate\": \"forSearchEngines.htm\",\n" - " \"searchEngineRobotsDb\": \"WEB-INF/robots.db\",\n" - " \"useDataStore\": true,\n" - " \"dataStoreClass\": \"org.cofax.SqlDataStore\",\n" - " \"redirectionClass\": \"org.cofax.SqlRedirection\",\n" - " \"dataStoreName\": \"cofax\",\n" - " \"dataStoreDriver\": \"com.microsoft.jdbc.sqlserver.SQLServerDriver\",\n" - " \"dataStoreUrl\": \"jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon\",\n" - " \"dataStoreUser\": \"sa\",\n" - " \"dataStorePassword\": \"dataStoreTestQuery\",\n" - " \"dataStoreTestQuery\": \"SET NOCOUNT ON;select test='test';\",\n" - " \"dataStoreLogFile\": \"/usr/local/tomcat/logs/datastore.log\",\n" - " \"dataStoreInitConns\": 10,\n" - " \"dataStoreMaxConns\": 100,\n" - " \"dataStoreConnUsageLimit\": 100,\n" - " \"dataStoreLogLevel\": \"debug\",\n" - " \"maxUrlLength\": 500}},\n" - " {\n" - " \"servlet-name\": \"cofaxEmail\",\n" - "\n \"servlet-class\": \"org.cofax.cds.EmailServlet\",\n" - " \"init-param\": {\n" - " \"mailHost\": \"mail1\",\n" - " \"mailHostOverride\": \"mail2\"}},\n" - " {\n" - " \"servlet-name\": \"cofaxAdmin\",\n" - " \"servlet-class\": \"org.cofax.cds.AdminServlet\"},\n" - " \n" - " {\n" - " \"servlet-name\": \"fileServlet\",\n" - " \"servlet-class\": \"org.cofax.cds.FileServlet\"},\n" - " {\n" - " \"servlet-name\": \"cofaxTools\",\n" - " \"servlet-class\": \"org.cofax.cms.CofaxToolsServlet\",\n" - " \"init-param\": {\n" - " \"templatePath\": \"toolstemplates/\",\n" - " \"log\": 1,\n" - " \"logLocation\": \"/usr/local/tomcat/logs/CofaxTools.log\",\n" - " \"logMaxSize\": \"\",\n" - " \"dataLog\": 1,\n" - " \"dataLogLocation\": \"/usr/local/tomcat/logs/dataLog.log\",\n" - " \"dataLogMaxSize\": \"\",\n" - " \"removePageCache\": \"/content/admin/remove?cache=pages&id=\",\n" - " \"removeTemplateCache\": \"/content/admin/remove?cache=templates&id=\",\n" - " \"fileTransferFolder\": \"/usr/local/tomcat/webapps/content/fileTransferFolder\",\n" - " \"lookInContext\": 1,\n" - " \"adminGroupID\": 4,\n" - " \"betaServer\": true}}],\n" - " \"servlet-mapping\": {\n" - " \"cofaxCDS\": \"/\",\n" - " \"cofaxEmail\": \"/cofaxutil/aemail/*\",\n" - " \"cofaxAdmin\": \"/admin/*\",\n" - " \"fileServlet\": \"/static/*\",\n" - " \"cofaxTools\": \"/tools/*\"},\n" - " \n" - " \"taglib\": {\n" - " \"taglib-uri\": \"cofax.tld\",\n" - " \"taglib-location\": \"/WEB-INF/tlds/cofax.tld\"}}}\n"; - -const char *ok_data_8 = - "{\"widget\": {\n" - " \"debug\": \"on\",\n" - " \"window\": {\n" - " \"title\": \"Sample Konfabulator Widget\", \"name\": \"main_window\", \"width\": 500, \"height\": 500\n" - " }, \"image\": { \n" - " \"src\": \"Images/Sun.png\",\n" - " \"name\": \"sun1\", \"hOffset\": 250, \"vOffset\": 250, \"alignment\": \"center\"\n" - " }, \"text\": {\n" - " \"data\": \"Click Here\",\n" - " \"size\": 36,\n" - " \"style\": \"bold\", \"name\": \"text1\", \"hOffset\": 250, \"vOffset\": 100, \"alignment\": \"center\",\n" - " \"onMouseUp\": \"sun1.opacity = (sun1.opacity / 100) * 90;\"\n" - " }\n" - "}} \n"; - -const char *ok_data_9 = - "{\"menu\": {\n" - " \"id\": \"file\",\n" - " \"value\": \"File:\",\n" - " \"popup\": {\n" - " \"menuitem\": [\n" - " {\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},\n" - " {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},\n" - "\n {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}\n" - " ]\n" - " }\n" - "}}\n"; - -const char *ok_data_10 = - "{\n" - " \"glossary\": {\n" - " \"title\": \"example glossary\",\n" - " \"GlossDiv\": {\n" - " \"title\": \"S\",\n" - " \"GlossList\": [{\n" - " \"ID\": \"SGML\",\n" - " \"SortAs\": \"SGML\",\n" - " \"GlossTerm\": \"Standard Generalized Markup Language\",\n" - " \"Acronym\": \"SGML\",\n" - " \"Abbrev\": \"ISO 8879:1986\",\n" - " \"GlossDef\": \n" - "\"A meta-markup language, used to create markup languages such as DocBook.\",\n" - " \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"]\n" - " }]\n" - " }\n" - " }\n" - "}\n"; - -const char *ok_data_11 = - "{\n" - " \"data\" : [\n" - " {\n" - " \"First Name\" : \"Bob\",\n" - " \"Last Name\" : \"Smith\",\n" - " \"Email\" : \"bsmith@someurl.com\",\n" - " \"Phone\" : \"(555) 555-1212\"\n" - " },\n" - " {\n" - " \"First Name\" : \"Jan\",\n" - " \"Last Name\" : \"Smith\",\n" - " \"Email\" : \"jsmith@someurl.com\",\n" - " \"Phone\" : \"(555) 555-3434\"\n" - " },\n" - " {\n" - " \"First Name\" : \"Sue\",\n" - " \"Last Name\" : \"Smith\",\n" - " \"Email\" : \"ssmith@someurl.com\",\n" - " \"Phone\" : \"(555) 555-5656\"\n" - " }\n" - " ]\n" - "}\n"; - -const char *ok_data_12 = - "{\" \\\" \\\\ \\0 \\b \\f \\n \\r \\t \" : \"multi\" \"-\" \"string\"}"; - -const char *error_data_1 = - ""; // No root object - -const char *error_data_2 = - "{\n\"a\":1\n"; // Unclosed object brace - -const char *error_data_3 = - "{\n\"a\":\n[1,2,3,4\n}"; // Unclosed array brace - -const char *error_data_4 = - "{\n\"a\"\n}"; // No object - -struct ReadFunc -{ - template - void operator()(const std::string &filename, Ptree &pt) const - { - boost::property_tree::read_json(filename, pt); - } -}; - -struct WriteFunc -{ - template - void operator()(const std::string &filename, const Ptree &pt) const - { - boost::property_tree::write_json(filename, pt); - } -}; - -template -void test_json_parser() -{ - - using namespace boost::property_tree; - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_1, NULL, - "testok1.json", NULL, "testok1out.json", 1, 0, 0 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_2, NULL, - "testok2.json", NULL, "testok2out.json", 18, 50, 74 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_3, NULL, - "testok3.json", NULL, "testok3out.json", 3, 1, 2 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_4, NULL, - "testok4.json", NULL, "testok4out.json", 11, 10, 4 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_5, NULL, - "testok5.json", NULL, "testok5out.json", 1, 0, 0 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_6, NULL, - "testok6.json", NULL, "testok6out.json", 56, 265, 111 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_7, NULL, - "testok7.json", NULL, "testok7out.json", 87, 1046, 1216 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_8, NULL, - "testok8.json", NULL, "testok8out.json", 23, 149, 125 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_9, NULL, - "testok9.json", NULL, "testok9out.json", 15, 54, 60 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_10, NULL, - "testok10.json", NULL, "testok10out.json", 17, 162, 85 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_11, NULL, - "testok11.json", NULL, "testok11out.json", 17, 120, 91 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_12, NULL, - "testok12.json", NULL, "testok12out.json", 2, 12, 19 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_1, NULL, - "testerr1.json", NULL, "testerr1out.json", 1 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_2, NULL, - "testerr2.json", NULL, "testerr2out.json", 3 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_3, NULL, - "testerr3.json", NULL, "testerr3out.json", 4 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_4, NULL, - "testerr4.json", NULL, "testerr4out.json", 3 - ); - -} - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_json_parser(); - test_json_parser(); -#ifndef BOOST_NO_CWCHAR - test_json_parser(); - test_json_parser(); -#endif - return 0; -} diff --git a/test/test_multi_module1.cpp b/test/test_multi_module1.cpp deleted file mode 100644 index 3bb3bb4555..0000000000 --- a/test/test_multi_module1.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#include -#include -#include -#include -#include - -void f(); - -int main() -{ - f(); -} diff --git a/test/test_multi_module2.cpp b/test/test_multi_module2.cpp deleted file mode 100644 index 6d35253f6c..0000000000 --- a/test/test_multi_module2.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#include -#include -#include -#include -#include - -void f() -{ -} diff --git a/test/test_property_tree.cpp b/test/test_property_tree.cpp deleted file mode 100644 index a4c3176338..0000000000 --- a/test/test_property_tree.cpp +++ /dev/null @@ -1,263 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#include "test_utils.hpp" -#include -#include -#include - -// If using VC, disable some warnings that trip in boost::serialization bowels -#ifdef BOOST_MSVC - #pragma warning(disable:4267) // Narrowing conversion - #pragma warning(disable:4996) // Deprecated functions -#endif - -#include -#include -#include -#include -#include -#include -#include - -// Predicate for sorting keys -template -struct SortPred -{ - bool operator()(const typename Ptree::value_type &v1, - const typename Ptree::value_type &v2) const - { - return v1.first < v2.first; - } -}; - -// Predicate for sorting keys in reverse -template -struct SortPredRev -{ - bool operator()(const typename Ptree::value_type &v1, - const typename Ptree::value_type &v2) const - { - return v1.first > v2.first; - } -}; - -// Custom translator that works with boost::any instead of std::string -struct MyTranslator -{ - - // Custom extractor - converts data from boost::any to T - template - bool get_value(const Ptree &pt, T &value) const - { - value = boost::any_cast(pt.data()); - return true; // Success - } - - // Custom inserter - converts data from T to boost::any - template - bool put_value(Ptree &pt, const T &value) const - { - pt.data() = value; - return true; - } - -}; - -// Include char tests, case sensitive -#define CHTYPE char -#define T(s) s -#define PTREE boost::property_tree::ptree -#define NOCASE 0 -#define WIDECHAR 0 -# include "test_property_tree.hpp" -#undef CHTYPE -#undef T -#undef PTREE -#undef NOCASE -#undef WIDECHAR - -// Include wchar_t tests, case sensitive -#ifndef BOOST_NO_CWCHAR -# define CHTYPE wchar_t -# define T(s) L ## s -# define PTREE boost::property_tree::wptree -# define NOCASE 0 -# define WIDECHAR 1 -# include "test_property_tree.hpp" -# undef CHTYPE -# undef T -# undef PTREE -# undef NOCASE -# undef WIDECHAR -#endif - -// Include char tests, case insensitive -#define CHTYPE char -#define T(s) s -#define PTREE boost::property_tree::iptree -#define NOCASE 1 -# define WIDECHAR 0 -# include "test_property_tree.hpp" -#undef CHTYPE -#undef T -#undef PTREE -#undef NOCASE -#undef WIDECHAR - -// Include wchar_t tests, case insensitive -#ifndef BOOST_NO_CWCHAR -# define CHTYPE wchar_t -# define T(s) L ## s -# define PTREE boost::property_tree::wiptree -# define NOCASE 1 -# define WIDECHAR 1 -# include "test_property_tree.hpp" -# undef CHTYPE -# undef T -# undef PTREE -# undef NOCASE -# undef WIDECHAR -#endif - -int test_main(int, char *[]) -{ - - using namespace boost::property_tree; - - // char tests, case sensitive - { - ptree *pt = 0; - test_debug(pt); - test_constructor_destructor_assignment(pt); - test_insertion(pt); - test_erasing(pt); - test_clear(pt); - test_pushpop(pt); - test_container_iteration(pt); - test_swap(pt); - test_sort_reverse(pt); - test_case(pt); - test_comparison(pt); - test_front_back(pt); - test_get_put(pt); - test_get_child_put_child(pt); - test_path_separator(pt); - test_path(pt); - test_precision(pt); - test_locale(pt); - test_custom_data_type(pt); - test_empty_size_max_size(pt); - test_ptree_bad_path(pt); - test_ptree_bad_data(pt); - test_serialization(pt); - test_bool(pt); - test_char(pt); - test_leaks(pt); // must be a final test - } - - // wchar_t tests, case sensitive -#ifndef BOOST_NO_CWCHAR - { - wptree *pt = 0; - test_debug(pt); - test_constructor_destructor_assignment(pt); - test_insertion(pt); - test_erasing(pt); - test_clear(pt); - test_pushpop(pt); - test_container_iteration(pt); - test_swap(pt); - test_sort_reverse(pt); - test_case(pt); - test_comparison(pt); - test_front_back(pt); - test_get_put(pt); - test_get_child_put_child(pt); - test_path_separator(pt); - test_path(pt); - test_precision(pt); - test_locale(pt); - test_custom_data_type(pt); - test_empty_size_max_size(pt); - test_ptree_bad_path(pt); - test_ptree_bad_data(pt); - test_serialization(pt); - test_bool(pt); - test_char(pt); - test_leaks(pt); // must be a final test - } -#endif - - // char tests, case insensitive - { - iptree *pt = 0; - test_debug(pt); - test_constructor_destructor_assignment(pt); - test_insertion(pt); - test_erasing(pt); - test_clear(pt); - test_pushpop(pt); - test_container_iteration(pt); - test_swap(pt); - test_sort_reverse(pt); - test_case(pt); - test_comparison(pt); - test_front_back(pt); - test_get_put(pt); - test_get_child_put_child(pt); - test_path_separator(pt); - test_path(pt); - test_precision(pt); - test_locale(pt); - test_custom_data_type(pt); - test_empty_size_max_size(pt); - test_ptree_bad_path(pt); - test_ptree_bad_data(pt); - test_serialization(pt); - test_bool(pt); - test_char(pt); - test_leaks(pt); // must be a final test - } - - // wchar_t tests, case insensitive -#ifndef BOOST_NO_CWCHAR - { - wiptree *pt = 0; - test_debug(pt); - test_constructor_destructor_assignment(pt); - test_insertion(pt); - test_erasing(pt); - test_clear(pt); - test_pushpop(pt); - test_container_iteration(pt); - test_swap(pt); - test_sort_reverse(pt); - test_case(pt); - test_comparison(pt); - test_front_back(pt); - test_get_put(pt); - test_get_child_put_child(pt); - test_path_separator(pt); - test_path(pt); - test_precision(pt); - test_locale(pt); - test_custom_data_type(pt); - test_empty_size_max_size(pt); - test_ptree_bad_path(pt); - test_ptree_bad_data(pt); - test_serialization(pt); - test_bool(pt); - test_char(pt); - test_leaks(pt); // must be a final test - } -#endif - - return 0; -} diff --git a/test/test_property_tree.hpp b/test/test_property_tree.hpp deleted file mode 100644 index 0d53cca008..0000000000 --- a/test/test_property_tree.hpp +++ /dev/null @@ -1,1263 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -// Intentionally no include guards (to be included more than once) - -#if !defined(CHTYPE) || !defined(T) || !defined(PTREE) || !defined(NOCASE) || !defined(WIDECHAR) -# error No character type specified -#endif - -void test_debug(PTREE *) -{ - - // Check count - BOOST_CHECK(PTREE::debug_get_instances_count() == 0); - - { - - // Create ptrees - PTREE pt1, pt2; - BOOST_CHECK(PTREE::debug_get_instances_count() == 2); - - // Create PTREE - PTREE *pt3 = new PTREE; - BOOST_CHECK(PTREE::debug_get_instances_count() == 3); - - // Insert - pt1.push_back(std::make_pair(T("key"), *pt3)); - BOOST_CHECK(PTREE::debug_get_instances_count() == 4); - - // Insert - pt2.push_back(std::make_pair(T("key"), *pt3)); - BOOST_CHECK(PTREE::debug_get_instances_count() == 5); - - // Clear - pt1.clear(); - BOOST_CHECK(PTREE::debug_get_instances_count() == 4); - - // Clear - pt2.clear(); - BOOST_CHECK(PTREE::debug_get_instances_count() == 3); - - // Delete - delete pt3; - BOOST_CHECK(PTREE::debug_get_instances_count() == 2); - - } - - // Check count - BOOST_CHECK(PTREE::debug_get_instances_count() == 0); - -} - -void test_constructor_destructor_assignment(PTREE *) -{ - - { - - // Test constructor from string - PTREE pt1(T("data")); - BOOST_CHECK(pt1.data() == T("data")); - BOOST_CHECK(PTREE::debug_get_instances_count() == 1); - - // Do insertions - PTREE &tmp1 = pt1.put(T("key1"), T("data1")); - PTREE &tmp2 = pt1.put(T("key2"), T("data2")); - tmp1.put(T("key3"), T("data3")); - tmp2.put(T("key4"), T("data4")); - BOOST_CHECK(PTREE::debug_get_instances_count() == 5); - - // Make a copy using copy constructor - PTREE *pt2 = new PTREE(pt1); - BOOST_CHECK(*pt2 == pt1); - BOOST_CHECK(PTREE::debug_get_instances_count() == 10); - - // Make a copy using = operator - PTREE *pt3 = new PTREE; - *pt3 = *pt2; - BOOST_CHECK(*pt3 == *pt2); - BOOST_CHECK(PTREE::debug_get_instances_count() == 15); - - // Test self assignment - pt1 = pt1; - BOOST_CHECK(pt1 == *pt2); - BOOST_CHECK(pt1 == *pt3); - BOOST_CHECK(PTREE::debug_get_instances_count() == 15); - - // Destroy - delete pt2; - BOOST_CHECK(PTREE::debug_get_instances_count() == 10); - - // Destroy - delete pt3; - BOOST_CHECK(PTREE::debug_get_instances_count() == 5); - - } - - // Check count - BOOST_CHECK(PTREE::debug_get_instances_count() == 0); - -} - -void test_insertion(PTREE *) -{ - - // Do insertions - PTREE pt; - PTREE tmp1(T("data1")); - PTREE tmp2(T("data2")); - PTREE tmp3(T("data3")); - PTREE tmp4(T("data4")); - PTREE::iterator it1 = pt.insert(pt.end(), std::make_pair(T("key1"), tmp1)); - PTREE::iterator it2 = pt.insert(it1, std::make_pair(T("key2"), tmp2)); - PTREE::iterator it3 = it1->second.push_back(std::make_pair(T("key3"), tmp3)); - PTREE::iterator it4 = it1->second.push_front(std::make_pair(T("key4"), tmp4)); - it2->second.insert(it2->second.end(), it1->second.begin(), it1->second.end()); - - // Check instance count - BOOST_CHECK(PTREE::debug_get_instances_count() == 11); - - // Check contents - BOOST_CHECK(pt.get(T("key1"), T("")) == T("data1")); - BOOST_CHECK(pt.get(T("key2"), T("")) == T("data2")); - BOOST_CHECK(pt.get(T("key1.key3"), T("")) == T("data3")); - BOOST_CHECK(pt.get(T("key1.key4"), T("")) == T("data4")); - BOOST_CHECK(pt.get(T("key2.key3"), T("")) == T("data3")); - BOOST_CHECK(pt.get(T("key2.key4"), T("")) == T("data4")); - - // Check sequence - PTREE::iterator it = it2; - ++it; BOOST_CHECK(it == it1); - ++it; BOOST_CHECK(it == pt.end()); - it = it4; - ++it; BOOST_CHECK(it == it3); - ++it; BOOST_CHECK(it == it1->second.end()); - -} - -void test_erasing(PTREE *) -{ - - // Do insertions - PTREE pt; - PTREE tmp1(T("data1")); - PTREE tmp2(T("data2")); - PTREE tmp3(T("data3")); - PTREE tmp4(T("data4")); - PTREE::iterator it1 = pt.insert(pt.end(), std::make_pair(T("key1"), tmp1)); - PTREE::iterator it2 = pt.insert(it1, std::make_pair(T("key2"), tmp2)); - it1->second.push_back(std::make_pair(T("key"), tmp3)); - it1->second.push_front(std::make_pair(T("key"), tmp4)); - it2->second.insert(it2->second.end(), it1->second.begin(), it1->second.end()); - - // Check instance count - BOOST_CHECK(PTREE::debug_get_instances_count() == 11); - - // Test range erase - PTREE::iterator it = it1->second.erase(it1->second.begin(), it1->second.end()); - BOOST_CHECK(it == it1->second.end()); - BOOST_CHECK(PTREE::debug_get_instances_count() == 9); - - // Test single erase - PTREE::size_type n = pt.erase(T("key1")); - BOOST_CHECK(n == 1); - BOOST_CHECK(PTREE::debug_get_instances_count() == 8); - - // Test multiple erase - n = it2->second.erase(T("key")); - BOOST_CHECK(n == 2); - BOOST_CHECK(PTREE::debug_get_instances_count() == 6); - - // Test one more erase - n = pt.erase(T("key2")); - BOOST_CHECK(n == 1); - BOOST_CHECK(PTREE::debug_get_instances_count() == 5); - -} - -void test_clear(PTREE *) -{ - - // Do insertions - PTREE pt(T("data")); - pt.push_back(std::make_pair(T("key"), PTREE(T("data")))); - - // Check instance count - BOOST_CHECK(PTREE::debug_get_instances_count() == 2); - - // Test clear - pt.clear(); - BOOST_CHECK(pt.empty()); - BOOST_CHECK(pt.data().empty()); - BOOST_CHECK(PTREE::debug_get_instances_count() == 1); - -} - -void test_pushpop(PTREE *) -{ - - // Do insertions - PTREE pt; - PTREE tmp1(T("data1")); - PTREE tmp2(T("data2")); - PTREE tmp3(T("data3")); - PTREE tmp4(T("data4")); - pt.push_back(std::make_pair(T("key3"), tmp3)); - pt.push_front(std::make_pair(T("key2"), tmp2)); - pt.push_back(std::make_pair(T("key4"), tmp4)); - pt.push_front(std::make_pair(T("key1"), tmp1)); - - // Check instance count - BOOST_CHECK(PTREE::debug_get_instances_count() == 9); - - // Check sequence - PTREE::iterator it = pt.begin(); - BOOST_CHECK(it->first == T("key1")); ++it; - BOOST_CHECK(it->first == T("key2")); ++it; - BOOST_CHECK(it->first == T("key3")); ++it; - BOOST_CHECK(it->first == T("key4")); ++it; - BOOST_CHECK(it == pt.end()); - - // Test pops - pt.pop_back(); - BOOST_CHECK(PTREE::debug_get_instances_count() == 8); - BOOST_CHECK(pt.front().second.data() == T("data1")); - BOOST_CHECK(pt.back().second.data() == T("data3")); - pt.pop_front(); - BOOST_CHECK(PTREE::debug_get_instances_count() == 7); - BOOST_CHECK(pt.front().second.data() == T("data2")); - BOOST_CHECK(pt.back().second.data() == T("data3")); - pt.pop_back(); - BOOST_CHECK(PTREE::debug_get_instances_count() == 6); - BOOST_CHECK(pt.front().second.data() == T("data2")); - BOOST_CHECK(pt.back().second.data() == T("data2")); - pt.pop_front(); - BOOST_CHECK(PTREE::debug_get_instances_count() == 5); - BOOST_CHECK(pt.empty()); - -} - -void test_container_iteration(PTREE *) -{ - - // Do insertions - PTREE pt; - pt.put(T("key3"), T("")); - pt.put(T("key1"), T("")); - pt.put(T("key4"), T("")); - pt.put(T("key2"), T("")); - - // iterator - { - PTREE::iterator it = pt.begin(); - BOOST_CHECK(it->first == T("key3")); ++it; - BOOST_CHECK(it->first == T("key1")); ++it; - BOOST_CHECK(it->first == T("key4")); ++it; - BOOST_CHECK(it->first == T("key2")); ++it; - BOOST_CHECK(it == pt.end()); - } - - // const_iterator - { - PTREE::const_iterator it = pt.begin(); - BOOST_CHECK(it->first == T("key3")); ++it; - BOOST_CHECK(it->first == T("key1")); ++it; - BOOST_CHECK(it->first == T("key4")); ++it; - BOOST_CHECK(it->first == T("key2")); ++it; - BOOST_CHECK(it == pt.end()); - } - - // reverse_iterator - { - PTREE::reverse_iterator it = pt.rbegin(); - BOOST_CHECK(it->first == T("key2")); ++it; - BOOST_CHECK(it->first == T("key4")); ++it; - BOOST_CHECK(it->first == T("key1")); ++it; - BOOST_CHECK(it->first == T("key3")); ++it; - BOOST_CHECK(it == pt.rend()); - } - - // const_reverse_iterator - { - PTREE::const_reverse_iterator it = pt.rbegin(); - BOOST_CHECK(it->first == T("key2")); ++it; - BOOST_CHECK(it->first == T("key4")); ++it; - BOOST_CHECK(it->first == T("key1")); ++it; - BOOST_CHECK(it->first == T("key3")); ++it; - BOOST_CHECK(it == PTREE::const_reverse_iterator(pt.rend())); - } - -} - -void test_swap(PTREE *) -{ - - PTREE pt1, pt2; - - // Do insertions - pt1.put(T("key1"), T("")); - pt1.put(T("key2"), T("")); - pt1.put(T("key1.key3"), T("")); - pt1.put(T("key1.key4"), T("")); - - // Check counts - BOOST_CHECK(PTREE::debug_get_instances_count() == 6); - BOOST_CHECK(pt1.size() == 2); - BOOST_CHECK(pt1.get_child(T("key1")).size() == 2); - BOOST_CHECK(pt2.size() == 0); - - // Swap using member function - pt1.swap(pt2); - - // Check counts - BOOST_CHECK(PTREE::debug_get_instances_count() == 6); - BOOST_CHECK(pt2.size() == 2); - BOOST_CHECK(pt2.get_child(T("key1")).size() == 2); - BOOST_CHECK(pt1.size() == 0); - - // Swap using free function - swap(pt1, pt2); - - // Check counts - BOOST_CHECK(PTREE::debug_get_instances_count() == 6); - BOOST_CHECK(pt1.size() == 2); - BOOST_CHECK(pt1.get_child(T("key1")).size() == 2); - BOOST_CHECK(pt2.size() == 0); - - // Swap using std algorithm - std::swap(pt1, pt2); - - // Check counts - BOOST_CHECK(PTREE::debug_get_instances_count() == 6); - BOOST_CHECK(pt2.size() == 2); - BOOST_CHECK(pt2.get_child(T("key1")).size() == 2); - BOOST_CHECK(pt1.size() == 0); - -} - -void test_sort_reverse(PTREE *) -{ - - PTREE pt; - - // Do insertions - pt.put(T("key2"), T("data2")); - pt.put(T("key1"), T("data1")); - pt.put(T("key4"), T("data4")); - pt.put(T("key3"), T("data3")); - pt.put(T("key3.key1"), T("")); - pt.put(T("key4.key2"), T("")); - - // Reverse - pt.reverse(); - - // Check sequence - { - PTREE::iterator it = pt.begin(); - BOOST_CHECK(it->first == T("key3")); ++it; - BOOST_CHECK(it->first == T("key4")); ++it; - BOOST_CHECK(it->first == T("key1")); ++it; - BOOST_CHECK(it->first == T("key2")); ++it; - BOOST_CHECK(it == pt.end()); - } - // Check sequence using find to check if index is ok - { - PTREE::iterator it = pt.begin(); - BOOST_CHECK(it == pt.find(T("key3"))); ++it; - BOOST_CHECK(it == pt.find(T("key4"))); ++it; - BOOST_CHECK(it == pt.find(T("key1"))); ++it; - BOOST_CHECK(it == pt.find(T("key2"))); ++it; - BOOST_CHECK(it == pt.end()); - } - - // Sort - pt.sort(SortPred()); - - // Check sequence - { - PTREE::iterator it = pt.begin(); - BOOST_CHECK(it->first == T("key1")); ++it; - BOOST_CHECK(it->first == T("key2")); ++it; - BOOST_CHECK(it->first == T("key3")); ++it; - BOOST_CHECK(it->first == T("key4")); ++it; - BOOST_CHECK(it == pt.end()); - } - // Check sequence (using find to check if index is ok) - { - PTREE::iterator it = pt.begin(); - BOOST_CHECK(it == pt.find(T("key1"))); ++it; - BOOST_CHECK(it == pt.find(T("key2"))); ++it; - BOOST_CHECK(it == pt.find(T("key3"))); ++it; - BOOST_CHECK(it == pt.find(T("key4"))); ++it; - BOOST_CHECK(it == pt.end()); - } - - // Sort reverse - pt.sort(SortPredRev()); - - // Check sequence - { - PTREE::iterator it = pt.begin(); - BOOST_CHECK(it->first == T("key4")); ++it; - BOOST_CHECK(it->first == T("key3")); ++it; - BOOST_CHECK(it->first == T("key2")); ++it; - BOOST_CHECK(it->first == T("key1")); ++it; - BOOST_CHECK(it == pt.end()); - } - // Check sequence (using find to check if index is ok) - { - PTREE::iterator it = pt.begin(); - BOOST_CHECK(it == pt.find(T("key4"))); ++it; - BOOST_CHECK(it == pt.find(T("key3"))); ++it; - BOOST_CHECK(it == pt.find(T("key2"))); ++it; - BOOST_CHECK(it == pt.find(T("key1"))); ++it; - BOOST_CHECK(it == pt.end()); - } - -} - -void test_case(PTREE *) -{ - - // Do insertions - PTREE pt; - pt.put(T("key1"), T("data1")); - pt.put(T("KEY2"), T("data2")); - pt.put(T("kEy1.keY3"), T("data3")); - pt.put(T("KEY1.key4"), T("data4")); - - // Check findings depending on traits type -#if (NOCASE == 0) - BOOST_CHECK(PTREE::debug_get_instances_count() == 7); - BOOST_CHECK(pt.get(T("key1"), T("")) == T("data1")); - BOOST_CHECK(pt.get(T("key2"), T("")) == T("")); - BOOST_CHECK(pt.get(T("key1.key3"), T("")) == T("")); - BOOST_CHECK(pt.get(T("KEY1.key4"), T("")) == T("data4")); -#else - BOOST_CHECK(PTREE::debug_get_instances_count() == 5); - BOOST_CHECK(pt.get(T("key1"), T("1")) == pt.get(T("KEY1"), T("2"))); - BOOST_CHECK(pt.get(T("key2"), T("1")) == pt.get(T("KEY2"), T("2"))); - BOOST_CHECK(pt.get(T("key1.key3"), T("1")) == pt.get(T("KEY1.KEY3"), T("2"))); - BOOST_CHECK(pt.get(T("key1.key4"), T("1")) == pt.get(T("KEY1.KEY4"), T("2"))); -#endif - - // Do more insertions - pt.push_back(PTREE::value_type(T("key1"), PTREE())); - pt.push_back(PTREE::value_type(T("key1"), PTREE())); - - // Test counts -#if (NOCASE == 0) - BOOST_CHECK(pt.count(T("key1")) == 3); - BOOST_CHECK(pt.count(T("KEY1")) == 1); - BOOST_CHECK(pt.count(T("key2")) == 0); - BOOST_CHECK(pt.count(T("KEY2")) == 1); - BOOST_CHECK(pt.count(T("key3")) == 0); - BOOST_CHECK(pt.count(T("KEY3")) == 0); -#else - BOOST_CHECK(pt.count(T("key1")) == 3); - BOOST_CHECK(pt.count(T("KEY1")) == 3); - BOOST_CHECK(pt.count(T("key2")) == 1); - BOOST_CHECK(pt.count(T("KEY2")) == 1); - BOOST_CHECK(pt.count(T("key3")) == 0); - BOOST_CHECK(pt.count(T("KEY3")) == 0); -#endif - -} - -void test_comparison(PTREE *) -{ - - // Prepare original - PTREE pt_orig(T("data")); - pt_orig.put(T("key1"), T("data1")); - pt_orig.put(T("key1.key3"), T("data2")); - pt_orig.put(T("key1.key4"), T("data3")); - pt_orig.put(T("key2"), T("data4")); - - // Test originals - { - PTREE pt1(pt_orig); - PTREE pt2(pt_orig); - BOOST_CHECK(pt1 == pt2); - BOOST_CHECK(pt2 == pt1); - BOOST_CHECK(!(pt1 != pt2)); - BOOST_CHECK(!(pt2 != pt1)); - } - - // Test originals with modified case -#if (NOCASE != 0) - { - PTREE pt1(pt_orig); - PTREE pt2(pt_orig); - pt1.pop_back(); - pt1.put(T("KEY2"), T("data4")); - BOOST_CHECK(pt1 == pt2); - BOOST_CHECK(pt2 == pt1); - BOOST_CHECK(!(pt1 != pt2)); - BOOST_CHECK(!(pt2 != pt1)); - } -#endif - - // Test modified copies (both modified the same way) - { - PTREE pt1(pt_orig); - PTREE pt2(pt_orig); - pt1.put(T("key1.key5"), T(".")); - pt2.put(T("key1.key5"), T(".")); - BOOST_CHECK(pt1 == pt2); - BOOST_CHECK(pt2 == pt1); - BOOST_CHECK(!(pt1 != pt2)); - BOOST_CHECK(!(pt2 != pt1)); - } - - // Test modified copies (modified root data) - { - PTREE pt1(pt_orig); - PTREE pt2(pt_orig); - pt1.data() = T("a"); - pt2.data() = T("b"); - BOOST_CHECK(!(pt1 == pt2)); - BOOST_CHECK(!(pt2 == pt1)); - BOOST_CHECK(pt1 != pt2); - BOOST_CHECK(pt2 != pt1); - } - - // Test modified copies (added subkeys with different data) - { - PTREE pt1(pt_orig); - PTREE pt2(pt_orig); - pt1.put(T("key1.key5"), T("a")); - pt2.put(T("key1.key5"), T("b")); - BOOST_CHECK(!(pt1 == pt2)); - BOOST_CHECK(!(pt2 == pt1)); - BOOST_CHECK(pt1 != pt2); - BOOST_CHECK(pt2 != pt1); - } - - // Test modified copies (added subkeys with different keys) - { - PTREE pt1(pt_orig); - PTREE pt2(pt_orig); - pt1.put(T("key1.key5"), T("")); - pt2.put(T("key1.key6"), T("")); - BOOST_CHECK(!(pt1 == pt2)); - BOOST_CHECK(!(pt2 == pt1)); - BOOST_CHECK(pt1 != pt2); - BOOST_CHECK(pt2 != pt1); - } - - // Test modified copies (added subkey to only one copy) - { - PTREE pt1(pt_orig); - PTREE pt2(pt_orig); - pt1.put(T("key1.key5"), T("")); - BOOST_CHECK(!(pt1 == pt2)); - BOOST_CHECK(!(pt2 == pt1)); - BOOST_CHECK(pt1 != pt2); - BOOST_CHECK(pt2 != pt1); - } - -} - -void test_front_back(PTREE *) -{ - - // Do insertions - PTREE pt; - pt.put(T("key1"), T("")); - pt.put(T("key2"), T("")); - - // Check front and back - BOOST_CHECK(pt.front().first == T("key1")); - BOOST_CHECK(pt.back().first == T("key2")); - -} - -void test_get_put(PTREE *) -{ - - typedef std::basic_string str_t; - - // Temporary storage - str_t tmp_string; - boost::optional opt_int; - boost::optional opt_long; - boost::optional opt_double; - boost::optional opt_float; - boost::optional opt_string; - boost::optional opt_char; - boost::optional opt_bool; - - // Do insertions via put - PTREE pt; - PTREE &pt1 = pt.put(T("k1"), 1); // put as int - PTREE &pt2 = pt.put(T("k2.k"), 2.5); // put as double - PTREE &pt3 = pt.put(T("k3.k.k"), T("ala ma kota")); // put as string - PTREE &pt4 = pt.put(T("k4.k.k.k"), CHTYPE('c')); // put as character - PTREE &pt5 = pt.put(T("k5.k.k.k.f"), false); // put as bool - PTREE &pt6 = pt.put(T("k5.k.k.k.t"), true); // put as bool - - // Check instances count - BOOST_CHECK(PTREE::debug_get_instances_count() == 17); - - // Check if const char * version returns std::string - BOOST_CHECK(typeid(pt.get_value(T(""))) == typeid(str_t)); - - // Do extractions via get (throwing version) - BOOST_CHECK(pt.get(T("k1")) == 1); // get as int - BOOST_CHECK(pt.get(T("k1")) == 1); // get as long - BOOST_CHECK(pt.get(T("k2.k")) == 2.5); // get as double - BOOST_CHECK(pt.get(T("k2.k")) == 2.5f); // get as float - BOOST_CHECK(pt.get(T("k3.k.k")) == str_t(T("ala ma kota"))); // get as string - BOOST_CHECK(pt.get(T("k4.k.k.k")) == CHTYPE('c')); // get as char - BOOST_CHECK(pt.get(T("k5.k.k.k.f")) == false); // get as bool - BOOST_CHECK(pt.get(T("k5.k.k.k.t")) == true); // get as bool - - // Do extractions via get (default value version) - BOOST_CHECK(pt.get(T("k1"), 0) == 1); // get as int - BOOST_CHECK(pt.get(T("k1"), 0L) == 1); // get as long - BOOST_CHECK(pt.get(T("k2.k"), 0.0) == 2.5); // get as double - BOOST_CHECK(pt.get(T("k2.k"), 0.0f) == 2.5f); // get as float - BOOST_CHECK(pt.get(T("k3.k.k"), str_t()) == str_t(T("ala ma kota"))); // get as string - BOOST_CHECK(pt.get(T("k3.k.k"), T("")) == T("ala ma kota")); // get as const char * - BOOST_CHECK(pt.get(T("k4.k.k.k"), CHTYPE('\0')) == CHTYPE('c')); // get as char - BOOST_CHECK(pt.get(T("k5.k.k.k.f"), true) == false); // get as bool - BOOST_CHECK(pt.get(T("k5.k.k.k.t"), false) == true); // get as bool - - // Do extractions via get (optional version) - opt_int = pt.get_optional(T("k1")); // get as int - BOOST_CHECK(opt_int && *opt_int == 1); - opt_long = pt.get_optional(T("k1")); // get as long - BOOST_CHECK(opt_long && *opt_long == 1); - opt_double = pt.get_optional(T("k2.k")); // get as double - BOOST_CHECK(opt_double && *opt_double == 2.5); - opt_float = pt.get_optional(T("k2.k")); // get as float - BOOST_CHECK(opt_float && *opt_float == 2.5f); - opt_string = pt.get_optional(T("k3.k.k")); // get as string - BOOST_CHECK(opt_string && *opt_string == str_t(T("ala ma kota"))); - opt_char = pt.get_optional(T("k4.k.k.k")); // get as char - BOOST_CHECK(opt_char && *opt_char == CHTYPE('c')); - opt_bool = pt.get_optional(T("k5.k.k.k.f")); // get as bool - BOOST_CHECK(opt_bool && *opt_bool == false); - opt_bool = pt.get_optional(T("k5.k.k.k.t")); // get as bool - BOOST_CHECK(opt_bool && *opt_bool == true); - - // Do insertions via put_value - pt1.put_value(short(1)); // put as short - pt2.put_value(2.5f); // put as float - pt3.put_value(str_t(T("ala ma kota"))); // put as string - pt4.put_value(CHTYPE('c')); // put as character - pt5.put_value(false); // put as bool - pt6.put_value(true); // put as bool - - // Do extractions via get_value (throwing version) - BOOST_CHECK(pt1.get_value() == 1); // get as int - BOOST_CHECK(pt1.get_value() == 1); // get as long - BOOST_CHECK(pt2.get_value() == 2.5); // get as double - BOOST_CHECK(pt2.get_value() == 2.5f); // get as float - BOOST_CHECK(pt3.get_value() == str_t(T("ala ma kota"))); // get as string - BOOST_CHECK(pt4.get_value() == CHTYPE('c')); // get as char - BOOST_CHECK(pt5.get_value() == false); // get as bool - BOOST_CHECK(pt6.get_value() == true); // get as bool - - // Do extractions via get_value (default value version) - BOOST_CHECK(pt1.get_value(0) == 1); // get as int - BOOST_CHECK(pt1.get_value(0L) == 1); // get as long - BOOST_CHECK(pt2.get_value(0.0) == 2.5); // get as double - BOOST_CHECK(pt2.get_value(0.0f) == 2.5f); // get as float - BOOST_CHECK(pt3.get_value(str_t()) == str_t(T("ala ma kota"))); // get as string - BOOST_CHECK(pt3.get_value(T("")) == T("ala ma kota")); // get as const char * - BOOST_CHECK(pt4.get_value(CHTYPE('\0')) == CHTYPE('c')); // get as char - BOOST_CHECK(pt5.get_value(true) == false); // get as bool - BOOST_CHECK(pt6.get_value(false) == true); // get as bool - - // Do extractions via get_value (optional version) - opt_int = pt1.get_value_optional(); // get as int - BOOST_CHECK(opt_int && *opt_int == 1); - opt_long = pt1.get_value_optional(); // get as long - BOOST_CHECK(opt_long && *opt_long == 1); - opt_double = pt2.get_value_optional(); // get as double - BOOST_CHECK(opt_double && *opt_double == 2.5); - opt_float = pt2.get_value_optional(); // get as float - BOOST_CHECK(opt_float && *opt_float == 2.5f); - opt_string = pt3.get_value_optional(); // get as string - BOOST_CHECK(opt_string && *opt_string == str_t(T("ala ma kota"))); - opt_char = pt4.get_value_optional(); // get as char - BOOST_CHECK(opt_char && *opt_char == CHTYPE('c')); - opt_bool = pt5.get_value_optional(); // get as bool - BOOST_CHECK(opt_bool && *opt_bool == false); - opt_bool = pt6.get_value_optional(); // get as bool - BOOST_CHECK(opt_bool && *opt_bool == true); - - // Do incorrect extractions (throwing version) - try - { - pt.get(T("k2.k.bogus.path")); - BOOST_ERROR("No required exception thrown"); - } - catch (boost::property_tree::ptree_bad_path &) { } - catch (...) - { - BOOST_ERROR("Wrong exception type thrown"); - } - try - { - pt.get(T("k2.k")); - BOOST_ERROR("No required exception thrown"); - } - catch (boost::property_tree::ptree_bad_data &) { } - catch (...) - { - BOOST_ERROR("Wrong exception type thrown"); - } - - // Do incorrect extractions (default value version) - BOOST_CHECK(pt.get(T("k2.k"), -7) == -7); - BOOST_CHECK(pt.get(T("k3.k.k"), -7) == -7); - BOOST_CHECK(pt.get(T("k4.k.k.k"), -7) == -7); - - // Do incorrect extractions (optional version) - BOOST_CHECK(!pt.get_optional(T("k2.k"))); - BOOST_CHECK(!pt.get_optional(T("k3.k.k"))); - BOOST_CHECK(!pt.get_optional(T("k4.k.k.k"))); - - // Test multiple puts with the same key - { - PTREE pt; - pt.put(T("key"), 1); - BOOST_CHECK(pt.get(T("key")) == 1); - BOOST_CHECK(pt.size() == 1); - pt.put(T("key"), 2); - BOOST_CHECK(pt.get(T("key")) == 2); - BOOST_CHECK(pt.size() == 1); - pt.put(T("key.key.key"), 1); - PTREE &child = pt.get_child(T("key.key")); - BOOST_CHECK(pt.get(T("key.key.key")) == 1); - BOOST_CHECK(child.size() == 1); - BOOST_CHECK(child.count(T("key")) == 1); - pt.put(T("key.key.key"), 2); - BOOST_CHECK(pt.get(T("key.key.key")) == 2); - BOOST_CHECK(child.size() == 1); - BOOST_CHECK(child.count(T("key")) == 1); - } - - // Test multiple puts with the same key - { - PTREE pt; - pt.put(T("key"), 1); - BOOST_CHECK(pt.get(T("key")) == 1); - BOOST_CHECK(pt.size() == 1); - pt.put(T("key"), 2); - BOOST_CHECK(pt.get(T("key")) == 2); - BOOST_CHECK(pt.size() == 1); - pt.put(T("key.key.key"), 1); - PTREE &child = pt.get_child(T("key.key")); - BOOST_CHECK(child.size() == 1); - BOOST_CHECK(child.count(T("key")) == 1); - pt.put(T("key.key.key"), 2, true); - BOOST_CHECK(child.size() == 2); - BOOST_CHECK(child.count(T("key")) == 2); - } - - // Test that put does not destroy children - { - PTREE pt; - pt.put(T("key1"), 1); - pt.put(T("key1.key2"), 2); - BOOST_CHECK(pt.get(T("key1"), 0) == 1); - BOOST_CHECK(pt.get(T("key1.key2"), 0) == 2); - pt.put(T("key1"), 2); - BOOST_CHECK(pt.get(T("key1"), 0) == 2); - BOOST_CHECK(pt.get(T("key1.key2"), 0) == 2); - } - - // Test that get of single character that is whitespace works - { - PTREE pt; - pt.put_value(T(' ')); - CHTYPE ch = pt.get_value(); - BOOST_CHECK(ch == T(' ')); - } - - // Test that get of non-char value with trailing and leading whitespace works - { - PTREE pt; - pt.put_value(T(" \t\n99 \t\n")); - BOOST_CHECK(pt.get_value(0) == 99); - } - -} - -void test_get_child_put_child(PTREE *) -{ - - typedef std::basic_string str_t; - - PTREE pt(T("ala ma kota")); - - // Do insertions via put_child - PTREE pt1, pt2, pt3; - pt1.put_child(T("k1"), boost::property_tree::empty_ptree()); - pt1.put_child(T("k2.k"), boost::property_tree::empty_ptree()); - pt2.put_child(T("k1"), pt); - pt2.put_child(T("k2.k"), pt); - - // Const references to test const versions of methods - const PTREE &cpt1 = pt1, &cpt2 = pt2; - - // Do correct extractions via get_child (throwing version) - BOOST_CHECK(pt1.get_child(T("k1")).empty()); - BOOST_CHECK(pt1.get_child(T("k2.k")).empty()); - BOOST_CHECK(pt2.get_child(T("k1")) == pt); - BOOST_CHECK(pt2.get_child(T("k2.k")) == pt); - BOOST_CHECK(cpt1.get_child(T("k1")).empty()); - BOOST_CHECK(cpt1.get_child(T("k2.k")).empty()); - BOOST_CHECK(cpt2.get_child(T("k1")) == pt); - BOOST_CHECK(cpt2.get_child(T("k2.k")) == pt); - - // Do correct extractions via get_child (default value version) - BOOST_CHECK(&pt1.get_child(T("k1"), boost::property_tree::empty_ptree()) != &boost::property_tree::empty_ptree()); - BOOST_CHECK(&pt1.get_child(T("k2.k"), boost::property_tree::empty_ptree()) != &boost::property_tree::empty_ptree()); - BOOST_CHECK(pt2.get_child(T("k1"), boost::property_tree::empty_ptree()) == pt); - BOOST_CHECK(pt2.get_child(T("k2.k"), boost::property_tree::empty_ptree()) == pt); - BOOST_CHECK(&cpt1.get_child(T("k1"), boost::property_tree::empty_ptree()) != &boost::property_tree::empty_ptree()); - BOOST_CHECK(&cpt1.get_child(T("k2.k"), boost::property_tree::empty_ptree()) != &boost::property_tree::empty_ptree()); - BOOST_CHECK(cpt2.get_child(T("k1"), boost::property_tree::empty_ptree()) == pt); - BOOST_CHECK(cpt2.get_child(T("k2.k"), boost::property_tree::empty_ptree()) == pt); - - // Do correct extractions via get_child (optional version) - boost::optional opt; - boost::optional copt; - opt = pt1.get_child_optional(T("k1")); - BOOST_CHECK(opt); - opt = pt1.get_child_optional(T("k2.k")); - BOOST_CHECK(opt); - opt = pt2.get_child_optional(T("k1")); - BOOST_CHECK(opt && *opt == pt); - opt = pt2.get_child_optional(T("k2.k")); - BOOST_CHECK(opt && *opt == pt); - copt = cpt1.get_child_optional(T("k1")); - BOOST_CHECK(copt); - copt = cpt1.get_child_optional(T("k2.k")); - BOOST_CHECK(copt); - copt = cpt2.get_child_optional(T("k1")); - BOOST_CHECK(copt && *copt == pt); - copt = cpt2.get_child_optional(T("k2.k")); - BOOST_CHECK(copt && *copt == pt); - - // Do incorrect extractions via get_child (throwing version) - try - { - pt.get_child(T("k2.k.bogus.path")); - BOOST_ERROR("No required exception thrown"); - } - catch (boost::property_tree::ptree_bad_path &) { } - catch (...) - { - BOOST_ERROR("Wrong exception type thrown"); - } - - // Do incorrect extractions via get_child (default value version) - BOOST_CHECK(&pt.get_child(T("k2.k.bogus.path"), pt3) == &pt3); - - // Do incorrect extractions via get_child (optional version) - BOOST_CHECK(!pt.get_child_optional(T("k2.k.bogus.path"))); - - // Test multiple puts with the same key - { - PTREE pt, tmp1(T("data1")), tmp2(T("data2")); - pt.put_child(T("key"), tmp1); - BOOST_CHECK(pt.get_child(T("key")) == tmp1); - BOOST_CHECK(pt.size() == 1); - pt.put_child(T("key"), tmp2); - BOOST_CHECK(pt.get_child(T("key")) == tmp2); - BOOST_CHECK(pt.size() == 1); - pt.put_child(T("key.key.key"), tmp1); - PTREE &child = pt.get_child(T("key.key")); - BOOST_CHECK(child.size() == 1); - pt.put_child(T("key.key.key"), tmp2); - BOOST_CHECK(child.size() == 1); - } - - // Test multiple puts with the same key using do_not_replace - { - PTREE pt, tmp1(T("data1")), tmp2(T("data2")); - pt.put_child(T("key"), tmp1); - BOOST_CHECK(pt.size() == 1); - pt.put_child(T("key"), tmp2, true); - BOOST_CHECK(pt.size() == 2); - BOOST_CHECK(pt.count(T("key")) == 2); - pt.put_child(T("key.key.key"), tmp1); - PTREE &child = pt.get_child(T("key.key")); - BOOST_CHECK(child.size() == 1); - BOOST_CHECK(child.count(T("key")) == 1); - pt.put_child(T("key.key.key"), tmp2, true); - BOOST_CHECK(child.size() == 2); - BOOST_CHECK(child.count(T("key")) == 2); - } - -} - -void test_path_separator(PTREE *) -{ - - typedef PTREE::path_type path; - - // Check instances count - BOOST_CHECK(PTREE::debug_get_instances_count() == 0); - - // Do insertions - PTREE pt; - pt.put(T("key1"), T("1")); - pt.put(T("key2.key"), T("2")); - pt.put(T("key3.key.key"), T("3")); - pt.put(path(T("key4"), CHTYPE('/')), T("4")); - pt.put(path(T("key5/key"), CHTYPE('/')), T("5")); - pt.put(path(T("key6/key/key"), CHTYPE('/')), T("6")); - - // Check instances count - BOOST_CHECK(PTREE::debug_get_instances_count() == 13); - - // Do correct extractions - BOOST_CHECK(pt.get(T("key1"), 0) == 1); - BOOST_CHECK(pt.get(T("key2.key"), 0) == 2); - BOOST_CHECK(pt.get(T("key3.key.key"), 0) == 3); - BOOST_CHECK(pt.get(path(T("key4"), CHTYPE('/')), 0) == 4); - BOOST_CHECK(pt.get(path(T("key5/key"), CHTYPE('/')), 0) == 5); - BOOST_CHECK(pt.get(path(T("key6/key/key"), CHTYPE('/')), 0) == 6); - - // Do incorrect extractions - BOOST_CHECK(pt.get(T("key2/key"), 0) == 0); - BOOST_CHECK(pt.get(T("key3/key/key"), 0) == 0); - BOOST_CHECK(pt.get(path(T("key5.key"), CHTYPE('/')), 0) == 0); - BOOST_CHECK(pt.get(path(T("key6.key.key"), CHTYPE('/')), 0) == 0); - -} - -void test_path(PTREE *) -{ - - typedef PTREE::path_type path; - - // Insert - PTREE pt; - pt.put(T("key1.key2.key3"), 1); - - // Test operator /= - { - path p; - p /= T("key1"); p /= T("key2"); p /= T("key3"); - BOOST_CHECK(pt.get(p, 0) == 1); - } - - // Test operator /= - { - path p(T("key1")); - p /= T("key2.key3"); - BOOST_CHECK(pt.get(p, 0) == 1); - } - - // Test operator /= - { - path p; - path p1(T("key1.key2")); - path p2(T("key3")); - p /= p1; - p /= p2; - BOOST_CHECK(pt.get(p, 0) == 1); - } - - // Test operator / - { - path p = path(T("key1")) / T("key2.key3"); - BOOST_CHECK(pt.get(p, 0) == 1); - } - - // Test operator / - { - path p = T("key1.key2") / path(T("key3")); - BOOST_CHECK(pt.get(p, 0) == 1); - } - -} - -void test_precision(PTREE *) -{ - - typedef double real; - - // Quite precise PI value - real pi = real(3.1415926535897932384626433832795028841971); - - // Put and get - PTREE pt; - pt.put_value(pi); - real pi2 = pt.get_value(); - - // Test if precision is "good enough", i.e. if stream precision increase worked - using namespace std; - real error = abs(pi - pi2) * - pow(real(numeric_limits::radix), - real(numeric_limits::digits)); - BOOST_CHECK(error < 100); - -} - -void test_locale(PTREE *) -{ - - try - { - - // Write strings in english and french locales - PTREE pt; -#ifdef BOOST_WINDOWS - std::locale loc_english("english"); - std::locale loc_french("french"); -#else - std::locale loc_english("en_GB"); - std::locale loc_french("fr_FR"); -#endif - pt.put(T("english"), 1.234, false, loc_english); - pt.put(T("french"), 1.234, false, loc_french); - - // Test contents - BOOST_CHECK(pt.get(T("english")) == T("1.234")); - BOOST_CHECK(pt.get(T("french")) == T("1,234")); - - } - catch (boost::property_tree::ptree_error &) - { - throw; - } - catch (std::runtime_error &e) - { - std::cerr << "Required locale not supported by the platform. " - "Skipping locale tests (caught std::runtime_error with message " << - e.what() << ").\n"; - } - -} - -void test_custom_data_type(PTREE *) -{ - - typedef std::basic_string Str; - typedef PTREE::key_compare Comp; - typedef PTREE::path_type Path; - - // Property_tree with boost::any as data type - typedef boost::property_tree::basic_ptree my_ptree; - my_ptree pt; - - // Put/get int value - pt.put(T("int value"), 3); - int int_value = pt.get(T("int value")); - BOOST_CHECK(int_value == 3); - - // Put/get string value - pt.put >(T("string value"), T("foo bar")); - std::basic_string string_value = pt.get >(T("string value")); - BOOST_CHECK(string_value == T("foo bar")); - - // Put/get list value - int list_data[] = { 1, 2, 3, 4, 5 }; - pt.put >(T("list value"), std::list(list_data, list_data + sizeof(list_data) / sizeof(*list_data))); - std::list list_value = pt.get >(T("list value")); - BOOST_CHECK(list_value.size() == 5); - BOOST_CHECK(list_value.front() == 1); - BOOST_CHECK(list_value.back() == 5); - -} - -void test_empty_size_max_size(PTREE *) -{ - - PTREE pt; - BOOST_CHECK(pt.max_size()); - BOOST_CHECK(pt.empty()); - BOOST_CHECK(pt.size() == 0); - - pt.put(T("test1"), 1); - BOOST_CHECK(pt.max_size()); - BOOST_CHECK(!pt.empty()); - BOOST_CHECK(pt.size() == 1); - - pt.put(T("test2"), 2); - BOOST_CHECK(pt.max_size()); - BOOST_CHECK(!pt.empty()); - BOOST_CHECK(pt.size() == 2); - -} - -void test_ptree_bad_path(PTREE *) -{ - - PTREE pt; - - try - { - pt.get(T("non.existent.path")); - } - catch (boost::property_tree::ptree_bad_path &e) - { - PTREE::path_type path = e.path(); - std::string what = e.what(); - BOOST_CHECK(what.find("non.existent.path") != std::string::npos); - return; - } - - BOOST_ERROR("No required exception thrown"); - -} - -void test_ptree_bad_data(PTREE *) -{ - - PTREE pt; - pt.put_value("non convertible to int"); - - try - { - pt.get_value(); - } - catch (boost::property_tree::ptree_bad_data &e) - { - PTREE::data_type data = e.data(); - std::string what = e.what(); - BOOST_CHECK(what.find("non convertible to int") != std::string::npos); - return; - } - - BOOST_ERROR("No required exception thrown"); -} - -void test_serialization(PTREE *) -{ - - // Prepare test tree - PTREE pt; - pt.put_value(1); - pt.put(T("key1"), 3); - pt.put(T("key1.key11)"), 3.3); - pt.put(T("key1.key12"), T("foo")); - pt.put(T("key2"), true); - pt.put(T("key2.key21.key211.key2111.key21111"), T("super deep!")); - pt.put_child(T("empty"), boost::property_tree::empty_ptree()); - pt.put(T("loooooong"), PTREE::data_type(10000, CHTYPE('a'))); - - // Endforce const for input - const PTREE &pt1 = pt; - - // Test text archives - { - std::stringstream stream; - boost::archive::text_oarchive oa(stream); - oa & pt1; - boost::archive::text_iarchive ia(stream); - PTREE pt2; - ia & pt2; - BOOST_CHECK(pt1 == pt2); - } - - // Test binary archives - { - std::stringstream stream; - boost::archive::binary_oarchive oa(stream); - oa & pt1; - boost::archive::binary_iarchive ia(stream); - PTREE pt2; - ia & pt2; - BOOST_CHECK(pt1 == pt2); - } - - // Test XML archives - { - std::stringstream stream; - boost::archive::xml_oarchive oa(stream); - oa & boost::serialization::make_nvp("pt", pt1); - boost::archive::xml_iarchive ia(stream); - PTREE pt2; - ia & boost::serialization::make_nvp("pt", pt2); - BOOST_CHECK(pt1 == pt2); - } - -} - -void test_bool(PTREE *) -{ - - // Prepare test tree - PTREE pt; - pt.put(T("bool.false.1"), false); - pt.put(T("bool.false.2"), T("0")); - pt.put(T("bool.true.1"), true); - pt.put(T("bool.true.2"), 1); - pt.put(T("bool.invalid.1"), T("")); - pt.put(T("bool.invalid.2"), T("tt")); - pt.put(T("bool.invalid.3"), T("ff")); - pt.put(T("bool.invalid.4"), T("2")); - pt.put(T("bool.invalid.5"), T("-1")); - - // Test false - for (PTREE::iterator it = pt.get_child(T("bool.false")).begin(); it != pt.get_child(T("bool.false")).end(); ++it) - BOOST_CHECK(it->second.get_value() == false); - - // Test true - for (PTREE::iterator it = pt.get_child(T("bool.true")).begin(); it != pt.get_child(T("bool.true")).end(); ++it) - BOOST_CHECK(it->second.get_value() == true); - - // Test invalid - for (PTREE::iterator it = pt.get_child(T("bool.invalid")).begin(); it != pt.get_child(T("bool.invalid")).end(); ++it) - { - BOOST_CHECK(it->second.get_value(false) == false); - BOOST_CHECK(it->second.get_value(true) == true); - } - -} - -void test_char(PTREE *) -{ - - // Prepare test tree - PTREE pt; -#if WIDECHAR == 0 - pt.put(T("char"), char('A')); -#endif - pt.put(T("signed char"), static_cast('A')); - pt.put(T("unsigned char"), static_cast('A')); - pt.put(T("signed char min"), (std::numeric_limits::min)()); - pt.put(T("signed char max"), (std::numeric_limits::max)()); - pt.put(T("unsigned char min"), (std::numeric_limits::min)()); - pt.put(T("unsigned char max"), (std::numeric_limits::max)()); - - // Verify normal conversions -#if WIDECHAR == 0 - BOOST_CHECK(pt.get(T("char")) == 'A'); -#endif - BOOST_CHECK(pt.get(T("signed char")) == static_cast('A')); - BOOST_CHECK(pt.get(T("unsigned char")) == static_cast('A')); - - // Verify that numbers are saved for signed and unsigned char - BOOST_CHECK(pt.get(T("signed char")) == int('A')); - BOOST_CHECK(pt.get(T("unsigned char")) == int('A')); - - // Verify ranges - BOOST_CHECK(pt.get(T("signed char min")) == (std::numeric_limits::min)()); - BOOST_CHECK(pt.get(T("signed char max")) == (std::numeric_limits::max)()); - BOOST_CHECK(pt.get(T("unsigned char min")) == (std::numeric_limits::min)()); - BOOST_CHECK(pt.get(T("unsigned char max")) == (std::numeric_limits::max)()); - -} - -void test_leaks(PTREE *) -{ - BOOST_CHECK(PTREE::debug_get_instances_count() == 0); -} diff --git a/test/test_registry_parser.cpp b/test/test_registry_parser.cpp deleted file mode 100644 index 2e7c348816..0000000000 --- a/test/test_registry_parser.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include "test_utils.hpp" - -// Only test registry parser if we have windows platform -#ifdef BOOST_WINDOWS - -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// Test data - -const char *data_1 = - "root\n" - "{\n" - " subkey1 \"default value 1\"\n" - " subkey2 \"default value 2\"\n" - " \\\\values\n" - " {\n" - " REG_NONE \"\"\n" - " REG_BINARY \"de ad be ef\"\n" - " REG_DWORD 1234567890\n" - " REG_QWORD 12345678901234567890\n" - " REG_SZ \"some text\"\n" - " REG_EXPAND_SZ \"some other text\"\n" - " }\n" - " \\\\types\n" - " {\n" - " REG_NONE 0\n" - " REG_BINARY 3\n" - " REG_DWORD 4\n" - " REG_QWORD 11\n" - " REG_SZ 1\n" - " REG_EXPAND_SZ 2\n" - " }\n" - "}\n"; - -template -void test_registry_parser() -{ - - using namespace boost::property_tree; - typedef typename Ptree::key_type::value_type Ch; - typedef std::basic_string Str; - - // Delete test registry key - RegDeleteKeyA(HKEY_CURRENT_USER, "boost ptree test"); - - // Get test ptree - Ptree pt; - std::basic_stringstream stream(detail::widen(data_1)); - read_info(stream, pt); - - try - { - - // Write to registry, read back and compare contents - Ptree pt2; - write_registry(HKEY_CURRENT_USER, detail::widen("boost ptree test"), pt); - read_registry(HKEY_CURRENT_USER, detail::widen("boost ptree test"), pt2); - BOOST_CHECK(pt == pt2); - - // Test binary translation - Str s = pt2.template get(detail::widen("root.\\values.REG_BINARY")); - std::vector bin = registry_parser::translate(REG_BINARY, s); - BOOST_REQUIRE(bin.size() == 4); - BOOST_CHECK(*reinterpret_cast(&bin.front()) == 0xEFBEADDE); - Str s2 = registry_parser::translate(REG_BINARY, bin); - BOOST_CHECK(s == s2); - - } - catch (std::exception &e) - { - BOOST_ERROR(e.what()); - } - - // Delete test registry key - RegDeleteKeyA(HKEY_CURRENT_USER, "boost ptree test"); - -} - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_registry_parser(); - //test_registry_parser(); -#ifndef BOOST_NO_CWCHAR - //test_registry_parser(); - //test_registry_parser(); -#endif - return 0; -} - -#else - -int test_main(int argc, char *argv[]) -{ - return 0; -} - -#endif diff --git a/test/test_utils.hpp b/test/test_utils.hpp deleted file mode 100644 index 2db2267348..0000000000 --- a/test/test_utils.hpp +++ /dev/null @@ -1,227 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2005 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#ifndef BOOST_PROPERTY_TREE_TEST_UTILS_INCLUDED -#define BOOST_PROPERTY_TREE_TEST_UTILS_INCLUDED - -#define BOOST_PROPERTY_TREE_DEBUG // Enable ptree debugging -#include - -// Do not deprecate insecure CRT calls on VC8 -#if (defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) && !defined(_CRT_SECURE_NO_DEPRECATE)) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -#include -#include -#include - -template -typename Ptree::size_type total_size(const Ptree &pt) -{ - typename Ptree::size_type size = 1; - for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) - size += total_size(it->second); - return size; -} - -template -typename Ptree::size_type total_keys_size(const Ptree &pt) -{ - typename Ptree::size_type size = 0; - for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) - { - size += it->first.size(); - size += total_keys_size(it->second); - } - return size; -} - -template -typename Ptree::size_type total_data_size(const Ptree &pt) -{ - typename Ptree::size_type size = pt.data().size(); - for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) - size += total_data_size(it->second); - return size; -} - -template -class test_file -{ -public: - test_file(const char *test_data, const char *filename) - { - if (test_data && filename) - { - name = filename; - std::basic_ofstream stream(name.c_str()); - while (*test_data) - { - stream << Ch(*test_data); - ++test_data; - } - BOOST_CHECK(stream.good()); - } - } - ~test_file() - { - if (!name.empty()) - remove(name.c_str()); - } -private: - std::string name; -}; - -template -Ptree get_test_ptree() -{ - using namespace boost::property_tree; - typedef typename Ptree::key_type::value_type Ch; - Ptree pt; - pt.put_value(detail::widen("data0")); - pt.put(detail::widen("key1"), detail::widen("data1")); - pt.put(detail::widen("key1.key"), detail::widen("data2")); - pt.put(detail::widen("key2"), detail::widen("data3")); - pt.put(detail::widen("key2.key"), detail::widen("data4")); - return pt; -} - -// Generic test for file parser -template -void generic_parser_test(Ptree &pt, - ReadFunc rf, - WriteFunc wf, - const char *test_data_1, - const char *test_data_2, - const char *filename_1, - const char *filename_2, - const char *filename_out) -{ - - using namespace boost::property_tree; - typedef typename Ptree::key_type::value_type Ch; - - // Create test files - test_file file_1(test_data_1, filename_1); - test_file file_2(test_data_2, filename_2); - test_file file_out("", filename_out); - - rf(filename_1, pt); // Read file - wf(filename_out, pt); // Write file - Ptree pt2; - rf(filename_out, pt2); // Read file again - - // Compare original with read - BOOST_CHECK(pt == pt2); - -} - -// Generic test for file parser with expected success -template -void generic_parser_test_ok(ReadFunc rf, - WriteFunc wf, - const char *test_data_1, - const char *test_data_2, - const char *filename_1, - const char *filename_2, - const char *filename_out, - unsigned int total_size, - unsigned int total_data_size, - unsigned int total_keys_size) -{ - - using namespace boost::property_tree; - - std::cerr << "(progress) Starting generic parser test with test file \"" << filename_1 << "\"\n"; - - // Make sure no instances exist - BOOST_CHECK(Ptree::debug_get_instances_count() == 0); - - try - { - - // Read file - Ptree pt; - generic_parser_test(pt, rf, wf, - test_data_1, test_data_2, - filename_1, filename_2, filename_out); - - // Determine total sizes - typename Ptree::size_type actual_total_size = ::total_size(pt); - typename Ptree::size_type actual_data_size = ::total_data_size(pt); - typename Ptree::size_type actual_keys_size = ::total_keys_size(pt); - if (actual_total_size != total_size || - actual_data_size != total_data_size || - actual_keys_size != total_keys_size) - std::cerr << "Sizes: " << (unsigned)::total_size(pt) << ", " << (unsigned)::total_data_size(pt) << ", " << (unsigned)::total_keys_size(pt) << "\n"; - - // Check total sizes - BOOST_CHECK(actual_total_size == total_size); - BOOST_CHECK(actual_data_size == total_data_size); - BOOST_CHECK(actual_keys_size == total_keys_size); - - } - catch (std::runtime_error &e) - { - BOOST_ERROR(e.what()); - } - - // Test for leaks - BOOST_CHECK(Ptree::debug_get_instances_count() == 0); - -} - -// Generic test for file parser with expected error -template -void generic_parser_test_error(ReadFunc rf, - WriteFunc wf, - const char *test_data_1, - const char *test_data_2, - const char *filename_1, - const char *filename_2, - const char *filename_out, - unsigned long expected_error_line) -{ - - std::cerr << "(progress) Starting generic parser test with test file \"" << filename_1 << "\"\n"; - - // Make sure no instances exist - BOOST_CHECK(Ptree::debug_get_instances_count() == 0); - - { - - // Create ptree as a copy of test ptree (to test if read failure does not damage ptree) - Ptree pt(get_test_ptree()); - try - { - generic_parser_test(pt, rf, wf, - test_data_1, test_data_2, - filename_1, filename_2, filename_out); - BOOST_ERROR("No required exception thrown"); - } - catch (Error &e) - { - BOOST_CHECK(e.line() == expected_error_line); // Test line number - BOOST_CHECK(pt == get_test_ptree()); // Test if error damaged contents - } - catch (...) - { - BOOST_ERROR("Invalid exception type thrown"); - throw; - } - - } - - // Test for leaks - BOOST_CHECK(Ptree::debug_get_instances_count() == 0); - -} - -#endif diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp deleted file mode 100644 index 9eeb04b24e..0000000000 --- a/test/test_xml_parser_common.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#ifndef TEST_XML_PARSER_COMMON_HPP_INCLUDED -#define TEST_XML_PARSER_COMMON_HPP_INCLUDED - -#include "test_utils.hpp" -#include -#include "xml_parser_test_data.hpp" - -struct ReadFunc -{ - template - void operator()(const std::string &filename, Ptree &pt) const - { - boost::property_tree::read_xml(filename, pt); - } -}; - -struct WriteFunc -{ - template - void operator()(const std::string &filename, const Ptree &pt) const - { - boost::property_tree::write_xml(filename, pt); - } -}; - -template -void test_xml_parser() -{ - - using namespace boost::property_tree; - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_1, NULL, - "testok1.xml", NULL, "testok1out.xml", 2, 0, 5 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_2, NULL, - "testok2.xml", NULL, "testok2out.xml", 5, 15, 7 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_3, NULL, - "testok3.xml", NULL, "testok3out.xml", 787, 31346, 3831 - ); - - generic_parser_test_ok - ( - ReadFunc(), WriteFunc(), ok_data_4, NULL, - "testok4.xml", NULL, "testok4out.xml", 5, 2, 20 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_1, NULL, - "testerr1.xml", NULL, "testerr1out.xml", 1 - ); - - generic_parser_test_error - ( - ReadFunc(), WriteFunc(), error_data_2, NULL, - "testerr2.xml", NULL, "testerr2out.xml", 2 - ); - -} - -#endif diff --git a/test/test_xml_parser_pugxml.cpp b/test/test_xml_parser_pugxml.cpp deleted file mode 100644 index b873c3c292..0000000000 --- a/test/test_xml_parser_pugxml.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#define _CRT_SECURE_NO_DEPRECATE -#define BOOST_PROPERTY_TREE_XML_PARSER_PUGXML -#include "test_xml_parser_common.hpp" - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_xml_parser(); - //test_xml_parser(); -#ifndef BOOST_NO_CWCHAR - //test_xml_parser(); - //test_xml_parser(); -#endif - return 0; -} diff --git a/test/test_xml_parser_rapidxml.cpp b/test/test_xml_parser_rapidxml.cpp deleted file mode 100644 index 5abc18f45e..0000000000 --- a/test/test_xml_parser_rapidxml.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include "test_xml_parser_common.hpp" - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_xml_parser(); - test_xml_parser(); -#ifndef BOOST_NO_CWCHAR - test_xml_parser(); - test_xml_parser(); -#endif - return 0; -} diff --git a/test/test_xml_parser_spirit.cpp b/test/test_xml_parser_spirit.cpp deleted file mode 100644 index 75cc49a215..0000000000 --- a/test/test_xml_parser_spirit.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#define BOOST_PROPERTY_TREE_XML_PARSER_SPIRIT -#include "test_xml_parser_common.hpp" - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_xml_parser(); - test_xml_parser(); -#ifndef BOOST_NO_CWCHAR - test_xml_parser(); - test_xml_parser(); -#endif - return 0; -} diff --git a/test/test_xml_parser_tinyxml.cpp b/test/test_xml_parser_tinyxml.cpp deleted file mode 100644 index eb4be3cb59..0000000000 --- a/test/test_xml_parser_tinyxml.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2005 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#ifdef _DEBUG - #pragma comment( lib, "tinyxmld_STL.lib" ) -#else - #pragma comment( lib, "tinyxml_STL.lib" ) -#endif - -#define BOOST_PROPERTY_TREE_XML_PARSER_TINYXML -#include "test_xml_parser_common.hpp" - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_xml_parser(); - test_xml_parser(); - return 0; -} diff --git a/test/xml_parser_test_data.hpp b/test/xml_parser_test_data.hpp deleted file mode 100644 index 557b052b77..0000000000 --- a/test/xml_parser_test_data.hpp +++ /dev/null @@ -1,743 +0,0 @@ -#ifndef XML_PARSER_TEST_DATA_HPP_INCLUDED -#define XML_PARSER_TEST_DATA_HPP_INCLUDED - -/////////////////////////////////////////////////////////////////////////////// -// Test data - -// Correct -const char *ok_data_1 = - "\n" - ""; - -// Correct -const char *ok_data_2 = - "\n" - "\n" - "<>&\n" - "1<2>3&4\n" - " < > & \n" - "\n"; - -// Correct -const char *ok_data_3 = - "\n" - "\n" - "\n" - "]>\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "
\n" - " XML Linking Language (XLink)\n" - " Version 1.0\n" - " WD-xlink-19990527\n" - " World Wide Web Consortium Working Draft\n" - " 29May1999\n" - " \n" - "

This draft is for public discussion.

\n" - "
\n" - " http://www.w3.org/XML/Group/1999/05/WD-xlink-current\n" - " \n" - " \n" - " http://www.w3.org/XML/Group/1999/05/WD-xlink-19990527\n" - " http://www.w3.org/XML/Group/1999/05/WD-xlink-19990505\n" - " http://www.w3.org/TR/1998/WD-xlink-19980303\n" - " http://www.w3.org/TR/WD-xml-link-970630\n" - "\n" - " \n" - " \n" - " \n" - " \n" - " Steve DeRose\n" - " Inso Corp. and Brown University\n" - " Steven_DeRose@Brown.edu\n" - " \n" - " \n" - " David Orchard\n" - " IBM Corp.\n" - " dorchard@ca.ibm.com\n" - " \n" - " \n" - " Ben Trafford\n" - " Invited Expert\n" - " bent@exemplary.net\n" - " \n" - " \n" - " \n" - "\n" - " \n" - "

This is a W3C Working Draft for review by W3C members and other interested parties. It is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use W3C Working Drafts as reference material or to cite them as other than \"work in progress\". A list of current W3C working drafts can be found at http://www.w3.org/TR.

\n" - "

Note: Since working drafts are subject to frequent change, you are advised to reference the above URI, rather than the URIs for working drafts themselves. Some of the work remaining is described in .

\n" - "

This work is part of the W3C XML Activity (for current status, see http://www.w3.org/XML/Activity ). For information about the XPointer language which is expected to be used with XLink, see http://www.w3.org/TR/WD-xptr.\n" - "

\n" - "

See http://www.w3.org/TR/NOTE-xlink-principles for additional background on the design principles informing XLink.

\n" - "

Also see http://www.w3.org/TR/NOTE-xlink-req/ for the XLink requirements that this document attempts to satisfy.

\n" - "
\n" - "\n" - " \n" - " \n" - "

This specification defines constructs that may be inserted into XML DTDs, schemas and document instances to describe links between objects. It uses XML syntax to create structures that can describe the simple unidirectional hyperlinks of today's HTML as well as more sophisticated links.

\n" - "
\n" - "\n" - " \n" - "

Burlington, Seekonk, et al.: World-Wide Web Consortium, XML Working Group, 1998.

\n" - "
\n" - "\n" - " \n" - "

Created in electronic form.

\n" - "
\n" - "\n" - " \n" - " English\n" - " Extended Backus-Naur Form (formal grammar)\n" - " \n" - "\n" - " \n" - " \n" - " 1997-01-15 : Skeleton draft by TB\n" - " 1997-01-24 : Fleshed out by sjd\n" - " 1997-04-08 : Substantive draft\n" - " 1997-06-30 : Public draft\n" - " 1997-08-01 : Public draft\n" - " 1997-08-05 : Prose/organization work by sjd\n" - " 1997-10-14: Conformance and design principles; a bit of cleanup by elm\n" - " 1997-11-07: Update for editorial issues per issues doc, by sjd.\n" - " 1997-12-01: Update for editorial issues per issues doc in preparation for F2F meeting, by sjd.\n" - " 1998-01-13: Editorial cleanup, addition of new design principles, by elm.\n" - " 1998-02-27: Splitting out of XLink and XPointer, by elm.\n" - " 1998-03-03: Moved most of the XPointer locator stuff here. elm\n" - " 1999-04-24: Editorial rewrites to represent new ideas on XLink, especially the inclusion of arcs. bent\n" - " 1999-05-05: Prose/organization work by dorchard. Moved much of the semantics section around, from: locators, link semantics, remote resource semantics, local resource semantics; to: resource semantics, locators, behavior semantics, link semantics, arc semantics\n" - " 1999-05-12: Prose/organization work. Re-organized some of the sections, removed XML constructs from the document, added descriptive prose, edited document text for clarity. Rewrote the link recognition section. bent\n" - " 1999-05-17: Further prose work. Added non-normative examples. Clarified arcs. bent\n" - " 1999-05-23: Edited for grammar and clarity. bent\n" - " 1999-05-27: Final once-over before sending to group. Fixed sjd's email address. bent\n" - " \n" - " \n" - "
\n" - "\n" - "\n" - " \n" - " Introduction\n" - "

This specification defines constructs that may be inserted into XML DTDs, schemas, and document instances to describe links between objects. A link, as the term is used here, is an explicit relationship between two or more data objects or portions of data objects. This specification is concerned with the syntax used to assert link existence and describe link characteristics. Implicit (unasserted) relationships, for example that of one word to the next or that of a word in a text to its entry in an on-line dictionary are obviously important, but outside its scope.

\n" - "

Links are asserted by elements contained in XML document instances. The simplest case is very like an HTML A link, and has these characteristics:\n" - " \n" - "

The link is expressed at one of its ends (similar to the A element in some document)

\n" - "

Users can only initiate travel from that end to the other

\n" - "

The link's effect on windows, frames, go-back lists, stylesheets in use, and so on is mainly determined by browsers, not by the link itself. For example, traveral of A links normally replaces the current view, perhaps with a user option to open a new window.

\n" - "

The link goes to only one destination (although a server may have great freedom in finding or dynamically creating that destination).

\n" - " \n" - "

\n" - "

While this set of characteristics is already very powerful and obviously has proven itself highly useful and effective, each of these assumptions also limits the range of hypertext functionality. The linking model defined here provides ways to create links that go beyond each of these specific characteristics, thus providing features previously available mostly in dedicated hypermedia systems.\n" - "

\n" - "\n" - "\n" - " Origin and Goals\n" - "

Following is a summary of the design principles governing XLink:\n" - " \n" - "

XLink must be straightforwardly usable over the Internet.

\n" - "

XLink must be usable by a wide variety of link usage domains and classes of linking application software.

\n" - "

XLink must support HTML 4.0 linking constructs.

\n" - "

The XLink expression language must be XML.

\n" - "

The XLink design must be formal, concise, and illustrative.

\n" - "

XLinks must be human-readable and human-writable.

\n" - "

XLinks may reside within or outside the documents in which the\n" - " participating resources reside.

\n" - "

XLink must represent the abstract structure and significance of links.

\n" - "

XLink must be feasible to implement.

\n" - "

XLink must be informed by knowledge of established hypermedia systems and standards.

\n" - " \n" - "

\n" - "
\n" - "\n" - "\n" - "\n" - " Relationship to Existing Standards\n" - "

Three standards have been especially influential:\n" - " \n" - "

HTML: Defines several SGML element types that represent links.

\n" - "

HyTime: Defines inline and out-of-line link structures and some semantic features, including traversal control and presentation of objects. \n" - "

\n" - "

Text Encoding Initiative Guidelines (TEI P3): Provides structures for creating links, aggregate objects, and link collections out of them.

\n" - " \n" - "

\n" - "

Many other linking systems have also informed this design, especially Dexter, FRESS, MicroCosm, and InterMedia.

\n" - "
\n" - "\n" - "\n" - " Terminology\n" - "

The following basic terms apply in this document. \n" - " \n" - " \n" - " \n" - "

A symbolic representation of traversal behavior in links, especially the direction, context and timing of traversal.

\n" - " \n" - " \n" - " \n" - "

A representation of the relevant structure specified by the tags and attributes in an XML document, based on \"groves\" as defined in the ISO DSSSL standard.

\n" - "
\n" - " \n" - " \n" - "

Abstractly, a link which serves as one of its own resources. Concretely, a link where the content of the linking element serves as a participating resource.\n" - " HTML A, HyTime clink, and TEI XREF\n" - " are all inline links.

\n" - "
\n" - " \n" - " \n" - "

An explicit relationship between two or more data objects or portions of data objects.

\n" - "
\n" - " \n" - " \n" - "

An element that asserts the existence and describes the characteristics of a link.

\n" - "
\n" - " \n" - " \n" - "

The content of an inlinelinking element. Note that the content of the linking element could be explicitly pointed to by means of a regular locator in the same linking element, in which case the resource is considered remote, not local.

\n" - "
\n" - " \n" - " \n" - "

Data, provided as part of a link, which identifies a\n" - " resource.

\n" - "
\n" - " \n" - " \n" - "

A link whose traversal can be initiated from more than one of its participating resources. Note that being able to \"go back\" after following a one-directional link does not make the link multidirectional.

\n" - "
\n" - " \n" - " \n" - "

A link whose content does not serve as one of the link's participating resources . Such links presuppose a notion like extended link groups, which instruct application software where to look for links. Out-of-line links are generally required for supporting multidirectional traversal and for allowing read-only resources to have outgoing links.

\n" - "
\n" - " \n" - "

In the context of link behavior, a parsed link is any link whose content is transcluded into the document where the link originated. The use of the term \"parsed\" directly refers to the concept in XML of a\n" - " parsed entity.

\n" - "
\n" - " \n" - " \n" - "

A resource that belongs to a link. All resources are potential contributors to a link; participating resources are the actual contributors to a particular link.

\n" - "
\n" - " \n" - " \n" - "

Any participating resource of a link that is pointed to with a locator.

\n" - "
\n" - " \n" - " \n" - "

In the abstract sense, an addressable unit of information or service that is participating in a link. Examples include files, images, documents, programs, and query results. Concretely, anything reachable by the use of a locator in some linking element. Note that this term and its definition are taken from the basic specifications governing the World Wide Web. \n" - "

\n" - "
\n" - " \n" - " \n" - "

A portion of a resource, pointed to as the precise destination of a link. As one example, a link might specify that an entire document be retrieved and displayed, but that some specific part(s) of it is the specific linked data, to be treated in an application-appropriate manner such as indication by highlighting, scrolling, etc.

\n" - "
\n" - " \n" - " \n" - "

The action of using a link; that is, of accessing a resource. Traversal may be initiated by a user action (for example, clicking on the displayed content of a linking element) or occur under program control.

\n" - "
\n" - " \n" - "

\n" - "
\n" - "\n" - "\n" - " Notation\n" - "

The formal grammar for locators is given using a simple Extended Backus-Naur Form (EBNF) location, as described in the XML specification.

\n" - " \n" - "
\n" - "
\n" - "\n" - "\n" - " Locator Syntax\n" - "

The locator for a resource is typically provided by means of a Uniform Resource Identifier, or URI. XPointers can be used in conjunction with the URI structure, as fragment identifiers, to specify a more precise sub-resource.

\n" - " \n" - "

A locator generally contains a URI, as described in IETF RFCs and . As these RFCs state, the URI may include a trailing query (marked by a leading \"?\"), and be followed by a \"#\" and a fragment identifier, with the query interpreted by the host providing the indicated resource, and the interpretation of the fragment identifier dependent on the data type of the indicated resource.

\n" - " \n" - "

In order to locate XML documents and portions of documents, a locator value may contain either a URI or a fragment identifier, or both. Any fragment identifier for pointing into XML must be an XPointer.

\n" - "

Special syntax may be used to request the use of particular processing models in accessing the locator's resource. This is designed to reflect the realities of network operation, where it may or may not be desirable to exercise fine control over the distribution of work between local and remote processors. \n" - " \n" - " Locator\n" - " \n" - " Locator\n" - " URI\n" - " | Connector (XPointer | Name)\n" - " | URI Connector (XPointer | Name)\n" - " \n" - " \n" - " Connector'#' | '|'\n" - " \n" - " \n" - " URIURIchar*\n" - " \n" - " \n" - "

\n" - "

In this discussion, the term designated resource refers to the resource which an entire locator serves to locate. The following rules apply:\n" - " \n" - " \n" - "

The URI, if provided, locates a resource called the containing resource.

\n" - " \n" - " \n" - "

If the URI is not provided, the containing resource is considered to be the document in which the linking element is contained. \n" - "

\n" - " \n" - "

If an XPointer is provided, the designated resource is a sub-resource\n" - " of the containing resource; otherwise the designated resource is the\n" - " containing resource.

\n" - "
\n" - " \n" - " \n" - "

If the Connector is followed directly by a Name, the Name is shorthand for the XPointer\"id(Name)\"; that is, the sub-resource is the element in the containing resource that has an XML ID attribute whose value matches the Name. This shorthand is to encourage use of the robust id addressing mode.

\n" - "
\n" - " \n" - " \n" - "

If the connector is \"#\", this signals an intent that the containing resource is to be fetched as a whole from the host that provides it, and that the XPointer processing to extract the sub-resource\n" - " is to be performed on the client, that is to say on the same system where the linking element is recognized and processed.

\n" - "
\n" - " \n" - "

If the connector is \"|\", no intent is signaled as to what processing model is to be used to go about accessing the designated resource.

\n" - "
\n" - " \n" - "

\n" - "

Note that the definition of a URI includes an optional query component.

\n" - "

In the case where the URI contains a query (to be interpreted by the server), information providers and authors of server software are urged to use queries as follows: \n" - " \n" - " Query\n" - " \n" - " Query'XML-XPTR=' ( XPointer | Name)\n" - " \n" - " \n" - "

\n" - " \n" - "
\n" - "\n" - "\n" - " Link Recognition\n" - "

The existence of a link is asserted by a linking element. Linking elements must be recognized reliably by application software in order to provide appropriate display and behavior. There are several ways link recognition could be accomplished: for example, reserving element type names, reserving attributes names, leaving the matter of recognition entirely up to stylesheets and application software, or using the XLink namespace to specify element names and attribute names that would be recognized by namespace and XLink-aware processors. Using element and attribute names within the XLink namespace provides a balance between giving users control of their own markup language design and keeping the identification of linking elements simple and unambiguous.

\n" - "

The two approaches to identifying linking elements are relatively simple to implement. For example, here's how the HTML A element would be declared using attributes within the XLink namespace, and then how an element within the XLink namespace might do the same:\n" - " <A xlink:type=\"simple\" xlink:href=\"http://www.w3.org/TR/wd-xlink/\"\n" - "xlink:title=\"The Xlink Working Draft\">The XLink Working Draft.</A>\n" - " <xlink:simple href=\"http://www.w3.org/TR/wd-xlink/\"\n" - "title=\"The XLink Working Draft\">The XLink Working Draft</xlink:simple>\n" - " Any arbitrary element can be made into an XLink by using the xlink:type attribute. And, of course, the explicit XLink elements may be used, as well. This document will go on to describe the linking attributes that are associated with linking elements. It may be assumed by the reader that these attributes would require the xlink namespace prefix if they existed within an arbitrary element, or that they may be used directly if they exist within an explicit Xlink element.

\n" - " \n" - "
\n" - "\n" - "\n" - "\n" - " Linking Attributes\n" - "

XLink has several attributes associated with the variety of links it may represent. These attributes define four main concepts: locators, arcs, behaviors, and semantics. Locators define where the actual resource is located. Arcs define the traversal of links. Where does the link come from? Where does it go to? All this information can be stored in the arc attributes. Behaviors define how the link is activated, and what the application should do with the resource being linked to. Semantics define useful information that the application may use, and enables the link for such specalized targets as constricted devices and accessibility software.

\n" - " \n" - " \n" - " Locator Attributes\n" - "

The only locator attribute at this time is href. This attribute must contain either a string in the form of a URI that defines the remote resource being linked to, a string containing a fragment identifier that links to a local resource, or a string containing a URI with a fragment identifier concacenated onto it.

\n" - "
\n" - "\n" - " \n" - " Arc Attributes\n" - "

Arcs contain two attributes, from and to. The from attribute may contain a string containing the content of a role attribute from the resource being linked from. The purpose of the from attribute is to define where this link is being actuated from.

\n" - "

The to attribute may contain a string containing the content of a role attribute from the resource being linked to. The purpose of the to attribute is to define where this link traverses to.

\n" - "

The application may use this information in a number of ways, especially in a complex hypertext system, but it is mainly useful in providing context for application behavior.

\n" - " \n" - "
\n" - "\n" - " \n" - " Behavior Attributes\n" - "

There are two attributes associated with behavior: show and actuate. The show attribute defines how the remote resource is to be revealed to the user. It has three options: new, parsed, and replace. The new option indicates that the remote resource should be shown in a new window (or other device context) without replacing the previous content. The parsed option, relating directly to the XML concept of a parsed entity, indicates that the content should be integrated into the document from which the link was actuated. The replace option is the one most commonly seen on the World Wide Web, where the document being linked from is entirely replaced by the object being linked to.

\n" - "

The actuate attribute defines how the link is initiated. It has two options: user and auto. The user option indicates that the link must be initiated by some sort of human-initiated selection, such as clicking on an HTML anchor. The auto option indicates that the link is automatically initiated when the application deems that the user has reached the link. It then follows the behavior set out in the show option.

\n" - " \n" - "
\n" - "\n" - " \n" - " Semantic Attributes\n" - "

There are two attributes associated with semantics, role and title. The role attribute is a generic string used to describe the function of the link's content. For example, a poem might have a link with a role=\"stanza\". The role is also used as an identifier for the from and to attributes of arcs.

\n" - "

The title attribute is designed to provide human-readable text describing the link. It is very useful for those who have text-based applications, whether that be due to a constricted device that cannot display the link's content, or if it's being read by an application to a visually-impaired user, or if it's being used to create a table of links. The title attribute contains a simple, descriptive string.

\n" - "
\n" - "
\n" - "\n" - "\n" - " Linking Elements\n" - "

There are several kinds of linking elements in XLink: simple links, locators, arcs, and extended links. These elements may be instantiated via element declarations from the XLink namespace, or they may be instantiated via attribute declarations from the XLink namespace. Both kinds of instantiation are described in the definition of each linking element.

\n" - "

The simple link is used to declare a link that approximates the functionality of the HTML A element. It has, however, a few added features to increase its value, including the potential declaration of semantics and behavior. The locator elements are used to define the resource being linked to. Some links may contain multiple locators, representing a choice of potential links to be traversed. The arcs are used to define the traversal semantics of the link. Finally, an extended linking element differs from a simple link in that it can connect any number of resources, not just one local resource (optionally) and one remote resource, and in that extended links are more often out-of-line than simple links.

\n" - "\n" - "\n" - " Simple Links\n" - "

Simple links can be used for purposes that approximate the functionality of a basic HTML A link, but they can also support a limited amount of additional functionality. Simple links have only one locator and thus, for convenience, combine the functions of a linking element and a locator into a single element. As a result of this combination, the simple linking element offers both a locator attribute and all the behavior and semantic attributes.

\n" - "

The following are two examples of linking elements, each showing all the possible attributes that can be associated with a simple link. Here is the explicit XLink simple linking element.\n" - " <!ELEMENT xlink:simple ANY>\n" - "<!ATTLIST xlink:slink\n" - " href CDATA #REQUIRED\n" - " role CDATA #IMPLIED\n" - " title CDATA #IMPLIED\n" - " show (new|parsed|replace) \"replace\"\n" - " actuate (user|auto) \"user\"\n" - ">\n" - " And here is how to make an arbitrary element into a simple link.\n" - " <!ELEMENT xlink:simple ANY>\n" - "<!ATTLIST foo\n" - " xlink:type (simple|extended|locator|arc) #FIXED \"simple\" \n" - " xlink:href CDATA #REQUIRED\n" - " xlink:role CDATA #IMPLIED\n" - " xlink:title CDATA #IMPLIED\n" - " xlink:show (new|parsed|replace) \"replace\"\n" - " xlink:actuate (user|auto) \"user\"\n" - ">\n" - " Here is how the first example might look in a document:\n" - "<xlink:simple href=\"http://www.w3.org/TR/wd-xlink\" role=\"working draft\" \n" - " title=\"The XLink Working Draft\" show=\"replace\" actuate=\"user\">\n" - "The XLink Working Draft.</xlink:simple>\n" - "<foo xlink:href=\"http://www.w3.org/TR/wd-xlink\" xlink:role=\"working draft\"\n" - " xlink:title=\"The XLink Working Draft\" xlink:show=\"new\" xlink:actuate=\"user\">\n" - "The XLink Working Draft.</foo>\n" - " Alternately, a simple link could be as terse as this:\n" - "<foo xlink:href=\"#stanza1\">The First Stanza.</foo>\n" - "

\n" - "

\n" - " There are no constraints on the contents of a simple linking element. In\n" - " the sample declaration above, it is given a content model of ANY\n" - " to illustrate that any content model or declared content is acceptable. In\n" - " a valid document, every element that is significant to XLink must still conform\n" - " to the constraints expressed in its governing DTD.

\n" - "

Note that it is meaningful to have an out-of-line simple link, although\n" - " such links are uncommon. They are called \"one-ended\" and are typically used\n" - " to associate discrete semantic properties with locations. The properties might\n" - " be expressed by attributes on the link, the link's element type name, or in\n" - " some other way, and are not considered full-fledged resources of the link.\n" - " Most out-of-line links are extended links, as these have a far wider range\n" - " of uses.

\n" - "
\n" - "\n" - "\n" - "Extended Links\n" - "

An extended link differs from a simple link in that it can connect any number of resources, not just one local resource (optionally) and one remote resource, and in that extended links are more often out-of-line than simple links.

\n" - "

These additional capabilities of extended links are required for: \n" - " \n" - " \n" - "

Enabling outgoing links in documents that cannot be modified to add an inline link

\n" - " \n" - " \n" - "

Creating links to and from resources in formats with no native support for embedded links (such as most multimedia formats)

\n" - "
\n" - " \n" - "

Applying and filtering sets of relevant links on demand

\n" - "
\n" - "

Enabling other advanced hypermedia capabilities

\n" - " \n" - "

\n" - "

Application software might be expected to provide traversal among all of a link's participating resources (subject to semantic constraints outside the scope of this specification) and to signal the fact that a given resource or sub-resource participates in one or more links when it is displayed (even though there is no markup at exactly that point to signal it).

\n" - "

A linking element for an extended link contains a series of child elements that serve as locators and arcs. Because an extended link can have more than one remote resource, it separates out linking itself from the mechanisms used to locate each resource (whereas a simple link combines the two).

\n" - "

The xlink:type attribute value for an extended link must be extended, if the link is being instantiated on an arbitrary element. Note that extended links introduce variants of the show and actuate behavior attributes. These attributes, the showdefault and actuatedefault define the same behavior as their counterparts. However, in this case, they are considered to define the default behavior for all the linking elements that they contain.

\n" - "

However, when a linking element within an extended link has a show or actuate attribute of its own, that attribute overrides the defaults set on the extended linking element.

\n" - "

The extended linking element itself retains those attributes relevant to the link as a whole, and to its local resource if any. Following are two sample declaration for an extended link. The first is an example of the explicit XLink extended link:\n" - " \n" - "<!ELEMENT xlink:extended ((xlink:arc | xlink:locator)*)>\n" - "<!ATTLIST xlink:extended\n" - " role CDATA #IMPLIED\n" - " title CDATA #IMPLIED\n" - " showdefault (new|parsed|replace) #IMPLIED \n" - " actuatedefault (user|auto) #IMPLIED >\n" - "\n" - " The second is an example of an arbitrary element being used an extended link:\n" - "\n" - "<!ELEMENT foo ((xlink:arc | xlink:locator)*)>\n" - "<!ATTLIST foo\n" - " xlink:type (simple|extended|locator|arc) #FIXED \"extended\"\n" - " xlink:role CDATA #IMPLIED\n" - " xlink:title CDATA #IMPLIED\n" - " xlink:showdefault (new|parsed|replace) #IMPLIED \n" - " xlink:actuatedefault (user|auto) #IMPLIED >\n" - "\n" - " The following two examples demonstrate how each of the above might appear within a document instance. Note that the content of these examples would be other elements. For brevity's sake, they've been left blank. The first example shows how the link might appear, using an explicit XLink extended link:\n" - "\n" - "<xlink:extended role=\"address book\" title=\"Ben's Address Book\" showdefault=\"replace\" actuatedefault=\"user\"> ... </xlink:extended>\n" - "\n" - " And the second shows how the link might appear, using an arbitrary element:\n" - "\n" - "<foo xlink:type=\"extended\" xlink:role=\"address book\" xlink:title=\"Ben's Address Book\" xlink:showdefault=\"replace\" xlink:actuatedefault=\"user\"> ... </foo>\n" - "

\n" - "\n" - "
\n" - "\n" - "\n" - " Arc Elements\n" - "

An arc is contained within an extended link for the purpose of defining traversal behavior. More than one arc may be associated with a link. Otherwise, arc elements function exactly as the arc attributes might lead on to expect.

\n" - " \n" - "
\n" - "\n" - "
\n" - "\n" - "Conformance\n" - "

An element conforms to XLink if: \n" - "

The element has an xml:link attribute whose value is\n" - "one of the attribute values prescribed by this specification, and

\n" - "

the element and all of its attributes and content adhere to the\n" - "syntactic\n" - "requirements imposed by the chosen xml:link attribute value,\n" - "as prescribed in this specification.

\n" - "

\n" - "

Note that conformance is assessed at the level of individual elements,\n" - "rather than whole XML documents, because XLink and non-XLink linking mechanisms\n" - "may be used side by side in any one document.

\n" - "

An application conforms to XLink if it interprets XLink-conforming elements\n" - "according to all required semantics prescribed by this specification and,\n" - "for any optional semantics it chooses to support, supports them in the way\n" - "prescribed.

\n" - "
\n" - "\n" - "\n" - "Unfinished Work\n" - "\n" - "Structured Titles\n" - "

The simple title mechanism described in this draft is insufficient to cope\n" - "with internationalization or the use of multimedia in link titles. A future\n" - "version will provide a mechanism for the use of structured link titles.

\n" - "
\n" - "
\n" - "\n" - "References\n" - "\n" - "Eve Maler and Steve DeRose, editors. \n" - "XML Pointer Language (XPointer) V1.0. ArborText, Inso, and Brown\n" - "University. Burlington, Seekonk, et al.: World Wide Web Consortium, 1998.\n" - "(See http://www.w3.org/TR/WD-xptr\n" - " .)\n" - "ISO (International Organization for\n" - "Standardization). ISO/IEC 10744-1992 (E). Information technology\n" - "- Hypermedia/Time-based Structuring Language (HyTime). [Geneva]:\n" - "International Organization for Standardization, 1992. Extended\n" - "Facilities\n" - "Annex. [Geneva]: International Organization for Standardization,\n" - "1996. (See http://www.ornl.go\n" - "v/sgml/wg8/hytime/html/is10744r.html ).\n" - "IETF (Internet Engineering Task\n" - "Force). \n" - "RFC 1738: Uniform Resource Locators. 1991. (See \n" - "http://www.w3.org/Addressing/rfc1738.txt).\n" - "IETF (Internet Engineering Task\n" - "Force). \n" - "RFC 1808: Relative Uniform Resource Locators. 1995. (See http://www.w3.org/Addressing/rfc\n" - "1808.txt ).\n" - "C. M. Sperberg-McQueen and Lou Burnard, editors.\n" - "\n" - "Guidelines for Electronic Text Encoding and Interchange. Association\n" - "for Computers and the Humanities (ACH), Association for Computational\n" - "Linguistics\n" - "(ACL), and Association for Literary and Linguistic Computing (ALLC). Chicago,\n" - "Oxford: Text Encoding Initiative, 1994. \n" - "]Steven J. DeRose and David G. Durand. 1995. \"The\n" - "TEI Hypertext Guidelines.\" In Computing and the Humanities\n" - "29(3).\n" - "Reprinted in Text Encoding Initiative: Background and\n" - "Context,\n" - "ed. Nancy Ide and Jean ronis , ISBN 0-7923-3704-2. \n" - "\n" - "
\n" - "\n"; - -// Correct -const char *ok_data_4 = - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - " \n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "]>\n" - "\n" - "\n" - "\n" - "PP\n" - "\n" - "\n"; - -// Erroneous -const char *error_data_1 = - "a"; // bogus character - -// Erroneous -const char *error_data_2 = - "\n" - ""; // XML tag not closed - -#endif From 88ee5f0811e38c5fb2355588af499060507400e7 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:38:02 +0000 Subject: [PATCH 02/23] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41370] --- examples/custom_data_type.cpp | 80 ++ examples/debug_settings.cpp | 109 ++ examples/debug_settings.xml | 10 + examples/empty_ptree_trick.cpp | 71 + examples/info_grammar_spirit.cpp | 152 ++ examples/settings_fully-existent.info | 6 + examples/settings_non-existent.info | 6 + examples/settings_partially-existent.info | 6 + examples/speed_test.cpp | 134 ++ index.html | 12 + test/Jamfile.v2 | 17 + test/custom-build/Makefile | 5 + test/custom-build/Makefile-Common | 80 ++ test/custom-build/debug_settings.xml | 10 + test/custom-build/gcc.mak | 6 + test/custom-build/icc.mak | 6 + test/custom-build/sandbox.vcproj | 330 +++++ .../custom-build/settings_fully-existent.info | 6 + test/custom-build/settings_non-existent.info | 6 + .../settings_partially-existent.info | 6 + .../test_example_custom_data_type.vcproj | 189 +++ .../test_example_debug_settings.vcproj | 189 +++ .../test_example_empty_ptree_trick.vcproj | 189 +++ .../test_info_grammar_spirit.vcproj | 189 +++ test/custom-build/test_info_parser.vcproj | 189 +++ test/custom-build/test_ini_parser.vcproj | 189 +++ test/custom-build/test_json_parser.vcproj | 189 +++ test/custom-build/test_multi_module.vcproj | 193 +++ test/custom-build/test_property_tree.vcproj | 194 +++ test/custom-build/test_xml_parser.vcproj | 197 +++ test/custom-build/tests.sln | 80 ++ test/custom-build/vc.mak | 7 + test/sandbox.cpp | 13 + test/test_cmdline_parser.cpp | 116 ++ test/test_info_parser.cpp | 249 ++++ test/test_ini_parser.cpp | 198 +++ test/test_json_parser.cpp | 384 +++++ test/test_multi_module1.cpp | 21 + test/test_multi_module2.cpp | 18 + test/test_property_tree.cpp | 263 ++++ test/test_property_tree.hpp | 1263 +++++++++++++++++ test/test_registry_parser.cpp | 110 ++ test/test_utils.hpp | 227 +++ test/test_xml_parser_common.hpp | 79 ++ test/test_xml_parser_pugxml.cpp | 25 + test/test_xml_parser_rapidxml.cpp | 23 + test/test_xml_parser_spirit.cpp | 24 + test/test_xml_parser_tinyxml.cpp | 26 + test/xml_parser_test_data.hpp | 743 ++++++++++ 49 files changed, 6834 insertions(+) create mode 100644 examples/custom_data_type.cpp create mode 100644 examples/debug_settings.cpp create mode 100644 examples/debug_settings.xml create mode 100644 examples/empty_ptree_trick.cpp create mode 100644 examples/info_grammar_spirit.cpp create mode 100644 examples/settings_fully-existent.info create mode 100644 examples/settings_non-existent.info create mode 100644 examples/settings_partially-existent.info create mode 100644 examples/speed_test.cpp create mode 100644 index.html create mode 100644 test/Jamfile.v2 create mode 100644 test/custom-build/Makefile create mode 100644 test/custom-build/Makefile-Common create mode 100644 test/custom-build/debug_settings.xml create mode 100644 test/custom-build/gcc.mak create mode 100644 test/custom-build/icc.mak create mode 100644 test/custom-build/sandbox.vcproj create mode 100644 test/custom-build/settings_fully-existent.info create mode 100644 test/custom-build/settings_non-existent.info create mode 100644 test/custom-build/settings_partially-existent.info create mode 100644 test/custom-build/test_example_custom_data_type.vcproj create mode 100644 test/custom-build/test_example_debug_settings.vcproj create mode 100644 test/custom-build/test_example_empty_ptree_trick.vcproj create mode 100644 test/custom-build/test_info_grammar_spirit.vcproj create mode 100644 test/custom-build/test_info_parser.vcproj create mode 100644 test/custom-build/test_ini_parser.vcproj create mode 100644 test/custom-build/test_json_parser.vcproj create mode 100644 test/custom-build/test_multi_module.vcproj create mode 100644 test/custom-build/test_property_tree.vcproj create mode 100644 test/custom-build/test_xml_parser.vcproj create mode 100644 test/custom-build/tests.sln create mode 100644 test/custom-build/vc.mak create mode 100644 test/sandbox.cpp create mode 100644 test/test_cmdline_parser.cpp create mode 100644 test/test_info_parser.cpp create mode 100644 test/test_ini_parser.cpp create mode 100644 test/test_json_parser.cpp create mode 100644 test/test_multi_module1.cpp create mode 100644 test/test_multi_module2.cpp create mode 100644 test/test_property_tree.cpp create mode 100644 test/test_property_tree.hpp create mode 100644 test/test_registry_parser.cpp create mode 100644 test/test_utils.hpp create mode 100644 test/test_xml_parser_common.hpp create mode 100644 test/test_xml_parser_pugxml.cpp create mode 100644 test/test_xml_parser_rapidxml.cpp create mode 100644 test/test_xml_parser_spirit.cpp create mode 100644 test/test_xml_parser_tinyxml.cpp create mode 100644 test/xml_parser_test_data.hpp diff --git a/examples/custom_data_type.cpp b/examples/custom_data_type.cpp new file mode 100644 index 0000000000..86097e9aa4 --- /dev/null +++ b/examples/custom_data_type.cpp @@ -0,0 +1,80 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +// This example shows what need to be done to customize data_type of ptree. +// +// It creates my_ptree type, which is a basic_ptree having boost::any as its data +// container (instead of std::string that standard ptree has). + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Custom translator that works with boost::any instead of std::string +struct my_translator +{ + + // Custom extractor - converts data from boost::any to T + template + bool get_value(const Ptree &pt, T &value) const + { + value = boost::any_cast(pt.data()); + return true; // Success + } + + // Custom inserter - converts data from T to boost::any + template + bool put_value(Ptree &pt, const T &value) const + { + pt.data() = value; + return true; + } + +}; + +int main() +{ + + using namespace boost::property_tree; + + // Property_tree with boost::any as data type + // Key comparison: std::less + // Key type: std::string + // Path type: path + // Data type: boost::any + // Translator type: my_translator + typedef basic_ptree, std::string, path, boost::any, my_translator> my_ptree; + my_ptree pt; + + // Put/get int value + pt.put("int value", 3); + int int_value = pt.get("int value"); + std::cout << "Int value: " << int_value << "\n"; + + // Put/get string value + pt.put("string value", "foo bar"); + std::string string_value = pt.get("string value"); + std::cout << "String value: " << string_value << "\n"; + + // Put/get list value + int list_data[] = { 1, 2, 3, 4, 5 }; + pt.put >("list value", std::list(list_data, list_data + sizeof(list_data) / sizeof(*list_data))); + std::list list_value = pt.get >("list value"); + std::cout << "List value: "; + for (std::list::iterator it = list_value.begin(); it != list_value.end(); ++it) + std::cout << *it << ' '; + std::cout << '\n'; +} diff --git a/examples/debug_settings.cpp b/examples/debug_settings.cpp new file mode 100644 index 0000000000..f7bcef74d8 --- /dev/null +++ b/examples/debug_settings.cpp @@ -0,0 +1,109 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#include +#include +//#include +#include +#include +#include +#include + +struct debug_settings +{ + std::string m_file; // log filename + int m_level; // debug level + std::set m_modules; // modules where logging is enabled + void load(const std::string &filename); + void save(const std::string &filename); +}; + +void debug_settings::load(const std::string &filename) +{ + + // Create empty property tree object + using boost::property_tree::ptree; + ptree pt; + + // Load XML file and put its contents in property tree. + // No namespace qualification is needed, because of Koenig + // lookup on the second argument. If reading fails, exception + // is thrown. + read_xml(filename, pt); + + // Get filename and store it in m_file variable. Note that + // we specify a path to the value using notation where keys + // are separated with dots (different separator may be used + // if keys themselves contain dots). If debug.filename key is + // not found, exception is thrown. + m_file = pt.get("debug.filename"); + + // Get debug level and store it in m_level variable. This is + // another version of get method: if debug.level key is not + // found, it will return default value (specified by second + // parameter) instead of throwing. Type of the value extracted + // is determined by type of second parameter, so we can simply + // write get(...) instead of get(...). + m_level = pt.get("debug.level", 0); + + // Iterate over debug.modules section and store all found + // modules in m_modules set. get_child() function returns a + // reference to child at specified path; if there is no such + // child, it throws. Property tree iterator can be used in + // the same way as standard container iterator. Category + // is bidirectional_iterator. + //BOOST_FOREACH(ptree::value_type &v, pt.get_child("debug.modules")) + // m_modules.insert(v.second.data()); + +} + +void debug_settings::save(const std::string &filename) +{ + + // Create empty property tree object + using boost::property_tree::ptree; + ptree pt; + + // Put log filename in property tree + pt.put("debug.filename", m_file); + + // Put debug level in property tree + pt.put("debug.level", m_level); + + // Iterate over modules in set and put them in property + // tree. Note that put function places new key at the + // end of list of keys. This is fine in most of the + // situations. If you want to place item at some other + // place (i.e. at front or somewhere in the middle), + // this can be achieved using combination of insert + // and put_value functions + //BOOST_FOREACH(const std::string &name, m_modules) + // pt.put("debug.modules.module", name, true); + + // Write property tree to XML file + write_xml(filename, pt); + +} + +int main() +{ + try + { + debug_settings ds; + ds.load("debug_settings.xml"); + ds.save("debug_settings_out.xml"); + std::cout << "Success\n"; + } + catch (std::exception &e) + { + std::cout << "Error: " << e.what() << "\n"; + } + return 0; +} diff --git a/examples/debug_settings.xml b/examples/debug_settings.xml new file mode 100644 index 0000000000..9b8524a4c2 --- /dev/null +++ b/examples/debug_settings.xml @@ -0,0 +1,10 @@ + + + debug.log + + Finance + Admin + HR + + 2 + diff --git a/examples/empty_ptree_trick.cpp b/examples/empty_ptree_trick.cpp new file mode 100644 index 0000000000..37285b24a2 --- /dev/null +++ b/examples/empty_ptree_trick.cpp @@ -0,0 +1,71 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include +#include + +using namespace boost::property_tree; + +// Process settings using empty ptree trick. Note that it is considerably simpler +// than version which does not use the "trick" +void process_settings(const std::string &filename) +{ + ptree pt; + read_info(filename, pt); + const ptree &settings = pt.get_child("settings", empty_ptree()); + std::cout << "\n Processing " << filename << std::endl; + std::cout << " Setting 1 is " << settings.get("setting1", 0) << std::endl; + std::cout << " Setting 2 is " << settings.get("setting2", 0.0) << std::endl; + std::cout << " Setting 3 is " << settings.get("setting3", "default") << std::endl; +} + +// Process settings not using empty ptree trick. This one must duplicate much of the code. +void process_settings_without_trick(const std::string &filename) +{ + ptree pt; + read_info(filename, pt); + if (boost::optional settings = pt.get_child_optional("settings")) + { + std::cout << "\n Processing " << filename << std::endl; + std::cout << " Setting 1 is " << settings.get().get("setting1", 0) << std::endl; + std::cout << " Setting 2 is " << settings.get().get("setting2", 0.0) << std::endl; + std::cout << " Setting 3 is " << settings.get().get("setting3", "default") << std::endl; + } + else + { + std::cout << "\n Processing " << filename << std::endl; + std::cout << " Setting 1 is " << 0 << std::endl; + std::cout << " Setting 2 is " << 0.0 << std::endl; + std::cout << " Setting 3 is " << "default" << std::endl; + } +} + +int main() +{ + try + { + std::cout << "Processing settings with empty-ptree-trick:\n"; + process_settings("settings_fully-existent.info"); + process_settings("settings_partially-existent.info"); + process_settings("settings_non-existent.info"); + std::cout << "\nProcessing settings without empty-ptree-trick:\n"; + process_settings_without_trick("settings_fully-existent.info"); + process_settings_without_trick("settings_partially-existent.info"); + process_settings_without_trick("settings_non-existent.info"); + } + catch (std::exception &e) + { + std::cout << "Error: " << e.what() << "\n"; + } + return 0; +} diff --git a/examples/info_grammar_spirit.cpp b/examples/info_grammar_spirit.cpp new file mode 100644 index 0000000000..07025341b6 --- /dev/null +++ b/examples/info_grammar_spirit.cpp @@ -0,0 +1,152 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +/* This is grammar of INFO file format written in form of boost::spirit rules. + For simplicity, it does not parse #include directive. Note that INFO parser + included in property_tree library does not use Spirit. +*/ + +//#define BOOST_SPIRIT_DEBUG // uncomment to enable debug output +#include + +struct info_grammar: public boost::spirit::grammar +{ + + template + struct definition + { + + boost::spirit::rule::type> chr, qchr, escape_seq; + boost::spirit::rule string, qstring, cstring, key, value, entry, info; + + definition(const info_grammar &self) + { + + using namespace boost::spirit; + + escape_seq = chset_p("0abfnrtv\"\'\\"); + chr = (anychar_p - space_p - '\\' - '{' - '}' - '#' - '"') | ('\\' >> escape_seq); + qchr = (anychar_p - '"' - '\n' - '\\') | ('\\' >> escape_seq); + string = lexeme_d[+chr]; + qstring = lexeme_d['"' >> *qchr >> '"']; + cstring = lexeme_d['"' >> *qchr >> '"' >> '\\']; + key = string | qstring; + value = string | qstring | (+cstring >> qstring) | eps_p; + entry = key >> value >> !('{' >> *entry >> '}'); + info = *entry >> end_p; + + // Debug nodes + BOOST_SPIRIT_DEBUG_NODE(escape_seq); + BOOST_SPIRIT_DEBUG_NODE(chr); + BOOST_SPIRIT_DEBUG_NODE(qchr); + BOOST_SPIRIT_DEBUG_NODE(string); + BOOST_SPIRIT_DEBUG_NODE(qstring); + BOOST_SPIRIT_DEBUG_NODE(key); + BOOST_SPIRIT_DEBUG_NODE(value); + BOOST_SPIRIT_DEBUG_NODE(entry); + BOOST_SPIRIT_DEBUG_NODE(info); + + } + + const boost::spirit::rule &start() const + { + return info; + } + + }; +}; + +void info_parse(const char *s) +{ + + using namespace boost::spirit; + + // Parse and display result + info_grammar g; + parse_info pi = parse(s, g, space_p | comment_p(";")); + std::cout << "Parse result: " << (pi.hit ? "Success" : "Failure") << "\n"; + +} + +int main() +{ + + // Sample data 1 + const char *data1 = + "\n" + "key1 data1\n" + "{\n" + "\tkey data\n" + "}\n" + "key2 \"data2 \" {\n" + "\tkey data\n" + "}\n" + "key3 \"data\"\n" + "\t \"3\" {\n" + "\tkey data\n" + "}\n" + "\n" + "\"key4\" data4\n" + "{\n" + "\tkey data\n" + "}\n" + "\"key.5\" \"data.5\" { \n" + "\tkey data \n" + "}\n" + "\"key6\" \"data\"\n" + "\t \"6\" {\n" + "\tkey data\n" + "}\n" + " \n" + "key1 data1\n" + "{\n" + "\tkey data\n" + "}\n" + "key2 \"data2 \" {\n" + "\tkey data\n" + "}\n" + "key3 \"data\"\n" + "\t \"3\" {\n" + "\tkey data\n" + "}\n" + "\n" + "\"key4\" data4\n" + "{\n" + "\tkey data\n" + "}\n" + "\"key.5\" \"data.5\" {\n" + "\tkey data\n" + "}\n" + "\"key6\" \"data\"\n" + "\t \"6\" {\n" + "\tkey data\n" + "}\n" + "\\\\key\\t7 data7\\n\\\"data7\\\"\n" + "{\n" + "\tkey data\n" + "}\n" + "\"\\\\key\\t8\" \"data8\\n\\\"data8\\\"\"\n" + "{\n" + "\tkey data\n" + "}\n" + "\n"; + + // Sample data 2 + const char *data2 = + "key1\n" + "key2\n" + "key3\n" + "key4\n"; + + // Parse sample data + info_parse(data1); + info_parse(data2); + +} diff --git a/examples/settings_fully-existent.info b/examples/settings_fully-existent.info new file mode 100644 index 0000000000..bec7a64b3c --- /dev/null +++ b/examples/settings_fully-existent.info @@ -0,0 +1,6 @@ +settings +{ + setting1 15 + setting2 9.876 + setting3 Alice in Wonderland +} diff --git a/examples/settings_non-existent.info b/examples/settings_non-existent.info new file mode 100644 index 0000000000..4f76b2a459 --- /dev/null +++ b/examples/settings_non-existent.info @@ -0,0 +1,6 @@ +;settings // non-existent +;{ +; setting1 15 +; setting2 9.876 +; setting3 Alice in Wonderland +;} diff --git a/examples/settings_partially-existent.info b/examples/settings_partially-existent.info new file mode 100644 index 0000000000..ed5e8c225d --- /dev/null +++ b/examples/settings_partially-existent.info @@ -0,0 +1,6 @@ +settings +{ + setting1 15 + ;setting2 9.876 // non-existent + ;setting3 Alice in Wonderland // non-existent +} diff --git a/examples/speed_test.cpp b/examples/speed_test.cpp new file mode 100644 index 0000000000..176b79e613 --- /dev/null +++ b/examples/speed_test.cpp @@ -0,0 +1,134 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#define _HAS_ITERATOR_DEBUGGING 0 + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace boost; +using namespace boost::property_tree; + +string dummy; +vector keys; +vector shuffled_keys; + +void prepare_keys(int size) +{ + // Prepare keys + keys.clear(); + for (int i = 0; i < size; ++i) + keys.push_back((format("%d") % i).str()); + shuffled_keys = keys; + srand(0); + random_shuffle(shuffled_keys.begin(), shuffled_keys.end()); +} + +void clock_push_back(int size) +{ + + prepare_keys(size); + int max_repeats = 1000000 / size; + shared_array pt_array(new ptree[max_repeats]); + + int n = 0; + clock_t t1 = clock(), t2; + do + { + if (n >= max_repeats) + break; + ptree &pt = pt_array[n]; + for (int i = 0; i < size; ++i) + pt.push_back(ptree::value_type(shuffled_keys[i], empty_ptree())); + t2 = clock(); + ++n; + } while (t2 - t1 < CLOCKS_PER_SEC); + + cout << " push_back (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n"; + +} + +void clock_find(int size) +{ + + prepare_keys(size); + + ptree pt; + for (int i = 0; i < size; ++i) + pt.push_back(ptree::value_type(keys[i], ptree("data"))); + + int n = 0; + clock_t t1 = clock(), t2; + do + { + for (int i = 0; i < size; ++i) + pt.find(shuffled_keys[i]); + t2 = clock(); + ++n; + } while (t2 - t1 < CLOCKS_PER_SEC); + + cout << " find (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n"; + +} + +void clock_erase(int size) +{ + + prepare_keys(size); + + int max_repeats = 100000 / size; + shared_array pt_array(new ptree[max_repeats]); + + ptree pt; + for (int n = 0; n < max_repeats; ++n) + for (int i = 0; i < size; ++i) + pt_array[n].push_back(ptree::value_type(keys[i], ptree("data"))); + + int n = 0; + clock_t t1 = clock(), t2; + do + { + if (n >= max_repeats) + break; + ptree &pt = pt_array[n]; + for (int i = 0; i < size; ++i) + pt.erase(shuffled_keys[i]); + t2 = clock(); + ++n; + } while (t2 - t1 < CLOCKS_PER_SEC); + + cout << " erase (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n"; + +} + +int main() +{ + + // push_back + clock_push_back(10); + clock_push_back(100); + clock_push_back(1000); + + // erase + clock_erase(10); + clock_erase(100); + clock_erase(1000); + + // find + clock_find(10); + clock_find(100); + clock_find(1000); + +} diff --git a/index.html b/index.html new file mode 100644 index 0000000000..7974904d47 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + +

+ Docs for Property Tree library not available yet.

+ + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000000..2db2829295 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,17 @@ +subproject libs/property_tree/test ; + +# bring in rules for testing +import testing ; + +# Make tests run by default. +DEPENDS all : property_tree ; + +{ + test-suite "property_tree" + : [ run test_property_tree.cpp ] + [ run test_info_parser.cpp ] + [ run test_json_parser.cpp ] + [ run test_ini_parser.cpp ] + [ run test_xml_parser_rapidxml.cpp ] + ; +} diff --git a/test/custom-build/Makefile b/test/custom-build/Makefile new file mode 100644 index 0000000000..e2dd24cff9 --- /dev/null +++ b/test/custom-build/Makefile @@ -0,0 +1,5 @@ +all: + +clean: + rm -f *_dbg.exe + rm -f *_rel.exe diff --git a/test/custom-build/Makefile-Common b/test/custom-build/Makefile-Common new file mode 100644 index 0000000000..fcf9f36d51 --- /dev/null +++ b/test/custom-build/Makefile-Common @@ -0,0 +1,80 @@ +CCINCLUDE=-I../../../../../boost -I../../../.. + +all: test + +-include Makefile + +test: build + ./ptree_dbg.exe + ./ptree_rel.exe + ./cmdline_dbg.exe + ./cmdline_rel.exe + ./ini_dbg.exe + ./ini_rel.exe + ./info_dbg.exe + ./info_rel.exe + ./json_dbg.exe + ./json_rel.exe + ./xml_dbg.exe + ./xml_rel.exe + ./multi_module_dbg.exe + ./multi_module_rel.exe + ./example_custom_data_type_dbg.exe + ./example_custom_data_type_rel.exe + ./example_debug_settings_dbg.exe + ./example_debug_settings_rel.exe + ./example_empty_ptree_trick_dbg.exe + ./example_empty_ptree_trick_rel.exe + ./example_info_grammar_spirit_dbg.exe + ./example_info_grammar_spirit_rel.exe + +build: debug release + +debug: ptree_dbg.exe cmdline_dbg.exe ini_dbg.exe info_dbg.exe json_dbg.exe xml_dbg.exe multi_module_dbg.exe example_custom_data_type_dbg.exe example_debug_settings_dbg.exe example_empty_ptree_trick_dbg.exe example_info_grammar_spirit_dbg.exe + +release: ptree_rel.exe cmdline_rel.exe ini_rel.exe info_rel.exe json_rel.exe xml_rel.exe multi_module_rel.exe example_custom_data_type_rel.exe example_debug_settings_rel.exe example_empty_ptree_trick_rel.exe example_info_grammar_spirit_rel.exe + +ptree_dbg.exe: ../test_property_tree.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +ptree_rel.exe: ../test_property_tree.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +cmdline_dbg.exe: ../test_cmdline_parser.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +cmdline_rel.exe: ../test_cmdline_parser.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +ini_dbg.exe: ../test_ini_parser.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +ini_rel.exe: ../test_ini_parser.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +info_dbg.exe: ../test_info_parser.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +info_rel.exe: ../test_info_parser.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +json_dbg.exe: ../test_json_parser.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +json_rel.exe: ../test_json_parser.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +xml_dbg.exe: ../test_xml_parser_spirit.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +xml_rel.exe: ../test_xml_parser_spirit.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +multi_module_dbg.exe: ../test_multi_module1.cpp ../test_multi_module2.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $? -o $@ $(EXTLIBS) +multi_module_rel.exe: ../test_multi_module1.cpp ../test_multi_module2.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $? -o $@ $(EXTLIBS) +example_custom_data_type_dbg.exe: ../../examples/custom_data_type.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +example_custom_data_type_rel.exe: ../../examples/custom_data_type.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +example_debug_settings_dbg.exe: ../../examples/debug_settings.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +example_debug_settings_rel.exe: ../../examples/debug_settings.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +example_empty_ptree_trick_dbg.exe: ../../examples/empty_ptree_trick.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +example_empty_ptree_trick_rel.exe: ../../examples/empty_ptree_trick.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +example_info_grammar_spirit_dbg.exe: ../../examples/info_grammar_spirit.cpp + $(CC) $(CFLAGSDBG) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) +example_info_grammar_spirit_rel.exe: ../../examples/info_grammar_spirit.cpp + $(CC) $(CFLAGSREL) $(CCINCLUDE) $(EXTINCLUDE) $< -o $@ $(EXTLIBS) diff --git a/test/custom-build/debug_settings.xml b/test/custom-build/debug_settings.xml new file mode 100644 index 0000000000..9b8524a4c2 --- /dev/null +++ b/test/custom-build/debug_settings.xml @@ -0,0 +1,10 @@ + + + debug.log + + Finance + Admin + HR + + 2 + diff --git a/test/custom-build/gcc.mak b/test/custom-build/gcc.mak new file mode 100644 index 0000000000..bc2660b05f --- /dev/null +++ b/test/custom-build/gcc.mak @@ -0,0 +1,6 @@ +CC=g++ +CFLAGSREL=-Wall -pedantic -ftemplate-depth-255 -O3 +CFLAGSDBG=-Wall -pedantic -ftemplate-depth-255 -O0 +INCLUDE=-I../../../../../boost -I../../../.. + +-include Makefile-Common diff --git a/test/custom-build/icc.mak b/test/custom-build/icc.mak new file mode 100644 index 0000000000..98d9d948b3 --- /dev/null +++ b/test/custom-build/icc.mak @@ -0,0 +1,6 @@ +CC=icc +CFLAGSREL=-O3 -static +CFLAGSDBG=-O0 -static +INCLUDE=-I../../../../../boost -I../../../.. + +-include Makefile-Common diff --git a/test/custom-build/sandbox.vcproj b/test/custom-build/sandbox.vcproj new file mode 100644 index 0000000000..b7bbd5c2a1 --- /dev/null +++ b/test/custom-build/sandbox.vcproj @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/settings_fully-existent.info b/test/custom-build/settings_fully-existent.info new file mode 100644 index 0000000000..bec7a64b3c --- /dev/null +++ b/test/custom-build/settings_fully-existent.info @@ -0,0 +1,6 @@ +settings +{ + setting1 15 + setting2 9.876 + setting3 Alice in Wonderland +} diff --git a/test/custom-build/settings_non-existent.info b/test/custom-build/settings_non-existent.info new file mode 100644 index 0000000000..4f76b2a459 --- /dev/null +++ b/test/custom-build/settings_non-existent.info @@ -0,0 +1,6 @@ +;settings // non-existent +;{ +; setting1 15 +; setting2 9.876 +; setting3 Alice in Wonderland +;} diff --git a/test/custom-build/settings_partially-existent.info b/test/custom-build/settings_partially-existent.info new file mode 100644 index 0000000000..ed5e8c225d --- /dev/null +++ b/test/custom-build/settings_partially-existent.info @@ -0,0 +1,6 @@ +settings +{ + setting1 15 + ;setting2 9.876 // non-existent + ;setting3 Alice in Wonderland // non-existent +} diff --git a/test/custom-build/test_example_custom_data_type.vcproj b/test/custom-build/test_example_custom_data_type.vcproj new file mode 100644 index 0000000000..e7f240ce2d --- /dev/null +++ b/test/custom-build/test_example_custom_data_type.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_example_debug_settings.vcproj b/test/custom-build/test_example_debug_settings.vcproj new file mode 100644 index 0000000000..b91c196257 --- /dev/null +++ b/test/custom-build/test_example_debug_settings.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_example_empty_ptree_trick.vcproj b/test/custom-build/test_example_empty_ptree_trick.vcproj new file mode 100644 index 0000000000..946c23ec22 --- /dev/null +++ b/test/custom-build/test_example_empty_ptree_trick.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_info_grammar_spirit.vcproj b/test/custom-build/test_info_grammar_spirit.vcproj new file mode 100644 index 0000000000..9f02d63bff --- /dev/null +++ b/test/custom-build/test_info_grammar_spirit.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_info_parser.vcproj b/test/custom-build/test_info_parser.vcproj new file mode 100644 index 0000000000..d490f80ed7 --- /dev/null +++ b/test/custom-build/test_info_parser.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_ini_parser.vcproj b/test/custom-build/test_ini_parser.vcproj new file mode 100644 index 0000000000..1129c52209 --- /dev/null +++ b/test/custom-build/test_ini_parser.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_json_parser.vcproj b/test/custom-build/test_json_parser.vcproj new file mode 100644 index 0000000000..6930190acd --- /dev/null +++ b/test/custom-build/test_json_parser.vcproj @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_multi_module.vcproj b/test/custom-build/test_multi_module.vcproj new file mode 100644 index 0000000000..812bf501e9 --- /dev/null +++ b/test/custom-build/test_multi_module.vcproj @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_property_tree.vcproj b/test/custom-build/test_property_tree.vcproj new file mode 100644 index 0000000000..2ce8fd3cd4 --- /dev/null +++ b/test/custom-build/test_property_tree.vcproj @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/test_xml_parser.vcproj b/test/custom-build/test_xml_parser.vcproj new file mode 100644 index 0000000000..bf0e110f4a --- /dev/null +++ b/test/custom-build/test_xml_parser.vcproj @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/custom-build/tests.sln b/test/custom-build/tests.sln new file mode 100644 index 0000000000..6becf5bae6 --- /dev/null +++ b/test/custom-build/tests.sln @@ -0,0 +1,80 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_property_tree", "test_property_tree.vcproj", "{DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_ini_parser", "test_ini_parser.vcproj", "{20D5FE87-9284-4B1A-8505-7B913474C4AA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_info_parser", "test_info_parser.vcproj", "{03A81E3E-895A-4E1D-A42C-EB155A2868E1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_xml_parser", "test_xml_parser.vcproj", "{02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sandbox", "sandbox.vcproj", "{85FA9AEF-966B-4D93-9431-F507754B0431}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_json_parser", "test_json_parser.vcproj", "{CDDC4697-F51B-4B9A-A029-C2EB5271848F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_example_custom_data_type", "test_example_custom_data_type.vcproj", "{87516DC2-FDF4-4ECC-8713-D6D955100D86}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_example_debug_settings", "test_example_debug_settings.vcproj", "{16D41CBD-3C58-4631-B4D4-29A42E47D619}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_example_empty_ptree_trick", "test_example_empty_ptree_trick.vcproj", "{A242FE56-D039-4CEC-9FD3-AACABEA684C9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_info_grammar_spirit", "test_info_grammar_spirit.vcproj", "{305891FE-2572-4F6A-A52B-3A1964A3CA76}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_multi_module", "test_multi_module.vcproj", "{4B88BAC5-5CA8-403A-83E7-0F758405AB2D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}.Debug|Win32.ActiveCfg = Debug|Win32 + {DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}.Debug|Win32.Build.0 = Debug|Win32 + {DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}.Release|Win32.ActiveCfg = Release|Win32 + {DB0C18AA-BBA4-4DBF-A76E-92B642E45A74}.Release|Win32.Build.0 = Release|Win32 + {20D5FE87-9284-4B1A-8505-7B913474C4AA}.Debug|Win32.ActiveCfg = Debug|Win32 + {20D5FE87-9284-4B1A-8505-7B913474C4AA}.Debug|Win32.Build.0 = Debug|Win32 + {20D5FE87-9284-4B1A-8505-7B913474C4AA}.Release|Win32.ActiveCfg = Release|Win32 + {20D5FE87-9284-4B1A-8505-7B913474C4AA}.Release|Win32.Build.0 = Release|Win32 + {03A81E3E-895A-4E1D-A42C-EB155A2868E1}.Debug|Win32.ActiveCfg = Debug|Win32 + {03A81E3E-895A-4E1D-A42C-EB155A2868E1}.Debug|Win32.Build.0 = Debug|Win32 + {03A81E3E-895A-4E1D-A42C-EB155A2868E1}.Release|Win32.ActiveCfg = Release|Win32 + {03A81E3E-895A-4E1D-A42C-EB155A2868E1}.Release|Win32.Build.0 = Release|Win32 + {02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}.Debug|Win32.ActiveCfg = Debug|Win32 + {02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}.Debug|Win32.Build.0 = Debug|Win32 + {02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}.Release|Win32.ActiveCfg = Release|Win32 + {02D60AE7-3C50-45BB-AB12-ECCB22F1B9AF}.Release|Win32.Build.0 = Release|Win32 + {85FA9AEF-966B-4D93-9431-F507754B0431}.Debug|Win32.ActiveCfg = Debug|Win32 + {85FA9AEF-966B-4D93-9431-F507754B0431}.Debug|Win32.Build.0 = Debug|Win32 + {85FA9AEF-966B-4D93-9431-F507754B0431}.Release|Win32.ActiveCfg = Release|Win32 + {85FA9AEF-966B-4D93-9431-F507754B0431}.Release|Win32.Build.0 = Release|Win32 + {CDDC4697-F51B-4B9A-A029-C2EB5271848F}.Debug|Win32.ActiveCfg = Debug|Win32 + {CDDC4697-F51B-4B9A-A029-C2EB5271848F}.Debug|Win32.Build.0 = Debug|Win32 + {CDDC4697-F51B-4B9A-A029-C2EB5271848F}.Release|Win32.ActiveCfg = Release|Win32 + {CDDC4697-F51B-4B9A-A029-C2EB5271848F}.Release|Win32.Build.0 = Release|Win32 + {87516DC2-FDF4-4ECC-8713-D6D955100D86}.Debug|Win32.ActiveCfg = Debug|Win32 + {87516DC2-FDF4-4ECC-8713-D6D955100D86}.Debug|Win32.Build.0 = Debug|Win32 + {87516DC2-FDF4-4ECC-8713-D6D955100D86}.Release|Win32.ActiveCfg = Release|Win32 + {87516DC2-FDF4-4ECC-8713-D6D955100D86}.Release|Win32.Build.0 = Release|Win32 + {16D41CBD-3C58-4631-B4D4-29A42E47D619}.Debug|Win32.ActiveCfg = Debug|Win32 + {16D41CBD-3C58-4631-B4D4-29A42E47D619}.Debug|Win32.Build.0 = Debug|Win32 + {16D41CBD-3C58-4631-B4D4-29A42E47D619}.Release|Win32.ActiveCfg = Release|Win32 + {16D41CBD-3C58-4631-B4D4-29A42E47D619}.Release|Win32.Build.0 = Release|Win32 + {A242FE56-D039-4CEC-9FD3-AACABEA684C9}.Debug|Win32.ActiveCfg = Debug|Win32 + {A242FE56-D039-4CEC-9FD3-AACABEA684C9}.Debug|Win32.Build.0 = Debug|Win32 + {A242FE56-D039-4CEC-9FD3-AACABEA684C9}.Release|Win32.ActiveCfg = Release|Win32 + {A242FE56-D039-4CEC-9FD3-AACABEA684C9}.Release|Win32.Build.0 = Release|Win32 + {305891FE-2572-4F6A-A52B-3A1964A3CA76}.Debug|Win32.ActiveCfg = Debug|Win32 + {305891FE-2572-4F6A-A52B-3A1964A3CA76}.Debug|Win32.Build.0 = Debug|Win32 + {305891FE-2572-4F6A-A52B-3A1964A3CA76}.Release|Win32.ActiveCfg = Release|Win32 + {305891FE-2572-4F6A-A52B-3A1964A3CA76}.Release|Win32.Build.0 = Release|Win32 + {4B88BAC5-5CA8-403A-83E7-0F758405AB2D}.Debug|Win32.ActiveCfg = Debug|Win32 + {4B88BAC5-5CA8-403A-83E7-0F758405AB2D}.Debug|Win32.Build.0 = Debug|Win32 + {4B88BAC5-5CA8-403A-83E7-0F758405AB2D}.Release|Win32.ActiveCfg = Release|Win32 + {4B88BAC5-5CA8-403A-83E7-0F758405AB2D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/test/custom-build/vc.mak b/test/custom-build/vc.mak new file mode 100644 index 0000000000..2ff7349a96 --- /dev/null +++ b/test/custom-build/vc.mak @@ -0,0 +1,7 @@ +CC=cl +CFLAGSREL=-O2 -Ox -EHsc -DBOOST_DISABLE_WIN32 -nologo +CFLAGSDBG=-EHsc -DBOOST_DISABLE_WIN32 -nologo +EXTINCLUDE= +EXTLIBS= + +-include Makefile-Common diff --git a/test/sandbox.cpp b/test/sandbox.cpp new file mode 100644 index 0000000000..2c1c97e4ff --- /dev/null +++ b/test/sandbox.cpp @@ -0,0 +1,13 @@ +#define _CRT_SECURE_NO_DEPRECATE +//#define BOOST_PROPERTY_TREE_XML_PARSER_PUGXML +#include +#include +#include + +int main() +{ + using namespace boost::property_tree; + ptree pt; + read_xml("simple_all.xml", pt); + write_info(std::cout, pt); +} diff --git a/test/test_cmdline_parser.cpp b/test/test_cmdline_parser.cpp new file mode 100644 index 0000000000..03b5d46400 --- /dev/null +++ b/test/test_cmdline_parser.cpp @@ -0,0 +1,116 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#include "test_utils.hpp" +#include +#include +#include +#include + +namespace +{ + + // Test arguments + char *argv[] = + { + "c:\\program.exe", + "-Isrc/include1", + " file2.cc ", + "/L src/lib1", + "-Lsrc/lib2", + "/ooutput", + "file1.cc", + "-g", + "-", + "/", + " /Isrc/include2 ", + " file3.cc ", + "-I src/include3 " + }; + + // Test arguments count + const int argc = sizeof(argv) / sizeof(*argv); + +} + +template +void test_cmdline_parser() +{ + + using namespace boost::property_tree; + typedef typename Ptree::key_type::value_type Ch; + typedef std::basic_string Str; + + // Prepare arguments of proper char type + std::vector p; + std::vector strings; + strings.reserve(argc); + for (int i = 0; i < argc; ++i) + { + strings.push_back(detail::widen(argv[i])); + p.push_back(const_cast(strings.back().c_str())); + } + + Ptree pt1; + read_cmdline(argc, &p.front(), detail::widen("-/"), pt1); + + // Check indices + BOOST_CHECK(pt1.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib1")); + BOOST_CHECK(pt1.template get_optional(detail::widen("L.1")).get() == detail::widen("src/lib2")); + BOOST_CHECK(!pt1.template get_optional(detail::widen("L.2"))); + BOOST_CHECK(pt1.template get_optional(detail::widen(".0")).get() == detail::widen("c:\\program.exe")); + BOOST_CHECK(pt1.template get_optional(detail::widen(".1")).get() == detail::widen("file2.cc")); + BOOST_CHECK(pt1.template get_optional(detail::widen(".2")).get() == detail::widen("file1.cc")); + BOOST_CHECK(pt1.template get_optional(detail::widen(".3")).get() == detail::widen("file3.cc")); + BOOST_CHECK(!pt1.template get_optional(detail::widen(".4"))); + + // Check total sizes + //std::cerr << total_size(pt1) << " " << total_data_size(pt1) << " " << total_keys_size(pt1) << "\n"; + BOOST_CHECK(total_size(pt1) == 21); + BOOST_CHECK(total_data_size(pt1) == 130); + BOOST_CHECK(total_keys_size(pt1) == 19); + + Ptree pt2; + read_cmdline(argc, &p.front(), detail::widen("-"), pt2); + + // Check indices + BOOST_CHECK(pt2.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib2")); + BOOST_CHECK(!pt2.template get_optional(detail::widen("L.1"))); + + // Check total sizes + //std::cerr << total_size(pt2) << " " << total_data_size(pt2) << " " << total_keys_size(pt2) << "\n"; + BOOST_CHECK(total_size(pt2) == 19); + BOOST_CHECK(total_data_size(pt2) == 135); + BOOST_CHECK(total_keys_size(pt2) == 17); + + Ptree pt3; + read_cmdline(argc, &p.front(), detail::widen("/"), pt3); + + // Check indices + BOOST_CHECK(pt3.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib1")); + BOOST_CHECK(!pt3.template get_optional(detail::widen("L.1"))); + + // Check total sizes + //std::cerr << total_size(pt3) << " " << total_data_size(pt3) << " " << total_keys_size(pt3) << "\n"; + BOOST_CHECK(total_size(pt3) == 19); + BOOST_CHECK(total_data_size(pt3) == 149); + BOOST_CHECK(total_keys_size(pt3) == 17); + +} + +int test_main(int argc, char *argv[]) +{ + using namespace boost::property_tree; + test_cmdline_parser(); +#ifndef BOOST_NO_CWCHAR + test_cmdline_parser(); +#endif + return 0; +} diff --git a/test/test_info_parser.cpp b/test/test_info_parser.cpp new file mode 100644 index 0000000000..3c28a077c6 --- /dev/null +++ b/test/test_info_parser.cpp @@ -0,0 +1,249 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#include "test_utils.hpp" +#include + +/////////////////////////////////////////////////////////////////////////////// +// Test data + +const char *ok_data_1 = + ";Test file for info_parser\n" + "\n" + "key1 data1\n" + "{\n" + "\tkey data\n" + "}\n" + "#include \"testok1_inc.info\"\n" + "key2 \"data2 \" {\n" + "\tkey data\n" + "}\n" + "#\tinclude \"testok1_inc.info\"\n" + "key3 \"data\"\n" + "\t \"3\" {\n" + "\tkey data\n" + "}\n" + "\t#include \"testok1_inc.info\"\n" + "\n" + "\"key4\" data4\n" + "{\n" + "\tkey data\n" + "}\n" + "#include \"testok1_inc.info\"\n" + "\"key.5\" \"data.5\" { \n" + "\tkey data \n" + "}\n" + "#\tinclude \"testok1_inc.info\"\n" + "\"key6\" \"data\"\n" + "\t \"6\" {\n" + "\tkey data\n" + "}\n" + "\t#include \"testok1_inc.info\"\n" + " \n" + "key1 data1; comment\n" + "{; comment\n" + "\tkey data; comment\n" + "}; comment\n" + "#include \"testok1_inc.info\"\n" + "key2 \"data2 \" {; comment\n" + "\tkey data; comment\n" + "}; comment\n" + "#\tinclude \"testok1_inc.info\"\n" + "key3 \"data\"; comment\n" + "\t \"3\" {; comment\n" + "\tkey data; comment\n" + "}; comment\n" + "\t#include \"testok1_inc.info\"\n" + "\n" + "\"key4\" data4; comment\n" + "{; comment\n" + "\tkey data; comment\n" + "}; comment\n" + "#include \"testok1_inc.info\"\n" + "\"key.5\" \"data.5\" {; comment\n" + "\tkey data; comment\n" + "}; comment\n" + "#\tinclude \"testok1_inc.info\"\n" + "\"key6\" \"data\"; comment\n" + "\t \"6\" {; comment\n" + "\tkey data; comment\n" + "}; comment\n" + "\t#include \"testok1_inc.info\"\n" + "\\\\key\\t7 data7\\n\\\"data7\\\"\n" + "{\n" + "\tkey data\n" + "}\n" + "\"\\\\key\\t8\" \"data8\\n\\\"data8\\\"\"\n" + "{\n" + "\tkey data\n" + "}\n" + "\n"; + +const char *ok_data_1_inc = + ";Test file for info_parser\n" + "\n" + "inc_key inc_data ;;; comment\\"; + +const char *ok_data_2 = + ""; + +const char *ok_data_3 = + "key1 \"\"\n" + "key2 \"\"\n" + "key3 \"\"\n" + "key4 \"\"\n"; + +const char *ok_data_4 = + "key1 data key2 data"; + +const char *ok_data_5 = + "key { key \"\" key \"\" }\n"; + +const char *ok_data_6 = + "\"key with spaces\" \"data with spaces\"\n" + "\"key with spaces\" \"multiline data\"\\\n" + "\"cont\"\\\n" + "\"cont\""; + +const char *error_data_1 = + ";Test file for info_parser\n" + "#include \"bogus_file\"\n"; // Nonexistent include file + +const char *error_data_2 = + ";Test file for info_parser\n" + "key \"data with bad escape: \\q\"\n"; // Bad escape + +const char *error_data_3 = + ";Test file for info_parser\n" + "{\n"; // Opening brace without key + +const char *error_data_4 = + ";Test file for info_parser\n" + "}\n"; // Closing brace without opening brace + +const char *error_data_5 = + ";Test file for info_parser\n" + "key data\n" + "{\n" + ""; // No closing brace + +struct ReadFunc +{ + template + void operator()(const std::string &filename, Ptree &pt) const + { + boost::property_tree::read_info(filename, pt); + } +}; + +struct WriteFunc +{ + template + void operator()(const std::string &filename, const Ptree &pt) const + { + boost::property_tree::write_info(filename, pt); + } +}; + +template +void test_info_parser() +{ + + using namespace boost::property_tree; + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_1, ok_data_1_inc, + "testok1.info", "testok1_inc.info", "testok1out.info", 45, 240, 192 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_2, NULL, + "testok2.info", NULL, "testok2out.info", 1, 0, 0 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_3, NULL, + "testok3.info", NULL, "testok3out.info", 5, 0, 16 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_4, NULL, + "testok4.info", NULL, "testok4out.info", 3, 8, 8 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_5, NULL, + "testok5.info", NULL, "testok5out.info", 4, 0, 9 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_6, NULL, + "testok6.info", NULL, "testok6out.info", 3, 38, 30 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_1, NULL, + "testerr1.info", NULL, "testerr1out.info", 2 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_2, NULL, + "testerr2.info", NULL, "testerr2out.info", 2 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_3, NULL, + "testerr3.info", NULL, "testerr3out.info", 2 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_4, NULL, + "testerr4.info", NULL, "testerr4out.info", 2 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_5, NULL, + "testerr5.info", NULL, "testerr5out.info", 4 + ); + + // Test read with default ptree + { + Ptree pt, default_pt; + pt.put_value(1); + default_pt.put_value(2); + BOOST_CHECK(pt != default_pt); + read_info("nonexisting file.nonexisting file", pt, default_pt); + BOOST_CHECK(pt == default_pt); + } + +} + +int test_main(int argc, char *argv[]) +{ + using namespace boost::property_tree; + test_info_parser(); + test_info_parser(); +#ifndef BOOST_NO_CWCHAR + test_info_parser(); + test_info_parser(); +#endif + return 0; +} diff --git a/test/test_ini_parser.cpp b/test/test_ini_parser.cpp new file mode 100644 index 0000000000..36c5ba22f6 --- /dev/null +++ b/test/test_ini_parser.cpp @@ -0,0 +1,198 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#include "test_utils.hpp" +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// Test data + +// Correct data +const char *ok_data_1 = + "\n" + "; Comment\n" + "[Section1]\n" + "\t \t; Comment\n" + " Key1=Data1\n" + " \n" + " Key2 = Data2\n" + "Key 3 = Data 3 \n" + "Key4=Data4\n" + "[Section2] ;Comment\n" + "\t \t; Comment\n" + " \t [ Section 3 ];Comment \n"; + +// Correct data +const char *ok_data_2 = + "[Section1]\n" + "Key1=Data1"; // No eol + +// Correct data +const char *ok_data_3 = + ""; + +// Correct data +const char *ok_data_4 = + ";Comment"; + +// Erroneous data +const char *error_data_1 = + "[Section1]\n" + "Key1\n" // No equals sign + "Key2=Data2"; + +// Erroneous data +const char *error_data_2 = + "Key1=Data1\n" // No section + "Key2=Data2\n"; + +// Erroneous data +const char *error_data_3 = + "[Section1]\n" + "Key1=Data1\n" + "=Data2\n"; // No key + +struct ReadFunc +{ + template + void operator()(const std::string &filename, Ptree &pt) const + { + boost::property_tree::read_ini(filename, pt); + } +}; + +struct WriteFunc +{ + template + void operator()(const std::string &filename, const Ptree &pt) const + { + boost::property_tree::write_ini(filename, pt); + } +}; + +void test_erroneous_write(const boost::property_tree::ptree &pt) +{ + using namespace boost::property_tree; + std::stringstream stream; + try + { + write_ini(stream, pt); + BOOST_ERROR("No required exception thrown"); + } + catch (ini_parser_error &e) + { + (void)e; + } + catch (...) + { + BOOST_ERROR("Wrong exception type thrown"); + } +} + +template +void test_ini_parser() +{ + + using namespace boost::property_tree; + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_1, NULL, + "testok1.ini", NULL, "testok1out.ini", 8, 21, 42 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_2, NULL, + "testok2.ini", NULL, "testok2out.ini", 3, 5, 12 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_3, NULL, + "testok3.ini", NULL, "testok3out.ini", 1, 0, 0 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_4, NULL, + "testok4.ini", NULL, "testok4out.ini", 1, 0, 0 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_1, NULL, + "testerr1.ini", NULL, "testerr1out.ini", 2 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_2, NULL, + "testerr2.ini", NULL, "testerr2out.ini", 1 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_3, NULL, + "testerr3.ini", NULL, "testerr3out.ini", 3 + ); + +} + +int test_main(int argc, char *argv[]) +{ + + using namespace boost::property_tree; + + test_ini_parser(); + test_ini_parser(); +#ifndef BOOST_NO_CWCHAR + test_ini_parser(); + test_ini_parser(); +#endif + + /////////////////////////////////////////////////////////////////////////// + // Too rich property tree tests + + // Test too deep ptrees + { + ptree pt; + pt.put_child("section.key.bogus", empty_ptree()); + test_erroneous_write(pt); + } + + // Test data in sections + { + ptree pt; + pt.put("section", 1); + test_erroneous_write(pt); + } + + // Test duplicate sections + { + ptree pt; + pt.push_back(std::make_pair("section", ptree())); + pt.push_back(std::make_pair("section", ptree())); + test_erroneous_write(pt); + } + + // Test duplicate keys + { + ptree pt; + ptree &child = pt.put_child("section", empty_ptree()); + child.push_back(std::make_pair("key", ptree())); + child.push_back(std::make_pair("key", ptree())); + test_erroneous_write(pt); + } + + return 0; + +} diff --git a/test/test_json_parser.cpp b/test/test_json_parser.cpp new file mode 100644 index 0000000000..c41917d935 --- /dev/null +++ b/test/test_json_parser.cpp @@ -0,0 +1,384 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#include "test_utils.hpp" +#include + +/////////////////////////////////////////////////////////////////////////////// +// Test data + +const char *ok_data_1 = + "{}"; + +const char *ok_data_2 = + " \t {\n" + " \t \"name 0\" : \"value\", \t // comment \n" + " \t \"name 1\" : \"\", // comment \n" + " \t \"name 2\" : true, // comment \n" + " \t \"name 3\" : false, // comment \n" + " \t \"name 4\" : null, // comment \n" + " \t \"name 5\" : 0, // comment \n" + " \t \"name 6\" : -5, // comment \n" + " \t \"name 7\" : 1.1, // comment \n" + " \t \"name 8\" : -956.45e+4, // comment \n" + " \t \"name 8\" : 5956.45E-11, // comment \n" + " \t \"name 9\" : [1,2,3,4], // comment \n" + " \t \"name 10\" : {\"a\":\"b\"} // comment \n" + " \t } // comment \n"; + +const char *ok_data_3 = + "{\"a\":{\"b\":\"c\"}}"; + +const char *ok_data_4 = + "{\"a\":[{\"b\":\"c\"},{\"d\":\"e\"},1,2,3,4],\"f\":null}"; + +const char *ok_data_5 = + "{/* \n\n//{}//{}{\n{//\n}//{}{\n */}"; + +const char *ok_data_6 = + "{\"menu\": {\n" + " \"header\": \"SVG Viewer\",\n" + " \"items\": [\n" + " {\"id\": \"Open\"},\n" + " {\"id\": \"OpenNew\", \"label\": \"Open New\"},\n" + " null,\n" + " {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},\n" + " {\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},\n" + " {\"id\": \"OriginalView\", \"label\": \"Original View\"},\n" + " null,\n" + " {\"id\": \"Quality\"},\n" + " {\"id\": \"Pause\"},\n" + " {\"id\": \"Mute\"},\n" + " null,\n" + " {\"id\": \"Find\", \"label\": \"Find...\"},\n" + " {\"id\": \"FindAgain\", \"label\": \"Find Again\"},\n" + " {\"id\": \"Copy\"},\n" + " {\"id\": \"CopyAgain\", \"label\": \"Copy Again\"},\n" + " {\"id\": \"CopySVG\", \"label\": \"Copy SVG\"},\n" + " {\"id\": \"ViewSVG\", \"label\": \"View SVG\"},\n" + " {\"id\": \"ViewSource\", \"label\": \"View Source\"},\n" + " {\"id\": \"SaveAs\", \"label\": \"Save As\"},\n" + " null,\n" + " {\"id\": \"Help\"},\n" + " {\"id\": \"About\", \"label\": \"About Adobe CVG Viewer...\"}\n" + " ]\n" + "}}\n"; + +const char *ok_data_7 = + "{\"web-app\": {\n" + " \"servlet\": [ // Defines the CDSServlet\n" + " {\n" + " \"servlet-name\": \"cofaxCDS\",\n" + " \"servlet-class\": \"org.cofax.cds.CDSServlet\",\n" + " \"init-param\": {\n" + " \"configGlossary:installationAt\": \"Philadelphia, PA\",\n" + " \"configGlossary:adminEmail\": \"ksm@pobox.com\",\n" + " \"configGlossary:poweredBy\": \"Cofax\",\n" + " \"configGlossary:poweredByIcon\": \"/images/cofax.gif\",\n" + " \"configGlossary:staticPath\": \"/content/static\",\n" + " \"templateProcessorClass\": \"org.cofax.WysiwygTemplate\",\n" + " \"templateLoaderClass\": \"org.cofax.FilesTemplateLoader\",\n" + " \"templatePath\": \"templates\",\n" + " \"templateOverridePath\": \"\",\n" + " \"defaultListTemplate\": \"listTemplate.htm\",\n" + " \"defaultFileTemplate\": \"articleTemplate.htm\",\n" + " \"useJSP\": false,\n" + " \"jspListTemplate\": \"listTemplate.jsp\",\n" + " \"jspFileTemplate\": \"articleTemplate.jsp\",\n" + " \"cachePackageTagsTrack\": 200,\n" + " \"cachePackageTagsStore\": 200,\n" + " \"cachePackageTagsRefresh\": 60,\n" + " \"cacheTemplatesTrack\": 100,\n" + " \"cacheTemplatesStore\": 50,\n" + " \"cacheTemplatesRefresh\": 15,\n" + " \"cachePagesTrack\": 200,\n" + " \"cachePagesStore\": 100,\n" + " \"cachePagesRefresh\": 10,\n" + " \"cachePagesDirtyRead\": 10,\n" + " \"searchEngineListTemplate\": \"forSearchEnginesList.htm\",\n" + " \"searchEngineFileTemplate\": \"forSearchEngines.htm\",\n" + " \"searchEngineRobotsDb\": \"WEB-INF/robots.db\",\n" + " \"useDataStore\": true,\n" + " \"dataStoreClass\": \"org.cofax.SqlDataStore\",\n" + " \"redirectionClass\": \"org.cofax.SqlRedirection\",\n" + " \"dataStoreName\": \"cofax\",\n" + " \"dataStoreDriver\": \"com.microsoft.jdbc.sqlserver.SQLServerDriver\",\n" + " \"dataStoreUrl\": \"jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon\",\n" + " \"dataStoreUser\": \"sa\",\n" + " \"dataStorePassword\": \"dataStoreTestQuery\",\n" + " \"dataStoreTestQuery\": \"SET NOCOUNT ON;select test='test';\",\n" + " \"dataStoreLogFile\": \"/usr/local/tomcat/logs/datastore.log\",\n" + " \"dataStoreInitConns\": 10,\n" + " \"dataStoreMaxConns\": 100,\n" + " \"dataStoreConnUsageLimit\": 100,\n" + " \"dataStoreLogLevel\": \"debug\",\n" + " \"maxUrlLength\": 500}},\n" + " {\n" + " \"servlet-name\": \"cofaxEmail\",\n" + "\n \"servlet-class\": \"org.cofax.cds.EmailServlet\",\n" + " \"init-param\": {\n" + " \"mailHost\": \"mail1\",\n" + " \"mailHostOverride\": \"mail2\"}},\n" + " {\n" + " \"servlet-name\": \"cofaxAdmin\",\n" + " \"servlet-class\": \"org.cofax.cds.AdminServlet\"},\n" + " \n" + " {\n" + " \"servlet-name\": \"fileServlet\",\n" + " \"servlet-class\": \"org.cofax.cds.FileServlet\"},\n" + " {\n" + " \"servlet-name\": \"cofaxTools\",\n" + " \"servlet-class\": \"org.cofax.cms.CofaxToolsServlet\",\n" + " \"init-param\": {\n" + " \"templatePath\": \"toolstemplates/\",\n" + " \"log\": 1,\n" + " \"logLocation\": \"/usr/local/tomcat/logs/CofaxTools.log\",\n" + " \"logMaxSize\": \"\",\n" + " \"dataLog\": 1,\n" + " \"dataLogLocation\": \"/usr/local/tomcat/logs/dataLog.log\",\n" + " \"dataLogMaxSize\": \"\",\n" + " \"removePageCache\": \"/content/admin/remove?cache=pages&id=\",\n" + " \"removeTemplateCache\": \"/content/admin/remove?cache=templates&id=\",\n" + " \"fileTransferFolder\": \"/usr/local/tomcat/webapps/content/fileTransferFolder\",\n" + " \"lookInContext\": 1,\n" + " \"adminGroupID\": 4,\n" + " \"betaServer\": true}}],\n" + " \"servlet-mapping\": {\n" + " \"cofaxCDS\": \"/\",\n" + " \"cofaxEmail\": \"/cofaxutil/aemail/*\",\n" + " \"cofaxAdmin\": \"/admin/*\",\n" + " \"fileServlet\": \"/static/*\",\n" + " \"cofaxTools\": \"/tools/*\"},\n" + " \n" + " \"taglib\": {\n" + " \"taglib-uri\": \"cofax.tld\",\n" + " \"taglib-location\": \"/WEB-INF/tlds/cofax.tld\"}}}\n"; + +const char *ok_data_8 = + "{\"widget\": {\n" + " \"debug\": \"on\",\n" + " \"window\": {\n" + " \"title\": \"Sample Konfabulator Widget\", \"name\": \"main_window\", \"width\": 500, \"height\": 500\n" + " }, \"image\": { \n" + " \"src\": \"Images/Sun.png\",\n" + " \"name\": \"sun1\", \"hOffset\": 250, \"vOffset\": 250, \"alignment\": \"center\"\n" + " }, \"text\": {\n" + " \"data\": \"Click Here\",\n" + " \"size\": 36,\n" + " \"style\": \"bold\", \"name\": \"text1\", \"hOffset\": 250, \"vOffset\": 100, \"alignment\": \"center\",\n" + " \"onMouseUp\": \"sun1.opacity = (sun1.opacity / 100) * 90;\"\n" + " }\n" + "}} \n"; + +const char *ok_data_9 = + "{\"menu\": {\n" + " \"id\": \"file\",\n" + " \"value\": \"File:\",\n" + " \"popup\": {\n" + " \"menuitem\": [\n" + " {\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},\n" + " {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},\n" + "\n {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}\n" + " ]\n" + " }\n" + "}}\n"; + +const char *ok_data_10 = + "{\n" + " \"glossary\": {\n" + " \"title\": \"example glossary\",\n" + " \"GlossDiv\": {\n" + " \"title\": \"S\",\n" + " \"GlossList\": [{\n" + " \"ID\": \"SGML\",\n" + " \"SortAs\": \"SGML\",\n" + " \"GlossTerm\": \"Standard Generalized Markup Language\",\n" + " \"Acronym\": \"SGML\",\n" + " \"Abbrev\": \"ISO 8879:1986\",\n" + " \"GlossDef\": \n" + "\"A meta-markup language, used to create markup languages such as DocBook.\",\n" + " \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"]\n" + " }]\n" + " }\n" + " }\n" + "}\n"; + +const char *ok_data_11 = + "{\n" + " \"data\" : [\n" + " {\n" + " \"First Name\" : \"Bob\",\n" + " \"Last Name\" : \"Smith\",\n" + " \"Email\" : \"bsmith@someurl.com\",\n" + " \"Phone\" : \"(555) 555-1212\"\n" + " },\n" + " {\n" + " \"First Name\" : \"Jan\",\n" + " \"Last Name\" : \"Smith\",\n" + " \"Email\" : \"jsmith@someurl.com\",\n" + " \"Phone\" : \"(555) 555-3434\"\n" + " },\n" + " {\n" + " \"First Name\" : \"Sue\",\n" + " \"Last Name\" : \"Smith\",\n" + " \"Email\" : \"ssmith@someurl.com\",\n" + " \"Phone\" : \"(555) 555-5656\"\n" + " }\n" + " ]\n" + "}\n"; + +const char *ok_data_12 = + "{\" \\\" \\\\ \\0 \\b \\f \\n \\r \\t \" : \"multi\" \"-\" \"string\"}"; + +const char *error_data_1 = + ""; // No root object + +const char *error_data_2 = + "{\n\"a\":1\n"; // Unclosed object brace + +const char *error_data_3 = + "{\n\"a\":\n[1,2,3,4\n}"; // Unclosed array brace + +const char *error_data_4 = + "{\n\"a\"\n}"; // No object + +struct ReadFunc +{ + template + void operator()(const std::string &filename, Ptree &pt) const + { + boost::property_tree::read_json(filename, pt); + } +}; + +struct WriteFunc +{ + template + void operator()(const std::string &filename, const Ptree &pt) const + { + boost::property_tree::write_json(filename, pt); + } +}; + +template +void test_json_parser() +{ + + using namespace boost::property_tree; + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_1, NULL, + "testok1.json", NULL, "testok1out.json", 1, 0, 0 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_2, NULL, + "testok2.json", NULL, "testok2out.json", 18, 50, 74 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_3, NULL, + "testok3.json", NULL, "testok3out.json", 3, 1, 2 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_4, NULL, + "testok4.json", NULL, "testok4out.json", 11, 10, 4 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_5, NULL, + "testok5.json", NULL, "testok5out.json", 1, 0, 0 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_6, NULL, + "testok6.json", NULL, "testok6out.json", 56, 265, 111 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_7, NULL, + "testok7.json", NULL, "testok7out.json", 87, 1046, 1216 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_8, NULL, + "testok8.json", NULL, "testok8out.json", 23, 149, 125 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_9, NULL, + "testok9.json", NULL, "testok9out.json", 15, 54, 60 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_10, NULL, + "testok10.json", NULL, "testok10out.json", 17, 162, 85 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_11, NULL, + "testok11.json", NULL, "testok11out.json", 17, 120, 91 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_12, NULL, + "testok12.json", NULL, "testok12out.json", 2, 12, 19 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_1, NULL, + "testerr1.json", NULL, "testerr1out.json", 1 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_2, NULL, + "testerr2.json", NULL, "testerr2out.json", 3 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_3, NULL, + "testerr3.json", NULL, "testerr3out.json", 4 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_4, NULL, + "testerr4.json", NULL, "testerr4out.json", 3 + ); + +} + +int test_main(int argc, char *argv[]) +{ + using namespace boost::property_tree; + test_json_parser(); + test_json_parser(); +#ifndef BOOST_NO_CWCHAR + test_json_parser(); + test_json_parser(); +#endif + return 0; +} diff --git a/test/test_multi_module1.cpp b/test/test_multi_module1.cpp new file mode 100644 index 0000000000..3bb3bb4555 --- /dev/null +++ b/test/test_multi_module1.cpp @@ -0,0 +1,21 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +void f(); + +int main() +{ + f(); +} diff --git a/test/test_multi_module2.cpp b/test/test_multi_module2.cpp new file mode 100644 index 0000000000..6d35253f6c --- /dev/null +++ b/test/test_multi_module2.cpp @@ -0,0 +1,18 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +void f() +{ +} diff --git a/test/test_property_tree.cpp b/test/test_property_tree.cpp new file mode 100644 index 0000000000..a4c3176338 --- /dev/null +++ b/test/test_property_tree.cpp @@ -0,0 +1,263 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- +#include "test_utils.hpp" +#include +#include +#include + +// If using VC, disable some warnings that trip in boost::serialization bowels +#ifdef BOOST_MSVC + #pragma warning(disable:4267) // Narrowing conversion + #pragma warning(disable:4996) // Deprecated functions +#endif + +#include +#include +#include +#include +#include +#include +#include + +// Predicate for sorting keys +template +struct SortPred +{ + bool operator()(const typename Ptree::value_type &v1, + const typename Ptree::value_type &v2) const + { + return v1.first < v2.first; + } +}; + +// Predicate for sorting keys in reverse +template +struct SortPredRev +{ + bool operator()(const typename Ptree::value_type &v1, + const typename Ptree::value_type &v2) const + { + return v1.first > v2.first; + } +}; + +// Custom translator that works with boost::any instead of std::string +struct MyTranslator +{ + + // Custom extractor - converts data from boost::any to T + template + bool get_value(const Ptree &pt, T &value) const + { + value = boost::any_cast(pt.data()); + return true; // Success + } + + // Custom inserter - converts data from T to boost::any + template + bool put_value(Ptree &pt, const T &value) const + { + pt.data() = value; + return true; + } + +}; + +// Include char tests, case sensitive +#define CHTYPE char +#define T(s) s +#define PTREE boost::property_tree::ptree +#define NOCASE 0 +#define WIDECHAR 0 +# include "test_property_tree.hpp" +#undef CHTYPE +#undef T +#undef PTREE +#undef NOCASE +#undef WIDECHAR + +// Include wchar_t tests, case sensitive +#ifndef BOOST_NO_CWCHAR +# define CHTYPE wchar_t +# define T(s) L ## s +# define PTREE boost::property_tree::wptree +# define NOCASE 0 +# define WIDECHAR 1 +# include "test_property_tree.hpp" +# undef CHTYPE +# undef T +# undef PTREE +# undef NOCASE +# undef WIDECHAR +#endif + +// Include char tests, case insensitive +#define CHTYPE char +#define T(s) s +#define PTREE boost::property_tree::iptree +#define NOCASE 1 +# define WIDECHAR 0 +# include "test_property_tree.hpp" +#undef CHTYPE +#undef T +#undef PTREE +#undef NOCASE +#undef WIDECHAR + +// Include wchar_t tests, case insensitive +#ifndef BOOST_NO_CWCHAR +# define CHTYPE wchar_t +# define T(s) L ## s +# define PTREE boost::property_tree::wiptree +# define NOCASE 1 +# define WIDECHAR 1 +# include "test_property_tree.hpp" +# undef CHTYPE +# undef T +# undef PTREE +# undef NOCASE +# undef WIDECHAR +#endif + +int test_main(int, char *[]) +{ + + using namespace boost::property_tree; + + // char tests, case sensitive + { + ptree *pt = 0; + test_debug(pt); + test_constructor_destructor_assignment(pt); + test_insertion(pt); + test_erasing(pt); + test_clear(pt); + test_pushpop(pt); + test_container_iteration(pt); + test_swap(pt); + test_sort_reverse(pt); + test_case(pt); + test_comparison(pt); + test_front_back(pt); + test_get_put(pt); + test_get_child_put_child(pt); + test_path_separator(pt); + test_path(pt); + test_precision(pt); + test_locale(pt); + test_custom_data_type(pt); + test_empty_size_max_size(pt); + test_ptree_bad_path(pt); + test_ptree_bad_data(pt); + test_serialization(pt); + test_bool(pt); + test_char(pt); + test_leaks(pt); // must be a final test + } + + // wchar_t tests, case sensitive +#ifndef BOOST_NO_CWCHAR + { + wptree *pt = 0; + test_debug(pt); + test_constructor_destructor_assignment(pt); + test_insertion(pt); + test_erasing(pt); + test_clear(pt); + test_pushpop(pt); + test_container_iteration(pt); + test_swap(pt); + test_sort_reverse(pt); + test_case(pt); + test_comparison(pt); + test_front_back(pt); + test_get_put(pt); + test_get_child_put_child(pt); + test_path_separator(pt); + test_path(pt); + test_precision(pt); + test_locale(pt); + test_custom_data_type(pt); + test_empty_size_max_size(pt); + test_ptree_bad_path(pt); + test_ptree_bad_data(pt); + test_serialization(pt); + test_bool(pt); + test_char(pt); + test_leaks(pt); // must be a final test + } +#endif + + // char tests, case insensitive + { + iptree *pt = 0; + test_debug(pt); + test_constructor_destructor_assignment(pt); + test_insertion(pt); + test_erasing(pt); + test_clear(pt); + test_pushpop(pt); + test_container_iteration(pt); + test_swap(pt); + test_sort_reverse(pt); + test_case(pt); + test_comparison(pt); + test_front_back(pt); + test_get_put(pt); + test_get_child_put_child(pt); + test_path_separator(pt); + test_path(pt); + test_precision(pt); + test_locale(pt); + test_custom_data_type(pt); + test_empty_size_max_size(pt); + test_ptree_bad_path(pt); + test_ptree_bad_data(pt); + test_serialization(pt); + test_bool(pt); + test_char(pt); + test_leaks(pt); // must be a final test + } + + // wchar_t tests, case insensitive +#ifndef BOOST_NO_CWCHAR + { + wiptree *pt = 0; + test_debug(pt); + test_constructor_destructor_assignment(pt); + test_insertion(pt); + test_erasing(pt); + test_clear(pt); + test_pushpop(pt); + test_container_iteration(pt); + test_swap(pt); + test_sort_reverse(pt); + test_case(pt); + test_comparison(pt); + test_front_back(pt); + test_get_put(pt); + test_get_child_put_child(pt); + test_path_separator(pt); + test_path(pt); + test_precision(pt); + test_locale(pt); + test_custom_data_type(pt); + test_empty_size_max_size(pt); + test_ptree_bad_path(pt); + test_ptree_bad_data(pt); + test_serialization(pt); + test_bool(pt); + test_char(pt); + test_leaks(pt); // must be a final test + } +#endif + + return 0; +} diff --git a/test/test_property_tree.hpp b/test/test_property_tree.hpp new file mode 100644 index 0000000000..0d53cca008 --- /dev/null +++ b/test/test_property_tree.hpp @@ -0,0 +1,1263 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +// Intentionally no include guards (to be included more than once) + +#if !defined(CHTYPE) || !defined(T) || !defined(PTREE) || !defined(NOCASE) || !defined(WIDECHAR) +# error No character type specified +#endif + +void test_debug(PTREE *) +{ + + // Check count + BOOST_CHECK(PTREE::debug_get_instances_count() == 0); + + { + + // Create ptrees + PTREE pt1, pt2; + BOOST_CHECK(PTREE::debug_get_instances_count() == 2); + + // Create PTREE + PTREE *pt3 = new PTREE; + BOOST_CHECK(PTREE::debug_get_instances_count() == 3); + + // Insert + pt1.push_back(std::make_pair(T("key"), *pt3)); + BOOST_CHECK(PTREE::debug_get_instances_count() == 4); + + // Insert + pt2.push_back(std::make_pair(T("key"), *pt3)); + BOOST_CHECK(PTREE::debug_get_instances_count() == 5); + + // Clear + pt1.clear(); + BOOST_CHECK(PTREE::debug_get_instances_count() == 4); + + // Clear + pt2.clear(); + BOOST_CHECK(PTREE::debug_get_instances_count() == 3); + + // Delete + delete pt3; + BOOST_CHECK(PTREE::debug_get_instances_count() == 2); + + } + + // Check count + BOOST_CHECK(PTREE::debug_get_instances_count() == 0); + +} + +void test_constructor_destructor_assignment(PTREE *) +{ + + { + + // Test constructor from string + PTREE pt1(T("data")); + BOOST_CHECK(pt1.data() == T("data")); + BOOST_CHECK(PTREE::debug_get_instances_count() == 1); + + // Do insertions + PTREE &tmp1 = pt1.put(T("key1"), T("data1")); + PTREE &tmp2 = pt1.put(T("key2"), T("data2")); + tmp1.put(T("key3"), T("data3")); + tmp2.put(T("key4"), T("data4")); + BOOST_CHECK(PTREE::debug_get_instances_count() == 5); + + // Make a copy using copy constructor + PTREE *pt2 = new PTREE(pt1); + BOOST_CHECK(*pt2 == pt1); + BOOST_CHECK(PTREE::debug_get_instances_count() == 10); + + // Make a copy using = operator + PTREE *pt3 = new PTREE; + *pt3 = *pt2; + BOOST_CHECK(*pt3 == *pt2); + BOOST_CHECK(PTREE::debug_get_instances_count() == 15); + + // Test self assignment + pt1 = pt1; + BOOST_CHECK(pt1 == *pt2); + BOOST_CHECK(pt1 == *pt3); + BOOST_CHECK(PTREE::debug_get_instances_count() == 15); + + // Destroy + delete pt2; + BOOST_CHECK(PTREE::debug_get_instances_count() == 10); + + // Destroy + delete pt3; + BOOST_CHECK(PTREE::debug_get_instances_count() == 5); + + } + + // Check count + BOOST_CHECK(PTREE::debug_get_instances_count() == 0); + +} + +void test_insertion(PTREE *) +{ + + // Do insertions + PTREE pt; + PTREE tmp1(T("data1")); + PTREE tmp2(T("data2")); + PTREE tmp3(T("data3")); + PTREE tmp4(T("data4")); + PTREE::iterator it1 = pt.insert(pt.end(), std::make_pair(T("key1"), tmp1)); + PTREE::iterator it2 = pt.insert(it1, std::make_pair(T("key2"), tmp2)); + PTREE::iterator it3 = it1->second.push_back(std::make_pair(T("key3"), tmp3)); + PTREE::iterator it4 = it1->second.push_front(std::make_pair(T("key4"), tmp4)); + it2->second.insert(it2->second.end(), it1->second.begin(), it1->second.end()); + + // Check instance count + BOOST_CHECK(PTREE::debug_get_instances_count() == 11); + + // Check contents + BOOST_CHECK(pt.get(T("key1"), T("")) == T("data1")); + BOOST_CHECK(pt.get(T("key2"), T("")) == T("data2")); + BOOST_CHECK(pt.get(T("key1.key3"), T("")) == T("data3")); + BOOST_CHECK(pt.get(T("key1.key4"), T("")) == T("data4")); + BOOST_CHECK(pt.get(T("key2.key3"), T("")) == T("data3")); + BOOST_CHECK(pt.get(T("key2.key4"), T("")) == T("data4")); + + // Check sequence + PTREE::iterator it = it2; + ++it; BOOST_CHECK(it == it1); + ++it; BOOST_CHECK(it == pt.end()); + it = it4; + ++it; BOOST_CHECK(it == it3); + ++it; BOOST_CHECK(it == it1->second.end()); + +} + +void test_erasing(PTREE *) +{ + + // Do insertions + PTREE pt; + PTREE tmp1(T("data1")); + PTREE tmp2(T("data2")); + PTREE tmp3(T("data3")); + PTREE tmp4(T("data4")); + PTREE::iterator it1 = pt.insert(pt.end(), std::make_pair(T("key1"), tmp1)); + PTREE::iterator it2 = pt.insert(it1, std::make_pair(T("key2"), tmp2)); + it1->second.push_back(std::make_pair(T("key"), tmp3)); + it1->second.push_front(std::make_pair(T("key"), tmp4)); + it2->second.insert(it2->second.end(), it1->second.begin(), it1->second.end()); + + // Check instance count + BOOST_CHECK(PTREE::debug_get_instances_count() == 11); + + // Test range erase + PTREE::iterator it = it1->second.erase(it1->second.begin(), it1->second.end()); + BOOST_CHECK(it == it1->second.end()); + BOOST_CHECK(PTREE::debug_get_instances_count() == 9); + + // Test single erase + PTREE::size_type n = pt.erase(T("key1")); + BOOST_CHECK(n == 1); + BOOST_CHECK(PTREE::debug_get_instances_count() == 8); + + // Test multiple erase + n = it2->second.erase(T("key")); + BOOST_CHECK(n == 2); + BOOST_CHECK(PTREE::debug_get_instances_count() == 6); + + // Test one more erase + n = pt.erase(T("key2")); + BOOST_CHECK(n == 1); + BOOST_CHECK(PTREE::debug_get_instances_count() == 5); + +} + +void test_clear(PTREE *) +{ + + // Do insertions + PTREE pt(T("data")); + pt.push_back(std::make_pair(T("key"), PTREE(T("data")))); + + // Check instance count + BOOST_CHECK(PTREE::debug_get_instances_count() == 2); + + // Test clear + pt.clear(); + BOOST_CHECK(pt.empty()); + BOOST_CHECK(pt.data().empty()); + BOOST_CHECK(PTREE::debug_get_instances_count() == 1); + +} + +void test_pushpop(PTREE *) +{ + + // Do insertions + PTREE pt; + PTREE tmp1(T("data1")); + PTREE tmp2(T("data2")); + PTREE tmp3(T("data3")); + PTREE tmp4(T("data4")); + pt.push_back(std::make_pair(T("key3"), tmp3)); + pt.push_front(std::make_pair(T("key2"), tmp2)); + pt.push_back(std::make_pair(T("key4"), tmp4)); + pt.push_front(std::make_pair(T("key1"), tmp1)); + + // Check instance count + BOOST_CHECK(PTREE::debug_get_instances_count() == 9); + + // Check sequence + PTREE::iterator it = pt.begin(); + BOOST_CHECK(it->first == T("key1")); ++it; + BOOST_CHECK(it->first == T("key2")); ++it; + BOOST_CHECK(it->first == T("key3")); ++it; + BOOST_CHECK(it->first == T("key4")); ++it; + BOOST_CHECK(it == pt.end()); + + // Test pops + pt.pop_back(); + BOOST_CHECK(PTREE::debug_get_instances_count() == 8); + BOOST_CHECK(pt.front().second.data() == T("data1")); + BOOST_CHECK(pt.back().second.data() == T("data3")); + pt.pop_front(); + BOOST_CHECK(PTREE::debug_get_instances_count() == 7); + BOOST_CHECK(pt.front().second.data() == T("data2")); + BOOST_CHECK(pt.back().second.data() == T("data3")); + pt.pop_back(); + BOOST_CHECK(PTREE::debug_get_instances_count() == 6); + BOOST_CHECK(pt.front().second.data() == T("data2")); + BOOST_CHECK(pt.back().second.data() == T("data2")); + pt.pop_front(); + BOOST_CHECK(PTREE::debug_get_instances_count() == 5); + BOOST_CHECK(pt.empty()); + +} + +void test_container_iteration(PTREE *) +{ + + // Do insertions + PTREE pt; + pt.put(T("key3"), T("")); + pt.put(T("key1"), T("")); + pt.put(T("key4"), T("")); + pt.put(T("key2"), T("")); + + // iterator + { + PTREE::iterator it = pt.begin(); + BOOST_CHECK(it->first == T("key3")); ++it; + BOOST_CHECK(it->first == T("key1")); ++it; + BOOST_CHECK(it->first == T("key4")); ++it; + BOOST_CHECK(it->first == T("key2")); ++it; + BOOST_CHECK(it == pt.end()); + } + + // const_iterator + { + PTREE::const_iterator it = pt.begin(); + BOOST_CHECK(it->first == T("key3")); ++it; + BOOST_CHECK(it->first == T("key1")); ++it; + BOOST_CHECK(it->first == T("key4")); ++it; + BOOST_CHECK(it->first == T("key2")); ++it; + BOOST_CHECK(it == pt.end()); + } + + // reverse_iterator + { + PTREE::reverse_iterator it = pt.rbegin(); + BOOST_CHECK(it->first == T("key2")); ++it; + BOOST_CHECK(it->first == T("key4")); ++it; + BOOST_CHECK(it->first == T("key1")); ++it; + BOOST_CHECK(it->first == T("key3")); ++it; + BOOST_CHECK(it == pt.rend()); + } + + // const_reverse_iterator + { + PTREE::const_reverse_iterator it = pt.rbegin(); + BOOST_CHECK(it->first == T("key2")); ++it; + BOOST_CHECK(it->first == T("key4")); ++it; + BOOST_CHECK(it->first == T("key1")); ++it; + BOOST_CHECK(it->first == T("key3")); ++it; + BOOST_CHECK(it == PTREE::const_reverse_iterator(pt.rend())); + } + +} + +void test_swap(PTREE *) +{ + + PTREE pt1, pt2; + + // Do insertions + pt1.put(T("key1"), T("")); + pt1.put(T("key2"), T("")); + pt1.put(T("key1.key3"), T("")); + pt1.put(T("key1.key4"), T("")); + + // Check counts + BOOST_CHECK(PTREE::debug_get_instances_count() == 6); + BOOST_CHECK(pt1.size() == 2); + BOOST_CHECK(pt1.get_child(T("key1")).size() == 2); + BOOST_CHECK(pt2.size() == 0); + + // Swap using member function + pt1.swap(pt2); + + // Check counts + BOOST_CHECK(PTREE::debug_get_instances_count() == 6); + BOOST_CHECK(pt2.size() == 2); + BOOST_CHECK(pt2.get_child(T("key1")).size() == 2); + BOOST_CHECK(pt1.size() == 0); + + // Swap using free function + swap(pt1, pt2); + + // Check counts + BOOST_CHECK(PTREE::debug_get_instances_count() == 6); + BOOST_CHECK(pt1.size() == 2); + BOOST_CHECK(pt1.get_child(T("key1")).size() == 2); + BOOST_CHECK(pt2.size() == 0); + + // Swap using std algorithm + std::swap(pt1, pt2); + + // Check counts + BOOST_CHECK(PTREE::debug_get_instances_count() == 6); + BOOST_CHECK(pt2.size() == 2); + BOOST_CHECK(pt2.get_child(T("key1")).size() == 2); + BOOST_CHECK(pt1.size() == 0); + +} + +void test_sort_reverse(PTREE *) +{ + + PTREE pt; + + // Do insertions + pt.put(T("key2"), T("data2")); + pt.put(T("key1"), T("data1")); + pt.put(T("key4"), T("data4")); + pt.put(T("key3"), T("data3")); + pt.put(T("key3.key1"), T("")); + pt.put(T("key4.key2"), T("")); + + // Reverse + pt.reverse(); + + // Check sequence + { + PTREE::iterator it = pt.begin(); + BOOST_CHECK(it->first == T("key3")); ++it; + BOOST_CHECK(it->first == T("key4")); ++it; + BOOST_CHECK(it->first == T("key1")); ++it; + BOOST_CHECK(it->first == T("key2")); ++it; + BOOST_CHECK(it == pt.end()); + } + // Check sequence using find to check if index is ok + { + PTREE::iterator it = pt.begin(); + BOOST_CHECK(it == pt.find(T("key3"))); ++it; + BOOST_CHECK(it == pt.find(T("key4"))); ++it; + BOOST_CHECK(it == pt.find(T("key1"))); ++it; + BOOST_CHECK(it == pt.find(T("key2"))); ++it; + BOOST_CHECK(it == pt.end()); + } + + // Sort + pt.sort(SortPred()); + + // Check sequence + { + PTREE::iterator it = pt.begin(); + BOOST_CHECK(it->first == T("key1")); ++it; + BOOST_CHECK(it->first == T("key2")); ++it; + BOOST_CHECK(it->first == T("key3")); ++it; + BOOST_CHECK(it->first == T("key4")); ++it; + BOOST_CHECK(it == pt.end()); + } + // Check sequence (using find to check if index is ok) + { + PTREE::iterator it = pt.begin(); + BOOST_CHECK(it == pt.find(T("key1"))); ++it; + BOOST_CHECK(it == pt.find(T("key2"))); ++it; + BOOST_CHECK(it == pt.find(T("key3"))); ++it; + BOOST_CHECK(it == pt.find(T("key4"))); ++it; + BOOST_CHECK(it == pt.end()); + } + + // Sort reverse + pt.sort(SortPredRev()); + + // Check sequence + { + PTREE::iterator it = pt.begin(); + BOOST_CHECK(it->first == T("key4")); ++it; + BOOST_CHECK(it->first == T("key3")); ++it; + BOOST_CHECK(it->first == T("key2")); ++it; + BOOST_CHECK(it->first == T("key1")); ++it; + BOOST_CHECK(it == pt.end()); + } + // Check sequence (using find to check if index is ok) + { + PTREE::iterator it = pt.begin(); + BOOST_CHECK(it == pt.find(T("key4"))); ++it; + BOOST_CHECK(it == pt.find(T("key3"))); ++it; + BOOST_CHECK(it == pt.find(T("key2"))); ++it; + BOOST_CHECK(it == pt.find(T("key1"))); ++it; + BOOST_CHECK(it == pt.end()); + } + +} + +void test_case(PTREE *) +{ + + // Do insertions + PTREE pt; + pt.put(T("key1"), T("data1")); + pt.put(T("KEY2"), T("data2")); + pt.put(T("kEy1.keY3"), T("data3")); + pt.put(T("KEY1.key4"), T("data4")); + + // Check findings depending on traits type +#if (NOCASE == 0) + BOOST_CHECK(PTREE::debug_get_instances_count() == 7); + BOOST_CHECK(pt.get(T("key1"), T("")) == T("data1")); + BOOST_CHECK(pt.get(T("key2"), T("")) == T("")); + BOOST_CHECK(pt.get(T("key1.key3"), T("")) == T("")); + BOOST_CHECK(pt.get(T("KEY1.key4"), T("")) == T("data4")); +#else + BOOST_CHECK(PTREE::debug_get_instances_count() == 5); + BOOST_CHECK(pt.get(T("key1"), T("1")) == pt.get(T("KEY1"), T("2"))); + BOOST_CHECK(pt.get(T("key2"), T("1")) == pt.get(T("KEY2"), T("2"))); + BOOST_CHECK(pt.get(T("key1.key3"), T("1")) == pt.get(T("KEY1.KEY3"), T("2"))); + BOOST_CHECK(pt.get(T("key1.key4"), T("1")) == pt.get(T("KEY1.KEY4"), T("2"))); +#endif + + // Do more insertions + pt.push_back(PTREE::value_type(T("key1"), PTREE())); + pt.push_back(PTREE::value_type(T("key1"), PTREE())); + + // Test counts +#if (NOCASE == 0) + BOOST_CHECK(pt.count(T("key1")) == 3); + BOOST_CHECK(pt.count(T("KEY1")) == 1); + BOOST_CHECK(pt.count(T("key2")) == 0); + BOOST_CHECK(pt.count(T("KEY2")) == 1); + BOOST_CHECK(pt.count(T("key3")) == 0); + BOOST_CHECK(pt.count(T("KEY3")) == 0); +#else + BOOST_CHECK(pt.count(T("key1")) == 3); + BOOST_CHECK(pt.count(T("KEY1")) == 3); + BOOST_CHECK(pt.count(T("key2")) == 1); + BOOST_CHECK(pt.count(T("KEY2")) == 1); + BOOST_CHECK(pt.count(T("key3")) == 0); + BOOST_CHECK(pt.count(T("KEY3")) == 0); +#endif + +} + +void test_comparison(PTREE *) +{ + + // Prepare original + PTREE pt_orig(T("data")); + pt_orig.put(T("key1"), T("data1")); + pt_orig.put(T("key1.key3"), T("data2")); + pt_orig.put(T("key1.key4"), T("data3")); + pt_orig.put(T("key2"), T("data4")); + + // Test originals + { + PTREE pt1(pt_orig); + PTREE pt2(pt_orig); + BOOST_CHECK(pt1 == pt2); + BOOST_CHECK(pt2 == pt1); + BOOST_CHECK(!(pt1 != pt2)); + BOOST_CHECK(!(pt2 != pt1)); + } + + // Test originals with modified case +#if (NOCASE != 0) + { + PTREE pt1(pt_orig); + PTREE pt2(pt_orig); + pt1.pop_back(); + pt1.put(T("KEY2"), T("data4")); + BOOST_CHECK(pt1 == pt2); + BOOST_CHECK(pt2 == pt1); + BOOST_CHECK(!(pt1 != pt2)); + BOOST_CHECK(!(pt2 != pt1)); + } +#endif + + // Test modified copies (both modified the same way) + { + PTREE pt1(pt_orig); + PTREE pt2(pt_orig); + pt1.put(T("key1.key5"), T(".")); + pt2.put(T("key1.key5"), T(".")); + BOOST_CHECK(pt1 == pt2); + BOOST_CHECK(pt2 == pt1); + BOOST_CHECK(!(pt1 != pt2)); + BOOST_CHECK(!(pt2 != pt1)); + } + + // Test modified copies (modified root data) + { + PTREE pt1(pt_orig); + PTREE pt2(pt_orig); + pt1.data() = T("a"); + pt2.data() = T("b"); + BOOST_CHECK(!(pt1 == pt2)); + BOOST_CHECK(!(pt2 == pt1)); + BOOST_CHECK(pt1 != pt2); + BOOST_CHECK(pt2 != pt1); + } + + // Test modified copies (added subkeys with different data) + { + PTREE pt1(pt_orig); + PTREE pt2(pt_orig); + pt1.put(T("key1.key5"), T("a")); + pt2.put(T("key1.key5"), T("b")); + BOOST_CHECK(!(pt1 == pt2)); + BOOST_CHECK(!(pt2 == pt1)); + BOOST_CHECK(pt1 != pt2); + BOOST_CHECK(pt2 != pt1); + } + + // Test modified copies (added subkeys with different keys) + { + PTREE pt1(pt_orig); + PTREE pt2(pt_orig); + pt1.put(T("key1.key5"), T("")); + pt2.put(T("key1.key6"), T("")); + BOOST_CHECK(!(pt1 == pt2)); + BOOST_CHECK(!(pt2 == pt1)); + BOOST_CHECK(pt1 != pt2); + BOOST_CHECK(pt2 != pt1); + } + + // Test modified copies (added subkey to only one copy) + { + PTREE pt1(pt_orig); + PTREE pt2(pt_orig); + pt1.put(T("key1.key5"), T("")); + BOOST_CHECK(!(pt1 == pt2)); + BOOST_CHECK(!(pt2 == pt1)); + BOOST_CHECK(pt1 != pt2); + BOOST_CHECK(pt2 != pt1); + } + +} + +void test_front_back(PTREE *) +{ + + // Do insertions + PTREE pt; + pt.put(T("key1"), T("")); + pt.put(T("key2"), T("")); + + // Check front and back + BOOST_CHECK(pt.front().first == T("key1")); + BOOST_CHECK(pt.back().first == T("key2")); + +} + +void test_get_put(PTREE *) +{ + + typedef std::basic_string str_t; + + // Temporary storage + str_t tmp_string; + boost::optional opt_int; + boost::optional opt_long; + boost::optional opt_double; + boost::optional opt_float; + boost::optional opt_string; + boost::optional opt_char; + boost::optional opt_bool; + + // Do insertions via put + PTREE pt; + PTREE &pt1 = pt.put(T("k1"), 1); // put as int + PTREE &pt2 = pt.put(T("k2.k"), 2.5); // put as double + PTREE &pt3 = pt.put(T("k3.k.k"), T("ala ma kota")); // put as string + PTREE &pt4 = pt.put(T("k4.k.k.k"), CHTYPE('c')); // put as character + PTREE &pt5 = pt.put(T("k5.k.k.k.f"), false); // put as bool + PTREE &pt6 = pt.put(T("k5.k.k.k.t"), true); // put as bool + + // Check instances count + BOOST_CHECK(PTREE::debug_get_instances_count() == 17); + + // Check if const char * version returns std::string + BOOST_CHECK(typeid(pt.get_value(T(""))) == typeid(str_t)); + + // Do extractions via get (throwing version) + BOOST_CHECK(pt.get(T("k1")) == 1); // get as int + BOOST_CHECK(pt.get(T("k1")) == 1); // get as long + BOOST_CHECK(pt.get(T("k2.k")) == 2.5); // get as double + BOOST_CHECK(pt.get(T("k2.k")) == 2.5f); // get as float + BOOST_CHECK(pt.get(T("k3.k.k")) == str_t(T("ala ma kota"))); // get as string + BOOST_CHECK(pt.get(T("k4.k.k.k")) == CHTYPE('c')); // get as char + BOOST_CHECK(pt.get(T("k5.k.k.k.f")) == false); // get as bool + BOOST_CHECK(pt.get(T("k5.k.k.k.t")) == true); // get as bool + + // Do extractions via get (default value version) + BOOST_CHECK(pt.get(T("k1"), 0) == 1); // get as int + BOOST_CHECK(pt.get(T("k1"), 0L) == 1); // get as long + BOOST_CHECK(pt.get(T("k2.k"), 0.0) == 2.5); // get as double + BOOST_CHECK(pt.get(T("k2.k"), 0.0f) == 2.5f); // get as float + BOOST_CHECK(pt.get(T("k3.k.k"), str_t()) == str_t(T("ala ma kota"))); // get as string + BOOST_CHECK(pt.get(T("k3.k.k"), T("")) == T("ala ma kota")); // get as const char * + BOOST_CHECK(pt.get(T("k4.k.k.k"), CHTYPE('\0')) == CHTYPE('c')); // get as char + BOOST_CHECK(pt.get(T("k5.k.k.k.f"), true) == false); // get as bool + BOOST_CHECK(pt.get(T("k5.k.k.k.t"), false) == true); // get as bool + + // Do extractions via get (optional version) + opt_int = pt.get_optional(T("k1")); // get as int + BOOST_CHECK(opt_int && *opt_int == 1); + opt_long = pt.get_optional(T("k1")); // get as long + BOOST_CHECK(opt_long && *opt_long == 1); + opt_double = pt.get_optional(T("k2.k")); // get as double + BOOST_CHECK(opt_double && *opt_double == 2.5); + opt_float = pt.get_optional(T("k2.k")); // get as float + BOOST_CHECK(opt_float && *opt_float == 2.5f); + opt_string = pt.get_optional(T("k3.k.k")); // get as string + BOOST_CHECK(opt_string && *opt_string == str_t(T("ala ma kota"))); + opt_char = pt.get_optional(T("k4.k.k.k")); // get as char + BOOST_CHECK(opt_char && *opt_char == CHTYPE('c')); + opt_bool = pt.get_optional(T("k5.k.k.k.f")); // get as bool + BOOST_CHECK(opt_bool && *opt_bool == false); + opt_bool = pt.get_optional(T("k5.k.k.k.t")); // get as bool + BOOST_CHECK(opt_bool && *opt_bool == true); + + // Do insertions via put_value + pt1.put_value(short(1)); // put as short + pt2.put_value(2.5f); // put as float + pt3.put_value(str_t(T("ala ma kota"))); // put as string + pt4.put_value(CHTYPE('c')); // put as character + pt5.put_value(false); // put as bool + pt6.put_value(true); // put as bool + + // Do extractions via get_value (throwing version) + BOOST_CHECK(pt1.get_value() == 1); // get as int + BOOST_CHECK(pt1.get_value() == 1); // get as long + BOOST_CHECK(pt2.get_value() == 2.5); // get as double + BOOST_CHECK(pt2.get_value() == 2.5f); // get as float + BOOST_CHECK(pt3.get_value() == str_t(T("ala ma kota"))); // get as string + BOOST_CHECK(pt4.get_value() == CHTYPE('c')); // get as char + BOOST_CHECK(pt5.get_value() == false); // get as bool + BOOST_CHECK(pt6.get_value() == true); // get as bool + + // Do extractions via get_value (default value version) + BOOST_CHECK(pt1.get_value(0) == 1); // get as int + BOOST_CHECK(pt1.get_value(0L) == 1); // get as long + BOOST_CHECK(pt2.get_value(0.0) == 2.5); // get as double + BOOST_CHECK(pt2.get_value(0.0f) == 2.5f); // get as float + BOOST_CHECK(pt3.get_value(str_t()) == str_t(T("ala ma kota"))); // get as string + BOOST_CHECK(pt3.get_value(T("")) == T("ala ma kota")); // get as const char * + BOOST_CHECK(pt4.get_value(CHTYPE('\0')) == CHTYPE('c')); // get as char + BOOST_CHECK(pt5.get_value(true) == false); // get as bool + BOOST_CHECK(pt6.get_value(false) == true); // get as bool + + // Do extractions via get_value (optional version) + opt_int = pt1.get_value_optional(); // get as int + BOOST_CHECK(opt_int && *opt_int == 1); + opt_long = pt1.get_value_optional(); // get as long + BOOST_CHECK(opt_long && *opt_long == 1); + opt_double = pt2.get_value_optional(); // get as double + BOOST_CHECK(opt_double && *opt_double == 2.5); + opt_float = pt2.get_value_optional(); // get as float + BOOST_CHECK(opt_float && *opt_float == 2.5f); + opt_string = pt3.get_value_optional(); // get as string + BOOST_CHECK(opt_string && *opt_string == str_t(T("ala ma kota"))); + opt_char = pt4.get_value_optional(); // get as char + BOOST_CHECK(opt_char && *opt_char == CHTYPE('c')); + opt_bool = pt5.get_value_optional(); // get as bool + BOOST_CHECK(opt_bool && *opt_bool == false); + opt_bool = pt6.get_value_optional(); // get as bool + BOOST_CHECK(opt_bool && *opt_bool == true); + + // Do incorrect extractions (throwing version) + try + { + pt.get(T("k2.k.bogus.path")); + BOOST_ERROR("No required exception thrown"); + } + catch (boost::property_tree::ptree_bad_path &) { } + catch (...) + { + BOOST_ERROR("Wrong exception type thrown"); + } + try + { + pt.get(T("k2.k")); + BOOST_ERROR("No required exception thrown"); + } + catch (boost::property_tree::ptree_bad_data &) { } + catch (...) + { + BOOST_ERROR("Wrong exception type thrown"); + } + + // Do incorrect extractions (default value version) + BOOST_CHECK(pt.get(T("k2.k"), -7) == -7); + BOOST_CHECK(pt.get(T("k3.k.k"), -7) == -7); + BOOST_CHECK(pt.get(T("k4.k.k.k"), -7) == -7); + + // Do incorrect extractions (optional version) + BOOST_CHECK(!pt.get_optional(T("k2.k"))); + BOOST_CHECK(!pt.get_optional(T("k3.k.k"))); + BOOST_CHECK(!pt.get_optional(T("k4.k.k.k"))); + + // Test multiple puts with the same key + { + PTREE pt; + pt.put(T("key"), 1); + BOOST_CHECK(pt.get(T("key")) == 1); + BOOST_CHECK(pt.size() == 1); + pt.put(T("key"), 2); + BOOST_CHECK(pt.get(T("key")) == 2); + BOOST_CHECK(pt.size() == 1); + pt.put(T("key.key.key"), 1); + PTREE &child = pt.get_child(T("key.key")); + BOOST_CHECK(pt.get(T("key.key.key")) == 1); + BOOST_CHECK(child.size() == 1); + BOOST_CHECK(child.count(T("key")) == 1); + pt.put(T("key.key.key"), 2); + BOOST_CHECK(pt.get(T("key.key.key")) == 2); + BOOST_CHECK(child.size() == 1); + BOOST_CHECK(child.count(T("key")) == 1); + } + + // Test multiple puts with the same key + { + PTREE pt; + pt.put(T("key"), 1); + BOOST_CHECK(pt.get(T("key")) == 1); + BOOST_CHECK(pt.size() == 1); + pt.put(T("key"), 2); + BOOST_CHECK(pt.get(T("key")) == 2); + BOOST_CHECK(pt.size() == 1); + pt.put(T("key.key.key"), 1); + PTREE &child = pt.get_child(T("key.key")); + BOOST_CHECK(child.size() == 1); + BOOST_CHECK(child.count(T("key")) == 1); + pt.put(T("key.key.key"), 2, true); + BOOST_CHECK(child.size() == 2); + BOOST_CHECK(child.count(T("key")) == 2); + } + + // Test that put does not destroy children + { + PTREE pt; + pt.put(T("key1"), 1); + pt.put(T("key1.key2"), 2); + BOOST_CHECK(pt.get(T("key1"), 0) == 1); + BOOST_CHECK(pt.get(T("key1.key2"), 0) == 2); + pt.put(T("key1"), 2); + BOOST_CHECK(pt.get(T("key1"), 0) == 2); + BOOST_CHECK(pt.get(T("key1.key2"), 0) == 2); + } + + // Test that get of single character that is whitespace works + { + PTREE pt; + pt.put_value(T(' ')); + CHTYPE ch = pt.get_value(); + BOOST_CHECK(ch == T(' ')); + } + + // Test that get of non-char value with trailing and leading whitespace works + { + PTREE pt; + pt.put_value(T(" \t\n99 \t\n")); + BOOST_CHECK(pt.get_value(0) == 99); + } + +} + +void test_get_child_put_child(PTREE *) +{ + + typedef std::basic_string str_t; + + PTREE pt(T("ala ma kota")); + + // Do insertions via put_child + PTREE pt1, pt2, pt3; + pt1.put_child(T("k1"), boost::property_tree::empty_ptree()); + pt1.put_child(T("k2.k"), boost::property_tree::empty_ptree()); + pt2.put_child(T("k1"), pt); + pt2.put_child(T("k2.k"), pt); + + // Const references to test const versions of methods + const PTREE &cpt1 = pt1, &cpt2 = pt2; + + // Do correct extractions via get_child (throwing version) + BOOST_CHECK(pt1.get_child(T("k1")).empty()); + BOOST_CHECK(pt1.get_child(T("k2.k")).empty()); + BOOST_CHECK(pt2.get_child(T("k1")) == pt); + BOOST_CHECK(pt2.get_child(T("k2.k")) == pt); + BOOST_CHECK(cpt1.get_child(T("k1")).empty()); + BOOST_CHECK(cpt1.get_child(T("k2.k")).empty()); + BOOST_CHECK(cpt2.get_child(T("k1")) == pt); + BOOST_CHECK(cpt2.get_child(T("k2.k")) == pt); + + // Do correct extractions via get_child (default value version) + BOOST_CHECK(&pt1.get_child(T("k1"), boost::property_tree::empty_ptree()) != &boost::property_tree::empty_ptree()); + BOOST_CHECK(&pt1.get_child(T("k2.k"), boost::property_tree::empty_ptree()) != &boost::property_tree::empty_ptree()); + BOOST_CHECK(pt2.get_child(T("k1"), boost::property_tree::empty_ptree()) == pt); + BOOST_CHECK(pt2.get_child(T("k2.k"), boost::property_tree::empty_ptree()) == pt); + BOOST_CHECK(&cpt1.get_child(T("k1"), boost::property_tree::empty_ptree()) != &boost::property_tree::empty_ptree()); + BOOST_CHECK(&cpt1.get_child(T("k2.k"), boost::property_tree::empty_ptree()) != &boost::property_tree::empty_ptree()); + BOOST_CHECK(cpt2.get_child(T("k1"), boost::property_tree::empty_ptree()) == pt); + BOOST_CHECK(cpt2.get_child(T("k2.k"), boost::property_tree::empty_ptree()) == pt); + + // Do correct extractions via get_child (optional version) + boost::optional opt; + boost::optional copt; + opt = pt1.get_child_optional(T("k1")); + BOOST_CHECK(opt); + opt = pt1.get_child_optional(T("k2.k")); + BOOST_CHECK(opt); + opt = pt2.get_child_optional(T("k1")); + BOOST_CHECK(opt && *opt == pt); + opt = pt2.get_child_optional(T("k2.k")); + BOOST_CHECK(opt && *opt == pt); + copt = cpt1.get_child_optional(T("k1")); + BOOST_CHECK(copt); + copt = cpt1.get_child_optional(T("k2.k")); + BOOST_CHECK(copt); + copt = cpt2.get_child_optional(T("k1")); + BOOST_CHECK(copt && *copt == pt); + copt = cpt2.get_child_optional(T("k2.k")); + BOOST_CHECK(copt && *copt == pt); + + // Do incorrect extractions via get_child (throwing version) + try + { + pt.get_child(T("k2.k.bogus.path")); + BOOST_ERROR("No required exception thrown"); + } + catch (boost::property_tree::ptree_bad_path &) { } + catch (...) + { + BOOST_ERROR("Wrong exception type thrown"); + } + + // Do incorrect extractions via get_child (default value version) + BOOST_CHECK(&pt.get_child(T("k2.k.bogus.path"), pt3) == &pt3); + + // Do incorrect extractions via get_child (optional version) + BOOST_CHECK(!pt.get_child_optional(T("k2.k.bogus.path"))); + + // Test multiple puts with the same key + { + PTREE pt, tmp1(T("data1")), tmp2(T("data2")); + pt.put_child(T("key"), tmp1); + BOOST_CHECK(pt.get_child(T("key")) == tmp1); + BOOST_CHECK(pt.size() == 1); + pt.put_child(T("key"), tmp2); + BOOST_CHECK(pt.get_child(T("key")) == tmp2); + BOOST_CHECK(pt.size() == 1); + pt.put_child(T("key.key.key"), tmp1); + PTREE &child = pt.get_child(T("key.key")); + BOOST_CHECK(child.size() == 1); + pt.put_child(T("key.key.key"), tmp2); + BOOST_CHECK(child.size() == 1); + } + + // Test multiple puts with the same key using do_not_replace + { + PTREE pt, tmp1(T("data1")), tmp2(T("data2")); + pt.put_child(T("key"), tmp1); + BOOST_CHECK(pt.size() == 1); + pt.put_child(T("key"), tmp2, true); + BOOST_CHECK(pt.size() == 2); + BOOST_CHECK(pt.count(T("key")) == 2); + pt.put_child(T("key.key.key"), tmp1); + PTREE &child = pt.get_child(T("key.key")); + BOOST_CHECK(child.size() == 1); + BOOST_CHECK(child.count(T("key")) == 1); + pt.put_child(T("key.key.key"), tmp2, true); + BOOST_CHECK(child.size() == 2); + BOOST_CHECK(child.count(T("key")) == 2); + } + +} + +void test_path_separator(PTREE *) +{ + + typedef PTREE::path_type path; + + // Check instances count + BOOST_CHECK(PTREE::debug_get_instances_count() == 0); + + // Do insertions + PTREE pt; + pt.put(T("key1"), T("1")); + pt.put(T("key2.key"), T("2")); + pt.put(T("key3.key.key"), T("3")); + pt.put(path(T("key4"), CHTYPE('/')), T("4")); + pt.put(path(T("key5/key"), CHTYPE('/')), T("5")); + pt.put(path(T("key6/key/key"), CHTYPE('/')), T("6")); + + // Check instances count + BOOST_CHECK(PTREE::debug_get_instances_count() == 13); + + // Do correct extractions + BOOST_CHECK(pt.get(T("key1"), 0) == 1); + BOOST_CHECK(pt.get(T("key2.key"), 0) == 2); + BOOST_CHECK(pt.get(T("key3.key.key"), 0) == 3); + BOOST_CHECK(pt.get(path(T("key4"), CHTYPE('/')), 0) == 4); + BOOST_CHECK(pt.get(path(T("key5/key"), CHTYPE('/')), 0) == 5); + BOOST_CHECK(pt.get(path(T("key6/key/key"), CHTYPE('/')), 0) == 6); + + // Do incorrect extractions + BOOST_CHECK(pt.get(T("key2/key"), 0) == 0); + BOOST_CHECK(pt.get(T("key3/key/key"), 0) == 0); + BOOST_CHECK(pt.get(path(T("key5.key"), CHTYPE('/')), 0) == 0); + BOOST_CHECK(pt.get(path(T("key6.key.key"), CHTYPE('/')), 0) == 0); + +} + +void test_path(PTREE *) +{ + + typedef PTREE::path_type path; + + // Insert + PTREE pt; + pt.put(T("key1.key2.key3"), 1); + + // Test operator /= + { + path p; + p /= T("key1"); p /= T("key2"); p /= T("key3"); + BOOST_CHECK(pt.get(p, 0) == 1); + } + + // Test operator /= + { + path p(T("key1")); + p /= T("key2.key3"); + BOOST_CHECK(pt.get(p, 0) == 1); + } + + // Test operator /= + { + path p; + path p1(T("key1.key2")); + path p2(T("key3")); + p /= p1; + p /= p2; + BOOST_CHECK(pt.get(p, 0) == 1); + } + + // Test operator / + { + path p = path(T("key1")) / T("key2.key3"); + BOOST_CHECK(pt.get(p, 0) == 1); + } + + // Test operator / + { + path p = T("key1.key2") / path(T("key3")); + BOOST_CHECK(pt.get(p, 0) == 1); + } + +} + +void test_precision(PTREE *) +{ + + typedef double real; + + // Quite precise PI value + real pi = real(3.1415926535897932384626433832795028841971); + + // Put and get + PTREE pt; + pt.put_value(pi); + real pi2 = pt.get_value(); + + // Test if precision is "good enough", i.e. if stream precision increase worked + using namespace std; + real error = abs(pi - pi2) * + pow(real(numeric_limits::radix), + real(numeric_limits::digits)); + BOOST_CHECK(error < 100); + +} + +void test_locale(PTREE *) +{ + + try + { + + // Write strings in english and french locales + PTREE pt; +#ifdef BOOST_WINDOWS + std::locale loc_english("english"); + std::locale loc_french("french"); +#else + std::locale loc_english("en_GB"); + std::locale loc_french("fr_FR"); +#endif + pt.put(T("english"), 1.234, false, loc_english); + pt.put(T("french"), 1.234, false, loc_french); + + // Test contents + BOOST_CHECK(pt.get(T("english")) == T("1.234")); + BOOST_CHECK(pt.get(T("french")) == T("1,234")); + + } + catch (boost::property_tree::ptree_error &) + { + throw; + } + catch (std::runtime_error &e) + { + std::cerr << "Required locale not supported by the platform. " + "Skipping locale tests (caught std::runtime_error with message " << + e.what() << ").\n"; + } + +} + +void test_custom_data_type(PTREE *) +{ + + typedef std::basic_string Str; + typedef PTREE::key_compare Comp; + typedef PTREE::path_type Path; + + // Property_tree with boost::any as data type + typedef boost::property_tree::basic_ptree my_ptree; + my_ptree pt; + + // Put/get int value + pt.put(T("int value"), 3); + int int_value = pt.get(T("int value")); + BOOST_CHECK(int_value == 3); + + // Put/get string value + pt.put >(T("string value"), T("foo bar")); + std::basic_string string_value = pt.get >(T("string value")); + BOOST_CHECK(string_value == T("foo bar")); + + // Put/get list value + int list_data[] = { 1, 2, 3, 4, 5 }; + pt.put >(T("list value"), std::list(list_data, list_data + sizeof(list_data) / sizeof(*list_data))); + std::list list_value = pt.get >(T("list value")); + BOOST_CHECK(list_value.size() == 5); + BOOST_CHECK(list_value.front() == 1); + BOOST_CHECK(list_value.back() == 5); + +} + +void test_empty_size_max_size(PTREE *) +{ + + PTREE pt; + BOOST_CHECK(pt.max_size()); + BOOST_CHECK(pt.empty()); + BOOST_CHECK(pt.size() == 0); + + pt.put(T("test1"), 1); + BOOST_CHECK(pt.max_size()); + BOOST_CHECK(!pt.empty()); + BOOST_CHECK(pt.size() == 1); + + pt.put(T("test2"), 2); + BOOST_CHECK(pt.max_size()); + BOOST_CHECK(!pt.empty()); + BOOST_CHECK(pt.size() == 2); + +} + +void test_ptree_bad_path(PTREE *) +{ + + PTREE pt; + + try + { + pt.get(T("non.existent.path")); + } + catch (boost::property_tree::ptree_bad_path &e) + { + PTREE::path_type path = e.path(); + std::string what = e.what(); + BOOST_CHECK(what.find("non.existent.path") != std::string::npos); + return; + } + + BOOST_ERROR("No required exception thrown"); + +} + +void test_ptree_bad_data(PTREE *) +{ + + PTREE pt; + pt.put_value("non convertible to int"); + + try + { + pt.get_value(); + } + catch (boost::property_tree::ptree_bad_data &e) + { + PTREE::data_type data = e.data(); + std::string what = e.what(); + BOOST_CHECK(what.find("non convertible to int") != std::string::npos); + return; + } + + BOOST_ERROR("No required exception thrown"); +} + +void test_serialization(PTREE *) +{ + + // Prepare test tree + PTREE pt; + pt.put_value(1); + pt.put(T("key1"), 3); + pt.put(T("key1.key11)"), 3.3); + pt.put(T("key1.key12"), T("foo")); + pt.put(T("key2"), true); + pt.put(T("key2.key21.key211.key2111.key21111"), T("super deep!")); + pt.put_child(T("empty"), boost::property_tree::empty_ptree()); + pt.put(T("loooooong"), PTREE::data_type(10000, CHTYPE('a'))); + + // Endforce const for input + const PTREE &pt1 = pt; + + // Test text archives + { + std::stringstream stream; + boost::archive::text_oarchive oa(stream); + oa & pt1; + boost::archive::text_iarchive ia(stream); + PTREE pt2; + ia & pt2; + BOOST_CHECK(pt1 == pt2); + } + + // Test binary archives + { + std::stringstream stream; + boost::archive::binary_oarchive oa(stream); + oa & pt1; + boost::archive::binary_iarchive ia(stream); + PTREE pt2; + ia & pt2; + BOOST_CHECK(pt1 == pt2); + } + + // Test XML archives + { + std::stringstream stream; + boost::archive::xml_oarchive oa(stream); + oa & boost::serialization::make_nvp("pt", pt1); + boost::archive::xml_iarchive ia(stream); + PTREE pt2; + ia & boost::serialization::make_nvp("pt", pt2); + BOOST_CHECK(pt1 == pt2); + } + +} + +void test_bool(PTREE *) +{ + + // Prepare test tree + PTREE pt; + pt.put(T("bool.false.1"), false); + pt.put(T("bool.false.2"), T("0")); + pt.put(T("bool.true.1"), true); + pt.put(T("bool.true.2"), 1); + pt.put(T("bool.invalid.1"), T("")); + pt.put(T("bool.invalid.2"), T("tt")); + pt.put(T("bool.invalid.3"), T("ff")); + pt.put(T("bool.invalid.4"), T("2")); + pt.put(T("bool.invalid.5"), T("-1")); + + // Test false + for (PTREE::iterator it = pt.get_child(T("bool.false")).begin(); it != pt.get_child(T("bool.false")).end(); ++it) + BOOST_CHECK(it->second.get_value() == false); + + // Test true + for (PTREE::iterator it = pt.get_child(T("bool.true")).begin(); it != pt.get_child(T("bool.true")).end(); ++it) + BOOST_CHECK(it->second.get_value() == true); + + // Test invalid + for (PTREE::iterator it = pt.get_child(T("bool.invalid")).begin(); it != pt.get_child(T("bool.invalid")).end(); ++it) + { + BOOST_CHECK(it->second.get_value(false) == false); + BOOST_CHECK(it->second.get_value(true) == true); + } + +} + +void test_char(PTREE *) +{ + + // Prepare test tree + PTREE pt; +#if WIDECHAR == 0 + pt.put(T("char"), char('A')); +#endif + pt.put(T("signed char"), static_cast('A')); + pt.put(T("unsigned char"), static_cast('A')); + pt.put(T("signed char min"), (std::numeric_limits::min)()); + pt.put(T("signed char max"), (std::numeric_limits::max)()); + pt.put(T("unsigned char min"), (std::numeric_limits::min)()); + pt.put(T("unsigned char max"), (std::numeric_limits::max)()); + + // Verify normal conversions +#if WIDECHAR == 0 + BOOST_CHECK(pt.get(T("char")) == 'A'); +#endif + BOOST_CHECK(pt.get(T("signed char")) == static_cast('A')); + BOOST_CHECK(pt.get(T("unsigned char")) == static_cast('A')); + + // Verify that numbers are saved for signed and unsigned char + BOOST_CHECK(pt.get(T("signed char")) == int('A')); + BOOST_CHECK(pt.get(T("unsigned char")) == int('A')); + + // Verify ranges + BOOST_CHECK(pt.get(T("signed char min")) == (std::numeric_limits::min)()); + BOOST_CHECK(pt.get(T("signed char max")) == (std::numeric_limits::max)()); + BOOST_CHECK(pt.get(T("unsigned char min")) == (std::numeric_limits::min)()); + BOOST_CHECK(pt.get(T("unsigned char max")) == (std::numeric_limits::max)()); + +} + +void test_leaks(PTREE *) +{ + BOOST_CHECK(PTREE::debug_get_instances_count() == 0); +} diff --git a/test/test_registry_parser.cpp b/test/test_registry_parser.cpp new file mode 100644 index 0000000000..2e7c348816 --- /dev/null +++ b/test/test_registry_parser.cpp @@ -0,0 +1,110 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#include "test_utils.hpp" + +// Only test registry parser if we have windows platform +#ifdef BOOST_WINDOWS + +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// Test data + +const char *data_1 = + "root\n" + "{\n" + " subkey1 \"default value 1\"\n" + " subkey2 \"default value 2\"\n" + " \\\\values\n" + " {\n" + " REG_NONE \"\"\n" + " REG_BINARY \"de ad be ef\"\n" + " REG_DWORD 1234567890\n" + " REG_QWORD 12345678901234567890\n" + " REG_SZ \"some text\"\n" + " REG_EXPAND_SZ \"some other text\"\n" + " }\n" + " \\\\types\n" + " {\n" + " REG_NONE 0\n" + " REG_BINARY 3\n" + " REG_DWORD 4\n" + " REG_QWORD 11\n" + " REG_SZ 1\n" + " REG_EXPAND_SZ 2\n" + " }\n" + "}\n"; + +template +void test_registry_parser() +{ + + using namespace boost::property_tree; + typedef typename Ptree::key_type::value_type Ch; + typedef std::basic_string Str; + + // Delete test registry key + RegDeleteKeyA(HKEY_CURRENT_USER, "boost ptree test"); + + // Get test ptree + Ptree pt; + std::basic_stringstream stream(detail::widen(data_1)); + read_info(stream, pt); + + try + { + + // Write to registry, read back and compare contents + Ptree pt2; + write_registry(HKEY_CURRENT_USER, detail::widen("boost ptree test"), pt); + read_registry(HKEY_CURRENT_USER, detail::widen("boost ptree test"), pt2); + BOOST_CHECK(pt == pt2); + + // Test binary translation + Str s = pt2.template get(detail::widen("root.\\values.REG_BINARY")); + std::vector bin = registry_parser::translate(REG_BINARY, s); + BOOST_REQUIRE(bin.size() == 4); + BOOST_CHECK(*reinterpret_cast(&bin.front()) == 0xEFBEADDE); + Str s2 = registry_parser::translate(REG_BINARY, bin); + BOOST_CHECK(s == s2); + + } + catch (std::exception &e) + { + BOOST_ERROR(e.what()); + } + + // Delete test registry key + RegDeleteKeyA(HKEY_CURRENT_USER, "boost ptree test"); + +} + +int test_main(int argc, char *argv[]) +{ + using namespace boost::property_tree; + test_registry_parser(); + //test_registry_parser(); +#ifndef BOOST_NO_CWCHAR + //test_registry_parser(); + //test_registry_parser(); +#endif + return 0; +} + +#else + +int test_main(int argc, char *argv[]) +{ + return 0; +} + +#endif diff --git a/test/test_utils.hpp b/test/test_utils.hpp new file mode 100644 index 0000000000..2db2267348 --- /dev/null +++ b/test/test_utils.hpp @@ -0,0 +1,227 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2005 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- +#ifndef BOOST_PROPERTY_TREE_TEST_UTILS_INCLUDED +#define BOOST_PROPERTY_TREE_TEST_UTILS_INCLUDED + +#define BOOST_PROPERTY_TREE_DEBUG // Enable ptree debugging +#include + +// Do not deprecate insecure CRT calls on VC8 +#if (defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) && !defined(_CRT_SECURE_NO_DEPRECATE)) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include +#include +#include + +template +typename Ptree::size_type total_size(const Ptree &pt) +{ + typename Ptree::size_type size = 1; + for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) + size += total_size(it->second); + return size; +} + +template +typename Ptree::size_type total_keys_size(const Ptree &pt) +{ + typename Ptree::size_type size = 0; + for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) + { + size += it->first.size(); + size += total_keys_size(it->second); + } + return size; +} + +template +typename Ptree::size_type total_data_size(const Ptree &pt) +{ + typename Ptree::size_type size = pt.data().size(); + for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it) + size += total_data_size(it->second); + return size; +} + +template +class test_file +{ +public: + test_file(const char *test_data, const char *filename) + { + if (test_data && filename) + { + name = filename; + std::basic_ofstream stream(name.c_str()); + while (*test_data) + { + stream << Ch(*test_data); + ++test_data; + } + BOOST_CHECK(stream.good()); + } + } + ~test_file() + { + if (!name.empty()) + remove(name.c_str()); + } +private: + std::string name; +}; + +template +Ptree get_test_ptree() +{ + using namespace boost::property_tree; + typedef typename Ptree::key_type::value_type Ch; + Ptree pt; + pt.put_value(detail::widen("data0")); + pt.put(detail::widen("key1"), detail::widen("data1")); + pt.put(detail::widen("key1.key"), detail::widen("data2")); + pt.put(detail::widen("key2"), detail::widen("data3")); + pt.put(detail::widen("key2.key"), detail::widen("data4")); + return pt; +} + +// Generic test for file parser +template +void generic_parser_test(Ptree &pt, + ReadFunc rf, + WriteFunc wf, + const char *test_data_1, + const char *test_data_2, + const char *filename_1, + const char *filename_2, + const char *filename_out) +{ + + using namespace boost::property_tree; + typedef typename Ptree::key_type::value_type Ch; + + // Create test files + test_file file_1(test_data_1, filename_1); + test_file file_2(test_data_2, filename_2); + test_file file_out("", filename_out); + + rf(filename_1, pt); // Read file + wf(filename_out, pt); // Write file + Ptree pt2; + rf(filename_out, pt2); // Read file again + + // Compare original with read + BOOST_CHECK(pt == pt2); + +} + +// Generic test for file parser with expected success +template +void generic_parser_test_ok(ReadFunc rf, + WriteFunc wf, + const char *test_data_1, + const char *test_data_2, + const char *filename_1, + const char *filename_2, + const char *filename_out, + unsigned int total_size, + unsigned int total_data_size, + unsigned int total_keys_size) +{ + + using namespace boost::property_tree; + + std::cerr << "(progress) Starting generic parser test with test file \"" << filename_1 << "\"\n"; + + // Make sure no instances exist + BOOST_CHECK(Ptree::debug_get_instances_count() == 0); + + try + { + + // Read file + Ptree pt; + generic_parser_test(pt, rf, wf, + test_data_1, test_data_2, + filename_1, filename_2, filename_out); + + // Determine total sizes + typename Ptree::size_type actual_total_size = ::total_size(pt); + typename Ptree::size_type actual_data_size = ::total_data_size(pt); + typename Ptree::size_type actual_keys_size = ::total_keys_size(pt); + if (actual_total_size != total_size || + actual_data_size != total_data_size || + actual_keys_size != total_keys_size) + std::cerr << "Sizes: " << (unsigned)::total_size(pt) << ", " << (unsigned)::total_data_size(pt) << ", " << (unsigned)::total_keys_size(pt) << "\n"; + + // Check total sizes + BOOST_CHECK(actual_total_size == total_size); + BOOST_CHECK(actual_data_size == total_data_size); + BOOST_CHECK(actual_keys_size == total_keys_size); + + } + catch (std::runtime_error &e) + { + BOOST_ERROR(e.what()); + } + + // Test for leaks + BOOST_CHECK(Ptree::debug_get_instances_count() == 0); + +} + +// Generic test for file parser with expected error +template +void generic_parser_test_error(ReadFunc rf, + WriteFunc wf, + const char *test_data_1, + const char *test_data_2, + const char *filename_1, + const char *filename_2, + const char *filename_out, + unsigned long expected_error_line) +{ + + std::cerr << "(progress) Starting generic parser test with test file \"" << filename_1 << "\"\n"; + + // Make sure no instances exist + BOOST_CHECK(Ptree::debug_get_instances_count() == 0); + + { + + // Create ptree as a copy of test ptree (to test if read failure does not damage ptree) + Ptree pt(get_test_ptree()); + try + { + generic_parser_test(pt, rf, wf, + test_data_1, test_data_2, + filename_1, filename_2, filename_out); + BOOST_ERROR("No required exception thrown"); + } + catch (Error &e) + { + BOOST_CHECK(e.line() == expected_error_line); // Test line number + BOOST_CHECK(pt == get_test_ptree()); // Test if error damaged contents + } + catch (...) + { + BOOST_ERROR("Invalid exception type thrown"); + throw; + } + + } + + // Test for leaks + BOOST_CHECK(Ptree::debug_get_instances_count() == 0); + +} + +#endif diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp new file mode 100644 index 0000000000..9eeb04b24e --- /dev/null +++ b/test/test_xml_parser_common.hpp @@ -0,0 +1,79 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- +#ifndef TEST_XML_PARSER_COMMON_HPP_INCLUDED +#define TEST_XML_PARSER_COMMON_HPP_INCLUDED + +#include "test_utils.hpp" +#include +#include "xml_parser_test_data.hpp" + +struct ReadFunc +{ + template + void operator()(const std::string &filename, Ptree &pt) const + { + boost::property_tree::read_xml(filename, pt); + } +}; + +struct WriteFunc +{ + template + void operator()(const std::string &filename, const Ptree &pt) const + { + boost::property_tree::write_xml(filename, pt); + } +}; + +template +void test_xml_parser() +{ + + using namespace boost::property_tree; + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_1, NULL, + "testok1.xml", NULL, "testok1out.xml", 2, 0, 5 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_2, NULL, + "testok2.xml", NULL, "testok2out.xml", 5, 15, 7 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_3, NULL, + "testok3.xml", NULL, "testok3out.xml", 787, 31346, 3831 + ); + + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_4, NULL, + "testok4.xml", NULL, "testok4out.xml", 5, 2, 20 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_1, NULL, + "testerr1.xml", NULL, "testerr1out.xml", 1 + ); + + generic_parser_test_error + ( + ReadFunc(), WriteFunc(), error_data_2, NULL, + "testerr2.xml", NULL, "testerr2out.xml", 2 + ); + +} + +#endif diff --git a/test/test_xml_parser_pugxml.cpp b/test/test_xml_parser_pugxml.cpp new file mode 100644 index 0000000000..b873c3c292 --- /dev/null +++ b/test/test_xml_parser_pugxml.cpp @@ -0,0 +1,25 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#define _CRT_SECURE_NO_DEPRECATE +#define BOOST_PROPERTY_TREE_XML_PARSER_PUGXML +#include "test_xml_parser_common.hpp" + +int test_main(int argc, char *argv[]) +{ + using namespace boost::property_tree; + test_xml_parser(); + //test_xml_parser(); +#ifndef BOOST_NO_CWCHAR + //test_xml_parser(); + //test_xml_parser(); +#endif + return 0; +} diff --git a/test/test_xml_parser_rapidxml.cpp b/test/test_xml_parser_rapidxml.cpp new file mode 100644 index 0000000000..5abc18f45e --- /dev/null +++ b/test/test_xml_parser_rapidxml.cpp @@ -0,0 +1,23 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#include "test_xml_parser_common.hpp" + +int test_main(int argc, char *argv[]) +{ + using namespace boost::property_tree; + test_xml_parser(); + test_xml_parser(); +#ifndef BOOST_NO_CWCHAR + test_xml_parser(); + test_xml_parser(); +#endif + return 0; +} diff --git a/test/test_xml_parser_spirit.cpp b/test/test_xml_parser_spirit.cpp new file mode 100644 index 0000000000..75cc49a215 --- /dev/null +++ b/test/test_xml_parser_spirit.cpp @@ -0,0 +1,24 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2006 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#define BOOST_PROPERTY_TREE_XML_PARSER_SPIRIT +#include "test_xml_parser_common.hpp" + +int test_main(int argc, char *argv[]) +{ + using namespace boost::property_tree; + test_xml_parser(); + test_xml_parser(); +#ifndef BOOST_NO_CWCHAR + test_xml_parser(); + test_xml_parser(); +#endif + return 0; +} diff --git a/test/test_xml_parser_tinyxml.cpp b/test/test_xml_parser_tinyxml.cpp new file mode 100644 index 0000000000..eb4be3cb59 --- /dev/null +++ b/test/test_xml_parser_tinyxml.cpp @@ -0,0 +1,26 @@ +// ---------------------------------------------------------------------------- +// Copyright (C) 2002-2005 Marcin Kalicinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see www.boost.org +// ---------------------------------------------------------------------------- + +#ifdef _DEBUG + #pragma comment( lib, "tinyxmld_STL.lib" ) +#else + #pragma comment( lib, "tinyxml_STL.lib" ) +#endif + +#define BOOST_PROPERTY_TREE_XML_PARSER_TINYXML +#include "test_xml_parser_common.hpp" + +int test_main(int argc, char *argv[]) +{ + using namespace boost::property_tree; + test_xml_parser(); + test_xml_parser(); + return 0; +} diff --git a/test/xml_parser_test_data.hpp b/test/xml_parser_test_data.hpp new file mode 100644 index 0000000000..557b052b77 --- /dev/null +++ b/test/xml_parser_test_data.hpp @@ -0,0 +1,743 @@ +#ifndef XML_PARSER_TEST_DATA_HPP_INCLUDED +#define XML_PARSER_TEST_DATA_HPP_INCLUDED + +/////////////////////////////////////////////////////////////////////////////// +// Test data + +// Correct +const char *ok_data_1 = + "\n" + ""; + +// Correct +const char *ok_data_2 = + "\n" + "\n" + "<>&\n" + "1<2>3&4\n" + " < > & \n" + "\n"; + +// Correct +const char *ok_data_3 = + "\n" + "\n" + "\n" + "]>\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "
\n" + " XML Linking Language (XLink)\n" + " Version 1.0\n" + " WD-xlink-19990527\n" + " World Wide Web Consortium Working Draft\n" + " 29May1999\n" + " \n" + "

This draft is for public discussion.

\n" + "
\n" + " http://www.w3.org/XML/Group/1999/05/WD-xlink-current\n" + " \n" + " \n" + " http://www.w3.org/XML/Group/1999/05/WD-xlink-19990527\n" + " http://www.w3.org/XML/Group/1999/05/WD-xlink-19990505\n" + " http://www.w3.org/TR/1998/WD-xlink-19980303\n" + " http://www.w3.org/TR/WD-xml-link-970630\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " Steve DeRose\n" + " Inso Corp. and Brown University\n" + " Steven_DeRose@Brown.edu\n" + " \n" + " \n" + " David Orchard\n" + " IBM Corp.\n" + " dorchard@ca.ibm.com\n" + " \n" + " \n" + " Ben Trafford\n" + " Invited Expert\n" + " bent@exemplary.net\n" + " \n" + " \n" + " \n" + "\n" + " \n" + "

This is a W3C Working Draft for review by W3C members and other interested parties. It is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use W3C Working Drafts as reference material or to cite them as other than \"work in progress\". A list of current W3C working drafts can be found at http://www.w3.org/TR.

\n" + "

Note: Since working drafts are subject to frequent change, you are advised to reference the above URI, rather than the URIs for working drafts themselves. Some of the work remaining is described in .

\n" + "

This work is part of the W3C XML Activity (for current status, see http://www.w3.org/XML/Activity ). For information about the XPointer language which is expected to be used with XLink, see http://www.w3.org/TR/WD-xptr.\n" + "

\n" + "

See http://www.w3.org/TR/NOTE-xlink-principles for additional background on the design principles informing XLink.

\n" + "

Also see http://www.w3.org/TR/NOTE-xlink-req/ for the XLink requirements that this document attempts to satisfy.

\n" + "
\n" + "\n" + " \n" + " \n" + "

This specification defines constructs that may be inserted into XML DTDs, schemas and document instances to describe links between objects. It uses XML syntax to create structures that can describe the simple unidirectional hyperlinks of today's HTML as well as more sophisticated links.

\n" + "
\n" + "\n" + " \n" + "

Burlington, Seekonk, et al.: World-Wide Web Consortium, XML Working Group, 1998.

\n" + "
\n" + "\n" + " \n" + "

Created in electronic form.

\n" + "
\n" + "\n" + " \n" + " English\n" + " Extended Backus-Naur Form (formal grammar)\n" + " \n" + "\n" + " \n" + " \n" + " 1997-01-15 : Skeleton draft by TB\n" + " 1997-01-24 : Fleshed out by sjd\n" + " 1997-04-08 : Substantive draft\n" + " 1997-06-30 : Public draft\n" + " 1997-08-01 : Public draft\n" + " 1997-08-05 : Prose/organization work by sjd\n" + " 1997-10-14: Conformance and design principles; a bit of cleanup by elm\n" + " 1997-11-07: Update for editorial issues per issues doc, by sjd.\n" + " 1997-12-01: Update for editorial issues per issues doc in preparation for F2F meeting, by sjd.\n" + " 1998-01-13: Editorial cleanup, addition of new design principles, by elm.\n" + " 1998-02-27: Splitting out of XLink and XPointer, by elm.\n" + " 1998-03-03: Moved most of the XPointer locator stuff here. elm\n" + " 1999-04-24: Editorial rewrites to represent new ideas on XLink, especially the inclusion of arcs. bent\n" + " 1999-05-05: Prose/organization work by dorchard. Moved much of the semantics section around, from: locators, link semantics, remote resource semantics, local resource semantics; to: resource semantics, locators, behavior semantics, link semantics, arc semantics\n" + " 1999-05-12: Prose/organization work. Re-organized some of the sections, removed XML constructs from the document, added descriptive prose, edited document text for clarity. Rewrote the link recognition section. bent\n" + " 1999-05-17: Further prose work. Added non-normative examples. Clarified arcs. bent\n" + " 1999-05-23: Edited for grammar and clarity. bent\n" + " 1999-05-27: Final once-over before sending to group. Fixed sjd's email address. bent\n" + " \n" + " \n" + "
\n" + "\n" + "\n" + " \n" + " Introduction\n" + "

This specification defines constructs that may be inserted into XML DTDs, schemas, and document instances to describe links between objects. A link, as the term is used here, is an explicit relationship between two or more data objects or portions of data objects. This specification is concerned with the syntax used to assert link existence and describe link characteristics. Implicit (unasserted) relationships, for example that of one word to the next or that of a word in a text to its entry in an on-line dictionary are obviously important, but outside its scope.

\n" + "

Links are asserted by elements contained in XML document instances. The simplest case is very like an HTML A link, and has these characteristics:\n" + " \n" + "

The link is expressed at one of its ends (similar to the A element in some document)

\n" + "

Users can only initiate travel from that end to the other

\n" + "

The link's effect on windows, frames, go-back lists, stylesheets in use, and so on is mainly determined by browsers, not by the link itself. For example, traveral of A links normally replaces the current view, perhaps with a user option to open a new window.

\n" + "

The link goes to only one destination (although a server may have great freedom in finding or dynamically creating that destination).

\n" + " \n" + "

\n" + "

While this set of characteristics is already very powerful and obviously has proven itself highly useful and effective, each of these assumptions also limits the range of hypertext functionality. The linking model defined here provides ways to create links that go beyond each of these specific characteristics, thus providing features previously available mostly in dedicated hypermedia systems.\n" + "

\n" + "\n" + "\n" + " Origin and Goals\n" + "

Following is a summary of the design principles governing XLink:\n" + " \n" + "

XLink must be straightforwardly usable over the Internet.

\n" + "

XLink must be usable by a wide variety of link usage domains and classes of linking application software.

\n" + "

XLink must support HTML 4.0 linking constructs.

\n" + "

The XLink expression language must be XML.

\n" + "

The XLink design must be formal, concise, and illustrative.

\n" + "

XLinks must be human-readable and human-writable.

\n" + "

XLinks may reside within or outside the documents in which the\n" + " participating resources reside.

\n" + "

XLink must represent the abstract structure and significance of links.

\n" + "

XLink must be feasible to implement.

\n" + "

XLink must be informed by knowledge of established hypermedia systems and standards.

\n" + " \n" + "

\n" + "
\n" + "\n" + "\n" + "\n" + " Relationship to Existing Standards\n" + "

Three standards have been especially influential:\n" + " \n" + "

HTML: Defines several SGML element types that represent links.

\n" + "

HyTime: Defines inline and out-of-line link structures and some semantic features, including traversal control and presentation of objects. \n" + "

\n" + "

Text Encoding Initiative Guidelines (TEI P3): Provides structures for creating links, aggregate objects, and link collections out of them.

\n" + " \n" + "

\n" + "

Many other linking systems have also informed this design, especially Dexter, FRESS, MicroCosm, and InterMedia.

\n" + "
\n" + "\n" + "\n" + " Terminology\n" + "

The following basic terms apply in this document. \n" + " \n" + " \n" + " \n" + "

A symbolic representation of traversal behavior in links, especially the direction, context and timing of traversal.

\n" + " \n" + " \n" + " \n" + "

A representation of the relevant structure specified by the tags and attributes in an XML document, based on \"groves\" as defined in the ISO DSSSL standard.

\n" + "
\n" + " \n" + " \n" + "

Abstractly, a link which serves as one of its own resources. Concretely, a link where the content of the linking element serves as a participating resource.\n" + " HTML A, HyTime clink, and TEI XREF\n" + " are all inline links.

\n" + "
\n" + " \n" + " \n" + "

An explicit relationship between two or more data objects or portions of data objects.

\n" + "
\n" + " \n" + " \n" + "

An element that asserts the existence and describes the characteristics of a link.

\n" + "
\n" + " \n" + " \n" + "

The content of an inlinelinking element. Note that the content of the linking element could be explicitly pointed to by means of a regular locator in the same linking element, in which case the resource is considered remote, not local.

\n" + "
\n" + " \n" + " \n" + "

Data, provided as part of a link, which identifies a\n" + " resource.

\n" + "
\n" + " \n" + " \n" + "

A link whose traversal can be initiated from more than one of its participating resources. Note that being able to \"go back\" after following a one-directional link does not make the link multidirectional.

\n" + "
\n" + " \n" + " \n" + "

A link whose content does not serve as one of the link's participating resources . Such links presuppose a notion like extended link groups, which instruct application software where to look for links. Out-of-line links are generally required for supporting multidirectional traversal and for allowing read-only resources to have outgoing links.

\n" + "
\n" + " \n" + "

In the context of link behavior, a parsed link is any link whose content is transcluded into the document where the link originated. The use of the term \"parsed\" directly refers to the concept in XML of a\n" + " parsed entity.

\n" + "
\n" + " \n" + " \n" + "

A resource that belongs to a link. All resources are potential contributors to a link; participating resources are the actual contributors to a particular link.

\n" + "
\n" + " \n" + " \n" + "

Any participating resource of a link that is pointed to with a locator.

\n" + "
\n" + " \n" + " \n" + "

In the abstract sense, an addressable unit of information or service that is participating in a link. Examples include files, images, documents, programs, and query results. Concretely, anything reachable by the use of a locator in some linking element. Note that this term and its definition are taken from the basic specifications governing the World Wide Web. \n" + "

\n" + "
\n" + " \n" + " \n" + "

A portion of a resource, pointed to as the precise destination of a link. As one example, a link might specify that an entire document be retrieved and displayed, but that some specific part(s) of it is the specific linked data, to be treated in an application-appropriate manner such as indication by highlighting, scrolling, etc.

\n" + "
\n" + " \n" + " \n" + "

The action of using a link; that is, of accessing a resource. Traversal may be initiated by a user action (for example, clicking on the displayed content of a linking element) or occur under program control.

\n" + "
\n" + " \n" + "

\n" + "
\n" + "\n" + "\n" + " Notation\n" + "

The formal grammar for locators is given using a simple Extended Backus-Naur Form (EBNF) location, as described in the XML specification.

\n" + " \n" + "
\n" + "
\n" + "\n" + "\n" + " Locator Syntax\n" + "

The locator for a resource is typically provided by means of a Uniform Resource Identifier, or URI. XPointers can be used in conjunction with the URI structure, as fragment identifiers, to specify a more precise sub-resource.

\n" + " \n" + "

A locator generally contains a URI, as described in IETF RFCs and . As these RFCs state, the URI may include a trailing query (marked by a leading \"?\"), and be followed by a \"#\" and a fragment identifier, with the query interpreted by the host providing the indicated resource, and the interpretation of the fragment identifier dependent on the data type of the indicated resource.

\n" + " \n" + "

In order to locate XML documents and portions of documents, a locator value may contain either a URI or a fragment identifier, or both. Any fragment identifier for pointing into XML must be an XPointer.

\n" + "

Special syntax may be used to request the use of particular processing models in accessing the locator's resource. This is designed to reflect the realities of network operation, where it may or may not be desirable to exercise fine control over the distribution of work between local and remote processors. \n" + " \n" + " Locator\n" + " \n" + " Locator\n" + " URI\n" + " | Connector (XPointer | Name)\n" + " | URI Connector (XPointer | Name)\n" + " \n" + " \n" + " Connector'#' | '|'\n" + " \n" + " \n" + " URIURIchar*\n" + " \n" + " \n" + "

\n" + "

In this discussion, the term designated resource refers to the resource which an entire locator serves to locate. The following rules apply:\n" + " \n" + " \n" + "

The URI, if provided, locates a resource called the containing resource.

\n" + " \n" + " \n" + "

If the URI is not provided, the containing resource is considered to be the document in which the linking element is contained. \n" + "

\n" + " \n" + "

If an XPointer is provided, the designated resource is a sub-resource\n" + " of the containing resource; otherwise the designated resource is the\n" + " containing resource.

\n" + "
\n" + " \n" + " \n" + "

If the Connector is followed directly by a Name, the Name is shorthand for the XPointer\"id(Name)\"; that is, the sub-resource is the element in the containing resource that has an XML ID attribute whose value matches the Name. This shorthand is to encourage use of the robust id addressing mode.

\n" + "
\n" + " \n" + " \n" + "

If the connector is \"#\", this signals an intent that the containing resource is to be fetched as a whole from the host that provides it, and that the XPointer processing to extract the sub-resource\n" + " is to be performed on the client, that is to say on the same system where the linking element is recognized and processed.

\n" + "
\n" + " \n" + "

If the connector is \"|\", no intent is signaled as to what processing model is to be used to go about accessing the designated resource.

\n" + "
\n" + " \n" + "

\n" + "

Note that the definition of a URI includes an optional query component.

\n" + "

In the case where the URI contains a query (to be interpreted by the server), information providers and authors of server software are urged to use queries as follows: \n" + " \n" + " Query\n" + " \n" + " Query'XML-XPTR=' ( XPointer | Name)\n" + " \n" + " \n" + "

\n" + " \n" + "
\n" + "\n" + "\n" + " Link Recognition\n" + "

The existence of a link is asserted by a linking element. Linking elements must be recognized reliably by application software in order to provide appropriate display and behavior. There are several ways link recognition could be accomplished: for example, reserving element type names, reserving attributes names, leaving the matter of recognition entirely up to stylesheets and application software, or using the XLink namespace to specify element names and attribute names that would be recognized by namespace and XLink-aware processors. Using element and attribute names within the XLink namespace provides a balance between giving users control of their own markup language design and keeping the identification of linking elements simple and unambiguous.

\n" + "

The two approaches to identifying linking elements are relatively simple to implement. For example, here's how the HTML A element would be declared using attributes within the XLink namespace, and then how an element within the XLink namespace might do the same:\n" + " <A xlink:type=\"simple\" xlink:href=\"http://www.w3.org/TR/wd-xlink/\"\n" + "xlink:title=\"The Xlink Working Draft\">The XLink Working Draft.</A>\n" + " <xlink:simple href=\"http://www.w3.org/TR/wd-xlink/\"\n" + "title=\"The XLink Working Draft\">The XLink Working Draft</xlink:simple>\n" + " Any arbitrary element can be made into an XLink by using the xlink:type attribute. And, of course, the explicit XLink elements may be used, as well. This document will go on to describe the linking attributes that are associated with linking elements. It may be assumed by the reader that these attributes would require the xlink namespace prefix if they existed within an arbitrary element, or that they may be used directly if they exist within an explicit Xlink element.

\n" + " \n" + "
\n" + "\n" + "\n" + "\n" + " Linking Attributes\n" + "

XLink has several attributes associated with the variety of links it may represent. These attributes define four main concepts: locators, arcs, behaviors, and semantics. Locators define where the actual resource is located. Arcs define the traversal of links. Where does the link come from? Where does it go to? All this information can be stored in the arc attributes. Behaviors define how the link is activated, and what the application should do with the resource being linked to. Semantics define useful information that the application may use, and enables the link for such specalized targets as constricted devices and accessibility software.

\n" + " \n" + " \n" + " Locator Attributes\n" + "

The only locator attribute at this time is href. This attribute must contain either a string in the form of a URI that defines the remote resource being linked to, a string containing a fragment identifier that links to a local resource, or a string containing a URI with a fragment identifier concacenated onto it.

\n" + "
\n" + "\n" + " \n" + " Arc Attributes\n" + "

Arcs contain two attributes, from and to. The from attribute may contain a string containing the content of a role attribute from the resource being linked from. The purpose of the from attribute is to define where this link is being actuated from.

\n" + "

The to attribute may contain a string containing the content of a role attribute from the resource being linked to. The purpose of the to attribute is to define where this link traverses to.

\n" + "

The application may use this information in a number of ways, especially in a complex hypertext system, but it is mainly useful in providing context for application behavior.

\n" + " \n" + "
\n" + "\n" + " \n" + " Behavior Attributes\n" + "

There are two attributes associated with behavior: show and actuate. The show attribute defines how the remote resource is to be revealed to the user. It has three options: new, parsed, and replace. The new option indicates that the remote resource should be shown in a new window (or other device context) without replacing the previous content. The parsed option, relating directly to the XML concept of a parsed entity, indicates that the content should be integrated into the document from which the link was actuated. The replace option is the one most commonly seen on the World Wide Web, where the document being linked from is entirely replaced by the object being linked to.

\n" + "

The actuate attribute defines how the link is initiated. It has two options: user and auto. The user option indicates that the link must be initiated by some sort of human-initiated selection, such as clicking on an HTML anchor. The auto option indicates that the link is automatically initiated when the application deems that the user has reached the link. It then follows the behavior set out in the show option.

\n" + " \n" + "
\n" + "\n" + " \n" + " Semantic Attributes\n" + "

There are two attributes associated with semantics, role and title. The role attribute is a generic string used to describe the function of the link's content. For example, a poem might have a link with a role=\"stanza\". The role is also used as an identifier for the from and to attributes of arcs.

\n" + "

The title attribute is designed to provide human-readable text describing the link. It is very useful for those who have text-based applications, whether that be due to a constricted device that cannot display the link's content, or if it's being read by an application to a visually-impaired user, or if it's being used to create a table of links. The title attribute contains a simple, descriptive string.

\n" + "
\n" + "
\n" + "\n" + "\n" + " Linking Elements\n" + "

There are several kinds of linking elements in XLink: simple links, locators, arcs, and extended links. These elements may be instantiated via element declarations from the XLink namespace, or they may be instantiated via attribute declarations from the XLink namespace. Both kinds of instantiation are described in the definition of each linking element.

\n" + "

The simple link is used to declare a link that approximates the functionality of the HTML A element. It has, however, a few added features to increase its value, including the potential declaration of semantics and behavior. The locator elements are used to define the resource being linked to. Some links may contain multiple locators, representing a choice of potential links to be traversed. The arcs are used to define the traversal semantics of the link. Finally, an extended linking element differs from a simple link in that it can connect any number of resources, not just one local resource (optionally) and one remote resource, and in that extended links are more often out-of-line than simple links.

\n" + "\n" + "\n" + " Simple Links\n" + "

Simple links can be used for purposes that approximate the functionality of a basic HTML A link, but they can also support a limited amount of additional functionality. Simple links have only one locator and thus, for convenience, combine the functions of a linking element and a locator into a single element. As a result of this combination, the simple linking element offers both a locator attribute and all the behavior and semantic attributes.

\n" + "

The following are two examples of linking elements, each showing all the possible attributes that can be associated with a simple link. Here is the explicit XLink simple linking element.\n" + " <!ELEMENT xlink:simple ANY>\n" + "<!ATTLIST xlink:slink\n" + " href CDATA #REQUIRED\n" + " role CDATA #IMPLIED\n" + " title CDATA #IMPLIED\n" + " show (new|parsed|replace) \"replace\"\n" + " actuate (user|auto) \"user\"\n" + ">\n" + " And here is how to make an arbitrary element into a simple link.\n" + " <!ELEMENT xlink:simple ANY>\n" + "<!ATTLIST foo\n" + " xlink:type (simple|extended|locator|arc) #FIXED \"simple\" \n" + " xlink:href CDATA #REQUIRED\n" + " xlink:role CDATA #IMPLIED\n" + " xlink:title CDATA #IMPLIED\n" + " xlink:show (new|parsed|replace) \"replace\"\n" + " xlink:actuate (user|auto) \"user\"\n" + ">\n" + " Here is how the first example might look in a document:\n" + "<xlink:simple href=\"http://www.w3.org/TR/wd-xlink\" role=\"working draft\" \n" + " title=\"The XLink Working Draft\" show=\"replace\" actuate=\"user\">\n" + "The XLink Working Draft.</xlink:simple>\n" + "<foo xlink:href=\"http://www.w3.org/TR/wd-xlink\" xlink:role=\"working draft\"\n" + " xlink:title=\"The XLink Working Draft\" xlink:show=\"new\" xlink:actuate=\"user\">\n" + "The XLink Working Draft.</foo>\n" + " Alternately, a simple link could be as terse as this:\n" + "<foo xlink:href=\"#stanza1\">The First Stanza.</foo>\n" + "

\n" + "

\n" + " There are no constraints on the contents of a simple linking element. In\n" + " the sample declaration above, it is given a content model of ANY\n" + " to illustrate that any content model or declared content is acceptable. In\n" + " a valid document, every element that is significant to XLink must still conform\n" + " to the constraints expressed in its governing DTD.

\n" + "

Note that it is meaningful to have an out-of-line simple link, although\n" + " such links are uncommon. They are called \"one-ended\" and are typically used\n" + " to associate discrete semantic properties with locations. The properties might\n" + " be expressed by attributes on the link, the link's element type name, or in\n" + " some other way, and are not considered full-fledged resources of the link.\n" + " Most out-of-line links are extended links, as these have a far wider range\n" + " of uses.

\n" + "
\n" + "\n" + "\n" + "Extended Links\n" + "

An extended link differs from a simple link in that it can connect any number of resources, not just one local resource (optionally) and one remote resource, and in that extended links are more often out-of-line than simple links.

\n" + "

These additional capabilities of extended links are required for: \n" + " \n" + " \n" + "

Enabling outgoing links in documents that cannot be modified to add an inline link

\n" + " \n" + " \n" + "

Creating links to and from resources in formats with no native support for embedded links (such as most multimedia formats)

\n" + "
\n" + " \n" + "

Applying and filtering sets of relevant links on demand

\n" + "
\n" + "

Enabling other advanced hypermedia capabilities

\n" + " \n" + "

\n" + "

Application software might be expected to provide traversal among all of a link's participating resources (subject to semantic constraints outside the scope of this specification) and to signal the fact that a given resource or sub-resource participates in one or more links when it is displayed (even though there is no markup at exactly that point to signal it).

\n" + "

A linking element for an extended link contains a series of child elements that serve as locators and arcs. Because an extended link can have more than one remote resource, it separates out linking itself from the mechanisms used to locate each resource (whereas a simple link combines the two).

\n" + "

The xlink:type attribute value for an extended link must be extended, if the link is being instantiated on an arbitrary element. Note that extended links introduce variants of the show and actuate behavior attributes. These attributes, the showdefault and actuatedefault define the same behavior as their counterparts. However, in this case, they are considered to define the default behavior for all the linking elements that they contain.

\n" + "

However, when a linking element within an extended link has a show or actuate attribute of its own, that attribute overrides the defaults set on the extended linking element.

\n" + "

The extended linking element itself retains those attributes relevant to the link as a whole, and to its local resource if any. Following are two sample declaration for an extended link. The first is an example of the explicit XLink extended link:\n" + " \n" + "<!ELEMENT xlink:extended ((xlink:arc | xlink:locator)*)>\n" + "<!ATTLIST xlink:extended\n" + " role CDATA #IMPLIED\n" + " title CDATA #IMPLIED\n" + " showdefault (new|parsed|replace) #IMPLIED \n" + " actuatedefault (user|auto) #IMPLIED >\n" + "\n" + " The second is an example of an arbitrary element being used an extended link:\n" + "\n" + "<!ELEMENT foo ((xlink:arc | xlink:locator)*)>\n" + "<!ATTLIST foo\n" + " xlink:type (simple|extended|locator|arc) #FIXED \"extended\"\n" + " xlink:role CDATA #IMPLIED\n" + " xlink:title CDATA #IMPLIED\n" + " xlink:showdefault (new|parsed|replace) #IMPLIED \n" + " xlink:actuatedefault (user|auto) #IMPLIED >\n" + "\n" + " The following two examples demonstrate how each of the above might appear within a document instance. Note that the content of these examples would be other elements. For brevity's sake, they've been left blank. The first example shows how the link might appear, using an explicit XLink extended link:\n" + "\n" + "<xlink:extended role=\"address book\" title=\"Ben's Address Book\" showdefault=\"replace\" actuatedefault=\"user\"> ... </xlink:extended>\n" + "\n" + " And the second shows how the link might appear, using an arbitrary element:\n" + "\n" + "<foo xlink:type=\"extended\" xlink:role=\"address book\" xlink:title=\"Ben's Address Book\" xlink:showdefault=\"replace\" xlink:actuatedefault=\"user\"> ... </foo>\n" + "

\n" + "\n" + "
\n" + "\n" + "\n" + " Arc Elements\n" + "

An arc is contained within an extended link for the purpose of defining traversal behavior. More than one arc may be associated with a link. Otherwise, arc elements function exactly as the arc attributes might lead on to expect.

\n" + " \n" + "
\n" + "\n" + "
\n" + "\n" + "Conformance\n" + "

An element conforms to XLink if: \n" + "

The element has an xml:link attribute whose value is\n" + "one of the attribute values prescribed by this specification, and

\n" + "

the element and all of its attributes and content adhere to the\n" + "syntactic\n" + "requirements imposed by the chosen xml:link attribute value,\n" + "as prescribed in this specification.

\n" + "

\n" + "

Note that conformance is assessed at the level of individual elements,\n" + "rather than whole XML documents, because XLink and non-XLink linking mechanisms\n" + "may be used side by side in any one document.

\n" + "

An application conforms to XLink if it interprets XLink-conforming elements\n" + "according to all required semantics prescribed by this specification and,\n" + "for any optional semantics it chooses to support, supports them in the way\n" + "prescribed.

\n" + "
\n" + "\n" + "\n" + "Unfinished Work\n" + "\n" + "Structured Titles\n" + "

The simple title mechanism described in this draft is insufficient to cope\n" + "with internationalization or the use of multimedia in link titles. A future\n" + "version will provide a mechanism for the use of structured link titles.

\n" + "
\n" + "
\n" + "\n" + "References\n" + "\n" + "Eve Maler and Steve DeRose, editors. \n" + "XML Pointer Language (XPointer) V1.0. ArborText, Inso, and Brown\n" + "University. Burlington, Seekonk, et al.: World Wide Web Consortium, 1998.\n" + "(See http://www.w3.org/TR/WD-xptr\n" + " .)\n" + "ISO (International Organization for\n" + "Standardization). ISO/IEC 10744-1992 (E). Information technology\n" + "- Hypermedia/Time-based Structuring Language (HyTime). [Geneva]:\n" + "International Organization for Standardization, 1992. Extended\n" + "Facilities\n" + "Annex. [Geneva]: International Organization for Standardization,\n" + "1996. (See http://www.ornl.go\n" + "v/sgml/wg8/hytime/html/is10744r.html ).\n" + "IETF (Internet Engineering Task\n" + "Force). \n" + "RFC 1738: Uniform Resource Locators. 1991. (See \n" + "http://www.w3.org/Addressing/rfc1738.txt).\n" + "IETF (Internet Engineering Task\n" + "Force). \n" + "RFC 1808: Relative Uniform Resource Locators. 1995. (See http://www.w3.org/Addressing/rfc\n" + "1808.txt ).\n" + "C. M. Sperberg-McQueen and Lou Burnard, editors.\n" + "\n" + "Guidelines for Electronic Text Encoding and Interchange. Association\n" + "for Computers and the Humanities (ACH), Association for Computational\n" + "Linguistics\n" + "(ACL), and Association for Literary and Linguistic Computing (ALLC). Chicago,\n" + "Oxford: Text Encoding Initiative, 1994. \n" + "]Steven J. DeRose and David G. Durand. 1995. \"The\n" + "TEI Hypertext Guidelines.\" In Computing and the Humanities\n" + "29(3).\n" + "Reprinted in Text Encoding Initiative: Background and\n" + "Context,\n" + "ed. Nancy Ide and Jean ronis , ISBN 0-7923-3704-2. \n" + "\n" + "
\n" + "\n"; + +// Correct +const char *ok_data_4 = + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + " \n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "]>\n" + "\n" + "\n" + "\n" + "PP\n" + "\n" + "\n"; + +// Erroneous +const char *error_data_1 = + "a"; // bogus character + +// Erroneous +const char *error_data_2 = + "\n" + ""; // XML tag not closed + +#endif From 235fedba4ead576cc532bb5af7940675e69eae18 Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sat, 17 Oct 2009 01:10:45 +0000 Subject: [PATCH 03/23] rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release. [SVN r56941] --- CMakeLists.txt | 27 --------------------------- module.cmake | 1 - test/CMakeLists.txt | 28 ---------------------------- 3 files changed, 56 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 module.cmake delete mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 2f10651af2..0000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright Sebastian Redl -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# -#---------------------------------------------------------------------------- -# This file was automatically generated from the original CMakeLists.txt file -# Add a variable to hold the headers for the library -set (lib_headers - property_tree -) - -# Add a library target to the build system -boost_library_project( - property_tree - # SRCDIRS - TESTDIRS test - HEADERS ${lib_headers} - # DOCDIRS - # DESCRIPTION "Helps Boost library developers adapt to compiler idiosyncrasies; not intended for library users." - MODULARIZED - # AUTHORS "John Maddock " - # MAINTAINERS -) - - diff --git a/module.cmake b/module.cmake deleted file mode 100644 index 8517f41c92..0000000000 --- a/module.cmake +++ /dev/null @@ -1 +0,0 @@ -boost_module(property_tree DEPENDS serialization any optional) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index e512617c24..0000000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright Sebastian Redl -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# -#---------------------------------------------------------------------------- -boost_additional_test_dependencies(property_tree BOOST_DEPENDS test serialization) - - -#-- List our regression tests -set (tests - test_property_tree - test_info_parser - test_json_parser - # test_xml_parser_rapidxml -) -message(STATUS "property_tree/test/test_xml_parser_rapidxml needs love.") - -# test_xml_parser_rapidxml gets compile errors that I can not figure out - - -#-- Create an executable test for each -foreach(test ${tests}) - boost_test_run(${test} "${test}.cpp" - COMPILE_FLAGS ${test_compile_flags} - DEPENDS boost_unit_test_framework boost_serialization STATIC) -endforeach(test ${tests}) From 750d471a770f776520d7abe134ed501cd93b8748 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sun, 9 May 2010 01:03:59 +0000 Subject: [PATCH 04/23] Merge standards conformance fixes for Boost.PropertyTree [SVN r61863] --- .../boost/property_tree/detail/ptree_implementation.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/property_tree/detail/ptree_implementation.hpp b/include/boost/property_tree/detail/ptree_implementation.hpp index 260c2cefe5..9759c697ab 100644 --- a/include/boost/property_tree/detail/ptree_implementation.hpp +++ b/include/boost/property_tree/detail/ptree_implementation.hpp @@ -480,14 +480,16 @@ namespace boost { namespace property_tree typename basic_ptree::iterator basic_ptree::to_iterator(assoc_iterator ai) { - return iterator(subs::ch(this).project<0>(ai.base())); + return iterator(subs::ch(this). + BOOST_NESTED_TEMPLATE project<0>(ai.base())); } template inline typename basic_ptree::const_iterator basic_ptree::to_iterator(const_assoc_iterator ai) const { - return const_iterator(subs::ch(this).project<0>(ai.base())); + return const_iterator(subs::ch(this). + BOOST_NESTED_TEMPLATE project<0>(ai.base())); } // Property tree view @@ -746,7 +748,7 @@ namespace boost { namespace property_tree Translator tr) const { if (optional child = get_child_optional(path)) - return child.get().get_value_optional(tr); + return child.get().BOOST_NESTED_TEMPLATE get_value_optional(tr); else return optional(); } From db59ef4801f18843682bed4b17f21c72ba5ba47f Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 26 Jun 2010 12:30:09 +0000 Subject: [PATCH 05/23] Merge documentation fixes. * Use `doc/src/*.css` instead of `doc/html/*.css`. * Remove wiki and people directories. * Some documentation fixes. * Left out `minimal.css` changes and boostbook changes because of clashes. [SVN r63347] --- doc/Jamfile.v2 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 379bd10988..4f62fc9df9 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -37,9 +37,7 @@ xml property_tree : property_tree.qbk ; boostbook standalone : property_tree - : html.stylesheet=../../../../doc/html/boostbook.css - boost.root=../../../.. - boost.libraries=../../../libraries.htm + : boost.root=../../../.. toc.max.depth=3 toc.section.depth=2 chunk.section.depth=3 From d1d123d192ad3574bd9414d999c6cdb2e2964b97 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Sat, 3 Jul 2010 20:59:45 +0000 Subject: [PATCH 06/23] Merged r59734 and r61606 from trunk; fixes #3594 and #4092 [SVN r63563] --- .../detail/ptree_implementation.hpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/boost/property_tree/detail/ptree_implementation.hpp b/include/boost/property_tree/detail/ptree_implementation.hpp index 9759c697ab..6616d874cb 100644 --- a/include/boost/property_tree/detail/ptree_implementation.hpp +++ b/include/boost/property_tree/detail/ptree_implementation.hpp @@ -15,6 +15,11 @@ #include #include +#if defined(BOOST_MSVC) && \ + (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000) +#define BOOST_PROPERTY_TREE_PAIR_BUG +#endif + namespace boost { namespace property_tree { template @@ -22,6 +27,22 @@ namespace boost { namespace property_tree { struct by_name {}; // The actual child container. +#if defined(BOOST_PROPERTY_TREE_PAIR_BUG) + // MSVC 10 has moved std::pair's members to a base + // class. Unfortunately this does break the interface. + BOOST_STATIC_CONSTANT(unsigned, + first_offset = offsetof(value_type, first)); + typedef multi_index_container, + multi_index::ordered_non_unique, + multi_index::member_offset, + key_compare + > + > + > base_container; +#else typedef multi_index_container, @@ -32,6 +53,7 @@ namespace boost { namespace property_tree > > > base_container; +#endif // The by-name lookup index. typedef typename base_container::template index::type by_name_index; @@ -874,4 +896,8 @@ namespace boost { namespace property_tree } } +#if defined(BOOST_PROPERTY_TREE_PAIR_BUG) +#undef BOOST_PROPERTY_TREE_PAIR_BUG +#endif + #endif From ab64e13f12352fa5c2ac15b65b5672fd1d3f6499 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Fri, 15 Oct 2010 12:40:04 +0000 Subject: [PATCH 07/23] Merge long-overdue PTree changes to release (boost) [SVN r65975] --- .../detail/exception_implementation.hpp | 12 +- .../detail/file_parser_error.hpp | 35 +- .../property_tree/detail/json_parser_read.hpp | 11 +- .../detail/json_parser_write.hpp | 86 ++--- .../detail/ptree_implementation.hpp | 13 +- .../boost/property_tree/detail/rapidxml.hpp | 355 ++++++++---------- .../property_tree/detail/xml_parser_error.hpp | 8 +- .../detail/xml_parser_read_rapidxml.hpp | 48 ++- .../property_tree/detail/xml_parser_utils.hpp | 3 + .../property_tree/detail/xml_parser_write.hpp | 16 +- .../detail/xml_parser_writer_settings.hpp | 12 +- include/boost/property_tree/json_parser.hpp | 14 +- include/boost/property_tree/ptree_fwd.hpp | 11 +- include/boost/property_tree/string_path.hpp | 2 + 14 files changed, 314 insertions(+), 312 deletions(-) diff --git a/include/boost/property_tree/detail/exception_implementation.hpp b/include/boost/property_tree/detail/exception_implementation.hpp index 8ac6d93b5c..551e10ce37 100644 --- a/include/boost/property_tree/detail/exception_implementation.hpp +++ b/include/boost/property_tree/detail/exception_implementation.hpp @@ -30,8 +30,8 @@ namespace boost { namespace property_tree /////////////////////////////////////////////////////////////////////////// // ptree_error - inline ptree_error::ptree_error(const std::string &what): - std::runtime_error(what) + inline ptree_error::ptree_error(const std::string &w): + std::runtime_error(w) { } @@ -43,8 +43,8 @@ namespace boost { namespace property_tree // ptree_bad_data template inline - ptree_bad_data::ptree_bad_data(const std::string &what, const D &data): - ptree_error(what), m_data(data) + ptree_bad_data::ptree_bad_data(const std::string &w, const D &d): + ptree_error(w), m_data(d) { } @@ -62,8 +62,8 @@ namespace boost { namespace property_tree // ptree_bad_path template inline - ptree_bad_path::ptree_bad_path(const std::string &what, const P &path): - ptree_error(detail::prepare_bad_path_what(what, path)), m_path(path) + ptree_bad_path::ptree_bad_path(const std::string &w, const P &p): + ptree_error(detail::prepare_bad_path_what(w, p)), m_path(p) { } diff --git a/include/boost/property_tree/detail/file_parser_error.hpp b/include/boost/property_tree/detail/file_parser_error.hpp index 4c8b237422..ff90583f9e 100644 --- a/include/boost/property_tree/detail/file_parser_error.hpp +++ b/include/boost/property_tree/detail/file_parser_error.hpp @@ -26,11 +26,11 @@ namespace boost { namespace property_tree // Construction & destruction // Construct error - file_parser_error(const std::string &message, - const std::string &filename, - unsigned long line) : - ptree_error(format_what(message, filename, line)), - m_message(message), m_filename(filename), m_line(line) + file_parser_error(const std::string &msg, + const std::string &file, + unsigned long l) : + ptree_error(format_what(msg, file, l)), + m_message(msg), m_filename(file), m_line(l) { } @@ -45,19 +45,19 @@ namespace boost { namespace property_tree // Get error message (without line and file - use what() to get // full message) - std::string message() + std::string message() const { return m_message; } // Get error filename - std::string filename() + std::string filename() const { return m_filename; } // Get error line number - unsigned long line() + unsigned long line() const { return m_line; } @@ -69,20 +69,15 @@ namespace boost { namespace property_tree unsigned long m_line; // Format error message to be returned by std::runtime_error::what() - std::string format_what(const std::string &message, - const std::string &filename, - unsigned long line) + static std::string format_what(const std::string &msg, + const std::string &file, + unsigned long l) { std::stringstream stream; - if (line > 0) - stream << (filename.empty() ? "" - : filename.c_str()) - << '(' << line << "): " - << message; - else - stream << (filename.empty() ? "" - : filename.c_str()) - << ": " << message; + stream << (file.empty() ? "" : file.c_str()); + if (l > 0) + stream << '(' << l << ')'; + stream << ": " << msg; return stream.str(); } diff --git a/include/boost/property_tree/detail/json_parser_read.hpp b/include/boost/property_tree/detail/json_parser_read.hpp index dc9ec02a34..25aabf4324 100644 --- a/include/boost/property_tree/detail/json_parser_read.hpp +++ b/include/boost/property_tree/detail/json_parser_read.hpp @@ -128,7 +128,6 @@ namespace boost { namespace property_tree { namespace json_parser { case Ch('\"'): c.string += Ch('\"'); break; case Ch('\\'): c.string += Ch('\\'); break; - case Ch('0'): c.string += Ch('\0'); break; case Ch('b'): c.string += Ch('\b'); break; case Ch('f'): c.string += Ch('\f'); break; case Ch('n'): c.string += Ch('\n'); break; @@ -232,8 +231,12 @@ namespace boost { namespace property_tree { namespace json_parser ; number - = strict_real_p - | int_p + = !ch_p("-") >> + (ch_p("0") | (range_p(Ch('1'), Ch('9')) >> *digit_p)) >> + !(ch_p(".") >> +digit_p) >> + !(chset_p(detail::widen("eE").c_str()) >> + !chset_p(detail::widen("-+").c_str()) >> + +digit_p) ; string @@ -246,7 +249,7 @@ namespace boost { namespace property_tree { namespace json_parser ; escape - = chset_p(detail::widen("\"\\0bfnrt").c_str())[typename Context::a_escape(self.c)] + = chset_p(detail::widen("\"\\bfnrt").c_str())[typename Context::a_escape(self.c)] | 'u' >> uint_parser()[typename Context::a_unicode(self.c)] ; diff --git a/include/boost/property_tree/detail/json_parser_write.hpp b/include/boost/property_tree/detail/json_parser_write.hpp index c5609eee1c..0b48ca1e28 100644 --- a/include/boost/property_tree/detail/json_parser_write.hpp +++ b/include/boost/property_tree/detail/json_parser_write.hpp @@ -21,37 +21,37 @@ namespace boost { namespace property_tree { namespace json_parser // Create necessary escape sequences from illegal characters template - std::basic_string create_escapes(const std::basic_string &s, - const std::locale &loc) + std::basic_string create_escapes(const std::basic_string &s) { std::basic_string result; typename std::basic_string::const_iterator b = s.begin(); typename std::basic_string::const_iterator e = s.end(); while (b != e) { - if (*b == Ch('\0')) result += Ch('\\'), result += Ch('0'); + // This assumes an ASCII superset. But so does everything in PTree. + // We escape everything outside ASCII, because this code can't + // handle high unicode characters. + if (*b == 0x20 || *b == 0x21 || + (*b >= 0x23 && *b <= 0x5B) || (*b >= 0x5D && *b <= 0xFF)) + result += *b; else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b'); else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f'); else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n'); else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r'); - else if (*b == Ch('"')) result += Ch('\\'), result += Ch('"'); + else if (*b == Ch('"')) result += Ch('\\'), result += Ch('"'); else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\'); else { - if (std::isprint(*b, loc)) - result += *b; - else - { - const char *hexdigits = "0123456789ABCDEF"; - unsigned long u = (std::min)(static_cast(*b), 0xFFFFul); - int d1 = u / 4096; u -= d1 * 4096; - int d2 = u / 256; u -= d2 * 256; - int d3 = u / 16; u -= d3 * 16; - int d4 = u; - result += Ch('\\'); result += Ch('u'); - result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]); - result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]); - } + const char *hexdigits = "0123456789ABCDEF"; + unsigned long u = (std::min)(static_cast(*b), + 0xFFFFul); + int d1 = u / 4096; u -= d1 * 4096; + int d2 = u / 256; u -= d2 * 256; + int d3 = u / 16; u -= d3 * 16; + int d4 = u; + result += Ch('\\'); result += Ch('u'); + result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]); + result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]); } ++b; } @@ -60,60 +60,61 @@ namespace boost { namespace property_tree { namespace json_parser template void write_json_helper(std::basic_ostream &stream, - const Ptree &pt, - int indent) + const Ptree &pt, + int indent, bool pretty) { typedef typename Ptree::key_type::value_type Ch; typedef typename std::basic_string Str; - + // Value or object or array if (indent > 0 && pt.empty()) { - // Write value - Str data = create_escapes(pt.template get_value(), stream.getloc()); + Str data = create_escapes(pt.template get_value()); stream << Ch('"') << data << Ch('"'); } else if (indent > 0 && pt.count(Str()) == pt.size()) { - // Write array - stream << Ch('[') << Ch('\n'); + stream << Ch('['); + if (pretty) stream << Ch('\n'); typename Ptree::const_iterator it = pt.begin(); for (; it != pt.end(); ++it) { - stream << Str(4 * (indent + 1), Ch(' ')); - write_json_helper(stream, it->second, indent + 1); + if (pretty) stream << Str(4 * (indent + 1), Ch(' ')); + write_json_helper(stream, it->second, indent + 1, pretty); if (boost::next(it) != pt.end()) stream << Ch(','); - stream << Ch('\n'); + if (pretty) stream << Ch('\n'); } stream << Str(4 * indent, Ch(' ')) << Ch(']'); } else { - // Write object - stream << Ch('{') << Ch('\n'); + stream << Ch('{'); + if (pretty) stream << Ch('\n'); typename Ptree::const_iterator it = pt.begin(); for (; it != pt.end(); ++it) { - stream << Str(4 * (indent + 1), Ch(' ')); - stream << Ch('"') << create_escapes(it->first, stream.getloc()) << Ch('"') << Ch(':'); - if (it->second.empty()) - stream << Ch(' '); - else - stream << Ch('\n') << Str(4 * (indent + 1), Ch(' ')); - write_json_helper(stream, it->second, indent + 1); + if (pretty) stream << Str(4 * (indent + 1), Ch(' ')); + stream << Ch('"') << create_escapes(it->first) << Ch('"') << Ch(':'); + if (pretty) { + if (it->second.empty()) + stream << Ch(' '); + else + stream << Ch('\n') << Str(4 * (indent + 1), Ch(' ')); + } + write_json_helper(stream, it->second, indent + 1, pretty); if (boost::next(it) != pt.end()) stream << Ch(','); - stream << Ch('\n'); + if (pretty) stream << Ch('\n'); } - stream << Str(4 * indent, Ch(' ')) << Ch('}'); - + if (pretty) stream << Str(4 * indent, Ch(' ')); + stream << Ch('}'); } } @@ -149,11 +150,12 @@ namespace boost { namespace property_tree { namespace json_parser template void write_json_internal(std::basic_ostream &stream, const Ptree &pt, - const std::string &filename) + const std::string &filename, + bool pretty) { if (!verify_json(pt, 0)) BOOST_PROPERTY_TREE_THROW(json_parser_error("ptree contains data that cannot be represented in JSON format", filename, 0)); - write_json_helper(stream, pt, 0); + write_json_helper(stream, pt, 0, pretty); stream << std::endl; if (!stream.good()) BOOST_PROPERTY_TREE_THROW(json_parser_error("write error", filename, 0)); diff --git a/include/boost/property_tree/detail/ptree_implementation.hpp b/include/boost/property_tree/detail/ptree_implementation.hpp index 6616d874cb..bfed43d3cf 100644 --- a/include/boost/property_tree/detail/ptree_implementation.hpp +++ b/include/boost/property_tree/detail/ptree_implementation.hpp @@ -183,8 +183,8 @@ namespace boost { namespace property_tree } template inline - basic_ptree::basic_ptree(const data_type &data) - : m_data(data), m_children(new typename subs::base_container) + basic_ptree::basic_ptree(const data_type &d) + : m_data(d), m_children(new typename subs::base_container) { } @@ -467,8 +467,8 @@ namespace boost { namespace property_tree std::pair r( subs::assoc(this).equal_range(key)); - return std::pair(r.first.base(), - r.second.base()); + return std::pair( + assoc_iterator(r.first), assoc_iterator(r.second)); } template inline @@ -481,7 +481,7 @@ namespace boost { namespace property_tree typename subs::by_name_index::const_iterator> r( subs::assoc(this).equal_range(key)); return std::pair( - r.first.base(), r.second.base()); + const_assoc_iterator(r.first), const_assoc_iterator(r.second)); } template inline @@ -770,7 +770,8 @@ namespace boost { namespace property_tree Translator tr) const { if (optional child = get_child_optional(path)) - return child.get().BOOST_NESTED_TEMPLATE get_value_optional(tr); + return child.get(). + BOOST_NESTED_TEMPLATE get_value_optional(tr); else return optional(); } diff --git a/include/boost/property_tree/detail/rapidxml.hpp b/include/boost/property_tree/detail/rapidxml.hpp index 1c5e2adae1..191bc709d6 100644 --- a/include/boost/property_tree/detail/rapidxml.hpp +++ b/include/boost/property_tree/detail/rapidxml.hpp @@ -7,17 +7,14 @@ // // For more information, see www.boost.org // ---------------------------------------------------------------------------- -#ifndef RAPIDXML_HPP_INCLUDED -#define RAPIDXML_HPP_INCLUDED +#ifndef BOOST_PROPERTY_TREE_RAPIDXML_HPP_INCLUDED +#define BOOST_PROPERTY_TREE_RAPIDXML_HPP_INCLUDED //! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation -// If standard library is disabled, user must provide implementations of required functions and typedefs -#if !defined(RAPIDXML_NO_STDLIB) - #include // For std::size_t - #include // For assert - #include // For placement new -#endif +#include // For std::size_t +#include // For assert +#include // For placement new // On MSVC, disable "conditional expression is constant" warning (level 4). // This warning is almost impossible to avoid with certain types of templated code @@ -27,40 +24,13 @@ #endif /////////////////////////////////////////////////////////////////////////// -// RAPIDXML_PARSE_ERROR - -#if defined(RAPIDXML_NO_EXCEPTIONS) - -#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } - -namespace rapidxml -{ - //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, - //! this function is called to notify user about the error. - //! It must be defined by the user. - //!

- //! This function cannot return. If it does, the results are undefined. - //!

- //! A very simple definition might look like that: - //!
-    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
-    //! {
-    //!     std::cout << "Parse error: " << what << "\n";
-    //!     std::abort();
-    //! }
-    //! 
- //! \param what Human readable description of the error. - //! \param where Pointer to character data where error was detected. - void parse_error_handler(const char *what, void *where); -} - -#else +// BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR #include // For std::exception -#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) +#define BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) -namespace rapidxml +namespace boost { namespace property_tree { namespace detail {namespace rapidxml { //! Parse error exception. @@ -80,9 +50,9 @@ namespace rapidxml public: //! Constructs parse error - parse_error(const char *what, void *where) - : m_what(what) - , m_where(where) + parse_error(const char *wa, void *we) + : m_what(wa) + , m_where(we) { } @@ -108,36 +78,34 @@ namespace rapidxml void *m_where; }; -} - -#endif +}}}} /////////////////////////////////////////////////////////////////////////// // Pool sizes -#ifndef RAPIDXML_STATIC_POOL_SIZE +#ifndef BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE // Size of static memory block of memory_pool. - // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // Define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. // No dynamic memory allocations are performed by memory_pool until static memory is exhausted. - #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) + #define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE (64 * 1024) #endif -#ifndef RAPIDXML_DYNAMIC_POOL_SIZE +#ifndef BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE // Size of dynamic memory block of memory_pool. - // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // Define BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. - #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) + #define BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) #endif -#ifndef RAPIDXML_ALIGNMENT +#ifndef BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT // Memory allocation alignment. - // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. + // Define BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. // All memory allocations for nodes, attributes and strings will be aligned to this value. // This must be a power of 2 and at least 1, otherwise memory_pool will not work. - #define RAPIDXML_ALIGNMENT sizeof(void *) + #define BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT sizeof(void *) #endif -namespace rapidxml +namespace boost { namespace property_tree { namespace detail {namespace rapidxml { // Forward declarations template class xml_node; @@ -364,20 +332,20 @@ namespace rapidxml //! It is also possible to create a standalone memory_pool, and use it //! to allocate nodes, whose lifetime will not be tied to any document. //!

- //! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. + //! Pool maintains BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. //! Until static memory is exhausted, no dynamic memory allocations are done. - //! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, + //! When static memory is exhausted, pool allocates additional blocks of memory of size BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE each, //! by using global new[] and delete[] operators. //! This behaviour can be changed by setting custom allocation routines. //! Use set_allocator() function to set them. //!

- //! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. + //! Allocations for nodes, attributes and strings are aligned at BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT bytes. //! This value defaults to the size of pointer on target architecture. //!

//! To obtain absolutely top performance from the parser, //! it is important that all nodes are allocated from a single, contiguous block of memory. //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. - //! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT + //! If required, you can tweak BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE, BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE and BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT //! to obtain best wasted memory to performance compromise. //! To do it, define their values before rapidxml.hpp file is included. //! \param Ch Character type of created nodes. @@ -578,7 +546,7 @@ namespace rapidxml char *align(char *ptr) { - std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1)); + std::size_t alignment = ((BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 1))) & (BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 1)); return ptr + alignment; } @@ -594,10 +562,6 @@ namespace rapidxml else { memory = new char[size]; -#ifdef RAPIDXML_NO_EXCEPTIONS - if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc - RAPIDXML_PARSE_ERROR("out of memory", 0); -#endif } return static_cast(memory); } @@ -610,13 +574,13 @@ namespace rapidxml // If not enough memory left in current pool, allocate a new pool if (result + size > m_end) { - // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) - std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + // Calculate required pool size (may be bigger than BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE) + std::size_t pool_size = BOOST_PROPERTY_TREE_RAPIDXML_DYNAMIC_POOL_SIZE; if (pool_size < size) pool_size = size; // Allocate - std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation + std::size_t alloc_size = sizeof(header) + (2 * BOOST_PROPERTY_TREE_RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation char *raw_memory = allocate_raw(alloc_size); // Setup new pool in allocated memory @@ -639,7 +603,7 @@ namespace rapidxml char *m_begin; // Start of raw memory making up current pool char *m_ptr; // First free byte in current pool char *m_end; // One past last available byte in current pool - char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory + char m_static_memory[BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used free_func *m_free_func; // Free function, or 0 if default is to be used }; @@ -722,20 +686,20 @@ namespace rapidxml //!

//! Size of name must be specified separately, because name does not have to be zero terminated. //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). - //! \param name Name of node to set. Does not have to be zero terminated. + //! \param n Name of node to set. Does not have to be zero terminated. //! \param size Size of name, in characters. This does not include zero terminator, if one is present. - void name(const Ch *name, std::size_t size) + void name(const Ch *n, std::size_t size) { - m_name = const_cast(name); + m_name = const_cast(n); m_name_size = size; } //! Sets name of node to a zero-terminated string. //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). - //! \param name Name of node to set. Must be zero terminated. - void name(const Ch *name) + //! \param n Name of node to set. Must be zero terminated. + void name(const Ch *n) { - this->name(name, internal::measure(name)); + name(n, internal::measure(n)); } //! Sets value of node to a non zero-terminated string. @@ -752,20 +716,20 @@ namespace rapidxml //!

//! If an element has a child node of type node_data, it will take precedence over element value when printing. //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. - //! \param value value of node to set. Does not have to be zero terminated. + //! \param val value of node to set. Does not have to be zero terminated. //! \param size Size of value, in characters. This does not include zero terminator, if one is present. - void value(const Ch *value, std::size_t size) + void value(const Ch *val, std::size_t size) { - m_value = const_cast(value); + m_value = const_cast(val); m_value_size = size; } //! Sets value of node to a zero-terminated string. //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). - //! \param value Vame of node to set. Must be zero terminated. - void value(const Ch *value) + //! \param val Vame of node to set. Must be zero terminated. + void value(const Ch *val) { - this->value(value, internal::measure(value)); + this->value(val, internal::measure(val)); } /////////////////////////////////////////////////////////////////////////// @@ -835,18 +799,18 @@ namespace rapidxml } //! Gets previous attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param n Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero + //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + xml_attribute *previous_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { - if (name) + if (n) { - if (name_size == 0) - name_size = internal::measure(name); + if (nsize == 0) + nsize = internal::measure(n); for (xml_attribute *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive)) return attribute; return 0; } @@ -855,18 +819,18 @@ namespace rapidxml } //! Gets next attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param n Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero + //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + xml_attribute *next_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { - if (name) + if (n) { - if (name_size == 0) - name_size = internal::measure(name); + if (nsize == 0) + nsize = internal::measure(n); for (xml_attribute *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive)) return attribute; return 0; } @@ -903,9 +867,9 @@ namespace rapidxml //! Constructs an empty node with the specified type. //! Consider using memory_pool of appropriate document to allocate nodes manually. - //! \param type Type of node to construct. - xml_node(node_type type) - : m_type(type) + //! \param t Type of node to construct. + xml_node(node_type t) + : m_type(t) , m_first_node(0) , m_first_attribute(0) { @@ -935,18 +899,18 @@ namespace rapidxml } //! Gets first child node, optionally matching node name. - //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param n Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero + //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found child, or 0 if not found. - xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + xml_node *first_node(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { - if (name) + if (n) { - if (name_size == 0) - name_size = internal::measure(name); + if (nsize == 0) + nsize = internal::measure(n); for (xml_node *child = m_first_node; child; child = child->next_sibling()) - if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + if (internal::compare(child->name(), child->name_size(), n, nsize, case_sensitive)) return child; return 0; } @@ -957,19 +921,19 @@ namespace rapidxml //! Gets last child node, optionally matching node name. //! Behaviour is undefined if node has no children. //! Use first_node() to test if node has children. - //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param n Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero + //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found child, or 0 if not found. - xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + xml_node *last_node(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { assert(m_first_node); // Cannot query for last child if node has no children - if (name) + if (n) { - if (name_size == 0) - name_size = internal::measure(name); + if (nsize == 0) + nsize = internal::measure(n); for (xml_node *child = m_last_node; child; child = child->previous_sibling()) - if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + if (internal::compare(child->name(), child->name_size(), n, nsize, case_sensitive)) return child; return 0; } @@ -980,19 +944,19 @@ namespace rapidxml //! Gets previous sibling node, optionally matching node name. //! Behaviour is undefined if node has no parent. //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param n Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero + //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found sibling, or 0 if not found. - xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + xml_node *previous_sibling(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) + if (n) { - if (name_size == 0) - name_size = internal::measure(name); + if (nsize == 0) + nsize = internal::measure(n); for (xml_node *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + if (internal::compare(sibling->name(), sibling->name_size(), n, nsize, case_sensitive)) return sibling; return 0; } @@ -1003,19 +967,19 @@ namespace rapidxml //! Gets next sibling node, optionally matching node name. //! Behaviour is undefined if node has no parent. //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param n Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero + //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found sibling, or 0 if not found. - xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + xml_node *next_sibling(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) + if (n) { - if (name_size == 0) - name_size = internal::measure(name); + if (nsize == 0) + nsize = internal::measure(n); for (xml_node *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + if (internal::compare(sibling->name(), sibling->name_size(), n, nsize, case_sensitive)) return sibling; return 0; } @@ -1024,18 +988,18 @@ namespace rapidxml } //! Gets first attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param n Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero + //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + xml_attribute *first_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { - if (name) + if (n) { - if (name_size == 0) - name_size = internal::measure(name); + if (nsize == 0) + nsize = internal::measure(n); for (xml_attribute *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive)) return attribute; return 0; } @@ -1044,18 +1008,18 @@ namespace rapidxml } //! Gets last attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param n Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if nsize is non-zero + //! \param nsize Size of name, in characters, or 0 to have size calculated automatically from string //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + xml_attribute *last_attribute(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { - if (name) + if (n) { - if (name_size == 0) - name_size = internal::measure(name); + if (nsize == 0) + nsize = internal::measure(n); for (xml_attribute *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + if (internal::compare(attribute->name(), attribute->name_size(), n, nsize, case_sensitive)) return attribute; return 0; } @@ -1067,10 +1031,10 @@ namespace rapidxml // Node modification //! Sets type of node. - //! \param type Type of node to set. - void type(node_type type) + //! \param t Type of node to set. + void type(node_type t) { - m_type = type; + m_type = t; } /////////////////////////////////////////////////////////////////////////// @@ -1411,7 +1375,7 @@ namespace rapidxml this->append_node(node); } else - RAPIDXML_PARSE_ERROR("expected <", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected <", text); } } @@ -1554,7 +1518,7 @@ namespace rapidxml } else // Invalid, only codes up to 0x10FFFF are allowed in Unicode { - RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); } } } @@ -1685,7 +1649,7 @@ namespace rapidxml if (*src == Ch(';')) ++src; else - RAPIDXML_PARSE_ERROR("expected ;", src); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected ;", src); continue; // Something else @@ -1735,7 +1699,7 @@ namespace rapidxml static_cast(text[1]) == 0xBB && static_cast(text[2]) == 0xBF) { - text += 3; // Skup utf-8 bom + text += 3; // Skip utf-8 bom } } @@ -1750,7 +1714,7 @@ namespace rapidxml while (text[0] != Ch('?') || text[1] != Ch('>')) { if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 2; // Skip '?>' @@ -1768,7 +1732,7 @@ namespace rapidxml // Skip ?> if (text[0] != Ch('?') || text[1] != Ch('>')) - RAPIDXML_PARSE_ERROR("expected ?>", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected ?>", text); text += 2; return declaration; @@ -1785,7 +1749,7 @@ namespace rapidxml while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 3; // Skip '-->' @@ -1793,19 +1757,19 @@ namespace rapidxml } // Remember value start - Ch *value = text; + Ch *val = text; // Skip until end of comment while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } // Create comment node xml_node *comment = this->allocate_node(node_comment); - comment->value(value, text - value); + comment->value(val, text - val); // Place zero terminator after comment value if (!(Flags & parse_no_string_terminators)) @@ -1820,7 +1784,7 @@ namespace rapidxml xml_node *parse_doctype(Ch *&text) { // Remember value start - Ch *value = text; + Ch *val = text; // Skip to > while (*text != Ch('>')) @@ -1841,7 +1805,8 @@ namespace rapidxml { case Ch('['): ++depth; break; case Ch(']'): --depth; break; - case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); + case 0: BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); + default: break; } ++text; } @@ -1850,7 +1815,7 @@ namespace rapidxml // Error on end of text case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); // Other character, skip it default: @@ -1864,7 +1829,7 @@ namespace rapidxml { // Create a new doctype node xml_node *doctype = this->allocate_node(node_doctype); - doctype->value(value, text - value); + doctype->value(val, text - val); // Place zero terminator after value if (!(Flags & parse_no_string_terminators)) @@ -1892,29 +1857,29 @@ namespace rapidxml xml_node *pi = this->allocate_node(node_pi); // Extract PI target name - Ch *name = text; + Ch *n = text; skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected PI target", text); - pi->name(name, text - name); + if (text == n) + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected PI target", text); + pi->name(n, text - n); // Skip whitespace between pi target and pi skip(text); // Remember start of pi - Ch *value = text; + Ch *val = text; // Skip to '?>' while (text[0] != Ch('?') || text[1] != Ch('>')) { if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } // Set pi value (verbatim, no entity expansion or whitespace normalization) - pi->value(value, text - value); - + pi->value(val, text - val); + // Place zero terminator after name and value if (!(Flags & parse_no_string_terminators)) { @@ -1931,7 +1896,7 @@ namespace rapidxml while (text[0] != Ch('?') || text[1] != Ch('>')) { if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 2; // Skip '?>' @@ -1950,7 +1915,7 @@ namespace rapidxml text = contents_start; // Skip until end of data - Ch *value = text, *end; + Ch *val = text, *end; if (Flags & parse_normalize_whitespace) end = skip_and_expand_character_refs(text); else @@ -1978,14 +1943,14 @@ namespace rapidxml if (!(Flags & parse_no_data_nodes)) { xml_node *data = this->allocate_node(node_data); - data->value(value, end - value); + data->value(val, end - val); node->append_node(data); } // Add data to parent node if no data exists yet if (!(Flags & parse_no_element_values)) if (*node->value() == Ch('\0')) - node->value(value, end - value); + node->value(val, end - val); // Place zero terminator after value if (!(Flags & parse_no_string_terminators)) @@ -2010,7 +1975,7 @@ namespace rapidxml while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } text += 3; // Skip ]]> @@ -2018,17 +1983,17 @@ namespace rapidxml } // Skip until end of cdata - Ch *value = text; + Ch *val = text; while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } // Create new cdata node xml_node *cdata = this->allocate_node(node_cdata); - cdata->value(value, text - value); + cdata->value(val, text - val); // Place zero terminator after value if (!(Flags & parse_no_string_terminators)) @@ -2046,11 +2011,11 @@ namespace rapidxml xml_node *element = this->allocate_node(node_element); // Extract element name - Ch *name = text; + Ch *n = text; skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected element name", text); - element->name(name, text - name); + if (text == n) + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected element name", text); + element->name(n, text - n); // Skip whitespace between element name and attributes or > skip(text); @@ -2068,11 +2033,11 @@ namespace rapidxml { ++text; if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected >", text); ++text; } else - RAPIDXML_PARSE_ERROR("expected >", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected >", text); // Place zero terminator after name if (!(Flags & parse_no_string_terminators)) @@ -2151,6 +2116,9 @@ namespace rapidxml text += 9; // skip '!DOCTYPE ' return parse_doctype(text); } + break; + + default: break; } // switch @@ -2159,7 +2127,7 @@ namespace rapidxml while (*text != Ch('>')) { if (*text == 0) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); ++text; } ++text; // Skip '>' @@ -2177,7 +2145,8 @@ namespace rapidxml { // Skip whitespace between > and node contents Ch *contents_start = text; // Store start of node contents before whitespace is skipped - skip(text); + if (Flags & parse_trim_whitespace) + skip(text); Ch next_char = *text; // After data nodes, instead of continuing the loop, control jumps here. @@ -2202,7 +2171,7 @@ namespace rapidxml Ch *closing_name = text; skip(text); if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true)) - RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("invalid closing tag name", text); } else { @@ -2212,7 +2181,7 @@ namespace rapidxml // Skip remaining whitespace after node name skip(text); if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected >", text); ++text; // Skip '>' return; // Node closed, finished parsing contents } @@ -2227,7 +2196,7 @@ namespace rapidxml // End of data - error case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("unexpected end of data", text); // Data node default: @@ -2246,15 +2215,15 @@ namespace rapidxml while (attribute_name_pred::test(*text)) { // Extract attribute name - Ch *name = text; + Ch *n = text; ++text; // Skip first character of attribute name skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected attribute name", name); + if (text == n) + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected attribute name", n); // Create new attribute xml_attribute *attribute = this->allocate_attribute(); - attribute->name(name, text - name); + attribute->name(n, text - n); node->append_attribute(attribute); // Skip whitespace after attribute name @@ -2262,7 +2231,7 @@ namespace rapidxml // Skip = if (*text != Ch('=')) - RAPIDXML_PARSE_ERROR("expected =", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected =", text); ++text; // Add terminating zero after name @@ -2275,11 +2244,11 @@ namespace rapidxml // Skip quote and remember if it was ' or " Ch quote = *text; if (quote != Ch('\'') && quote != Ch('"')) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected ' or \"", text); ++text; // Extract attribute value and expand char refs in it - Ch *value = text, *end; + Ch *val = text, *end; const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes if (quote == Ch('\'')) end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); @@ -2287,11 +2256,11 @@ namespace rapidxml end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); // Set attribute value - attribute->value(value, end - value); + attribute->value(val, end - val); // Make sure that end quote is present if (*text != quote) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); + BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR("expected ' or \"", text); ++text; // Skip quote // Add terminating zero after value @@ -2589,10 +2558,10 @@ namespace rapidxml } //! \endcond -} +}}}} // Undefine internal macros -#undef RAPIDXML_PARSE_ERROR +#undef BOOST_PROPERTY_TREE_RAPIDXML_PARSE_ERROR // On MSVC, restore warnings state #ifdef _MSC_VER diff --git a/include/boost/property_tree/detail/xml_parser_error.hpp b/include/boost/property_tree/detail/xml_parser_error.hpp index 3410a0426b..c79835c43f 100644 --- a/include/boost/property_tree/detail/xml_parser_error.hpp +++ b/include/boost/property_tree/detail/xml_parser_error.hpp @@ -20,10 +20,10 @@ namespace boost { namespace property_tree { namespace xml_parser class xml_parser_error: public file_parser_error { public: - xml_parser_error(const std::string &message, - const std::string &filename, - unsigned long line): - file_parser_error(message, filename, line) + xml_parser_error(const std::string &msg, + const std::string &file, + unsigned long l): + file_parser_error(msg, file, l) { } }; 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 d271d5e36e..acec34d9dd 100644 --- a/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp +++ b/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp @@ -21,49 +21,58 @@ namespace boost { namespace property_tree { namespace xml_parser { template - void read_xml_node(rapidxml::xml_node *node, Ptree &pt, int flags) + void read_xml_node(detail::rapidxml::xml_node *node, + Ptree &pt, int flags) { + using namespace detail::rapidxml; switch (node->type()) { // Element nodes - case rapidxml::node_element: + case node_element: { // Create node - Ptree &pt_node = pt.push_back(std::make_pair(node->name(), Ptree()))->second; - + Ptree &pt_node = pt.push_back(std::make_pair(node->name(), + Ptree()))->second; + // Copy attributes if (node->first_attribute()) { - Ptree &pt_attr_root = pt_node.push_back(std::make_pair(xmlattr(), Ptree()))->second; - for (rapidxml::xml_attribute *attr = node->first_attribute(); attr; attr = attr->next_attribute()) + Ptree &pt_attr_root = pt_node.push_back( + std::make_pair(xmlattr(), Ptree()))->second; + for (xml_attribute *attr = node->first_attribute(); + attr; attr = attr->next_attribute()) { - Ptree &pt_attr = pt_attr_root.push_back(std::make_pair(attr->name(), Ptree()))->second; + Ptree &pt_attr = pt_attr_root.push_back( + std::make_pair(attr->name(), Ptree()))->second; pt_attr.data() = attr->value(); } } // Copy children - for (rapidxml::xml_node *child = node->first_node(); child; child = child->next_sibling()) + for (xml_node *child = node->first_node(); + child; child = child->next_sibling()) read_xml_node(child, pt_node, flags); } break; // Data nodes - case rapidxml::node_data: - case rapidxml::node_cdata: + case node_data: + case node_cdata: { if (flags & no_concat_text) - pt.push_back(std::make_pair(xmltext(), Ptree(node->value()))); + pt.push_back(std::make_pair(xmltext(), + Ptree(node->value()))); else pt.data() += node->value(); } break; // Comment nodes - case rapidxml::node_comment: + case node_comment: { if (!(flags & no_comments)) - pt.push_back(std::make_pair(xmlcomment(), Ptree(node->value()))); + pt.push_back(std::make_pair(xmlcomment(), + Ptree(node->value()))); } break; @@ -81,6 +90,7 @@ namespace boost { namespace property_tree { namespace xml_parser const std::string &filename) { typedef typename Ptree::key_type::value_type Ch; + using namespace detail::rapidxml; // Load data into vector stream.unsetf(std::ios::skipws); @@ -93,10 +103,13 @@ namespace boost { namespace property_tree { namespace xml_parser try { // Parse using appropriate flags - using namespace rapidxml; const int f_tws = parse_normalize_whitespace | parse_trim_whitespace; const int f_c = parse_comment_nodes; + // Some compilers don't like the bitwise or in the template arg. + const int f_tws_c = parse_normalize_whitespace + | parse_trim_whitespace + | parse_comment_nodes; xml_document doc; if (flags & no_comments) { if (flags & trim_whitespace) @@ -105,19 +118,20 @@ namespace boost { namespace property_tree { namespace xml_parser doc.BOOST_NESTED_TEMPLATE parse<0>(&v.front()); } else { if (flags & trim_whitespace) - doc.BOOST_NESTED_TEMPLATE parse(&v.front()); + doc.BOOST_NESTED_TEMPLATE parse(&v.front()); else doc.BOOST_NESTED_TEMPLATE parse(&v.front()); } // Create ptree from nodes Ptree local; - for (rapidxml::xml_node *child = doc.first_node(); child; child = child->next_sibling()) + for (xml_node *child = doc.first_node(); + child; child = child->next_sibling()) read_xml_node(child, local, flags); // Swap local and result ptrees pt.swap(local); - } catch (rapidxml::parse_error &e) { + } catch (parse_error &e) { long line = static_cast( std::count(&v.front(), e.where(), Ch('\n')) + 1); BOOST_PROPERTY_TREE_THROW( diff --git a/include/boost/property_tree/detail/xml_parser_utils.hpp b/include/boost/property_tree/detail/xml_parser_utils.hpp index 995bea63f2..7c8a6e13a7 100644 --- a/include/boost/property_tree/detail/xml_parser_utils.hpp +++ b/include/boost/property_tree/detail/xml_parser_utils.hpp @@ -44,6 +44,9 @@ namespace boost { namespace property_tree { namespace xml_parser template std::basic_string encode_char_entities(const std::basic_string &s) { + // Don't do anything for empty strings. + if(s.empty()) return s; + typedef typename std::basic_string Str; Str r; // To properly round-trip spaces and not uglify the XML beyond diff --git a/include/boost/property_tree/detail/xml_parser_write.hpp b/include/boost/property_tree/detail/xml_parser_write.hpp index 77423a0045..614854e5b6 100644 --- a/include/boost/property_tree/detail/xml_parser_write.hpp +++ b/include/boost/property_tree/detail/xml_parser_write.hpp @@ -31,14 +31,18 @@ namespace boost { namespace property_tree { namespace xml_parser void write_xml_comment(std::basic_ostream &stream, const std::basic_string &s, int indent, + bool separate_line, const xml_writer_settings & settings ) { typedef typename std::basic_string Str; - write_xml_indent(stream,indent,settings); + if (separate_line) + write_xml_indent(stream,indent,settings); stream << Ch('<') << Ch('!') << Ch('-') << Ch('-'); stream << s; - stream << Ch('-') << Ch('-') << Ch('>') << std::endl; + stream << Ch('-') << Ch('-') << Ch('>'); + if (separate_line) + stream << Ch('\n'); } template @@ -52,7 +56,7 @@ namespace boost { namespace property_tree { namespace xml_parser if (separate_line) write_xml_indent(stream,indent,settings); stream << encode_char_entities(s); - if (separate_line) + if (separate_line) stream << Ch('\n'); } @@ -92,7 +96,9 @@ namespace boost { namespace property_tree { namespace xml_parser { write_xml_indent(stream,indent,settings); stream << Ch('<') << key << - Ch('/') << Ch('>') << std::endl; + Ch('/') << Ch('>'); + if (want_pretty) + stream << Ch('\n'); } } else // Nonempty key @@ -144,7 +150,7 @@ namespace boost { namespace property_tree { namespace xml_parser else if (it->first == xmlcomment()) write_xml_comment(stream, it->second.template get_value >(), - indent + 1, settings); + indent + 1, want_pretty, settings); else if (it->first == xmltext()) write_xml_text(stream, it->second.template get_value >(), diff --git a/include/boost/property_tree/detail/xml_parser_writer_settings.hpp b/include/boost/property_tree/detail/xml_parser_writer_settings.hpp index 678c213a8a..0cc707a538 100644 --- a/include/boost/property_tree/detail/xml_parser_writer_settings.hpp +++ b/include/boost/property_tree/detail/xml_parser_writer_settings.hpp @@ -35,12 +35,12 @@ namespace boost { namespace property_tree { namespace xml_parser class xml_writer_settings { public: - xml_writer_settings(Ch indent_char = Ch(' '), - typename std::basic_string::size_type indent_count = 0, - const std::basic_string &encoding = widen("utf-8")) - : indent_char(indent_char) - , indent_count(indent_count) - , encoding(encoding) + xml_writer_settings(Ch inchar = Ch(' '), + typename std::basic_string::size_type incount = 0, + const std::basic_string &enc = widen("utf-8")) + : indent_char(inchar) + , indent_count(incount) + , encoding(enc) { } diff --git a/include/boost/property_tree/json_parser.hpp b/include/boost/property_tree/json_parser.hpp index 3199d2d11a..d3bc32edb1 100644 --- a/include/boost/property_tree/json_parser.hpp +++ b/include/boost/property_tree/json_parser.hpp @@ -85,14 +85,17 @@ namespace boost { namespace property_tree { namespace json_parser * @param stream The stream to which to write the JSON representation of the * property tree. * @param pt The property tree to tranlsate to JSON and output. + * @param pretty Whether to pretty-print. Defaults to true for backward + * compatibility. */ template void write_json(std::basic_ostream< typename Ptree::key_type::value_type > &stream, - const Ptree &pt) + const Ptree &pt, + bool pretty = true) { - write_json_internal(stream, pt, std::string()); + write_json_internal(stream, pt, std::string(), pretty); } /** @@ -106,11 +109,14 @@ namespace boost { namespace property_tree { namespace json_parser * representation of the property tree. * @param pt The property tree to translate to JSON and output. * @param loc The locale to use when writing out to the output file. + * @param pretty Whether to pretty-print. Defaults to true and last place + * for backward compatibility. */ template void write_json(const std::string &filename, const Ptree &pt, - const std::locale &loc = std::locale()) + const std::locale &loc = std::locale(), + bool pretty = true) { std::basic_ofstream stream(filename.c_str()); @@ -118,7 +124,7 @@ namespace boost { namespace property_tree { namespace json_parser BOOST_PROPERTY_TREE_THROW(json_parser_error( "cannot open file", filename, 0)); stream.imbue(loc); - write_json_internal(stream, pt, filename); + write_json_internal(stream, pt, filename, pretty); } } } } diff --git a/include/boost/property_tree/ptree_fwd.hpp b/include/boost/property_tree/ptree_fwd.hpp index d8e2f148bb..fe36741067 100644 --- a/include/boost/property_tree/ptree_fwd.hpp +++ b/include/boost/property_tree/ptree_fwd.hpp @@ -13,6 +13,7 @@ #include #include +#include #include // for std::less #include // for std::allocator #include @@ -87,9 +88,6 @@ namespace boost { namespace property_tree /** Implements a path using a std::string as the key. */ typedef string_path > path; - /** Implements a path using a std::wstring as the key. */ - typedef string_path > wpath; - /** * A property tree with std::string for key and data, and default * comparison. @@ -104,7 +102,10 @@ namespace boost { namespace property_tree detail::less_nocase > iptree; -#ifndef BOOST_NO_CWCHAR +#ifndef BOOST_NO_STD_WSTRING + /** Implements a path using a std::wstring as the key. */ + typedef string_path > wpath; + /** * A property tree with std::wstring for key and data, and default * comparison. @@ -136,7 +137,7 @@ namespace boost { namespace property_tree #if !defined(BOOST_PROPERTY_TREE_DOXYGEN_INVOKED) // Throwing macro to avoid no return warnings portably -# define BOOST_PROPERTY_TREE_THROW(e) { throw_exception(e); std::exit(1); } +# define BOOST_PROPERTY_TREE_THROW(e) BOOST_THROW_EXCEPTION(e) #endif #endif diff --git a/include/boost/property_tree/string_path.hpp b/include/boost/property_tree/string_path.hpp index 73762c782c..1d9299455a 100644 --- a/include/boost/property_tree/string_path.hpp +++ b/include/boost/property_tree/string_path.hpp @@ -57,10 +57,12 @@ namespace boost { namespace property_tree { return s; } +#ifndef BOOST_NO_STD_WSTRING inline std::string dump_sequence(const std::wstring &s) { return narrow(s.c_str()); } +#endif } /// Default path class. A path is a sequence of values. Groups of values From d0d71452fc8117b85f2d2082ab10ea57dd25b792 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Fri, 15 Oct 2010 12:41:49 +0000 Subject: [PATCH 08/23] Merge long-overdue PTree changes to release (libs) [SVN r65976] --- doc/property_tree.qbk | 5 +-- doc/tutorial.qbk | 2 +- examples/custom_data_type.cpp | 64 +++++++++++++++++-------------- examples/debug_settings.cpp | 12 +++--- test/test_json_parser.cpp | 4 +- test/test_property_tree.cpp | 6 +++ test/test_property_tree.hpp | 15 ++++++++ test/test_xml_parser_common.hpp | 17 +++++--- test/test_xml_parser_rapidxml.cpp | 3 +- test/xml_parser_test_data.hpp | 4 ++ 10 files changed, 85 insertions(+), 47 deletions(-) diff --git a/doc/property_tree.qbk b/doc/property_tree.qbk index 0fadf51c01..61e33b6d6b 100644 --- a/doc/property_tree.qbk +++ b/doc/property_tree.qbk @@ -53,6 +53,7 @@ [def __ptree_get_value_optional__ [memberref boost::property_tree::basic_ptree::get_value_optional get_value_optional]] [def __ptree_get_child__ [memberref boost::property_tree::basic_ptree::get_child get_child]] [def __ptree_put__ [memberref boost::property_tree::basic_ptree::put put]] +[def __ptree_put__ [memberref boost::property_tree::basic_ptree::add add]] [def __ptree_put_value__ [memberref boost::property_tree::basic_ptree::put_value put_value]] [/ free-functions] @@ -104,10 +105,6 @@ these three basic patterns of usage: itself.] Used when you want to vary control flow depending on get success/failure. Or to check for presence of a key. -# [*Why does the separator character come before the path and not after - as one would expect?] -It helps with overload resolution in some cases. - [heading Future Development] * More parsers: YAML, environment strings. * More robust XML parser. diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index a35b8ca756..4d374c3684 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -106,7 +106,7 @@ Now the save() function. It is also 7 lines of code: // be achieved using a combination of the insert and put_own // functions. BOOST_FOREACH(const std::string &name, m_modules) - pt.__ptree_put__("debug.modules.module", name, true); + pt.__ptree_add__("debug.modules.module", name); // Write the property tree to the XML file. __write_xml__(filename, pt); diff --git a/examples/custom_data_type.cpp b/examples/custom_data_type.cpp index 86097e9aa4..dbc905fe00 100644 --- a/examples/custom_data_type.cpp +++ b/examples/custom_data_type.cpp @@ -14,35 +14,28 @@ // container (instead of std::string that standard ptree has). #include -#include -#include -#include -#include #include #include #include #include // Custom translator that works with boost::any instead of std::string -struct my_translator +template +struct variant_translator { + typedef Ext external_type; + typedef Int internal_type; - // Custom extractor - converts data from boost::any to T - template - bool get_value(const Ptree &pt, T &value) const + external_type + get_value(const internal_type &value) const { - value = boost::any_cast(pt.data()); - return true; // Success + return boost::any_cast(value); } - - // Custom inserter - converts data from T to boost::any - template - bool put_value(Ptree &pt, const T &value) const + internal_type + put_value(const external_type &value) const { - pt.data() = value; - return true; + return value; } - }; int main() @@ -51,30 +44,45 @@ int main() using namespace boost::property_tree; // Property_tree with boost::any as data type - // Key comparison: std::less // Key type: std::string - // Path type: path // Data type: boost::any - // Translator type: my_translator - typedef basic_ptree, std::string, path, boost::any, my_translator> my_ptree; + // Key comparison: default (std::less) + typedef basic_ptree my_ptree; my_ptree pt; // Put/get int value - pt.put("int value", 3); - int int_value = pt.get("int value"); + typedef variant_translator int_tran; + pt.put("int value", 3, int_tran()); + int int_value = pt.get("int value", int_tran()); std::cout << "Int value: " << int_value << "\n"; // Put/get string value - pt.put("string value", "foo bar"); - std::string string_value = pt.get("string value"); + typedef variant_translator string_tran; + pt.put("string value", "foo bar", string_tran()); + std::string string_value = pt.get( + "string value" + , string_tran() + ); std::cout << "String value: " << string_value << "\n"; // Put/get list value + typedef std::list intlist; + typedef variant_translator intlist_tran; int list_data[] = { 1, 2, 3, 4, 5 }; - pt.put >("list value", std::list(list_data, list_data + sizeof(list_data) / sizeof(*list_data))); - std::list list_value = pt.get >("list value"); + pt.put( + "list value" + , intlist( + list_data + , list_data + sizeof(list_data) / sizeof(*list_data) + ) + , intlist_tran() + ); + intlist list_value = pt.get( + "list value" + , intlist_tran() + ); std::cout << "List value: "; - for (std::list::iterator it = list_value.begin(); it != list_value.end(); ++it) + for (intlist::iterator it = list_value.begin(); it != list_value.end(); ++it) std::cout << *it << ' '; std::cout << '\n'; } diff --git a/examples/debug_settings.cpp b/examples/debug_settings.cpp index f7bcef74d8..78d704ac1e 100644 --- a/examples/debug_settings.cpp +++ b/examples/debug_settings.cpp @@ -10,7 +10,7 @@ #include #include -//#include +#include #include #include #include @@ -77,15 +77,15 @@ void debug_settings::save(const std::string &filename) // Put debug level in property tree pt.put("debug.level", m_level); - // Iterate over modules in set and put them in property - // tree. Note that put function places new key at the + // Iterate over modules in set and put them in property + // tree. Note that the add function places new key at the // end of list of keys. This is fine in most of the // situations. If you want to place item at some other // place (i.e. at front or somewhere in the middle), - // this can be achieved using combination of insert + // this can be achieved using a combination of the insert // and put_value functions - //BOOST_FOREACH(const std::string &name, m_modules) - // pt.put("debug.modules.module", name, true); + BOOST_FOREACH(const std::string &name, m_modules) + pt.add("debug.modules.module", name); // Write property tree to XML file write_xml(filename, pt); diff --git a/test/test_json_parser.cpp b/test/test_json_parser.cpp index 4d37a93a99..d4d8f47f12 100644 --- a/test/test_json_parser.cpp +++ b/test/test_json_parser.cpp @@ -235,7 +235,7 @@ const char *ok_data_11 = "}\n"; const char *ok_data_12 = - "{\" \\\" \\\\ \\0 \\b \\f \\n \\r \\t \" : \"multi\" \"-\" \"string\"}"; + "{\" \\\" \\\\ \\b \\f \\n \\r \\t \" : \"multi\" \"-\" \"string\"}"; const char *error_data_1 = ""; // No root object @@ -342,7 +342,7 @@ void test_json_parser() generic_parser_test_ok ( ReadFunc(), WriteFunc(), ok_data_12, NULL, - "testok12.json", NULL, "testok12out.json", 2, 12, 19 + "testok12.json", NULL, "testok12out.json", 2, 12, 17 ); generic_parser_test_error diff --git a/test/test_property_tree.cpp b/test/test_property_tree.cpp index 9634091a9e..aed4827570 100644 --- a/test/test_property_tree.cpp +++ b/test/test_property_tree.cpp @@ -9,8 +9,10 @@ // ---------------------------------------------------------------------------- #include "test_utils.hpp" #include +#include #include #include +#include // If using VC, disable some warnings that trip in boost::serialization bowels #ifdef BOOST_MSVC @@ -152,6 +154,7 @@ int test_main(int, char *[]) test_front_back(pt); test_get_put(pt); test_get_child_put_child(pt); + test_equal_range(pt); test_path_separator(pt); test_path(pt); test_precision(pt); @@ -184,6 +187,7 @@ int test_main(int, char *[]) test_front_back(pt); test_get_put(pt); test_get_child_put_child(pt); + test_equal_range(pt); test_path_separator(pt); test_path(pt); test_precision(pt); @@ -216,6 +220,7 @@ int test_main(int, char *[]) test_front_back(pt); test_get_put(pt); test_get_child_put_child(pt); + test_equal_range(pt); test_path_separator(pt); test_path(pt); test_precision(pt); @@ -248,6 +253,7 @@ int test_main(int, char *[]) test_front_back(pt); test_get_put(pt); test_get_child_put_child(pt); + test_equal_range(pt); test_path_separator(pt); test_path(pt); test_precision(pt); diff --git a/test/test_property_tree.hpp b/test/test_property_tree.hpp index 8b8d33dc27..4e670b18ff 100644 --- a/test/test_property_tree.hpp +++ b/test/test_property_tree.hpp @@ -914,6 +914,21 @@ void test_get_child_put_child(PTREE *) } +void test_equal_range(PTREE *) +{ + PTREE pt; + pt.add_child(T("k1"), PTREE()); + pt.add_child(T("k2"), PTREE()); + pt.add_child(T("k1"), PTREE()); + pt.add_child(T("k3"), PTREE()); + pt.add_child(T("k1"), PTREE()); + pt.add_child(T("k2"), PTREE()); + + BOOST_CHECK(boost::distance(pt.equal_range(T("k1"))) == 3); + BOOST_CHECK(boost::distance(pt.equal_range(T("k2"))) == 2); + BOOST_CHECK(boost::distance(pt.equal_range(T("k3"))) == 1); +} + void test_path_separator(PTREE *) { diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp index 4c51111a8e..6e6a124175 100644 --- a/test/test_xml_parser_common.hpp +++ b/test/test_xml_parser_common.hpp @@ -19,7 +19,8 @@ struct ReadFuncWS template void operator()(const std::string &filename, Ptree &pt) const { - boost::property_tree::read_xml(filename, pt); + boost::property_tree::read_xml(filename, pt, + boost::property_tree::xml_parser::no_concat_text); } }; @@ -72,7 +73,7 @@ void test_xml_parser() generic_parser_test_ok ( ReadFuncWS(), WriteFuncWS(), ok_data_2, NULL, - "testok2a.xml", NULL, "testok2aout.xml", 6, 18, 8 + "testok2a.xml", NULL, "testok2aout.xml", 15, 23, 89 ); generic_parser_test_ok @@ -84,7 +85,7 @@ void test_xml_parser() generic_parser_test_ok ( ReadFuncWS(), WriteFuncWS(), ok_data_3, NULL, - "testok3a.xml", NULL, "testok3aout.xml", 787, 32523, 3831 + "testok3a.xml", NULL, "testok3aout.xml", 1662, 35377, 11706 ); generic_parser_test_ok @@ -96,14 +97,14 @@ void test_xml_parser() generic_parser_test_ok ( ReadFuncWS(), WriteFuncWS(), ok_data_4, NULL, - "testok4.xml", NULL, "testok4out.xml", 5, 2, 20 + "testok4.xml", NULL, "testok4out.xml", 11, 7, 74 ); generic_parser_test_ok ( ReadFuncWS(), WriteFuncWS(), ok_data_5, NULL, "testok5.xml", NULL, "testok5out.xml", - 2, umlautsize(), 3 + 3, umlautsize(), 12 ); generic_parser_test_error @@ -118,6 +119,12 @@ void test_xml_parser() "testerr2.xml", NULL, "testerr2out.xml", 2 ); + generic_parser_test_ok + ( + ReadFuncWS(), WriteFuncWS(), bug_data_pr2855, NULL, + "testpr2855.xml", NULL, "testpr2855out.xml", 3, 7, 14 + ); + } #endif diff --git a/test/test_xml_parser_rapidxml.cpp b/test/test_xml_parser_rapidxml.cpp index 7aacfad0b8..5a0e3d4091 100644 --- a/test/test_xml_parser_rapidxml.cpp +++ b/test/test_xml_parser_rapidxml.cpp @@ -1,5 +1,6 @@ // ---------------------------------------------------------------------------- // Copyright (C) 2002-2006 Marcin Kalicinski +// Copyright (C) 2009-2010 Sebastian Redl // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -19,10 +20,10 @@ int test_main(int argc, char *argv[]) { using namespace boost::property_tree; - using std::locale; test_xml_parser(); test_xml_parser(); #ifndef BOOST_NO_CWCHAR + using std::locale; // We need a UTF-8-aware global locale now. locale loc(locale(), new utf8_codecvt_facet); locale::global(loc); diff --git a/test/xml_parser_test_data.hpp b/test/xml_parser_test_data.hpp index a1f1637a94..c4708162f9 100644 --- a/test/xml_parser_test_data.hpp +++ b/test/xml_parser_test_data.hpp @@ -760,4 +760,8 @@ const char *error_data_2 = "\n" ""; // XML tag not closed +const char *bug_data_pr2855 = + "\n" + " notrim"; + #endif From 61c44fdf234b1e9db13164e6c9d26d3c30d8d4f0 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Fri, 15 Oct 2010 13:56:17 +0000 Subject: [PATCH 09/23] Merge more PTree fixes to release (boost) [SVN r65978] --- .../property_tree/detail/json_parser_read.hpp | 30 +++++++++++-------- .../detail/json_parser_write.hpp | 10 +++++-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/boost/property_tree/detail/json_parser_read.hpp b/include/boost/property_tree/detail/json_parser_read.hpp index 25aabf4324..3f067949c4 100644 --- a/include/boost/property_tree/detail/json_parser_read.hpp +++ b/include/boost/property_tree/detail/json_parser_read.hpp @@ -128,6 +128,7 @@ namespace boost { namespace property_tree { namespace json_parser { case Ch('\"'): c.string += Ch('\"'); break; case Ch('\\'): c.string += Ch('\\'); break; + case Ch('/'): c.string += Ch('/'); break; case Ch('b'): c.string += Ch('\b'); break; case Ch('f'): c.string += Ch('\f'); break; case Ch('n'): c.string += Ch('\n'); break; @@ -238,21 +239,24 @@ namespace boost { namespace property_tree { namespace json_parser !chset_p(detail::widen("-+").c_str()) >> +digit_p) ; - - string + + string = +(lexeme_d[confix_p('\"', *character, '\"')]) ; - - character - = (anychar_p - "\\" - "\"")[typename Context::a_char(self.c)] - | ch_p("\\") >> expect_escape(escape) - ; - - escape - = chset_p(detail::widen("\"\\bfnrt").c_str())[typename Context::a_escape(self.c)] - | 'u' >> uint_parser()[typename Context::a_unicode(self.c)] - ; - + + character + = (anychar_p - "\\" - "\"") + [typename Context::a_char(self.c)] + | ch_p("\\") >> expect_escape(escape) + ; + + escape + = chset_p(detail::widen("\"\\/bfnrt").c_str()) + [typename Context::a_escape(self.c)] + | 'u' >> uint_parser() + [typename Context::a_unicode(self.c)] + ; + // Debug BOOST_SPIRIT_DEBUG_RULE(root); BOOST_SPIRIT_DEBUG_RULE(object); diff --git a/include/boost/property_tree/detail/json_parser_write.hpp b/include/boost/property_tree/detail/json_parser_write.hpp index 0b48ca1e28..7639887f65 100644 --- a/include/boost/property_tree/detail/json_parser_write.hpp +++ b/include/boost/property_tree/detail/json_parser_write.hpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -31,19 +32,22 @@ namespace boost { namespace property_tree { namespace json_parser // This assumes an ASCII superset. But so does everything in PTree. // We escape everything outside ASCII, because this code can't // handle high unicode characters. - if (*b == 0x20 || *b == 0x21 || - (*b >= 0x23 && *b <= 0x5B) || (*b >= 0x5D && *b <= 0xFF)) + if (*b == 0x20 || *b == 0x21 || (*b >= 0x23 && *b <= 0x2E) || + (*b >= 0x30 && *b <= 0x5B) || (*b >= 0x5D && *b <= 0xFF)) result += *b; else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b'); else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f'); else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n'); else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r'); + else if (*b == Ch('/')) result += Ch('\\'), result += Ch('/'); else if (*b == Ch('"')) result += Ch('\\'), result += Ch('"'); else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\'); else { const char *hexdigits = "0123456789ABCDEF"; - unsigned long u = (std::min)(static_cast(*b), + typedef typename make_unsigned::type UCh; + unsigned long u = (std::min)(static_cast( + static_cast(*b)), 0xFFFFul); int d1 = u / 4096; u -= d1 * 4096; int d2 = u / 256; u -= d2 * 256; From 5cbf7eac2607936d6bc5a28f1c7cbe06984b657a Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Wed, 10 Nov 2010 08:22:59 +0000 Subject: [PATCH 10/23] Make PTree's parser_writer_settings fields non-const, so that the struct is assignable. [SVN r66478] --- .../property_tree/detail/xml_parser_writer_settings.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/property_tree/detail/xml_parser_writer_settings.hpp b/include/boost/property_tree/detail/xml_parser_writer_settings.hpp index 0cc707a538..f22d85e8a4 100644 --- a/include/boost/property_tree/detail/xml_parser_writer_settings.hpp +++ b/include/boost/property_tree/detail/xml_parser_writer_settings.hpp @@ -44,9 +44,9 @@ namespace boost { namespace property_tree { namespace xml_parser { } - const Ch indent_char; - const typename std::basic_string::size_type indent_count; - const std::basic_string encoding; + Ch indent_char; + typename std::basic_string::size_type indent_count; + std::basic_string encoding; }; template From 043ec14851c6b542aa2060b06f673f172e92f2c7 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Wed, 10 Nov 2010 09:23:27 +0000 Subject: [PATCH 11/23] Merge simple fix for non-ascii XML parsing to release. Fixes bug 4340. [SVN r66479] --- .../boost/property_tree/detail/rapidxml.hpp | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/include/boost/property_tree/detail/rapidxml.hpp b/include/boost/property_tree/detail/rapidxml.hpp index 191bc709d6..712bf3fb75 100644 --- a/include/boost/property_tree/detail/rapidxml.hpp +++ b/include/boost/property_tree/detail/rapidxml.hpp @@ -309,6 +309,17 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml } return true; } + + template + inline size_t get_index(const Ch c) + { + // If not ASCII char, its sematic is same as plain 'z' + if (c > 255) + { + return 'z'; + } + return c; + } } //! \endcond @@ -1399,7 +1410,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml { static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_whitespace[internal::get_index(ch)]; } }; @@ -1408,7 +1419,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml { static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_node_name[internal::get_index(ch)]; } }; @@ -1417,7 +1428,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml { static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_attribute_name[internal::get_index(ch)]; } }; @@ -1426,7 +1437,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml { static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_text[internal::get_index(ch)]; } }; @@ -1435,7 +1446,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml { static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_text_pure_no_ws[internal::get_index(ch)]; } }; @@ -1444,7 +1455,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml { static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_text_pure_with_ws[internal::get_index(ch)]; } }; @@ -1455,9 +1466,9 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml static unsigned char test(Ch ch) { if (Quote == Ch('\'')) - return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_attribute_data_1[internal::get_index(ch)]; if (Quote == Ch('\"')) - return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_attribute_data_2[internal::get_index(ch)]; return 0; // Should never be executed, to avoid warnings on Comeau } }; @@ -1469,9 +1480,9 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml static unsigned char test(Ch ch) { if (Quote == Ch('\'')) - return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_attribute_data_1_pure[internal::get_index(ch)]; if (Quote == Ch('\"')) - return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; + return internal::lookup_tables<0>::lookup_attribute_data_2_pure[internal::get_index(ch)]; return 0; // Should never be executed, to avoid warnings on Comeau } }; From 1f205126f10a500739ff980492fd12ee8bee2e98 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Thu, 11 Nov 2010 20:34:42 +0000 Subject: [PATCH 12/23] Merged revisions 66498 via svnmerge from https://svn.boost.org/svn/boost/trunk ........ r66498 | eric_niebler | 2010-11-11 15:28:11 -0500 (Thu, 11 Nov 2010) | 1 line add missing includes, fixes #4841 ........ [SVN r66499] --- include/boost/property_tree/detail/ptree_implementation.hpp | 1 + include/boost/property_tree/string_path.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/include/boost/property_tree/detail/ptree_implementation.hpp b/include/boost/property_tree/detail/ptree_implementation.hpp index bfed43d3cf..422000242c 100644 --- a/include/boost/property_tree/detail/ptree_implementation.hpp +++ b/include/boost/property_tree/detail/ptree_implementation.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #if defined(BOOST_MSVC) && \ (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000) diff --git a/include/boost/property_tree/string_path.hpp b/include/boost/property_tree/string_path.hpp index 1d9299455a..07ec6b00ce 100644 --- a/include/boost/property_tree/string_path.hpp +++ b/include/boost/property_tree/string_path.hpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace boost { namespace property_tree { From 6386e5fea2706d888de3de863c79e655c28e798f Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Tue, 8 Mar 2011 14:58:52 +0000 Subject: [PATCH 13/23] Merge r68990 to release just before 2.46.1, because it's a critical and low-risk fix. Sorry about not waiting for permission, but I won't have access to this computer again until after the release. So if this merge is a problem, just revert it. [SVN r69684] --- include/boost/property_tree/detail/json_parser_read.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/boost/property_tree/detail/json_parser_read.hpp b/include/boost/property_tree/detail/json_parser_read.hpp index 3f067949c4..46acc5abdb 100644 --- a/include/boost/property_tree/detail/json_parser_read.hpp +++ b/include/boost/property_tree/detail/json_parser_read.hpp @@ -179,6 +179,9 @@ namespace boost { namespace property_tree { namespace json_parser { using namespace boost::spirit::classic; + // There's a boost::assertion too, so another explicit using + // here: + using boost::spirit::classic::assertion; // Assertions assertion expect_object("expected object"); From 3e9c566a1b7a17f62abd5dd1dd26cad3342e9c4b Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Mon, 16 May 2011 18:33:39 +0000 Subject: [PATCH 14/23] Merge r68990-68993, several fixes to PTree. Fixes bug 1678. Fixes bug 4387. [SVN r71991] --- .../property_tree/detail/json_parser_read.hpp | 4 +- .../detail/ptree_implementation.hpp | 4 +- .../boost/property_tree/detail/rapidxml.hpp | 64 +++++++++++-------- include/boost/property_tree/string_path.hpp | 10 +-- 4 files changed, 47 insertions(+), 35 deletions(-) diff --git a/include/boost/property_tree/detail/json_parser_read.hpp b/include/boost/property_tree/detail/json_parser_read.hpp index 46acc5abdb..3849450975 100644 --- a/include/boost/property_tree/detail/json_parser_read.hpp +++ b/include/boost/property_tree/detail/json_parser_read.hpp @@ -184,7 +184,7 @@ namespace boost { namespace property_tree { namespace json_parser using boost::spirit::classic::assertion; // Assertions - assertion expect_object("expected object"); + assertion expect_root("expected object or array"); assertion expect_eoi("expected end of input"); assertion expect_objclose("expected ',' or '}'"); assertion expect_arrclose("expected ',' or ']'"); @@ -195,7 +195,7 @@ namespace boost { namespace property_tree { namespace json_parser // JSON grammar rules root - = expect_object(object) + = expect_root(object | array) >> expect_eoi(end_p) ; diff --git a/include/boost/property_tree/detail/ptree_implementation.hpp b/include/boost/property_tree/detail/ptree_implementation.hpp index 422000242c..226a096855 100644 --- a/include/boost/property_tree/detail/ptree_implementation.hpp +++ b/include/boost/property_tree/detail/ptree_implementation.hpp @@ -13,8 +13,8 @@ #include #include +#include #include -#include #if defined(BOOST_MSVC) && \ (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000) @@ -874,7 +874,7 @@ namespace boost { namespace property_tree template basic_ptree & basic_ptree::force_path(path_type &p) { - assert(!p.empty() && "Empty path not allowed for put_child."); + BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child."); if(p.single()) { // I'm the parent we're looking for. return *this; diff --git a/include/boost/property_tree/detail/rapidxml.hpp b/include/boost/property_tree/detail/rapidxml.hpp index 712bf3fb75..003fe7774f 100644 --- a/include/boost/property_tree/detail/rapidxml.hpp +++ b/include/boost/property_tree/detail/rapidxml.hpp @@ -12,8 +12,8 @@ //! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation +#include #include // For std::size_t -#include // For assert #include // For placement new // On MSVC, disable "conditional expression is constant" warning (level 4). @@ -460,7 +460,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \return Pointer to allocated char array. This pointer will never be NULL. Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) { - assert(source || size); // Either source or size (or both) must be specified + BOOST_ASSERT(source || size); // Either source or size (or both) must be specified if (size == 0) size = internal::measure(source) + 1; Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); @@ -536,7 +536,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \param ff Free function, or 0 to restore default function void set_allocator(alloc_func *af, free_func *ff) { - assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet + BOOST_ASSERT(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet m_alloc_func = af; m_free_func = ff; } @@ -568,7 +568,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] { memory = m_alloc_func(size); - assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp + BOOST_ASSERT(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp } else { @@ -938,7 +938,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \return Pointer to found child, or 0 if not found. xml_node *last_node(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { - assert(m_first_node); // Cannot query for last child if node has no children + BOOST_ASSERT(m_first_node); // Cannot query for last child if node has no children if (n) { if (nsize == 0) @@ -961,7 +961,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \return Pointer to found sibling, or 0 if not found. xml_node *previous_sibling(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { - assert(this->m_parent); // Cannot query for siblings if node has no parent + BOOST_ASSERT(this->m_parent); // Cannot query for siblings if node has no parent if (n) { if (nsize == 0) @@ -984,7 +984,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \return Pointer to found sibling, or 0 if not found. xml_node *next_sibling(const Ch *n = 0, std::size_t nsize = 0, bool case_sensitive = true) const { - assert(this->m_parent); // Cannot query for siblings if node has no parent + BOOST_ASSERT(this->m_parent); // Cannot query for siblings if node has no parent if (n) { if (nsize == 0) @@ -1056,7 +1056,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \param child Node to prepend. void prepend_node(xml_node *child) { - assert(child && !child->parent() && child->type() != node_document); + BOOST_ASSERT(child && !child->parent() && child->type() != node_document); if (first_node()) { child->m_next_sibling = m_first_node; @@ -1077,7 +1077,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \param child Node to append. void append_node(xml_node *child) { - assert(child && !child->parent() && child->type() != node_document); + BOOST_ASSERT(child && !child->parent() && child->type() != node_document); if (first_node()) { child->m_prev_sibling = m_last_node; @@ -1099,8 +1099,8 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \param child Node to insert. void insert_node(xml_node *where, xml_node *child) { - assert(!where || where->parent() == this); - assert(child && !child->parent() && child->type() != node_document); + BOOST_ASSERT(!where || where->parent() == this); + BOOST_ASSERT(child && !child->parent() && child->type() != node_document); if (where == m_first_node) prepend_node(child); else if (where == 0) @@ -1120,7 +1120,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! Use first_node() to test if node has children. void remove_first_node() { - assert(first_node()); + BOOST_ASSERT(first_node()); xml_node *child = m_first_node; m_first_node = child->m_next_sibling; if (child->m_next_sibling) @@ -1135,7 +1135,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! Use first_node() to test if node has children. void remove_last_node() { - assert(first_node()); + BOOST_ASSERT(first_node()); xml_node *child = m_last_node; if (child->m_prev_sibling) { @@ -1151,8 +1151,8 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml // \param where Pointer to child to be removed. void remove_node(xml_node *where) { - assert(where && where->parent() == this); - assert(first_node()); + BOOST_ASSERT(where && where->parent() == this); + BOOST_ASSERT(first_node()); if (where == m_first_node) remove_first_node(); else if (where == m_last_node) @@ -1177,7 +1177,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \param attribute Attribute to prepend. void prepend_attribute(xml_attribute *attribute) { - assert(attribute && !attribute->parent()); + BOOST_ASSERT(attribute && !attribute->parent()); if (first_attribute()) { attribute->m_next_attribute = m_first_attribute; @@ -1197,7 +1197,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \param attribute Attribute to append. void append_attribute(xml_attribute *attribute) { - assert(attribute && !attribute->parent()); + BOOST_ASSERT(attribute && !attribute->parent()); if (first_attribute()) { attribute->m_prev_attribute = m_last_attribute; @@ -1219,8 +1219,8 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \param attribute Attribute to insert. void insert_attribute(xml_attribute *where, xml_attribute *attribute) { - assert(!where || where->parent() == this); - assert(attribute && !attribute->parent()); + BOOST_ASSERT(!where || where->parent() == this); + BOOST_ASSERT(attribute && !attribute->parent()); if (where == m_first_attribute) prepend_attribute(attribute); else if (where == 0) @@ -1240,7 +1240,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! Use first_attribute() to test if node has attributes. void remove_first_attribute() { - assert(first_attribute()); + BOOST_ASSERT(first_attribute()); xml_attribute *attribute = m_first_attribute; if (attribute->m_next_attribute) { @@ -1257,7 +1257,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! Use first_attribute() to test if node has attributes. void remove_last_attribute() { - assert(first_attribute()); + BOOST_ASSERT(first_attribute()); xml_attribute *attribute = m_last_attribute; if (attribute->m_prev_attribute) { @@ -1273,7 +1273,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //! \param where Pointer to attribute to be removed. void remove_attribute(xml_attribute *where) { - assert(first_attribute() && where->parent() == this); + BOOST_ASSERT(first_attribute() && where->parent() == this); if (where == m_first_attribute) remove_first_attribute(); else if (where == m_last_attribute) @@ -1361,7 +1361,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml template void parse(Ch *text) { - assert(text); + BOOST_ASSERT(text); // Remove current contents this->remove_all_nodes(); @@ -1701,16 +1701,26 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml /////////////////////////////////////////////////////////////////////// // Internal parsing functions - // Parse BOM, if any + // Parse UTF-8 BOM, if any template - void parse_bom(Ch *&text) + void parse_bom(char *&text) { - // UTF-8? if (static_cast(text[0]) == 0xEF && static_cast(text[1]) == 0xBB && static_cast(text[2]) == 0xBF) { - text += 3; // Skip utf-8 bom + text += 3; + } + } + + // Parse UTF-16/32 BOM, if any + template + void parse_bom(wchar_t *&text) + { + const wchar_t bom = 0xFEFF; + if (text[0] == bom) + { + ++text; } } diff --git a/include/boost/property_tree/string_path.hpp b/include/boost/property_tree/string_path.hpp index 07ec6b00ce..53d90de63a 100644 --- a/include/boost/property_tree/string_path.hpp +++ b/include/boost/property_tree/string_path.hpp @@ -17,13 +17,13 @@ #include #include +#include #include #include #include #include #include #include -#include namespace boost { namespace property_tree { @@ -132,8 +132,10 @@ namespace boost { namespace property_tree // If it's single, there's no separator. This allows to do // p /= "piece"; // even for non-default separators. - assert((m_separator == o.m_separator || o.empty() || o.single()) - && "Incompatible paths."); + BOOST_ASSERT((m_separator == o.m_separator + || o.empty() + || o.single()) + && "Incompatible paths."); if(!o.empty()) { String sub; if(!this->empty()) { @@ -200,7 +202,7 @@ namespace boost { namespace property_tree template typename Translator::external_type string_path::reduce() { - assert(!empty() && "Reducing empty path"); + BOOST_ASSERT(!empty() && "Reducing empty path"); s_iter next_sep = std::find(m_start, m_value.end(), m_separator); String part(m_start, next_sep); From b183df107e66c788c2dd09834ba065d86088f0e5 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Mon, 16 May 2011 18:34:41 +0000 Subject: [PATCH 15/23] Merge r68990-68993, several fixes to PTree. Fixes bug 1678. Fixes bug 4387. Forgot to commit these together with the header part. [SVN r71992] --- test/test_json_parser.cpp | 9 +++++++++ test/test_xml_parser_common.hpp | 6 ++++++ test/xml_parser_test_data.hpp | 6 +++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/test/test_json_parser.cpp b/test/test_json_parser.cpp index d4d8f47f12..3addb9482e 100644 --- a/test/test_json_parser.cpp +++ b/test/test_json_parser.cpp @@ -249,6 +249,9 @@ const char *error_data_3 = const char *error_data_4 = "{\n\"a\"\n}"; // No object +const char *bug_data_pr4387 = + "[1, 2, 3]"; // Root array + struct ReadFunc { template @@ -369,6 +372,12 @@ void test_json_parser() "testerr4.json", NULL, "testerr4out.json", 3 ); + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), bug_data_pr4387, NULL, + "testpr4387.json", NULL, "testpr4387out.json", 4, 3, 0 + ); + } int test_main(int argc, char *argv[]) diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp index 6e6a124175..9e0c7b051f 100644 --- a/test/test_xml_parser_common.hpp +++ b/test/test_xml_parser_common.hpp @@ -124,6 +124,12 @@ void test_xml_parser() ReadFuncWS(), WriteFuncWS(), bug_data_pr2855, NULL, "testpr2855.xml", NULL, "testpr2855out.xml", 3, 7, 14 ); + + generic_parser_test_ok + ( + ReadFuncWS(), WriteFuncWS(), bug_data_pr1678, NULL, + "testpr1678.xml", NULL, "testpr1678out.xml", 2, 0, 4 + ); } diff --git a/test/xml_parser_test_data.hpp b/test/xml_parser_test_data.hpp index c4708162f9..994e8b0591 100644 --- a/test/xml_parser_test_data.hpp +++ b/test/xml_parser_test_data.hpp @@ -761,7 +761,11 @@ const char *error_data_2 = ""; // XML tag not closed const char *bug_data_pr2855 = - "\n" + "\n" " notrim"; +// byte order mark +const char *bug_data_pr1678 = + "\xEF\xBB\xBF"; + #endif From afb776760240f619ca8138c250f0f78979c4ff14 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Mon, 16 May 2011 18:39:10 +0000 Subject: [PATCH 16/23] Merge UTF-8 XML support improvements (r69622) to release. Fixes bug 5203. [SVN r71993] --- include/boost/property_tree/detail/rapidxml.hpp | 6 ++++-- test/test_xml_parser_common.hpp | 10 +++++++++- test/xml_parser_test_data.hpp | 5 +++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/boost/property_tree/detail/rapidxml.hpp b/include/boost/property_tree/detail/rapidxml.hpp index 003fe7774f..92122505c8 100644 --- a/include/boost/property_tree/detail/rapidxml.hpp +++ b/include/boost/property_tree/detail/rapidxml.hpp @@ -313,8 +313,10 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml template inline size_t get_index(const Ch c) { - // If not ASCII char, its sematic is same as plain 'z' - if (c > 255) + // If not ASCII char, its semantic is same as plain 'z'. + // char could be signed, so first stretch and make unsigned. + unsigned n = c; + if (n > 127) { return 'z'; } diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp index 9e0c7b051f..0f99fbdeb1 100644 --- a/test/test_xml_parser_common.hpp +++ b/test/test_xml_parser_common.hpp @@ -63,6 +63,7 @@ void test_xml_parser() { using namespace boost::property_tree; + typedef typename Ptree::data_type::value_type char_type; generic_parser_test_ok ( @@ -104,7 +105,7 @@ void test_xml_parser() ( ReadFuncWS(), WriteFuncWS(), ok_data_5, NULL, "testok5.xml", NULL, "testok5out.xml", - 3, umlautsize(), 12 + 3, umlautsize(), 12 ); generic_parser_test_error @@ -131,6 +132,13 @@ void test_xml_parser() "testpr1678.xml", NULL, "testpr1678out.xml", 2, 0, 4 ); + generic_parser_test_ok + ( + ReadFuncWS(), WriteFuncWS(), bug_data_pr5203, NULL, + "testpr5203.xml", NULL, "testpr5203out.xml", + 3, 4 * umlautsize(), 13 + ); + } #endif diff --git a/test/xml_parser_test_data.hpp b/test/xml_parser_test_data.hpp index 994e8b0591..3d8dafa521 100644 --- a/test/xml_parser_test_data.hpp +++ b/test/xml_parser_test_data.hpp @@ -768,4 +768,9 @@ const char *bug_data_pr2855 = const char *bug_data_pr1678 = "\xEF\xBB\xBF"; +// russian +const char *bug_data_pr5203 = + "\n" + "\xD0\xAE\xD0\xBD\xD0\xB8\xD1\x82"; + #endif From 56cfb6b2f913d84060a6dc98f71c9a166bc58c86 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Mon, 16 May 2011 18:50:06 +0000 Subject: [PATCH 17/23] Merge r70664-70666 to release. Improves INI parser and brings improvement to docs. Docs should now at least no longer contain completely incorrect examples. [SVN r71994] --- doc/accessing.qbk | 38 +++++++++++++++------- doc/container.qbk | 21 ++++++++---- doc/json_parser.qbk | 4 +-- doc/parsers.qbk | 8 ++--- doc/property_tree.qbk | 4 +-- doc/synopsis.qbk | 2 +- doc/xml_parser.qbk | 4 +-- examples/debug_settings.cpp | 4 +-- include/boost/property_tree/ini_parser.hpp | 3 +- include/boost/property_tree/ptree.hpp | 5 +-- test/test_ini_parser.cpp | 12 +++++++ 11 files changed, 71 insertions(+), 34 deletions(-) diff --git a/doc/accessing.qbk b/doc/accessing.qbk index 6e605b89cb..20f0bc4a52 100644 --- a/doc/accessing.qbk +++ b/doc/accessing.qbk @@ -17,7 +17,7 @@ Property tree resembles (almost is) a standard container with value type of `pai To find the value of `pi` we might do the following: __ptree__::__ptree_const_iterator__ it = pt.__ptree_find__("pi"); - double pi = boost::lexical_cast(it->second._ptree_data__()); + double pi = boost::lexical_cast(it->second.__ptree_data__()); This looks quite cumbersome, and would be even more so if `pi` value was not stored so near the top of the tree, and we cared just a little bit more about errors. Fortunately, there is another, correct way of doing it: @@ -53,26 +53,42 @@ boost::optional v = pt.__ptree_get_optional__("a.path.to.float.val `` This version uses boost::optional class to handle extraction failure. On successful extraction, it will return boost::optional initialized with extracted value. Otherwise, it will return uninitialized boost::optional. -To retrieve value from this tree (not some subkey), use __ptree_get_value__, __ptree_get_value__ (default-value version), and __ptree_get_value_optional__. They have identical semantics to __ptree_get__ functions, except they don't take the __path__ parameter. Don't call __ptree_get__ with and empty __path__ to do this as it will try to extract contents of subkey with empty name. +To retrieve a value from this tree (not some subkey), use __ptree_get_value__, __ptree_get_value__ (default-value version), and __ptree_get_value_optional__. They have identical semantics to __ptree_get__ functions, except they don't take the __path__ parameter. Don't call __ptree_get__ with and empty __path__ to do this as it will try to extract contents of subkey with empty name. -To use separator character other than default '[^.]', each of the __ptree_get__ versions has another form, which takes an additional parameter in front of path. This parameter of type `char/wchar_t` specifies the separating character. This is a lifesaving device for those who may have dots in their keys: +To use a separator character other than default '[^.]', you need to construct +a path object explicitly. The path type for a __ptree__ is a string_path +instantiation, so the easiest way to refer to it is __ptree__::path_type. +This way you can use trees that have dots in their keys: - pt.get('/', "p.a.t.h/t.o/v.a.l.u.e"); - pt.get('/', "p.a.t.h/t.o/v.a.l.u.e", 0, NULL); - pt.get_optional('/', "p.a.t.h/t.o/v.a.l.u.e"); + typedef ptree::path_type path; + pt.get(path("p.a.t.h/t.o/v.a.l.u.e", '/')); + pt.get(path("p.a.t.h/t.o/v.a.l.u.e", '/'), 0, NULL); + pt.get_optional(path("p.a.t.h/t.o/v.a.l.u.e", '/')); -[heading One Way of Putting Data] +Note: the special overloads of __ptree_get__ and __ptree_get_optional__ taking +a separator character that existed in pre-release versions of PropertyTree have +been removed. This is because the overloads conflicted with using per-call data +translators. -To complement __ptree_get__, there is a __ptree_put__ function. Contrary to __ptree_get__, it has only one variant. The reason is, there is no need to handle put failures so often (normally, __ptree_put__ will only fail if conversion of the supplied value to __ptree_data_type__ fails or the system runs out of memory. In the former case, __ptree_put__ will throw __ptree_bad_data__). Sample usage of __ptree_put__ might appear as: +[heading Two Ways of Putting Data] + +To complement __ptree_get__, there are __ptree_put__ and __ptree_add__. Contrary to __ptree_get__, they have only one variant each. This is because there is no need to deal with missing values when adding data. If the supplied value cannot be converted to the tree's data type, the functions will throw __ptree_bad_data__. __ptree__ pt; pt.__ptree_put__("a.path.to.float.value", 3.14f); + // Overwrites the value + pt.__ptree_put__("a.path.to.float.value", 2.72f); + // Adds a second node with the new value. + pt.__ptree_add__("a.path.to.float.value", 3.14f); Calling __ptree_put__ will insert a new value at specified path, so that a call to __ptree_get__ specifying the same path will retrieve it. Further, __ptree_put__ will insert any missing path elements during path traversal. For example, calling `__ptree_put__("key1.key2.key3", 3.14f)` on an empty tree will insert three new children: `key1`, `key1.key2` and `key1.key2.key3`. The last one will receive a string `"3.14"` as data, while the two former ones will have empty data strings. __ptree_put__ always inserts new keys at the back of the existing sequences. +The difference between __ptree_put__ and __ptree_add__ is that put will overwrite existing values if there are any, while add will create a new node to hold the value even if the specified path references an existing node. -Similar to __ptree_get_value__, there is also a __ptree_put_value__ function. It does the same for this property tree what __ptree_put__ does for its children. Thus, it does not require __path__: +Similar to __ptree_get_value__, there is also a __ptree_put_value__ function. It does the same for this property tree what __ptree_put__ does for its children. Thus, it does not receive a __path__: __ptree__ pt; - pt.__ptree_put_own__(3.14f); + pt.__ptree_put_value__(3.14f); + +There is no add_value function. -[endsect] \ No newline at end of file +[endsect] diff --git a/doc/container.qbk b/doc/container.qbk index 5f0742f0e7..ea545d1ca7 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -15,12 +15,19 @@ way to iterate over the entire tree. It is very important to remember that the property sequence is *not* ordered by the key. It preserves the order of insertion. It closely resembles a std::list. -Fast access to children by name is provided via a separate lookup structure. Do not -attempt to use algorithms that expect an ordered sequence (like binary_search) -on a node's children. +Fast access to children by name is provided via a separate lookup structure. Do +not attempt to use algorithms that expect an ordered sequence (like +binary_search) on a node's children. -There may be multiple children with the same key value in a node. However, these -children are not necessarily sequential. The iterator returned by __ptree_find__ -may refer to any of these, and there are no guarantees about the relative -position of the other equally named children. +The property tree exposes a second container-like interface, called the +associative view. Its iterator type is the nested type assoc_iterator (and its +const counterpart const_assoc_iterator). You can get an ordered view of all +children by using ordered_begin() and ordered_end(). + +The associative view also provides find() and equal_range() members, which +return assoc_iterators, but otherwise have the same semantics as the members +of std::map of the same name. + +You can get a normal iterator from an assoc_iterator by using the to_iterator() +member function. Converting the other way is not possible. [endsect] [/container] diff --git a/doc/json_parser.qbk b/doc/json_parser.qbk index 469d5a24cb..d27355c7bd 100644 --- a/doc/json_parser.qbk +++ b/doc/json_parser.qbk @@ -10,8 +10,8 @@ The __json__ is a data interchange format derived from the object literal notation of JavaScript. (JSON stands for JavaScript Object Notation.) JSON is a simple, compact format for loosely structured node trees of any depth, -very similar to the property tree dataset. It is less stuctured than XML and has -no schema support, but has the advantage of being simpler, smaller and typed +very similar to the property tree dataset. It is less structured than XML and +has no schema support, but has the advantage of being simpler, smaller and typed without the need for a complex schema. The property tree dataset is not typed, and does not support arrays as such. diff --git a/doc/parsers.qbk b/doc/parsers.qbk index e793b5fc0f..d4086114b8 100644 --- a/doc/parsers.qbk +++ b/doc/parsers.qbk @@ -14,11 +14,11 @@ [include info_parser.qbk] -# These parsers will be dropped for now. -#[include cmd_line_parser.qbk] +[/ These parsers will be dropped for now.] +[/ include cmd_line_parser.qbk] -#[include windows_registry_parser.qbk] +[/ include windows_registry_parser.qbk] -#[include system_environment_parser.qbk] +[/ include system_environment_parser.qbk] [endsect] [/parsers] diff --git a/doc/property_tree.qbk b/doc/property_tree.qbk index 61e33b6d6b..fef18f749e 100644 --- a/doc/property_tree.qbk +++ b/doc/property_tree.qbk @@ -29,7 +29,7 @@ [def __ptree_data_type__ [classref boost::property_tree::basic_ptree::data_type data_type]] [def __ptree_iterator__ [classref boost::property_tree::basic_ptree::iterator iterator]] [def __ptree_const_iterator__ [classref boost::property_tree::basic_ptree::const_iterator const_iterator]] -[def __path__ [classref boost::property_tree::path path]] +[def __path__ [classref boost::property_tree::string_path path]] [def __ptree_error__ [classref boost::property_tree::ptree_error ptree_error]] [def __ptree_bad_data__ [classref boost::property_tree::ptree_bad_data ptree_bad_data]] [def __ptree_bad_path__ [classref boost::property_tree::ptree_bad_path ptree_bad_path]] @@ -53,7 +53,7 @@ [def __ptree_get_value_optional__ [memberref boost::property_tree::basic_ptree::get_value_optional get_value_optional]] [def __ptree_get_child__ [memberref boost::property_tree::basic_ptree::get_child get_child]] [def __ptree_put__ [memberref boost::property_tree::basic_ptree::put put]] -[def __ptree_put__ [memberref boost::property_tree::basic_ptree::add add]] +[def __ptree_add__ [memberref boost::property_tree::basic_ptree::add add]] [def __ptree_put_value__ [memberref boost::property_tree::basic_ptree::put_value put_value]] [/ free-functions] diff --git a/doc/synopsis.qbk b/doc/synopsis.qbk index 9355081543..9a462d6512 100644 --- a/doc/synopsis.qbk +++ b/doc/synopsis.qbk @@ -28,7 +28,7 @@ container (the closest being std::list), plus a bunch of extra member functions. These functions allow easy and effective access to the data stored in property tree. They are various variants of __ptree_get__, __ptree_put__, __ptree_get_value__, __ptree_put_value__, __ptree_get_child__, -__ptree_put_child__. Additionally, there is __ptree_data__ function to access +__ptree_put_child__. Additionally, there is a __ptree_data__ function to access node data directly. See the [classref boost::property_tree::basic_ptree basic_ptree class template synopsis] for more information. diff --git a/doc/xml_parser.qbk b/doc/xml_parser.qbk index 13dfd5cd88..8a9a9b1d02 100644 --- a/doc/xml_parser.qbk +++ b/doc/xml_parser.qbk @@ -41,8 +41,8 @@ XML / property tree conversion schema (__read_xml__ and __write_xml__): * XML comments are stored in nodes named [^], unless comment ignoring is enabled via the flags. * Text content is stored in one of two ways, depending on the flags. The default - way concatenates all text nodes and stores them in a single node called - [^]. This way, the entire content can be conveniently read, but the + way concatenates all text nodes and stores them as the data of the element + node. This way, the entire content can be conveniently read, but the relative ordering of text and child elements is lost. The other way stores each text content as a separate node, all called [^]. diff --git a/examples/debug_settings.cpp b/examples/debug_settings.cpp index 78d704ac1e..6391556088 100644 --- a/examples/debug_settings.cpp +++ b/examples/debug_settings.cpp @@ -59,8 +59,8 @@ void debug_settings::load(const std::string &filename) // child, it throws. Property tree iterator can be used in // the same way as standard container iterator. Category // is bidirectional_iterator. - //BOOST_FOREACH(ptree::value_type &v, pt.get_child("debug.modules")) - // m_modules.insert(v.second.data()); + BOOST_FOREACH(ptree::value_type &v, pt.get_child("debug.modules")) + m_modules.insert(v.second.data()); } diff --git a/include/boost/property_tree/ini_parser.hpp b/include/boost/property_tree/ini_parser.hpp index 0d9cd60a51..d2a457f831 100644 --- a/include/boost/property_tree/ini_parser.hpp +++ b/include/boost/property_tree/ini_parser.hpp @@ -69,6 +69,7 @@ namespace boost { namespace property_tree { namespace ini_parser typedef typename Ptree::key_type::value_type Ch; typedef std::basic_string Str; const Ch semicolon = stream.widen(';'); + const Ch hash = stream.widen('#'); const Ch lbracket = stream.widen('['); const Ch rbracket = stream.widen(']'); @@ -93,7 +94,7 @@ namespace boost { namespace property_tree { namespace ini_parser if (!line.empty()) { // Comment, section or key? - if (line[0] == semicolon) + if (line[0] == semicolon || line[0] == hash) { // Ignore comments } diff --git a/include/boost/property_tree/ptree.hpp b/include/boost/property_tree/ptree.hpp index 243a9b6a5b..d18ffeb2a7 100644 --- a/include/boost/property_tree/ptree.hpp +++ b/include/boost/property_tree/ptree.hpp @@ -181,9 +181,9 @@ namespace boost { namespace property_tree // Associative view - /** Returns an iterator to the first child, in order. */ + /** Returns an iterator to the first child, in key order. */ assoc_iterator ordered_begin(); - /** Returns an iterator to the first child, in order. */ + /** Returns an iterator to the first child, in key order. */ const_assoc_iterator ordered_begin() const; /** Returns the not-found iterator. Equivalent to end() in a real @@ -432,6 +432,7 @@ namespace boost { namespace property_tree * return node->get_value_optional(); * return boost::null; * @endcode + * That is, return the value if it exists and can be converted, or nil. */ template optional get_optional(const path_type &path) const; diff --git a/test/test_ini_parser.cpp b/test/test_ini_parser.cpp index aa250ad9c3..6507bd353e 100644 --- a/test/test_ini_parser.cpp +++ b/test/test_ini_parser.cpp @@ -47,6 +47,12 @@ const char *ok_data_5 = "Key1=Data1\n" // No section "Key2=Data2\n"; +// Treat # as comment. +const char *ok_data_6 = + "# Comment\n" + "[Section1]\n" + "Key1=Data1\n"; + // Erroneous data const char *error_data_1 = "[Section1]\n" @@ -132,6 +138,12 @@ void test_ini_parser() "testok5.ini", NULL, "testok5out.ini", 3, 10, 8 ); + generic_parser_test_ok + ( + ReadFunc(), WriteFunc(), ok_data_6, NULL, + "testok6.ini", NULL, "testok6out.ini", 3, 5, 12 + ); + generic_parser_test_error ( ReadFunc(), WriteFunc(), error_data_1, NULL, From 9b707a030d4ee16afb1ec696c88f284a67c8ca7f Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Fri, 13 Jan 2012 12:20:39 +0000 Subject: [PATCH 18/23] Merge [72000],[72001],[72003], [74691], [75587], [75589], [75590], and [75593] from trunk. Fixes bug 4840. Fixes bug 5259. Fixes bug 5281, I think. Fixes bug 5944. Fixes bug 5757. Fixes bug 5710. Fixes bug 5307, I think. [SVN r76447] --- .../detail/exception_implementation.hpp | 4 +-- .../detail/ptree_implementation.hpp | 35 ++++++++++++------- .../boost/property_tree/detail/rapidxml.hpp | 11 +++--- .../detail/xml_parser_read_rapidxml.hpp | 9 +++-- .../property_tree/detail/xml_parser_write.hpp | 7 ++-- include/boost/property_tree/exceptions.hpp | 10 +++--- include/boost/property_tree/string_path.hpp | 3 ++ test/Jamfile.v2 | 19 ++++++---- test/test_property_tree.cpp | 4 +++ test/test_property_tree.hpp | 25 +++++++++++++ test/test_xml_parser_common.hpp | 7 ++++ test/xml_parser_test_data.hpp | 5 +++ 12 files changed, 103 insertions(+), 36 deletions(-) diff --git a/include/boost/property_tree/detail/exception_implementation.hpp b/include/boost/property_tree/detail/exception_implementation.hpp index 551e10ce37..bb39135fd9 100644 --- a/include/boost/property_tree/detail/exception_implementation.hpp +++ b/include/boost/property_tree/detail/exception_implementation.hpp @@ -53,7 +53,7 @@ namespace boost { namespace property_tree } template inline - D ptree_bad_data::data() + D ptree_bad_data::data() const { return boost::any_cast(m_data); } @@ -73,7 +73,7 @@ namespace boost { namespace property_tree } template inline - P ptree_bad_path::path() + P ptree_bad_path::path() const { return boost::any_cast

(m_path); } diff --git a/include/boost/property_tree/detail/ptree_implementation.hpp b/include/boost/property_tree/detail/ptree_implementation.hpp index 226a096855..e1839ffb6d 100644 --- a/include/boost/property_tree/detail/ptree_implementation.hpp +++ b/include/boost/property_tree/detail/ptree_implementation.hpp @@ -14,10 +14,13 @@ #include #include #include +#include #include -#if defined(BOOST_MSVC) && \ - (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000) +#if (defined(BOOST_MSVC) && \ + (_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)) || \ + (defined(BOOST_INTEL_WIN) && \ + defined(BOOST_DINKUMWARE_STDLIB)) #define BOOST_PROPERTY_TREE_PAIR_BUG #endif @@ -33,28 +36,23 @@ namespace boost { namespace property_tree // class. Unfortunately this does break the interface. BOOST_STATIC_CONSTANT(unsigned, first_offset = offsetof(value_type, first)); +#endif typedef multi_index_container, multi_index::ordered_non_unique, +#if defined(BOOST_PROPERTY_TREE_PAIR_BUG) multi_index::member_offset, - key_compare - > - > - > base_container; #else - typedef multi_index_container, - multi_index::ordered_non_unique, multi_index::member, +#endif key_compare > > > base_container; -#endif + // The by-name lookup index. typedef typename base_container::template index::type by_name_index; @@ -213,7 +211,7 @@ namespace boost { namespace property_tree template inline void basic_ptree::swap(basic_ptree &rhs) { - m_data.swap(rhs.m_data); + boost::swap(m_data, rhs.m_data); // Void pointers, no ADL necessary std::swap(m_children, rhs.m_children); } @@ -384,10 +382,21 @@ namespace boost { namespace property_tree subs::ch(this).reverse(); } + namespace impl + { + struct by_first + { + template + bool operator ()(const P& lhs, const P& rhs) const { + return lhs.first < rhs.first; + }; + }; + } + template inline void basic_ptree::sort() { - subs::ch(this).sort(); + sort(impl::by_first()); } template diff --git a/include/boost/property_tree/detail/rapidxml.hpp b/include/boost/property_tree/detail/rapidxml.hpp index 92122505c8..d3615c1193 100644 --- a/include/boost/property_tree/detail/rapidxml.hpp +++ b/include/boost/property_tree/detail/rapidxml.hpp @@ -369,8 +369,9 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml public: //! \cond internal - typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory - typedef void (free_func)(void *); // Type of user-defined function used to free memory + // Prefixed names to work around weird MSVC lookup bug. + typedef void *(boost_ptree_raw_alloc_func)(std::size_t); // Type of user-defined function used to allocate memory + typedef void (boost_ptree_raw_free_func)(void *); // Type of user-defined function used to free memory //! \endcond //! Constructs empty pool with default allocator functions. @@ -536,7 +537,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml //!
//! \param af Allocation function, or 0 to restore default function //! \param ff Free function, or 0 to restore default function - void set_allocator(alloc_func *af, free_func *ff) + void set_allocator(boost_ptree_raw_alloc_func *af, boost_ptree_raw_free_func *ff) { BOOST_ASSERT(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet m_alloc_func = af; @@ -617,8 +618,8 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml char *m_ptr; // First free byte in current pool char *m_end; // One past last available byte in current pool char m_static_memory[BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory - alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used - free_func *m_free_func; // Free function, or 0 if default is to be used + boost_ptree_raw_alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used + boost_ptree_raw_free_func *m_free_func; // Free function, or 0 if default is to be used }; /////////////////////////////////////////////////////////////////////////// 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 acec34d9dd..fc994b162e 100644 --- a/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp +++ b/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp @@ -44,7 +44,8 @@ namespace boost { namespace property_tree { namespace xml_parser { Ptree &pt_attr = pt_attr_root.push_back( std::make_pair(attr->name(), Ptree()))->second; - pt_attr.data() = attr->value(); + pt_attr.data() = std::basic_string(attr->value(), + attr->value_size()); } } @@ -63,7 +64,8 @@ namespace boost { namespace property_tree { namespace xml_parser pt.push_back(std::make_pair(xmltext(), Ptree(node->value()))); else - pt.data() += node->value(); + pt.data() += std::basic_string(node->value(), + node->value_size()); } break; @@ -72,7 +74,8 @@ namespace boost { namespace property_tree { namespace xml_parser { if (!(flags & no_comments)) pt.push_back(std::make_pair(xmlcomment(), - Ptree(node->value()))); + Ptree(std::basic_string(node->value(), + node->value_size())))); } break; diff --git a/include/boost/property_tree/detail/xml_parser_write.hpp b/include/boost/property_tree/detail/xml_parser_write.hpp index 614854e5b6..52d0aeb82d 100644 --- a/include/boost/property_tree/detail/xml_parser_write.hpp +++ b/include/boost/property_tree/detail/xml_parser_write.hpp @@ -115,8 +115,11 @@ namespace boost { namespace property_tree { namespace xml_parser // Write attributes if (optional attribs = pt.get_child_optional(xmlattr())) for (It it = attribs.get().begin(); it != attribs.get().end(); ++it) - stream << Ch(' ') << it->first << Ch('=') << - Ch('"') << it->second.template get_value >() << Ch('"'); + stream << Ch(' ') << it->first << Ch('=') + << Ch('"') + << encode_char_entities( + it->second.template get_value >()) + << Ch('"'); if ( has_attrs_only ) { diff --git a/include/boost/property_tree/exceptions.hpp b/include/boost/property_tree/exceptions.hpp index 42e2cbddeb..b35b27fce9 100644 --- a/include/boost/property_tree/exceptions.hpp +++ b/include/boost/property_tree/exceptions.hpp @@ -51,8 +51,9 @@ namespace boost { namespace property_tree ~ptree_bad_data() throw(); /// Retrieve the data associated with this error. This is the source - /// value that failed to be translated. - template T data(); + /// value that failed to be translated. You need to explicitly + /// specify its type. + template T data() const; private: boost::any m_data; }; @@ -71,8 +72,9 @@ namespace boost { namespace property_tree ~ptree_bad_path() throw(); - /// Retrieve the invalid path. - template T path(); + /// Retrieve the invalid path. You need to explicitly specify the + /// type of path. + template T path() const; private: boost::any m_path; }; diff --git a/include/boost/property_tree/string_path.hpp b/include/boost/property_tree/string_path.hpp index 53d90de63a..d4bc686dc6 100644 --- a/include/boost/property_tree/string_path.hpp +++ b/include/boost/property_tree/string_path.hpp @@ -122,6 +122,9 @@ namespace boost { namespace property_tree /// Test if the path contains a single element, i.e. no separators. bool single() const; + /// Get the separator used by this path. + char_type separator() const { return m_separator; } + std::string dump() const { return detail::dump_sequence(m_value); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 28ea4700a9..e8ea53b08d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -10,12 +10,17 @@ import testing ; test-suite "property_tree" - : [ run test_property_tree.cpp /boost/serialization//boost_serialization ] - [ run test_info_parser.cpp ] - [ run test_json_parser.cpp ] - [ run test_ini_parser.cpp ] - [ run test_xml_parser_rapidxml.cpp ] + : [ run test_property_tree.cpp /boost/serialization//boost_serialization + : : : _SCL_SECURE_NO_WARNINGS=1 ] + [ run test_info_parser.cpp + : : : _SCL_SECURE_NO_WARNINGS=1 ] + [ run test_json_parser.cpp + : : : _SCL_SECURE_NO_WARNINGS=1 ] + [ run test_ini_parser.cpp + : : : _SCL_SECURE_NO_WARNINGS=1 ] + [ run test_xml_parser_rapidxml.cpp + : : : _SCL_SECURE_NO_WARNINGS=1 ] - [ run test_multi_module1.cpp test_multi_module2.cpp ] - #[ run test_registry_parser.cpp ] + [ run test_multi_module1.cpp test_multi_module2.cpp + : : : _SCL_SECURE_NO_WARNINGS=1 ] ; diff --git a/test/test_property_tree.cpp b/test/test_property_tree.cpp index aed4827570..d9dd10bbdb 100644 --- a/test/test_property_tree.cpp +++ b/test/test_property_tree.cpp @@ -166,6 +166,7 @@ int test_main(int, char *[]) test_serialization(pt); test_bool(pt); test_char(pt); + test_sort(pt); test_leaks(pt); // must be a final test } #if 0 @@ -199,6 +200,7 @@ int test_main(int, char *[]) test_serialization(pt); test_bool(pt); test_char(pt); + test_sort(pt); test_leaks(pt); // must be a final test } #endif @@ -232,6 +234,7 @@ int test_main(int, char *[]) test_serialization(pt); test_bool(pt); test_char(pt); + test_sort(pt); test_leaks(pt); // must be a final test } @@ -265,6 +268,7 @@ int test_main(int, char *[]) test_serialization(pt); test_bool(pt); test_char(pt); + test_sort(pt); test_leaks(pt); // must be a final test } #endif diff --git a/test/test_property_tree.hpp b/test/test_property_tree.hpp index 4e670b18ff..f9ac6664fd 100644 --- a/test/test_property_tree.hpp +++ b/test/test_property_tree.hpp @@ -1290,6 +1290,31 @@ void test_char(PTREE *) } +void test_sort(PTREE *) +{ + PTREE pt; + pt.put(T("one"), T("v1")); + pt.put(T("two"), T("v2")); + pt.put(T("three"), T("v3")); + pt.put(T("four"), T("v4")); + + pt.sort(); + + PTREE::iterator it = pt.begin(); + BOOST_CHECK(std::distance(it, pt.end()) == 4); + BOOST_CHECK(it->first == T("four")); + BOOST_CHECK(it->second.data() == T("v4")); + ++it; + BOOST_CHECK(it->first == T("one")); + BOOST_CHECK(it->second.data() == T("v1")); + ++it; + BOOST_CHECK(it->first == T("three")); + BOOST_CHECK(it->second.data() == T("v3")); + ++it; + BOOST_CHECK(it->first == T("two")); + BOOST_CHECK(it->second.data() == T("v2")); +} + void test_leaks(PTREE *) { //BOOST_CHECK(PTREE::debug_get_instances_count() == 0); diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp index 0f99fbdeb1..9679cb57ec 100644 --- a/test/test_xml_parser_common.hpp +++ b/test/test_xml_parser_common.hpp @@ -139,6 +139,13 @@ void test_xml_parser() 3, 4 * umlautsize(), 13 ); + generic_parser_test_ok + ( + ReadFuncWS(), WriteFuncWS(), bug_data_pr4840, NULL, + "testpr4840.xml", NULL, "testpr4840out.xml", + 4, 13, 15 + ); + } #endif diff --git a/test/xml_parser_test_data.hpp b/test/xml_parser_test_data.hpp index 3d8dafa521..8ed3297534 100644 --- a/test/xml_parser_test_data.hpp +++ b/test/xml_parser_test_data.hpp @@ -773,4 +773,9 @@ const char *bug_data_pr5203 = "\n" "\xD0\xAE\xD0\xBD\xD0\xB8\xD1\x82"; +// Quoting attributes +const char *bug_data_pr4840 = + "\n" + ""; + #endif From c3e643059e06cae6961fa33ae02932c243d8b795 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Sun, 27 May 2012 13:16:21 +0000 Subject: [PATCH 19/23] Merge r78550 to release. Fixes an outdated test to work again. Fixes bug #6785. Fixes bug #6808. [SVN r78679] --- include/boost/property_tree/detail/json_parser_read.hpp | 3 ++- include/boost/property_tree/detail/ptree_implementation.hpp | 2 +- test/test_xml_parser_rapidxml.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/property_tree/detail/json_parser_read.hpp b/include/boost/property_tree/detail/json_parser_read.hpp index 3849450975..9638ac9748 100644 --- a/include/boost/property_tree/detail/json_parser_read.hpp +++ b/include/boost/property_tree/detail/json_parser_read.hpp @@ -102,7 +102,8 @@ namespace boost { namespace property_tree { namespace json_parser void operator()(It b, It e) const { BOOST_ASSERT(c.stack.size() >= 1); - c.stack.back()->push_back(std::make_pair(c.name, Str(b, e))); + c.stack.back()->push_back(std::make_pair(c.name, + Ptree(Str(b, e)))); c.name.clear(); c.string.clear(); } diff --git a/include/boost/property_tree/detail/ptree_implementation.hpp b/include/boost/property_tree/detail/ptree_implementation.hpp index e1839ffb6d..31d60e3ee2 100644 --- a/include/boost/property_tree/detail/ptree_implementation.hpp +++ b/include/boost/property_tree/detail/ptree_implementation.hpp @@ -389,7 +389,7 @@ namespace boost { namespace property_tree template bool operator ()(const P& lhs, const P& rhs) const { return lhs.first < rhs.first; - }; + } }; } diff --git a/test/test_xml_parser_rapidxml.cpp b/test/test_xml_parser_rapidxml.cpp index 5a0e3d4091..ed24e5fcbd 100644 --- a/test/test_xml_parser_rapidxml.cpp +++ b/test/test_xml_parser_rapidxml.cpp @@ -15,7 +15,7 @@ #define BOOST_UTF8_END_NAMESPACE }} #define BOOST_UTF8_DECL #include -#include "../../detail/utf8_codecvt_facet.cpp" +#include int test_main(int argc, char *argv[]) { From 23d8e7bbbe0a3b569472ae94cccc75f20f7a4606 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Fri, 20 Dec 2013 13:52:24 +0100 Subject: [PATCH 20/23] Delete files that shouldn't have been there. These are either SVN conversion zombies, or maybe I never merged this from devel. Either way they're gone now. --- .../detail/exceptions_implementation.hpp | 106 - .../detail/path_implementation.hpp | 181 - include/boost/property_tree/detail/pugxml.hpp | 3929 ----------------- .../detail/translator_implementation.hpp | 277 -- .../detail/xml_parser_read_pugixml.hpp | 106 - .../detail/xml_parser_read_pugxml.hpp | 82 - .../detail/xml_parser_read_spirit.hpp | 733 --- .../detail/xml_parser_read_tinyxml.hpp | 143 - test/test_cmdline_parser.cpp | 116 - test/test_registry_parser.cpp | 110 - test/test_xml_parser_pugxml.cpp | 25 - test/test_xml_parser_spirit.cpp | 24 - test/test_xml_parser_tinyxml.cpp | 26 - 13 files changed, 5858 deletions(-) delete mode 100644 include/boost/property_tree/detail/exceptions_implementation.hpp delete mode 100644 include/boost/property_tree/detail/path_implementation.hpp delete mode 100644 include/boost/property_tree/detail/pugxml.hpp delete mode 100644 include/boost/property_tree/detail/translator_implementation.hpp delete mode 100644 include/boost/property_tree/detail/xml_parser_read_pugixml.hpp delete mode 100644 include/boost/property_tree/detail/xml_parser_read_pugxml.hpp delete mode 100644 include/boost/property_tree/detail/xml_parser_read_spirit.hpp delete mode 100644 include/boost/property_tree/detail/xml_parser_read_tinyxml.hpp delete mode 100644 test/test_cmdline_parser.cpp delete mode 100644 test/test_registry_parser.cpp delete mode 100644 test/test_xml_parser_pugxml.cpp delete mode 100644 test/test_xml_parser_spirit.cpp delete mode 100644 test/test_xml_parser_tinyxml.cpp diff --git a/include/boost/property_tree/detail/exceptions_implementation.hpp b/include/boost/property_tree/detail/exceptions_implementation.hpp deleted file mode 100644 index 402051c70f..0000000000 --- a/include/boost/property_tree/detail/exceptions_implementation.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#ifndef BOOST_PROPERTY_TREE_DETAIL_EXCEPTIONS_IMPLEMENTATION_HPP_INCLUDED -#define BOOST_PROPERTY_TREE_DETAIL_EXCEPTIONS_IMPLEMENTATION_HPP_INCLUDED - -namespace boost { namespace property_tree -{ - - namespace detail - { - - // Default path-to-string converter; this is overridden for default path - template - std::string path_to_string(const P &path) - { - return std::string(""); - } - - // Helper for preparing what string in ptree_bad_path exception - template - std::string prepare_bad_path_what(const std::string &what, const P &path) - { - using namespace detail; // To allow correct resolution of path_to_string() - return what + " (" + path_to_string(path) + ")"; - } - - // Default data-to-string converter; this is overridden for default data (string) - template - std::string data_to_string(const D &data) - { - return std::string(""); - } - - // Helper for preparing what string in ptree_bad_data exception - template - std::string prepare_bad_data_what(const std::string &what, const D &data) - { - using namespace detail; // To allow correct resolution of data_to_string() - return what + " (" + data_to_string(data) + ")"; - } - - } - - /////////////////////////////////////////////////////////////////////////// - // ptree_error - - inline ptree_error::ptree_error(const std::string &what): - std::runtime_error(what) - { - } - - inline ptree_error::~ptree_error() throw() - { - } - - /////////////////////////////////////////////////////////////////////////// - // ptree_bad_data - - template - ptree_bad_data::ptree_bad_data(const std::string &what, const D &data): - ptree_error(detail::prepare_bad_data_what(what, data)), - m_data(data) - { - } - - inline ptree_bad_data::~ptree_bad_data() throw() - { - } - - template - D ptree_bad_data::data() - { - return boost::any_cast(m_data); - } - - /////////////////////////////////////////////////////////////////////////// - // ptree_bad_path - - template - ptree_bad_path::ptree_bad_path(const std::string &what, const P &path): - ptree_error(detail::prepare_bad_path_what(what, path)), - m_path(path) - { - - } - - inline ptree_bad_path::~ptree_bad_path() throw() - { - } - - template - P ptree_bad_path::path() - { - return boost::any_cast

(m_path); - } - -} } - -#endif diff --git a/include/boost/property_tree/detail/path_implementation.hpp b/include/boost/property_tree/detail/path_implementation.hpp deleted file mode 100644 index 040a580207..0000000000 --- a/include/boost/property_tree/detail/path_implementation.hpp +++ /dev/null @@ -1,181 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#ifndef BOOST_PROPERTY_TREE_DETAIL_PATH_IMPLEMENTATION_HPP_INCLUDED -#define BOOST_PROPERTY_TREE_DETAIL_PATH_IMPLEMENTATION_HPP_INCLUDED - -namespace boost { namespace property_tree -{ - - namespace detail - { - - // Path-to-string converter for basic_path - template - std::string path_to_string(const basic_path &path) - { - return path.to_string(); - } - - } - - /////////////////////////////////////////////////////////////////////// - // Free functions - - inline path operator /(const path &p1, const path &p2) - { - return path(p1) /= p2; - } - - inline wpath operator /(const wpath &p1, const wpath &p2) - { - return wpath(p1) /= p2; - } - - /////////////////////////////////////////////////////////////////////// - // Construction & destruction - - template - basic_path::basic_path() - { - } - - template - basic_path::basic_path(const Key &path, char_type separator) - { - parse(path.begin(), path.end(), separator); - } - - template - basic_path::basic_path(const char_type *path, char_type separator) - { - parse(path, path + std::char_traits::length(path), separator); - } - - /////////////////////////////////////////////////////////////////////// - // Path manipulation - - template - basic_path &basic_path::operator /=(const basic_path &rhs) - { - for (typename std::vector::const_iterator it = rhs.m_path.begin(); it != rhs.m_path.end(); ++it) - m_path.push_back(*it); - return *this; - } - - template - std::string basic_path::to_string() const - { - std::string s; - for (typename std::vector::const_iterator it = m_path.begin(); it != m_path.end(); ++it) - { - if (it == m_path.begin()) - s += detail::narrow(it->c_str()); - else - s += '.', s += detail::narrow(it->c_str()); - } - return s; - } - - /////////////////////////////////////////////////////////////////////// - // Operations - - template - template - basic_ptree, D, X> * - basic_path::get_child(basic_ptree, D, X> &root) const - { - typedef basic_ptree, D, X> ptree_type; - ptree_type *pt = &root; - for (typename std::vector::const_iterator it = m_path.begin(); it != m_path.end(); ++it) - { - typename ptree_type::iterator it_child = pt->find(*it); - if (it_child == pt->end()) - return 0; - else - pt = &(it_child->second); - } - return pt; - } - - template - template - const basic_ptree, D, X> * - basic_path::get_child(const basic_ptree, D, X> &root) const - { - typedef basic_ptree, D, X> ptree_type; - basic_path *nc_this = const_cast *>(this); - ptree_type &nc_root = const_cast(root); - return nc_this->get_child(nc_root); - } - - template - template - basic_ptree, D, X> * - basic_path::put_child(basic_ptree, D, X> &root, - const basic_ptree, D, X> &child, - bool do_not_replace) const - { - if (m_path.empty()) - { - return 0; - } - else - { - - typedef basic_ptree, D, X> ptree_type; - typedef typename std::vector::const_iterator path_iterator; - - ptree_type *pt = &root; - for (path_iterator it = m_path.begin(), end = m_path.end() - 1; it != end; ++it) - { - typename ptree_type::iterator it_child = pt->find(*it); - if (it_child == pt->end()) - pt = &pt->push_back(typename ptree_type::value_type(*it, empty_ptree()))->second; - else - pt = &it_child->second; - } - - if (do_not_replace) - return &pt->push_back(typename ptree_type::value_type(m_path.back(), child))->second; - else - { - typename ptree_type::iterator it = pt->find(m_path.back()); - if (it == pt->end()) - return &pt->push_back(typename ptree_type::value_type(m_path.back(), child))->second; - else - { - it->second = child; - return &it->second; - } - } - } - } - - /////////////////////////////////////////////////////////////////////// - // Internal - - template - template - void basic_path::parse(RanIt begin, RanIt end, char_type separator) - { - m_path.reserve(8); - while (1) - { - RanIt it = std::find(begin, end, separator); - m_path.push_back(Key(begin, it)); - if (it == end) - break; - begin = it + 1; - } - } - -} } - -#endif diff --git a/include/boost/property_tree/detail/pugxml.hpp b/include/boost/property_tree/detail/pugxml.hpp deleted file mode 100644 index 423152913f..0000000000 --- a/include/boost/property_tree/detail/pugxml.hpp +++ /dev/null @@ -1,3929 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Pug XML Parser - Version 1.0002 -// -------------------------------------------------------- -// Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) -// Released into the Public Domain. Use at your own risk. -// See pugxml.xml for further information, history, etc. -// Contributions by Neville Franks (readonly@getsoft.com). -// -// Modified to suit boost::property_tree library by Marcin Kalicinski - -#ifndef BOOST_PROPERTY_TREE_DETAIL_PUGXML_HPP_INCLUDED -#define BOOST_PROPERTY_TREE_DETAIL_PUGXML_HPP_INCLUDED - -#ifndef TCHAR - #define UNDEF_TCHAR_AND_REST - #define TCHAR char - #define _tcslen strlen - #define _istalnum isalnum - #define _tcsncpy strncpy - #define _tcscpy strcpy - #define _tcscmp strcmp - #define _tcstol strtol - #define _tcstod strtod - #define _tcstok strtok - #define _stprintf sprintf - #define _T(s) s -#endif - -//#define PUGOPT_MEMFIL //Uncomment to enable memory-mapped file parsing support. -//#define PUGOPT_NONSEG //Uncomment to enable non-destructive (non-segmenting) parsing support. - -#ifdef PUGOPT_MEMFIL -# ifndef PUGOPT_NONSEG -# define PUGOPT_NONSEG //PUGOPT_MEMFIL implies PUGOPT_NONSEG. -# endif -#endif - -#include -#include -#include -#if defined(PUGOPT_MEMFIL) | defined(PUGOPT_NONSEG) -# include -#endif - -#ifndef HIWORD -# define UNDEF_LOHIWORD -# define HIWORD(X) ((unsigned short)((unsigned long)(X)>>16)) -# define LOWORD(X) ((unsigned short)((unsigned long)(X)&0xFFFF)) -#endif - -//

-// Library variant ID. The ID 0x58475550 is owned by Kristen Wegner. You *MUST* -// provide your own unique ID if you modify or fork the code in this library to -// your own purposes. If you change this then *you* are now the maintainer, not me. -// Change also in the package section of pugxml.xml, and append yourself to the -// authors section. -// -#define PUGAPI_INTERNAL_VARIANT 0xdeadbeef -//Major version. Increment for each major release. Only change if you own the variant. -#define PUGAPI_INTERNAL_VERSION_MAJOR 1 -//Minor version. Increment for each minor release. Only change if you own the variant ID. -#define PUGAPI_INTERNAL_VERSION_MINOR 2 - -#define PUGAPI_INTERNAL_VERSION ((PUGAPI_INTERNAL_VERSION_MINOR&0xFFFF)|PUGAPI_INTERNAL_VERSION_MAJOR<<16) - -#define PUGDEF_ATTR_NAME_SIZE 128 -#define PUGDEF_ATTR_VALU_SIZE 256 -#define PUGDEF_ELEM_NAME_SIZE 256 - -//The PugXML Parser namespace. -namespace boost { namespace property_tree { namespace xml_parser { namespace pug -{ - -//The Library Variant ID. See PUGAPI_INTERNAL_VARIANT for an explanation. -//The current Library Variant ID. -inline static unsigned long lib_variant(){ return PUGAPI_INTERNAL_VARIANT; } -//The library version. High word is major version. Low word is minor version. -//The current Library Version. -inline static unsigned long lib_version(){ return PUGAPI_INTERNAL_VERSION; } - - -//A 'name=value' XML attribute structure. -typedef struct t_xml_attribute_struct -{ - TCHAR* name; //Pointer to attribute name. - bool name_insitu; //True if 'name' is a segment of the original parse string. -#ifdef PUGOPT_NONSEG - unsigned int name_size; //Length of element name. -#endif - TCHAR* value; //Pointer to attribute value. - bool value_insitu; //True if 'value' is a segment of the original parse string. -#ifdef PUGOPT_NONSEG - unsigned int value_size; //Length of element name. -#endif -} - xml_attribute_struct; - - -//Tree node classification. -//See 'xml_node_struct::type'. -typedef enum t_xml_node_type -{ - node_null, //An undifferentiated entity. - node_document, //A document tree's absolute root. - node_element, //E.g. '<...>' - node_pcdata, //E.g. '>...<' - node_cdata, //E.g. '<![CDATA[...]]>' - node_comment, //E.g. '<!--...-->' - node_pi, //E.g. '<?...?>' - node_include, //E.g. '<![INCLUDE[...]]>' - node_doctype, //E.g. '<!DOCTYPE ...>'. - node_dtd_entity, //E.g. '<!ENTITY ...>'. - node_dtd_attlist, //E.g. '<!ATTLIST ...>'. - node_dtd_element, //E.g. '<!ELEMENT ...>'. - node_dtd_notation //E.g. '<!NOTATION ...>'. -} - xml_node_type; - - -static const unsigned long parse_grow = 4; //Default child element & attribute space growth increment. - - -//Parser Options -static const unsigned long parse_minimal = 0x00000000; //Unset the following flags. -static const unsigned long parse_pi = 0x00000002; //Parse '<?...?>' -static const unsigned long parse_doctype = 0x00000004; //Parse '<!DOCTYPE ...>' section, setting '[...]' as data member. -static const unsigned long parse_comments = 0x00000008; //Parse <!--...-->' -static const unsigned long parse_cdata = 0x00000010; //Parse '<![CDATA[...]]>', and/or '<![INCLUDE[...]]>' -static const unsigned long parse_escapes = 0x00000020; //Not implemented. -static const unsigned long parse_trim_pcdata = 0x00000040; //Trim '>...<' -static const unsigned long parse_trim_attribute = 0x00000080; //Trim 'foo="..."'. -static const unsigned long parse_trim_cdata = 0x00000100; //Trim '<![CDATA[...]]>', and/or '<![INCLUDE[...]]>' -static const unsigned long parse_trim_entity = 0x00000200; //Trim '<!ENTITY name ...>', etc. -static const unsigned long parse_trim_doctype = 0x00000400; //Trim '<!DOCTYPE [...]>' -static const unsigned long parse_trim_comment = 0x00000800; //Trim <!--...-->' -static const unsigned long parse_wnorm = 0x00001000; //Normalize all entities that are flagged to be trimmed. -static const unsigned long parse_dtd = 0x00002000; //If parse_doctype set, then parse whatever is in data member ('[...]'). -static const unsigned long parse_dtd_only = 0x00004000; //If parse_doctype|parse_dtd set, then parse only '<!DOCTYPE [*]>' -static const unsigned long parse_default = 0x0000FFFF; -static const unsigned long parse_noset = 0x80000000; - - -//An XML document tree node. -typedef struct t_xml_node_struct -{ - t_xml_node_struct* parent; //Pointer to parent - TCHAR* name; //Pointer to element name. -#ifdef PUGOPT_NONSEG - unsigned int name_size; //Length of element name. Since 19 Jan 2003 NF. -#endif - bool name_insitu; //True if 'name' is a segment of the original parse string. - xml_node_type type; //Node type; see xml_node_type. - unsigned int attributes; //Count attributes. - unsigned int attribute_space; //Available pointer space in 'attribute'. - xml_attribute_struct** attribute; //Array of pointers to attributes; see xml_attribute_struct. - unsigned int children; //Count children in member 'child'. - unsigned int child_space; //Available pointer space in 'child'. - t_xml_node_struct** child; //Array of pointers to children. - TCHAR* value; //Pointer to any associated string data. -#ifdef PUGOPT_NONSEG - unsigned int value_size; //Length of element data. Since 19 Jan 2003 NF. -#endif - bool value_insitu; //True if 'data' is a segment of the original parse string. -} -xml_node_struct; - - -//Concatenate 'rhs' to 'lhs', growing 'rhs' if neccessary. -//Pointer to pointer to receiving string. Note: If '*lhs' is not null, it must have been dynamically allocated using 'malloc'. -//Source. -//Success if 'realloc' was successful. -//'rhs' is resized and 'rhs' is concatenated to it. -inline static bool strcatgrow(TCHAR** lhs,const TCHAR* rhs) -{ - if(!*lhs) //Null, so first allocate. - { - *lhs = (TCHAR*) malloc(1UL*sizeof(TCHAR)); - **lhs = 0; //Zero-terminate. - } - size_t ulhs = _tcslen(*lhs); - size_t urhs = _tcslen(rhs); - TCHAR* temp = (TCHAR*) realloc(*lhs,(ulhs+urhs+1UL)*sizeof(TCHAR)); - if(!temp) return false; //Realloc failed. - memcpy(temp+ulhs,rhs,urhs*sizeof(TCHAR)); //Concatenate. - temp[ulhs+urhs] = 0; //Terminate it. - *lhs = temp; - return true; -} - - -inline static bool chartype_symbol(TCHAR c) //Character is alphanumeric, -or- '_', -or- ':', -or- '-', -or- '.'. -{ return (_istalnum(c)||c==_T('_')||c==_T(':')||c==_T('-')||c==_T('.')); } -inline static bool chartype_space(TCHAR c) //Character is greater than 0 or character is less than exclamation. -{ return (c>0 && c<_T('!')); } -inline static bool chartype_enter(TCHAR c) //Character is '<'. -{ return (c==_T('<')); } -inline static bool chartype_leave(TCHAR c) //Character is '>'. -{ return (c==_T('>')); } -inline static bool chartype_close(TCHAR c) //Character is '/'. -{ return (c==_T('/')); } -inline static bool chartype_equals(TCHAR c) //Character is '='. -{ return (c==_T('=')); } -inline static bool chartype_special(TCHAR c) //Character is '!'. -{ return (c==_T('!')); } -inline static bool chartype_pi(TCHAR c) //Character is '?'. -{ return (c==_T('?')); } -inline static bool chartype_dash(TCHAR c) //Character is '-'. -{ return (c==_T('-')); } -inline static bool chartype_quote(TCHAR c) //Character is "‘" -or- ‘"‘. -{ return (c==_T('"')||c==_T('\'')); } -inline static bool chartype_lbracket(TCHAR c) //Character is '['. -{ return (c==_T('[')); } -inline static bool chartype_rbracket(TCHAR c) //Character is ']'. -{ return (c==_T(']')); } - - -#ifdef PUGOPT_NONSEG - - -//Concatenate 'rhs' to 'lhs', growing 'lhs' if neccessary. -//Pointer to pointer to receiving string. Note: If '*lhs' is not null, it must have been dynamically allocated using 'malloc'. -//Source. -//Specifies the length of *lhs in bytes and returns its new length. -//Specifies the length of *rhs in bytes. -//Success if 'realloc' was successful. -//'lhs' is resized and 'rhs' is concatenated to it. -inline static bool strcatgrown_impl(TCHAR** lhs,const TCHAR* rhs,unsigned int& lsize,unsigned int rsize) -{ - if(!*lhs) //Null, allocate and copy. - { - *lhs = (TCHAR*) malloc(rsize+sizeof(TCHAR)); - if(!*lhs) - { - lsize = 0; - return false; //Allocate failed. - } - memcpy(*lhs,rhs,rsize); //Concatenate. - *(*lhs + rsize) = 0; //Terminate it. - lsize = rsize; - } - else //Reallocate. NF I don't think this is right for MBCS, nor is code in 'StrCatGrow()'. - { - TCHAR* temp = (TCHAR*) realloc(*lhs,lsize + rsize + sizeof(TCHAR)); - if(!temp) return false; //Realloc failed. - memcpy(temp+lsize,rhs,rsize); //Concatenate. - lsize += rsize; //Set new length. - temp[lsize] = 0; //Terminate it. - *lhs = temp; - } - return true; -} - -//Concatenate 'rhs' to 'lhs', growing 'lhs' if neccessary. -//Pointer to pointer to receiving string. Note: If '*lhs' is not null, it must have been dynamically allocated using 'malloc'. -//Source. -//Specifies the length of *lhs in bytes and returns its new length. -//Success if 'realloc' was successful. -//'lhs' is resized and 'rhs' is concatenated to it. -inline static bool strcatgrown(TCHAR** lhs,const TCHAR* rhs,unsigned int& lsize) -{ - const unsigned int rsize = _tcslen(rhs) * sizeof(TCHAR); - return pug::strcatgrown_impl(lhs,rhs,lsize,rsize); -} - -//Trim leading and trailing whitespace. -//Pointer to pointer to string. -//Specifies the length of *s in bytes and returns its new length. -//Success. -//*s is modified to point to the first non-white character in the string. -inline static bool strwtrim(TCHAR** s,unsigned int& len) -{ - if(!s || !*s) return false; - TCHAR* pse = *s + len; - while(*s < pse && pug::chartype_space(**s)) //Find first non-white character. - ++*s; //As long as we hit whitespace, increment the string pointer. - for(; *s < --pse;) //As long as we hit whitespace, decrement. - { - if(!pug::chartype_space(*pse)) - { - len = pse + 1 - *s; - break; - } - } - return true; -} - - -#else - - -//Trim leading and trailing whitespace. -//Pointer to pointer to string. -//Success. -inline static bool strwtrim(TCHAR** s) -{ - if(!s || !*s) return false; - while(**s > 0 && **s < _T('!')) ++*s; //As long as we hit whitespace, increment the string pointer. - const TCHAR* temp = *s; - while(0 != *temp++); //Find the terminating null. - long i, n = (long)(temp-*s-1); - --n; //Start from the last string TCHAR. - for(i=n; (i > -1) && (*s)[i] > 0 && (*s)[i] < _T('!'); --i); //As long as we hit whitespace, decrement. - if(i -// In situ trim leading and trailing whitespace, then convert all consecutive -// whitespace to a single space TCHAR. -// -//Pointer to pointer to string. -//Success. -inline static bool strwnorm(TCHAR** s) -{ - if(!s || !*s) return false; //No string to normalize. - while(**s > 0 && **s < _T('!')) ++(*s); //As long as we hit whitespace, increment the string pointer. - const TCHAR* temp = *s; - while(0 != *temp++); //Find the terminating null. - long n = (long)(temp-*s-1); - TCHAR* norm = (TCHAR*)malloc(sizeof(TCHAR)*(n+1)); //Allocate a temporary normalization buffer. - if(!norm) return false; //Allocation failed. - memset(norm,0,sizeof(TCHAR)*(n+1)); //Zero it. - long j = 1; - norm[0] = (*s)[0]; - long i; - for(i=1; i= _T('!')) //Previous was not whitespace-like. - { - norm[j] = _T(' '); //Convert to a space TCHAR. - ++j; //Normalization buffer grew by one TCHAR. - } - } - else { norm[j] = (*s)[i]; ++j; } //Not whitespace, so just copy over. - } - if(j < n) //Normalization buffer is actually different that input. - { - _tcsncpy(*s,norm,j); //So, copy it back to input. - (*s)[j] = 0; //Zero-terminate. - } - free(norm); //Don't need this anymore. - --n; //Start from the last string TCHAR. - for(i=n; (i > -1) && (*s)[i] > 0 && (*s)[i] < _T('!'); --i); //Find the first non-whitespace from the end. - if(iSet structure string member to given value. -//Pointer to pointer to destination. -//Source. -//Pointer to boolean in-situ string flag. -//True if member was set to the new value. -// -// If 'src' is larger than 'dest' then 'dest' is resized, in which case -// it is probably no longer in-situ,and 'in_situ' is set to false. If -// 'dest' is already no longer in-situ, and 'src' is too small then the -// existing memory pointed to is freed. If 'dest' is larger than or equal -// to 'dest' then it is merely copied with no resize. -// -inline static bool strcpyinsitu - ( - TCHAR** dest, - const TCHAR* src, - bool* insitu -#ifdef PUGOPT_NONSEG - , - unsigned int& destlen -#endif - ) -{ - if(!dest || !src || !insitu) return false; //Bad argument(s), so fail. -#ifndef PUGOPT_NONSEG //Always use heap for our r/o string. - size_t l = (*dest) ? _tcslen(*dest) : 0; //How long is destination? - if(l >= _tcslen(src)) //Destination is large enough, so just copy. - { - _tcscpy(*dest,src); //Copy. - return true; //Success. - } - else //Destination is too small. -#endif - { - if(*dest && !*insitu) free(*dest); //If destination is not in-situ, then free it. - *dest = NULL; //Mark destination as NULL, forcing 'StrCatGrow' to 'malloc. -#ifdef PUGOPT_NONSEG - if(strcatgrown(dest,src,destlen)) //Allocate & copy source to destination -#else - if(strcatgrow(dest,src)) //Allocate & copy source to destination -#endif - { - *insitu = false; //Mark as no longer being in-situ, so we can free it later. - return true; //Success. - } - } - return false; //Failure. -} - - -//Character set pattern match. -//String or expression for left-hand side of comparison. -//String for right-hand side of comparison. -//Used by 'strcmpwild'. -inline int strcmpwild_cset(const TCHAR** src,const TCHAR** dst) -{ - int find = 0; - int excl = 0; - int star = 1; - if(**src == _T('!')) - { - excl = 1; - ++(*src); - } - while(**src != _T(']') || star == 1) - { - if(find == 0) - { - if(**src == _T('-') && *(*src-1) < *(*src+1) && *(*src+1) != _T(']') && star == 0) - { - if(**dst >= *(*src-1) && **dst <= *(*src+1)) - { - find = 1; - ++(*src); - } - } - else if(**src == **dst) find = 1; - } - ++(*src); - star = 0; - } - if(excl == 1) find = (1 - find); - if(find == 1) ++(*dst); - return find; -} - - -inline int strcmpwild_impl(const TCHAR* src,const TCHAR* dst); //Forward declaration. - - -//Wildcard pattern match. -//String or expression for left-hand side of comparison. -//String for right-hand side of comparison. -//Used by 'strcmpwild'. -inline int strcmpwild_astr(const TCHAR** src,const TCHAR** dst) -{ - int find = 1; - ++(*src); - while((**dst != 0 && **src == _T('?')) || **src == _T('*')) - { - if(**src == _T('?')) ++(*dst); - ++(*src); - } - while(**src == _T('*')) ++(*src); - if(**dst == 0 && **src != 0) return 0; - if(**dst == 0 && **src == 0) return 1; - else - { - if(strcmpwild_impl(*src,*dst) == 0) - { - do - { - ++(*dst); - while(**src != **dst && **src != _T('[') && **dst != 0) - ++(*dst); - } - while((**dst != 0) ? strcmpwild_impl(*src,*dst) == 0 : 0 != (find=0)); - } - if(**dst == 0 && **src == 0) find = 1; - return find; - } -} - - -//Compare two strings, with globbing, and character sets. -//String or expression for left-hand side of comparison. -//String for right-hand side of comparison. -//Used by 'strcmpwild'. -inline int strcmpwild_impl(const TCHAR* src,const TCHAR* dst) -{ - int find = 1; - for(; *src != 0 && find == 1 && *dst != 0; ++src) - { - switch(*src) - { - case _T('?'): ++dst; break; - case _T('['): ++src; find = strcmpwild_cset(&src,&dst); break; - case _T('*'): find = strcmpwild_astr(&src,&dst); --src; break; - default : find = (int) (*src == *dst); ++dst; - } - } - while(*src == _T('*') && find == 1) ++src; - return (int) (find == 1 && *dst == 0 && *src == 0); -} - -//Compare two strings, with globbing, and character sets. -//String or expression for left-hand side of comparison. -//String for right-hand side of comparison. -// -// Returns 1 if src does not match dst, or -1 if either src or dst are null, -// or 0 if src matches dst. -// -// -// Simple regular expressions are permitted in 'src': The character '*' matches -// zero or more characters up to the next pattern, or the end of the string. The -// '?' character matches any single character. Character sets and negation are -// also permitted, for example, '[abcd]', '[a-zA-Z]', etc. -// -inline int strcmpwild(const TCHAR* src,const TCHAR* dst) -{ - if(!src || !dst) return -1; - return (strcmpwild_impl(src,dst)==1)?0:1; -} - - -//Allocate & init an xml_attribute_struct structure. -//Pointer to new xml_attribute_struct structure. -inline static xml_attribute_struct* new_attribute(void) -{ - xml_attribute_struct* p = (xml_attribute_struct*)malloc(sizeof(xml_attribute_struct)); //Allocate one attribute. - if(p) //If allocation succeeded. - { - p->name = p->value = 0; //No name or value. -#ifdef PUGOPT_NONSEG - p->name_size = p->value_size = 0; //Lengths of zero. -#endif - p->name_insitu = p->value_insitu = true; //Default to being in-situ of the parse string. - } - return p; -} - - -//Allocate & init an xml_node_struct structure. -//Desired node type. -//Pointer to new xml_node_struct structure. -inline static xml_node_struct* new_node(xml_node_type type = node_element) -{ - xml_node_struct* p = (xml_node_struct*)malloc(sizeof(xml_node_struct)); //Allocate one node. - if(p) //If allocation succeeded. - { - p->name = p->value = 0; //No name or data. -#ifdef PUGOPT_NONSEG - p->name_size = p->value_size = 0; -#endif - p->type = type; //Set the desired type. - p->attributes = p->children = 0; //No attributes or children. - p->name_insitu = p->value_insitu = true; //Default to being in-situ of the parse string. - if - ( - type != node_document && //None of these will have attributes. - type != node_pcdata && - type != node_cdata && - type != node_include && - type != node_comment - ) - p->attribute = (xml_attribute_struct**)malloc(sizeof(xml_attribute_struct*)); //Allocate one attribute. - else p->attribute = NULL; - p->attribute_space = (p->attribute) ? 1 : 0; - if - ( - type == node_element || //Only these will have children. - type == node_doctype || - type == node_document - ) - p->child = (xml_node_struct**)malloc(sizeof(xml_node_struct*)); //Allocate one child. - else p->child = NULL; - p->child_space = (p->child) ? 1 : 0; - } - return p; -} - - -//Allocate & append a new xml_node_struct onto the given parent. -//Pointer to parent node. -//Pointer space growth increment. -//Desired node type. -//Pointer to new node. -//Child pointer space of 'node' may be reallocated. -inline static xml_node_struct* append_node(xml_node_struct* parent,long grow,xml_node_type type = node_element) -{ - if(!parent) return NULL; //Must have a parent. - if(parent->children == parent->child_space) //Out of pointer space. - { - xml_node_struct** t = (xml_node_struct**)realloc(parent->child,sizeof(xml_node_struct*)*(parent->child_space+grow)); //Grow pointer space. - if(t) //Reallocation succeeded. - { - parent->child = t; - parent->child_space += grow; //Update the available space. - } - } - xml_node_struct* child = new_node(type); //Allocate a new child. - child->parent = parent; //Set it's parent pointer. - parent->child[parent->children] = child; //Set the parent's child pointer. - parent->children++; //One more child. - return child; -} - - -//Allocate & append a new attribute to the given xml_node_struct. -//Pointer to parent node. -//Pointer space growth increment. -//Pointer to appended xml_attribute_struct. -//Attribute pointer space of 'node' may be reallocated. -inline static xml_attribute_struct* append_attribute(xml_node_struct* node,long grow) -{ - if(!node) return NULL; - xml_attribute_struct* a = new_attribute(); - if(!a) return NULL; - if(node->attributes == node->attribute_space) //Out of space, so grow. - { - xml_attribute_struct** t = (xml_attribute_struct**)realloc(node->attribute,sizeof(xml_node_struct*)*(node->attribute_space+grow)); - if(t) - { - node->attribute = t; - node->attribute_space += grow; - } - } - node->attribute[node->attributes] = a; - node->attributes++; - return a; -} - - -//Non-recursively free a tree. -// -// Pointer to the root of the tree. Note: 'root' must have been dynamically -// allocated using 'malloc' or 'realloc', as 'free_node' tries to also free -// the structure pointed to by 'root'. -// -//'root' no longer points to a valid structure. -inline static void free_node(xml_node_struct* node) -{ - if(!node) return; - - register xml_node_struct* cursor = node; - - //Free all children of children. - do - { -LOC_STEP_INTO: - for(; cursor->children>0; --cursor->children) //Free each child in turn; 'children' keeps count while we jump around. - { - register xml_node_struct* t = cursor->child[cursor->children-1]; //Take a pointer to the child. - if(t && t->children) //If the child has children. - { - cursor = t; //Step in. - goto LOC_STEP_INTO; //Step into this node. - } - else if(t) - { - if(t->attributes) //Child has attributes. - { - register unsigned int n = t->attributes; //Free each attribute. - for(register unsigned int i=0; iattribute[i]->name && !t->attribute[i]->name_insitu) - free(t->attribute[i]->name); - if(t->attribute[i]->value && !t->attribute[i]->value_insitu) - free(t->attribute[i]->value); - free(t->attribute[i]); - } - } - if(t->attribute) free(t->attribute); //Free attribute pointer space. - if(t->child) free(t->child); //Free child pointer space. - if(t->name && !t->name_insitu) free(t->name); - if(t->value && !t->value_insitu) free(t->value); - free(t); //Free the child node. - } - } - cursor = cursor->parent; //Step out. - } - while(cursor->children); //While there are children. - //Finally, free the root's children & the root itself. - if(cursor->attributes) - { - register unsigned int n = cursor->attributes; - for(register unsigned int i=0; iattribute[i]->name && !cursor->attribute[i]->name_insitu) - free(cursor->attribute[i]->name); - if(cursor->attribute[i]->value && !cursor->attribute[i]->value_insitu) - free(cursor->attribute[i]->value); - free(cursor->attribute[i]); - } - } - if(cursor->attribute) free(cursor->attribute); //Free attribute pointer space. - if(cursor->child) free(cursor->child); //Free child pointer space. - if(cursor->name && !cursor->name_insitu) free(cursor->name); //Free name & data. - if(cursor->value && !cursor->value_insitu) free(cursor->value); - free(cursor); //Free the root itself. -} - -//Recursively free a tree. -//Pointer to the root of the tree. -//Not used. -inline static void free_node_recursive(xml_node_struct* root) -{ - if(root) - { - unsigned int n = root->attributes; - register unsigned int i; - for(i=0; iattribute[i]->name && !root->attribute[i]->name_insitu) - free(root->attribute[i]->name); - if(root->attribute[i]->value && !root->attribute[i]->value_insitu) - free(root->attribute[i]->value); - free(root->attribute[i]); - } - free(root->attribute); - n = root->children; - for(i=0; ichild[i]); - free(root->child); - if(root->name && !root->name_insitu) free(root->name); - if(root->value && !root->value_insitu) free(root->value); - free(root); - } -} - - -//Parser utilities. -#define SKIPWS() { while(chartype_space(*s)) ++s; if(*s==0) return s; } -#define OPTSET(OPT) ( optmsk & OPT ) -#define PUSHNODE(TYPE) { cursor = append_node(cursor,growby,TYPE); } -#define POPNODE() { cursor = cursor->parent; } -#define SCANFOR(X) { while(*s!=0 && !(X)) ++s; if(*s==0) return s; } -#define SCANWHILE(X) { while((X)) ++s; if(*s==0) return s; } -#ifndef PUGOPT_NONSEG -# define ENDSEG() { ch = *s; *s = 0; ++s; if(*s==0) return s; } -#else -# define ENDSEG() { ch = *s; ++s; if(*s==0) return s; } -# define SETLEN() ( cursor->value_size = s - cursor->value ) -# define ENDSEGDAT() { ch = *s; SETLEN(); ++s; if(*s==0) return s; } -# define ENDSEGNAM(S) { ch = *s; S->name_size = s - S->name; ++s; if(*s==0) return s; } -# define ENDSEGATT(S) { ch = *s; S->value_size = s - S->value; ++s; if(*s==0) return s; } -#endif - - -//Static single-pass in-situ parse the given xml string. -//Pointer to XML-formatted string. -//Pointer to root. -//Pointer space growth increment. -//Parse options mask. -//Last string position or null. -// -// Input string is zero-segmented if 'PUGOPT_NONSEG' is not defined. Memory -// may have been allocated to 'root' (free with 'free_node'). -// -static TCHAR* parse(register TCHAR* s,xml_node_struct* xmldoc,long growby,unsigned long optmsk = parse_default) -{ - if(!s || !xmldoc) return s; - TCHAR ch = 0; //Current char, in cases where we must null-terminate before we test. - xml_node_struct* cursor = xmldoc; //Tree node cursor. - TCHAR* mark = s; //Marked string position for temporary look-ahead. - while(*s!=0) - { -LOC_SEARCH: //Obliviously search for next element. - SCANFOR(chartype_enter(*s)); //Find the next '<'. - if(chartype_enter(*s)) - { - ++s; -LOC_CLASSIFY: //What kind of element? - if(chartype_pi(*s)) //'', so fudge it. -#endif - s = mark; - PUSHNODE(node_pi); //Append a new node on the tree. - goto LOC_ELEMENT; //Go read the element name. - } - else //Bad PI or parse_pi not set. - { - SCANFOR(chartype_leave(*s)); //Look for '>'. - ++s; - mark = 0; - continue; - } - } - else if(chartype_special(*s)) //'value = s; //Save the offset. - while(*s!=0 && *(s+1) && *(s+2) && !((chartype_dash(*s) && chartype_dash(*(s+1))) && chartype_leave(*(s+2)))) ++s; //Scan for terminating '-->'. - if(*s==0) return s; -#ifdef PUGOPT_NONSEG - SETLEN(); //NF 19 Jan 2003. -#else - *s = 0; //Zero-terminate this segment at the first terminating '-'. -#endif - if(OPTSET(parse_trim_comment)) //Trim whitespace. - { -#ifdef PUGOPT_NONSEG - strwtrim(&cursor->value,cursor->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&cursor->value); - else strwtrim(&cursor->value); -#endif - } - s += 2; //Step over the '\0-'. - POPNODE(); //Pop since this is a standalone. - goto LOC_LEAVE; //Look for any following PCDATA. - } - else - { - while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !((chartype_dash(*s) && chartype_dash(*(s+1))) && chartype_leave(*(s+2)))) ++s; //Scan for terminating '-->'. - if(*s==0) return s; - s += 2; - goto LOC_LEAVE; //Look for any following PCDATA. - } - } - else if(chartype_lbracket(*s)) //'value = s; //Save the offset. - while(!(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'. - if(chartype_rbracket(*s)) - { -#ifdef PUGOPT_NONSEG - SETLEN(); //NF 19 Jan 2003. -#else - *s = 0; //Zero-terminate this segment. -#endif - ++s; - if(OPTSET(parse_trim_cdata)) //Trim whitespace. - { -#ifdef PUGOPT_NONSEG - strwtrim(&cursor->value, cursor->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&cursor->value); - else strwtrim(&cursor->value); -#endif - } - } - POPNODE(); //Pop since this is a standalone. - } - else //Flagged for discard, but we still have to scan for the terminator. - { - while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'. - ++s; - } - ++s; //Step over the last ']'. - goto LOC_LEAVE; //Look for any following PCDATA. - } - } - } - } - } - } - } - } - else if(*s==_T('C')) //'value = s; //Save the offset. - while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'. - if(*(s+2)==0) return s; //Very badly formed. - if(chartype_rbracket(*s)) - { -#ifdef PUGOPT_NONSEG - SETLEN(); //NF 19 Jan 2003. -#else - *s = 0; //Zero-terminate this segment. -#endif - ++s; - if(OPTSET(parse_trim_cdata)) //Trim whitespace. - { -#ifdef PUGOPT_NONSEG - strwtrim(&cursor->value,cursor->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&cursor->value); - else strwtrim(&cursor->value); -#endif - } - } - POPNODE(); //Pop since this is a standalone. - } - else //Flagged for discard, but we still have to scan for the terminator. - { - while(*s!=0 && *(s+1)!=0 && *(s+2)!=0 && !(chartype_rbracket(*s) && chartype_rbracket(*(s+1)) && chartype_leave(*(s+2)))) ++s; //Scan for terminating ']]>'. - ++s; - } - ++s; //Step over the last ']'. - goto LOC_LEAVE; //Look for any following PCDATA. - } - } - } - } - } - } - continue; //Probably a corrupted CDATA section, so just eat it. - } - else if(*s==_T('D')) //'value = a->name = s; //Save the offset. - } - SCANWHILE(chartype_symbol(*s)); //'name_size = a->value_size = s - a->value; //Save the length. rem: Before ENDSEG() -#endif - ENDSEG(); //Save char in 'ch', terminate & step over. - if(chartype_space(ch)) SKIPWS(); //Eat any whitespace. -LOC_DOCTYPE_SYMBOL: - if(chartype_symbol(*s)) - { - mark = s; - SCANWHILE(chartype_symbol(*s)); //'...symbol SYSTEM...' - if(OPTSET(parse_doctype)) - { - a = append_attribute(cursor,1); - a->value = a->name = mark; -#ifdef PUGOPT_NONSEG - a->value_size = a->name_size = s - mark; //NF 19 Jan 2003. -#else - *s = 0; -#endif - } - ++s; - SKIPWS(); - } - if(chartype_quote(*s)) //'...SYSTEM "..."' - { -LOC_DOCTYPE_QUOTE: - ch = *s; - ++s; - mark = s; - while(*s!=0 && *s != ch) ++s; - if(*s!=0) - { - if(OPTSET(parse_doctype)) - { - a = append_attribute(cursor,1); - a->value = mark; -#ifdef PUGOPT_NONSEG - a->value_size = s - mark; //NF 19 Jan 2003. -#else - *s = 0; -#endif - } - ++s; - SKIPWS(); //Eat whitespace. - if(chartype_quote(*s)) goto LOC_DOCTYPE_QUOTE; //Another quoted section to store. - else if(chartype_symbol(*s)) goto LOC_DOCTYPE_SYMBOL; //Not wellformed, but just parse it. - } - } - if(chartype_lbracket(*s)) //'...[...' - { - ++s; //Step over the bracket. - if(OPTSET(parse_doctype)) cursor->value = s; //Store the offset. - unsigned int bd = 1; //Bracket depth counter. - while(*s!=0) //Loop till we're out of all brackets. - { - if(chartype_rbracket(*s)) --bd; - else if(chartype_lbracket(*s)) ++bd; - if(bd == 0) break; - ++s; - } - //Note: 's' now points to end of DTD, i.e.: ']'. - if(OPTSET(parse_doctype)) - { - //Note: If we aren't parsing the DTD ('!parse_dtd', etc.) then it is stored in the DOM as one whole chunk. -#ifdef PUGOPT_NONSEG - SETLEN(); //NF 19 Jan 2003 -#else - *s = 0; //Zero-terminate. -#endif - if(OPTSET(parse_dtd)||OPTSET(parse_dtd_only)) - { - if(OPTSET(parse_dtd)) - { -#ifdef PUGOPT_NONSEG - TCHAR svch = *s; - try - { - *s = 0; //Zero-terminate. - parse(cursor->value,cursor,growby,optmsk); //Parse it. - } - catch(...){ assert(false); } - *s = svch; -#else - parse(cursor->value,cursor,growby,optmsk); //Parse it. -#endif - } - if(OPTSET(parse_dtd_only)) return (s+1); //Flagged to parse DTD only, so leave here. - } - else if(OPTSET(parse_trim_doctype)) //Trim whitespace. - { -#ifdef PUGOPT_NONSEG - strwtrim(&cursor->value, cursor->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&cursor->value); - else strwtrim(&cursor->value); -#endif - } - ++s; //Step over the zero. - POPNODE(); //Pop since this is a standalone. - } - SCANFOR(chartype_leave(*s)); - continue; - } - //Fall-through; make sure we pop. - POPNODE(); //Pop since this is a standalone. - continue; - } - } - } - } - } - } - } - else if(chartype_symbol(*s)) //An inline DTD tag. - { - mark = s; - SCANWHILE(chartype_symbol(*s)); - ENDSEG(); //Save char in 'ch', terminate & step over. - xml_node_type e = node_dtd_entity; -#ifdef PUGOPT_NONSEG - const unsigned int dtdilen = (s - 1) - mark; - if(_tcsncmp(mark,_T("ATTLIST"),max((7*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_attlist; - else if(_tcsncmp(mark,_T("ELEMENT"),max((7*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_element; - else if(_tcsncmp(mark,_T("NOTATION"),max((8*sizeof(TCHAR)),dtdilen))==0) e = node_dtd_notation; -#else - if(_tcscmp(mark,_T("ATTLIST"))==0) e = node_dtd_attlist; - else if(_tcscmp(mark,_T("ELEMENT"))==0) e = node_dtd_element; - else if(_tcscmp(mark,_T("NOTATION"))==0) e = node_dtd_notation; -#endif - PUSHNODE(e); //Append a new node on the tree. - if(*s!=0 && chartype_space(ch)) - { - SKIPWS(); //Eat whitespace. - if(chartype_symbol(*s) || *s==_T('%')) - { - mark = s; - if(*s==_T('%')) //Could be 'name = mark; //Sort out extraneous whitespace when we retrieve it. TODO: Whitespace cleanup. -#endif - ++s; - if(chartype_space(*s)) - { - SKIPWS(); //Eat whitespace. -#ifndef PUGOPT_NONSEG - *(s-1) = _T('%'); - cursor->name = (s-1); -#endif - } -#ifndef PUGOPT_NONSEG - else cursor->name = mark; -#endif - } - else cursor->name = s; - SCANWHILE(chartype_symbol(*s)); -#ifdef PUGOPT_NONSEG - cursor->name_size = s - cursor->name; -#endif - ENDSEG(); //Save char in 'ch', terminate & step over. - if(chartype_space(ch)) - { - SKIPWS(); //Eat whitespace. - if(e == node_dtd_entity) //Special case; may have multiple quoted sections w/anything inside. - { - cursor->value = s; //Just store everything here. - bool qq = false; //Quote in/out flag. - while(*s != 0) //Loop till we find the right sequence. - { - if(!qq && chartype_quote(*s)){ ch = *s; qq = true; } - else if(qq && *s == ch) qq = false; - else if(!qq && chartype_leave(*s)) //Not in quoted reqion and '>' hit. - { -#ifdef PUGOPT_NONSEG - SETLEN(); //NF 19 Jan 2003. -#else - *s = 0; -#endif - ++s; - if(OPTSET(parse_trim_entity)) - { -#ifdef PUGOPT_NONSEG - strwtrim(&cursor->value,cursor->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&cursor->value); - else strwtrim(&cursor->value); -#endif - } - POPNODE(); - goto LOC_SEARCH; - } - ++s; - } - if(OPTSET(parse_trim_entity)) - { -#ifdef PUGOPT_NONSEG - strwtrim(&cursor->value, cursor->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&cursor->value); - else strwtrim(&cursor->value); -#endif - } - } - else - { - cursor->value = s; - SCANFOR(chartype_leave(*s)); //Just look for '>'. -#ifdef PUGOPT_NONSEG - SETLEN(); //NF 19 Jan 2003. -#else - *s = 0; -#endif - ++s; - if(OPTSET(parse_trim_entity)) - { -#ifdef PUGOPT_NONSEG - strwtrim(&cursor->value, cursor->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&cursor->value); - else strwtrim(&cursor->value); -#endif - } - POPNODE(); - goto LOC_SEARCH; - } - } - } - } - POPNODE(); - } - } - else if(chartype_symbol(*s)) //'<#...' - { - cursor = append_node(cursor,growby); //Append a new node to the tree. -LOC_ELEMENT: //Scan for & store element name. - cursor->name = s; - SCANWHILE(chartype_symbol(*s)); //Scan for a terminator. -#ifdef PUGOPT_NONSEG - cursor->name_size = s - cursor->name; //Note: Before ENDSEG(). -#endif - ENDSEG(); //Save char in 'ch', terminate & step over. - if - ( - *s!=0 && - ( - chartype_close(ch) //'' as '/>' NF 19 Jan 2003 -#endif - ) - ) - { - SCANFOR(chartype_leave(*s)); //Scan for '>', stepping over the tag name. - POPNODE(); //Pop. - continue; - } - else if(*s!=0 && !chartype_space(ch)) goto LOC_PCDATA; //No attributes, so scan for PCDATA. - else if(*s!=0 && chartype_space(ch)) - { - SKIPWS(); //Eat any whitespace. -LOC_ATTRIBUTE: - if(chartype_symbol(*s)) //<... #... - { - xml_attribute_struct* a = append_attribute(cursor,growby); //Make space for this attribute. - a->name = s; //Save the offset. - SCANWHILE(chartype_symbol(*s)); //Scan for a terminator. -#ifdef PUGOPT_NONSEG - ENDSEGNAM(a); -#else - ENDSEG(); //Save char in 'ch', terminate & step over. -#endif - if(*s!=0 && chartype_space(ch)) SKIPWS(); //Eat any whitespace. - if(*s!=0 && (chartype_equals(ch) || chartype_equals(*s))) //'<... #=...' - { - if(chartype_equals(*s)) ++s; - SKIPWS(); //Eat any whitespace. - if(chartype_quote(*s)) //'<... #="...' - { - ch = *s; //Save quote char to avoid breaking on "''" -or- '""'. - ++s; //Step over the quote. - a->value = s; //Save the offset. - SCANFOR(*s == ch); //Scan for the terminating quote, or '>'. -#ifdef PUGOPT_NONSEG - ENDSEGATT(a); -#else - ENDSEG(); //Save char in 'ch', terminate & step over. -#endif - if(OPTSET(parse_trim_attribute)) //Trim whitespace. - { -#ifdef PUGOPT_NONSEG - strwtrim(&a->value,a->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&a->value); - else strwtrim(&a->value); -#endif - } - if(chartype_leave(*s)){ ++s; goto LOC_PCDATA; } - else if(chartype_close(*s)) - { - ++s; - POPNODE(); - SKIPWS(); //Eat any whitespace. - if(chartype_leave(*s)) ++s; - goto LOC_PCDATA; - } - if(chartype_space(*s)) //This may indicate a following attribute. - { - SKIPWS(); //Eat any whitespace. - goto LOC_ATTRIBUTE; //Go scan for additional attributes. - } - } - } - if(chartype_symbol(*s)) goto LOC_ATTRIBUTE; - else if(*s!=0 && cursor->type == node_pi) - { -#ifdef PUGOPT_NONSEG - SCANFOR(chartype_pi(*s)); //compliments change where we don't fudge to '/>' when we find the PI. NF 20 Jan 2003 - SKIPWS(); //Eat any whitespace. - if(chartype_pi(*s)) ++s; -#else - SCANFOR(chartype_close(*s)); - SKIPWS(); //Eat any whitespace. - if(chartype_close(*s)) ++s; -#endif - SKIPWS(); //Eat any whitespace. - if(chartype_leave(*s)) ++s; - POPNODE(); - goto LOC_PCDATA; - } - } - } -LOC_LEAVE: - if(chartype_leave(*s)) //'...>' - { - ++s; //Step over the '>'. -LOC_PCDATA: //'>...<' - mark = s; //Save this offset while searching for a terminator. - SKIPWS(); //Eat whitespace if no genuine PCDATA here. - if(chartype_enter(*s)) //We hit a '<...', with only whitespace, so don't bother storing anything. - { - if(chartype_close(*(s+1))) //'', stepping over any end-tag name. - POPNODE(); //Pop. - continue; //Continue scanning. - } - else goto LOC_SEARCH; //Expect a new element enter, so go scan for it. - } - s = mark; //We hit something other than whitespace; restore the original offset. - PUSHNODE(node_pcdata); //Append a new node on the tree. - cursor->value = s; //Save the offset. - SCANFOR(chartype_enter(*s)); //'...<' -#ifdef PUGOPT_NONSEG - ENDSEGDAT(); -#else - ENDSEG(); //Save char in 'ch', terminate & step over. -#endif - if(OPTSET(parse_trim_pcdata)) //Trim whitespace. - { -#ifdef PUGOPT_NONSEG - strwtrim(&cursor->value,cursor->value_size); -#else - if(OPTSET(parse_wnorm)) strwnorm(&cursor->value); - else strwtrim(&cursor->value); -#endif - } - POPNODE(); //Pop since this is a standalone. - if(chartype_enter(ch)) //Did we hit a '<...'? - { - if(chartype_close(*s)) //'' - POPNODE(); //Pop. - goto LOC_LEAVE; - } - else if(chartype_special(*s)) goto LOC_CLASSIFY; //We hit a '' - { - POPNODE(); //Pop. - ++s; - continue; - } - } - } - //Fall-through B. - else if(chartype_close(*s)) //'.../' - { - SCANFOR(chartype_leave(*s)); //'.../>' - POPNODE(); //Pop. - continue; - } - } - } - return s; -} - - -/* -//Read data from the file at 'path' into the buffer. Free with 'free'. -//File path. -//Pointer to pointer to string to recieve buffer. -//Pointer to count bytes read and stored in 'buffer'. -//Temporary read buffer size. -//Success if file at 'path' was opened and bytes were read into memory. -//Memory is allocated at '*buffer'. Free with 'free'. -inline static bool load_file(const TCHAR* path,TCHAR** buffer,unsigned long* size,unsigned long tempsize = 4096) -{ - if(!path || !buffer || !size) return false; - *size = 0; - *buffer = 0; - HANDLE file_handle = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); - if(file_handle == INVALID_HANDLE_VALUE) return false; - TCHAR* temp = (TCHAR*) malloc(sizeof(TCHAR)*tempsize); - if(!temp) return false; - unsigned long read_bytes = 0; - ZeroMemory(temp,sizeof(TCHAR)*tempsize); - while(ReadFile(file_handle,(void*)temp,tempsize-1,&read_bytes,0) && read_bytes && strcatgrow(buffer,temp)) - { - *size += read_bytes; - ZeroMemory(temp,sizeof(TCHAR)*tempsize); - } - CloseHandle(file_handle); - free(temp); - return (*size) ? true : false; -} -*/ - - -//A void pointer array. Used by various xml_node::find* functions. -class pointer_array -{ -//Internal Data Members -protected: - unsigned int _size; //Count items. - unsigned int _room; //Available space. - void** _data; //The list. - unsigned int _grow; //Grow by increment. -public: - //Default constructor. - //Array growth increment. - pointer_array(unsigned int grow = 4): - _size(0), - _room(0), - _data(NULL), - _grow(grow) - { - _data = (void**)malloc(sizeof(void*)*_grow); - _room = (_data) ? _grow : 0; - } - ~pointer_array(){ if(_data) free(_data); } -public: - bool empty(){ return (_size == 0); } //True if there is no data in the array. - void remove_all(){ _size = 0; } //Remove all data elements from the array. - void clear() //Free any allocated memory. - { - if(_data) - { - _data = (void**)realloc(_data,sizeof(void*)*_grow); //Reallocate to first growth increment. - _room = _grow; //Mark it as such. - _size = 0; //Mark array as empty. - } - } - virtual void*& operator[](unsigned int i) //Access element at subscript, or dummy value if overflow. - { - static void* dummy = 0; - if(i < _size) return _data[i]; else return dummy; - } - unsigned int size(){ return _size; } //Count data elements in the array. - virtual void* at(unsigned int i){ if(i < _size) return _data[i]; else return NULL; } //Access element at subscript, or NULL if overflow. - long push_back(void* element) //Append a new element to the array. - { - if(_data) //Fail if no array. - { - if(_size < _room) //There is enough allocated space. - { - _data[_size] = element; //Set it. - _size++; //Increment our count of elements. - return _size-1; //Return the element's subscript. - } - else //Not enough room. - { - void** temp = (void**)realloc(_data,sizeof(void*)*(_size+_grow)); //Grow the array. - if(temp) //Reallocation succeeded. - { - _room += _grow; //Increment available space. - _data = temp; //Assign reallocated value to array pointer. - _data[_size] = element; //Set the element to be added. - _size++; //Increment our count of elements. - return _size-1; //Return the element's subscript. - } - } - } - return -1; //Something failed, so return a bad subscript. - } -}; - - -//A simple indentation stack. -//Used by xml_node::outer_xml function. -class indent_stack -{ -//Internal Data Members -protected: - TCHAR _inch; //The indent character. - TCHAR* _stac; //The aggregate indent string (stack). - int _size; //Current depth (avoids using '_tcslen' on push/pop). -//Construction/Destruction -public: - //Default constructor. - //Indent character. - indent_stack(TCHAR c = _T('\t')): - _inch(c), - _stac(0) , - _size(0) - { - _stac = (TCHAR*)malloc(sizeof(TCHAR)); //Allocate. - *_stac = 0; //Zero-terminate. - } - //Destructor. - virtual ~indent_stack(){ if(_stac) free(_stac); } -//Stack Operators -public: - //Grow indent string by one indent character. - //Reallocates the indent string. - void push() - { - if(_inch && _stac) - { - _size++; - _stac = (TCHAR*)realloc(_stac,sizeof(TCHAR)*(_size+1)); - _stac[_size-1] = _inch; - _stac[_size] = 0; - } - } - //Shrink the indent string by one indent character. - void pop() - { - if(_inch && _stac && _size > 0) - { - _size--; - _stac = (TCHAR*)realloc(_stac,sizeof(TCHAR)*(_size+1)); - _stac[_size] = 0; - } - } - //Accesses the indent depth. - //The current indent string, or "" if empty. - const TCHAR* depth(){ return (_inch && _stac) ? _stac : _T(""); } -}; - - -// -// Stream output. Recursively writes the given xml_node_struct structure to -// the given stream. NOTE: Use this recursive implementation for debug purposes -// only, since a large tree may cause a stack overflow. -// -//Reference to output stream. -//Reference to indentation stack. -//Pointer to the node. -//Use linebreaks? -// -// String data is written to stream. Indent stack may be altered. -// If you want to make this prettier, and to avoid propagating whitespace, -// you will have to trim excess whitespace from the PCDATA sections. -// -inline static void outer_xml(std::basic_ostream > & os,indent_stack& indent,xml_node_struct* node,bool breaks = true) -{ - if(node && os.good()) //There is a node and ostream is OK. - { - register unsigned int n, i; - os << indent.depth(); - switch(node->type) - { - case node_dtd_attlist: - if(node->name) - { -#ifdef PUGOPT_NONSEG - os << _T("name, node->name_size ); -#else - os << _T("name; -#endif - if(node->value) -#ifdef PUGOPT_NONSEG - { - os << _T(" "); - os.write( node->value, node->value_size ); - } -#else - os << _T(" ") << node->value; -#endif - - os << _T(">"); - } - break; - case node_dtd_element: - if(node->name) - { -#ifdef PUGOPT_NONSEG - os << _T("name, node->name_size ); - if(node->value) - { - os << _T(" "); - os.write( node->value, node->value_size ); - } -#else - os << _T("name; - if(node->value) os << _T(" ") << node->value; -#endif - os << _T(">"); - } - break; - case node_dtd_entity: - if(node->name) - { -#ifdef PUGOPT_NONSEG - os << _T("name, node->name_size ); - if(node->value) - { - os << _T(" "); - os.write( node->value, node->value_size ); - } -#else - os << _T("name; - if(node->value) os << _T(" ") << node->value; -#endif - os << _T(">"); - } - break; - case node_dtd_notation: - if(node->name) - { -#ifdef PUGOPT_NONSEG - os << _T("name, node->name_size ); - if(node->value) - { - os << _T(" "); - os.write( node->value, node->value_size ); - } -#else - os << _T("name; - if(node->value) os << _T(" ") << node->value; -#endif - os << _T(">"); - } - break; - case node_doctype: - os << _T("attributes; - for(i=0; iattribute[i]->name) -#ifdef PUGOPT_NONSEG - os.write( node->attribute[i]->name, node->attribute[i]->name_size ); -#else - os << node->attribute[i]->name; -#endif - else if(node->attribute[i]->value) -#ifdef PUGOPT_NONSEG - { - os << _T("\""); - os.write( node->attribute[i]->value, node->attribute[i]->value_size ); - os << _T("\""); - } -#else - os << _T("\"") << node->attribute[i]->value << _T("\""); -#endif - } - if(node->children) - { - if(breaks) os << std::endl; - else os << _T(" "); - os << _T("["); - if(breaks) os << std::endl; - else os << _T(" "); - n = node->children; - indent.push(); //Push the indent stack. - for(i=0; ichild[i] && //There is a child at i. - ( - node->child[i]->type == node_dtd_attlist || //Skip all other types. - node->child[i]->type == node_dtd_element || - node->child[i]->type == node_dtd_entity || - node->child[i]->type == node_dtd_notation - ) - ) - outer_xml(os,indent,node->child[i],breaks); - } - indent.pop(); //Pop the indent stack. - os << _T("]"); - } - else if(node->value) -#ifdef PUGOPT_NONSEG - { - os << _T(" ["); - os.write(node->value,node->value_size); - os << _T("]"); - } -#else - os << _T(" [") << node->value << _T("]"); -#endif - os << _T(">"); - break; - case node_pcdata: -#ifdef PUGOPT_NONSEG - if(node->value) os.write(node->value,node->value_size); -#else - if(node->value) os << node->value; -#endif - break; - case node_cdata: -#ifdef PUGOPT_NONSEG - if(node->value) - { - os << _T("value,node->value_size); - os << _T("]]>"); - } -#else - if(node->value) os << _T("value << _T("]]>"); -#endif - break; - case node_include: -#ifdef PUGOPT_NONSEG - if(node->value) - { - os << _T("value, node->value_size); - os << _T("]]>"); - } -#else - if(node->value) os << _T("value << _T("]]>"); -#endif - break; - case node_comment: -#ifdef PUGOPT_NONSEG - if(node->value) - { - os << _T(""); - } -#else - if(node->value) os << _T(""); -#endif - break; - case node_element: - case node_pi: - os << _T("<"); - if(node->type==node_pi) os << _T("?"); - if(node->name) -#ifdef PUGOPT_NONSEG - os.write(node->name,node->name_size); -#else - os << node->name; -#endif - else os << _T("anonymous"); - n = node->attributes; - for(i=0; iattribute[i] && node->attribute[i]->name) - { -#ifdef PUGOPT_NONSEG - os << _T(" "); - os.write(node->attribute[i]->name,node->attribute[i]->name_size); - if(node->attribute[i]->value) - { - os << _T("=\""); - os.write(node->attribute[i]->value,node->attribute[i]->value_size); - os << _T("\""); - } -#else - os << _T(" ") << node->attribute[i]->name; - if(node->attribute[i]->value) os << _T("=\"") << node->attribute[i]->value << _T("\""); -#endif - } - } - n = node->children; - if(n && node->type == node_element) - { - os << _T(">"); - if(n == 1 && node->child[0]->type == node_pcdata) - { - if(node->child[0] && node->child[0]->value) -#ifdef PUGOPT_NONSEG - os.write(node->child[0]->value,node->child[0]->value_size); -#else - os << node->child[0]->value; -#endif - } - else - { - if(breaks) os << std::endl; - indent.push(); - for(i=0; ichild[i],breaks); - indent.pop(); - os << indent.depth(); - } - os << _T("name) - os.write(node->name, node->name_size); -#else - if(node->name) os << node->name; -#endif - os << _T(">"); - } - else - { - if(node->type==node_pi) os << _T("?>"); - else os << _T("/>"); - } - break; - default: break; - } - if(breaks) os << std::endl; - os.flush(); - } -} - - -//Abstract iterator class for interating over a node's members. -//Used as base class for 'xml_node_iterator' and 'xml_attribute_iterator'. -template -class xml_iterator : public std::_Ranit<_Ty,_Diff,_Pointer,_Reference> -{ -protected: - xml_node_struct* _vref; //A pointer to the node over which to iterate. - long _sscr; //Current subscript of element. -public: - xml_iterator() : _vref(0), _sscr(-1) {} //Default constructor. - xml_iterator(xml_node_struct* vref,long sscr = 0) : _vref(vref), _sscr(sscr){ } //Initializing constructor. - xml_iterator(const xml_iterator& r) : _vref(r._vref), _sscr(r._sscr){ } //Copy constructor. - virtual ~xml_iterator(){} //Destructor. -public: - virtual bool good() = 0; //Internal validity of '_vref'. - virtual bool oob() = 0; //Out of bounds check for '_sscr' with respect to '_vref'. Returns true if '_sscr' is O.O.B. -public: - virtual long subscript(){ return _sscr; } //Get subscript value; - virtual void subscript(long new_subscript){ _sscr = new_subscript; } //Set subscript value; -public: - virtual xml_iterator& operator=(const xml_iterator& rhs){ _vref = rhs._vref; _sscr = rhs._sscr; return *this; } //Assignment. - virtual bool operator==(const xml_iterator& rhs){ return (_sscr == rhs._sscr); } //True if this is equal to RHS. - virtual bool operator!=(const xml_iterator& rhs){ return (_sscr != rhs._sscr); } //True if this is not equal to RHS. - virtual bool operator<(const xml_iterator& rhs){ return (_sscr < rhs._sscr); } //True if this subscript is less than RHS. - virtual bool operator>(const xml_iterator& rhs){ return (_sscr > rhs._sscr); } //True if this subscript is greater than RHS. - virtual bool operator<=(const xml_iterator& rhs){ return (_sscr <= rhs._sscr); } //True if this subscript is less than or equal to RHS. - virtual bool operator>=(const xml_iterator& rhs){ return (_sscr >= rhs._sscr); } //True if this subscript is greater than or equal to RHS. - virtual xml_iterator& operator++(){ _sscr++; return *this; } //Increment the iterator (subscript). - virtual xml_iterator& operator--(){ _sscr--; return *this; } //Decrement the iterator (subscript). - virtual _Ty& operator*() = 0; //Dereference operator. - virtual _Ty* operator->() = 0; -}; - -class xml_node; //Forward decl. - - -//Abstract tree walker class for xml_node::traverse(). -class xml_tree_walker -{ -protected: - long _deep; //Current node depth. -public: - xml_tree_walker() : _deep(0) {} //Default constructor. - virtual ~xml_tree_walker(){} //Destructor. -public: - virtual void push(){ ++_deep; } //Increment node depth. - virtual void pop(){ --_deep; } //Decrement node depth. - virtual long depth(){ return (_deep > 0) ? _deep : 0; } //Access node depth. -public: - //Callback when traverse on a given root node begins. - //Returning false will abort the traversal. - //Override this to implement your own custom behavior. - virtual bool begin(xml_node&){ return true; } - //Callback for each node that is hit on traverse. - //Returning false will abort the traversal. - virtual bool for_each(xml_node&) = 0; - //Callback when traverse on a given root node ends. - //Returning false will abort the traversal. - //Override this to implement your own custom behavior. - virtual bool end(xml_node&){ return true; } -}; - - -//Provides a light-weight wrapper for manipulating xml_attribute_struct structures. -// -// Note: xml_attribute does not create any memory for the attribute it wraps; -// it only wraps a pointer to an existing xml_attribute_struct. -// -class xml_attribute -{ -//Internal Data Members -protected: - xml_attribute_struct* _attr; //The internal attribute pointer. -//Construction/Destruction -public: - xml_attribute() : _attr(NULL) {} //Default constructor. - xml_attribute(xml_attribute_struct* attr) : _attr(attr) {} //Initializing constructor. - xml_attribute(const xml_attribute& r) : _attr(r._attr) {} //Copy constructor. - virtual ~xml_attribute(){} //Destructor. -//Operators -public: - void attach(xml_attribute_struct* v){ _attr = v; } - xml_attribute& operator=(const xml_attribute& r){ _attr = r._attr; return *this; } //Assign internal pointer. - bool operator==(const xml_attribute& r){ return (_attr == r._attr); } //Compare internal pointer. - bool operator!=(const xml_attribute& r){ return (_attr != r._attr); } - operator xml_attribute_struct*(){ return _attr; } - //Cast attribute value as std::string. If not found, return empty. - //The std::string attribute value, or empty. - //Note: Modifying this will not change the value, e.g. read only. - operator std::string() - { - std::string temp; - if(!empty() && has_value()) - { -#ifdef PUGOPT_NONSEG - temp.append(_attr->value,_attr->value_size); -#else - temp = _attr->value; -#endif - } - return temp; - } - //Cast attribute value as integral character string. If not found, return NULL. - //Integral character string attribute value, or NULL. - //Warning: Modifying this may corrupt portions of the document tree. - operator const TCHAR*() - { - if(empty() || !has_value()) return NULL; - return _attr->value; - } - //Cast attribute value as long. If not found, return 0. - //Attribute value as long, or 0. - //Note: Modifying this will not change the value, e.g. read only. - operator long() - { - if(empty() || !has_value()) return 0; -#ifdef PUGOPT_NONSEG - TCHAR temp[PUGDEF_ATTR_VALU_SIZE]; - unsigned int valulen = sizeof(temp)-1; - const unsigned int maxlen = valulen ? min(valulen,_attr->value_size) : _attr->value_size; - _tcsncpy(temp,_attr->value,maxlen); - temp[maxlen] = 0; - return _tcstol(temp,NULL,10); -#else - return _tcstol(_attr->value,NULL,10); -#endif - } - //Cast attribute value as double. If not found, return 0.0. - //Attribute value as double, or 0.0. - //Note: Modifying this will not change the value, e.g. read only. - operator double() - { - if(empty() || !has_value()) return 0.0; -#ifdef PUGOPT_NONSEG - TCHAR temp[PUGDEF_ATTR_VALU_SIZE]; - unsigned int valulen = sizeof(temp)-1; - const unsigned int maxlen = valulen ? min(valulen,_attr->value_size) : _attr->value_size; - _tcsncpy(temp,_attr->value,maxlen); - temp[maxlen] = 0; - return _tcstod(temp,0); -#else - return _tcstod(_attr->value,0); -#endif - } - //Cast attribute value as bool. If not found, return false. - //Attribute value as bool, or false. - //Note: Modifying this will not change the value, e.g. read only. - operator bool() - { - if(empty() || !has_value()) return false; - if(*(_attr->value)) - { - return //Only look at first char: - ( - *(_attr->value) == _T('1') || //1* - *(_attr->value) == _T('t') || //t* (true) - *(_attr->value) == _T('T') || //T* (True|true) - *(_attr->value) == _T('y') || //y* (yes) - *(_attr->value) == _T('Y') //Y* (Yes|YES) - ) - ? true : false; //Return true if matches above, else false. - } - } - //Set attribute to std::string. - //Value std::string to set. - //Reference to xml_attribute. - xml_attribute& operator=(const std::string& rhs){ value(rhs.c_str()); return *this; } - //Set attribute to string. - //Value string to set. - //Reference to xml_attribute. - xml_attribute& operator=(const TCHAR* rhs){ if(rhs) value(rhs); return *this; } - //Set attribute to long. - //Value long to set. - //Reference to xml_attribute. - xml_attribute& operator=(long rhs) - { - TCHAR temp[32] = {0}; - _stprintf(temp,_T("%ld"),rhs); - value(temp); - return *this; - } - //Set attribute to double. - //Value double to set. - //Reference to xml_attribute. - xml_attribute& operator=(double rhs) - { - TCHAR temp[32] = {0}; - _stprintf(temp,_T("%lf"),rhs); - value(temp); - return *this; - } - //Set attribute to bool. - //Value bool to set. - //Reference to xml_attribute. - xml_attribute& operator=(bool rhs) - { - value(rhs?_T("true"):_T("false")); - return *this; - } - //Right-shift attribute value to std::string. - //Reference to std::string to set. - //Reference to xml_attribute. - xml_attribute& operator>>(std::string& rhs) - { -#ifdef PUGOPT_NONSEG - rhs.clear(); - rhs.append(_attr->value,_attr->value_size); -#else - rhs = value(); -#endif - return *this; - } - //Right-shift attribute value to long. - //Reference to long to set. - //Reference to xml_attribute. - xml_attribute& operator>>(long& rhs){ rhs = (long)*this; return *this; } - //Right-shift attribute value to double. - //Reference to double to set. - //Reference to xml_attribute. - xml_attribute& operator>>(double& rhs){ rhs = (double)*this; return *this; } - //Right-shift attribute value to bool. - //Reference to bool to set. - //Reference to xml_attribute. - xml_attribute& operator>>(bool& rhs){ rhs = (bool)*this; return *this; } - //Left-shift attribute value to long. - //Reference to long to set. - //Reference to xml_attribute to read. - //Reference to long. - friend long& operator<<(long& lhs,xml_attribute& rhs){ lhs = (long)rhs; return lhs; } - //Left-shift attribute value to double. - //Reference to double to set. - //Reference to xml_attribute to read. - //Reference to double. - friend double& operator<<(double& lhs,xml_attribute& rhs){ lhs = (double)rhs; return lhs; } - //Left-shift attribute value to bool. - //Reference to bool to set. - //Reference to xml_attribute to read. - //Reference to bool. - friend bool& operator<<(bool& lhs,xml_attribute& rhs){ lhs = (bool)rhs; return lhs; } - //Left-shift long to attribute value. - //Reference to xml_attribute to set. - //Reference to long to read. - //Reference to xml_attribute. - friend xml_attribute& operator<<(xml_attribute& lhs,const long rhs){ lhs = rhs; return lhs; } - //Left-shift double to attribute value. - //Reference to xml_attribute to set. - //Reference to double to read. - //Reference to xml_attribute. - friend xml_attribute& operator<<(xml_attribute& lhs,const double& rhs){ lhs = rhs; return lhs; } - //Left-shift bool to attribute value. - //Reference to xml_attribute to set. - //Reference to bool to read. - //Reference to xml_attribute. - friend xml_attribute& operator<<(xml_attribute& lhs,const bool& rhs){ lhs = rhs; return lhs; } -public: - bool empty(){ return (_attr == NULL); } //True if the internal xml_attribute_struct pointer is NULL. - bool has_name(){ return (!empty() && _attr->name); } //True if the attribute has a name. - bool has_value(){ return (!empty() && _attr->value); } //True if the attribute has a value. -#ifdef PUGOPT_NONSEG - bool has_name(const TCHAR* name) { return (name && !empty() && has_name() && _tcsncmp(_attr->name,name,_attr->name_size)==0); } //Is named 'name'. - bool has_value(const TCHAR* value) { return (value && !empty() && has_value() && _tcsncmp(_attr->value,value,_attr->value_size)==0); } //Has value 'value'. -#else - bool has_name(const TCHAR* name) { return (name && !empty() && has_name() && _tcscmp(_attr->name,name)==0); } //Is named 'name'. - bool has_value(const TCHAR* value) { return (value && !empty() && has_value() && _tcscmp(_attr->value,value)==0); } //Has value 'value'. -#endif -public: - const TCHAR* name(){ return (!empty() && _attr->name) ? _attr->name : _T(""); } //Access the attribute name. -#ifdef PUGOPT_NONSEG - const unsigned int name_size(){ return (!empty()) ? _attr->name_size : 0; } //Access the attribute name length (for PUGOPT_NONSEG). -#endif - bool name(TCHAR* new_name) //Set the attribute name. - { - if(!empty() && new_name) -#ifdef PUGOPT_NONSEG - return strcpyinsitu(&_attr->name,new_name,&_attr->name_insitu,_attr->name_size); -#else - return strcpyinsitu(&_attr->name,new_name,&_attr->name_insitu); -#endif - return false; - } - const TCHAR* value(){ return (!empty()) ? _attr->value : _T(""); } //Access the attribute value. -#ifdef PUGOPT_NONSEG - const unsigned int value_size(){ return (!empty()) ? _attr->value_size : 0; } //Access the attribute name length (for PUGOPT_NONSEG). -#endif - bool value(const TCHAR* new_value) //Set the attribute value. - { - if(!empty() && new_value) -#ifdef PUGOPT_NONSEG - return strcpyinsitu(&_attr->value,new_value,&_attr->value_insitu,_attr->value_size); -#else - return strcpyinsitu(&_attr->value,new_value,&_attr->value_insitu); -#endif - return false; - } -}; - - -class xml_node; //Forward declaration. - - -//Forward wrapper for any as-yet undefined class. -// -// Used by xml_node_iterator, and xml_attribute_iterator to assist with -// operator->(), and operator*() mapping to xml_node and xml_attribute -// types. -// -template class forward_class -{ -protected: - TYPE* _obj; //The class, internal. -public: - forward_class() : _obj(NULL) { _obj = new TYPE(); } //Default constructor. - forward_class(const TYPE& r) : _obj(NULL) { _obj = new TYPE(r); } //Copy constructor. - virtual ~forward_class(){ if(_obj) delete _obj; } //Destructor. -public: - TYPE& operator* (){ return *_obj; } //Dereference to the class. - TYPE* operator->(){ return _obj; } //Class member selection. - operator TYPE (){ return *_obj; } //Cast as class type. - operator TYPE&(){ return *_obj; } //Cast as class type reference. - operator TYPE*(){ return _obj; } //Cast as class type pointer. -}; - - -//Provides a light-weight wrapper for manipulating xml_node_struct structures. -class xml_node -{ -//Internal Data Members -protected: - - xml_node_struct* _root; //Pointer to node root. - xml_node_struct _dummy; //Utility. - -//Construction/Destruction -public: - - //Default constructor. - // - // Node root points to a dummy 'xml_node_struct' structure. Test for this - // with 'empty'. - // - xml_node(): _root(0) - { - memset(&_dummy,0,sizeof(xml_node_struct)); - _dummy.type = node_null; - _dummy.parent = &_dummy; - _root = &_dummy; - } - - //Construct, wrapping the given 'xml_node_struct' pointer. - //Pointer to node to wrap. - //It is possible that 'p' is NULL, so test for this with 'empty'. - xml_node(xml_node_struct* p): _root(p) { memset(&_dummy,0,sizeof(xml_node_struct)); } - - //Copy constructor. - //Reference to node. - // - // Only the root pointer is assigned, so both classes now in fact point - // to the same structure. - // - xml_node(const xml_node& r): _root(r._root) {} - - //Destructor. - virtual ~xml_node(){} - - //Attach to the given structure. - //Pointer to node structure to wrap. - //Pointer to previous node structure. - xml_node_struct* attach(xml_node_struct* p) - { - xml_node_struct* prev = _root; - _root = p; - return prev; - } - -//Iteration -public: - - //Child node iterator. - class xml_node_iterator : public xml_iterator - { - protected: - forward_class _wrap; //Wrapper for xml_node. - public: - xml_node_iterator() : _wrap(), xml_iterator() {} //Default constructor. - xml_node_iterator(xml_node_struct* vref,long sscr = 0) : _wrap(), xml_iterator(vref,sscr) { } //Initializing constructor. - xml_node_iterator(const xml_node_iterator& r) : _wrap(), xml_iterator(r) { } //Copy constructor. - virtual bool good() //Internal validity. - { - if - ( - _vref != 0 && //Pointing to some node. - _vref->child != 0 && //The node has an array of children. - _vref->children > 0 //There are 1 or more children in the array. - ) - return true; - return false; - } - virtual bool oob() //Out of bounds check. - { - if - ( - !good() || //There is no data over which to iterate. - _sscr < 0 || //Subscript is out of range. - _sscr >= (long)_vref->children - ) - return true; - return false; - } - //Pointer dereference for current xml_node. - // - // Reference to the internal xml_node object, which wraps the - // xml_node_struct corresponding to the node at the - // current subscript. - // - virtual xml_node& operator*() - { - if(!oob()) _wrap->attach(_vref->child[_sscr]); - else _wrap->attach(NULL); - return (xml_node&)_wrap; - } - virtual xml_node* operator->() //Member selection for current xml_node. - { - if(!oob()) _wrap->attach(_vref->child[_sscr]); - else _wrap->attach(NULL); - return (xml_node*)_wrap; - } - }; - - //Attribute iterator. - class xml_attribute_iterator : public xml_iterator - { - protected: - forward_class _wrap; - public: - xml_attribute_iterator() : _wrap(), xml_iterator() {} //Default constructor. - xml_attribute_iterator(xml_node_struct* vref,long sscr = 0) : _wrap(), xml_iterator(vref,sscr) { } //Initializing constructor. - xml_attribute_iterator(const xml_attribute_iterator& r) : _wrap(), xml_iterator(r) { } //Copy constructor. - virtual bool good() //Internal validity check. - { - if - ( - _vref != 0 && //Pointing to some node. - _vref->attribute != 0 && //The node has an array of children. - _vref->attributes > 0 //There are 1 or more children in the array. - ) - return true; - return false; - } - virtual bool oob() //Out of bounds check. - { - if - ( - !good() || //There is no data over which to iterate. - _sscr < 0 || //Subscript is out of range. - _sscr >= (long)_vref->attributes //For 'end' - ) - return true; - return false; - } - //Pointer dereference for current xml_attribute. - // - // Reference to the internal xml_attribute object, which wraps the - // xml_attribute_struct corresponding to the attribute at the - // current subscript. - // - virtual xml_attribute& operator*() - { - if(!oob()) _wrap->attach(_vref->attribute[_sscr]); - else _wrap->attach(NULL); - return (xml_attribute&)_wrap; - } - //Member selection for current xml_attribute. - // - virtual xml_attribute* operator->() - { - if(!oob()) _wrap->attach(_vref->attribute[_sscr]); - else _wrap->attach(NULL); - return (xml_attribute*)_wrap; - } - }; - - //Base iterator type (for child nodes). Same as 'child_iterator'. - typedef xml_node_iterator iterator; - //Base iterator type (for child nodes). Same as 'iterator'. - typedef xml_node_iterator child_iterator; - //Base iterator type (for sibling nodes). Same as 'iterator'. - typedef xml_node_iterator sibling_iterator; - //Attribute iterator type. - typedef xml_attribute_iterator attribute_iterator; - - //Access the begin iterator for this node's collection of child nodes. - //The begin iterator for this node's collection of child nodes. - //Same as 'children_begin'. - iterator begin(){ return iterator(_root,0); } - //Access the end iterator for this node's collection of child nodes. - //The end iterator for this node's collection of child nodes. - //Same as 'children_end'. - iterator end(){ return iterator(_root,_root->children); } - //Erase the given node from node's collection of child nodes. - //The begin iterator for this node's collection of child nodes. - //Same as 'children_erase'. - iterator erase(iterator where){ remove_child((unsigned int)where.subscript()); return iterator(_root,0); } - - //Access the begin iterator for this node's collection of child nodes. - //The begin iterator for this node's collection of child nodes. - //Same as 'begin'. - child_iterator children_begin(){ return child_iterator(_root,0); } - //Access the end iterator for this node's collection of child nodes. - //The end iterator for this node's collection of child nodes. - //Same as 'end'. - child_iterator children_end(){ return child_iterator(_root,_root->children); } - //Erase the given node from node's collection of child nodes. - //The begin iterator for this node's collection of child nodes. - //Same as 'erase'. - child_iterator children_erase(child_iterator where){ remove_child((unsigned int)where.subscript()); return child_iterator(_root,0); } - - //Access the begin iterator for this node's collection of attributes. - //The begin iterator for this node's collection of attributes. - attribute_iterator attributes_begin(){ return attribute_iterator(_root,0); } - //Access the end iterator for this node's collection of attributes. - //The end iterator for this node's collection of attributes. - attribute_iterator attributes_end(){ return attribute_iterator(_root,_root->attributes); } - //Erase the given attribute from node's collection of attributes. - //The begin iterator for this node's collection of attributes. - attribute_iterator attributes_erase(attribute_iterator where){ remove_attribute((unsigned int)where.subscript()); return attribute_iterator(_root,0); } - - //Access the begin iterator for this node's collection of siblings. - //The begin iterator for this node's collection of siblings. - sibling_iterator siblings_begin(){ if(!empty()) return sibling_iterator(_root->parent,0); return sibling_iterator(); } - //Access the end iterator for this node's collection of siblings. - //The end iterator for this node's collection of siblings. - sibling_iterator siblings_end(){ if(!empty()) return sibling_iterator(_root->parent,_root->parent->children); return sibling_iterator(); } - //Erase the given sibling from node's collection of siblings. - //The begin iterator for this node's collection of siblings. - sibling_iterator siblings_erase(sibling_iterator where){ parent().remove_child((unsigned int)where.subscript()); return iterator(_root->parent,0); } - -//Overloaded Operators -public: - - operator xml_node_struct*(){ return _root; } //Cast as xml_node_struct pointer. - operator void*(){ return (void*)_root; } //Cast root as void*. - xml_node& operator=(const xml_node& r){ _root = r._root; return *this; } //Assign to xml_node_struct pointer. - bool operator==(const xml_node& r){ return (_root == r._root); } //True if this has the same internal xml_node_struct pointer value. - xml_node operator[](unsigned int i){ return child(i); } //Access the child at subscript. - -//Node Classification -public: - - bool empty() { return (_root == 0 || _root->type == node_null); } //Node pointer is null, or type is node_null. Same as type_null. - bool type_null() { return empty(); } //Node pointer is null, or type is node_null. Same as empty. - bool type_document() { return (_root && _root == _root->parent && _root->type == node_document); } //Node is tree root. - bool type_element() { return (_root && _root->type == node_element); } //Node is an element. - bool type_comment() { return (_root && _root->type == node_comment); } //Node is a comment. - bool type_pcdata() { return (_root && _root->type == node_pcdata); } //Node is PCDATA. - bool type_cdata() { return (_root && _root->type == node_cdata); } //Node is CDATA. - bool type_include() { return (_root && _root->type == node_include); } //Node is INCLUDE. - bool type_pi() { return (_root && _root->type == node_pi); } //Node is a processing instruction. - bool type_doctype() { return (_root && _root->type == node_doctype); } //Node is DOCTYPE. - bool type_dtd_item() { return (_root && _root->type > node_doctype); } //Node is NODE_DTD_*. - bool type_dtd_attlist() { return (_root && _root->type == node_dtd_attlist); } //Node is node_dtd_attlist. - bool type_dtd_element() { return (_root && _root->type == node_dtd_element); } //Node is node_dtd_element. - bool type_dtd_entity() { return (_root && _root->type == node_dtd_entity); } //Node is node_dtd_entity. - bool type_dtd_notation() { return (_root && _root->type == node_dtd_notation); } //Node is node_dtd_notation. - -//Member Inventory -public: - - bool has_value() { return (!empty() && _root->value != 0); } //Node has data (comment, CDATA or PCDATA). - bool has_child_nodes() { return (!empty() && children() > 0); } //Node has 1 or more children. - bool has_attributes() { return (!empty() && attributes() > 0); } //Node has 1 or more attributes. - bool has_siblings() { return (!empty() && siblings() > 0); } //Node has one or more siblings. - bool has_name() { return (!empty() && _root->name != 0); } //Node has a name. - bool has_name(const std::string& name) const { return has_name(name.c_str()); } //Node is named 'name'. - bool has_attribute(const std::string& name) { return has_attribute(name.c_str()); } //Node has an attribute named 'name'. -#ifdef PUGOPT_NONSEG - bool has_name(const TCHAR* name) const { return (name && _root && _root->name && _tcsncmp(_root->name,name,_root->name_size)==0); } //Node is named 'name'. -#else - bool has_name(const TCHAR* name) const { return (name && _root && _root->name && strcmpwild(name,_root->name)==0); } //Node is named 'name'. -#endif - bool has_attribute(const TCHAR* name){ return (mapto_attribute_idx(name) > -1); } //Node has an attribute named name. - -//Member Accessors -public: - -#ifdef PUGOPT_NONSEG - - //Access node name if any. - //Name, or dummy value if the no name. - //Only returns up to 'PUGDEF_ELEM_NAME_SIZE' chars of name. - const TCHAR* name() - { - static TCHAR temp[PUGDEF_ELEM_NAME_SIZE] = {0}; - if(has_name()) - { - _tcsncpy(temp,_root->name,_root->name_size); - temp[_root->name_sizename_size:(PUGDEF_ELEM_NAME_SIZE-1)] = 0; - return temp; - } - return _T(""); - } - unsigned int name_size(){ return (has_name()) ? _root->name_size : 0; } //Get node name length if any, else 0. - unsigned int value_size(){ return (has_value()) ? _root->value_size : 0; } //Get node value length if any, else 0. - inline bool matches_attribute_name(const TCHAR* name,const unsigned int namelen,const int i) const { return (_tcsncmp(name,_root->attribute[i]->name,max(namelen,_root->attribute[i]->name_size))==0); } //There is an attribute at 'i' named 'name'. - inline bool matches_child_name(const TCHAR* name,const unsigned int namelen,const int i) const { return (_tcsncmp(name,_root->child[i]->name,max(namelen,_root->child[i]->name_size))==0); } //There is a child at 'i' named 'name'. - inline bool matches_name(const TCHAR* name,const unsigned int namelen,xml_node_struct* node) const { return (_tcsncmp(name,node->name,max(namelen,node->name_size))==0); } //This is named 'name'. - inline bool matches_value(const TCHAR* data,const unsigned int datalen,xml_node_struct* node) const { return (_tcsncmp(data,node->value,max(datalen,node->value_size))==0); } //This is valued 'value'. - inline bool matches_attribute_name(const TCHAR* name,const unsigned int namelen,xml_attribute_struct* attr) const { return (_tcsncmp(name,attr->name,max(namelen,attr->name_size))==0); } //The given attribute is named 'name'. - inline bool matches_attribute_name_value(const TCHAR* value,const unsigned int valulen,xml_attribute_struct* attr) const { return (_tcsncmp(value,attr->value,max(valulen,attr->value_size))==0); } //The given attribute is valued 'value'. -#else - const TCHAR* name(){ return (has_name()) ? _root->name : _T(""); } //Access pointer to node name if any, else empty string. - inline bool matches_attribute_name(const TCHAR* name,const unsigned int i) const { return (strcmpwild(name,_root->attribute[i]->name)==0); } //There is an attribute at 'i' named 'name'. - inline bool matches_child_name(const TCHAR* name,const unsigned int i) const { return (strcmpwild(name,_root->child[i]->name)==0); } //There is a child at 'i' named 'name'. - inline bool matches_name(const TCHAR* name,xml_node_struct* node) const { return (strcmpwild(name,node->name)==0); } //This is named 'name'. - inline bool matches_value(const TCHAR* data,xml_node_struct* node) const { return (strcmpwild(data,node->value)==0); } //This is valued 'value'. - inline bool matches_attribute_name(const TCHAR* attribute,xml_attribute_struct* attr) const { return (strcmpwild(attribute,attr->name)==0); } //The given attribute is named 'name'. - inline bool matches_attribute_name_value(const TCHAR* value,xml_attribute_struct* attr) const { return (strcmpwild(value,attr->value)==0); } //The given attribute is valued 'value'. -#endif - xml_node_type type() const { return (_root) ? (xml_node_type)_root->type : node_null; } //Access node entity type. - const TCHAR* value() { return (has_value()) ? _root->value : _T(""); } //Access pointer to data if any, else empty string. - unsigned int children() const { return _root->children; } //Access node's child count. - xml_node child(unsigned int i){ return (i < children()) ? xml_node(_root->child[i]) : xml_node(); } //Access child node at subscript as xml_node or xml_node(NULL) if bad subscript. - unsigned int attributes() const { return _root->attributes; } //Access node's attribute count. - xml_attribute attribute(unsigned int i){ return (i < attributes()) ? xml_attribute(_root->attribute[i]) : xml_attribute(); } //Access attribute at subscript if any, else empty attribute. - //Access or create the attribute having 'name'. - //Name of attribute to access/create. - //Reference to xml_attribute wrapper. - xml_attribute attribute(const std::string& name){ return attribute(name.c_str()); } - //Access or create the attribute having 'name'. - //Name of attribute to access/create. - //Reference to xml_attribute wrapper. - xml_attribute attribute(const TCHAR* name) - { - xml_attribute_struct* attr = mapto_attribute_ptr(name); - if(!attr) attr = append_attribute(name,_T("")); - return xml_attribute(attr); - } - const unsigned int siblings(){ return (!type_document()) ? _root->parent->children : 0; } //Access node's sibling count (parent's child count). - xml_node sibling(unsigned int i){ return (!type_document() && i < siblings()) ? xml_node(_root->parent->child[i]) : xml_node(); } //Access sibling node at subscript as xml_node or xml_node(NULL) if bad subscript. - xml_node parent(){ return (!type_document()) ? xml_node(_root->parent) : xml_node(); } //Access node's parent if any, else xml_node(NULL) - - //Return the first child that has data's data. If none, return NULL. - //Returns a copy of the data. - //Specifies the maximum number of characters to copy into value. - //Pointer to value if exists, else NULL. - // - // Used to get the PCDATA for the current element. This handles elements - // like: <LINE><STAGEDIR>Aside</STAGEDIR>Thy father, - // Pompey, would ne'er have</LINE>, where 'this' points to <LINE>. - // - TCHAR* child_value(TCHAR* value,const unsigned int valuelen)const - { - if(_root->children) - { - for(register unsigned int i=0; i < _root->children; ++i) - { - xml_node_struct* node = _root->child[i]; - if(node->value) - { - const unsigned int n = -#ifdef PUGOPT_NONSEG - (std::min)(valuelen,node->value_size); -#else - (std::min)(valuelen,unsigned(_tcslen(node->value))); -#endif - _tcsncpy(value,node->value,n); - value[n] = 0; - break; - } - } - return value; - } - return NULL; - } - -//Name-To-Object Mapping -public: - - //Map an attribute name to a pointer to that attribute, if found. - //Reference to name of attribute to find. - //Pointer to attribute, or NULL if not found. - //Implement your own hash table if you have a great many attributes. - xml_attribute_struct* mapto_attribute_ptr(const std::string& name){ return mapto_attribute_ptr(name.c_str()); } - - //Map an attribute name to a pointer to that attribute, if found. - //Pointer to name of attribute to find. - //Pointer to attribute, or NULL if not found. - //Implement your own hash table if you have a great many attributes. - xml_attribute_struct* mapto_attribute_ptr(const TCHAR* name) - { - if(!_root || !name) return NULL; - register unsigned int n = _root->attributes; -#ifdef PUGOPT_NONSEG - const int namelen = _tcslen(name); -#endif - for(register unsigned int i=0; iattribute[i]; - return NULL; - } - - //Map an attribute name to the index of that attribute, if found. - //Pointer to name of attribute to find. - //Index of attribute, or -1 if not found. - //Implement your own hash table if you have a great many attributes. - int mapto_attribute_idx(const TCHAR* name) - { - if(!_root || !name) return -1; - register unsigned int n = _root->attributes; -#ifdef PUGOPT_NONSEG - const int namelen = _tcslen(name); -#endif - for(register unsigned int i=0; iMap a child name to a pointer to the first instance, if found. - //Reference to name of child to find. - //Index of child, or -1 if not found. - //Implement your own hash table if you have a great many children. - xml_node_struct* mapto_child_ptr(const std::string& name){ return mapto_child_ptr(name.c_str()); } - - //Map a child name to a pointer to the first instance, if found. - //Pointer to name of child to find. - //Index of child, or -1 if not found. - //Implement your own hash table if you have a great many children. - xml_node_struct* mapto_child_ptr(const TCHAR* name) - { - if(!_root || !name) return NULL; - register unsigned int n = _root->children; -#ifdef PUGOPT_NONSEG - const int namelen = _tcslen(name); -#endif - for(register unsigned int i=0; ichild[i]->name && -#ifdef PUGOPT_NONSEG - matches_child_name(name,namelen,i) -#else - matches_child_name(name,i) -#endif - ) - return _root->child[i]; - } - return NULL; - } - - //Map a child name to the index of the first instance, if found. - //Reference to name of child to find. - //Index of child, or -1 if not found. - //Implement your own hash table if you have a great many children. - int mapto_child_idx(const std::string& name){ return mapto_child_idx(name.c_str()); } - - //Map a child name to the index of the first instance, if found. - //Pointer to name of child to find. - //Index of child, or -1 if not found. - //Implement your own hash table if you have a great many children. - int mapto_child_idx(const TCHAR* name) - { - if(!_root || !name) return -1; - register unsigned int n = _root->children; -#ifdef PUGOPT_NONSEG - const int namelen = _tcslen(name); -#endif - for(register unsigned int i=0; ichild[i]->name && -#ifdef PUGOPT_NONSEG - matches_child_name(name,namelen,i) -#else - matches_child_name(name,i) -#endif - ) - return i; - } - return -1; - } - -//Traversal Helpers -public: - - //Find all elements having the given name. - //Reference to name of child to find. - //Reference to xml_node_list or pointer_array to receive the matching elements. - void all_elements_by_name(const std::string& name,pointer_array& found){ all_elements_by_name(name.c_str(),found); } - - //Find all elements having the given name. - //Pointer to name of child to find. - //Reference to xml_node_list or pointer_array to receive the matching elements. - void all_elements_by_name(const TCHAR* name,pointer_array& found) - { - if(empty() || !name) return; //Invalid node, so fail. - if(_root->children > 0) //Has children. - { -#ifdef PUGOPT_NONSEG - const unsigned int namelen = _tcslen(name); -#endif - register unsigned int n = _root->children; //For each child. - for(register unsigned int i=0; ichild[i] && //There is a child at i. - _root->child[i]->name && //The child has a name. -#ifdef PUGOPT_NONSEG - matches_child_name(name,namelen,i) -#else - matches_child_name(name,i) -#endif - ) - found.push_back(_root->child[i]); //push_back it to the array. - if(_root->child[i]->children) //If there are children. - { - xml_node subsearch(_root->child[i]); //Wrap it up for ease. - subsearch.all_elements_by_name(name,found); //Find any matching children. - } - } - } - } - - // - // Recursively-implemented depth-first find the first matching element. - // Use for shallow drill-downs. - // - //Const reference to name of element to find. - //Valid xml_node if such element named 'name' is found. - //xml_node may be invalid if not found; test with 'empty'. - xml_node first_element_by_name(const std::string& name){ return first_element_by_name(name.c_str()); } - - // - // Recursively-implemented depth-first find the first matching element. - // Use for shallow drill-downs. - // - //Pointer to name of element to find. - //Valid xml_node if such element named 'name' is found. - //xml_node may be invalid if not found; test with 'empty'. - xml_node first_element_by_name(const TCHAR* name) - { - if(empty() || !name) return xml_node(); //Invalid node, so fail. - if(_root->children > 0) //Has children. - { - register unsigned int n = _root->children; //For each child. -#ifdef PUGOPT_NONSEG - const int namelen = _tcslen(name); -#endif - for(register unsigned int i=0; ichild[i]->name && -#ifdef PUGOPT_NONSEG - matches_child_name(name,namelen,i) -#else - matches_child_name(name,i) -#endif - ) - return xml_node(_root->child[i]); - else if(_root->child[i]->children) - { - xml_node subsearch(_root->child[i]); //Wrap it up for ease. - xml_node found = subsearch.first_element_by_name(name); - if(!found.empty()) return found; //Found. - } - } - } - return xml_node(); //Not found. - } - - // - // Recursively-implemented depth-first find the first matching element - // also having matching PCDATA. - // - //Reference to name of element to find. - //Reference to PCDATA to find. - //Valid xml_node if such element named 'name' is found with PCDATA 'value'. - //xml_node may be invalid if not found; test with 'empty'. - xml_node first_element_by_value(const std::string& name,const std::string& value){ return first_element_by_value(name.c_str(),value.c_str()); } - - // - // Recursively-implemented depth-first find the first matching element - // also having matching PCDATA. - // - //Pointer to name of element to find. - //Pointer to PCDATA to find. - //Valid xml_node if such element named 'name' is found with PCDATA 'value'. - //xml_node may be invalid if not found; test with 'empty'. - xml_node first_element_by_value(const TCHAR* name,const TCHAR* value) - { - if(empty() || !name || !value) return xml_node(); //Invalid node, so fail. - if(_root->children > 0) //Has children. - { - register unsigned int n = _root->children; //For each child. -#ifdef PUGOPT_NONSEG - const unsigned int namelen = _tcslen(name); - const unsigned int valulen = _tcslen(value); -#endif - for(register unsigned int i=0; ichild[i] && //There is a child at i. - _root->child[i]->name && //The child has a name. -#ifdef PUGOPT_NONSEG - matches_child_name(name,namelen,i) -#else - matches_child_name(name,i) -#endif - ) - { - register unsigned int m = _root->child[i]->children; //For each child of child. - for(register unsigned int j=0; jchild[i]->child[j] && //There is a child at j. - _root->child[i]->child[j]->type == node_pcdata && //It is of the PCDATA type. - _root->child[i]->child[j]->value && //It has data. -#ifdef PUGOPT_NONSEG - matches_value(value,valulen,_root->child[i]->child[j]) -#else - matches_value(value,_root->child[i]->child[j]) -#endif - ) - return xml_node(_root->child[i]); //Wrap it up and return. - } - } - else if(_root->child[i] && _root->child[i]->children) //The child has children. - { - xml_node subsearch(_root->child[i]); //Wrap it up for ease. - xml_node found = subsearch.first_element_by_value(name,value); //Search any children. - if(!found.empty()) return found; //Found. - } - } - } - return xml_node(); //Not found. - } - - // - // Recursively-implemented depth-first find the first matching element - // also having matching attribute. - // - //Reference to name of element to find. - //Reference to name of attribute to find. - //Reference to attribute value to find. - //Valid xml_node if such element named 'name' is found. - //xml_node may be invalid if not found; test with 'empty'. - xml_node first_element_by_attribute(const std::string& name,const std::string& attr_name,const std::string& attr_value){ return first_element_by_attribute(name.c_str(),attr_name.c_str(),attr_value.c_str()); } - - // - // Recursively-implemented depth-first find the first matching element - // also having matching attribute. - // - //Pointer to name of element to find. - //Pointer to name of attribute to find. - //Pointer to attribute value to find. - //Valid xml_node if such element named 'name' is found. - //xml_node may be invalid if not found; test with 'empty'. - xml_node first_element_by_attribute(const TCHAR* name,const TCHAR* attr_name,const TCHAR* attr_value) - { - if(empty() || !name || !attr_name || !attr_value) return xml_node(); //Invalid data, so fail. - if(_root->children > 0) //Has children. - { -#ifdef PUGOPT_NONSEG - const unsigned int namelen = _tcslen(name); - const unsigned int attrlen = _tcslen(attr_name); - const unsigned int valulen = _tcslen(attr_value); -#endif - register unsigned int n = _root->children; //For each child. - for(register unsigned int i=0; ichild[i] && //There is a child at i. - _root->child[i]->name && //The child has a name. -#ifdef PUGOPT_NONSEG - matches_name(name,namelen,_root->child[i]) -#else - matches_name(name,_root->child[i]) -#endif - ) - { - register unsigned int m = _root->child[i]->attributes; //For each attribute of child. - for(register unsigned int j=0; jchild[i]->attribute[j] && //There is an attribute at j. - _root->child[i]->attribute[j]->name && //The attribute has a name. -#ifdef PUGOPT_NONSEG - matches_attribute_name(attr_name,attrlen,_root->child[i]->attribute[j]) && -#else - matches_attribute_name(attr_name,_root->child[i]->attribute[j]) && -#endif - _root->child[i]->attribute[j]->value && //The attribute has a value. -#ifdef PUGOPT_NONSEG - matches_attribute_name_value(attr_value,valulen,_root->child[i]->attribute[j]) -#else - matches_attribute_name_value(attr_value,_root->child[i]->attribute[j]) -#endif - ) - return xml_node(_root->child[i]); //Wrap it up and return. - } - } - else if(_root->child[i] && _root->child[i]->children) - { - xml_node subsearch(_root->child[i]); //Wrap it up for ease. - xml_node found = subsearch.first_element_by_attribute(name,attr_name,attr_value); //Search any children. - if(!found.empty()) return found; //Found. - } - } - } - return xml_node(); //Not found. - } - - // - // Recursively-implemented depth-first find the first matching entity. - // Use for shallow drill-downs. - // - //Pointer to name of element to find. - //Valid xml_node if such element named 'name' is found. - //xml_node may be invalid if not found; test with 'empty'. - xml_node first_node(xml_node_type type) - { - if(!_root) return xml_node(); - if(_root->children > 0) //Has children. - { - register unsigned int n = _root->children; //For each child. - for(register unsigned int i=0; ichild[i]->type==type) - return xml_node(_root->child[i]); - else if(_root->child[i]->children) - { - xml_node subsearch(_root->child[i]); - xml_node found = subsearch.first_node(type); - if(!found.empty()) return found; //Found. - } - } - } - return xml_node(); //Not found. - } - - //Move to the absolute root of the document tree. - //True if the current node is valid. - //Member '_root' may now point to absolute root of the document. - bool moveto_root() - { - if(empty()) return false; //Nowhere to go. - while(!type_document()) _root = _root->parent; //Keep stepping out until we hit the root. - return true; //Success. - } - - //Move to the current node's parent. - //true if there is a parent and cursor is not parent, and cursor points thereto. - //'_root' may now point to parent. - bool moveto_parent() - { - if(empty() || type_document()) return false; //Invalid, or at the root (has no parent). - _root = _root->parent; //Move to parent. - return true; //Success. - } - - // - // Move to the current node's sibling at subscript. Equivalent to - // 'moveto_child' following 'moveto_parent'. - // - //Subscript of sibling to move cursor to. - //True if valid subscript, and cursor points thereto. - //If matching co-node was found, '_root' points thereto. - bool moveto_sibling(unsigned int i) - { - if(empty()) return false; //Nowhere to go. - xml_node_struct* restore = _root; //Save position in case invalid subscript & we want to restore. - if(moveto_parent()) //Try to move to parent. - { - if(i < children()) //Subscript is in range. (Assume parent *does* have children.) - { - _root = _root->child[i]; //Move to child at subscript ('sibling'). - return true; //Success. - } - } - _root = restore; //Bad subscript, or parent move; restore. - return false; - } - - //Move to the current node's first sibling matching given name. - //Element name of sibling to move to. - //True if sibling was found, and cursor points thereto. - //If matching co-node was found, '_root' points thereto. - bool moveto_first_sibling(const std::string& name){ return moveto_first_sibling(name.c_str()); } - - //Move to the current node's first sibling matching given name. - //Element name of sibling to move to. - //True if sibling was found, and cursor points thereto. - //If matching co-node was found, '_root' points thereto. - bool moveto_first_sibling(const TCHAR* name) - { - if(empty() || !name) return false; //Nowhere to go, or nothing to find. - xml_node_struct* restore = _root; //Save position in case invalid subscript & we want to restore. - if(moveto_parent()) //Try to move to parent. - { -#ifdef PUGOPT_NONSEG - const unsigned int namelen = _tcslen(name); -#endif - register unsigned int n = children(); //Search for matching name - for(register unsigned int i=0; iMove to the current node's child at subscript. - //Subscript of child to move cursor to. - //true if valid subscript, and cursor points thereto. - //If matching sub-node was found, '_root' points thereto. - bool moveto_child(unsigned int i) - { - if(empty()) return false; //Null, so no children. - if(has_child_nodes() && i < children()) //Has children and subscript is in bounds. - { - _root = child(i); //Move to the child at i. - return true; //Success. - } - return false; //Failure. - } - - //Move to the current node's child matching given name. - //Element name of child to move to if found. - //True if child was found, and cursor points thereto. - //If matching sub-node was found, '_root' points thereto. - bool moveto_child(const std::string& name){ return moveto_child(name.c_str()); } - - //Move to the current node's child matching given name. - //Element name of child to move to if found. - //True if child was found, and cursor points thereto. - //If matching sub-node was found, '_root' points thereto. - bool moveto_child(const TCHAR* name) - { - if(empty() || !name || !has_child_nodes()) return false; //The node is null, a name was not specified, or node has no children. -#ifdef PUGOPT_NONSEG - const unsigned int namelen = _tcslen(name); -#endif - register unsigned int n = children(); //For each child. - for(register unsigned int i=0; iMove to the current node's next sibling by position and name. - //Name of sibling to move to if found. - //True if there is a next sibling, and cursor points thereto. - bool moveto_next_sibling(const std::string& name){ return moveto_next_sibling(name.c_str()); } - - //Move to the current node's next sibling by position and name. - //Name of sibling to move to if found. - //True if there is a next sibling, and cursor points thereto. - bool moveto_next_sibling(const TCHAR* name) - { - if(empty() || type_document() || !_root->parent || !name) return false; //Null, or at root, or no name, so there are no valid matches. -#ifdef PUGOPT_NONSEG - const unsigned int namelen = _tcslen(name); -#endif - register unsigned int n = _root->parent->children; //For each child of parent. - for(register unsigned int i=0; i<(n-1); ++i) - { - if - ( - _root->parent->child[i] && //There is a child at i. - _root->parent->child[i] == _root && //The child is identical with this node. - i < (n-1) //This is not the last child. - ) - { - for(++i; iparent->child[i] && //There is a child at i. - _root->parent->child[i]->name && //The child's name is not null. -#ifdef PUGOPT_NONSEG - matches_name(name,namelen,_root->parent->child[i]) -#else - matches_name(name,_root->parent->child[i]) -#endif - ) - { - moveto_sibling(i); //Move to it. - return true; //Success. - } - } - } - } - return false; //Failure. - } - - //Move to the current node's next sibling by position. - //True if there is a next sibling, and cursor points thereto. - bool moveto_next_sibling() - { - if(empty() || type_document() || !_root->parent) return false; //Null or at root, so there are no valid siblings. - register unsigned int n = _root->parent->children; //For each child of parent (each sibling). - for(register unsigned int i=0; i<(n-1); ++i) - { - if - ( - _root->parent->child[i] && //There is a child at i. - _root->parent->child[i] == _root && //The child is identical with this node. - i < (n-1) //This is not the last child. - ) - { - for(++i; iparent->child[i]) //There is a child at i. - { - moveto_sibling(i); //Move to it. - return true; //Success. - } - } - } - } - return false; //Failure. - } - - //Compile the absolute node path from root as a text string. - //Delimiter string to insert between element names. - //Path string (e.g. with '/' as delimiter, '/document/.../this'. - std::string path(const TCHAR* delimiter = _T("/")) - { - TCHAR* path = NULL; //Current path. - TCHAR* temp; //Temporary pointer. - xml_node cursor = *this; //Make a copy. -#ifdef PUGOPT_NONSEG - unsigned int destlen = 0; - strcatgrown_impl(&path,cursor.name(),destlen,cursor.name_size()); //Get this name. -#else - strcatgrow(&path,cursor.name()); //Get this name. -#endif - while(cursor.moveto_parent() && !cursor.type_document()) //Loop to parent (stopping on actual root because it has no name). - { - temp = NULL; //Mark as null so 'strcatgrow' will allocate memory. -#ifdef PUGOPT_NONSEG - destlen = 0; - strcatgrown_impl(&temp,cursor.name(),destlen,cursor.name_size()); //Append next element name. -#else - strcatgrow(&temp,cursor.name()); //Append next element name. -#endif - strcatgrow(&temp,delimiter); //Append delimiter. - strcatgrow(&temp,path); //Append current path. - free(path); //Free the old path. - path = temp; //Set path as new string. - } - temp = NULL; - strcatgrow(&temp,delimiter); //Prepend final delimiter. - strcatgrow(&temp,path); //Append current path. - free(path); //Free the old path. - std::string returns = temp; //Set path as new string. - free(temp); - return returns; //Return the path; - } - - //Search for a node by path. - // - // Path string; e.g. './foo/bar' (relative to node), '/foo/bar' (relative - // to root), '../foo/bar' (pop relative position). - // - //Delimiter string to use in tokenizing path. - //Matching node, or xml_node(NULL) if not found. - xml_node first_element_by_path(const std::string& path,const std::string& delimiter = _T("/")){ return first_element_by_path(path.c_str(),delimiter.c_str()); } - - //Search for a node by path. - // - // Path string; e.g. './foo/bar' (relative to node), '/foo/bar' (relative - // to root), '../foo/bar' (pop relative to position). - // - //Delimiter string to use in tokenizing path. - //Matching node, or xml_node(NULL) if not found. - //To-do: Support XPath-style queries. - xml_node first_element_by_path(const TCHAR* path,const TCHAR* delimiter = _T("/")) - { - if(!path) return xml_node(); - TCHAR* temp = NULL; - pointer_array path_segments; //Array of path segments. - xml_node found = *this; //Current search context. - strcatgrow(&temp,path); - TCHAR* name = _tcstok(temp,delimiter); - while(name) //Tokenize the whole path. - { - path_segments.push_back((void*)name); //push_back it to array. - name = _tcstok(NULL,delimiter); //Get the next token, - } - register unsigned int n = path_segments.size(); - if(n == 0) return xml_node(); //Return null node if no path segments. - if(path[0]==delimiter[0]) found.moveto_root(); //Absolute path; e.g. '/foo/bar' - for(register unsigned int i = 0; i 0) --i; //Try the previous path segment. - goto NEXT_ELEM; - } - else //Move to parent to search further. - { - if(!found.type_document() && found.moveto_parent() && !found.type_document()) //Not root and stepped to parent and parent is not root. - { - if(i > 0) --i; //Try the previous path segment. - if(found.moveto_next_sibling(found.name())) //Try to find next sibling having same name. - { - if(i > 0) --i; //Try the previous path segment. - goto NEXT_ELEM; - } - } - } - } - } -NEXT_ELEM:; - if(found.type_document()) //Can't move up any higher, so fail. - { - free(temp); //Got to free this. - return xml_node(); //Return null node. - } - } - free(temp); //Got to free this. - return found; //Return the matching node. - } - - //Recursively traverse the tree. - //Reference to tree walker derived from xml_tree_walker. - //True if traversal was not halted by xml_tree_walker::for_each() callback. - bool traverse(xml_tree_walker& walker) - { - if(walker.depth() == 0 && !walker.begin(*this)) return false; //Send the callback for begin traverse if depth is zero. - if(!empty()) //Don't traveres if this is a null node. - { - walker.push(); //Increment the walker depth counter. - register unsigned int n = _root->children; //For each child. - for(register unsigned int i=0; ichild[i]) //There is a child at i. - { - xml_node subsearch(_root->child[i]); //Wrap it. - if(!(walker.for_each(subsearch) && subsearch.traverse(walker))) - return false; //Traversal was aborted. - } - } - walker.pop(); //Decrement the walker depth counter. - } - if(walker.depth() == 0 && !walker.end(*this)) return false; //Send the callback for end traverse if depth is zero. - return true; - } - -//Editorial Helpers -public: - - //Set element name. - //New element name. - //Success. - bool name(const std::string& new_name){ return name(new_name.c_str()); } - - //Set element name. - //New element name. - //Success. - bool name(const TCHAR* new_name) - { - if((type_element() || type_pi()) && new_name) -#ifdef PUGOPT_NONSEG - return strcpyinsitu(&_root->name,new_name,&_root->name_insitu,_root->name_size ); -#else - return strcpyinsitu(&_root->name,new_name,&_root->name_insitu); -#endif - return false; - } - - //Set node data. - //New data (PCDATA, CDATA, or comment) value. - //Success. - bool value(const std::string& new_value){ return value(new_value.c_str()); } - - //Set node data. - //New data (PCDATA, CDATA, or comment) value. - //Success. - bool value(const TCHAR* new_value) - { - if((type_pcdata() || type_cdata() || type_comment()) && new_value) -#ifdef PUGOPT_NONSEG - return strcpyinsitu(&_root->value,new_value,&_root->value_insitu,_root->value_size); -#else - return strcpyinsitu(&_root->value,new_value,&_root->value_insitu); -#endif - return false; - } - - //Remove attribute at the given subscript. - //Subscript. - //Success. - bool remove_attribute(unsigned int i) - { - unsigned int n = _root->attributes; - if(i < n) - { - xml_attribute_struct* temp = _root->attribute[i]; - --n; - for(unsigned int j=i; jattribute[j] = _root->attribute[j+1]; - _root->attribute[n] = NULL; - if(!temp->name_insitu) free(temp->name); - if(!temp->value_insitu) free(temp->value); - free(temp); - --_root->attributes; - return true; - } - return false; - } - - //Remove attribute having the given name. - //Name of attribute to delete. - //Success. - bool remove_attribute(const std::string& name){ return remove_attribute(name.c_str()); } - - //Remove attribute having the given name. - //Name of attribute to delete. - //Success. - bool remove_attribute(const TCHAR* name) - { - int i = mapto_attribute_idx(name); - if(i > -1) return remove_attribute((unsigned int)i); - return false; - } - - //Append a new attribute to the node list of attributes. - //Name. - //Value thereof. - //Attribute structure wrapper. - //Pointer space may be grown, memory for name/value members allocated. - xml_attribute append_attribute(const std::string& name,const std::string& value){ return append_attribute(name.c_str(),value.c_str()); } - - //Append a new attribute to the node list of attributes. - //Name. - //Value thereof. - //Attribute structure wrapper. - //Pointer space may be grown, memory for name/value members allocated. - xml_attribute append_attribute(const TCHAR* name,const TCHAR* value) - { - if(!name || !value) return xml_attribute(); //We must have both to proceed. - xml_attribute_struct* p = pug::append_attribute(_root,1); //Append/allocate a new attribute structure. - if(p) //If append/allocate succeeded. - { -#ifdef PUGOPT_NONSEG - strcatgrown(&p->name,name,p->name_size); //Append the name. - strcatgrown(&p->value,value,p->value_size); //Append the name. -#else - strcatgrow(&p->name,name); //Append the name. - strcatgrow(&p->value,value); //Append the name. -#endif - p->name_insitu = p->value_insitu = false; //Mark as not part of original parse string. - return xml_attribute(p); //Success. - } - return xml_attribute(); //Failure; return an empty. - } - - //Append a new attribute of type long to the node list of attributes. - //Name. - //Value thereof. - //Attribute structure wrapper. - //Pointer space may be grown, memory for name/value members allocated. - xml_attribute append_attribute(const TCHAR* name,long value) - { - if(!name) return false; - TCHAR temp[32] = {0}; - _stprintf(temp,_T("%ld"),value); - return append_attribute(name,temp); - } - - //Append a new attribute of type double to the node list of attributes. - //Name. - //Value thereof. - //Attribute structure wrapper. - //Pointer space may be grown, memory for name/value members allocated. - xml_attribute append_attribute(const TCHAR* name,double value) - { - if(!name) return false; - TCHAR temp[32] = {0}; - _stprintf(temp,_T("%lf"),value); - return append_attribute(name,temp); - } - - //Append a new attribute of type bool to the node list of attributes. - //Name. - //Value thereof. - //Attribute structure wrapper. - //Pointer space may be grown, memory for name/value members allocated. - xml_attribute append_attribute(const TCHAR* name,bool value) - { - if(!name) return false; - return append_attribute(name,((value)?_T("true"):_T("false"))); - } - - //Set the current node entity type. - //New type to set. - //Previous type. - //If has children and now is not node_element, children are obscured. - xml_node_type type(xml_node_type new_type) - { - xml_node_type prev = _root->type; //Save old type. - _root->type = new_type; //Set new type. - return prev; //Return old type. - } - - // - // Allocate & append a child node of the given type at the end of the - // current node array of children. - // - //New child node type. - //xml_node wrapping the new child. - //Pointer space may be grown. An xml_node_struct structure is allocated. - xml_node append_child(xml_node_type type) - { - if(type_document()||type_element()) //Don't do anything if not an node_element or root. - { - xml_node_struct* p = pug::append_node(_root,1,type); //Append the node. - if(p) - { - p->name_insitu = p->value_insitu = false; - return xml_node(p); //If we have it, return wrapped. - } - } - return xml_node(); //Return dummy. - } - - //Allocate & insert a child node of the given type at subscript. - //Subscript at which to insert. - //New child node type. - //xml_node wrapping the new child. - // - // Pointer space may be grown. An xml_node_struct structure is allocated, - // and existing children are shifted in their array position. - // - xml_node insert_child(unsigned int i,xml_node_type type) - { - if(!type_element()) return xml_node(); //Don't do anything if not an node_element. - unsigned int n = _root->children; //Get count of existing children. - if(type_element() && i >= n) return append_child(type); //If subscript at end of array then just append. - else if(type_element() && i < n) - { - xml_node_struct* p = pug::append_node(_root,1,type); //Append the new node (by default at last array position). - if(p) //Ensure we have it. - { - register int m = (i-1); //Stop at i. - for(register int j=(n-1); j>m; --j) //Starting at one less than end of array, reverse loop to i. - _root->child[j+1] = _root->child[j]; //Shift node to right. - _root->child[i] = p; //Set node at subscript to new node. - return xml_node(p); //Return new node. - } - } - return xml_node(); //Return dummy. - } - - //Delete the child node at the given subscript. - //Subscript. - //Success. - //Shifts child array element positions. Frees entire tree under child to be deleted. - bool remove_child(unsigned int i) - { - unsigned int n = _root->children; - if(i < n) //Ensure subscript is in bounds. - { - xml_node_struct* p = _root->child[i]; //Keep a pointer to this node so we can free it. - --n; - unsigned int j; - for(j=i; jchild[j] = _root->child[j+1]; - _root->child[j] = NULL; //Mark the last element null. - --_root->children; //One less children. - p->parent = p; //This ensures we only free this node when calling 'free_node'. - pug::free_node(p); //Free the node tree. - return true; //Success. - } - return false; //Failure. - } - - //Stream/Output Helpers -public: - - // - // Stream output. Recursively writes the internal xml_node_struct structure - // to the given stream. - // - //Reference to output stream. - //Char to use for indent. - //Use linebreaks? - //String data is written to stream. - void outer_xml(std::basic_ostream >& os,TCHAR indent_char = _T('\t'),bool breaks = true) - { - if(empty()) return; //Make sure there is something to output. - indent_stack indent(indent_char); //Prepare the indent. - if(type_document()) //If this is the root, we don't want to output the root itself. - { - register unsigned int n = _root->children; //Output each child of the root. - for(register unsigned int i=0; ichild[i],breaks); - } - else pug::outer_xml(os,indent,_root,breaks); //Output the node. - } - - // - // Stream output operator. Wraps 'outer_xml'. Recursively writes - // the given node to the given stream. - // - //Reference to output stream. - //Reference to tree node. - //Reference to output stream. - //String data is written to stream. - friend std::basic_ostream >& operator<<(std::basic_ostream >& os,xml_node node) - { - if(!os.good()) return os; - if((os.flags()|std::ostream::skipws) == std::ostream::skipws) - node.outer_xml(os,0,false); //Skipping whitespace; suppress indents & linebreaks. - else node.outer_xml(os); //Default options. - return os; - } -}; - - -//Provides a high-level interface to the XML parser. -class xml_parser -{ -//Internal Data Members -protected: - - xml_node_struct* _xmldoc; //Pointer to current XML document tree root. - long _growby; //Attribute & child pointer space growth increment. - bool _autdel; //Delete the tree on destruct? - TCHAR* _buffer; //Pointer to in-memory buffer (for 'parse_file'). - TCHAR* _strpos; //Where parsing left off (for 'parse_file'). - unsigned long _optmsk; //Parser options. -#ifdef PUGOPT_MEMFIL - HANDLE _mmfile; //File handle. - HANDLE _mmfmap; //Handle which maps the file. - void* _mmaddr; //Base address of map. - size_t _mfsize; //Size of memory-mapped file. - bool _addeos; //True if we had to add a 0 to then end of the file. -#endif - -//Construction/Destruction -public: - - //Constructor. - //Options mask. - //Delete tree on destruct? - //Parser pointer space growth increment. - //Root node structure is allocated. - xml_parser(unsigned long optmsk = parse_default,bool autdel = true,long growby = parse_grow): - _xmldoc(0), - _growby(growby), - _autdel(autdel), - _optmsk(optmsk), - _buffer(0), - _strpos(0) -#ifdef PUGOPT_MEMFIL - , - _mmfile(0), - _mmfmap(0), - _mmaddr(0), - _mfsize(0), - _addeos(false) -#endif - { - } - - //Direct parse constructor. - // - // XML-formatted string to parse. Note: String must persist for the - // life of the tree. String is zero-segmented, but not freed. - // - //Parser options. - //Delete tree on destruct? - //Parser pointer space growth increment. - //Root node structure is allocated, string is parsed & tree may be grown. - xml_parser(TCHAR* xmlstr,unsigned long optmsk = parse_default,bool autdel = true,long growby = parse_grow) : - _xmldoc(0), - _growby(growby), - _autdel(autdel), - _optmsk(optmsk), - _buffer(0), - _strpos(0) -#ifdef PUGOPT_MEMFIL - , - _mmfile(0), - _mmfmap(0), - _mmaddr(0), - _mfsize(0), - _addeos(false) -#endif - { - parse(xmlstr,_optmsk); //Parse it. - } - - //Destructor. - //Tree memory and string memory may be freed. - virtual ~xml_parser() - { - if(_autdel && _xmldoc) free_node(_xmldoc); - if(_buffer) free(_buffer); -#ifdef PUGOPT_MEMFIL - close_memfile(); -#endif - } - -//Accessors/Operators -public: - - operator xml_node_struct*() { return _xmldoc; } //Cast as xml_node_struct pointer to root. - operator xml_node() { return xml_node(_xmldoc); } //Cast as xml_node (same as document). - xml_node document(){ return xml_node(_xmldoc); } //Returns the root wrapped by an xml_node. - -//Miscellaneous -public: - - //Allocate a new, empty root. - //Tree memory and string memory may be freed. - void create() - { - clear(); //Free any allocated memory. - _xmldoc = new_node(node_document); //Allocate a new root. - _xmldoc->parent = _xmldoc; //Point to self. - } - - //Clear any existing tree or string. - //Tree memory and string memory may be freed. - void clear() - { - if(_xmldoc){ free_node(_xmldoc); _xmldoc = 0; } - if(_buffer){ free(_buffer); _buffer = 0; } -#ifdef PUGOPT_MEMFIL - close_memfile(); -#endif - } - -#ifdef PUGOPT_MEMFIL - -//Memory-Mapped File Support -protected: - - //Closes any existing memory-mapped file. - void close_memfile() - { - if(_mmaddr != 0) - { - UnmapViewOfFile(_mmaddr); - _mmaddr = 0; - } - if(_mmfmap != 0) - { - CloseHandle(_mmfmap); - _mmfmap = 0; - } - if(_mmfile != 0) - { - if(_addeos) //Remove the 0 we added to the end of the file. - { - SetFilePointer(_mmfile,_mfsize,NULL,FILE_BEGIN); - SetEndOfFile(_mmfile); - _addeos = false; - } - CloseHandle(_mmfile); - _mmfile = 0; - } - _mfsize = 0; - } - -public: - -#endif - - //Attach an externally-generated root to the parser. - //Pointer to node structure. - //Pointer to old root if any. - //New root may be deleted on dtor if autodelete set. - xml_node_struct* attach(xml_node_struct* root) - { - xml_node_struct* t = _xmldoc; //Save this root. - _xmldoc = root; //Assign. - _xmldoc->parent = _xmldoc; //Ensure we are the root. - return t; //Return the old root if any. - } - - //Detach the current root from the parser. - //Pointer to old root, if any. - xml_node_struct* detach() - { - xml_node_struct* t = _xmldoc; //Save this root. - _xmldoc = 0; //So we don't delete later on if autodelete set. - return t; //Return the old root if any. - } - - //Get parser optsions mask. - //Options mask. - unsigned long options(){ return _optmsk; } - - //Set parser options mask. - //Options mask to set. - //Old options mask. - unsigned long options(unsigned long optmsk) - { - unsigned long prev = _optmsk; - _optmsk = optmsk; - return prev; - } - - //Get pointer space growth size increment. - //Grow size. - unsigned long growby(){ return _growby; } - - //Set pointer space growth size increment. - //Grow size to set. - //Old size. - unsigned long growby(long grow) - { - long prev = _growby; - _growby = grow; - return prev; - } - - //Get parse file buffer last string position. - //Last string position. - // - // Use after parse_file, with parse_dtd_only set in order to recommence - // parse of document body. - // - TCHAR* strpos() - { - return _strpos; - } - -//Parsing Helpers -public: - - //Parse the given XML string in-situ. - //Pointer to XML-formatted string. - //Parser options mask. - //Last string position or null. - //Input string is zero-segmented. - TCHAR* parse(TCHAR* s,unsigned long optmsk = parse_noset) - { - if(!s) return s; - clear(); //Free any allocated memory. - _xmldoc = new_node(node_document); //Allocate a new root. - _xmldoc->parent = _xmldoc; //Point to self. - if(optmsk != parse_noset) _optmsk = optmsk; - return pug::parse(s,_xmldoc,_growby,_optmsk); //Parse the input string. - } - - /* - //Load into memory and parse the contents of the file at the given path. - //File path. - //Parser options. - //Success if the file was loaded. - // - // The file contents is loaded and stored in the member '_buffer' until - // freed by calling 'Parse', 'parse_file', 'clear' or '~xml_parser'. - // - bool parse_file(const TCHAR* path,unsigned long optmsk = parse_noset) - { - if(!path) return false; - clear(); //clear any existing data. - unsigned long bytes; - if(optmsk != parse_noset) _optmsk = optmsk; - if(load_file(path,&_buffer,&bytes) && bytes > 0) - { - _xmldoc = pug::new_node(node_document); - _xmldoc->parent = _xmldoc; //Point to self. - TCHAR* s = pug::parse(_buffer,_xmldoc,_growby,_optmsk); - _strpos = s; - return true; - } - return false; - } - */ - -#ifdef PUGOPT_MEMFIL - - //Parse the contents of the file at the given path, using a memory-mapped file. - //File path. - //Parser options. - // - // True (1) if the file was parsed successfully, false (0) if open failed, - // and -1 if an exception occured. - // - // - // The file contents are available until closed by calling 'parse', - // 'parse_file', 'clear' or '~xml_parser'. - // - int parse_mmfile(const TCHAR* path,unsigned long optmsk = parse_noset) - { - int status = 0; - if(path) - { - clear(); //Clear any existing data. - if(optmsk != parse_noset) _optmsk = optmsk; - assert((optmsk & parse_wnorm) == 0); //Normalization isn't implemented for memory-mapped files, as of 23 Jan 2003. - const bool readonly = (optmsk & (parse_dtd|parse_dtd_only)) == 0; - if(open_mmfile(path,readonly,false)) - { - //If the file has a 0 at the end we are ok to proceed, otherwise add one. - if - ( - ( - *(((TCHAR*)_mmaddr) + _mfsize) == 0 - || - ( - _mfsize > 0 && - *(((TCHAR*)_mmaddr) + _mfsize - 1) == 0 - ) - ) - || - open_mmfile(path,false,true) //Re-open and add 0 at EOF. - ) - { - try - { - _xmldoc = new_node(node_document); - _xmldoc->parent = _xmldoc; //Point to self. - TCHAR* s = pug::parse((TCHAR*)_mmaddr,_xmldoc,_growby,_optmsk); - _strpos = s; - status = 1; - } - catch(...) - { - status = -1; - assert(false); - } - } - } - } - return status; - } - -protected: - - //Opens the specified memory-mapped file. - //File path. - //True to open the file for read-only access. - //True to add a 0 to the end of the file. - //Success if the file was opened. - bool open_mmfile(const TCHAR* path,const bool readonly,const bool addeos) - { - clear(); //Close any existing MMF and clear any existing data. - assert(_mmfile == NULL && _mmfile == NULL && _mmaddr == NULL); - _addeos = false; - _mmfile = CreateFile(path,readonly?GENERIC_READ:GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); //Open read-only, no share, no security attrs, ..., no template. - if(_mmfile != INVALID_HANDLE_VALUE) - { - _mfsize = ::GetFileSize(_mmfile,NULL); - _mmfmap = CreateFileMapping(_mmfile,NULL,readonly?PAGE_READONLY:PAGE_READWRITE,0,_mfsize+(addeos?sizeof(TCHAR):0),NULL); //Create map: handle, no security attr, read|read/write, larger if addeos, anonymous. - if(_mmfmap != NULL) - { - assert(_mmaddr == NULL); - _mmaddr = MapViewOfFile(_mmfmap,readonly?FILE_MAP_READ:FILE_MAP_WRITE,0,0,0); //Map the view: handle, read|read/write, start at beginning, map entire file. - if(_mmaddr != NULL) - { - if(addeos) //Add a terminating 0 to the end of the file for 'parse()'. - { - assert(!readonly); - *(((TCHAR*)_mmaddr) + _mfsize) = 0; - _addeos = true; - } - } - else - { - CloseHandle(_mmfmap); - CloseHandle(_mmfile); - _mmfile = _mmfmap = 0; - } - } - else - { - CloseHandle(_mmfile); - _mmfile = 0; - } - } - return (_mmaddr != NULL); - } - -#endif - -}; - - -//An array of nodes, used by xml_node queries. -class xml_node_list: public pointer_array -{ -public: - xml_node_list(unsigned int grow = 4) : pointer_array(grow) { } - virtual ~xml_node_list(){ } -public: - xml_node at(long i){ return xml_node((xml_node_struct*)pointer_array::at((unsigned int)i)); } //Access xml_node at subscript. - xml_node operator[](long i){ return xml_node((xml_node_struct*)pointer_array::at((unsigned int)i)); } //Access xml_node at subscript. - friend std::ostream& operator<<(std::ostream& os,xml_node_list& list) //Output helper. - { - if(!os.good()) return os; - unsigned int n = list.size(); - for(unsigned int i=0; i - template - std::string data_to_string(const std::basic_string &data) - { - return narrow(data.c_str()); - } - - template - struct array_to_pointer_decay - { - typedef T type; - }; - - template - struct array_to_pointer_decay - { - typedef const T *type; - }; - - //////////////////////////////////////////////////////////////////////////// - // Extractor - - // Various specializations of extractors and inserters are provided to: - // 1. Optimize use of strings by copying them directly instead through stringstream - // 2. Optimize use of native char (i.e the same char as used by data string) by copying - // it directly instead of through stringstream - // 3. Treat signed and unsigned chars as integers, not as characters, i.e. - // pt.put_value(signed char(65)) produces data equal to "65", instead of "A". - // Only plain char is treated as a character type, i.e pt.put_value(char(65)) will - // produce "A" - // 4. Allow recognizing various bool strings (0, 1, true, false) - - template - struct extractor - { - inline bool operator()(const std::basic_string &data, - T &extracted, - const std::locale &loc) const - { - std::basic_istringstream stream(data); - stream.imbue(loc); - stream >> extracted; - if (!stream.eof()) - stream >> std::ws; - return stream.eof() && !stream.fail() && !stream.bad(); - } - }; - - template - struct extractor > - { - inline bool operator()(const std::basic_string &data, - std::basic_string &extracted, - const std::locale &loc) const - { - extracted = data; - return true; - } - }; - - template - struct extractor - { - inline bool operator()(const std::basic_string &data, - Ch &extracted, - const std::locale &loc) const - { - if (data.size() == 1) - { - extracted = data[0]; - return true; - } - else - return false; - } - }; - - template - struct extractor - { - inline bool operator()(const std::basic_string &data, - signed char &extracted, - const std::locale &loc) const - { - std::basic_istringstream stream(data); - stream.imbue(loc); - int tmp; - stream >> tmp; - if (!stream.eof()) - stream >> std::ws; - if (stream.eof() && !stream.fail() && !stream.bad()) - { - extracted = static_cast(tmp); - return true; - } - else - return false; - } - }; - - template - struct extractor - { - inline bool operator()(const std::basic_string &data, - unsigned char &extracted, - const std::locale &loc) const - { - std::basic_istringstream stream(data); - stream.imbue(loc); - unsigned int tmp; - stream >> tmp; - if (!stream.eof()) - stream >> std::ws; - if (stream.eof() && !stream.fail() && !stream.bad()) - { - extracted = static_cast(tmp); - return true; - } - else - return false; - } - }; - - template - struct extractor - { - inline bool operator()(const std::basic_string &data, - bool &extracted, - const std::locale &loc) const - { - std::basic_istringstream stream(data); - stream.imbue(loc); - bool tmp; - stream >> std::boolalpha >> tmp; - if (!stream.eof()) - stream >> std::ws; - if (stream.eof() && !stream.fail() && !stream.bad()) - { - extracted = tmp; - return true; - } - else - { - std::basic_istringstream stream2(data); - stream2.imbue(loc); - bool tmp; - stream2 >> tmp; - if (!stream2.eof()) - stream >> std::ws; - if (stream2.eof() && !stream2.fail() && !stream2.bad()) - { - extracted = tmp; - return true; - } - } - return false; - } - }; - - //////////////////////////////////////////////////////////////////////////// - // Inserter - - template - struct inserter - { - inline bool operator()(std::basic_string &data, - const T &to_insert, - const std::locale &loc) const - { - typedef typename detail::array_to_pointer_decay::type T2; - std::basic_ostringstream stream; - stream.imbue(loc); - if (std::numeric_limits::is_specialized - && !std::numeric_limits::is_exact) - stream.precision(std::numeric_limits::digits10 + 1); - stream << std::boolalpha << to_insert; - data = stream.str(); - return !stream.fail() && !stream.bad(); - } - }; - - template - struct inserter - { - inline bool operator()(std::basic_string &data, - const signed char &to_insert, - const std::locale &loc) const - { - return detail::inserter()(data, static_cast(to_insert), loc); - } - }; - - template - struct inserter - { - inline bool operator()(std::basic_string &data, - const unsigned char &to_insert, - const std::locale &loc) const - { - return detail::inserter()(data, static_cast(to_insert), loc); - } - }; - - template - struct inserter > - { - inline bool operator()(std::basic_string &data, - const std::basic_string &to_insert, - const std::locale &loc) const - { - data = to_insert; - return true; - } - }; - - } - - inline translator::translator() - { - } - - inline translator::translator(const std::locale &loc): - m_locale(loc) - { - } - - template - bool translator::get_value(const Ptree &pt, T &value) const - { - typedef typename Ptree::data_type::value_type Ch; - return detail::extractor()(pt.data(), value, m_locale); - } - - template - bool translator::put_value(Ptree &pt, const T &value) const - { - - typedef typename Ptree::data_type::value_type Ch; - - // Make sure that no pointer other than char_type * is allowed - BOOST_STATIC_ASSERT((is_pointer::value == false || - is_same::type>::type>::value == true)); - - return detail::inserter()(pt.data(), value, m_locale); - - } - -} } - -#endif diff --git a/include/boost/property_tree/detail/xml_parser_read_pugixml.hpp b/include/boost/property_tree/detail/xml_parser_read_pugixml.hpp deleted file mode 100644 index c4cbcb9a3a..0000000000 --- a/include/boost/property_tree/detail/xml_parser_read_pugixml.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2006-2007 Alexey Baskakov -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -// PugiXML-based parser. To enable it define -// BOOST_PROPERTY_TREE_XML_PARSER_PUGIXML before including xml_parser.hpp file. -// -// PugiXML library has to be obtained separately. -// Check it out at http://code.google.com/p/pugixml/ -// -// This module is derived from an example shipped as part of -// the PugiXML documentation. This example contains the following notice: -// Copyright (C) 2006, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - -#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_PUGIXML_HPP_INCLUDED -#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_PUGIXML_HPP_INCLUDED - -#include -#include -#include -#include - -#include - -namespace boost { namespace property_tree { namespace xml_parser -{ - - template - void read_xml_node( pugi::xml_node node, Ptree &pt, int flags) - { - typedef typename Ptree::key_type::value_type Ch; - - switch ( node.type() ) - { - case pugi::node_element: - { - Ptree &tmp = pt.push_back(std::make_pair( node.name(), Ptree()))->second; - for ( pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute() ) - tmp.put( xmlattr() + "." + attr.name(), attr.value()); - for ( pugi::xml_node child = node.first_child(); child; child = child.next_sibling()) - read_xml_node(child, tmp, flags); - } - break; - case pugi::node_pcdata: - { - if (flags & no_concat_text) - pt.push_back(std::make_pair(xmltext(), Ptree( node.value() ))); - else - pt.data() += node.value(); - } - break; - case pugi::node_comment: - { - if (!(flags & no_comments)) - pt.push_back(std::make_pair(xmlcomment(), Ptree( node.value() ))); - } - break; - default: - // skip other types - break; - } - } - - template - void read_xml_internal(std::basic_istream &stream, - Ptree &pt, - int flags, - const std::string &filename) - { - typedef typename Ptree::key_type::value_type Ch; - - // Create and load document from stream - stream.unsetf(std::ios::skipws); - - if (!stream.good()) - throw xml_parser_error("read error", filename, 0); - - std::vector buf; - std::copy(std::istream_iterator(stream), std::istream_iterator(), std::back_inserter(buf)); - buf.push_back(0); // zero-terminate - - unsigned int pugi_flags = pugi::parse_w3c; - if ( flags & no_comments ) - pugi_flags = pugi_flags & ~pugi::parse_comments; - - pugi::xml_parser parser(&buf[0], pugi_flags); - pugi::xml_node doc = parser.document(); - - // Create ptree from nodes - Ptree local; - for ( pugi::xml_node child = doc.first_child(); child; child = child.next_sibling()) - read_xml_node( child, local, flags ); - - // Swap local and result ptrees - pt.swap(local); - } - -} } } - -#endif diff --git a/include/boost/property_tree/detail/xml_parser_read_pugxml.hpp b/include/boost/property_tree/detail/xml_parser_read_pugxml.hpp deleted file mode 100644 index 075b9d4c79..0000000000 --- a/include/boost/property_tree/detail/xml_parser_read_pugxml.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_PUGXML_HPP_INCLUDED -#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_PUGXML_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost { namespace property_tree { namespace xml_parser -{ - - template - void read_xml_node(pug::xml_node node, Ptree &pt, int flags) - { - typedef typename Ptree::key_type::value_type Ch; - if (node.type() == pug::node_element || - node.type() == pug::node_document) - { - Ptree &tmp = pt.push_back(std::make_pair(node.name(), empty_ptree()))->second; - for (pug::xml_node::attribute_iterator it = node.attributes_begin(); it != node.attributes_end(); ++it) - tmp.put(xmlattr() + Ch('.') + it->name(), it->value()); - for (pug::xml_node::child_iterator it = node.children_begin(); it != node.children_end(); ++it) - read_xml_node(*it, tmp, flags); - } - else if (node.type() == pug::node_pcdata) - { - if (flags & no_concat_text) - pt.push_back(std::make_pair(xmltext(), Ptree(node.value()))); - else - pt.data() += node.value(); - } - else if (node.type() == pug::node_comment) - { - if (!(flags & no_comments)) - pt.push_back(std::make_pair(xmlcomment(), Ptree(node.value()))); - } - } - - template - void read_xml_internal(std::basic_istream &stream, - Ptree &pt, - int flags, - const std::string &filename) - { - - typedef typename Ptree::key_type::value_type Ch; - - // Load data into vector - std::vector data(std::istreambuf_iterator(stream.rdbuf()), - std::istreambuf_iterator()); - if (!stream.good()) - BOOST_PROPERTY_TREE_THROW(xml_parser_error("read error", filename, 0)); - data.push_back(Ch('\0')); - - // Parse - pug::xml_parser parser; - if (parser.parse(&data.front())) - { - Ptree local; - pug::xml_node doc = parser.document(); - for (pug::xml_node::child_iterator it = doc.children_begin(); it != doc.children_end(); ++it) - read_xml_node(*it, local, flags); - local.swap(pt); - } - else - BOOST_PROPERTY_TREE_THROW(xml_parser_error("parse error", filename, 0)); - - } - -} } } - -#endif diff --git a/include/boost/property_tree/detail/xml_parser_read_spirit.hpp b/include/boost/property_tree/detail/xml_parser_read_spirit.hpp deleted file mode 100644 index a368adb2c4..0000000000 --- a/include/boost/property_tree/detail/xml_parser_read_spirit.hpp +++ /dev/null @@ -1,733 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Based on XML grammar by Daniel C. Nuffer -// http://spirit.sourceforge.net/repository/applications/xml.zip -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_SPIRIT_HPP_INCLUDED -#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_SPIRIT_HPP_INCLUDED - -//#define BOOST_SPIRIT_DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace property_tree { namespace xml_parser -{ - - // XML parser context - template - struct context - { - - typedef typename Ptree::key_type::value_type Ch; - typedef std::basic_string Str; - typedef typename Ptree::path_type Path; - typedef boost::spirit::position_iterator::const_iterator> It; - - int flags; - std::vector stack; - - /////////////////////////////////////////////////////////////////////// - // Actions - - struct a_key_s - { - context &c; - a_key_s(context &c): c(c) { } - void operator()(It b, It e) const - { - if (c.stack.empty()) - BOOST_PROPERTY_TREE_THROW(xml_parser_error("xml parse error", - detail::narrow(b.get_position().file.c_str()), - b.get_position().line)); - Str name(b, e); - Ptree *child = &c.stack.back()->push_back(std::make_pair(name, Ptree()))->second; - c.stack.push_back(child); - } - }; - - struct a_key_e - { - context &c; - a_key_e(context &c): c(c) { } - void operator()(It b, It e) const - { - if (c.stack.size() <= 1) - BOOST_PROPERTY_TREE_THROW(xml_parser_error("xml parse error", - detail::narrow(b.get_position().file.c_str()), - b.get_position().line)); - c.stack.pop_back(); - } - }; - - struct a_content - { - context &c; - a_content(context &c): c(c) { } - void operator()(It b, It e) const - { - Str s = decode_char_entities(detail::trim(condense(Str(b, e)))); - if (!s.empty()) - { - if (c.flags & no_concat_text) - c.stack.back()->push_back(std::make_pair(xmltext(), Ptree(s))); - else - c.stack.back()->put_value(c.stack.back()->template get_value >() + s); - } - } - }; - - struct a_attr_key - { - context &c; - a_attr_key(context &c): c(c) { } - void operator()(It b, It e) const - { - Path p(xmlattr()); - p /= Str(b, e); - c.stack.back()->put_child(p, empty_ptree()); - } - }; - - struct a_attr_data - { - context &c; - a_attr_data(context &c): c(c) { } - void operator()(It b, It e) const - { - Ptree &attr = c.stack.back()->get_child(xmlattr()); - attr.back().second.put_value(Str(b + 1, e - 1)); - } - }; - - struct a_comment - { - context &c; - a_comment(context &c): c(c) { } - void operator()(It b, It e) const - { - c.stack.back()->push_back(std::make_pair(xmlcomment(), Ptree(Str(b, e)))); - } - }; - - }; - - /////////////////////////////////////////////////////////////////////// - // Grammar - - template - struct xml_grammar: public boost::spirit::grammar > - { - - typedef context context_t; - - mutable context_t c; - - template - struct definition - { - - typedef typename ScannerT::value_t char_t; - typedef boost::spirit::chset chset_t; - - boost::spirit::rule - prolog, element, Misc, PEReference, Reference, PITarget, CData, - doctypedecl, XMLDecl, SDDecl, VersionInfo, EncodingDecl, VersionNum, - Eq, DeclSep, ExternalID, markupdecl, NotationDecl, EntityDecl, - AttlistDecl, elementdecl, TextDecl, extSubsetDecl, conditionalSect, - EmptyElemTag, STag, content, ETag, Attribute, contentspec, Mixed, - children, choice, seq, cp, AttDef, AttType, DefaultDecl, StringType, - TokenizedType, EnumeratedType, NotationType, Enumeration, EntityValue, - AttValue, SystemLiteral, PubidLiteral, CharDataChar, CharData, Comment, - PI, CDSect, extSubset, includeSect, ignoreSect, ignoreSectContents, - Ignore, CharRef, EntityRef, GEDecl, PEDecl, EntityDef, PEDef, - NDataDecl, extParsedEnt, EncName, PublicID, document, S, Name, Names, - Nmtoken, Nmtokens, STagB, STagE1, STagE2; - - definition(const xml_grammar &self) - { - - using namespace boost::spirit; - - // XML Char sets - chset_t Char("\x9\xA\xD\x20-\x7F"); - chset_t Sch("\x20\x9\xD\xA"); - chset_t Letter("\x41-\x5A\x61-\x7A"); - chset_t Digit("0-9"); - chset_t XDigit("0-9A-Fa-f"); - chset_t Extender("\xB7"); - chset_t NameChar = - Letter - | Digit - | (char_t)'.' - | (char_t)'-' - | (char_t)'_' - | (char_t)':' - | Extender; - - document = - prolog >> element >> *Misc - ; - - S = - +(Sch) - ; - - Name = - (Letter | '_' | ':') - >> *(NameChar) - ; - - Names = - Name >> *(S >> Name) - ; - - Nmtoken = - +NameChar - ; - - Nmtokens = - Nmtoken >> *(S >> Nmtoken) - ; - - EntityValue = - '"' >> *( (anychar_p - (chset_t(detail::widen("%&\"").c_str()))) - | PEReference - | Reference) - >> '"' - | '\'' >> *( (anychar_p - (chset_t("%&'"))) - | PEReference - | Reference) - >> '\'' - ; - - AttValue = - '"' >> *( (anychar_p - (chset_t("<&\""))) - | Reference) - >> '"' - | '\'' >> *( (anychar_p - (chset_t("<&'"))) - | Reference) - >> '\'' - ; - - SystemLiteral= - ('"' >> *(anychar_p - '"') >> '"') - | ('\'' >> *(anychar_p - '\'') >> '\'') - ; - - chset_t PubidChar("\x20\xD\xA'a-zA-Z0-9()+,./:=?;!*#@$_%-"); - - PubidLiteral = - '"' >> *PubidChar >> '"' - | '\'' >> *(PubidChar - '\'') >> '\'' - ; - - CharDataChar = - //anychar_p - (chset_t("<&")) - anychar_p - (chset_t("<")) - ; - - CharData = - *(CharDataChar - "]]>") - ; - - Comment = - "" - ; - - PI = - "> PITarget >> !(S >> (*(Char - "?>"))) >> "?>" - ; - - PITarget = - Name - (as_lower_d["xml"]) - ; - - CDSect = - "> CData >> "]]>" - ; - - CData = - *(Char - "]]>") - ; - - prolog = - !XMLDecl >> *Misc >> !(doctypedecl >> *Misc) - ; - - XMLDecl = - "> VersionInfo >> !EncodingDecl >> !SDDecl - >> !S >> "?>" - ; - - VersionInfo = - S >> "version" >> Eq >> - ( - '\'' >> VersionNum >> '\'' - | '"' >> VersionNum >> '"' - ) - ; - - Eq = - !S >> '=' >> !S - ; - - chset_t VersionNumCh("a-zA-Z0-9_.:-"); - - VersionNum = - +(VersionNumCh) - ; - - Misc = - Comment - | PI - | S - ; - - doctypedecl = - "> S >> Name >> !(S >> ExternalID) >> !S >> - !( - '[' >> *(markupdecl | DeclSep) >> ']' >> !S - ) - >> '>' - ; - - DeclSep = - PEReference - | S - ; - - markupdecl = - elementdecl - | AttlistDecl - | EntityDecl - | NotationDecl - | PI - | Comment - ; - - extSubset = - !TextDecl >> extSubsetDecl - ; - - extSubsetDecl = - *( - markupdecl - | conditionalSect - | DeclSep - ) - ; - - SDDecl = - S >> "standalone" >> Eq >> - ( - ('\'' >> (str_p("yes") | "no") >> '\'') - | ('"' >> (str_p("yes") | "no") >> '"') - ) - ; - - /* - element = - EmptyElemTag - | STag >> content >> ETag - ; - */ - element = - STagB >> (STagE2 | (STagE1 >> content >> ETag))[typename context_t::a_key_e(self.c)] - ; - - STag = - '<' >> Name >> *(S >> Attribute) >> !S >> '>' - ; - - STagB = - '<' - >> Name[typename context_t::a_key_s(self.c)] - >> *(S >> Attribute) - >> !S - ; - - STagE1 = - ch_p(">") - ; - - STagE2 = - str_p("/>") - ; - - Attribute = - Name[typename context_t::a_attr_key(self.c)] - >> Eq - >> AttValue[typename context_t::a_attr_data(self.c)] - ; - - ETag = - "> Name >> !S >> '>' - ; - - content = - !(CharData[typename context_t::a_content(self.c)]) >> - *( - ( - element - // | Reference - | CDSect - | PI - | Comment - ) >> - !(CharData[typename context_t::a_content(self.c)]) - ) - ; - - EmptyElemTag = - '<' >> Name >> *(S >> Attribute) >> !S >> "/>" - ; - - elementdecl = - "> S >> Name >> S >> contentspec >> !S >> '>' - ; - - contentspec = - str_p("EMPTY") - | "ANY" - | Mixed - | children - ; - - children = - (choice | seq) >> !(ch_p('?') | '*' | '+') - ; - - cp = - (Name | choice | seq) >> !(ch_p('?') | '*' | '+') - ; - - choice = - '(' >> !S >> cp - >> +(!S >> '|' >> !S >> cp) - >> !S >> ')' - ; - - seq = - '(' >> !S >> cp >> - *(!S >> ',' >> !S >> cp) - >> !S >> ')' - ; - - Mixed = - '(' >> !S >> "#PCDATA" - >> *(!S >> '|' >> !S >> Name) - >> !S >> ")*" - | '(' >> !S >> "#PCDATA" >> !S >> ')' - ; - - AttlistDecl = - "> S >> Name >> *AttDef >> !S >> '>' - ; - - AttDef = - S >> Name >> S >> AttType >> S >> DefaultDecl - ; - - AttType = - StringType - | TokenizedType - | EnumeratedType - ; - - StringType = - str_p("CDATA") - ; - - TokenizedType = - longest_d[ - str_p("ID") - | "IDREF" - | "IDREFS" - | "ENTITY" - | "ENTITIES" - | "NMTOKEN" - | "NMTOKENS" - ] - ; - - EnumeratedType = - NotationType - | Enumeration - ; - - NotationType = - "NOTATION" >> S >> '(' >> !S >> Name - >> *(!S >> '|' >> !S >> Name) - >> !S >> ')' - ; - - Enumeration = - '(' >> !S >> Nmtoken - >> *(!S >> '|' >> !S >> Nmtoken) - >> !S >> ')' - ; - - DefaultDecl = - str_p("#REQUIRED") - | "#IMPLIED" - | !("#FIXED" >> S) >> AttValue - ; - - conditionalSect = - includeSect - | ignoreSect - ; - - includeSect = - "> !S >> "INCLUDE" >> !S - >> '[' >> extSubsetDecl >> "]]>" - ; - - ignoreSect = - "> !S >> "IGNORE" >> !S - >> '[' >> *ignoreSectContents >> "]]>" - ; - - ignoreSectContents = - Ignore >> *("> ignoreSectContents >> "]]>" >> Ignore) - ; - - Ignore = - *(Char - (str_p("")) - ; - - CharRef = - "&#" >> +Digit >> ';' - | "&#x" >> +XDigit >> ';' - ; - - Reference = - EntityRef - | CharRef - ; - - EntityRef = - '&' >> Name >> ';' - ; - - PEReference = - '%' >> Name >> ';' - ; - - EntityDecl = - GEDecl - | PEDecl - ; - - GEDecl = - "> S >> Name >> S >> EntityDef >> !S >> '>' - ; - - PEDecl = - "> S >> '%' >> S >> Name >> S >> PEDef - >> !S >> '>' - ; - - EntityDef = - EntityValue - | ExternalID >> !NDataDecl - ; - - PEDef = - EntityValue - | ExternalID - ; - - ExternalID = - "SYSTEM" >> S >> SystemLiteral - | "PUBLIC" >> S >> PubidLiteral >> S >> SystemLiteral - ; - - NDataDecl = - S >> "NDATA" >> S >> Name - ; - - TextDecl = - "> !VersionInfo >> EncodingDecl >> !S >> "?>" - ; - - extParsedEnt = - !TextDecl >> content - ; - - EncodingDecl = - S >> "encoding" >> Eq - >> ( '"' >> EncName >> '"' - | '\'' >> EncName >> '\'' - ) - ; - - EncName = - Letter >> *(Letter | Digit | '.' | '_' | '-') - ; - - NotationDecl = - "> S >> Name >> S - >> (ExternalID | PublicID) >> !S >> '>' - ; - - PublicID = - "PUBLIC" >> S >> PubidLiteral - ; - - BOOST_SPIRIT_DEBUG_RULE(document); - BOOST_SPIRIT_DEBUG_RULE(prolog); - BOOST_SPIRIT_DEBUG_RULE(element); - BOOST_SPIRIT_DEBUG_RULE(Misc); - BOOST_SPIRIT_DEBUG_RULE(PEReference); - BOOST_SPIRIT_DEBUG_RULE(Reference); - BOOST_SPIRIT_DEBUG_RULE(PITarget); - BOOST_SPIRIT_DEBUG_RULE(CData); - BOOST_SPIRIT_DEBUG_RULE(doctypedecl); - BOOST_SPIRIT_DEBUG_RULE(XMLDecl); - BOOST_SPIRIT_DEBUG_RULE(SDDecl); - BOOST_SPIRIT_DEBUG_RULE(VersionInfo); - BOOST_SPIRIT_DEBUG_RULE(EncodingDecl); - BOOST_SPIRIT_DEBUG_RULE(VersionNum); - BOOST_SPIRIT_DEBUG_RULE(Eq); - BOOST_SPIRIT_DEBUG_RULE(DeclSep); - BOOST_SPIRIT_DEBUG_RULE(ExternalID); - BOOST_SPIRIT_DEBUG_RULE(markupdecl); - BOOST_SPIRIT_DEBUG_RULE(NotationDecl); - BOOST_SPIRIT_DEBUG_RULE(EntityDecl); - BOOST_SPIRIT_DEBUG_RULE(AttlistDecl); - BOOST_SPIRIT_DEBUG_RULE(elementdecl); - BOOST_SPIRIT_DEBUG_RULE(TextDecl); - BOOST_SPIRIT_DEBUG_RULE(extSubsetDecl); - BOOST_SPIRIT_DEBUG_RULE(conditionalSect); - BOOST_SPIRIT_DEBUG_RULE(EmptyElemTag); - BOOST_SPIRIT_DEBUG_RULE(STag); - BOOST_SPIRIT_DEBUG_RULE(content); - BOOST_SPIRIT_DEBUG_RULE(ETag); - BOOST_SPIRIT_DEBUG_RULE(Attribute); - BOOST_SPIRIT_DEBUG_RULE(contentspec); - BOOST_SPIRIT_DEBUG_RULE(Mixed); - BOOST_SPIRIT_DEBUG_RULE(children); - BOOST_SPIRIT_DEBUG_RULE(choice); - BOOST_SPIRIT_DEBUG_RULE(seq); - BOOST_SPIRIT_DEBUG_RULE(cp); - BOOST_SPIRIT_DEBUG_RULE(AttDef); - BOOST_SPIRIT_DEBUG_RULE(AttType); - BOOST_SPIRIT_DEBUG_RULE(DefaultDecl); - BOOST_SPIRIT_DEBUG_RULE(StringType); - BOOST_SPIRIT_DEBUG_RULE(TokenizedType); - BOOST_SPIRIT_DEBUG_RULE(EnumeratedType); - BOOST_SPIRIT_DEBUG_RULE(NotationType); - BOOST_SPIRIT_DEBUG_RULE(Enumeration); - BOOST_SPIRIT_DEBUG_RULE(EntityValue); - BOOST_SPIRIT_DEBUG_RULE(AttValue); - BOOST_SPIRIT_DEBUG_RULE(SystemLiteral); - BOOST_SPIRIT_DEBUG_RULE(PubidLiteral); - BOOST_SPIRIT_DEBUG_RULE(CharDataChar); - BOOST_SPIRIT_DEBUG_RULE(CharData); - BOOST_SPIRIT_DEBUG_RULE(Comment); - BOOST_SPIRIT_DEBUG_RULE(PI); - BOOST_SPIRIT_DEBUG_RULE(CDSect); - BOOST_SPIRIT_DEBUG_RULE(extSubset); - BOOST_SPIRIT_DEBUG_RULE(includeSect); - BOOST_SPIRIT_DEBUG_RULE(ignoreSect); - BOOST_SPIRIT_DEBUG_RULE(ignoreSectContents); - BOOST_SPIRIT_DEBUG_RULE(Ignore); - BOOST_SPIRIT_DEBUG_RULE(CharRef); - BOOST_SPIRIT_DEBUG_RULE(EntityRef); - BOOST_SPIRIT_DEBUG_RULE(GEDecl); - BOOST_SPIRIT_DEBUG_RULE(PEDecl); - BOOST_SPIRIT_DEBUG_RULE(EntityDef); - BOOST_SPIRIT_DEBUG_RULE(PEDef); - BOOST_SPIRIT_DEBUG_RULE(NDataDecl); - BOOST_SPIRIT_DEBUG_RULE(extParsedEnt); - BOOST_SPIRIT_DEBUG_RULE(EncName); - BOOST_SPIRIT_DEBUG_RULE(PublicID); - BOOST_SPIRIT_DEBUG_RULE(document); - BOOST_SPIRIT_DEBUG_RULE(S); - BOOST_SPIRIT_DEBUG_RULE(Name); - BOOST_SPIRIT_DEBUG_RULE(Names); - BOOST_SPIRIT_DEBUG_RULE(Nmtoken); - BOOST_SPIRIT_DEBUG_RULE(Nmtokens); - BOOST_SPIRIT_DEBUG_RULE(STagB); - BOOST_SPIRIT_DEBUG_RULE(STagE1); - BOOST_SPIRIT_DEBUG_RULE(STagE2); - - } - - const boost::spirit::rule &start() const - { - return document; - } - - }; - - }; - - template - void read_xml_internal(std::basic_istream &stream, - Ptree &pt, - int flags, - const std::string &filename) - { - - typedef typename Ptree::key_type::value_type Ch; - typedef boost::spirit::position_iterator::const_iterator> It; - - BOOST_ASSERT(validate_flags(flags)); - - // Load data into vector - std::vector v(std::istreambuf_iterator(stream.rdbuf()), - std::istreambuf_iterator()); - if (!stream.good()) - BOOST_PROPERTY_TREE_THROW(xml_parser_error("read error", filename, 0)); - - // Initialize iterators - It begin(v.begin(), v.end()); - It end; - - begin.set_position(detail::widen(filename.c_str())); - - // Prepare grammar - Ptree local; - xml_grammar g; - g.c.stack.push_back(&local); // Push root ptree on context stack - g.c.flags = flags; - - // Parse into local - boost::spirit::parse_info result = boost::spirit::parse(begin, end, g); - if (!result.full || g.c.stack.size() != 1) - BOOST_PROPERTY_TREE_THROW(xml_parser_error("xml parse error", - detail::narrow(result.stop.get_position().file.c_str()), - result.stop.get_position().line)); - - // Swap local and pt - pt.swap(local); - } - -} } } - -#endif diff --git a/include/boost/property_tree/detail/xml_parser_read_tinyxml.hpp b/include/boost/property_tree/detail/xml_parser_read_tinyxml.hpp deleted file mode 100644 index f0bd7f985b..0000000000 --- a/include/boost/property_tree/detail/xml_parser_read_tinyxml.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- -#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_TINYXML_HPP_INCLUDED -#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_TINYXML_HPP_INCLUDED - -#include -#include -#include -#include - -#include - -namespace boost { namespace property_tree { namespace xml_parser -{ - -#ifdef TIXML_USE_STL - - template - void read_xml_node(TiXmlNode *node, Ptree &pt, int flags) - { - - typedef typename Ptree::key_type::value_type Ch; - - if (TiXmlElement *elem = node->ToElement()) - { - Ptree &tmp = pt.push_back(std::make_pair(elem->Value(), Ptree()))->second; - for (TiXmlAttribute *attr = elem->FirstAttribute(); attr; attr = attr->Next()) - tmp.put(xmlattr() + Ch('.') + attr->Name(), attr->Value()); - for (TiXmlNode *child = node->FirstChild(); child; child = child->NextSibling()) - read_xml_node(child, tmp, flags); - } - else if (TiXmlText *text = node->ToText()) - { - if (flags & no_concat_text) - pt.push_back(std::make_pair(xmltext(), Ptree(text->Value()))); - else - pt.data() += text->Value(); - } - else if (TiXmlComment *comment = node->ToComment()) - { - if (!(flags & no_comments)) - pt.push_back(std::make_pair(xmlcomment(), Ptree(comment->Value()))); - } - } - - template - void read_xml_internal(std::basic_istream &stream, - Ptree &pt, - int flags, - const std::string &filename) - { - - // Create and load document from stream - TiXmlDocument doc; - stream >> doc; - if (!stream.good()) - BOOST_PROPERTY_TREE_THROW(xml_parser_error("read error", filename, 0)); - if (doc.Error()) - BOOST_PROPERTY_TREE_THROW(xml_parser_error(doc.ErrorDesc(), filename, doc.ErrorRow())); - - // Create ptree from nodes - Ptree local; - for (TiXmlNode *child = doc.FirstChild(); child; child = child->NextSibling()) - read_xml_node(child, local, flags); - - // Swap local and result ptrees - pt.swap(local); - - } - -#else - - template - void read_xml_node(TiXmlNode *node, Ptree &pt, int flags) - { - - typedef typename Ptree::key_type::value_type Ch; - - if (TiXmlElement *elem = node->ToElement()) - { - Ptree &tmp = pt.push_back(std::make_pair(elem->Value(), Ptree()))->second; - for (TiXmlAttribute *attr = elem->FirstAttribute(); attr; attr = attr->Next()) - tmp.put(xmlattr() + Ch('.') + attr->Name(), attr->Value()); - for (TiXmlNode *child = node->FirstChild(); child; child = child->NextSibling()) - read_xml_node(child, tmp, flags); - } - else if (TiXmlText *text = node->ToText()) - { - if (flags & no_concat_text) - pt.push_back(std::make_pair(xmltext(), Ptree(text->Value()))); - else - pt.data() += text->Value(); - } - else if (TiXmlComment *comment = node->ToComment()) - { - if (!(flags & no_comments)) - pt.push_back(std::make_pair(xmlcomment(), Ptree(comment->Value()))); - } - } - - template - void read_xml_internal(std::basic_istream &stream, - Ptree &pt, - int flags, - const std::string &filename) - { - - // Load data into vector - typedef typename Ptree::key_type::value_type Ch; - std::vector data(std::istreambuf_iterator(stream.rdbuf()), - std::istreambuf_iterator()); - if (!stream.good()) - BOOST_PROPERTY_TREE_THROW(xml_parser_error("read error", filename, 0)); - data.push_back(Ch('\0')); - - // Create and load document - TiXmlDocument doc; - doc.Parse(&data.front()); - if (doc.Error()) - BOOST_PROPERTY_TREE_THROW(xml_parser_error(doc.ErrorDesc(), filename, doc.ErrorRow())); - - // Create ptree from nodes - Ptree local; - for (TiXmlNode *child = doc.FirstChild(); child; child = child->NextSibling()) - read_xml_node(child, local, flags); - - // Swap local and result ptrees - pt.swap(local); - - } - -#endif - -} } } - -#endif diff --git a/test/test_cmdline_parser.cpp b/test/test_cmdline_parser.cpp deleted file mode 100644 index 03b5d46400..0000000000 --- a/test/test_cmdline_parser.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include "test_utils.hpp" -#include -#include -#include -#include - -namespace -{ - - // Test arguments - char *argv[] = - { - "c:\\program.exe", - "-Isrc/include1", - " file2.cc ", - "/L src/lib1", - "-Lsrc/lib2", - "/ooutput", - "file1.cc", - "-g", - "-", - "/", - " /Isrc/include2 ", - " file3.cc ", - "-I src/include3 " - }; - - // Test arguments count - const int argc = sizeof(argv) / sizeof(*argv); - -} - -template -void test_cmdline_parser() -{ - - using namespace boost::property_tree; - typedef typename Ptree::key_type::value_type Ch; - typedef std::basic_string Str; - - // Prepare arguments of proper char type - std::vector p; - std::vector strings; - strings.reserve(argc); - for (int i = 0; i < argc; ++i) - { - strings.push_back(detail::widen(argv[i])); - p.push_back(const_cast(strings.back().c_str())); - } - - Ptree pt1; - read_cmdline(argc, &p.front(), detail::widen("-/"), pt1); - - // Check indices - BOOST_CHECK(pt1.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib1")); - BOOST_CHECK(pt1.template get_optional(detail::widen("L.1")).get() == detail::widen("src/lib2")); - BOOST_CHECK(!pt1.template get_optional(detail::widen("L.2"))); - BOOST_CHECK(pt1.template get_optional(detail::widen(".0")).get() == detail::widen("c:\\program.exe")); - BOOST_CHECK(pt1.template get_optional(detail::widen(".1")).get() == detail::widen("file2.cc")); - BOOST_CHECK(pt1.template get_optional(detail::widen(".2")).get() == detail::widen("file1.cc")); - BOOST_CHECK(pt1.template get_optional(detail::widen(".3")).get() == detail::widen("file3.cc")); - BOOST_CHECK(!pt1.template get_optional(detail::widen(".4"))); - - // Check total sizes - //std::cerr << total_size(pt1) << " " << total_data_size(pt1) << " " << total_keys_size(pt1) << "\n"; - BOOST_CHECK(total_size(pt1) == 21); - BOOST_CHECK(total_data_size(pt1) == 130); - BOOST_CHECK(total_keys_size(pt1) == 19); - - Ptree pt2; - read_cmdline(argc, &p.front(), detail::widen("-"), pt2); - - // Check indices - BOOST_CHECK(pt2.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib2")); - BOOST_CHECK(!pt2.template get_optional(detail::widen("L.1"))); - - // Check total sizes - //std::cerr << total_size(pt2) << " " << total_data_size(pt2) << " " << total_keys_size(pt2) << "\n"; - BOOST_CHECK(total_size(pt2) == 19); - BOOST_CHECK(total_data_size(pt2) == 135); - BOOST_CHECK(total_keys_size(pt2) == 17); - - Ptree pt3; - read_cmdline(argc, &p.front(), detail::widen("/"), pt3); - - // Check indices - BOOST_CHECK(pt3.template get_optional(detail::widen("L.0")).get() == detail::widen("src/lib1")); - BOOST_CHECK(!pt3.template get_optional(detail::widen("L.1"))); - - // Check total sizes - //std::cerr << total_size(pt3) << " " << total_data_size(pt3) << " " << total_keys_size(pt3) << "\n"; - BOOST_CHECK(total_size(pt3) == 19); - BOOST_CHECK(total_data_size(pt3) == 149); - BOOST_CHECK(total_keys_size(pt3) == 17); - -} - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_cmdline_parser(); -#ifndef BOOST_NO_CWCHAR - test_cmdline_parser(); -#endif - return 0; -} diff --git a/test/test_registry_parser.cpp b/test/test_registry_parser.cpp deleted file mode 100644 index 2e7c348816..0000000000 --- a/test/test_registry_parser.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#include "test_utils.hpp" - -// Only test registry parser if we have windows platform -#ifdef BOOST_WINDOWS - -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// Test data - -const char *data_1 = - "root\n" - "{\n" - " subkey1 \"default value 1\"\n" - " subkey2 \"default value 2\"\n" - " \\\\values\n" - " {\n" - " REG_NONE \"\"\n" - " REG_BINARY \"de ad be ef\"\n" - " REG_DWORD 1234567890\n" - " REG_QWORD 12345678901234567890\n" - " REG_SZ \"some text\"\n" - " REG_EXPAND_SZ \"some other text\"\n" - " }\n" - " \\\\types\n" - " {\n" - " REG_NONE 0\n" - " REG_BINARY 3\n" - " REG_DWORD 4\n" - " REG_QWORD 11\n" - " REG_SZ 1\n" - " REG_EXPAND_SZ 2\n" - " }\n" - "}\n"; - -template -void test_registry_parser() -{ - - using namespace boost::property_tree; - typedef typename Ptree::key_type::value_type Ch; - typedef std::basic_string Str; - - // Delete test registry key - RegDeleteKeyA(HKEY_CURRENT_USER, "boost ptree test"); - - // Get test ptree - Ptree pt; - std::basic_stringstream stream(detail::widen(data_1)); - read_info(stream, pt); - - try - { - - // Write to registry, read back and compare contents - Ptree pt2; - write_registry(HKEY_CURRENT_USER, detail::widen("boost ptree test"), pt); - read_registry(HKEY_CURRENT_USER, detail::widen("boost ptree test"), pt2); - BOOST_CHECK(pt == pt2); - - // Test binary translation - Str s = pt2.template get(detail::widen("root.\\values.REG_BINARY")); - std::vector bin = registry_parser::translate(REG_BINARY, s); - BOOST_REQUIRE(bin.size() == 4); - BOOST_CHECK(*reinterpret_cast(&bin.front()) == 0xEFBEADDE); - Str s2 = registry_parser::translate(REG_BINARY, bin); - BOOST_CHECK(s == s2); - - } - catch (std::exception &e) - { - BOOST_ERROR(e.what()); - } - - // Delete test registry key - RegDeleteKeyA(HKEY_CURRENT_USER, "boost ptree test"); - -} - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_registry_parser(); - //test_registry_parser(); -#ifndef BOOST_NO_CWCHAR - //test_registry_parser(); - //test_registry_parser(); -#endif - return 0; -} - -#else - -int test_main(int argc, char *argv[]) -{ - return 0; -} - -#endif diff --git a/test/test_xml_parser_pugxml.cpp b/test/test_xml_parser_pugxml.cpp deleted file mode 100644 index b873c3c292..0000000000 --- a/test/test_xml_parser_pugxml.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#define _CRT_SECURE_NO_DEPRECATE -#define BOOST_PROPERTY_TREE_XML_PARSER_PUGXML -#include "test_xml_parser_common.hpp" - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_xml_parser(); - //test_xml_parser(); -#ifndef BOOST_NO_CWCHAR - //test_xml_parser(); - //test_xml_parser(); -#endif - return 0; -} diff --git a/test/test_xml_parser_spirit.cpp b/test/test_xml_parser_spirit.cpp deleted file mode 100644 index 75cc49a215..0000000000 --- a/test/test_xml_parser_spirit.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2006 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#define BOOST_PROPERTY_TREE_XML_PARSER_SPIRIT -#include "test_xml_parser_common.hpp" - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_xml_parser(); - test_xml_parser(); -#ifndef BOOST_NO_CWCHAR - test_xml_parser(); - test_xml_parser(); -#endif - return 0; -} diff --git a/test/test_xml_parser_tinyxml.cpp b/test/test_xml_parser_tinyxml.cpp deleted file mode 100644 index eb4be3cb59..0000000000 --- a/test/test_xml_parser_tinyxml.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright (C) 2002-2005 Marcin Kalicinski -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see www.boost.org -// ---------------------------------------------------------------------------- - -#ifdef _DEBUG - #pragma comment( lib, "tinyxmld_STL.lib" ) -#else - #pragma comment( lib, "tinyxml_STL.lib" ) -#endif - -#define BOOST_PROPERTY_TREE_XML_PARSER_TINYXML -#include "test_xml_parser_common.hpp" - -int test_main(int argc, char *argv[]) -{ - using namespace boost::property_tree; - test_xml_parser(); - test_xml_parser(); - return 0; -} From 8af8b6bf3b65fa59792d849b526678f176d87132 Mon Sep 17 00:00:00 2001 From: Alexander Bogdashevsky Date: Tue, 15 Apr 2014 06:19:02 -0400 Subject: [PATCH 21/23] support for non-std::string keys --- .../property_tree/detail/json_parser_read.hpp | 14 ++-- .../property_tree/detail/ptree_utils.hpp | 31 ++++---- .../detail/xml_parser_read_rapidxml.hpp | 15 ++-- .../property_tree/detail/xml_parser_utils.hpp | 75 ++++++++++--------- .../property_tree/detail/xml_parser_write.hpp | 61 +++++++-------- .../detail/xml_parser_writer_settings.hpp | 28 +++---- include/boost/property_tree/string_path.hpp | 2 +- include/boost/property_tree/xml_parser.hpp | 9 +-- test/test_property_tree.hpp | 4 - test/test_utils.hpp | 16 ++-- test/test_xml_parser_common.hpp | 3 +- 11 files changed, 127 insertions(+), 131 deletions(-) diff --git a/include/boost/property_tree/detail/json_parser_read.hpp b/include/boost/property_tree/detail/json_parser_read.hpp index f8a374c44d..798552f6f1 100644 --- a/include/boost/property_tree/detail/json_parser_read.hpp +++ b/include/boost/property_tree/detail/json_parser_read.hpp @@ -32,9 +32,8 @@ namespace boost { namespace property_tree { namespace json_parser template struct context { - - typedef typename Ptree::key_type::value_type Ch; - typedef std::basic_string Str; + typedef typename Ptree::key_type Str; + typedef typename Str::value_type Ch; typedef typename std::vector::iterator It; Str string; @@ -162,7 +161,8 @@ namespace boost { namespace property_tree { namespace json_parser { typedef context Context; - typedef typename Ptree::key_type::value_type Ch; + typedef typename Ptree::key_type Str; + typedef typename Str::value_type Ch; mutable Context c; @@ -239,8 +239,8 @@ namespace boost { namespace property_tree { namespace json_parser = !ch_p("-") >> (ch_p("0") | (range_p(Ch('1'), Ch('9')) >> *digit_p)) >> !(ch_p(".") >> +digit_p) >> - !(chset_p(detail::widen("eE").c_str()) >> - !chset_p(detail::widen("-+").c_str()) >> + !(chset_p(detail::widen("eE").c_str()) >> + !chset_p(detail::widen("-+").c_str()) >> +digit_p) ; @@ -255,7 +255,7 @@ namespace boost { namespace property_tree { namespace json_parser ; escape - = chset_p(detail::widen("\"\\/bfnrt").c_str()) + = chset_p(detail::widen("\"\\/bfnrt").c_str()) [typename Context::a_escape(self.c)] | 'u' >> uint_parser() [typename Context::a_unicode(self.c)] diff --git a/include/boost/property_tree/detail/ptree_utils.hpp b/include/boost/property_tree/detail/ptree_utils.hpp index 7e56c8f4bb..72aed4614c 100644 --- a/include/boost/property_tree/detail/ptree_utils.hpp +++ b/include/boost/property_tree/detail/ptree_utils.hpp @@ -54,49 +54,48 @@ namespace boost { namespace property_tree { namespace detail // Naively convert narrow string to another character type - template - std::basic_string widen(const char *text) + template + Str widen(const char *text) { - std::basic_string result; + Str result; while (*text) { - result += Ch(*text); + result += typename Str::value_type(*text); ++text; } return result; } // Naively convert string to narrow character type - template - std::string narrow(const Ch *text) + template + Str narrow(const char_type *text) { - std::string result; + Str result; while (*text) { if (*text < 0 || *text > (std::numeric_limits::max)()) result += '*'; else - result += char(*text); + result += typename Str::value_type(*text); ++text; } return result; } // Remove trailing and leading spaces - template - std::basic_string trim(const std::basic_string &s, - const std::locale &loc = std::locale()) + template + Str trim(const Str &s, const std::locale &loc = std::locale()) { - typename std::basic_string::const_iterator first = s.begin(); - typename std::basic_string::const_iterator end = s.end(); + typename Str::const_iterator first = s.begin(); + typename Str::const_iterator end = s.end(); while (first != end && std::isspace(*first, loc)) ++first; if (first == end) - return std::basic_string(); - typename std::basic_string::const_iterator last = end; + return Str(); + typename Str::const_iterator last = end; do --last; while (std::isspace(*last, loc)); if (first != s.begin() || last + 1 != end) - return std::basic_string(first, last + 1); + return Str(first, last + 1); else return s; } 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 fc994b162e..9c04219189 100644 --- a/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp +++ b/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp @@ -38,14 +38,13 @@ namespace boost { namespace property_tree { namespace xml_parser if (node->first_attribute()) { Ptree &pt_attr_root = pt_node.push_back( - std::make_pair(xmlattr(), Ptree()))->second; + std::make_pair(xmlattr(), Ptree()))->second; for (xml_attribute *attr = node->first_attribute(); attr; attr = attr->next_attribute()) { Ptree &pt_attr = pt_attr_root.push_back( std::make_pair(attr->name(), Ptree()))->second; - pt_attr.data() = std::basic_string(attr->value(), - attr->value_size()); + pt_attr.data() = typename Ptree::key_type(attr->value(), attr->value_size()); } } @@ -61,11 +60,10 @@ namespace boost { namespace property_tree { namespace xml_parser case node_cdata: { if (flags & no_concat_text) - pt.push_back(std::make_pair(xmltext(), + pt.push_back(std::make_pair(xmltext(), Ptree(node->value()))); else - pt.data() += std::basic_string(node->value(), - node->value_size()); + pt.data() += typename Ptree::key_type(node->value(), node->value_size()); } break; @@ -73,9 +71,8 @@ namespace boost { namespace property_tree { namespace xml_parser case node_comment: { if (!(flags & no_comments)) - pt.push_back(std::make_pair(xmlcomment(), - Ptree(std::basic_string(node->value(), - node->value_size())))); + pt.push_back(std::make_pair(xmlcomment(), + Ptree(typename Ptree::key_type(node->value(), node->value_size())))); } break; diff --git a/include/boost/property_tree/detail/xml_parser_utils.hpp b/include/boost/property_tree/detail/xml_parser_utils.hpp index 02e0936826..b4c502b5eb 100644 --- a/include/boost/property_tree/detail/xml_parser_utils.hpp +++ b/include/boost/property_tree/detail/xml_parser_utils.hpp @@ -20,14 +20,15 @@ namespace boost { namespace property_tree { namespace xml_parser { - template - std::basic_string condense(const std::basic_string &s) + template + Str condense(const Str &s) { - std::basic_string r; + typedef typename Str::value_type Ch; + Str r; std::locale loc; bool space = false; - typename std::basic_string::const_iterator end = s.end(); - for (typename std::basic_string::const_iterator it = s.begin(); + typename Str::const_iterator end = s.end(); + for (typename Str::const_iterator it = s.begin(); it != end; ++it) { if (isspace(*it, loc) || *it == Ch('\n')) @@ -41,20 +42,22 @@ namespace boost { namespace property_tree { namespace xml_parser return r; } - template - std::basic_string encode_char_entities(const std::basic_string &s) + + template + Str encode_char_entities(const Str &s) { // Don't do anything for empty strings. if(s.empty()) return s; - typedef typename std::basic_string Str; + typedef typename Str::value_type Ch; + Str r; // To properly round-trip spaces and not uglify the XML beyond // recognition, we have to encode them IF the text contains only spaces. Str sp(1, Ch(' ')); if(s.find_first_not_of(sp) == Str::npos) { // The first will suffice. - r = detail::widen(" "); + r = detail::widen(" "); r += Str(s.size() - 1, Ch(' ')); } else { typename Str::const_iterator end = s.end(); @@ -62,13 +65,13 @@ namespace boost { namespace property_tree { namespace xml_parser { switch (*it) { - case Ch('<'): r += detail::widen("<"); break; - case Ch('>'): r += detail::widen(">"); break; - case Ch('&'): r += detail::widen("&"); break; - case Ch('"'): r += detail::widen("""); break; - case Ch('\''): r += detail::widen("'"); break; - case Ch('\t'): r += detail::widen(" "); break; - case Ch('\n'): r += detail::widen(" "); break; + case Ch('<'): r += detail::widen("<"); break; + case Ch('>'): r += detail::widen(">"); break; + case Ch('&'): r += detail::widen("&"); break; + case Ch('"'): r += detail::widen("""); break; + case Ch('\''): r += detail::widen("'"); break; + case Ch('\t'): r += detail::widen(" "); break; + case Ch('\n'): r += detail::widen(" "); break; default: r += *it; break; } } @@ -76,10 +79,10 @@ namespace boost { namespace property_tree { namespace xml_parser return r; } - template - std::basic_string decode_char_entities(const std::basic_string &s) + template + Str decode_char_entities(const Str &s) { - typedef typename std::basic_string Str; + typedef typename Str::value_type Ch; Str r; typename Str::const_iterator end = s.end(); for (typename Str::const_iterator it = s.begin(); it != end; ++it) @@ -90,11 +93,11 @@ namespace boost { namespace property_tree { namespace xml_parser if (semicolon == end) BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0)); Str ent(it + 1, semicolon); - if (ent == detail::widen("lt")) r += Ch('<'); - else if (ent == detail::widen("gt")) r += Ch('>'); - else if (ent == detail::widen("amp")) r += Ch('&'); - else if (ent == detail::widen("quot")) r += Ch('"'); - else if (ent == detail::widen("apos")) r += Ch('\''); + if (ent == detail::widen("lt")) r += Ch('<'); + else if (ent == detail::widen("gt")) r += Ch('>'); + else if (ent == detail::widen("amp")) r += Ch('&'); + else if (ent == detail::widen("quot")) r += Ch('"'); + else if (ent == detail::widen("apos")) r += Ch('\''); else BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0)); it = semicolon; @@ -105,31 +108,31 @@ namespace boost { namespace property_tree { namespace xml_parser return r; } - template - const std::basic_string &xmldecl() + template + const Str &xmldecl() { - static std::basic_string s = detail::widen(""); + static Str s = detail::widen(""); return s; } - template - const std::basic_string &xmlattr() + template + const Str &xmlattr() { - static std::basic_string s = detail::widen(""); + static Str s = detail::widen(""); return s; } - template - const std::basic_string &xmlcomment() + template + const Str &xmlcomment() { - static std::basic_string s = detail::widen(""); + static Str s = detail::widen(""); return s; } - template - const std::basic_string &xmltext() + template + const Str &xmltext() { - static std::basic_string s = detail::widen(""); + static Str s = detail::widen(""); return s; } diff --git a/include/boost/property_tree/detail/xml_parser_write.hpp b/include/boost/property_tree/detail/xml_parser_write.hpp index d4d709c881..45af878488 100644 --- a/include/boost/property_tree/detail/xml_parser_write.hpp +++ b/include/boost/property_tree/detail/xml_parser_write.hpp @@ -19,23 +19,24 @@ namespace boost { namespace property_tree { namespace xml_parser { - template - void write_xml_indent(std::basic_ostream &stream, + template + void write_xml_indent(std::basic_ostream &stream, int indent, - const xml_writer_settings & settings + const xml_writer_settings & settings ) { - stream << std::basic_string(indent * settings.indent_count, settings.indent_char); + stream << std::basic_string(indent * settings.indent_count, settings.indent_char); } - template - void write_xml_comment(std::basic_ostream &stream, - const std::basic_string &s, + template + void write_xml_comment(std::basic_ostream &stream, + const Str &s, int indent, bool separate_line, - const xml_writer_settings & settings + const xml_writer_settings & settings ) { + typedef typename Str::value_type Ch; if (separate_line) write_xml_indent(stream,indent,settings); stream << Ch('<') << Ch('!') << Ch('-') << Ch('-'); @@ -45,14 +46,15 @@ namespace boost { namespace property_tree { namespace xml_parser stream << Ch('\n'); } - template - void write_xml_text(std::basic_ostream &stream, - const std::basic_string &s, + template + void write_xml_text(std::basic_ostream &stream, + const Str &s, int indent, bool separate_line, - const xml_writer_settings & settings + const xml_writer_settings & settings ) { + typedef typename Str::value_type Ch; if (separate_line) write_xml_indent(stream,indent,settings); stream << encode_char_entities(s); @@ -62,13 +64,13 @@ namespace boost { namespace property_tree { namespace xml_parser template void write_xml_element(std::basic_ostream &stream, - const std::basic_string &key, + const typename Ptree::key_type &key, const Ptree &pt, int indent, - const xml_writer_settings & settings) + const xml_writer_settings & settings) { - typedef typename Ptree::key_type::value_type Ch; + typedef typename Ptree::key_type Str; typedef typename Ptree::const_iterator It; bool want_pretty = settings.indent_count > 0; @@ -77,10 +79,10 @@ namespace boost { namespace property_tree { namespace xml_parser bool has_attrs_only = pt.data().empty(); for (It it = pt.begin(), end = pt.end(); it != end; ++it) { - if (it->first != xmlattr() ) + if (it->first != xmlattr() ) { has_attrs_only = false; - if (it->first != xmltext()) + if (it->first != xmltext()) { has_elements = true; break; @@ -112,12 +114,12 @@ namespace boost { namespace property_tree { namespace xml_parser stream << Ch('<') << key; // Write attributes - if (optional attribs = pt.get_child_optional(xmlattr())) + if (optional attribs = pt.get_child_optional(xmlattr())) for (It it = attribs.get().begin(); it != attribs.get().end(); ++it) stream << Ch(' ') << it->first << Ch('=') << Ch('"') << encode_char_entities( - it->second.template get_value >()) + it->second.template get_value()) << Ch('"'); if ( has_attrs_only ) @@ -141,21 +143,21 @@ namespace boost { namespace property_tree { namespace xml_parser // Write data text, if present if (!pt.data().empty()) write_xml_text(stream, - pt.template get_value >(), + pt.template get_value(), indent + 1, has_elements && want_pretty, settings); // Write elements, comments and texts for (It it = pt.begin(); it != pt.end(); ++it) { - if (it->first == xmlattr()) + if (it->first == xmlattr()) continue; - else if (it->first == xmlcomment()) + else if (it->first == xmlcomment()) write_xml_comment(stream, - it->second.template get_value >(), + it->second.template get_value(), indent + 1, want_pretty, settings); - else if (it->first == xmltext()) + else if (it->first == xmltext()) write_xml_text(stream, - it->second.template get_value >(), + it->second.template get_value(), indent + 1, has_elements && want_pretty, settings); else write_xml_element(stream, it->first, it->second, @@ -179,13 +181,12 @@ namespace boost { namespace property_tree { namespace xml_parser void write_xml_internal(std::basic_ostream &stream, const Ptree &pt, const std::string &filename, - const xml_writer_settings & settings) + const xml_writer_settings & settings) { - typedef typename Ptree::key_type::value_type Ch; - typedef typename std::basic_string Str; - stream << detail::widen("("("\"?>\n"); + << detail::widen("\"?>\n"); write_xml_element(stream, Str(), pt, -1, settings); if (!stream) BOOST_PROPERTY_TREE_THROW(xml_parser_error("write error", filename, 0)); diff --git a/include/boost/property_tree/detail/xml_parser_writer_settings.hpp b/include/boost/property_tree/detail/xml_parser_writer_settings.hpp index f22d85e8a4..9b14a5d723 100644 --- a/include/boost/property_tree/detail/xml_parser_writer_settings.hpp +++ b/include/boost/property_tree/detail/xml_parser_writer_settings.hpp @@ -18,10 +18,11 @@ namespace boost { namespace property_tree { namespace xml_parser { // Naively convert narrow string to another character type - template - std::basic_string widen(const char *text) + template + Str widen(const char *text) { - std::basic_string result; + typedef typename Str::value_type Ch; + Str result; while (*text) { result += Ch(*text); @@ -31,13 +32,14 @@ namespace boost { namespace property_tree { namespace xml_parser } //! Xml writer settings. The default settings lead to no pretty printing. - template + template class xml_writer_settings { + typedef typename Str::value_type Ch; public: xml_writer_settings(Ch inchar = Ch(' '), - typename std::basic_string::size_type incount = 0, - const std::basic_string &enc = widen("utf-8")) + typename Str::size_type incount = 0, + const Str &enc = widen("utf-8")) : indent_char(inchar) , indent_count(incount) , encoding(enc) @@ -45,16 +47,16 @@ namespace boost { namespace property_tree { namespace xml_parser } Ch indent_char; - typename std::basic_string::size_type indent_count; - std::basic_string encoding; + typename Str::size_type indent_count; + Str encoding; }; - template - xml_writer_settings xml_writer_make_settings(Ch indent_char = Ch(' '), - typename std::basic_string::size_type indent_count = 0, - const std::basic_string &encoding = widen("utf-8")) + template + xml_writer_settings xml_writer_make_settings(typename Str::value_type indent_char = (typename Str::value_type)(' '), + typename Str::size_type indent_count = 0, + const Str &encoding = widen("utf-8")) { - return xml_writer_settings(indent_char, indent_count, encoding); + return xml_writer_settings(indent_char, indent_count, encoding); } } } } diff --git a/include/boost/property_tree/string_path.hpp b/include/boost/property_tree/string_path.hpp index d4bc686dc6..3ddcfb2033 100644 --- a/include/boost/property_tree/string_path.hpp +++ b/include/boost/property_tree/string_path.hpp @@ -61,7 +61,7 @@ namespace boost { namespace property_tree #ifndef BOOST_NO_STD_WSTRING inline std::string dump_sequence(const std::wstring &s) { - return narrow(s.c_str()); + return narrow(s.c_str()); } #endif } diff --git a/include/boost/property_tree/xml_parser.hpp b/include/boost/property_tree/xml_parser.hpp index 4f36e9a0be..0544c55544 100644 --- a/include/boost/property_tree/xml_parser.hpp +++ b/include/boost/property_tree/xml_parser.hpp @@ -102,9 +102,9 @@ namespace boost { namespace property_tree { namespace xml_parser > &stream, const Ptree &pt, const xml_writer_settings< - typename Ptree::key_type::value_type + typename Ptree::key_type > & settings = xml_writer_settings< - typename Ptree::key_type::value_type>() ) + typename Ptree::key_type>() ) { write_xml_internal(stream, pt, std::string(), settings); } @@ -125,9 +125,8 @@ namespace boost { namespace property_tree { namespace xml_parser const Ptree &pt, const std::locale &loc = std::locale(), const xml_writer_settings< - typename Ptree::key_type::value_type - > & settings = xml_writer_settings< - typename Ptree::key_type::value_type>()) + typename Ptree::key_type + > & settings = xml_writer_settings()) { std::basic_ofstream stream(filename.c_str()); diff --git a/test/test_property_tree.hpp b/test/test_property_tree.hpp index f9ac6664fd..9a0b1272ff 100644 --- a/test/test_property_tree.hpp +++ b/test/test_property_tree.hpp @@ -797,9 +797,6 @@ void test_get_put(PTREE *) void test_get_child_put_child(PTREE *) { - - typedef std::basic_string str_t; - PTREE pt(T("ala ma kota")); // Do insertions via put_child @@ -1076,7 +1073,6 @@ void test_custom_data_type(PTREE *) typedef std::basic_string Str; typedef PTREE::key_compare Comp; - typedef PTREE::path_type Path; // Property_tree with boost::any as data type typedef boost::property_tree::basic_ptree my_ptree; diff --git a/test/test_utils.hpp b/test/test_utils.hpp index 2a4a3bdae6..809f91f572 100644 --- a/test/test_utils.hpp +++ b/test/test_utils.hpp @@ -81,13 +81,13 @@ template Ptree get_test_ptree() { using namespace boost::property_tree; - typedef typename Ptree::key_type::value_type Ch; + typedef typename Ptree::key_type Str; Ptree pt; - pt.put_value(detail::widen("data0")); - pt.put(detail::widen("key1"), detail::widen("data1")); - pt.put(detail::widen("key1.key"), detail::widen("data2")); - pt.put(detail::widen("key2"), detail::widen("data3")); - pt.put(detail::widen("key2.key"), detail::widen("data4")); + pt.put_value(detail::widen("data0")); + pt.put(detail::widen("key1"), detail::widen("data1")); + pt.put(detail::widen("key1.key"), detail::widen("data2")); + pt.put(detail::widen("key2"), detail::widen("data3")); + pt.put(detail::widen("key2.key"), detail::widen("data4")); return pt; } @@ -104,7 +104,6 @@ void generic_parser_test(Ptree &pt, { using namespace boost::property_tree; - typedef typename Ptree::key_type::value_type Ch; // Create test files test_file file_1(test_data_1, filename_1); @@ -236,7 +235,8 @@ void check_exact_roundtrip(ReadFunc rf, WriteFunc wf, const char *test_data) { << test_data << "\n-----\n"; using namespace boost::property_tree; typedef typename Ptree::key_type::value_type Ch; - std::basic_string native_test_data = detail::widen(test_data); + typedef typename Ptree::key_type Str; + Str native_test_data = detail::widen(test_data); std::basic_istringstream in_stream(native_test_data); std::basic_ostringstream out_stream; diff --git a/test/test_xml_parser_common.hpp b/test/test_xml_parser_common.hpp index 9679cb57ec..019773bb65 100644 --- a/test/test_xml_parser_common.hpp +++ b/test/test_xml_parser_common.hpp @@ -49,8 +49,7 @@ struct WriteFuncNS void operator()(const std::string &filename, const Ptree &pt) const { boost::property_tree::write_xml(filename, pt, std::locale(), - boost::property_tree::xml_writer_make_settings( - typename Ptree::key_type::value_type(' '), 4)); + boost::property_tree::xml_writer_make_settings(' ', 4)); } }; From 4e16d57fa634fc9ddb64cde1c687e11e23b6e34a Mon Sep 17 00:00:00 2001 From: Alexander Bogdashevsky Date: Wed, 30 Jul 2014 23:25:36 -0400 Subject: [PATCH 22/23] Ticket 10272 --- .../property_tree/detail/xml_parser_write.hpp | 24 ++++----- .../detail/xml_parser_writer_settings.hpp | 25 +++++++++ include/boost/property_tree/xml_parser.hpp | 54 +++++++++++++++---- 3 files changed, 81 insertions(+), 22 deletions(-) diff --git a/include/boost/property_tree/detail/xml_parser_write.hpp b/include/boost/property_tree/detail/xml_parser_write.hpp index 45af878488..f861eabf73 100644 --- a/include/boost/property_tree/detail/xml_parser_write.hpp +++ b/include/boost/property_tree/detail/xml_parser_write.hpp @@ -19,21 +19,21 @@ namespace boost { namespace property_tree { namespace xml_parser { - template - void write_xml_indent(std::basic_ostream &stream, + template + void write_xml_indent(Stream &stream, int indent, - const xml_writer_settings & settings + const Settings & settings ) { - stream << std::basic_string(indent * settings.indent_count, settings.indent_char); + stream << std::basic_string(indent * settings.indent_count, settings.indent_char); } - template + template void write_xml_comment(std::basic_ostream &stream, const Str &s, int indent, bool separate_line, - const xml_writer_settings & settings + const Settings& settings ) { typedef typename Str::value_type Ch; @@ -46,12 +46,12 @@ namespace boost { namespace property_tree { namespace xml_parser stream << Ch('\n'); } - template + template void write_xml_text(std::basic_ostream &stream, const Str &s, int indent, bool separate_line, - const xml_writer_settings & settings + const Settings& settings ) { typedef typename Str::value_type Ch; @@ -62,12 +62,12 @@ namespace boost { namespace property_tree { namespace xml_parser stream << Ch('\n'); } - template + template void write_xml_element(std::basic_ostream &stream, const typename Ptree::key_type &key, const Ptree &pt, int indent, - const xml_writer_settings & settings) + const Settings& settings) { typedef typename Ptree::key_type::value_type Ch; typedef typename Ptree::key_type Str; @@ -177,11 +177,11 @@ namespace boost { namespace property_tree { namespace xml_parser } } - template + template void write_xml_internal(std::basic_ostream &stream, const Ptree &pt, const std::string &filename, - const xml_writer_settings & settings) + const Settings & settings) { typedef typename Ptree::key_type Str; stream << detail::widen(" + class xml_writer_settings + { + public: + xml_writer_settings(char inchar = ' ', + typename std::string::size_type incount = 0, + const std::string &enc = widen("utf-8")) + : indent_char(inchar) + , indent_count(incount) + , encoding(enc) + { + } + + char indent_char; + typename std::string::size_type indent_count; + std::string encoding; + }; + template xml_writer_settings xml_writer_make_settings(typename Str::value_type indent_char = (typename Str::value_type)(' '), typename Str::size_type indent_count = 0, @@ -59,6 +77,13 @@ namespace boost { namespace property_tree { namespace xml_parser return xml_writer_settings(indent_char, indent_count, encoding); } + template + xml_writer_settings xml_writer_make_settings(char indent_char, + size_type indent_count) + { + return xml_writer_settings(indent_char, indent_count, widen("utf-8")); + } + } } } #endif diff --git a/include/boost/property_tree/xml_parser.hpp b/include/boost/property_tree/xml_parser.hpp index 0544c55544..739f622590 100644 --- a/include/boost/property_tree/xml_parser.hpp +++ b/include/boost/property_tree/xml_parser.hpp @@ -96,19 +96,37 @@ namespace boost { namespace property_tree { namespace xml_parser * @param settings The settings to use when writing out the property tree as * XML. */ - template + template void write_xml(std::basic_ostream< typename Ptree::key_type::value_type > &stream, const Ptree &pt, - const xml_writer_settings< - typename Ptree::key_type - > & settings = xml_writer_settings< - typename Ptree::key_type>() ) + const Settings & settings) + { + write_xml_internal(stream, pt, std::string(), settings); + } + + /** + * Translates the property tree to XML and writes it the given output + * stream. + * @throw xml_parser_error In case of error translating the property tree to + * XML or writing to the output stream. + * @param stream The stream to which to write the XML representation of the + * property tree. + * @param pt The property tree to tranlsate to XML and output. + */ + template + void write_xml(std::basic_ostream< + typename Ptree::key_type::value_type + > &stream, + const Ptree &pt ) { + xml_writer_settings settings; + write_xml_internal(stream, pt, std::string(), settings); } + /** * Translates the property tree to XML and writes it the given file. * @throw xml_parser_error In case of error translating the property tree to @@ -120,13 +138,11 @@ namespace boost { namespace property_tree { namespace xml_parser * @param settings The settings to use when writing out the property tree as * XML. */ - template + template void write_xml(const std::string &filename, const Ptree &pt, - const std::locale &loc = std::locale(), - const xml_writer_settings< - typename Ptree::key_type - > & settings = xml_writer_settings()) + const std::locale &loc, + const Settings & settings) { std::basic_ofstream stream(filename.c_str()); @@ -137,6 +153,24 @@ namespace boost { namespace property_tree { namespace xml_parser write_xml_internal(stream, pt, filename, settings); } + /** + * Translates the property tree to XML and writes it the given file. + * @throw xml_parser_error In case of error translating the property tree to + * XML or writing to the output stream. + * @param filename The file to which to write the XML representation of the + * property tree. + * @param pt The property tree to tranlsate to XML and output. + * @param loc The locale to use when writing the output to file. + */ + template + void write_xml(const std::string &filename, + const Ptree &pt, + const std::locale &loc = std::locale()) + { + xml_writer_settings settings; + write_xml(filename, pt, loc, settings); + } + } } } namespace boost { namespace property_tree From 540f5d2f2a2283a11999c3a577e9689b88913e73 Mon Sep 17 00:00:00 2001 From: Alexander Bogdashevsky Date: Sun, 24 Aug 2014 00:13:24 -0400 Subject: [PATCH 23/23] superfluous typename's --- .../boost/property_tree/detail/xml_parser_writer_settings.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/property_tree/detail/xml_parser_writer_settings.hpp b/include/boost/property_tree/detail/xml_parser_writer_settings.hpp index a2ab755a4a..dfdb50affa 100644 --- a/include/boost/property_tree/detail/xml_parser_writer_settings.hpp +++ b/include/boost/property_tree/detail/xml_parser_writer_settings.hpp @@ -56,7 +56,7 @@ namespace boost { namespace property_tree { namespace xml_parser { public: xml_writer_settings(char inchar = ' ', - typename std::string::size_type incount = 0, + std::string::size_type incount = 0, const std::string &enc = widen("utf-8")) : indent_char(inchar) , indent_count(incount) @@ -65,7 +65,7 @@ namespace boost { namespace property_tree { namespace xml_parser } char indent_char; - typename std::string::size_type indent_count; + std::string::size_type indent_count; std::string encoding; };