From e53657b79c819c9d43aa34c2aef8af9556d54d73 Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Sat, 28 Nov 2015 19:00:35 +0300 Subject: [PATCH] update pugixml to version 1.7 --- 3party/pugixml/README.md | 6 +- 3party/pugixml/contrib/foreach.hpp | 0 3party/pugixml/docs/config.adoc | 0 3party/pugixml/docs/images/dom_tree.png | Bin 3party/pugixml/docs/images/vs2005_link1.png | Bin 3party/pugixml/docs/images/vs2005_link2.png | Bin 3party/pugixml/docs/images/vs2005_pch1.png | Bin 3party/pugixml/docs/images/vs2005_pch2.png | Bin 3party/pugixml/docs/images/vs2005_pch3.png | Bin 3party/pugixml/docs/images/vs2005_pch4.png | Bin 3party/pugixml/docs/images/vs2010_link1.png | Bin 3party/pugixml/docs/images/vs2010_link2.png | Bin 3party/pugixml/docs/manual.adoc | 206 +- 3party/pugixml/docs/manual.html | 217 +- 3party/pugixml/docs/quickstart.adoc | 8 +- 3party/pugixml/docs/quickstart.html | 10 +- 3party/pugixml/docs/samples/character.xml | 0 .../docs/samples/custom_memory_management.cpp | 0 3party/pugixml/docs/samples/include.cpp | 2 +- .../docs/samples/load_error_handling.cpp | 0 3party/pugixml/docs/samples/load_file.cpp | 0 3party/pugixml/docs/samples/load_memory.cpp | 0 3party/pugixml/docs/samples/load_options.cpp | 0 3party/pugixml/docs/samples/load_stream.cpp | 0 3party/pugixml/docs/samples/modify_add.cpp | 0 3party/pugixml/docs/samples/modify_base.cpp | 0 3party/pugixml/docs/samples/modify_remove.cpp | 0 .../docs/samples/save_custom_writer.cpp | 0 .../pugixml/docs/samples/save_declaration.cpp | 2 +- 3party/pugixml/docs/samples/save_file.cpp | 0 3party/pugixml/docs/samples/save_options.cpp | 0 3party/pugixml/docs/samples/save_stream.cpp | 0 3party/pugixml/docs/samples/save_subtree.cpp | 0 3party/pugixml/docs/samples/text.cpp | 0 3party/pugixml/docs/samples/transitions.xml | 0 3party/pugixml/docs/samples/traverse_base.cpp | 0 3party/pugixml/docs/samples/traverse_iter.cpp | 0 .../docs/samples/traverse_predicate.cpp | 0 .../docs/samples/traverse_rangefor.cpp | 0 .../pugixml/docs/samples/traverse_walker.cpp | 0 3party/pugixml/docs/samples/tree.xml | 0 .../pugixml/docs/samples/weekly-shift_jis.xml | 0 3party/pugixml/docs/samples/weekly-utf-16.xml | Bin 3party/pugixml/docs/samples/weekly-utf-8.xml | 0 3party/pugixml/docs/samples/xgconsole.xml | 2 +- 3party/pugixml/docs/samples/xpath_error.cpp | 0 3party/pugixml/docs/samples/xpath_query.cpp | 0 3party/pugixml/docs/samples/xpath_select.cpp | 0 .../pugixml/docs/samples/xpath_variables.cpp | 0 3party/pugixml/pugixml.pro | 13 +- 3party/pugixml/readme.txt | 2 +- 3party/pugixml/scripts/CMakeLists.txt | 28 +- 3party/pugixml/scripts/nuget.autopkg | 32 + 3party/pugixml/scripts/nuget_build.bat | 9 + 3party/pugixml/scripts/premake4.lua | 0 .../scripts/pugixml.xcodeproj/project.pbxproj | 0 3party/pugixml/scripts/pugixml_airplay.mkf | 1 + 3party/pugixml/scripts/pugixml_codeblocks.cbp | 1 + .../pugixml/scripts/pugixml_codelite.project | 0 3party/pugixml/src/pugiconfig.hpp | 7 +- 3party/pugixml/src/pugixml.cpp | 3027 +++++++++++------ 3party/pugixml/src/pugixml.hpp | 148 +- 3party/pugixml/tests/allocator.cpp | 27 +- 3party/pugixml/tests/allocator.hpp | 0 3party/pugixml/tests/archive.pl | 0 3party/pugixml/tests/autotest-appveyor.ps1 | 71 + 3party/pugixml/tests/autotest-freebsd.sh | 10 - 3party/pugixml/tests/autotest-linux.sh | 14 - 3party/pugixml/tests/autotest-local.pl | 150 - 3party/pugixml/tests/autotest-macos.sh | 12 - 3party/pugixml/tests/autotest-remote-host.pl | 37 - .../pugixml/tests/autotest-remote-server.pl | 33 - 3party/pugixml/tests/autotest-report.pl | 229 -- 3party/pugixml/tests/autotest-solaris.sh | 10 - 3party/pugixml/tests/common.hpp | 0 3party/pugixml/tests/data/empty.xml | 0 3party/pugixml/tests/data/large.xml | 0 .../pugixml/tests/data/latintest_latin1.xml | 0 3party/pugixml/tests/data/latintest_utf8.xml | 0 3party/pugixml/tests/data/multiline.xml | 0 3party/pugixml/tests/data/small.xml | 0 3party/pugixml/tests/data/truncation.xml | 0 .../pugixml/tests/data/utftest_utf16_be.xml | Bin .../tests/data/utftest_utf16_be_bom.xml | Bin .../tests/data/utftest_utf16_be_clean.xml | Bin .../tests/data/utftest_utf16_be_nodecl.xml | Bin .../pugixml/tests/data/utftest_utf16_le.xml | Bin .../tests/data/utftest_utf16_le_bom.xml | Bin .../tests/data/utftest_utf16_le_clean.xml | Bin .../tests/data/utftest_utf16_le_nodecl.xml | Bin .../pugixml/tests/data/utftest_utf32_be.xml | Bin .../tests/data/utftest_utf32_be_bom.xml | Bin .../tests/data/utftest_utf32_be_clean.xml | Bin .../tests/data/utftest_utf32_be_nodecl.xml | Bin .../pugixml/tests/data/utftest_utf32_le.xml | Bin .../tests/data/utftest_utf32_le_bom.xml | Bin .../tests/data/utftest_utf32_le_clean.xml | Bin .../tests/data/utftest_utf32_le_nodecl.xml | Bin 3party/pugixml/tests/data/utftest_utf8.xml | 0 .../pugixml/tests/data/utftest_utf8_bom.xml | 0 .../pugixml/tests/data/utftest_utf8_clean.xml | 0 .../tests/data/utftest_utf8_nodecl.xml | 0 3party/pugixml/tests/data/тест.xml | 0 .../pugixml/tests/data_fuzz_parse/basic.xml | 2 +- .../pugixml/tests/data_fuzz_parse/doctype.xml | 2 +- 3party/pugixml/tests/data_fuzz_parse/refs.xml | 2 +- .../pugixml/tests/data_fuzz_parse/types.xml | 2 +- .../pugixml/tests/data_fuzz_parse/utf16.xml | Bin .../pugixml/tests/data_fuzz_parse/utf32.xml | Bin 3party/pugixml/tests/fuzz_parse.cpp | 0 3party/pugixml/tests/gcov-filter.pl | 36 - 3party/pugixml/tests/helpers.hpp | 0 3party/pugixml/tests/main.cpp | 55 +- 3party/pugixml/tests/test.cpp | 0 3party/pugixml/tests/test.hpp | 14 +- 3party/pugixml/tests/test_document.cpp | 79 +- 3party/pugixml/tests/test_dom_modify.cpp | 292 +- 3party/pugixml/tests/test_dom_text.cpp | 6 +- 3party/pugixml/tests/test_dom_traverse.cpp | 206 +- 3party/pugixml/tests/test_header_guard.cpp | 0 3party/pugixml/tests/test_header_iosfwd_1.cpp | 0 3party/pugixml/tests/test_header_iosfwd_2.cpp | 0 .../pugixml/tests/test_header_iostream_1.cpp | 0 .../pugixml/tests/test_header_iostream_2.cpp | 0 ...header_only.cpp => test_header_only_1.cpp} | 2 +- 3party/pugixml/tests/test_header_only_2.cpp | 19 + 3party/pugixml/tests/test_header_string_1.cpp | 0 3party/pugixml/tests/test_header_string_2.cpp | 0 .../tests/test_header_string_iostream.cpp | 0 3party/pugixml/tests/test_memory.cpp | 105 +- 3party/pugixml/tests/test_parse.cpp | 80 +- 3party/pugixml/tests/test_parse_doctype.cpp | 0 3party/pugixml/tests/test_unicode.cpp | 0 3party/pugixml/tests/test_version.cpp | 2 +- 3party/pugixml/tests/test_write.cpp | 64 + 3party/pugixml/tests/test_xpath.cpp | 76 +- 3party/pugixml/tests/test_xpath_api.cpp | 279 +- 3party/pugixml/tests/test_xpath_functions.cpp | 58 +- 3party/pugixml/tests/test_xpath_operators.cpp | 6 +- 3party/pugixml/tests/test_xpath_parse.cpp | 25 +- 3party/pugixml/tests/test_xpath_paths.cpp | 0 .../tests/test_xpath_paths_abbrev_w3c.cpp | 0 3party/pugixml/tests/test_xpath_paths_w3c.cpp | 0 3party/pugixml/tests/test_xpath_variables.cpp | 188 +- 3party/pugixml/tests/test_xpath_xalan_1.cpp | 2 +- 3party/pugixml/tests/test_xpath_xalan_2.cpp | 0 3party/pugixml/tests/test_xpath_xalan_3.cpp | 0 3party/pugixml/tests/test_xpath_xalan_4.cpp | 0 3party/pugixml/tests/test_xpath_xalan_5.cpp | 0 3party/pugixml/tests/writer_string.cpp | 0 3party/pugixml/tests/writer_string.hpp | 2 +- 151 files changed, 3731 insertions(+), 2187 deletions(-) mode change 100644 => 100755 3party/pugixml/README.md mode change 100644 => 100755 3party/pugixml/contrib/foreach.hpp mode change 100644 => 100755 3party/pugixml/docs/config.adoc mode change 100644 => 100755 3party/pugixml/docs/images/dom_tree.png mode change 100644 => 100755 3party/pugixml/docs/images/vs2005_link1.png mode change 100644 => 100755 3party/pugixml/docs/images/vs2005_link2.png mode change 100644 => 100755 3party/pugixml/docs/images/vs2005_pch1.png mode change 100644 => 100755 3party/pugixml/docs/images/vs2005_pch2.png mode change 100644 => 100755 3party/pugixml/docs/images/vs2005_pch3.png mode change 100644 => 100755 3party/pugixml/docs/images/vs2005_pch4.png mode change 100644 => 100755 3party/pugixml/docs/images/vs2010_link1.png mode change 100644 => 100755 3party/pugixml/docs/images/vs2010_link2.png mode change 100644 => 100755 3party/pugixml/docs/manual.adoc mode change 100644 => 100755 3party/pugixml/docs/manual.html mode change 100644 => 100755 3party/pugixml/docs/quickstart.adoc mode change 100644 => 100755 3party/pugixml/docs/quickstart.html mode change 100644 => 100755 3party/pugixml/docs/samples/character.xml mode change 100644 => 100755 3party/pugixml/docs/samples/custom_memory_management.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/include.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/load_error_handling.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/load_file.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/load_memory.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/load_options.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/load_stream.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/modify_add.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/modify_base.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/modify_remove.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/save_custom_writer.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/save_declaration.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/save_file.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/save_options.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/save_stream.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/save_subtree.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/text.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/transitions.xml mode change 100644 => 100755 3party/pugixml/docs/samples/traverse_base.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/traverse_iter.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/traverse_predicate.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/traverse_rangefor.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/traverse_walker.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/tree.xml mode change 100644 => 100755 3party/pugixml/docs/samples/weekly-shift_jis.xml mode change 100644 => 100755 3party/pugixml/docs/samples/weekly-utf-16.xml mode change 100644 => 100755 3party/pugixml/docs/samples/weekly-utf-8.xml mode change 100644 => 100755 3party/pugixml/docs/samples/xgconsole.xml mode change 100644 => 100755 3party/pugixml/docs/samples/xpath_error.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/xpath_query.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/xpath_select.cpp mode change 100644 => 100755 3party/pugixml/docs/samples/xpath_variables.cpp mode change 100644 => 100755 3party/pugixml/readme.txt mode change 100644 => 100755 3party/pugixml/scripts/CMakeLists.txt create mode 100755 3party/pugixml/scripts/nuget.autopkg create mode 100755 3party/pugixml/scripts/nuget_build.bat mode change 100644 => 100755 3party/pugixml/scripts/premake4.lua mode change 100644 => 100755 3party/pugixml/scripts/pugixml.xcodeproj/project.pbxproj mode change 100644 => 100755 3party/pugixml/scripts/pugixml_airplay.mkf mode change 100644 => 100755 3party/pugixml/scripts/pugixml_codeblocks.cbp mode change 100644 => 100755 3party/pugixml/scripts/pugixml_codelite.project mode change 100644 => 100755 3party/pugixml/src/pugiconfig.hpp mode change 100644 => 100755 3party/pugixml/src/pugixml.cpp mode change 100644 => 100755 3party/pugixml/src/pugixml.hpp mode change 100644 => 100755 3party/pugixml/tests/allocator.cpp mode change 100644 => 100755 3party/pugixml/tests/allocator.hpp mode change 100644 => 100755 3party/pugixml/tests/archive.pl create mode 100755 3party/pugixml/tests/autotest-appveyor.ps1 delete mode 100644 3party/pugixml/tests/autotest-freebsd.sh delete mode 100644 3party/pugixml/tests/autotest-linux.sh delete mode 100644 3party/pugixml/tests/autotest-local.pl delete mode 100644 3party/pugixml/tests/autotest-macos.sh delete mode 100644 3party/pugixml/tests/autotest-remote-host.pl delete mode 100644 3party/pugixml/tests/autotest-remote-server.pl delete mode 100644 3party/pugixml/tests/autotest-report.pl delete mode 100644 3party/pugixml/tests/autotest-solaris.sh mode change 100644 => 100755 3party/pugixml/tests/common.hpp mode change 100644 => 100755 3party/pugixml/tests/data/empty.xml mode change 100644 => 100755 3party/pugixml/tests/data/large.xml mode change 100644 => 100755 3party/pugixml/tests/data/latintest_latin1.xml mode change 100644 => 100755 3party/pugixml/tests/data/latintest_utf8.xml mode change 100644 => 100755 3party/pugixml/tests/data/multiline.xml mode change 100644 => 100755 3party/pugixml/tests/data/small.xml mode change 100644 => 100755 3party/pugixml/tests/data/truncation.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf16_be.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf16_be_bom.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf16_be_clean.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf16_be_nodecl.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf16_le.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf16_le_bom.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf16_le_clean.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf16_le_nodecl.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf32_be.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf32_be_bom.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf32_be_clean.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf32_be_nodecl.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf32_le.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf32_le_bom.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf32_le_clean.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf32_le_nodecl.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf8.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf8_bom.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf8_clean.xml mode change 100644 => 100755 3party/pugixml/tests/data/utftest_utf8_nodecl.xml mode change 100644 => 100755 3party/pugixml/tests/data/тест.xml mode change 100644 => 100755 3party/pugixml/tests/data_fuzz_parse/basic.xml mode change 100644 => 100755 3party/pugixml/tests/data_fuzz_parse/doctype.xml mode change 100644 => 100755 3party/pugixml/tests/data_fuzz_parse/refs.xml mode change 100644 => 100755 3party/pugixml/tests/data_fuzz_parse/types.xml mode change 100644 => 100755 3party/pugixml/tests/data_fuzz_parse/utf16.xml mode change 100644 => 100755 3party/pugixml/tests/data_fuzz_parse/utf32.xml mode change 100644 => 100755 3party/pugixml/tests/fuzz_parse.cpp delete mode 100644 3party/pugixml/tests/gcov-filter.pl mode change 100644 => 100755 3party/pugixml/tests/helpers.hpp mode change 100644 => 100755 3party/pugixml/tests/main.cpp mode change 100644 => 100755 3party/pugixml/tests/test.cpp mode change 100644 => 100755 3party/pugixml/tests/test.hpp mode change 100644 => 100755 3party/pugixml/tests/test_document.cpp mode change 100644 => 100755 3party/pugixml/tests/test_dom_modify.cpp mode change 100644 => 100755 3party/pugixml/tests/test_dom_text.cpp mode change 100644 => 100755 3party/pugixml/tests/test_dom_traverse.cpp mode change 100644 => 100755 3party/pugixml/tests/test_header_guard.cpp mode change 100644 => 100755 3party/pugixml/tests/test_header_iosfwd_1.cpp mode change 100644 => 100755 3party/pugixml/tests/test_header_iosfwd_2.cpp mode change 100644 => 100755 3party/pugixml/tests/test_header_iostream_1.cpp mode change 100644 => 100755 3party/pugixml/tests/test_header_iostream_2.cpp rename 3party/pugixml/tests/{test_header_only.cpp => test_header_only_1.cpp} (94%) mode change 100644 => 100755 create mode 100755 3party/pugixml/tests/test_header_only_2.cpp mode change 100644 => 100755 3party/pugixml/tests/test_header_string_1.cpp mode change 100644 => 100755 3party/pugixml/tests/test_header_string_2.cpp mode change 100644 => 100755 3party/pugixml/tests/test_header_string_iostream.cpp mode change 100644 => 100755 3party/pugixml/tests/test_memory.cpp mode change 100644 => 100755 3party/pugixml/tests/test_parse.cpp mode change 100644 => 100755 3party/pugixml/tests/test_parse_doctype.cpp mode change 100644 => 100755 3party/pugixml/tests/test_unicode.cpp mode change 100644 => 100755 3party/pugixml/tests/test_version.cpp mode change 100644 => 100755 3party/pugixml/tests/test_write.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_api.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_functions.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_operators.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_parse.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_paths.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_paths_abbrev_w3c.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_paths_w3c.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_variables.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_xalan_1.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_xalan_2.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_xalan_3.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_xalan_4.cpp mode change 100644 => 100755 3party/pugixml/tests/test_xpath_xalan_5.cpp mode change 100644 => 100755 3party/pugixml/tests/writer_string.cpp mode change 100644 => 100755 3party/pugixml/tests/writer_string.hpp diff --git a/3party/pugixml/README.md b/3party/pugixml/README.md old mode 100644 new mode 100755 index 9c6320e296..cdd4663eb2 --- a/3party/pugixml/README.md +++ b/3party/pugixml/README.md @@ -1,4 +1,4 @@ -pugixml [![Build Status](https://travis-ci.org/zeux/pugixml.png?branch=master)](https://travis-ci.org/zeux/pugixml) +pugixml [![Build Status](https://travis-ci.org/zeux/pugixml.svg?branch=master)](https://travis-ci.org/zeux/pugixml) [![Build status](https://ci.appveyor.com/api/projects/status/9hdks1doqvq8pwe7/branch/master?svg=true)](https://ci.appveyor.com/project/zeux/pugixml) [![codecov.io](http://codecov.io/github/zeux/pugixml/coverage.svg?branch=master)](http://codecov.io/github/zeux/pugixml?branch=master) ======= pugixml is a C++ XML processing library, which consists of a DOM-like interface with rich traversal/modification @@ -12,8 +12,8 @@ pugixml is used by a lot of projects, both open-source and proprietary, for perf Documentation for the current release of pugixml is available on-line as two separate documents: -* [Quick-start guide](http://cdn.rawgit.com/zeux/pugixml/v1.5/docs/quickstart.html), that aims to provide enough information to start using the library; -* [Complete reference manual](http://cdn.rawgit.com/zeux/pugixml/v1.5/docs/manual.html), that describes all features of the library in detail. +* [Quick-start guide](http://pugixml.org/docs/quickstart.html), that aims to provide enough information to start using the library; +* [Complete reference manual](http://pugixml.org/docs/manual.html), that describes all features of the library in detail. You’re advised to start with the quick-start guide; however, many important library features are either not described in it at all or only mentioned briefly; if you require more information you should read the complete manual. diff --git a/3party/pugixml/contrib/foreach.hpp b/3party/pugixml/contrib/foreach.hpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/config.adoc b/3party/pugixml/docs/config.adoc old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/dom_tree.png b/3party/pugixml/docs/images/dom_tree.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/vs2005_link1.png b/3party/pugixml/docs/images/vs2005_link1.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/vs2005_link2.png b/3party/pugixml/docs/images/vs2005_link2.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/vs2005_pch1.png b/3party/pugixml/docs/images/vs2005_pch1.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/vs2005_pch2.png b/3party/pugixml/docs/images/vs2005_pch2.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/vs2005_pch3.png b/3party/pugixml/docs/images/vs2005_pch3.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/vs2005_pch4.png b/3party/pugixml/docs/images/vs2005_pch4.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/vs2010_link1.png b/3party/pugixml/docs/images/vs2010_link1.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/images/vs2010_link2.png b/3party/pugixml/docs/images/vs2010_link2.png old mode 100644 new mode 100755 diff --git a/3party/pugixml/docs/manual.adoc b/3party/pugixml/docs/manual.adoc old mode 100644 new mode 100755 index 7441530b7d..62a3e057b2 --- a/3party/pugixml/docs/manual.adoc +++ b/3party/pugixml/docs/manual.adoc @@ -38,7 +38,7 @@ Thanks to *Neville Franks* for contributions to pugxml parser. Thanks to *Artyom Palvelev* for suggesting a lazy gap contraction approach. -Thanks to *Vyacheslav Egorov* for documentation proofreading. +Thanks to *Vyacheslav Egorov* for documentation proofreading and fuzz testing. [[overview.license]] === License @@ -71,7 +71,7 @@ OTHER DEALINGS IN THE SOFTWARE. .... This means that you can freely use pugixml in your applications, both open-source and proprietary. If you use pugixml in a product, it is sufficient to add an acknowledgment like this to the product distribution: - + .... This software is based on pugixml library (http://pugixml.org). pugixml is Copyright (C) 2006-2015 Arseny Kapoulkine. @@ -126,13 +126,25 @@ You can access the Git repository via Subversion using https://github.com/zeux/p svn checkout https://github.com/zeux/pugixml/tags/v{version} pugixml ---- +[[install.getting.packages]] +==== Packages + +pugixml is available as a package via various package managers. Note that most packages are maintained separately from the main repository so they do not necessarily contain the latest version. + +Here's an incomplete list of pugixml packages in various systems: + +* Linux (http://packages.ubuntu.com/search?keywords=pugixml[Ubuntu], https://tracker.debian.org/pkg/pugixml[Debian], https://apps.fedoraproject.org/packages/pugixml[Fedora], https://aur.archlinux.org/packages/pugixml/[Arch Linux], other http://pkgs.org/search/pugixml[distributions]) +* http://fbsdmon.org/ports/textproc/pugixml[FreeBSD] +* OSX, via http://brewformulas.org/Pugixml[Homebrew] +* Windows, via https://www.nuget.org/packages/pugixml/[NuGet] + [[install.building]] === Building pugixml pugixml is distributed in source form without any pre-built binaries; you have to build them yourself. - + The complete pugixml source consists of three files - one source file, `pugixml.cpp`, and two header files, `pugixml.hpp` and `pugiconfig.hpp`. `pugixml.hpp` is the primary header which you need to include in order to use pugixml classes/functions; `pugiconfig.hpp` is a supplementary configuration file (see <>). The rest of this guide assumes that `pugixml.hpp` is either in the current directory or in one of include directories of your projects, so that `#include "pugixml.hpp"` can find the header; however you can also use relative path (i.e. `#include "../libs/pugixml/src/pugixml.hpp"`) or include directory-relative path (i.e. `#include `). - + [[install.building.embed]] ==== Building pugixml as a part of another static library/executable @@ -153,11 +165,11 @@ The correct way to resolve this is to disable precompiled headers for `pugixml.c | image::vs2005_pch3.png[link="images/vs2005_pch3.png"] | image::vs2005_pch4.png[link="images/vs2005_pch4.png"] |=== - + [[install.building.static]] ==== Building pugixml as a standalone static library - -It's possible to compile pugixml as a standalone static library. This process depends on the method of building your application; pugixml distribution comes with project files for several popular IDEs/build systems. There are project files for Apple XCode, Code::Blocks, Codelite, Microsoft Visual Studio 2005, 2008, 2010+, and configuration scripts for CMake and premake4. You're welcome to submit project files/build scripts for other software; see <>. + +It's possible to compile pugixml as a standalone static library. This process depends on the method of building your application; pugixml distribution comes with project files for several popular IDEs/build systems. There are project files for Apple XCode, Code::Blocks, Codelite, Microsoft Visual Studio 2005, 2008, 2010+, and configuration scripts for CMake and premake4. You're welcome to submit project files/build scripts for other software; see <>. There are two projects for each version of Microsoft Visual Studio: one for dynamically linked CRT, which has a name like `pugixml_vs2008.vcproj`, and another one for statically linked CRT, which has a name like `pugixml_vs2008_static.vcproj`. You should select the version that matches the CRT used in your application; the default option for new projects created by Microsoft Visual Studio is dynamically linked CRT, so unless you changed the defaults, you should use the version with dynamic CRT (i.e. `pugixml_vs2008.vcproj` for Microsoft Visual Studio 2008). @@ -175,7 +187,7 @@ In addition to adding pugixml project to your workspace, you'll have to make sur [[install.building.shared]] ==== Building pugixml as a standalone shared library - + It's possible to compile pugixml as a standalone shared library. The process is usually similar to the static library approach; however, no preconfigured projects/scripts are included into pugixml distribution, so you'll have to do it yourself. Generally, if you're using GCC-based toolchain, the process does not differ from building any other library as DLL (adding -shared to compilation flags should suffice); if you're using MSVC-based toolchain, you'll have to explicitly mark exported symbols with a declspec attribute. You can do it by defining <> macro, i.e. via `pugiconfig.hpp`: [source] @@ -216,6 +228,8 @@ pugixml uses several defines to control the compilation process. There are two w [[PUGIXML_WCHAR_MODE]]`PUGIXML_WCHAR_MODE` define toggles between UTF-8 style interface (the in-memory text encoding is assumed to be UTF-8, most functions use `char` as character type) and UTF-16/32 style interface (the in-memory text encoding is assumed to be UTF-16/32, depending on `wchar_t` size, most functions use `wchar_t` as character type). See <> for more details. +[[PUGIXML_COMPACT]]`PUGIXML_COMPACT` define activates a different internal representation of document storage that is much more memory efficient for documents with a lot of markup (i.e. nodes and attributes), but is slightly slower to parse and access. For details see <>. + [[PUGIXML_NO_XPATH]]`PUGIXML_NO_XPATH` define disables XPath. Both XPath interfaces and XPath implementation are excluded from compilation. This option is provided in case you do not need XPath functionality and need to save code space. [[PUGIXML_NO_STL]]`PUGIXML_NO_STL` define disables use of STL in pugixml. The functions that operate on STL types are no longer present (i.e. load/save via iostream) if this macro is defined. This option is provided in case your target platform does not have a standard-compliant STL implementation. @@ -229,29 +243,19 @@ NOTE: In that example `PUGIXML_API` is inconsistent between several source files [[PUGIXML_MEMORY_PAGE_SIZE]]`PUGIXML_MEMORY_PAGE_SIZE`, [[PUGIXML_MEMORY_OUTPUT_STACK]]`PUGIXML_MEMORY_OUTPUT_STACK` and [[PUGIXML_MEMORY_XPATH_PAGE_SIZE]]`PUGIXML_MEMORY_XPATH_PAGE_SIZE` can be used to customize certain important sizes to optimize memory usage for the application-specific patterns. For details see <>. [[PUGIXML_HAS_LONG_LONG]]`PUGIXML_HAS_LONG_LONG` define enables support for `long long` type in pugixml. This define is automatically enabled if your platform is known to have `long long` support (i.e. has C{plus}{plus}11 support or uses a reasonably modern version of a known compiler); if pugixml does not recognize that your platform supports `long long` but in fact it does, you can enable the define manually. - + [[install.portability]] === Portability -pugixml is written in standard-compliant C{plus}{plus} with some compiler-specific workarounds where appropriate. pugixml is compatible with the C{plus}{plus}11 standard, but does not require C{plus}{plus}11 support. Each version is tested with a unit test suite (with code coverage about 99%) on the following platforms: +pugixml is written in standard-compliant C{plus}{plus} with some compiler-specific workarounds where appropriate. pugixml is compatible with the C{plus}{plus}11 standard, but does not require C{plus}{plus}11 support. Each version is tested with a unit test suite with code coverage exceeding 99%. -* Microsoft Windows: -** Borland C{plus}{plus} Compiler 5.82 -** Digital Mars C{plus}{plus} Compiler 8.51 -** Intel C{plus}{plus} Compiler 8.0, 9.0 x86/x64, 10.0 x86/x64, 11.0 x86/x64 -** Metrowerks CodeWarrior 8.0 -** Microsoft Visual C{plus}{plus} 6.0, 7.0 (2002), 7.1 (2003), 8.0 (2005) x86/x64, 9.0 (2008) x86/x64, 10.0 (2010) x86/x64, 11.0 (2011) x86/x64/ARM, 12.0 (2013) x86/x64/ARM and some CLR versions -** MinGW (GCC) 3.4, 4.4, 4.5, 4.6 x64 +pugixml runs on a variety of desktop platforms (including Microsoft Windows, Linux, FreeBSD, Apple MacOSX and Sun Solaris), game consoles (inclusing Microsoft Xbox 360, Microsoft Xbox One, Nintendo Wii, Sony Playstation Portable and Sony Playstation 3) and mobile platforms (including Android, iOS, BlackBerry, Samsung bada and Microsoft Windows CE). -* Linux (GCC 4.4.3 x86/x64, GCC 4.8.1 x64, Clang 3.2 x64) -* FreeBSD (GCC 4.2.1 x86/x64) -* Apple MacOSX (GCC 4.0.1 x86/x64/PowerPC, Clang 3.5 x64) -* Sun Solaris (sunCC x86/x64) -* Microsoft Xbox 360 -* Nintendo Wii (Metrowerks CodeWarrior 4.1) -* Sony Playstation Portable (GCC 3.4.2) -* Sony Playstation 3 (GCC 4.1.1, SNC 310.1) -* Various portable platforms (Android NDK, BlackBerry NDK, Samsung bada, Windows CE) +pugixml supports various architectures, such as x86/x86-64, PowerPC, ARM, MIPS and SPARC. In general it should run on any architecture since it does not use architecture-specific code and does not rely on features such as unaligned memory access. + +pugixml can be compiled using any C++ compiler; it was tested with all versions of Microsoft Visual C{plus}{plus} from 6.0 up to 2015, GCC from 3.4 up to 5.2, Clang from 3.2 up to 3.7, as well as a variety of other compilers (e.g. Borland C{plus}{plus}, Digital Mars C{plus}{plus}, Intel C{plus}{plus}, Metrowerks CodeWarrior and PathScale). The code is written to avoid compilation warnings even on reasonably high warning levels. + +Note that some platforms may have very bare-bones support of C++; in some cases you'll have to use `PUGIXML_NO_STL` and/or `PUGIXML_NO_EXCEPTIONS` to compile without issues. This mostly applies to old game consoles and embedded systems. [[dom]] == Document object model @@ -287,7 +291,7 @@ Here `"node"` element has three children, two of which are PCDATA nodes with val * Character data nodes ([[node_cdata]]`node_cdata`) represent text in XML that is quoted in a special way. CDATA nodes do not differ from PCDATA nodes except in XML representation - the above text example looks like this with CDATA: + ---- - + ---- + CDATA nodes make it easy to include non-escaped `<`, `&` and `>` characters in plain text. CDATA value can not contain the character sequence `]]>`, since it is used to determine the end of node contents. @@ -379,7 +383,7 @@ Both `xml_node` and `xml_attribute` have the default constructor which initializ `xml_node` and `xml_attribute` try to behave like pointers, that is, they can be compared with other objects of the same type, making it possible to use them as keys in associative containers. All handles to the same underlying object are equal, and any two handles to different underlying objects are not equal. Null handles only compare as equal to themselves. The result of relational comparison can not be reliably determined from the order of nodes in file or in any other way. Do not use relational comparison operators except for search optimization (i.e. associative container keys). [[xml_attribute::hash_value]][[xml_node::hash_value]] -If you want to use `xml_node` or `xml_attribute` objects as keys in hash-based associative containers, you can use the `hash_value` member functions. They return the hash values that are guaranteed to be the same for all handles to the same underlying object. The hash value for null handles is 0. +If you want to use `xml_node` or `xml_attribute` objects as keys in hash-based associative containers, you can use the `hash_value` member functions. They return the hash values that are guaranteed to be the same for all handles to the same underlying object. The hash value for null handles is 0. Note that hash value does not depend on the content of the node, only on the location of the underlying structure in memory - this means that loading the same document twice will likely produce different hash values, and copying the node will not preserve the hash. [[xml_attribute::unspecified_bool_type]][[xml_node::unspecified_bool_type]][[xml_attribute::empty]][[xml_node::empty]] Finally handles can be implicitly cast to boolean-like objects, so that you can test if the node/attribute is empty with the following code: `if (node) { ... }` or `if (!node) { ... } else { ... }`. Alternatively you can check if a given `xml_node`/`xml_attribute` handle is null by calling the following methods: @@ -418,7 +422,7 @@ bool xml_node::set_name(const wchar_t* value); [[char_t]][[string_t]] There is a special type, `pugi::char_t`, that is defined as the character type and depends on the library configuration; it will be also used in the documentation hereafter. There is also a type `pugi::string_t`, which is defined as the STL string of the character type; it corresponds to `std::string` in char mode and to `std::wstring` in wchar_t mode. -In addition to the interface, the internal implementation changes to store XML data as `pugi::char_t`; this means that these two modes have different memory usage characteristics. The conversion to `pugi::char_t` upon document loading and from `pugi::char_t` upon document saving happen automatically, which also carries minor performance penalty. The general advice however is to select the character mode based on usage scenario, i.e. if UTF-8 is inconvenient to process and most of your XML data is non-ASCII, wchar_t mode is probably a better choice. +In addition to the interface, the internal implementation changes to store XML data as `pugi::char_t`; this means that these two modes have different memory usage characteristics - generally UTF-8 mode is more memory and performance efficient, especially if `sizeof(wchar_t)` is 4. The conversion to `pugi::char_t` upon document loading and from `pugi::char_t` upon document saving happen automatically, which also carries minor performance penalty. The general advice however is to select the character mode based on usage scenario, i.e. if UTF-8 is inconvenient to process and most of your XML data is non-ASCII, wchar_t mode is probably a better choice. [[as_utf8]][[as_wide]] There are cases when you'll have to convert string data between UTF-8 and wchar_t encodings; the following helper functions are provided for such purposes: @@ -447,7 +451,7 @@ you'll have to use `xml_node node = doc.child(L"bookstore").find_child_by_attribute(L"book", L"id", L"12345");` ==== - + [[dom.thread]] === Thread-safety guarantees @@ -497,7 +501,7 @@ allocation_function get_memory_allocation_function(); deallocation_function get_memory_deallocation_function(); ---- -Allocation function is called with the size (in bytes) as an argument and should return a pointer to a memory block with alignment that is suitable for storage of primitive types (usually a maximum of `void*` and `double` types alignment is sufficient) and size that is greater than or equal to the requested one. If the allocation fails, the function has to return null pointer (throwing an exception from allocation function results in undefined behavior). +Allocation function is called with the size (in bytes) as an argument and should return a pointer to a memory block with alignment that is suitable for storage of primitive types (usually a maximum of `void*` and `double` types alignment is sufficient) and size that is greater than or equal to the requested one. If the allocation fails, the function has to either return null pointer or to throw an exception. Deallocation function is called with the pointer that was returned by some call to allocation function; it is never called with a null pointer. If memory management functions are not thread-safe, library thread safety is not guaranteed. @@ -505,11 +509,11 @@ This is a simple example of custom memory management (link:samples/custom_memory [source,indent=0] ---- -include::samples/custom_memory_management.cpp[tags=decl] +include::samples/custom_memory_management.cpp[tags=decl] ---- [source,indent=0] ---- -include::samples/custom_memory_management.cpp[tags=call] +include::samples/custom_memory_management.cpp[tags=call] ---- When setting new memory management functions, care must be taken to make sure that there are no live pugixml objects. Otherwise when the objects are destroyed, the new deallocation function will be called with the memory obtained by the old allocation function, resulting in undefined behavior. @@ -536,6 +540,17 @@ When the document is loaded from file/buffer, unless an inplace loading function All additional memory, such as memory for document structure (node/attribute objects) and memory for node/attribute names/values is allocated in pages on the order of 32 Kb; actual objects are allocated inside the pages using a memory management scheme optimized for fast allocation/deallocation of many small objects. Because of the scheme specifics, the pages are only destroyed if all objects inside them are destroyed; also, generally destroying an object does not mean that subsequent object creation will reuse the same memory. This means that it is possible to devise a usage scheme which will lead to higher memory usage than expected; one example is adding a lot of nodes, and them removing all even numbered ones; not a single page is reclaimed in the process. However this is an example specifically crafted to produce unsatisfying behavior; in all practical usage scenarios the memory consumption is less than that of a general-purpose allocator because allocation meta-data is very small in size. +[[dom.memory.compact]] +==== Compact mode + +By default nodes and attributes are optimized for efficiency of access. This can cause them to take a significant amount of memory - for documents with a lot of nodes and not a lot of contents (short attribute values/node text), and depending on the pointer size, the document structure can take noticeably more memory than the document itself (e.g. on a 64-bit platform in UTF-8 mode a markup-heavy document with the file size of 2.1 Mb can use 2.1 Mb for document buffer and 8.3 Mb for document structure). + +If you are processing big documents or your platform is memory constrained and you're willing to sacrifice a bit of performance for memory, you can compile pugixml with `PUGIXML_COMPACT` define which will activate compact mode. Compact mode uses a different representation of the document structure that assumes locality of reference between nodes and attributes to optimize memory usage. As a result you get significantly smaller node/attribute objects; usually most objects in most documents don't require additional storage, but in the worst case - if assumptions about locality of reference don't hold - additional memory will be allocated to store the extra data required. + +The compact storage supports all existing operations - including tree modification - with the same amortized complexity (that is, all basic document manipulations are still O(1) on average). The operations are slightly slower; you can usually expect 10-50% slowdown in terms of processing time unless your processing was memory-bound. + +On 32-bit architectures document structure in compact mode is typically reduced by around 2.5x; on 64-bit architectures the ratio is around 5x. Thus for big markup-heavy documents compact mode can make the difference between the processing of a multi-gigabyte document running completely from RAM vs requiring swapping to disk. Even if the document fits into memory, compact storage can use CPU caches more efficiently by taking less space and causing less cache/TLB misses. + [[loading]] == Loading document @@ -554,7 +569,7 @@ The most common source of XML data is files; pugixml provides dedicated function xml_parse_result xml_document::load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); xml_parse_result xml_document::load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); ---- - + These functions accept the file path as its first argument, and also two optional arguments, which specify parsing options (see <>) and input data encoding (see <>). The path has the target operating system format, so it can be a relative or absolute one, it should have the delimiters of the target system, it should have the exact case if the target file system is case-sensitive, etc. File path is passed to the system file opening function as is in case of the first function (which accepts `const char* path`); the second function either uses a special file opening function if it is provided by the runtime library or converts the path to UTF-8 and uses the system file opening function. @@ -565,7 +580,7 @@ This is an example of loading XML document from file (link:samples/load_file.cpp [source,indent=0] ---- -include::samples/load_file.cpp[tags=code] +include::samples/load_file.cpp[tags=code] ---- [[loading.memory]] @@ -601,25 +616,25 @@ This is an example of loading XML document from memory using different functions [source,indent=0] ---- -include::samples/load_memory.cpp[tags=decl] +include::samples/load_memory.cpp[tags=decl] ---- [source,indent=0] ---- -include::samples/load_memory.cpp[tags=load_buffer] +include::samples/load_memory.cpp[tags=load_buffer] ---- [source,indent=0] ---- -include::samples/load_memory.cpp[tags=load_buffer_inplace_begin] +include::samples/load_memory.cpp[tags=load_buffer_inplace_begin] -include::samples/load_memory.cpp[tags=load_buffer_inplace_end] +include::samples/load_memory.cpp[tags=load_buffer_inplace_end] ---- [source,indent=0] ---- -include::samples/load_memory.cpp[tags=load_buffer_inplace_own] +include::samples/load_memory.cpp[tags=load_buffer_inplace_own] ---- [source,indent=0] ---- -include::samples/load_memory.cpp[tags=load_string] +include::samples/load_memory.cpp[tags=load_string] ---- [[loading.stream]] @@ -642,7 +657,7 @@ This is a simple example of loading XML document from file using streams (link:s [source,indent=0] ---- -include::samples/load_stream.cpp[tags=code] +include::samples/load_stream.cpp[tags=code] ---- [[loading.errors]] @@ -703,7 +718,7 @@ This is an example of handling loading errors (link:samples/load_error_handling. [source,indent=0] ---- -include::samples/load_error_handling.cpp[tags=code] +include::samples/load_error_handling.cpp[tags=code] ---- [[loading.options]] @@ -759,7 +774,7 @@ This is an example of using different parsing options (link:samples/load_options [source,indent=0] ---- -include::samples/load_options.cpp[tags=code] +include::samples/load_options.cpp[tags=code] ---- [[loading.encoding]] @@ -820,7 +835,7 @@ pugixml features an extensive interface for getting various types of data from t [[xml_node::parent]][[xml_node::first_child]][[xml_node::last_child]][[xml_node::next_sibling]][[xml_node::previous_sibling]][[xml_node::first_attribute]][[xml_node::last_attribute]][[xml_attribute::next_attribute]][[xml_attribute::previous_attribute]] The internal representation of the document is a tree, where each node has a list of child nodes (the order of children corresponds to their order in the XML representation), and additionally element nodes have a list of attributes, which is also ordered. Several functions are provided in order to let you get from one node in the tree to the other. These functions roughly correspond to the internal representation, and thus are usually building blocks for other methods of traversing (i.e. XPath traversals are based on these functions). - + [source] ---- xml_node xml_node::parent() const; @@ -845,7 +860,7 @@ With these functions, you can iterate through all child nodes and display all at [source,indent=0] ---- -include::samples/traverse_base.cpp[tags=basic] +include::samples/traverse_base.cpp[tags=basic] ---- [[access.nodedata]] @@ -904,7 +919,7 @@ It returns `def` argument if the attribute handle is null. If you do not specify [[xml_attribute::as_int]][[xml_attribute::as_uint]][[xml_attribute::as_double]][[xml_attribute::as_float]][[xml_attribute::as_bool]][[xml_attribute::as_llong]][[xml_attribute::as_ullong]] In many cases attribute values have types that are not strings - i.e. an attribute may always contain values that should be treated as integers, despite the fact that they are represented as strings in XML. pugixml provides several accessors that convert attribute value to some other type: - + [source] ---- int xml_attribute::as_int(int def = 0) const; @@ -931,7 +946,7 @@ This is an example of using these functions, along with node data retrieval ones [source,indent=0] ---- -include::samples/traverse_base.cpp[tags=data] +include::samples/traverse_base.cpp[tags=data] ---- [[access.contents]] @@ -974,7 +989,7 @@ This is an example of using these functions (link:samples/traverse_base.cpp[]): [source,indent=0] ---- -include::samples/traverse_base.cpp[tags=contents] +include::samples/traverse_base.cpp[tags=contents] ---- [[access.rangefor]] @@ -996,7 +1011,7 @@ This is an example of using these functions (link:samples/traverse_rangefor.cpp[ [source,indent=0] ---- -include::samples/traverse_rangefor.cpp[tags=code] +include::samples/traverse_rangefor.cpp[tags=code] ---- [[access.iterators]] @@ -1029,7 +1044,7 @@ Here is an example of using iterators for document traversal (link:samples/trave [source,indent=0] ---- -include::samples/traverse_iter.cpp[tags=code] +include::samples/traverse_iter.cpp[tags=code] ---- CAUTION: Node and attribute iterators are somewhere in the middle between const and non-const iterators. While dereference operation yields a non-constant reference to the object, so that you can use it for tree modification operations, modifying this reference using assignment - i.e. passing iterators to a function like `std::sort` - will not give expected results, as assignment modifies local handle that's stored in the iterator. @@ -1071,11 +1086,11 @@ This is an example of traversing tree hierarchy with xml_tree_walker (link:sampl [source,indent=0] ---- -include::samples/traverse_walker.cpp[tags=impl] +include::samples/traverse_walker.cpp[tags=impl] ---- [source,indent=0] ---- -include::samples/traverse_walker.cpp[tags=traverse] +include::samples/traverse_walker.cpp[tags=traverse] ---- [[access.predicate]] @@ -1103,11 +1118,11 @@ This is an example of using predicate-based functions (link:samples/traverse_pre [source,indent=0] ---- -include::samples/traverse_predicate.cpp[tags=decl] +include::samples/traverse_predicate.cpp[tags=decl] ---- [source,indent=0] ---- -include::samples/traverse_predicate.cpp[tags=find] +include::samples/traverse_predicate.cpp[tags=find] ---- [[access.text]] @@ -1118,7 +1133,7 @@ It is common to store data as text contents of some node - i.e. ``, node `` has path `"a/b/c"`; calling `first_element_by_path` for document with path `"a/b"` results in node ``; calling `first_element_by_path` for node `` with path `"../a/./b/../."` results in node ``; calling `first_element_by_path` with path `"/a"` results in node `` for any node. -In case path component is ambiguous (if there are two nodes with given name), the first one is selected; paths are not guaranteed to uniquely identify nodes in a document. If any component of a path is not found, the result of `first_element_by_path` is null node; also `first_element_by_path` returns null node for null nodes, in which case the path does not matter. `path` returns an empty string for null nodes. +In case path component is ambiguous (if there are two nodes with given name), the first one is selected; paths are not guaranteed to uniquely identify nodes in a document. If any component of a path is not found, the result of `first_element_by_path` is null node; also `first_element_by_path` returns null node for null nodes, in which case the path does not matter. `path` returns an empty string for null nodes. NOTE: `path` function returns the result as STL string, and thus is not available if <> is defined. @@ -1243,7 +1258,7 @@ This is an example of setting node name and value (link:samples/modify_base.cpp[ [source,indent=0] ---- -include::samples/modify_base.cpp[tags=node] +include::samples/modify_base.cpp[tags=node] ---- [[modify.attrdata]] @@ -1272,7 +1287,7 @@ bool xml_attribute::set_value(bool rhs); bool xml_attribute::set_value(long long rhs); bool xml_attribute::set_value(unsigned long long rhs); ---- - + The above functions convert the argument to string and then call the base `set_value` function. Integers are converted to a decimal form, floating-point numbers are converted to either decimal or scientific form, depending on the number magnitude, boolean values are converted to either `"true"` or `"false"`. CAUTION: Number conversion functions depend on current C locale as set with `setlocale`, so may generate unexpected results if the locale is different from `"C"`. @@ -1301,7 +1316,7 @@ This is an example of setting attribute name and value (link:samples/modify_base [source,indent=0] ---- -include::samples/modify_base.cpp[tags=attr] +include::samples/modify_base.cpp[tags=attr] ---- [[modify.add]] @@ -1350,7 +1365,7 @@ This is an example of adding new attributes/nodes to the document (link:samples/ [source,indent=0] ---- -include::samples/modify_add.cpp[tags=code] +include::samples/modify_add.cpp[tags=code] ---- [[modify.remove]] @@ -1387,7 +1402,7 @@ This is an example of removing attributes/nodes from the document (link:samples/ [source,indent=0] ---- -include::samples/modify_remove.cpp[tags=code] +include::samples/modify_remove.cpp[tags=code] ---- [[modify.text]] @@ -1418,7 +1433,7 @@ bool xml_text::set(bool rhs); bool xml_text::set(long long rhs); bool xml_text::set(unsigned long long rhs); ---- - + The above functions convert the argument to string and then call the base `set` function. These functions have the same semantics as similar `xml_attribute` functions. You can <> for details. [[xml_text::assign]] @@ -1443,7 +1458,7 @@ This is an example of using `xml_text` object to modify text contents (link:samp [source,indent=0] ---- -include::samples/text.cpp[tags=modify] +include::samples/text.cpp[tags=modify] ---- [[modify.clone]] @@ -1479,7 +1494,7 @@ This is an example with one possible implementation of include tags in XML (link [source,indent=0] ---- -include::samples/include.cpp[tags=code] +include::samples/include.cpp[tags=code] ---- [[modify.move]] @@ -1582,7 +1597,7 @@ This is a simple example of saving XML document to file (link:samples/save_file. [source,indent=0] ---- -include::samples/save_file.cpp[tags=code] +include::samples/save_file.cpp[tags=code] ---- [[saving.stream]] @@ -1606,7 +1621,7 @@ This is a simple example of saving XML document to standard output (link:samples [source,indent=0] ---- -include::samples/save_stream.cpp[tags=code] +include::samples/save_stream.cpp[tags=code] ---- [[saving.writer]] @@ -1634,7 +1649,7 @@ This is a simple example of custom writer for saving document data to STL string [source,indent=0] ---- -include::samples/save_custom_writer.cpp[tags=code] +include::samples/save_custom_writer.cpp[tags=code] ---- [[saving.subtree]] @@ -1656,7 +1671,7 @@ Saving a subtree differs from saving the whole document: the process behaves as [source,indent=0] ---- -include::samples/save_subtree.cpp[tags=code] +include::samples/save_subtree.cpp[tags=code] ---- [[saving.options]] @@ -1668,7 +1683,9 @@ NOTE: You should use the usual bitwise arithmetics to manipulate the bitmask: to These flags control the resulting tree contents: -* [[format_indent]]`format_indent` determines if all nodes should be indented with the indentation string (this is an additional parameter for all saving functions, and is `"\t"` by default). If this flag is on, before every node the indentation string is output several times, where the amount of indentation depends on the node's depth relative to the output subtree. This flag has no effect if <> is enabled. This flag is *on* by default. +* [[format_indent]]`format_indent` determines if all nodes should be indented with the indentation string (this is an additional parameter for all saving functions, and is `"\t"` by default). If this flag is on, the indentation string is printed several times before every node, where the amount of indentation depends on the node's depth relative to the output subtree. This flag has no effect if <> is enabled. This flag is *on* by default. + +* [[format_indent_attributes]]`format_indent_attributes` determines if all attributes should be printed on a new line, indented with the indentation string according to the attribute's depth. This flag implies <>. This flag has no effect if <> is enabled. This flag is *off* by default. * [[format_raw]]`format_raw` switches between formatted and raw output. If this flag is on, the nodes are not indented in any way, and also no newlines that are not part of document text are printed. Raw mode can be used for serialization where the result is not intended to be read by humans; also it can be useful if the document was parsed with <> flag, to preserve the original document formatting as much as possible. This flag is *off* by default. @@ -1691,7 +1708,7 @@ This is an example that shows the outputs of different output options (link:samp [source,indent=0] ---- -include::samples/save_options.cpp[tags=code] +include::samples/save_options.cpp[tags=code] ---- [[saving.encoding]] @@ -1718,7 +1735,7 @@ This is an example that shows how to create a custom declaration node (link:samp [source,indent=0] ---- -include::samples/save_declaration.cpp[tags=code] +include::samples/save_declaration.cpp[tags=code] ---- [[xpath]] @@ -1852,7 +1869,7 @@ This is an example of selecting nodes using XPath expressions (link:samples/xpat [source,indent=0] ---- -include::samples/xpath_select.cpp[tags=code] +include::samples/xpath_select.cpp[tags=code] ---- [[xpath.query]] @@ -1865,7 +1882,7 @@ When you call `select_nodes` with an expression string as an argument, a query o * You can use query objects to evaluate XPath expressions which result in booleans, numbers or strings; * You can get the type of expression value via query object. -Query objects correspond to `xpath_query` type. They are immutable and non-copyable: they are bound to the expression at creation time and can not be cloned. If you want to put query objects in a container, allocate them on heap via `new` operator and store pointers to `xpath_query` in the container. +Query objects correspond to `xpath_query` type. They are immutable and non-copyable: they are bound to the expression at creation time and can not be cloned. If you want to put query objects in a container, either allocate them on heap via `new` operator and store pointers to `xpath_query` in the container, or use a C++11 compiler (query objects are movable in C++11). [[xpath_query::ctor]] You can create a query object with the constructor that takes XPath expression as an argument: @@ -1907,7 +1924,7 @@ Note that `evaluate_string` function returns the STL string; as such, it's not a size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const; ---- -This function evaluates the string, and then writes the result to `buffer` (but at most `capacity` characters); then it returns the full size of the result in characters, including the terminating zero. If `capacity` is not 0, the resulting buffer is always zero-terminated. You can use this function as follows: +This function evaluates the string, and then writes the result to `buffer` (but at most `capacity` characters); then it returns the full size of the result in characters, including the terminating zero. If `capacity` is not 0, the resulting buffer is always zero-terminated. You can use this function as follows: * First call the function with `buffer = 0` and `capacity = 0`; then allocate the returned amount of characters, and call the function again, passing the allocated storage and the amount of characters; * First call the function with small buffer and buffer capacity; then, if the result is larger than the capacity, the output has been trimmed, so allocate a larger buffer and call the function again. @@ -1916,7 +1933,7 @@ This is an example of using query objects (link:samples/xpath_query.cpp[]): [source,indent=0] ---- -include::samples/xpath_query.cpp[tags=code] +include::samples/xpath_query.cpp[tags=code] ---- [[xpath.variables]] @@ -2020,7 +2037,7 @@ This is an example of using variables in XPath queries (link:samples/xpath_varia [source,indent=0] ---- -include::samples/xpath_variables.cpp[tags=code] +include::samples/xpath_variables.cpp[tags=code] ---- [[xpath.errors]] @@ -2044,7 +2061,7 @@ If exceptions are disabled, then in the event of parsing failure the query is in ---- const xpath_parse_result& xpath_query::result() const; ---- - + Without exceptions, evaluating invalid query results in `false`, empty string, `NaN` or an empty node set, depending on the type; evaluating a query as a node set results in an empty node set if the return type is not node set. [[xpath_parse_result]] @@ -2078,7 +2095,7 @@ This is an example of XPath error handling (link:samples/xpath_error.cpp[]): [source,indent=0] ---- -include::samples/xpath_error.cpp[tags=code] +include::samples/xpath_error.cpp[tags=code] ---- [[xpath.w3c]] @@ -2097,6 +2114,31 @@ Because of the differences in document object models, performance considerations :!numbered: +[[v1.7]] +=== v1.7 ^19.10.2015^ + +Major release, featuring performance and memory improvements along with some new features. Changes: + +* Compact mode: + . Introduced a new tree storage mode that takes significantly less memory (2-5x smaller DOM) at some performance cost. + . The mode can be enabled using `PUGIXML_COMPACT` define. + +* New integer parsing/formatting implementation: + . Functions that convert from and to integers (e.g. `as_int`/`set_value`) do not rely on CRT any more. + . New implementation is 3-5x faster and is always correct wrt overflow or underflow. This is a behavior change - where previously `as_uint()` would return UINT_MAX on a value "-1", it now returns 0. + +* New features: + . XPath objects (`xpath_query`, `xpath_node_set`, `xpath_variable_set`) are now movable if your compiler supports C++11. Additionally, `xpath_variable_set` is copyable. + . Added `format_indent_attributes` that makes the resulting XML friendlier to line diff/merge tools. + . Added a variant of `xml_node::attribute` function with a hint that can improve lookup performance. + . Custom allocation functions are now allowed (but not required) to throw instead of returning a null pointer. + +* Bug fixes: + . Fix Clang 3.7 crashes in out-of-memory cases (C++ DR 1748) + . Fix XPath crashes on SPARC64 (and other 32-bit architectures where doubles have to be aligned to 8 bytes) + . Fix xpath_node_set assignment to provide strong exception guarantee + . Fix saving for custom xml_writer implementations that can throw from write() + [[v1.6]] === v1.6 ^10.04.2015^ @@ -2459,6 +2501,7 @@ This is the reference for all macros, types, enumerations, classes and functions [source,subs="+macros"] ---- #define +++PUGIXML_WCHAR_MODE+++ +#define +++PUGIXML_COMPACT+++ #define +++PUGIXML_NO_XPATH+++ #define +++PUGIXML_NO_STL+++ #define +++PUGIXML_NO_EXCEPTIONS+++ @@ -2546,6 +2589,7 @@ enum +++xpath_value_type+++ // Formatting options bit flags: const unsigned int +++format_default+++ const unsigned int +++format_indent+++ +const unsigned int +++format_indent_attributes+++ const unsigned int +++format_no_declaration+++ const unsigned int +++format_no_escapes+++ const unsigned int +++format_raw+++ @@ -2570,7 +2614,7 @@ const unsigned int +++parse_ws_pcdata_singleparse_wconv_attribute+++ const unsigned int +++parse_wnorm_attribute+++ ---- - + [[apiref.classes]] === Classes diff --git a/3party/pugixml/docs/manual.html b/3party/pugixml/docs/manual.html old mode 100644 new mode 100755 index 99cc6545f1..5fd778527d --- a/3party/pugixml/docs/manual.html +++ b/3party/pugixml/docs/manual.html @@ -6,7 +6,7 @@ -pugixml 1.6 manual +pugixml 1.7 manual -

pugixml autotest report

- -END - -# print configuration header (release/debug) -print ""; -print &prettybox((split /\s+/)[0] eq 'release') foreach (@configurationarray); -print "\n"; - -# print defines header (one row for each define) -foreach $define (sort {$a cmp $b} keys %defines) -{ - print ""; - - foreach (@configurationarray) - { - my $present = ($_ =~ /\b$define\b/); - - print &prettybox($present); - } - print "\n"; -} - -# print data (one row for each toolset) -foreach $tool (@toolsetarray) -{ - my ($platform, $toolset) = split(/\s+/, $tool, 2); - print ""; - - foreach (@configurationarray) - { - my $info = $results{$tool}{$_}; - - if (!defined $$info{result}) - { - print ""; - } - elsif ($$info{result} eq "success") - { - my $coverage = $$info{coverage}; - - print ""; - } - elsif ($$info{result} eq "skiprun") - { - print "" - } - else - { - print "" - } - } - - print "\n"; -} - -# print footer -$date = localtime; - -print <
-Generated on $date from Git $revision - -END diff --git a/3party/pugixml/tests/autotest-solaris.sh b/3party/pugixml/tests/autotest-solaris.sh deleted file mode 100644 index 96111a77b4..0000000000 --- a/3party/pugixml/tests/autotest-solaris.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# put this to /etc/init.d/pugixml-autotest.sh, then launch -# ln -s /etc/init.d/pugixml-autotest.sh /etc/rc3.d/S80pugixml-autotest -# don't forget to chmod +x pugixml-autotest.sh and to replace /export/home/USERNAME with actual path - -if [ "$1" = "start" ] -then - cd /export/home/USERNAME/pugixml - perl tests/autotest-remote-host.pl "shutdown -g 0 -i 5 -y" & -fi diff --git a/3party/pugixml/tests/common.hpp b/3party/pugixml/tests/common.hpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/empty.xml b/3party/pugixml/tests/data/empty.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/large.xml b/3party/pugixml/tests/data/large.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/latintest_latin1.xml b/3party/pugixml/tests/data/latintest_latin1.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/latintest_utf8.xml b/3party/pugixml/tests/data/latintest_utf8.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/multiline.xml b/3party/pugixml/tests/data/multiline.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/small.xml b/3party/pugixml/tests/data/small.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/truncation.xml b/3party/pugixml/tests/data/truncation.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf16_be.xml b/3party/pugixml/tests/data/utftest_utf16_be.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf16_be_bom.xml b/3party/pugixml/tests/data/utftest_utf16_be_bom.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf16_be_clean.xml b/3party/pugixml/tests/data/utftest_utf16_be_clean.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf16_be_nodecl.xml b/3party/pugixml/tests/data/utftest_utf16_be_nodecl.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf16_le.xml b/3party/pugixml/tests/data/utftest_utf16_le.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf16_le_bom.xml b/3party/pugixml/tests/data/utftest_utf16_le_bom.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf16_le_clean.xml b/3party/pugixml/tests/data/utftest_utf16_le_clean.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf16_le_nodecl.xml b/3party/pugixml/tests/data/utftest_utf16_le_nodecl.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf32_be.xml b/3party/pugixml/tests/data/utftest_utf32_be.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf32_be_bom.xml b/3party/pugixml/tests/data/utftest_utf32_be_bom.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf32_be_clean.xml b/3party/pugixml/tests/data/utftest_utf32_be_clean.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf32_be_nodecl.xml b/3party/pugixml/tests/data/utftest_utf32_be_nodecl.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf32_le.xml b/3party/pugixml/tests/data/utftest_utf32_le.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf32_le_bom.xml b/3party/pugixml/tests/data/utftest_utf32_le_bom.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf32_le_clean.xml b/3party/pugixml/tests/data/utftest_utf32_le_clean.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf32_le_nodecl.xml b/3party/pugixml/tests/data/utftest_utf32_le_nodecl.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf8.xml b/3party/pugixml/tests/data/utftest_utf8.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf8_bom.xml b/3party/pugixml/tests/data/utftest_utf8_bom.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf8_clean.xml b/3party/pugixml/tests/data/utftest_utf8_clean.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/utftest_utf8_nodecl.xml b/3party/pugixml/tests/data/utftest_utf8_nodecl.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data/тест.xml b/3party/pugixml/tests/data/тест.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data_fuzz_parse/basic.xml b/3party/pugixml/tests/data_fuzz_parse/basic.xml old mode 100644 new mode 100755 index f026c64472..a8eaa09d4d --- a/3party/pugixml/tests/data_fuzz_parse/basic.xml +++ b/3party/pugixml/tests/data_fuzz_parse/basic.xml @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/3party/pugixml/tests/data_fuzz_parse/doctype.xml b/3party/pugixml/tests/data_fuzz_parse/doctype.xml old mode 100644 new mode 100755 index 125bf2ee38..dd1831d1c7 --- a/3party/pugixml/tests/data_fuzz_parse/doctype.xml +++ b/3party/pugixml/tests/data_fuzz_parse/doctype.xml @@ -1 +1 @@ - ]> ]]> ]> ]> \ No newline at end of file + ]> ]]> ]> ]> \ No newline at end of file diff --git a/3party/pugixml/tests/data_fuzz_parse/refs.xml b/3party/pugixml/tests/data_fuzz_parse/refs.xml old mode 100644 new mode 100755 index d8f3ee48f6..e42df5f699 --- a/3party/pugixml/tests/data_fuzz_parse/refs.xml +++ b/3party/pugixml/tests/data_fuzz_parse/refs.xml @@ -1 +1 @@ - pcdata < > & " ' « &unknown; %entity; \ No newline at end of file + pcdata < > & " ' « &unknown; %entity; \ No newline at end of file diff --git a/3party/pugixml/tests/data_fuzz_parse/types.xml b/3party/pugixml/tests/data_fuzz_parse/types.xml old mode 100644 new mode 100755 index fc837f172f..dc6369a4a1 --- a/3party/pugixml/tests/data_fuzz_parse/types.xml +++ b/3party/pugixml/tests/data_fuzz_parse/types.xml @@ -1 +1 @@ - pcdata \ No newline at end of file + pcdata \ No newline at end of file diff --git a/3party/pugixml/tests/data_fuzz_parse/utf16.xml b/3party/pugixml/tests/data_fuzz_parse/utf16.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/data_fuzz_parse/utf32.xml b/3party/pugixml/tests/data_fuzz_parse/utf32.xml old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/fuzz_parse.cpp b/3party/pugixml/tests/fuzz_parse.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/gcov-filter.pl b/3party/pugixml/tests/gcov-filter.pl deleted file mode 100644 index f0d201972c..0000000000 --- a/3party/pugixml/tests/gcov-filter.pl +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/perl - -sub funcinfo -{ - my ($name, $info) = @_; - - return if ($info =~ /No executable lines/); - - my $lines = ($info =~ /Lines executed:([^%]+)%/) ? $1 : 100; - my $calls = ($info =~ /Calls executed:([^%]+)%/) ? $1 : 100; - my $branches = ($info =~ /Branches executed:([^%]+)%/) ? $1 : 100; - my $taken = ($info =~ /Taken at least once:([^%]+)%/) ? $1 : 100; - - return if ($lines == 100 && $calls == 100 && $branches == 100 && $taken == 100); - - return "Function $name: L $lines, C $calls, B $branches, BT $taken\n"; -} - -$prefix = join(' ', @ARGV); -$prefix .= ' ' if ($prefix ne ''); - -$lines = join('', ); - -# merge file information -$lines =~ s/File (.+)\nLines (.+)\n(.+\n)*\n/$1 $2\n/g; - -# merge function information -$lines =~ s/Function (.+)\n((.+\n)*)\n/funcinfo($1, $2)/eg; - -# remove include information -$lines =~ s/.+include\/c\+\+.+\n//g; - -foreach $line (split /\n/, $lines) -{ - print "$prefix$line\n"; -} diff --git a/3party/pugixml/tests/helpers.hpp b/3party/pugixml/tests/helpers.hpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/main.cpp b/3party/pugixml/tests/main.cpp old mode 100644 new mode 100755 index 8a4ee739c3..00016a6646 --- a/3party/pugixml/tests/main.cpp +++ b/3party/pugixml/tests/main.cpp @@ -27,11 +27,13 @@ const char* test_runner::_temp_path; static size_t g_memory_total_size = 0; static size_t g_memory_total_count = 0; +static size_t g_memory_fail_triggered = false; static void* custom_allocate(size_t size) { if (test_runner::_memory_fail_threshold > 0 && test_runner::_memory_fail_threshold < g_memory_total_size + size) { + g_memory_fail_triggered = true; test_runner::_memory_fail_triggered = true; return 0; @@ -43,18 +45,30 @@ static void* custom_allocate(size_t size) g_memory_total_size += memory_size(ptr); g_memory_total_count++; - + return ptr; } } +#ifndef PUGIXML_NO_EXCEPTIONS +static void* custom_allocate_throw(size_t size) +{ + void* result = custom_allocate(size); + + if (!result) + throw std::bad_alloc(); + + return result; +} +#endif + static void custom_deallocate(void* ptr) { assert(ptr); g_memory_total_size -= memory_size(ptr); g_memory_total_count--; - + memory_deallocate(ptr); } @@ -80,7 +94,7 @@ namespace std } #endif -static bool run_test(test_runner* test) +static bool run_test(test_runner* test, const char* test_name, pugi::allocation_function allocate) { #ifndef PUGIXML_NO_EXCEPTIONS try @@ -88,11 +102,12 @@ static bool run_test(test_runner* test) #endif g_memory_total_size = 0; g_memory_total_count = 0; + g_memory_fail_triggered = false; test_runner::_memory_fail_threshold = 0; test_runner::_memory_fail_triggered = false; - - pugi::set_memory_management_functions(custom_allocate, custom_deallocate); - + + pugi::set_memory_management_functions(allocate, custom_deallocate); + #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4611) // interaction between _setjmp and C++ object destruction is non-portable @@ -100,22 +115,28 @@ static bool run_test(test_runner* test) #endif volatile int result = setjmp(test_runner::_failure_buffer); - + #ifdef _MSC_VER # pragma warning(pop) #endif if (result) { - printf("Test %s failed: %s\n", test->_name, test_runner::_failure_message); + printf("Test %s failed: %s\n", test_name, test_runner::_failure_message); return false; } test->run(); + if (test_runner::_memory_fail_triggered) + { + printf("Test %s failed: unguarded memory fail triggered\n", test_name); + return false; + } + if (g_memory_total_size != 0 || g_memory_total_count != 0) { - printf("Test %s failed: memory leaks found (%u bytes in %u allocations)\n", test->_name, static_cast(g_memory_total_size), static_cast(g_memory_total_count)); + printf("Test %s failed: memory leaks found (%u bytes in %u allocations)\n", test_name, static_cast(g_memory_total_size), static_cast(g_memory_total_count)); return false; } @@ -124,12 +145,12 @@ static bool run_test(test_runner* test) } catch (const std::exception& e) { - printf("Test %s failed: exception %s\n", test->_name, e.what()); + printf("Test %s failed: exception %s\n", test_name, e.what()); return false; } catch (...) { - printf("Test %s failed for unknown reason\n", test->_name); + printf("Test %s failed for unknown reason\n", test_name); return false; } #endif @@ -156,7 +177,7 @@ int main(int, char** argv) temp.erase((slash != std::string::npos) ? slash + 1 : 0); test_runner::_temp_path = temp.c_str(); - + replace_memory_management(); unsigned int total = 0; @@ -167,7 +188,15 @@ int main(int, char** argv) for (test = test_runner::_tests; test; test = test->_next) { total++; - passed += run_test(test); + passed += run_test(test, test->_name, custom_allocate); + + #ifndef PUGIXML_NO_EXCEPTIONS + if (g_memory_fail_triggered) + { + total++; + passed += run_test(test, (test->_name + std::string(" (throw)")).c_str(), custom_allocate_throw); + } + #endif } unsigned int failed = total - passed; diff --git a/3party/pugixml/tests/test.cpp b/3party/pugixml/tests/test.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test.hpp b/3party/pugixml/tests/test.hpp old mode 100644 new mode 100755 index 6a73065bde..fad555db81 --- a/3party/pugixml/tests/test.hpp +++ b/3party/pugixml/tests/test.hpp @@ -112,8 +112,8 @@ struct dummy_fixture {}; #define CHECK_TEXT(condition, text) if (condition) ; else test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1) #define CHECK_FORCE_FAIL(text) test_runner::_failure_message = CHECK_JOIN2(text, __FILE__, __LINE__), longjmp(test_runner::_failure_buffer, 1) -#if (defined(_MSC_VER) && _MSC_VER == 1200) || defined(__MWERKS__) -# define STRINGIZE(value) "??" // MSVC 6.0 and CodeWarrior have troubles stringizing stuff with strings w/escaping inside +#if (defined(_MSC_VER) && _MSC_VER == 1200) || defined(__MWERKS__) || (defined(__BORLANDC__) && __BORLANDC__ <= 0x540) +# define STRINGIZE(value) "??" // Some compilers have issues with stringizing expressions that contain strings w/escaping inside #else # define STRINGIZE(value) #value #endif @@ -142,16 +142,22 @@ struct dummy_fixture {}; #define CHECK_XPATH_FAIL(query) CHECK_XPATH_FAIL_VAR(query, 0) #endif +#ifdef PUGIXML_NO_EXCEPTIONS +#define CHECK_ALLOC_FAIL(code) do { CHECK(!test_runner::_memory_fail_triggered); code; CHECK(test_runner::_memory_fail_triggered); test_runner::_memory_fail_triggered = false; } while (test_runner::_memory_fail_triggered) +#else +#define CHECK_ALLOC_FAIL(code) do { CHECK(!test_runner::_memory_fail_triggered); try { code; } catch (std::bad_alloc&) {} CHECK(test_runner::_memory_fail_triggered); test_runner::_memory_fail_triggered = false; } while (test_runner::_memory_fail_triggered) +#endif + #define STR(text) PUGIXML_TEXT(text) -#ifdef __DMC__ +#if defined(__DMC__) || defined(__BORLANDC__) #define U_LITERALS // DMC does not understand \x01234 (it parses first three digits), but understands \u01234 #endif #if (defined(_MSC_VER) && _MSC_VER == 1200) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER == 800) || defined(__BORLANDC__) // NaN comparison on MSVC6 is incorrect, see http://www.nabble.com/assertDoubleEquals,-NaN---Microsoft-Visual-Studio-6-td9137859.html // IC8 and BCC are also affected by the same bug -# define MSVC6_NAN_BUG +# define MSVC6_NAN_BUG #endif inline wchar_t wchar_cast(unsigned int value) diff --git a/3party/pugixml/tests/test_document.cpp b/3party/pugixml/tests/test_document.cpp old mode 100644 new mode 100755 index 4d8bf4b0ff..8573ce3eda --- a/3party/pugixml/tests/test_document.cpp +++ b/3party/pugixml/tests/test_document.cpp @@ -32,9 +32,11 @@ static bool load_file_in_memory(const char* path, char*& data, size_t& size) if (!file) return false; fseek(file, 0, SEEK_END); - size = static_cast(ftell(file)); + long length = ftell(file); fseek(file, 0, SEEK_SET); + CHECK(length >= 0); + size = static_cast(length); data = new char[size]; CHECK(fread(data, 1, size, file) == size); @@ -107,10 +109,10 @@ TEST(document_load_stream_error) std::ifstream fs("filedoesnotexist"); CHECK(doc.load(fs).status == status_io_error); - + std::istringstream iss(""); test_runner::_memory_fail_threshold = 1; - CHECK(doc.load(iss).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.load(iss).status == status_out_of_memory)); } TEST(document_load_stream_empty) @@ -237,7 +239,7 @@ TEST(document_load_stream_nonseekable_out_of_memory) test_runner::_memory_fail_threshold = 1; pugi::xml_document doc; - CHECK(doc.load(in).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory)); } TEST(document_load_stream_nonseekable_out_of_memory_large) @@ -253,7 +255,7 @@ TEST(document_load_stream_nonseekable_out_of_memory_large) test_runner::_memory_fail_threshold = 10000 * 8 * 3 / 2; pugi::xml_document doc; - CHECK(doc.load(in).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory)); } #endif @@ -300,9 +302,44 @@ TEST(document_load_file_error) pugi::xml_document doc; CHECK(doc.load_file("filedoesnotexist").status == status_file_not_found); +} +TEST(document_load_file_out_of_memory) +{ test_runner::_memory_fail_threshold = 1; - CHECK(doc.load_file("tests/data/small.xml").status == status_out_of_memory); + + pugi::xml_document doc; + CHECK_ALLOC_FAIL(CHECK(doc.load_file("tests/data/small.xml").status == status_out_of_memory)); +} + +TEST(document_load_file_out_of_memory_file_leak) +{ + test_runner::_memory_fail_threshold = 1; + + pugi::xml_document doc; + + for (int i = 0; i < 256; ++i) + CHECK_ALLOC_FAIL(CHECK(doc.load_file("tests/data/small.xml").status == status_out_of_memory)); + + test_runner::_memory_fail_threshold = 0; + + CHECK(doc.load_file("tests/data/small.xml")); + CHECK_NODE(doc, STR("")); +} + +TEST(document_load_file_wide_out_of_memory_file_leak) +{ + test_runner::_memory_fail_threshold = 256; + + pugi::xml_document doc; + + for (int i = 0; i < 256; ++i) + CHECK_ALLOC_FAIL(CHECK(doc.load_file(L"tests/data/small.xml").status == status_out_of_memory)); + + test_runner::_memory_fail_threshold = 0; + + CHECK(doc.load_file(L"tests/data/small.xml")); + CHECK_NODE(doc, STR("")); } TEST(document_load_file_error_previous) @@ -323,7 +360,7 @@ TEST(document_load_file_wide_ascii) CHECK_NODE(doc, STR("")); } -#if !defined(__DMC__) && !defined(__MWERKS__) && !(defined(__MINGW32__) && defined(__STRICT_ANSI__) && !defined(__MINGW64_VERSION_MAJOR)) +#if !defined(__DMC__) && !defined(__MWERKS__) && !(defined(__MINGW32__) && defined(__STRICT_ANSI__) && !defined(__MINGW64_VERSION_MAJOR)) && !defined(__BORLANDC__) TEST(document_load_file_wide_unicode) { pugi::xml_document doc; @@ -339,7 +376,9 @@ TEST(document_load_file_wide_out_of_memory) pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(L"tests/data/small.xml"); + pugi::xml_parse_result result; + result.status = status_out_of_memory; + CHECK_ALLOC_FAIL(result = doc.load_file(L"tests/data/small.xml")); CHECK(result.status == status_out_of_memory || result.status == status_file_not_found); } @@ -460,7 +499,7 @@ TEST_XML(document_save_declaration_latin1, "") struct temp_file { char path[512]; - + temp_file() { static int index = 0; @@ -530,6 +569,26 @@ TEST_XML(document_save_file_wide_text, "") CHECK(test_file_contents(f.path, "\n", 9)); } +TEST_XML(document_save_file_leak, "") +{ + temp_file f; + + for (int i = 0; i < 256; ++i) + CHECK(doc.save_file(f.path)); +} + +TEST_XML(document_save_file_wide_leak, "") +{ + temp_file f; + + // widen the path + wchar_t wpath[sizeof(f.path)]; + std::copy(f.path, f.path + strlen(f.path) + 1, wpath + 0); + + for (int i = 0; i < 256; ++i) + CHECK(doc.save_file(wpath)); +} + TEST(document_load_buffer) { const pugi::char_t text[] = STR(""); @@ -1320,7 +1379,7 @@ TEST(document_convert_out_of_memory) for (unsigned int src = 0; src < sizeof(files) / sizeof(files[0]); ++src) { xml_document doc; - CHECK(doc.load_buffer(files[src].data, files[src].size, parse_default, files[src].encoding).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.load_buffer(files[src].data, files[src].size, parse_default, files[src].encoding).status == status_out_of_memory)); } // cleanup diff --git a/3party/pugixml/tests/test_dom_modify.cpp b/3party/pugixml/tests/test_dom_modify.cpp old mode 100644 new mode 100755 index c40c77f4e5..e84f098bd3 --- a/3party/pugixml/tests/test_dom_modify.cpp +++ b/3party/pugixml/tests/test_dom_modify.cpp @@ -6,10 +6,6 @@ #include #include -#ifdef __BORLANDC__ -using std::ldexpf; -#endif - TEST_XML(dom_attr_assign, "") { xml_node node = doc.child(STR("node")); @@ -78,7 +74,7 @@ TEST_XML(dom_attr_set_value, "") TEST_XML(dom_attr_assign_llong, "") { xml_node node = doc.child(STR("node")); - + node.append_attribute(STR("attr1")) = -9223372036854775807ll; node.append_attribute(STR("attr2")) = -9223372036854775807ll - 1; xml_attribute() = -9223372036854775807ll - 1; @@ -93,7 +89,7 @@ TEST_XML(dom_attr_assign_llong, "") TEST_XML(dom_attr_set_value_llong, "") { xml_node node = doc.child(STR("node")); - + CHECK(node.append_attribute(STR("attr1")).set_value(-9223372036854775807ll)); CHECK(node.append_attribute(STR("attr2")).set_value(-9223372036854775807ll - 1)); CHECK(!xml_attribute().set_value(-9223372036854775807ll - 1)); @@ -162,7 +158,7 @@ TEST_XML(dom_node_prepend_attribute, "") { CHECK(xml_node().prepend_attribute(STR("a")) == xml_attribute()); CHECK(doc.prepend_attribute(STR("a")) == xml_attribute()); - + xml_attribute a1 = doc.child(STR("node")).prepend_attribute(STR("a1")); CHECK(a1); a1 = STR("v1"); @@ -182,7 +178,7 @@ TEST_XML(dom_node_append_attribute, "") { CHECK(xml_node().append_attribute(STR("a")) == xml_attribute()); CHECK(doc.append_attribute(STR("a")) == xml_attribute()); - + xml_attribute a1 = doc.child(STR("node")).append_attribute(STR("a1")); CHECK(a1); a1 = STR("v1"); @@ -210,7 +206,7 @@ TEST_XML(dom_node_insert_attribute_after, " CHECK(node.insert_attribute_after(STR("a"), xml_attribute()) == xml_attribute()); CHECK(node.insert_attribute_after(STR("a"), a2) == xml_attribute()); - + xml_attribute a3 = node.insert_attribute_after(STR("a3"), a1); CHECK(a3 && a3 != a2 && a3 != a1); a3 = STR("v3"); @@ -240,7 +236,7 @@ TEST_XML(dom_node_insert_attribute_before, "")); } @@ -300,7 +296,7 @@ TEST_XML(dom_node_append_copy_attribute, " CHECK(xml_node().append_copy(doc.child(STR("node")).attribute(STR("a1"))) == xml_attribute()); CHECK(doc.append_copy(doc.child(STR("node")).attribute(STR("a1"))) == xml_attribute()); CHECK(doc.child(STR("node")).append_copy(xml_attribute()) == xml_attribute()); - + xml_node node = doc.child(STR("node")); xml_node child = node.child(STR("child")); @@ -320,13 +316,13 @@ TEST_XML(dom_node_append_copy_attribute, " a3.set_name(STR("a3")); a3 = STR("v3"); - + a4.set_name(STR("a4")); a4 = STR("v4"); - + a5.set_name(STR("a5")); a5 = STR("v5"); - + CHECK_NODE(doc, STR("")); } @@ -343,7 +339,7 @@ TEST_XML(dom_node_insert_copy_after_attribute, "")); } @@ -382,7 +378,7 @@ TEST_XML(dom_node_insert_copy_before_attribute, "< CHECK(node.insert_copy_before(a1, xml_attribute()) == xml_attribute()); CHECK(node.insert_copy_before(xml_attribute(), a1) == xml_attribute()); CHECK(node.insert_copy_before(a2, a2) == xml_attribute()); - + xml_attribute a3 = node.insert_copy_before(a1, a1); CHECK(a3 && a3 != a2 && a3 != a1); @@ -398,13 +394,13 @@ TEST_XML(dom_node_insert_copy_before_attribute, "< a3.set_name(STR("a3")); a3 = STR("v3"); - + a4.set_name(STR("a4")); a4 = STR("v4"); - + a5.set_name(STR("a5")); a5 = STR("v5"); - + CHECK_NODE(doc, STR("")); } @@ -412,7 +408,7 @@ TEST_XML(dom_node_remove_attribute, "") { - doc.child(STR("node")).remove_child(STR("n1")); + CHECK(doc.child(STR("node")).remove_child(STR("n1"))); CHECK_NODE(doc, STR("")); @@ -669,7 +665,7 @@ TEST_XML(dom_node_prepend_copy, "foo") CHECK(doc.child(STR("node")).first_child().prepend_copy(doc.child(STR("node"))) == xml_node()); CHECK(doc.prepend_copy(doc) == xml_node()); CHECK(doc.prepend_copy(xml_node()) == xml_node()); - + xml_node n1 = doc.child(STR("node")).prepend_copy(doc.child(STR("node")).first_child()); CHECK(n1); CHECK_STRING(n1.value(), STR("foo")); @@ -692,7 +688,7 @@ TEST_XML(dom_node_append_copy, "foo") CHECK(doc.child(STR("node")).first_child().append_copy(doc.child(STR("node"))) == xml_node()); CHECK(doc.append_copy(doc) == xml_node()); CHECK(doc.append_copy(xml_node()) == xml_node()); - + xml_node n1 = doc.child(STR("node")).append_copy(doc.child(STR("node")).first_child()); CHECK(n1); CHECK_STRING(n1.value(), STR("foo")); @@ -716,7 +712,7 @@ TEST_XML(dom_node_insert_copy_after, "foo") CHECK(doc.insert_copy_after(doc, doc) == xml_node()); CHECK(doc.insert_copy_after(xml_node(), doc.child(STR("node"))) == xml_node()); CHECK(doc.insert_copy_after(doc.child(STR("node")), xml_node()) == xml_node()); - + xml_node n1 = doc.child(STR("node")).insert_copy_after(doc.child(STR("node")).child(STR("child")), doc.child(STR("node")).first_child()); CHECK(n1); CHECK_STRING(n1.name(), STR("child")); @@ -740,7 +736,7 @@ TEST_XML(dom_node_insert_copy_before, "foo") CHECK(doc.insert_copy_before(doc, doc) == xml_node()); CHECK(doc.insert_copy_before(xml_node(), doc.child(STR("node"))) == xml_node()); CHECK(doc.insert_copy_before(doc.child(STR("node")), xml_node()) == xml_node()); - + xml_node n1 = doc.child(STR("node")).insert_copy_before(doc.child(STR("node")).child(STR("child")), doc.child(STR("node")).first_child()); CHECK(n1); CHECK_STRING(n1.name(), STR("child")); @@ -771,6 +767,14 @@ TEST_XML(dom_node_copy_crossdoc, "") CHECK_NODE(newdoc, STR("")); } +TEST_XML(dom_node_copy_crossdoc_attribute, "") +{ + xml_document newdoc; + newdoc.append_child(STR("copy")).append_copy(doc.child(STR("node")).attribute(STR("attr"))); + CHECK_NODE(doc, STR("")); + CHECK_NODE(newdoc, STR("")); +} + TEST_XML_FLAGS(dom_node_copy_types, "pcdata", parse_full) { doc.append_copy(doc.child(STR("root"))); @@ -858,10 +862,10 @@ TEST(dom_string_out_of_memory) // no value => long value test_runner::_memory_fail_threshold = 32; - CHECK(!node.set_name(string)); - CHECK(!text.set_value(string)); - CHECK(!attr.set_name(string)); - CHECK(!attr.set_value(string)); + CHECK_ALLOC_FAIL(CHECK(!node.set_name(string))); + CHECK_ALLOC_FAIL(CHECK(!text.set_value(string))); + CHECK_ALLOC_FAIL(CHECK(!attr.set_name(string))); + CHECK_ALLOC_FAIL(CHECK(!attr.set_value(string))); // set some names/values test_runner::_memory_fail_threshold = 0; @@ -873,10 +877,10 @@ TEST(dom_string_out_of_memory) // some value => long value test_runner::_memory_fail_threshold = 32; - CHECK(!node.set_name(string)); - CHECK(!text.set_value(string)); - CHECK(!attr.set_name(string)); - CHECK(!attr.set_value(string)); + CHECK_ALLOC_FAIL(CHECK(!node.set_name(string))); + CHECK_ALLOC_FAIL(CHECK(!text.set_value(string))); + CHECK_ALLOC_FAIL(CHECK(!attr.set_name(string))); + CHECK_ALLOC_FAIL(CHECK(!attr.set_value(string))); // check that original state was preserved test_runner::_memory_fail_threshold = 0; @@ -897,30 +901,28 @@ TEST(dom_node_out_of_memory) xml_attribute a = n.append_attribute(STR("a")); CHECK(a); - while (n.append_child(node_comment) || n.append_attribute(STR("b"))) - { - // nop - } + CHECK_ALLOC_FAIL(while (n.append_child(node_comment)) { /* nop */ }); + CHECK_ALLOC_FAIL(while (n.append_attribute(STR("b"))) { /* nop */ }); // verify all node modification operations - CHECK(!n.append_child()); - CHECK(!n.prepend_child()); - CHECK(!n.insert_child_after(node_element, n.first_child())); - CHECK(!n.insert_child_before(node_element, n.first_child())); - CHECK(!n.append_attribute(STR(""))); - CHECK(!n.prepend_attribute(STR(""))); - CHECK(!n.insert_attribute_after(STR(""), a)); - CHECK(!n.insert_attribute_before(STR(""), a)); + CHECK_ALLOC_FAIL(CHECK(!n.append_child())); + CHECK_ALLOC_FAIL(CHECK(!n.prepend_child())); + CHECK_ALLOC_FAIL(CHECK(!n.insert_child_after(node_element, n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_child_before(node_element, n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.append_attribute(STR("")))); + CHECK_ALLOC_FAIL(CHECK(!n.prepend_attribute(STR("")))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_attribute_after(STR(""), a))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_attribute_before(STR(""), a))); // verify node copy operations - CHECK(!n.append_copy(n.first_child())); - CHECK(!n.prepend_copy(n.first_child())); - CHECK(!n.insert_copy_after(n.first_child(), n.first_child())); - CHECK(!n.insert_copy_before(n.first_child(), n.first_child())); - CHECK(!n.append_copy(a)); - CHECK(!n.prepend_copy(a)); - CHECK(!n.insert_copy_after(a, a)); - CHECK(!n.insert_copy_before(a, a)); + CHECK_ALLOC_FAIL(CHECK(!n.append_copy(n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.prepend_copy(n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_copy_after(n.first_child(), n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_copy_before(n.first_child(), n.first_child()))); + CHECK_ALLOC_FAIL(CHECK(!n.append_copy(a))); + CHECK_ALLOC_FAIL(CHECK(!n.prepend_copy(a))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_copy_after(a, a))); + CHECK_ALLOC_FAIL(CHECK(!n.insert_copy_before(a, a))); } TEST(dom_node_memory_limit) @@ -942,6 +944,25 @@ TEST(dom_node_memory_limit) } } +TEST(dom_node_memory_limit_pi) +{ + const unsigned int length = 65536; + static char_t string[length + 1]; + + for (unsigned int i = 0; i < length; ++i) string[i] = 'a'; + string[length] = 0; + + test_runner::_memory_fail_threshold = 32768 * 2 + sizeof(string); + + xml_document doc; + + for (int j = 0; j < 32; ++j) + { + CHECK(doc.append_child(node_pi).set_value(string)); + CHECK(doc.remove_child(doc.first_child())); + } +} + TEST(dom_node_doctype_top_level) { xml_document doc; @@ -1043,7 +1064,7 @@ TEST_XML(dom_node_append_buffer_remove, "test") CHECK_NODE(doc, STR("test")); - doc.remove_child(STR("node")); + CHECK(doc.remove_child(STR("node"))); CHECK(!doc.first_child()); } @@ -1085,7 +1106,7 @@ TEST(dom_node_append_buffer_out_of_memory_extra) test_runner::_memory_fail_threshold = 1; xml_document doc; - CHECK(doc.append_buffer("", 4).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.append_buffer("", 4).status == status_out_of_memory)); CHECK(!doc.first_child()); } @@ -1096,10 +1117,51 @@ TEST(dom_node_append_buffer_out_of_memory_buffer) char data[128] = {0}; xml_document doc; - CHECK(doc.append_buffer(data, sizeof(data)).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.append_buffer(data, sizeof(data)).status == status_out_of_memory)); CHECK(!doc.first_child()); } +TEST(dom_node_append_buffer_out_of_memory_nodes) +{ + unsigned int count = 4000; + std::basic_string data; + + for (unsigned int i = 0; i < count; ++i) + data += STR(""); + + test_runner::_memory_fail_threshold = 32768 + 128 + data.length() * sizeof(char_t) + 32; + +#ifdef PUGIXML_COMPACT + // ... and some space for hash table + test_runner::_memory_fail_threshold += 2048; +#endif + + xml_document doc; + CHECK_ALLOC_FAIL(CHECK(doc.append_buffer(data.c_str(), data.length() * sizeof(char_t), parse_fragment).status == status_out_of_memory)); + + unsigned int valid = 0; + + for (xml_node n = doc.first_child(); n; n = n.next_sibling()) + { + CHECK_STRING(n.name(), STR("a")); + valid++; + } + + CHECK(valid > 0 && valid < count); +} + +TEST(dom_node_append_buffer_out_of_memory_name) +{ + test_runner::_memory_fail_threshold = 32768 + 4096; + + char data[4096] = {0}; + + xml_document doc; + CHECK(doc.append_child(STR("root"))); + CHECK_ALLOC_FAIL(CHECK(doc.first_child().append_buffer(data, sizeof(data)).status == status_out_of_memory)); + CHECK_STRING(doc.first_child().name(), STR("root")); +} + TEST_XML(dom_node_append_buffer_fragment, "") { xml_node node = doc.child(STR("node")); @@ -1336,6 +1398,11 @@ TEST(dom_node_copy_copyless) // the document is parsed in-place so there should only be 1 page worth of allocations test_runner::_memory_fail_threshold = 32768 + 128; +#ifdef PUGIXML_COMPACT + // ... and some space for hash table + test_runner::_memory_fail_threshold += 2048; +#endif + xml_document doc; CHECK(doc.load_buffer_inplace(&datacopy[0], datacopy.size() * sizeof(char_t), parse_full)); @@ -1376,7 +1443,7 @@ TEST(dom_node_copy_copyless_mix) CHECK_NODE(copy2, dataxml.c_str()); } -TEST_XML(dom_node_copyless_taint, "") +TEST_XML(dom_node_copy_copyless_taint, "") { xml_node node = doc.child(STR("node")); xml_node copy = doc.append_copy(node); @@ -1400,13 +1467,70 @@ TEST_XML(dom_node_copyless_taint, "") CHECK_NODE(doc, STR("")); } +TEST(dom_node_copy_attribute_copyless) +{ + std::basic_string data; + data += STR(""); + + std::basic_string datacopy = data; + + // the document is parsed in-place so there should only be 1 page worth of allocations + test_runner::_memory_fail_threshold = 32768 + 128; + +#ifdef PUGIXML_COMPACT + // ... and some space for hash table + test_runner::_memory_fail_threshold += 2048; +#endif + + xml_document doc; + CHECK(doc.load_buffer_inplace(&datacopy[0], datacopy.size() * sizeof(char_t), parse_full)); + + // this copy should share all string storage; since there are not a lot of nodes we should not have *any* allocations here (everything will fit in the same page in the document) + xml_node copy1 = doc.append_child(STR("node")); + copy1.append_copy(doc.first_child().first_attribute()); + + xml_node copy2 = doc.append_child(STR("node")); + copy2.append_copy(copy1.first_attribute()); + + CHECK_NODE(copy1, data.c_str()); + CHECK_NODE(copy2, data.c_str()); +} + +TEST_XML(dom_node_copy_attribute_copyless_taint, "") +{ + xml_node node = doc.child(STR("node")); + xml_attribute attr = node.first_attribute(); + + xml_node copy1 = doc.append_child(STR("copy1")); + xml_node copy2 = doc.append_child(STR("copy2")); + xml_node copy3 = doc.append_child(STR("copy3")); + + CHECK_NODE(doc, STR("")); + + copy1.append_copy(attr); + + CHECK_NODE(doc, STR("")); + + attr.set_name(STR("att1")); + copy2.append_copy(attr); + + CHECK_NODE(doc, STR("")); + + copy1.first_attribute().set_value(STR("valu2")); + copy3.append_copy(copy1.first_attribute()); + + CHECK_NODE(doc, STR("")); +} + TEST_XML(dom_node_copy_out_of_memory_node, "text1text2") { test_runner::_memory_fail_threshold = 32768 * 2 + 4096; xml_document copy; - for (int i = 0; i < 1000; ++i) - copy.append_copy(doc.first_child()); + CHECK_ALLOC_FAIL(for (int i = 0; i < 1000; ++i) copy.append_copy(doc.first_child())); } TEST_XML(dom_node_copy_out_of_memory_attr, "") @@ -1414,8 +1538,7 @@ TEST_XML(dom_node_copy_out_of_memory_attr, "text") @@ -1476,7 +1599,7 @@ template bool fp_equal(T lhs, T rhs) #endif } -TEST(dom_fp_roundtrip_min_max) +TEST(dom_fp_roundtrip_min_max_float) { xml_document doc; xml_node node = doc.append_child(STR("node")); @@ -1487,6 +1610,13 @@ TEST(dom_fp_roundtrip_min_max) attr.set_value(std::numeric_limits::max()); CHECK(fp_equal(attr.as_float(), std::numeric_limits::max())); +} + +TEST(dom_fp_roundtrip_min_max_double) +{ + xml_document doc; + xml_node node = doc.append_child(STR("node")); + xml_attribute attr = node.append_attribute(STR("attr")); attr.set_value(std::numeric_limits::min()); CHECK(fp_equal(attr.as_double(), std::numeric_limits::min())); @@ -1513,7 +1643,7 @@ TEST(dom_fp_roundtrip_float) { for (size_t i = 0; i < sizeof(fp_roundtrip_base) / sizeof(fp_roundtrip_base[0]); ++i) { - float value = ldexpf(static_cast(fp_roundtrip_base[i]), e); + float value = static_cast(ldexp(fp_roundtrip_base[i], e)); doc.text().set(value); CHECK(fp_equal(doc.text().as_float(), value)); diff --git a/3party/pugixml/tests/test_dom_text.cpp b/3party/pugixml/tests/test_dom_text.cpp old mode 100644 new mode 100755 index 4d91452fb5..01c815cc3a --- a/3party/pugixml/tests/test_dom_text.cpp +++ b/3party/pugixml/tests/test_dom_text.cpp @@ -303,7 +303,7 @@ TEST_XML(dom_text_set_value, "") TEST_XML(dom_text_assign_llong, "") { xml_node node = doc.child(STR("node")); - + node.append_child(STR("text1")).text() = -9223372036854775807ll; node.append_child(STR("text2")).text() = -9223372036854775807ll - 1; xml_text() = -9223372036854775807ll - 1; @@ -311,14 +311,14 @@ TEST_XML(dom_text_assign_llong, "") node.append_child(STR("text3")).text() = 18446744073709551615ull; node.append_child(STR("text4")).text() = 18446744073709551614ull; xml_text() = 18446744073709551615ull; - + CHECK_NODE(node, STR("-9223372036854775807-92233720368547758081844674407370955161518446744073709551614")); } TEST_XML(dom_text_set_value_llong, "") { xml_node node = doc.child(STR("node")); - + CHECK(node.append_child(STR("text1")).text().set(-9223372036854775807ll)); CHECK(node.append_child(STR("text2")).text().set(-9223372036854775807ll - 1)); CHECK(!xml_text().set(-9223372036854775807ll - 1)); diff --git a/3party/pugixml/tests/test_dom_traverse.cpp b/3party/pugixml/tests/test_dom_traverse.cpp old mode 100644 new mode 100755 index e83964ca44..5c7579abc5 --- a/3party/pugixml/tests/test_dom_traverse.cpp +++ b/3party/pugixml/tests/test_dom_traverse.cpp @@ -57,10 +57,10 @@ TEST_XML(dom_attr_next_previous_attribute, "") CHECK(attr1.next_attribute() == attr2); CHECK(attr2.next_attribute() == xml_attribute()); - + CHECK(attr1.previous_attribute() == xml_attribute()); CHECK(attr2.previous_attribute() == attr1); - + CHECK(xml_attribute().next_attribute() == xml_attribute()); CHECK(xml_attribute().previous_attribute() == xml_attribute()); } @@ -497,7 +497,7 @@ TEST_XML_FLAGS(dom_node_type, "pcdata CHECK((it++)->type() == node_element); xml_node_iterator cit = doc.child(STR("node")).begin(); - + CHECK((cit++)->type() == node_pcdata); CHECK((cit++)->type() == node_cdata); } @@ -516,7 +516,7 @@ TEST_XML_FLAGS(dom_node_name_value, "") TEST_XML(dom_node_path, "text") { CHECK(xml_node().path() == STR("")); - + CHECK(doc.path() == STR("")); CHECK(doc.child(STR("node")).path() == STR("/node")); CHECK(doc.child(STR("node")).child(STR("child1")).path() == STR("/node/child1")); CHECK(doc.child(STR("node")).child(STR("child1")).child(STR("child2")).path() == STR("/node/child1/child2")); CHECK(doc.child(STR("node")).child(STR("child1")).first_child().path() == STR("/node/child1/")); - + CHECK(doc.child(STR("node")).child(STR("child1")).path('\\') == STR("\\node\\child1")); } #endif @@ -743,7 +743,7 @@ TEST_XML(dom_node_first_element_by_path, "texttextpcd CHECK((it++)->offset_debug() == 38); xml_node_iterator cit = doc.child(STR("node")).begin(); - + CHECK((cit++)->offset_debug() == 43); CHECK((cit++)->offset_debug() == 58); } @@ -966,7 +966,7 @@ TEST_XML(dom_internal_object, "value") xml_node node = doc.child(STR("node")); xml_attribute attr = node.first_attribute(); xml_node value = node.first_child(); - + CHECK(xml_node().internal_object() == 0); CHECK(xml_attribute().internal_object() == 0); @@ -988,7 +988,7 @@ TEST_XML(dom_hash_value, "value") xml_node node = doc.child(STR("node")); xml_attribute attr = node.first_attribute(); xml_node value = node.first_child(); - + CHECK(xml_node().hash_value() == 0); CHECK(xml_attribute().hash_value() == 0); @@ -1085,14 +1085,192 @@ TEST_XML(dom_unspecified_bool_coverage, "text") { xml_node node = doc.first_child(); + CHECK(node); static_cast(node)(0); + + CHECK(node.first_attribute()); static_cast(node.first_attribute())(0); + + CHECK(node.text()); static_cast(node.text())(0); #ifndef PUGIXML_NO_XPATH xpath_query q(STR("/node")); + CHECK(q); static_cast(q)(0); - static_cast(q.evaluate_node(doc))(0); + + xpath_node qn = q.evaluate_node(doc); + + CHECK(qn); + static_cast(qn)(0); +#endif +} + +#if __cplusplus >= 201103 +TEST_XML(dom_ranged_for, "354") +{ + int index = 1; + + for (xml_node n: doc.children()) + { + for (xml_attribute a: n.attributes()) + { + CHECK(a.as_int() == index); + index++; + } + + for (xml_node c: n.children(STR("test"))) + { + CHECK(c.text().as_int() == index); + index++; + } + } + + CHECK(index == 5); +} +#endif + +TEST_XML(dom_node_attribute_hinted, "") +{ + xml_node node = doc.first_child(); + xml_attribute attr1 = node.attribute(STR("attr1")); + xml_attribute attr2 = node.attribute(STR("attr2")); + xml_attribute attr3 = node.attribute(STR("attr3")); + + xml_attribute hint; + CHECK(!xml_node().attribute(STR("test"), hint) && !hint); + + CHECK(node.attribute(STR("attr2"), hint) == attr2 && hint == attr3); + CHECK(node.attribute(STR("attr3"), hint) == attr3 && !hint); + + CHECK(node.attribute(STR("attr1"), hint) == attr1 && hint == attr2); + CHECK(node.attribute(STR("attr2"), hint) == attr2 && hint == attr3); + CHECK(node.attribute(STR("attr1"), hint) == attr1 && hint == attr2); + CHECK(node.attribute(STR("attr1"), hint) == attr1 && hint == attr2); + + CHECK(!node.attribute(STR("attr"), hint) && hint == attr2); +} + +TEST_XML(dom_as_int_overflow, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_int() == -2147483647 - 1); + CHECK(node.attribute(STR("attr2")).as_int() == 2147483647); + CHECK(node.attribute(STR("attr3")).as_int() == -2147483647 - 1); +} + +TEST_XML(dom_as_uint_overflow, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_uint() == 0); + CHECK(node.attribute(STR("attr2")).as_uint() == 4294967295u); + CHECK(node.attribute(STR("attr3")).as_uint() == 4294967295u); + CHECK(node.attribute(STR("attr4")).as_uint() == 4294967295u); +} + +TEST_XML(dom_as_int_hex_overflow, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_int() == -2147483647 - 1); + CHECK(node.attribute(STR("attr2")).as_int() == 2147483647); +} + +TEST_XML(dom_as_uint_hex_overflow, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_uint() == 0); + CHECK(node.attribute(STR("attr2")).as_uint() == 4294967295u); + CHECK(node.attribute(STR("attr3")).as_uint() == 4294967295u); +} + +TEST_XML(dom_as_int_many_digits, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_int() == 1); + CHECK(node.attribute(STR("attr1")).as_uint() == 1); +} + +TEST_XML(dom_as_int_hex_many_digits, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_int() == 1); + CHECK(node.attribute(STR("attr1")).as_uint() == 1); +} + +#ifdef PUGIXML_HAS_LONG_LONG +TEST_XML(dom_as_llong_overflow, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_llong() == -9223372036854775807ll - 1); + CHECK(node.attribute(STR("attr2")).as_llong() == 9223372036854775807ll); + CHECK(node.attribute(STR("attr3")).as_llong() == -9223372036854775807ll - 1); +} + +TEST_XML(dom_as_ullong_overflow, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_ullong() == 0); + CHECK(node.attribute(STR("attr2")).as_ullong() == 18446744073709551615ull); + CHECK(node.attribute(STR("attr3")).as_ullong() == 18446744073709551615ull); + CHECK(node.attribute(STR("attr4")).as_ullong() == 18446744073709551615ull); +} + +TEST_XML(dom_as_llong_hex_overflow, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_llong() == -9223372036854775807ll - 1); + CHECK(node.attribute(STR("attr2")).as_llong() == 9223372036854775807ll); +} + +TEST_XML(dom_as_ullong_hex_overflow, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_ullong() == 0); + CHECK(node.attribute(STR("attr2")).as_ullong() == 18446744073709551615ull); + CHECK(node.attribute(STR("attr3")).as_ullong() == 18446744073709551615ull); +} + +TEST_XML(dom_as_llong_many_digits, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_llong() == 1); + CHECK(node.attribute(STR("attr1")).as_ullong() == 1); +} + +TEST_XML(dom_as_llong_hex_many_digits, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_llong() == 1); + CHECK(node.attribute(STR("attr1")).as_ullong() == 1); +} +#endif + +TEST_XML(dom_as_int_plus, "") +{ + xml_node node = doc.child(STR("node")); + + CHECK(node.attribute(STR("attr1")).as_int() == 1); + CHECK(node.attribute(STR("attr1")).as_uint() == 1); + CHECK(node.attribute(STR("attr2")).as_int() == 10); + CHECK(node.attribute(STR("attr2")).as_uint() == 10); + +#ifdef PUGIXML_HAS_LONG_LONG + CHECK(node.attribute(STR("attr1")).as_llong() == 1); + CHECK(node.attribute(STR("attr1")).as_ullong() == 1); + CHECK(node.attribute(STR("attr2")).as_llong() == 10); + CHECK(node.attribute(STR("attr2")).as_ullong() == 10); #endif } diff --git a/3party/pugixml/tests/test_header_guard.cpp b/3party/pugixml/tests/test_header_guard.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_header_iosfwd_1.cpp b/3party/pugixml/tests/test_header_iosfwd_1.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_header_iosfwd_2.cpp b/3party/pugixml/tests/test_header_iosfwd_2.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_header_iostream_1.cpp b/3party/pugixml/tests/test_header_iostream_1.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_header_iostream_2.cpp b/3party/pugixml/tests/test_header_iostream_2.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_header_only.cpp b/3party/pugixml/tests/test_header_only_1.cpp old mode 100644 new mode 100755 similarity index 94% rename from 3party/pugixml/tests/test_header_only.cpp rename to 3party/pugixml/tests/test_header_only_1.cpp index 17cafca78d..e33fd783a7 --- a/3party/pugixml/tests/test_header_only.cpp +++ b/3party/pugixml/tests/test_header_only_1.cpp @@ -7,7 +7,7 @@ #include "../src/pugixml.hpp" #include "../src/pugixml.hpp" -TEST(header_only) +TEST(header_only_1) { xml_document doc; CHECK(doc.load_string(STR(""))); diff --git a/3party/pugixml/tests/test_header_only_2.cpp b/3party/pugixml/tests/test_header_only_2.cpp new file mode 100755 index 0000000000..220c807756 --- /dev/null +++ b/3party/pugixml/tests/test_header_only_2.cpp @@ -0,0 +1,19 @@ +#define PUGIXML_HEADER_ONLY +#define pugi pugih + +#include "common.hpp" + +// Check header guards +#include "../src/pugixml.hpp" +#include "../src/pugixml.hpp" + +TEST(header_only_2) +{ + xml_document doc; + CHECK(doc.load_string(STR(""))); + CHECK_STRING(doc.first_child().name(), STR("node")); + +#ifndef PUGIXML_NO_XPATH + CHECK(doc.first_child() == doc.select_node(STR("//*")).node()); +#endif +} diff --git a/3party/pugixml/tests/test_header_string_1.cpp b/3party/pugixml/tests/test_header_string_1.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_header_string_2.cpp b/3party/pugixml/tests/test_header_string_2.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_header_string_iostream.cpp b/3party/pugixml/tests/test_header_string_iostream.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_memory.cpp b/3party/pugixml/tests/test_memory.cpp old mode 100644 new mode 100755 index 9314831851..85d6e861a6 --- a/3party/pugixml/tests/test_memory.cpp +++ b/3party/pugixml/tests/test_memory.cpp @@ -1,30 +1,38 @@ #include "common.hpp" #include "writer_string.hpp" +#include "allocator.hpp" #include +#include namespace { - int allocate_count = 0; - int deallocate_count = 0; + int page_allocs = 0; + int page_deallocs = 0; + + bool is_page(size_t size) + { + return size >= 16384; + } void* allocate(size_t size) { - ++allocate_count; - return new char[size]; + void* ptr = memory_allocate(size); + page_allocs += is_page(memory_size(ptr)); + return ptr; } void deallocate(void* ptr) { - ++deallocate_count; - delete[] reinterpret_cast(ptr); + page_deallocs += is_page(memory_size(ptr)); + memory_deallocate(ptr); } } TEST(memory_custom_memory_management) { - allocate_count = deallocate_count = 0; + page_allocs = page_deallocs = 0; // remember old functions allocation_function old_allocate = get_memory_allocation_function(); @@ -37,30 +45,30 @@ TEST(memory_custom_memory_management) // parse document xml_document doc; - CHECK(allocate_count == 0 && deallocate_count == 0); + CHECK(page_allocs == 0 && page_deallocs == 0); CHECK(doc.load_string(STR(""))); - - CHECK(allocate_count == 2 && deallocate_count == 0); + + CHECK(page_allocs == 1 && page_deallocs == 0); // modify document (no new page) CHECK(doc.first_child().set_name(STR("foobars"))); - CHECK(allocate_count == 2 && deallocate_count == 0); + CHECK(page_allocs == 1 && page_deallocs == 0); // modify document (new page) std::basic_string s(65536, 'x'); CHECK(doc.first_child().set_name(s.c_str())); - CHECK(allocate_count == 3 && deallocate_count == 0); + CHECK(page_allocs == 2 && page_deallocs == 0); // modify document (new page, old one should die) s += s; CHECK(doc.first_child().set_name(s.c_str())); - CHECK(allocate_count == 4 && deallocate_count == 1); + CHECK(page_allocs == 3 && page_deallocs == 1); } - CHECK(allocate_count == 4 && deallocate_count == 4); + CHECK(page_allocs == 3 && page_deallocs == 3); // restore old functions set_memory_management_functions(old_allocate, old_deallocate); @@ -68,7 +76,7 @@ TEST(memory_custom_memory_management) TEST(memory_large_allocations) { - allocate_count = deallocate_count = 0; + page_allocs = page_deallocs = 0; // remember old functions allocation_function old_allocate = get_memory_allocation_function(); @@ -80,7 +88,7 @@ TEST(memory_large_allocations) { xml_document doc; - CHECK(allocate_count == 0 && deallocate_count == 0); + CHECK(page_allocs == 0 && page_deallocs == 0); // initial fill for (size_t i = 0; i < 128; ++i) @@ -90,7 +98,7 @@ TEST(memory_large_allocations) CHECK(doc.append_child(node_pcdata).set_value(s.c_str())); } - CHECK(allocate_count > 0 && deallocate_count == 0); + CHECK(page_allocs > 0 && page_deallocs == 0); // grow-prune loop while (doc.first_child()) @@ -116,15 +124,72 @@ TEST(memory_large_allocations) } } - CHECK(allocate_count == deallocate_count + 1); // only one live page left (it waits for new allocations) + CHECK(page_allocs == page_deallocs + 1); // only one live page left (it waits for new allocations) char buffer; CHECK(doc.load_buffer_inplace(&buffer, 0, parse_fragment, get_native_encoding())); - CHECK(allocate_count == deallocate_count); // no live pages left + CHECK(page_allocs == page_deallocs); // no live pages left } - CHECK(allocate_count == deallocate_count); // everything is freed + CHECK(page_allocs == page_deallocs); // everything is freed + + // restore old functions + set_memory_management_functions(old_allocate, old_deallocate); +} + +TEST(memory_page_management) +{ + page_allocs = page_deallocs = 0; + + // remember old functions + allocation_function old_allocate = get_memory_allocation_function(); + deallocation_function old_deallocate = get_memory_deallocation_function(); + + // replace functions + set_memory_management_functions(allocate, deallocate); + + { + xml_document doc; + + CHECK(page_allocs == 0 && page_deallocs == 0); + + // initial fill + std::vector nodes; + + for (size_t i = 0; i < 4000; ++i) + { + xml_node node = doc.append_child(STR("node")); + CHECK(node); + + nodes.push_back(node); + } + + CHECK(page_allocs > 0 && page_deallocs == 0); + + // grow-prune loop + size_t offset = 0; + size_t prime = 15485863; + + while (nodes.size() > 0) + { + offset = (offset + prime) % nodes.size(); + + doc.remove_child(nodes[offset]); + + nodes[offset] = nodes.back(); + nodes.pop_back(); + } + + CHECK(page_allocs == page_deallocs + 1); // only one live page left (it waits for new allocations) + + char buffer; + CHECK(doc.load_buffer_inplace(&buffer, 0, parse_fragment, get_native_encoding())); + + CHECK(page_allocs == page_deallocs); // no live pages left + } + + CHECK(page_allocs == page_deallocs); // everything is freed // restore old functions set_memory_management_functions(old_allocate, old_deallocate); diff --git a/3party/pugixml/tests/test_parse.cpp b/3party/pugixml/tests/test_parse.cpp old mode 100644 new mode 100755 index 12498ae31c..2c3f125c2f --- a/3party/pugixml/tests/test_parse.cpp +++ b/3party/pugixml/tests/test_parse.cpp @@ -82,7 +82,7 @@ TEST(parse_pi_error) CHECK(doc.load_string(STR(""), parse_fragment | parse_pi).status == status_bad_pi); CHECK(doc.load_string(STR(""), parse_fragment | parse_pi).status == status_bad_pi); CHECK(doc.load_string(STR(""), parse_fragment | parse_pi).status == status_bad_pi); @@ -235,9 +235,9 @@ TEST(parse_ws_pcdata_skip) CHECK(!doc.first_child()); CHECK(doc.load_string(STR(" "), parse_minimal)); - + xml_node root = doc.child(STR("root")); - + CHECK(root.first_child() == root.last_child()); CHECK(!root.first_child().first_child()); } @@ -436,21 +436,21 @@ TEST(parse_pcdata_trim) test_data_t test_data[] = { - { STR(" text"), STR("text"), 0 }, - { STR("\t\n text"), STR("text"), 0 }, - { STR("text "), STR("text"), 0 }, - { STR("text \t\n"), STR("text"), 0 }, - { STR("\r\n\t text \t\n\r"), STR("text"), 0 }, - { STR(" text"), STR("text"), parse_fragment }, - { STR("\t\n text"), STR("text"), parse_fragment }, - { STR("text "), STR("text"), parse_fragment }, - { STR("text \t\n"), STR("text"), parse_fragment }, - { STR("\r\n\t text \t\n\r"), STR("text"), parse_fragment }, - { STR("\r\n\t text \t\n\r more \r\n\t"), STR("text \t\n\r more"), 0 }, - { STR("\r\n\t text \t\n\r more \r\n\t"), STR("text \t\n\n more"), parse_eol }, - { STR("\r\n\t text \r\n\r\n\r\n\r\n\r\n\r\n\r\n more \r\n\t"), STR("text \n\n\n\n\n\n\n more"), parse_eol }, - { STR(" test&&&&&&& "), STR("test&&&&&&&"), 0 }, - { STR(" test&&&&&&& "), STR("test&&&&&&&"), parse_escapes }, + { STR(" text"), STR("text"), 0 }, + { STR("\t\n text"), STR("text"), 0 }, + { STR("text "), STR("text"), 0 }, + { STR("text \t\n"), STR("text"), 0 }, + { STR("\r\n\t text \t\n\r"), STR("text"), 0 }, + { STR(" text"), STR("text"), parse_fragment }, + { STR("\t\n text"), STR("text"), parse_fragment }, + { STR("text "), STR("text"), parse_fragment }, + { STR("text \t\n"), STR("text"), parse_fragment }, + { STR("\r\n\t text \t\n\r"), STR("text"), parse_fragment }, + { STR("\r\n\t text \t\n\r more \r\n\t"), STR("text \t\n\r more"), 0 }, + { STR("\r\n\t text \t\n\r more \r\n\t"), STR("text \t\n\n more"), parse_eol }, + { STR("\r\n\t text \r\n\r\n\r\n\r\n\r\n\r\n\r\n more \r\n\t"), STR("text \n\n\n\n\n\n\n more"), parse_eol }, + { STR(" test&&&&&&& "), STR("test&&&&&&&"), 0 }, + { STR(" test&&&&&&& "), STR("test&&&&&&&"), parse_escapes }, { STR(" test&&&&&&& "), STR("test&&&&&&&"), parse_fragment | parse_escapes }, { STR("\r\n\t text \t\n\r m&&e \r\n\t"), STR("text \t\n\n m&&e"), parse_eol | parse_escapes } }; @@ -855,7 +855,7 @@ TEST(parse_declaration_error) CHECK(doc.load_string(STR(""), flags).status == status_bad_pi); CHECK(doc.load_string(STR(""), flags).status == status_bad_pi); } - + CHECK(doc.load_string(STR(""), parse_fragment | parse_declaration).status == status_bad_attribute); CHECK(doc.load_string(STR(""), parse_fragment | parse_declaration).status == status_bad_pi); } @@ -873,7 +873,7 @@ TEST(parse_out_of_memory) test_runner::_memory_fail_threshold = 256; xml_document doc; - CHECK(doc.load_string(STR("")).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.load_string(STR("")).status == status_out_of_memory)); CHECK(!doc.first_child()); } @@ -893,7 +893,7 @@ TEST(parse_out_of_memory_halfway_node) test_runner::_memory_fail_threshold = 65536; xml_document doc; - CHECK(doc.load_buffer_inplace(text, count * 4).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.load_buffer_inplace(text, count * 4).status == status_out_of_memory)); CHECK_NODE(doc.first_child(), STR("")); } @@ -920,12 +920,46 @@ TEST(parse_out_of_memory_halfway_attr) test_runner::_memory_fail_threshold = 65536; xml_document doc; - CHECK(doc.load_buffer_inplace(text, count * 5 + 4).status == status_out_of_memory); + CHECK_ALLOC_FAIL(CHECK(doc.load_buffer_inplace(text, count * 5 + 4).status == status_out_of_memory)); CHECK_STRING(doc.first_child().name(), STR("n")); CHECK_STRING(doc.first_child().first_attribute().name(), STR("a")); CHECK_STRING(doc.first_child().last_attribute().name(), STR("a")); } +TEST(parse_out_of_memory_conversion) +{ + test_runner::_memory_fail_threshold = 256; + + xml_document doc; + CHECK_ALLOC_FAIL(CHECK(doc.load_buffer("", 7, parse_default, encoding_latin1).status == status_out_of_memory)); + CHECK(!doc.first_child()); +} + +TEST(parse_out_of_memory_allocator_state_sync) +{ + const unsigned int count = 10000; + static char_t text[count * 4]; + + for (unsigned int i = 0; i < count; ++i) + { + text[4*i + 0] = '<'; + text[4*i + 1] = 'n'; + text[4*i + 2] = '/'; + text[4*i + 3] = '>'; + } + + test_runner::_memory_fail_threshold = 65536; + + xml_document doc; + CHECK_ALLOC_FAIL(CHECK(doc.load_buffer_inplace(text, count * 4).status == status_out_of_memory)); + CHECK_NODE(doc.first_child(), STR("")); + + test_runner::_memory_fail_threshold = 0; + + for (unsigned int j = 0; j < count; ++j) + CHECK(doc.append_child(STR("n"))); +} + static bool test_offset(const char_t* contents, unsigned int options, pugi::xml_parse_status status, ptrdiff_t offset) { xml_document doc; @@ -941,7 +975,7 @@ TEST(parse_error_offset) CHECK_OFFSET("", parse_default, status_ok, 0); test_runner::_memory_fail_threshold = 1; - CHECK_OFFSET("", parse_default, status_out_of_memory, 0); + CHECK_ALLOC_FAIL(CHECK_OFFSET("", parse_default, status_out_of_memory, 0)); test_runner::_memory_fail_threshold = 0; CHECK_OFFSET("<3d/>", parse_default, status_unrecognized_tag, 1); diff --git a/3party/pugixml/tests/test_parse_doctype.cpp b/3party/pugixml/tests/test_parse_doctype.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_unicode.cpp b/3party/pugixml/tests/test_unicode.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_version.cpp b/3party/pugixml/tests/test_version.cpp old mode 100644 new mode 100755 index 38ec7bcf39..99979bb56c --- a/3party/pugixml/tests/test_version.cpp +++ b/3party/pugixml/tests/test_version.cpp @@ -1,5 +1,5 @@ #include "../src/pugixml.hpp" -#if PUGIXML_VERSION != 160 +#if PUGIXML_VERSION != 170 #error Unexpected pugixml version #endif diff --git a/3party/pugixml/tests/test_write.cpp b/3party/pugixml/tests/test_write.cpp old mode 100644 new mode 100755 index 5aad5055ae..df7b0b1a54 --- a/3party/pugixml/tests/test_write.cpp +++ b/3party/pugixml/tests/test_write.cpp @@ -4,6 +4,7 @@ #include #include +#include TEST_XML(write_simple, "text") { @@ -20,6 +21,31 @@ TEST_XML(write_indent, "text") CHECK_NODE_EX(doc, STR("\n\t\n\t\ttext\n\t\n\n"), STR("\t"), format_indent); } +TEST_XML(write_indent_attributes, "text") +{ + CHECK_NODE_EX(doc, STR("\n\t\n\t\ttext\n\t\n\n"), STR("\t"), format_indent_attributes); +} + +TEST_XML(write_indent_attributes_empty_element, "") +{ + CHECK_NODE_EX(doc, STR("\n"), STR("\t"), format_indent_attributes); +} + +TEST_XML_FLAGS(write_indent_attributes_declaration, "", parse_full) +{ + CHECK_NODE_EX(doc, STR("\n\n"), STR("\t"), format_indent_attributes); +} + +TEST_XML(write_indent_attributes_raw, "text") +{ + CHECK_NODE_EX(doc, STR("text"), STR("\t"), format_indent_attributes | format_raw); +} + +TEST_XML(write_indent_attributes_empty_indent, "text") +{ + CHECK_NODE_EX(doc, STR("\n\ntext\n\n\n"), STR(""), format_indent_attributes); +} + TEST_XML(write_pcdata, "text") { CHECK_NODE_EX(doc, STR("\n\t\n\t\ttext\n\n"), STR("\t"), format_indent); @@ -574,3 +600,41 @@ TEST_XML_FLAGS(write_mixed, "premid\npostfin\n\n\n"), STR("\t"), 0); CHECK_NODE_EX(doc, STR("\n\t\n\tpremid\n\t\tpostfin\n\t\n\n"), STR("\t"), format_indent); } + +#ifndef PUGIXML_NO_EXCEPTIONS +struct throwing_writer: pugi::xml_writer +{ + virtual void write(const void*, size_t) + { + throw std::runtime_error("write failed"); + } +}; + +TEST_XML(write_throw_simple, "") +{ + try + { + throwing_writer w; + doc.print(w); + + CHECK_FORCE_FAIL("Expected exception"); + } + catch (std::runtime_error&) + { + } +} + +TEST_XML(write_throw_encoding, "") +{ + try + { + throwing_writer w; + doc.print(w, STR("\t"), format_default, encoding_utf32_be); + + CHECK_FORCE_FAIL("Expected exception"); + } + catch (std::runtime_error&) + { + } +} +#endif diff --git a/3party/pugixml/tests/test_xpath.cpp b/3party/pugixml/tests/test_xpath.cpp old mode 100644 new mode 100755 index 35f166779b..57fa95b452 --- a/3party/pugixml/tests/test_xpath.cpp +++ b/3party/pugixml/tests/test_xpath.cpp @@ -196,7 +196,7 @@ TEST(xpath_long_numbers_parse) { const pugi::char_t* str_flt_max = STR("340282346638528860000000000000000000000"); const pugi::char_t* str_flt_max_dec = STR("340282346638528860000000000000000000000.000000"); - + const pugi::char_t* str_dbl_max = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); const pugi::char_t* str_dbl_max_dec = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000"); @@ -225,7 +225,7 @@ TEST(xpath_long_numbers_stringize) { const pugi::char_t* str_flt_max = STR("340282346638528860000000000000000000000"); const pugi::char_t* str_flt_max_dec = STR("340282346638528860000000000000000000000.000000"); - + const pugi::char_t* str_dbl_max = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); const pugi::char_t* str_dbl_max_dec = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000"); @@ -378,19 +378,7 @@ TEST(xpath_out_of_memory_evaluate_concat) pugi::xpath_query q(query.c_str()); -#ifdef PUGIXML_NO_EXCEPTIONS - CHECK(q.evaluate_string(0, 0, xml_node()) == 1); -#else - try - { - q.evaluate_string(0, 0, xml_node()); - - CHECK_FORCE_FAIL("Expected out of memory exception"); - } - catch (const std::bad_alloc&) - { - } -#endif + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, xml_node()) == 1)); } TEST(xpath_out_of_memory_evaluate_substring) @@ -404,19 +392,7 @@ TEST(xpath_out_of_memory_evaluate_substring) pugi::xpath_query q(query.c_str()); -#ifdef PUGIXML_NO_EXCEPTIONS - CHECK(q.evaluate_string(0, 0, xml_node()) == 1); -#else - try - { - q.evaluate_string(0, 0, xml_node()); - - CHECK_FORCE_FAIL("Expected out of memory exception"); - } - catch (const std::bad_alloc&) - { - } -#endif + CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, xml_node()) == 1)); } TEST_XML(xpath_out_of_memory_evaluate_union, "") @@ -425,19 +401,7 @@ TEST_XML(xpath_out_of_memory_evaluate_union, " pugi::xpath_query q(STR("a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|(a|a)))))))))))))))))))")); -#ifdef PUGIXML_NO_EXCEPTIONS - CHECK(q.evaluate_node_set(doc.child(STR("node"))).empty()); -#else - try - { - q.evaluate_node_set(doc.child(STR("node"))); - - CHECK_FORCE_FAIL("Expected out of memory exception"); - } - catch (const std::bad_alloc&) - { - } -#endif + CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc.child(STR("node"))).empty())); } TEST_XML(xpath_out_of_memory_evaluate_predicate, "") @@ -446,19 +410,7 @@ TEST_XML(xpath_out_of_memory_evaluate_predicate, " pugi::xpath_query q(STR("//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[true()]]]]]]]]]]]]]]")); -#ifdef PUGIXML_NO_EXCEPTIONS - CHECK(q.evaluate_node_set(doc).empty()); -#else - try - { - q.evaluate_node_set(doc); - - CHECK_FORCE_FAIL("Expected out of memory exception"); - } - catch (const std::bad_alloc&) - { - } -#endif + CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc).empty())); } TEST(xpath_memory_concat_massive) @@ -634,20 +586,8 @@ TEST(xpath_allocate_string_out_of_memory) test_runner::_memory_fail_threshold = 8*1024; -#ifdef PUGIXML_NO_EXCEPTIONS - CHECK(!xpath_query(query.c_str())); -#else - try - { - #ifndef __DMC__ // DigitalMars exception handling crashes instead of catching the exception... - xpath_query q(query.c_str()); - - CHECK_FORCE_FAIL("Expected out of memory exception"); - #endif - } - catch (const std::bad_alloc&) - { - } +#ifndef __DMC__ // DigitalMars exception handling crashes instead of catching the exception... + CHECK_ALLOC_FAIL(CHECK(!xpath_query(query.c_str()))); #endif } diff --git a/3party/pugixml/tests/test_xpath_api.cpp b/3party/pugixml/tests/test_xpath_api.cpp old mode 100644 new mode 100755 index a2c4871939..e53c25a7d1 --- a/3party/pugixml/tests/test_xpath_api.cpp +++ b/3party/pugixml/tests/test_xpath_api.cpp @@ -7,6 +7,7 @@ #include "helpers.hpp" #include +#include TEST_XML(xpath_api_select_nodes, "") { @@ -30,12 +31,12 @@ TEST_XML(xpath_api_select_node, "" CHECK(n2.node().attribute(STR("id")).as_int() == 1); xpath_node n3 = doc.select_node(STR("node/bar")); - + CHECK(!n3); xpath_node n4 = doc.select_node(STR("node/head/following-sibling::foo")); xpath_node n5 = doc.select_node(STR("node/tail/preceding-sibling::foo")); - + CHECK(n4.node().attribute(STR("id")).as_int() == 1); CHECK(n5.node().attribute(STR("id")).as_int() == 1); } @@ -257,7 +258,7 @@ TEST(xpath_api_evaluate_string) // test for just enough space std::basic_string s1 = base; CHECK(q.evaluate_string(&s1[0], 11, xml_node()) == 11 && memcmp(&s1[0], STR("0123456789\0xxxxx"), 16 * sizeof(char_t)) == 0); - + // test for just not enough space std::basic_string s2 = base; CHECK(q.evaluate_string(&s2[0], 10, xml_node()) == 11 && memcmp(&s2[0], STR("012345678\0xxxxxx"), 16 * sizeof(char_t)) == 0); @@ -291,7 +292,7 @@ TEST(xpath_api_return_type) TEST(xpath_api_query_bool) { xpath_query q(STR("node")); - + CHECK(q); CHECK((!q) == false); } @@ -300,7 +301,7 @@ TEST(xpath_api_query_bool) TEST(xpath_api_query_bool_fail) { xpath_query q(STR("")); - + CHECK((q ? true : false) == false); CHECK((!q) == true); } @@ -356,6 +357,7 @@ TEST(xpath_api_exception_what) CHECK(e.what()[0] != 0); } } +#endif TEST(xpath_api_node_set_ctor_out_of_memory) { @@ -363,15 +365,7 @@ TEST(xpath_api_node_set_ctor_out_of_memory) xpath_node data[2]; - try - { - xpath_node_set ns(data, data + 2); - - CHECK_FORCE_FAIL("Expected out of memory exception"); - } - catch (const std::bad_alloc&) - { - } + CHECK_ALLOC_FAIL(xpath_node_set ns(data, data + 2)); } TEST(xpath_api_node_set_copy_ctor_out_of_memory) @@ -381,40 +375,28 @@ TEST(xpath_api_node_set_copy_ctor_out_of_memory) test_runner::_memory_fail_threshold = 1; - try - { - xpath_node_set copy = ns; - - CHECK_FORCE_FAIL("Expected out of memory exception"); - } - catch (const std::bad_alloc&) - { - } + CHECK_ALLOC_FAIL(xpath_node_set copy = ns); } TEST_XML(xpath_api_node_set_assign_out_of_memory_preserve, "") { xpath_node_set ns = doc.select_nodes(STR("node/*")); CHECK(ns.size() == 2); + CHECK(ns.type() == xpath_node_set::type_sorted); xpath_node_set nsall = doc.select_nodes(STR("//*")); + nsall.sort(true); CHECK(nsall.size() == 3); + CHECK(nsall.type() == xpath_node_set::type_sorted_reverse); test_runner::_memory_fail_threshold = 1; - try - { - ns = nsall; + CHECK_ALLOC_FAIL(ns = nsall); - CHECK_FORCE_FAIL("Expected out of memory exception"); - } - catch (const std::bad_alloc&) - { - } - - CHECK(ns.size() == 2 && ns[0] == doc.child(STR("node")).child(STR("a")) && ns[1] == doc.child(STR("node")).child(STR("b"))); + CHECK(ns.size() == 2); + CHECK(ns.type() == xpath_node_set::type_sorted); + CHECK(ns[0] == doc.child(STR("node")).child(STR("a")) && ns[1] == doc.child(STR("node")).child(STR("b"))); } -#endif TEST_XML(xpath_api_deprecated_select_single_node, "") { @@ -426,4 +408,233 @@ TEST_XML(xpath_api_deprecated_select_single_node, "= 201103 +TEST_XML(xpath_api_nodeset_move_ctor, "") +{ + xpath_node_set set = doc.select_nodes(STR("node/bar/preceding::*")); + + CHECK(set.size() == 2); + CHECK(set.type() == xpath_node_set::type_sorted_reverse); + + test_runner::_memory_fail_threshold = 1; + + xpath_node_set move = std::move(set); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_unsorted); + + CHECK(move.size() == 2); + CHECK(move.type() == xpath_node_set::type_sorted_reverse); + CHECK(move[1] == doc.first_child().first_child()); +} + + +TEST_XML(xpath_api_nodeset_move_ctor_single, "") +{ + xpath_node_set set = doc.select_nodes(STR("node/bar")); + + CHECK(set.size() == 1); + CHECK(set.type() == xpath_node_set::type_sorted); + + test_runner::_memory_fail_threshold = 1; + + xpath_node_set move = std::move(set); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_unsorted); + + CHECK(move.size() == 1); + CHECK(move.type() == xpath_node_set::type_sorted); + CHECK(move[0] == doc.first_child().last_child()); +} + +TEST(xpath_api_nodeset_move_ctor_empty) +{ + xpath_node_set set; + set.sort(); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_sorted); + + test_runner::_memory_fail_threshold = 1; + + xpath_node_set move = std::move(set); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_unsorted); + + CHECK(move.size() == 0); + CHECK(move.type() == xpath_node_set::type_sorted); +} + +TEST_XML(xpath_api_nodeset_move_assign, "") +{ + xpath_node_set set = doc.select_nodes(STR("node/bar/preceding::*")); + + CHECK(set.size() == 2); + CHECK(set.type() == xpath_node_set::type_sorted_reverse); + + test_runner::_memory_fail_threshold = 1; + + xpath_node_set move; + + CHECK(move.size() == 0); + CHECK(move.type() == xpath_node_set::type_unsorted); + + move = std::move(set); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_unsorted); + + CHECK(move.size() == 2); + CHECK(move.type() == xpath_node_set::type_sorted_reverse); + CHECK(move[1] == doc.first_child().first_child()); +} + +TEST_XML(xpath_api_nodeset_move_assign_destroy, "") +{ + xpath_node_set set = doc.select_nodes(STR("node/bar/preceding::*")); + + CHECK(set.size() == 2); + CHECK(set.type() == xpath_node_set::type_sorted_reverse); + + xpath_node_set all = doc.select_nodes(STR("//*")); + + CHECK(all.size() == 4); + + test_runner::_memory_fail_threshold = 1; + + all = std::move(set); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_unsorted); + + CHECK(all.size() == 2); + CHECK(all.type() == xpath_node_set::type_sorted_reverse); + CHECK(all[1] == doc.first_child().first_child()); +} + +TEST_XML(xpath_api_nodeset_move_assign_single, "") +{ + xpath_node_set set = doc.select_nodes(STR("node/bar")); + + CHECK(set.size() == 1); + CHECK(set.type() == xpath_node_set::type_sorted); + + test_runner::_memory_fail_threshold = 1; + + xpath_node_set move; + + CHECK(move.size() == 0); + CHECK(move.type() == xpath_node_set::type_unsorted); + + move = std::move(set); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_unsorted); + + CHECK(move.size() == 1); + CHECK(move.type() == xpath_node_set::type_sorted); + CHECK(move[0] == doc.first_child().last_child()); +} + +TEST(xpath_api_nodeset_move_assign_empty) +{ + xpath_node_set set; + set.sort(); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_sorted); + + test_runner::_memory_fail_threshold = 1; + + xpath_node_set move; + + CHECK(move.size() == 0); + CHECK(move.type() == xpath_node_set::type_unsorted); + + move = std::move(set); + + CHECK(set.size() == 0); + CHECK(set.type() == xpath_node_set::type_unsorted); + + CHECK(move.size() == 0); + CHECK(move.type() == xpath_node_set::type_sorted); +} + +TEST(xpath_api_query_move) +{ + xml_node c; + + xpath_query q1(STR("true()")); + xpath_query q4(STR("true() and false()")); + + test_runner::_memory_fail_threshold = 1; + + CHECK(q1); + CHECK(q1.evaluate_boolean(c)); + + xpath_query q2 = std::move(q1); + CHECK(!q1); + CHECK(!q1.evaluate_boolean(c)); + CHECK(q2); + CHECK(q2.evaluate_boolean(c)); + + xpath_query q3; + CHECK(!q3); + CHECK(!q3.evaluate_boolean(c)); + + q3 = std::move(q2); + CHECK(!q2); + CHECK(!q2.evaluate_boolean(c)); + CHECK(q3); + CHECK(q3.evaluate_boolean(c)); + + CHECK(q4); + CHECK(!q4.evaluate_boolean(c)); + + q4 = std::move(q3); + + CHECK(!q3); + CHECK(!q3.evaluate_boolean(c)); + CHECK(q4); + CHECK(q4.evaluate_boolean(c)); + + q4 = std::move(*&q4); + + CHECK(q4); + CHECK(q4.evaluate_boolean(c)); +} + +TEST(xpath_api_query_vector) +{ + std::vector qv; + + for (int i = 0; i < 10; ++i) + { + char_t expr[2]; + expr[0] = char_t('0' + i); + expr[1] = 0; + + qv.push_back(xpath_query(expr)); + } + + double result = 0; + + for (auto& q: qv) + result += q.evaluate_number(xml_node()); + + CHECK(result == 45); +} +#endif #endif diff --git a/3party/pugixml/tests/test_xpath_functions.cpp b/3party/pugixml/tests/test_xpath_functions.cpp old mode 100644 new mode 100755 index 211dbfb162..eb43bb5d06 --- a/3party/pugixml/tests/test_xpath_functions.cpp +++ b/3party/pugixml/tests/test_xpath_functions.cpp @@ -6,7 +6,7 @@ TEST_XML(xpath_number_number, "123") { xml_node c; xml_node n = doc.child(STR("node")).first_child(); - + // number with 0 arguments CHECK_XPATH_NUMBER_NAN(c, STR("number()")); CHECK_XPATH_NUMBER(n, STR("number()"), 123); @@ -35,7 +35,7 @@ TEST_XML(xpath_number_number, "123") // number with 1 number argument CHECK_XPATH_NUMBER(c, STR("number(1)"), 1); - + // number with 2 arguments CHECK_XPATH_FAIL(STR("number(1, 2)")); } @@ -44,21 +44,21 @@ TEST_XML(xpath_number_sum, "123789") { xml_node c; xml_node n = doc.child(STR("node")); - + // sum with 0 arguments CHECK_XPATH_FAIL(STR("sum()")); // sum with 1 argument CHECK_XPATH_NUMBER(c, STR("sum(.)"), 0); CHECK_XPATH_NUMBER(n, STR("sum(.)"), 123789); // 123 .. 789 - + CHECK_XPATH_NUMBER(n, STR("sum(./descendant-or-self::node())"), 125490); // node + 123 + child + 789 = 123789 + 123 + 789 + 789 = 125490 CHECK_XPATH_NUMBER(n, STR("sum(.//node())"), 1701); // 123 + child + 789 = 123 + 789 + 789 CHECK_XPATH_NUMBER_NAN(doc.last_child(), STR("sum(.)")); // sum with 2 arguments CHECK_XPATH_FAIL(STR("sum(1, 2)")); - + // sum with 1 non-node-set argument CHECK_XPATH_FAIL(STR("sum(1)")); } @@ -155,7 +155,7 @@ TEST(xpath_number_round) TEST_XML(xpath_boolean_boolean, "") { xml_node c; - + // boolean with 0 arguments CHECK_XPATH_FAIL(STR("boolean()")); @@ -182,14 +182,14 @@ TEST_XML(xpath_boolean_boolean, "") TEST(xpath_boolean_not) { xml_node c; - + // not with 0 arguments CHECK_XPATH_FAIL(STR("not()")); // not with 1 argument CHECK_XPATH_BOOLEAN(c, STR("not(true())"), false); CHECK_XPATH_BOOLEAN(c, STR("not(false())"), true); - + // boolean with 2 arguments CHECK_XPATH_FAIL(STR("not(1, 2)")); } @@ -197,7 +197,7 @@ TEST(xpath_boolean_not) TEST(xpath_boolean_true) { xml_node c; - + // true with 0 arguments CHECK_XPATH_BOOLEAN(c, STR("true()"), true); @@ -208,7 +208,7 @@ TEST(xpath_boolean_true) TEST(xpath_boolean_false) { xml_node c; - + // false with 0 arguments CHECK_XPATH_BOOLEAN(c, STR("false()"), false); @@ -219,7 +219,7 @@ TEST(xpath_boolean_false) TEST_XML(xpath_boolean_lang, "") { xml_node c; - + // lang with 0 arguments CHECK_XPATH_FAIL(STR("lang()")); @@ -228,7 +228,7 @@ TEST_XML(xpath_boolean_lang, " \t\r\rval1 \rval2\r\nval3\ // normalize-space with 0 arguments CHECK_XPATH_STRING(c, STR("normalize-space()"), STR("")); CHECK_XPATH_STRING(n, STR("normalize-space()"), STR("val1 val2 val3 val4")); - + // normalize-space with 1 argument CHECK_XPATH_STRING(c, STR("normalize-space('')"), STR("")); CHECK_XPATH_STRING(c, STR("normalize-space('abcd')"), STR("abcd")); @@ -526,7 +526,7 @@ TEST_XML_FLAGS(xpath_string_normalize_space, " \t\r\rval1 \rval2\r\nval3\ CHECK_XPATH_STRING(c, STR("normalize-space('ab\r\n\tcd')"), STR("ab cd")); CHECK_XPATH_STRING(c, STR("normalize-space('ab cd')"), STR("ab cd")); CHECK_XPATH_STRING(c, STR("normalize-space('\07')"), STR("\07")); - + // normalize-space with 2 arguments CHECK_XPATH_FAIL(STR("normalize-space(1, 2)")); } @@ -537,13 +537,13 @@ TEST(xpath_string_translate) // translate with 0 arguments CHECK_XPATH_FAIL(STR("translate()")); - + // translate with 1 argument CHECK_XPATH_FAIL(STR("translate('a')")); // translate with 2 arguments CHECK_XPATH_FAIL(STR("translate('a', 'b')")); - + // translate with 3 arguments CHECK_XPATH_STRING(c, STR("translate('abc', '', '')"), STR("abc")); CHECK_XPATH_STRING(c, STR("translate('abc', '', 'foo')"), STR("abc")); @@ -604,7 +604,7 @@ TEST_XML(xpath_nodeset_position, "") // id with 0 arguments CHECK_XPATH_FAIL(STR("id()")); - + // id with 1 argument - no DTD => no id CHECK_XPATH_NODESET(n, STR("id('foo')")); @@ -656,7 +656,7 @@ TEST_XML_FLAGS(xpath_nodeset_local_name, "text< // local-name with 0 arguments CHECK_XPATH_STRING(c, STR("local-name()"), STR("")); CHECK_XPATH_STRING(n, STR("local-name()"), STR("node")); - + // local-name with 1 non-node-set argument CHECK_XPATH_FAIL(STR("local-name(1)")); @@ -681,7 +681,7 @@ TEST_XML_FLAGS(xpath_nodeset_namespace_uri, "te // namespace-uri with 0 arguments CHECK_XPATH_STRING(c, STR("namespace-uri()"), STR("")); CHECK_XPATH_STRING(n.child(STR("c2")).child(STR("foo:child")), STR("namespace-uri()"), STR("http://foo2")); - + // namespace-uri with 1 non-node-set argument CHECK_XPATH_FAIL(STR("namespace-uri(1)")); @@ -710,7 +710,7 @@ TEST_XML_FLAGS(xpath_nodeset_name, "text1-1") CHECK_XPATH_NODESET(doc, STR("/*[/]")) % 2; } -#ifdef PUGIXML_NO_EXCEPTIONS -# define CHECK_XPATH_FAIL_OOM(query) CHECK_XPATH_FAIL(query) -#else -static void test_xpath_fail_oom(const char_t* query) -{ - try - { - pugi::xpath_query q(query); - - CHECK_FORCE_FAIL("Expected out of memory exception"); - } - catch (const std::bad_alloc&) - { - } -} - -# define CHECK_XPATH_FAIL_OOM(query) test_xpath_fail_oom(query) -#endif - TEST(xpath_parse_out_of_memory_first_page) { test_runner::_memory_fail_threshold = 1; - CHECK_XPATH_FAIL_OOM(STR("1")); + CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL(STR("1"))); } TEST(xpath_parse_out_of_memory_second_page_node) { test_runner::_memory_fail_threshold = 8192; - CHECK_XPATH_FAIL_OOM(STR("1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1")); + CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL(STR("1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1"))); } TEST(xpath_parse_out_of_memory_string_to_number) { test_runner::_memory_fail_threshold = 4096 + 128; - CHECK_XPATH_FAIL_OOM(STR("0.11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); + CHECK_ALLOC_FAIL(CHECK_XPATH_FAIL(STR("0.11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"))); } TEST(xpath_parse_qname_error) diff --git a/3party/pugixml/tests/test_xpath_paths.cpp b/3party/pugixml/tests/test_xpath_paths.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_xpath_paths_abbrev_w3c.cpp b/3party/pugixml/tests/test_xpath_paths_abbrev_w3c.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_xpath_paths_w3c.cpp b/3party/pugixml/tests/test_xpath_paths_w3c.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_xpath_variables.cpp b/3party/pugixml/tests/test_xpath_variables.cpp old mode 100644 new mode 100755 index 3a33c1d54c..fec138600e --- a/3party/pugixml/tests/test_xpath_variables.cpp +++ b/3party/pugixml/tests/test_xpath_variables.cpp @@ -177,7 +177,8 @@ TEST(xpath_variables_set_out_of_memory) xpath_variable_set set; - xpath_variable* var = set.add(STR("target"), xpath_type_number); + xpath_variable* var = 0; + CHECK_ALLOC_FAIL(var = set.add(STR("target"), xpath_type_number)); CHECK(!var); } @@ -190,7 +191,7 @@ TEST(xpath_variables_out_of_memory) xpath_variable* var = set.add(STR("target"), xpath_type_string); CHECK(var); - CHECK(!var->set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))); + CHECK_ALLOC_FAIL(CHECK(!var->set(STR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")))); } TEST_XML(xpath_variables_evaluate, "") @@ -260,7 +261,7 @@ TEST(xpath_variables_multiple_documents) CHECK(ns.size() == 3); CHECK(ns[0] != ns[1] && ns[0] != ns[2]); - + xml_node n0 = doc.child(STR("node")), n1 = doc1.child(STR("node")), n2 = doc2.child(STR("node")); CHECK(n0 == ns[0].node() || n0 == ns[1].node() || n0 == ns[2].node()); @@ -283,20 +284,7 @@ TEST(xpath_variables_long_name_out_of_memory) test_runner::_memory_fail_threshold = 4096 + 64 + 52 * sizeof(char_t); -#ifdef PUGIXML_NO_EXCEPTIONS - xpath_query q(STR("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), &set); - CHECK(!q); -#else - try - { - xpath_query q(STR("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), &set); - - CHECK_FORCE_FAIL("Expected exception"); - } - catch (const xpath_exception&) - { - } -#endif + CHECK_ALLOC_FAIL(CHECK(!xpath_query(STR("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), &set))); } TEST_XML(xpath_variables_select, "") @@ -425,4 +413,170 @@ TEST_XML(xpath_variables_count_sum, "122334") +{ + xpath_variable_set set1; + set1.set(STR("a"), true); + set1.set(STR("b"), 2.0); + set1.set(STR("c"), STR("string")); + set1.set(STR("d"), doc.select_nodes(STR("//*"))); + + CHECK_XPATH_STRING_VAR(xml_node(), STR("substring($c, count($d[$a]) + $b)"), &set1, STR("ring")); + + xpath_variable_set set2 = set1; + + CHECK_XPATH_STRING_VAR(xml_node(), STR("substring($c, count($d[$a]) + $b)"), &set2, STR("ring")); + + xpath_variable_set set3; + + CHECK(!set3.get(STR("a"))); + + set3 = set1; + + CHECK_XPATH_STRING_VAR(xml_node(), STR("substring($c, count($d[$a]) + $b)"), &set2, STR("ring")); + + set3 = set3; + + CHECK_XPATH_STRING_VAR(xml_node(), STR("substring($c, count($d[$a]) + $b)"), &set2, STR("ring")); + + set3 = xpath_variable_set(); + + CHECK(!set3.get(STR("a"))); +} + +TEST_XML(xpath_variables_copy_out_of_memory, "") +{ + xpath_variable_set set1; + set1.set(STR("a"), true); + set1.set(STR("b"), 2.0); + set1.set(STR("c"), STR("string")); + set1.set(STR("d"), doc.select_nodes(STR("//*"))); + + xpath_variable_set set2 = set1; + + test_runner::_memory_fail_threshold = 32768 + 75 * sizeof(void*); + + CHECK_ALLOC_FAIL(xpath_variable_set set3 = set1); + + xpath_variable_set set4; + + CHECK_ALLOC_FAIL(set4 = set1); + CHECK(!set4.get(STR("a")) && !set4.get(STR("b")) && !set4.get(STR("c")) && !set4.get(STR("d"))); + + CHECK_ALLOC_FAIL(set2 = set1); + + CHECK(set2.get(STR("a")) && set2.get(STR("b")) && set2.get(STR("c")) && set2.get(STR("d"))); + + CHECK(set2.get(STR("a"))->get_boolean() == true); + CHECK(set2.get(STR("b"))->get_number() == 2.0); + CHECK_STRING(set2.get(STR("c"))->get_string(), STR("string")); + CHECK(set2.get(STR("d"))->get_node_set().size() == 2); +} + +#if __cplusplus >= 201103 +TEST_XML(xpath_variables_move, "") +{ + xpath_variable_set set; + set.set(STR("a"), true); + set.set(STR("b"), 2.0); + set.set(STR("c"), STR("string")); + set.set(STR("d"), doc.select_nodes(STR("//*"))); + + xpath_variable_set copy = set; + copy.set(STR("e"), 42.0); + + test_runner::_memory_fail_threshold = 1; + + xpath_variable_set move1 = std::move(set); + + CHECK(!set.get(STR("a")) && !set.get(STR("b")) && !set.get(STR("c")) && !set.get(STR("d"))); + CHECK(move1.get(STR("a")) && move1.get(STR("b")) && move1.get(STR("c")) && move1.get(STR("d"))); + + CHECK(move1.get(STR("a"))->get_boolean() == true); + CHECK(move1.get(STR("b"))->get_number() == 2.0); + CHECK_STRING(move1.get(STR("c"))->get_string(), STR("string")); + CHECK(move1.get(STR("d"))->get_node_set().size() == 1); + + xpath_variable_set move2; + move2 = std::move(move1); + + CHECK(!move1.get(STR("a")) && !move1.get(STR("b")) && !move1.get(STR("c")) && !move1.get(STR("d"))); + CHECK(move2.get(STR("a")) && move2.get(STR("b")) && move2.get(STR("c")) && move2.get(STR("d"))); + + CHECK(copy.get(STR("e"))); + + copy = std::move(move2); + + CHECK(!move2.get(STR("a")) && !move2.get(STR("b")) && !move2.get(STR("c")) && !move2.get(STR("d"))); + CHECK(copy.get(STR("a")) && copy.get(STR("b")) && copy.get(STR("c")) && copy.get(STR("d"))); + CHECK(!copy.get(STR("e"))); + + CHECK(copy.get(STR("a"))->get_boolean() == true); + CHECK(copy.get(STR("b"))->get_number() == 2.0); + CHECK_STRING(copy.get(STR("c"))->get_string(), STR("string")); + CHECK(copy.get(STR("d"))->get_node_set().size() == 1); +} +#endif + +TEST(xpath_variables_copy_big) +{ + xpath_variable_set set; + + for (int i = 0; i < 100; ++i) + { + char_t name[4]; + name[0] = 'a'; + name[1] = char_t('0' + i / 10); + name[2] = char_t('0' + i % 10); + name[3] = 0; + + set.set(name, double(i)); + } + + xpath_variable_set copy = set; + + for (int j = 0; j < 100; ++j) + { + char_t name[4]; + name[0] = 'a'; + name[1] = char_t('0' + j / 10); + name[2] = char_t('0' + j % 10); + name[3] = 0; + + CHECK(copy.get(name) && copy.get(name)->get_number() == j); + } +} + +TEST(xpath_variables_copy_big_out_of_memory) +{ + xpath_variable_set set; + + for (int i = 0; i < 100; ++i) + { + char_t name[4]; + name[0] = 'a'; + name[1] = char_t('0' + i / 10); + name[2] = char_t('0' + i % 10); + name[3] = 0; + + set.set(name, double(i)); + } + + test_runner::_memory_fail_threshold = 1; + + xpath_variable_set copy; + CHECK_ALLOC_FAIL(copy = set); + + for (int j = 0; j < 100; ++j) + { + char_t name[4]; + name[0] = 'a'; + name[1] = char_t('0' + j / 10); + name[2] = char_t('0' + j % 10); + name[3] = 0; + + CHECK(!copy.get(name)); + } +} #endif diff --git a/3party/pugixml/tests/test_xpath_xalan_1.cpp b/3party/pugixml/tests/test_xpath_xalan_1.cpp old mode 100644 new mode 100755 index 7f87c52a25..28db218340 --- a/3party/pugixml/tests/test_xpath_xalan_1.cpp +++ b/3party/pugixml/tests/test_xpath_xalan_1.cpp @@ -363,7 +363,7 @@ TEST_XML(xpath_xalan_math_8, "0.0004") CHECK_XPATH_NUMBER(doc, STR("number(4 div 10000)"), 0.0004); // +0 works around extended precision in div on x86 (this is needed for some configurations in MinGW 3.4) - CHECK_XPATH_BOOLEAN(doc, STR("(number(k) = (4 div 10000 + 0))"), true); + CHECK_XPATH_BOOLEAN(doc, STR("(number(k) = (4 div 10000 + 0))"), true); CHECK_XPATH_NUMBER(doc, STR("number(0.0001 * 4)"), 0.0004); CHECK_XPATH_BOOLEAN(doc, STR("(number(k) = (0.0001 * 4))"), true); } diff --git a/3party/pugixml/tests/test_xpath_xalan_2.cpp b/3party/pugixml/tests/test_xpath_xalan_2.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_xpath_xalan_3.cpp b/3party/pugixml/tests/test_xpath_xalan_3.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_xpath_xalan_4.cpp b/3party/pugixml/tests/test_xpath_xalan_4.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/test_xpath_xalan_5.cpp b/3party/pugixml/tests/test_xpath_xalan_5.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/writer_string.cpp b/3party/pugixml/tests/writer_string.cpp old mode 100644 new mode 100755 diff --git a/3party/pugixml/tests/writer_string.hpp b/3party/pugixml/tests/writer_string.hpp old mode 100644 new mode 100755 index 0c1089d818..6bffc3213f --- a/3party/pugixml/tests/writer_string.hpp +++ b/3party/pugixml/tests/writer_string.hpp @@ -8,7 +8,7 @@ struct xml_writer_string: public pugi::xml_writer { std::string contents; - + virtual void write(const void* data, size_t size); std::string as_narrow() const;
optimization
$define
$platform$toolset pass"; - - if ($coverage > 0) - { - print "
" . ($coverage + 0) . "%"; - } - - print "
passfail