Compare commits

...

725 commits
v1.6 ... master

Author SHA1 Message Date
Arseny Kapoulkine
1dc3266fff docs: Add missing documentation for xml_node::attribute with hint
The feature was added in 2015 but somehow was never documented.
2022-11-08 16:49:34 -08:00
Arseny Kapoulkine
cb217f5a85
Merge pull request #530 from zeux/snprintf
Fix Xcode 14 sprintf deprecation warning
2022-11-06 15:09:53 -08:00
Arseny Kapoulkine
e11e0c965f Fix comment typo. 2022-11-06 13:47:53 -08:00
Arseny Kapoulkine
b6b747244e Adjust the workaround for -pedantic mode and fix tests 2022-11-06 10:21:35 -08:00
Arseny Kapoulkine
8be081fbbe Fix Xcode 14 sprintf deprecation warning
We use snprintf when stdc is set to C++11, however in C++98 mode we can't use variadic macros,
and Xcode 14 complains about the use of sprintf.

It should be safe however to use variadic macros on any remotely recent version of clang on Apple,
unless -pedantic is defined which warns against the use of variadic macros in C++98 mode...

This change fixes the problem for the builds that don't specify -pedantic, which is a problem for
another day.
2022-11-06 10:16:21 -08:00
Arseny Kapoulkine
a0e0643363
Merge pull request #526 from zeux/newver
Prepare for 1.13 release
2022-10-28 16:53:25 -07:00
Arseny Kapoulkine
3bd1f452b5 Fix version check in test 2022-10-20 20:23:26 -07:00
Arseny Kapoulkine
c5b288d91a Update HTML documentation 2022-10-20 20:20:45 -07:00
Arseny Kapoulkine
0ef3da1e6e Update release notes and manual for 1.13
This includes a previously unnoticed link fix for xml_text::set
2022-10-20 20:18:08 -07:00
Arseny Kapoulkine
76dcd89427 Update version number in preparation for 1.13 2022-10-20 20:08:52 -07:00
Arseny Kapoulkine
43ef7e25d9
Merge pull request #525 from bruxisma/master
Fix exported symbols under clang-cl (Closes #503)
2022-10-20 19:49:48 -07:00
Izzy Muerte
ab8af53059 Fix exported symbols under clang-cl (Closes #503)
This also turns the define for PUGIXML_API into an `$<IF:>`, instead of an
`$<IF:>` with an empty true condition. If this is inadequate, I will
undo it, and place them on separate lines as they were before, but will
most likely use an inverse `$<NOT:>` instead of an `$<IF:>`.
2022-10-20 13:35:49 -07:00
Arseny Kapoulkine
86c9105154
Merge pull request #523 from zeux/ferrh
Fix error handling in xml_document::save_file
2022-10-09 09:08:50 -07:00
Arseny Kapoulkine
444963e269 Fix error handling in xml_document::save_file
There were two conditions under which xml_document::save_file could
previously return true even though the saving failed:

- The last write to the file was buffered in stdio buffer, and it's that
  last write that would fail due to lack of disk space
- The data has been written correctly but fclose failed to update file
  metadata, which can result in truncated size / missing inode updates.

This change fixes both by adjusting save_file to fflush before the check,
and also checking fclose results. Note that while fflush here is
technically redundant, because it's implied by fclose, we must check
ferror explicitly anyway, and so it feels a little cleaner to do most of
the error handling in save_file_impl, so that the changes of fclose()
failing are very slim.

Of course, neither change guarantees that the contents of the file are
going to be safe on disk following a power failure.
2022-10-07 22:13:04 -07:00
Arseny Kapoulkine
0cb4f02579 Final tweaks after #522
This cleans up xml_attribute::set_value to be uniform wrt
xml_node::set_value and xml_text::set_value - for now we duplicate the
body since the logic is trivial and this keeps debug performance
excellent.
2022-10-07 21:46:27 -07:00
Arseny Kapoulkine
c342266fae
Merge pull request #522 from Ferenc-/followup-on-pr-490
Followup on pr 490
2022-10-07 21:42:41 -07:00
Ferenc Géczi
39e169285c Add test for xml_attribute::set_value with size argument 2022-09-29 00:00:00 +00:00
Ferenc Géczi
1905284494 Add test for xml_node::set_value with size argument 2022-09-29 00:00:00 +00:00
Ferenc Géczi
d359402311 Add xml_text::set test with size set to substring 2022-09-29 00:00:00 +00:00
Ferenc Géczi
09e7cc9b1c Add test for xml_text::set with size argument 2022-09-29 00:00:00 +00:00
Ferenc Géczi
f327371219 Add overloads with size_t type argument
* xml_node::set_value(const char_t* rhs, size_t sz)
* xml_text::set(const char_t* rhs, size_t sz)

Signed-off-by: Ferenc Géczi <ferenc.gm@gmail.com>
2022-09-29 18:26:05 +00:00
Arseny Kapoulkine
bcf483c3b7
Merge pull request #492 from KDAB/fix-default-visibility
Correctly set default visibility on non-windows compilers
2022-09-27 12:53:06 -07:00
Milian Wolff
173a263490 Correctly set default visibility on non-windows compilers
This fixes compilation of pugixml with -fvisibility=hidden. Without
this patch, one would get lots of unresolved symbols when consuming
pugixml as a shared library.
2022-09-25 11:37:48 +02:00
Arseny Kapoulkine
521b2cd854 Add issue templates to try to route questions to Discussions 2022-09-02 21:42:25 -07:00
Arseny Kapoulkine
27bc68ab45
Merge pull request #506 from brandl-muc/nullptr_for_msvc
Enable usage of nullptr for MSVC 16 and newer (MSVS 2010)
2022-08-04 08:46:13 -07:00
Matthäus Brandl
f7de324855 Enable usage of nullptr for MSVC 16 and newer (MSVS 2010) 2022-08-04 16:59:37 +02:00
Arseny Kapoulkine
3b5c1fb022 tests: Fix MSVC 2005 build
... I forgot we still support platforms without C99, 23 years later.
2022-07-21 21:17:17 -07:00
Arseny Kapoulkine
ab8453c572 tests: Use snprintf instead of sprintf
sprintf now results in a deprecation warning in Xcode 14 beta.
2022-07-21 20:51:26 -07:00
Arseny Kapoulkine
2639dfd053
Merge pull request #477 from zeux/compactopt
Optimize compact mode
2022-05-31 20:00:01 -05:00
Arseny Kapoulkine
0401559dde
Merge pull request #498 from zeux/fix-oom-safer
Fix memory leak during OOM in convert_buffer
2022-05-16 20:50:07 -07:00
Arseny Kapoulkine
832a4f4914 Use more idiomatic code in this codebase 2022-05-16 19:14:29 -07:00
Arseny Kapoulkine
33a75c734b Fix memory leak during OOM in convert_buffer
This is the same fix as #497, but we're using auto_deleter instead
because if allocation function throws, we can't rely on an explicit call
to deallocate.

Comes along with two tests that validate the behavior.
2022-05-16 19:12:52 -07:00
Arseny Kapoulkine
ec851bb18d
Merge pull request #497 from TodorHryn/master
Fix memory leak
2022-05-16 19:05:29 -07:00
TodorHryn
6fbf32140b Fix memory leak 2022-05-16 13:21:20 +03:00
Viktor Govako
effc46f0ed Added bool set_value(const char_t* rhs, size_t sz). 2022-04-13 12:25:01 +03:00
Arseny Kapoulkine
363ebdde91
Merge pull request #482 from zeux/fix-msvc-test
tests: Fix MSVC 2022 build
2022-02-15 21:12:03 -08:00
Arseny Kapoulkine
c60ca94cdd tests: Fix MSVC 2022 build
Instead of trying to detect if we can safely use random shuffle simply reimplement it ourselves.
The quality of the RNG is not essential for these tests.
2022-02-15 20:23:05 -08:00
Arseny Kapoulkine
dd50fa5b45 Fix PUGIXML_VERSION macro
Also make sure the line shows up in grep when using the current version
number.

Fixes #478.
2022-02-10 08:36:19 -08:00
Arseny Kapoulkine
2fa9158b4f Optimize compact mode: xml_text 2022-02-08 23:04:31 -08:00
Arseny Kapoulkine
fad2d5e4ef Optimize compact mode: xml_attribute/xml_node implementation 2022-02-08 23:00:17 -08:00
Arseny Kapoulkine
f388c465dd Optimize compact mode: reuse access in insert/remove 2022-02-08 22:44:31 -08:00
Arseny Kapoulkine
314baf6605 docs: Regenerate HTML documentation 2022-02-08 20:09:10 -08:00
Arseny Kapoulkine
eb918f2078 docs: Update manual with 1.12 changelog 2022-02-08 19:59:44 -08:00
Arseny Kapoulkine
25c4fb74a8 Update copyright year to 2022 2022-02-08 19:58:58 -08:00
Arseny Kapoulkine
c9e219c17b Update version to 1.12 2022-02-08 19:56:41 -08:00
Arseny Kapoulkine
9ba92a7fa7 Restore compatibility with WinCE
WinCE lacks most recent CRT additions to MSVC; we used to explicitly disable specific sections
of code, but it's more comprehensive to just specify that the CRT is from MSVC7 instead of MSVC8.

Fixes #401
2022-02-08 19:19:34 -08:00
Arseny Kapoulkine
6ce48ec379
Merge pull request #468 from appls/master
Add support for Visual Studio 2022 with Platform Toolset v143.
2022-02-08 12:43:53 -08:00
Arseny Kapoulkine
428606b3c1
Create SECURITY.md
Fixes #475
2022-02-06 09:13:33 -08:00
tobias
64de196ba9 Fix path. 2022-01-21 15:56:25 +01:00
tobias
bd90579718 Add missing build script and test script entries for appveyor. 2022-01-21 15:44:39 +01:00
tobias
16a4f382ac Add missing appveyor test config for Visual Studio 2022. 2022-01-21 15:30:45 +01:00
tobias
bc2448afbb Add support for Visual Studio 2022 with Platform Toolset v143. 2022-01-21 15:06:27 +01:00
Arseny Kapoulkine
9e382f9807
Merge pull request #436 from zeux/zeux-patch-1
Set CMP0091 CMake policy
2021-08-07 19:06:12 -07:00
Arseny Kapoulkine
f1fbd707f1
Set CMP0091 CMake policy
This allows the correct use of runtime library override.

Fixes #412
2021-08-07 09:57:21 -07:00
Arseny Kapoulkine
a5991972ba
Merge pull request #426 from bjornblissing/feature/cmake_pugiconfig
Add Cmake options for pugiconfig.hpp options

Fixes #387 
Closes #388
2021-08-07 09:54:18 -07:00
Arseny Kapoulkine
c624c7a8bd
Update CMakeLists.txt
Remove memory configuration options and rely on automatic detection of long long
2021-08-07 09:51:54 -07:00
Arseny Kapoulkine
8bd209fb8b docs: Update manual to be more explicit about save_file return
The function returns true on success and false on failure.
2021-07-09 17:27:01 -07:00
Arseny Kapoulkine
657619962f
Merge pull request #431 from justinkb/master
Fix include in test_document.cpp when building against libc++. The _GLIBCXX_HAVE_UNISTD_H relies on pugixml and its tests being built against libstdc++, with LLVM's libc++ this won't be defined
2021-06-30 14:28:44 -07:00
Paul Mulders
81274bb026 Fix include in test_document.cpp when building against libc++ 2021-06-30 23:07:54 +02:00
Arseny Kapoulkine
37eddaa0b2
Update .codecov.yml
Mark "project" check as information and disable "patch" check.
2021-06-30 13:11:45 -07:00
Björn Blissing
e7eae035ff Store definitions in variable to avoid duplication
Store compile definitions in variable to avoid duplicated generator
expressions.
2021-06-28 19:51:20 +02:00
Björn Blissing
52a7981b85 Make some compile definitions public
Moved needed defines to public section of target_compile_definitions.
2021-06-28 13:36:55 +02:00
Björn Blissing
92ac6ac1d9 Update github action to trigger defines via CMake
Use options via explicit CMake defines, instead of calling them from
the generic PUGI_BUILD_DEFINES variable.
2021-06-28 13:17:06 +02:00
Björn Blissing
50b103f127 Fix generator expressions 2021-06-28 13:17:06 +02:00
Björn Blissing
1cd65c7eb8 Move advanced memory settings into target defs.
Moved the advanced memory options into target_compile_definitions using
generator expressions.
2021-06-28 12:50:27 +02:00
Björn Blissing
f1946432ee Check for existence of long long 2021-06-28 12:50:27 +02:00
Björn Blissing
e2ba4f4014 Add options to build targets
Add custom options to the build targets via generator expressions.
2021-06-28 12:50:27 +02:00
Björn Blissing
5f49f2c657 Mark advanced options and removed redundant ones
Options marked as advanced are hidden by default in the CMake GUI.

The `PUGIXML_HEADER_ONLY` are redundant when during CMake builds, hence
removed.

The `PUGIXML_HAS_LONG_LONG` should be handled automatically and needs to
be rewritten, hence these options has been removed.
2021-06-28 12:50:27 +02:00
Björn Blissing
986b7ffd01 Add Cmake options for pugiconfig.hpp
Add Cmake options variables for each of the defines in pugiconfig.hpp.
2021-06-28 12:50:27 +02:00
Arseny Kapoulkine
06a516c73c
Merge pull request #428 from zeux/gha
Switch to GitHub Actions build from Travis CI
2021-06-27 20:08:57 -07:00
Arseny Kapoulkine
a6a63a1b50 gcov crashes on LLVM-produced coverage on Linux 2021-06-27 19:27:40 -07:00
Arseny Kapoulkine
5cff00e5ea Fix coverage build to include CXX define
Also it seems like we don't need to restrict coverage build to
Linux/clang?
2021-06-27 19:20:27 -07:00
Arseny Kapoulkine
0de580155d Don't run GHA workflow on push to branches
Also convert line endings to Unix.
2021-06-27 19:12:59 -07:00
Arseny Kapoulkine
e7b545b288 Remove custom job name for unix 2021-06-27 19:09:08 -07:00
Arseny Kapoulkine
3097a2c711 Switch to export and GH vars 2021-06-27 19:04:15 -07:00
Arseny Kapoulkine
8bd9a19a7e Change badge to GHA badge.
So long, Travis.
2021-06-27 19:01:06 -07:00
Arseny Kapoulkine
0b793a3126 Add GitHub Actions based build 2021-06-27 19:00:18 -07:00
Arseny Kapoulkine
7da44ddc5b
Merge pull request #399 from bjornblissing/feature/cmake_prefix
Add PUGIXML as prefix to CMake options
2021-06-22 14:32:00 -07:00
Björn Blissing
7b1b7ee16d Reverted to use of global BUILD_SHARED_LIBS option
This commit reverts back to exposing the global variable
BUILD_SHARED_LIBS.

Since building static libraries are the default for CMake
(i.e. BUILD_SHARED_LIBS=OFF) the option to build both static and shared
libraries were moved into a conditional option. So the option
PUGIXML_BUILD_SHARED_AND_STATIC is now only visible when the global
BUILD_SHARED_LIBS variable is set to ON.

The change also prevents the case were the user first enables
BUILD_SHARED_LIBS and then enables PUGIXML_BUILD_SHARED_AND_STATIC to
then again disable BUILD_SHARED_LIBS.
2021-06-19 12:51:27 +02:00
Björn Blissing
fc7928a4b7 Use target_compile_definitions for custom defines
Replace `add_definitions` with `target_compile_definitions` for
specified targets. Multiple options are separated using the
`separate_arguments` function, which converts any string using
space-separated arguments into a semicolon-separated list.
2021-06-19 11:22:31 +02:00
Björn Blissing
0f1e75a902 Re-introduced the custom build defines
The ability to use custom build defines were removed in commit:
1c5a0bb325

This commit will reintroduce this feature, but using a prefixed variable
name.
2021-06-15 09:00:31 +02:00
Björn Blissing
91fde92fc2 Add PUGIXML as prefix to CMake options
Added PUGIXML as prefix to all CMake options to avoid naming collisions
with downstream projects.

Removed the cached variable BUILD_DEFINES, since it was unused.
2021-06-15 08:42:30 +02:00
Arseny Kapoulkine
5c4225b5c9 tests: Fix wchar_t build 2021-05-11 23:22:13 -07:00
Arseny Kapoulkine
8cece4b9fe Fix a bug in move construction when move source is empty
Previously when copying the allocator state we would copy an incorrect
root pointer into the document's current state; while this had a minimal
impact on the allocation state due to the fact that any new allocation
would need to create a new page, this used a potentially stale field of
the moved document when setting up new pages, which could create issues
in future uses of the pages.

This change fixes the core problem and also removes the use of the
_root->allocator from allocate_page since it's not clear why we need it
there in the first place.
2021-05-11 22:53:54 -07:00
Arseny Kapoulkine
56c9afa7c8 XPath: Improve recursion limit for deep chains of //
Since foo//bar//baz adds two nodes for each //, we need to increment the
depth by 2 on each iteration to limit the AST correctly.

Fixes the stack overflow found by cluster-fuzz (I suspect the issue
there is a bit deeper, but this part is definitely a bug and as such I'd
rather wait for the next test case for now).
2021-05-11 22:27:53 -07:00
Arseny Kapoulkine
791971ee59
Merge pull request #422 from neheb/patch-1
fix cygwin compilation
2021-05-07 00:35:47 -07:00
Rosen Penev
e672b1c9f0
fix cygwin compilation 2021-05-06 23:25:29 -07:00
Arseny Kapoulkine
5df537f348
Merge pull request #419 from neheb/ranges
add empty method
2021-04-27 23:37:06 -07:00
Rosen Penev
c167259e60 add empty method
Simple and allows to avoid using std::distance.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-04-27 13:55:02 -07:00
Arseny Kapoulkine
5d58e94b6d
Merge pull request #418 from neheb/ranges
remove const from xml_node_iterator ++/--

Fixes #417.
2021-04-26 14:32:51 -07:00
Rosen Penev
ef257796db remove const from operator++/--
This prevents usage with C++20 ranges since it does not satisfy
std::weakly_incrementable.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-04-26 14:06:19 -07:00
Arseny Kapoulkine
08b3433180
Merge pull request #394 from zeux/cmake-yay
Don't define pugixml import target if it already exists
2020-12-22 08:41:08 -08:00
Arseny Kapoulkine
06868c8f57 Don't define pugixml import target if it already exists
This fixes duplicate target definition errors when find_package(pugixml)
is called twice in a build.

Fixes #393.
2020-12-22 08:15:11 -08:00
Arseny Kapoulkine
0e3f1699ff
Merge pull request #391 from zeux/cmake-omg
Fix compatibility issue with CMake 3.10
2020-12-18 09:52:06 -08:00
Arseny Kapoulkine
e2bc4f4af2 Fix compatibility issue with CMake 3.10
target_link_libraries/INTERFACE doesn't seem to work on CMake 3.10, but
directly setting the property does work.

Fixes #390.
2020-12-18 09:07:44 -08:00
Arseny Kapoulkine
907955280f
Merge pull request #389 from mathstuf/fix-alias-compat-target
cmake: avoid ALIAS target
2020-12-14 19:47:56 -08:00
Ben Boeckel
4feab60bb7 cmake: avoid ALIAS target
This is not allowed on IMPORTED targets.
2020-12-10 12:02:01 -05:00
Arseny Kapoulkine
5a0fd5d85f docs: Rebuild HTML documentation 2020-12-04 16:31:20 -08:00
Arseny Kapoulkine
68a92aa972
Merge pull request #384 from mathstuf/update-1.11-release-notes
Update 1.11 release notes
2020-12-04 15:59:40 -08:00
Ben Boeckel
d1d415e666 docs: add a note about the new imported target name for CMake 2020-12-02 17:17:21 -05:00
Ben Boeckel
5063e87499 cmake: provide a compatibility target for users
For users using older pugixml releases, add an ALIAS target which works
with the new versions too.
2020-12-02 17:16:47 -05:00
Arseny Kapoulkine
7a9da11d8b scripts: Convert archive.py to Python 3
The changes are mostly mechanically converting str to bytes.
2020-11-26 01:08:07 -08:00
Arseny Kapoulkine
a3ae05cc9f scripts: Remove deprecated iconUrl from NuGet package
The logo.svg link is dead anyway.
2020-11-26 01:01:57 -08:00
Arseny Kapoulkine
fe4bc946b2 Update copyright year to 2020 everywhere 2020-11-26 01:00:27 -08:00
Arseny Kapoulkine
632c042a35
Merge pull request #383 from zeux/next-release
Update version to 1.11 and update documentation
2020-11-25 14:37:35 -08:00
Arseny Kapoulkine
70bd6a6b0a Update version to 1.11 and update documentation 2020-11-25 10:18:42 -08:00
Arseny Kapoulkine
8afc1239a3 tests: Fix test fallout for MSVC6
One more XPath test falls prey to MSVC6 NaN comparison codegen issues.
2020-11-25 09:48:19 -08:00
Arseny Kapoulkine
5f97d5d66f Fix -Wshadow in remove_children()
child variable was shadowing xml_node::child
2020-11-25 09:28:26 -08:00
Arseny Kapoulkine
28aebf2b22
Merge pull request #382 from zeux/TheNicker-master
Fix MSVC deprecation warnings when using clang-cl
2020-11-25 09:19:24 -08:00
Arseny Kapoulkine
df42668e18 Cleanup code and feature detection
We now use open_file similarly to open_file_wide, and activate the
workaround for MSVC 2005+ since that's when the _s versions were added
in the first place.
2020-11-25 08:38:22 -08:00
Arseny Kapoulkine
30761e48df
Merge pull request #376 from jjmccollum/mingw-dll-fix
Added fix to pugixml_dll.rc so shared lib can be built with MinGW
2020-10-26 15:48:58 -07:00
James McCollum
24e454066d Added fix to pugixml_dll.rc so shared lib can be built with MinGW 2020-10-26 08:17:46 -04:00
Arseny Kapoulkine
c4bae8d818
Merge pull request #370 from zeux/xpath-rec
XPath: Fix stack overflow in functions with long argument lists
2020-09-11 13:06:44 -07:00
Arseny Kapoulkine
8e5b8e0f46 XPath: Fix stack overflow in functions with long argument lists
Function call arguments are stored in a list which is processed
recursively during optimize(). We now limit the depth of this construct
as well to make sure optimize() doesn't run out of stack space.
2020-09-11 09:50:41 -07:00
Arseny Kapoulkine
a3fad540a7
Merge pull request #369 from zeux/xpath-rec
XPath: Restrict AST depth to prevent stack overflow
2020-09-10 09:53:25 -07:00
Arseny Kapoulkine
20aef1cd4b Fix stack overflow in tests on MSVC x64
The default stack on MSVC/x64/debug is sufficient for 1692 nested
invocations only, whereas on clang/linux it's ~8K...

For now set the limit to be conservative.
2020-09-10 09:11:46 -07:00
Arseny Kapoulkine
c7090e6c33 Fix tests in wchar mode 2020-09-10 01:07:48 -07:00
Arseny Kapoulkine
1f84db837b XPath: Restrict AST depth to prevent stack overflow
XPath parser and execution engine isn't stackless; the depth of the
query controls the amount of C stack space required.

This change instruments places in the parser where the control flow can
recurse, requiring too much C stack space to produce an AST, or where a
stackless parse is used to produce arbitrarily deep AST which will
create issues for downstream processing.

As a result XPath parser should now be fuzz safe for malicious inputs.
2020-09-10 00:55:26 -07:00
Lior Lahav
c258fba6f1 Replaced fopen and _wfopen deprecated functions with the safer fopen_s and _wfopen_s 2020-07-21 22:37:16 +03:00
Arseny Kapoulkine
22401bafaf
Merge pull request #363 from c72578/2020-07-15_Fix_pkgconfig_lib_postfix
Fix debug postfix in pkgconfig file
2020-07-15 14:05:14 -07:00
Wolfgang Stöggl
8b074b171f Fix debug postfix in pkgconfig file
In case of USE_POSTFIX, the POSTFIX is dependent
on the CMAKE_BUILD_TYPE.
Use the correct POSTFIX also in the generated pugixml.pc file.

This results in the following contents of pugixml.pc:
- Release:
  Libs: -L${libdir} -lpugixml
- RelWithDebInfo
  Libs: -L${libdir} -lpugixml_r
- MinSizeRel:
  Libs: -L${libdir} -lpugixml_m
- Debug:
  Libs: -L${libdir} -lpugixml_d
2020-07-15 21:59:05 +02:00
Arseny Kapoulkine
d58115e581
Merge pull request #360 from julianxhokaxhiu/patch-1
[Cmake] Static build should not export APIs
2020-07-06 09:22:06 -07:00
Arseny Kapoulkine
45271c9c9c
Merge pull request #361 from zeux/ps-stderr
Fix PowerShell errors on stderr
2020-07-06 09:21:46 -07:00
Arseny Kapoulkine
f08768d9bf Fix PowerShell errors on stderr
PS invocation of code coverage upload gets triggered because of stderr
output from curl with progress report when uploading coverage.
2020-07-06 08:32:24 -07:00
Julian Xhokaxhiu
5fdc78b66b
[Cmake] Static build should not export APIs
Fixes #359
2020-07-06 10:22:21 +02:00
Arseny Kapoulkine
23ca940487 Work around a false positive in MSVC debug runtime checker
In some MSVC versions on x64 configurations, the hashing function
triggers this failure:

Run-Time Check Failure #1 - A cast to a smaller data type has caused a
loss of data.  If this was intentional, you should mask the source of
the cast with the appropriate bitmask.

This is similar to the integer sanitizer - this code is valid C++ but
MSVC decides to warn about this nonetheless. Masking the pointer's low
32 bits fixes the issue.

Fixes #357.
2020-06-13 08:41:22 -07:00
Arseny Kapoulkine
a196b9b7e9
Merge pull request #353 from jhasse/nullptr-in-header
Use nullptr in pugixml.hpp if available, see #91
2020-05-11 10:26:05 -07:00
Jan Niklas Hasse
c2d90c49f9 Use nullptr in pugixml.hpp if available, see #91 2020-05-10 17:28:30 +02:00
Arseny Kapoulkine
f49d7acdfb Clarify the document element behavior.
pugixml currently unconditionally accepts documents with multiple
top-level element nodes in absence of parse_fragment. This is an
unfortunate omission; while it can be corrected, it will result in
regressions for some users, and it's trivial to perform the validity
check after the parse is done.

Because of this, for now we're just going to amend documentation here to
both highlight this in the W3C Conformance section, but also to more
strongly push users into realizing that there's just a single document
element (normally).

We might decide to change the behavior here to prohibit such documents
by default in the future, but for now a documentation change seems like
a better tradeoff.

Fixes #337
2020-05-02 09:47:34 -07:00
Arseny Kapoulkine
285776354d
Merge pull request #349 from KyleFromKitware/cmake-improvements
Various CMake improvements
2020-05-02 09:36:58 -07:00
Kyle Edwards
d272f11073 Export targets from build directory
This will allow projects to use pugixml from its build directory
rather than having to install it.
2020-04-27 16:02:56 -04:00
Arseny Kapoulkine
ef9cafa9ce
Merge pull request #348 from rip-nsk/source_and_header-only_linkage_options
Add "Include pugixml.cpp" and "Header Only" linkage options
2020-04-27 11:15:15 -07:00
Kyle Edwards
184e6ed916 Use COMPONENT arguments in install() commands 2020-04-27 13:47:58 -04:00
Kyle Edwards
8c74d8b198 Fix multiple-rules-for-target error
The old logic for BUILD_SHARED_LIBS and BUILD_SHARED_AND_STATIC_LIBS
would produce two targets with the same name and different build
rules. The Makefile generator tolerated this, but the Ninja generator
raised an error. Fix the logic so that only one shared and one static
target gets built, and make the pugixml target an ALIAS of the one
dictated by BUILD_SHARED_LIBS.
2020-04-27 13:47:58 -04:00
rip.nsk
ab86960e48 Add "Include pugixml.cpp" and "Header Only" linkage options 2020-04-24 17:56:46 -07:00
Arseny Kapoulkine
5e64076af9 Adjust node_copy_tree to be more explicit about invariants
The loop traverses the source tree and simultaneously builds up a copy
of it at destination. Short of race conditions, this code is safe -
however, it's not obvious that dit stays inside the destination tree.

This change adds a few assertions to help enforce/document these
invariants. One particular subtlety is that dit can actually *become*
null after we exit out of the loop, but it's guaranteed to only do so
once sit goes back to sn.

This is only possible when doing a full document copy - for some reason
we weren't using this for that (in reset(xml_document)), but we are now.

Fixes #314.
2020-02-19 21:02:33 -08:00
Arseny Kapoulkine
76c3914484 XPath: Remove the use of fallthrough switch cases
We were previously relying on non-standard comment detection that is
supported by gcc/clang to avoid warnings about implicit fallthrough.

This can be solved using attributes but using them requires a lot of
compiler-specific detection logic because not all versions of gcc/clang
support them.

We don't *really* need to rely on fallthrough here - the type conversion
block can be located *after* the AST type switch instead, which means
that any AST type that has type ambiguity can fall back to that in the
future.

Fixes #331.
2020-02-19 07:50:59 -08:00
Arseny Kapoulkine
6fbe927575
Merge pull request #330 from LocutusOfBorg/patch-2
Update CMakeLists.txt to rename the static and shared libraries to pugixml
2020-02-07 23:08:22 -08:00
Gianfranco Costamagna
2c24e90c23
Update CMakeLists.txt to rename the static and shared libraries to pugixml
Don't call them pugixml-shared or pugixml-static, because this breaks pkgconfig calls and userspace tools.
2020-02-07 14:55:25 +01:00
Arseny Kapoulkine
546cafefa3 XPath: Add a clarification comment for ast_variable fallthrough 2020-02-01 07:48:45 -08:00
Arseny Kapoulkine
85a39b955d tests: Add a dedicated test for XPath variable conversion
This makes sure all conversions work as expected (note that no type can
be converted to node set so we don't check that).
2020-02-01 07:44:14 -08:00
Arseny Kapoulkine
41b6ff21c4
Merge pull request #316 from BotellaA/patch-1
Add POSITION_INDEPENDENT_CODE option
2019-12-20 08:13:28 -08:00
Arnaud Botella
aa2e0909ac
Add POSITION_INDEPENDENT_CODE option
Allow to use the static library in other dynamic librairies. This is a standard cmake option https://cmake.org/cmake/help/v3.11/prop_tgt/POSITION_INDEPENDENT_CODE.html#prop_tgt:POSITION_INDEPENDENT_CODE
2019-12-06 17:25:37 +01:00
Arseny Kapoulkine
53a30c6571 Cleanup first_element_by_path
Instead of performing a late null check that is redundant and only
needed to silence clang static analysis warning, we pick the context as
a root / self node. This way the code is a bit less redundant and the
static analyzer is happy.
2019-12-03 21:23:15 -08:00
Arseny Kapoulkine
2e8631d2eb
Merge pull request #313 from valeriyvan/nulldereference
Fixing possible null pointer dereference
2019-12-03 21:17:28 -08:00
Valeriy Van
cda8623468 Fixing possible null pointer dereference 2019-12-02 15:02:54 +01:00
Arseny Kapoulkine
51d177e938
Merge pull request #310 from amlucas/master
explicit casts for -Wconversions warnings in gcc
2019-11-27 17:50:21 +01:00
Lucas Amoudruz
78e98c446d explicit casts for -Wconversions warnings in gcc 2019-11-27 15:56:05 +01:00
Arseny Kapoulkine
fe5460c6dc
Merge pull request #305 from slurps-mad-rips/modern-cmake
Fix incorrect installation location for exported CMake targets
2019-10-17 22:07:54 -07:00
Isabella Muerte
99ad261611 🐛 Fix incorrect installation location for exported CMake targets 2019-10-17 21:44:48 -07:00
Arseny Kapoulkine
40be014e48
Merge pull request #303 from slurps-mad-rips/modern-cmake
Fix install locations for pkgconfig *and* cmake
2019-10-06 15:45:55 -07:00
Isabella Muerte
6949232bbd 🐛 Fix install locations for pkgconfig *and* cmake 2019-10-06 13:08:01 -07:00
Arseny Kapoulkine
fdd618f13a
Merge pull request #302 from slurps-mad-rips/modern-cmake
Modernize CMake
2019-10-06 12:44:43 -07:00
Isabella Muerte
3df5036344 🔥 Remove commented out CMake code 2019-10-06 12:33:03 -07:00
Isabella Muerte
ad93a373ab Adjust MSVC runtime settings as requested.
The block of code can be removed in the future if CMake 3.15 ever
becomes the minimum
2019-10-01 10:20:30 -07:00
Isabella Muerte
8a0aac18ea Update check command to output text on failure
Move pugixml-config.cmake.in to scripts/ to prevent polluting the root
2019-09-30 22:00:04 -07:00
Isabella Muerte
1c5a0bb325 Update CMake to modern approach
New Features:

pugixml-shared and pugixml-static are "always" available, but not always
built. This allows downstream projects to still use them, and to make
sure our configurations are correct regardless of if they are being
built. They are not always installed however.

pugixml-shared and pugixml-static have ALIAS libraries of
pugixml::shared and pugixml::static respectively. These names are also
respected in the `find_package(pugixml CONFIG)` generated files, so its
safe to use pugixml in a CMake project regardless of whether it is
installed locally, or if its a subproject via `add_subdirectory`.

pugixml will automatically select the correct library type based on
BUILD_SHARED_LIBS. A pugixml::pugixml ALIAS is also available.

CMAKE_MSVC_RUNTIME_LIBRARY from CMake 3.15 has been backported.

CMake will now rely on generator expressions (a powerful abstraction in
large projects with many subdirectories) for most work. This offloads
work from the single-threaded configure stage to the multithreaded
generation stage.

pugixml now uses CTest as the runner.

Some settings are automatically disabled if pugixml is used as a
subdirectory. These are still able to be manually set, but are hidden
from folks who choose to use CMake GUI.
2019-09-28 13:02:55 -07:00
Isabella Muerte
195dfe1d8d 🚧 Begin moving pugixml to modern(ish) CMake
⬆️ Bump CMake minimum to 3.4
🐛 pugixml no longer requires a C compiler to be found or set to
compile correctly. This speeds up configuration and building on windows.
🚧 Begin laying groundwork to backport MSVC_RUNTIME_LIBRARY
property
2019-09-28 10:47:15 -07:00
Tuan Anh Tran
b9b2aeecaf Custom precision (#300)
Fixes #285
2019-09-22 08:42:41 -07:00
Arseny Kapoulkine
6934b123d4 Move pugixml.rc to scripts/
This keeps src/ folder clean of auxiliary files only required for
special builds; note that CMakeLists.txt already depends on scripts/
(specifically for pkgconfig setup).
2019-09-21 09:21:13 -07:00
lady mesh
6fb765ca9d Add: Windows DLL version info header (#298)
Closes #294
2019-09-19 07:27:40 -07:00
Arseny Kapoulkine
6202519ca6 tests: Add memory safety tests for remove_children/attributes
The newly added tests make sure that during node/attribute destruction
we deallocate a few memory pages; this makes sure that we don't read
node data after it's being destroyed.

Also clean up formatting/style in the remove_* implementation a bit.
2019-09-17 20:34:40 -07:00
Tuan Anh Tran
fd7326fb91 feat: add remove_attributes() and remove_children() (#296)
These functions remove all attributes / child nodes in bulk which is faster than removing them one at a time.
2019-09-17 20:18:41 -07:00
Wolfgang Stöggl
ccb63a9186 Add LICENSE.md to RELEASE (#295) 2019-09-16 14:21:48 -07:00
Arseny Kapoulkine
5329ba03b5 scripts: Update NuGet package spec
Migrate from licenseUrl to license since licenseUrl is deprecated and
fix grammar for VS version list.
2019-09-15 17:56:15 -07:00
Arseny Kapoulkine
3c59df555b docs: Update documentation for 1.10 release
Update changelog and regenerate HTML documentation.
2019-09-11 21:51:02 -07:00
Arseny Kapoulkine
c6607740a0 Never escape > in attribute values
According to XML spec, > sometimes needs to be escaped in PCDATA (when
it occurs as a ]]> pattern), but it doesn't need to be escaped in
attribute values.

Contributes to #272.
2019-09-11 21:35:03 -07:00
Arseny Kapoulkine
946de603b1 Don't escape attribute quotation symbol
When using double quotes for attributes, we don't need to escape '; when
using single quotes, we don't need to escape ".

This changes behavior to match 1.9 by default (where we don't escape ').

Contributes to #272.
2019-09-11 21:27:20 -07:00
Arseny Kapoulkine
44e4d7e40b Update version to 1.10
Note: this chang also updates PUGIXML_VERSION macro to allow for
double-digit minor versions; this preserves the continuity of versions
so PUGIXML_VERSION >= 190 will still work.
2019-09-11 21:09:50 -07:00
Joel Andres Granados
84e322738b Update nuget creation to VS2019 (#291)
Create visual studio projects that are vs2019 compliant.
* nuget_build.ps1 :
Introduce a new argument that will define how we implement the nuget
build. For now we accept 201{9,7.5.3} as possible argument values.

* pugixml_vs2019{,_static}.vcxproj :
Add two visual studio projects that build pugi with the latest SDK and
build tools

* appveyor.yml
- Add Visual Studio 2019 to build targets
- Add Visual Studio 201{9,3,5} to build_scripts. And call
  nuget_build.ps1 with a new argument.
- Add Visual Studio 2019 to the test_scripts.
2019-09-09 07:37:29 -07:00
Wolfgang Stöggl
fdf0295753 Fix minor typos (#286)
- Typos were found by codespell v1.15.0
2019-08-21 07:46:11 -07:00
Arseny Kapoulkine
a556845555 tests: Work around test warnings in clang-7
Self-assignment generates a Wself-assign-overloaded warning.
2019-08-21 07:45:27 -07:00
Matan Nassau
4f6e7454fd fix cmake option USE_POSTFIX (#283)
appending the suffix to the build product need not be a function of
whether CMAKE_CONFIGURATION_TYPES is set.  for example, having two ninja
build trees---one for debug and another for release---is a fine use-case
for USE_POSTFIX.
2019-08-04 13:15:10 -07:00
Artur Leonov
c5752917c7 fix running tests (#280) 2019-07-25 19:14:39 -07:00
m-naumann
5a867cb1e3 Add support for using single quotes to enclose attribute values
This change adds format_attribute_single_quote flag that uses single quotes (`'`) instead of double quotes (`"`) for formatting attribute values.

Internal quotation marks are escaped using `&quot;` and `&apos;`.
2019-06-18 19:51:10 -07:00
Arseny Kapoulkine
fcb7c8d3e5
Merge pull request #276 from denchat/patch-1
std::random_shuffle is removed in current standard
2019-06-09 11:55:36 -07:00
denchat
86e0fe1980
Fix forgotten indentation 2019-06-10 00:35:17 +07:00
denchat
1312a46d91
std::random_shuffle is removed in current standard
use <random> 's generator and std::shuffle instead
2019-06-10 00:14:21 +07:00
Arseny Kapoulkine
7247a823b7 XPath: Add missing inline/PUGI__FN specifiers
Also split one-liner if/for loops for better readability and coverage.
2019-03-17 07:14:11 -07:00
Arseny Kapoulkine
cdd5d92f26
Merge pull request #265 from zeux/nocontrib
Remove contrib folder
2019-03-16 18:26:28 -07:00
Arseny Kapoulkine
29f3177d10 Remove contrib from Makefile and readme.txt 2019-03-13 23:17:23 -07:00
Arseny Kapoulkine
434c4a4d41 Remove contrib folder
This change removes contrib folder since it doesn't seem very useful;
Natvis scripts can and should go to scripts/ along with project files.

foreach.hpp is supporting a severely outdated BOOST_FOREACH construct;
in C++11 ranged for loop can be used with xml_node::children/attributes,
and BOOST_FOREACH can work with these as well.

foreach.hpp was also accidentally licensed as public domain which isn't
very helpful when the actual library is MIT. We could fix the license
but it seems better to just remove it.

Fixes #264.
2019-03-13 21:30:10 -07:00
Arseny Kapoulkine
8bf806c035 tests: Move control char tests to test_write.cpp
Also fix code style.
2019-03-09 06:58:07 -08:00
Arseny Kapoulkine
b01569918a docs: Regenerate HTML documentation
Includes wording fixes and format_skip_control_chars
2019-03-09 06:55:55 -08:00
Arseny Kapoulkine
b9a0d7ff23
Merge pull request #263 from Yanpas/fix_char_esc
format_skip_control_chars
2019-03-09 06:54:48 -08:00
Yan Pas
138976fd95 unit test and doc 2019-03-08 19:17:19 +03:00
Yan Pashkovsky
66e1b4e03e format_skip_control_chars 2019-03-07 17:54:30 +03:00
WheretIB
36e274d949 Visual Studio Natvis visualization for compact mode 2019-02-28 04:29:56 -08:00
Arseny Kapoulkine
12e8b699ce tests: Expand out-of-memory union tests
We now have two tests: one tests behavior when we run out of space when
appending the node set (in which case the append fails), another one
tests behavior when we run out of space when filtering the node set (in
which case the set still contains redundant data).
2019-02-26 23:57:58 -08:00
Arseny Kapoulkine
c55ea3bc1e XPath: Make remove_duplicates generate stable order
Given an unsorted sequence, remove_duplicates would sort it using the
pointer value of attributes/nodes and then remove consecutive
duplicates.

This was problematic because it meant that the result of XPath queries
was dependent on the memory allocation pattern. While it's technically
incorrect to rely on the order, this results in easy to miss bugs.

This is particularly common when XPath queries use union operators -
although we also will call remove_duplicates in other cases.

This change reworks the code to use a hash set instead, using the same
hash function we use for compact storage. To make sure it performs well,
we allocate enough buckets for count * 1.5 (assuming all elements are
unique); since each bucket is a single pointer unlike xpath_node which
is two pointers, we need somewhere between size * 0.75 and size * 1.5
temporary storage.

The resulting filtering is stable - we remove elements that we have seen
before but we don't change the order - and is actually significantly
faster than sorting was.

With a large union operation, before this change it took ~56 ms per 100
query invocations to remove duplicates, and after this change it takes
~20ms.

Fixes #254.
2019-02-26 23:57:58 -08:00
Arseny Kapoulkine
930a701f1f tests: Disable flaky test
This test is very sensitive to the particular implementation of union
aggregation; for now lets disable this.

We need a more robust way to test union allocation failures.
2019-02-26 22:15:34 -08:00
Arseny Kapoulkine
93c7bacb29 XPath: Create set for a|b in order before duplicate filtering
This does not change the result of a union operation [substantially], but
it means that we now give a list to remove_duplicates that has more natural
ordering.

If remove_duplicates didn't sort the array, we'd have union operations
resulting in a consistent predictable order.

Contributes to #254.
2019-02-26 21:39:52 -08:00
Arseny Kapoulkine
d902709da2 Refactor CMakeLists.txt support for multiple targets
We now have a ${LIBRARY} variable that we can either use directly or in
a foreach loop to be able to process either pugixml or pugixml-static
and pugixml-shared targets.

Also fixes incorrect shared library assignment when
BUILD_SHARED_AND_STATIC_LIBS is defined, and only links the static
library in for make check.
2019-02-06 08:15:27 -08:00
basti171
1d59e4d9d8 make pugixml build static and shared via cmake (#257) 2019-02-06 07:39:23 -08:00
Arseny Kapoulkine
160c1c23d9
docs: Improve null node comparison wording
Change confusing wording: null nodes compare as equal to null handles, the previous wording implied that each null handle is unique
2019-01-25 16:42:25 -08:00
Arseny Kapoulkine
b67ef29c08 docs: Draw attention to the fact that you have to compile pugixml.cpp
This may or may not make it more clear that pugixml.cpp has to be
compiled - either as one of the projects or as a standalone project via
CMake et al - for it to work by default.

Fixes #256.
2019-01-19 18:25:25 -08:00
Arseny Kapoulkine
9fcae40bb5 Happy New Year! 2019-01-01 23:05:04 +03:00
Millian Poquet
b3db08ffcc pkg-config: Use CMake GnuInstallDirs FULL vars
Fixes an installation problem in Nix packages, as non-FULL variables are
already absolute paths in this case.
2018-12-10 11:12:36 -08:00
Arseny Kapoulkine
ba84465d2e Move unreachable line handling to Makefile
This allows us to reuse this code for MinGW builds.

Additionally disable coverage step for Linux clang - it looks like
Travis has a mismatch in the version of gcov info between clang and gcov
which causes gcov to crash - somehow this crash isn't picked up as a
build error.
2018-12-10 11:12:13 -08:00
Arseny Kapoulkine
2da1524977 Add PUGIXML_WCHAR_MODE configuration to MinGW tests
We are currently only testing UTF8 mode which means we don't have code
coverage for some UTF->UTF decoding paths.
2018-12-09 17:20:02 -08:00
Arseny Kapoulkine
7d0d8ee79f Update .travis.yml
This is a dummy commit to trigger codecov build
2018-12-09 16:31:22 -08:00
Arseny Kapoulkine
4b57d09882 Add support for MinGW builds on AppVeyor
Use cygwin to build coverage build and upload coverage data to codecov.
2018-12-09 16:16:59 -08:00
Arseny Kapoulkine
7664bbf9af tests: Only use load_file_special_folder test on macOS
The behavior on Linux is very different between kernel versions, and it
triggers an unexpected OOM during sanitizer runs because somehow the
size is reported to be LONG_MAX. It's not clear that it helps us cover
any paths we don't cover otherwise - it would be nice to be able to test
failing to load a multi-gigabyte file on a 32-bit system, but we can't
do this easily atm anyway.
2018-11-27 08:07:31 -08:00
Arseny Kapoulkine
1a9c3f66db Enable config=sanitize in Travis CI
This commit changes sanitize configuration to fail on the first error
and ignore floating-point division and overflow "errors" that trigger
when we test the corresponding functionality. This makes it possible to
run this on all commits - if new UB or memory safety issues are introduced,
asan/ubsan will catch them.
2018-11-27 08:07:31 -08:00
Arseny Kapoulkine
f9a2a7d19e Fix Wdouble-promotion warnings
We had a few places in test code and library source where we used an
implicit float->double cast; while it should preserve the value exactly,
gcc/clang implement this warning to make sure uses of double are intentional.

This change also adds the warning to Makefile to make sure we don't
regress on this warning.

Fixes #243.
2018-11-23 23:39:22 -08:00
Arseny Kapoulkine
aac75cd299 Escape TAB character in attribute values with &#09;
This change modifies the table entries for ctx_special_attr to treat TAB
character as special, which makes the output code escape it.

Before this change, trying to use TAB in an attribute value would output
it verbatim; during subsequent parsing, pugixml - and other compliant
parsers - would apply attribute-value normalization, turning the TAB
into a space and losing the original value.

Using &#09; fixes this; if an input document has &#09; in an attribute
value, that gets unescaped into \t during parsing and escaped back into
&#09; during output, which means we can now roundtrip values like this.

Fixes #242.
2018-11-19 22:26:21 -08:00
cecilios
7d2436ec2f Add coverity annotations 2018-11-16 15:25:12 -08:00
Arseny Kapoulkine
fa686f004a Update all URLs to pugixml.org to https:// 2018-11-12 12:28:54 -08:00
Wolfgang Stöggl
d3dd79d54d Update URL to https in pugixml.pc.in 2018-11-12 07:49:54 -08:00
Arseny Kapoulkine
d9fadc7464 XPath: Workaround Coverity false positive
Coverity hits a similar false positive to what clang static analyzer hit
- it assumes that since optimize() checks _right for being nullptr,
optimize_self() might hit _right=nullptr in the ast_op_equal case which
is impossible.

Contributes to #236.
2018-10-23 21:40:18 -07:00
Dan Lipsa
273fa0ab26 Remove warning in Visual Studio (#235)
The following warning is removed:
Visual Studio 14.0
1. warning C4275: non dll-interface class 'std::exception' used as
   base for dll-interface class 'vtkpugixml::xpath_exception'
2018-10-16 08:43:32 -07:00
Arseny Kapoulkine
81c82588bd Work around clang --analyze warnings
clang doesn't understand the invariants guaranteed for specific AST node
types and, when seeing null pointer checks in optimize(), assumes any
pointers in the node might be null. Work around this by adding explicit
- redundant - null pointer checks.
2018-09-24 20:38:09 -07:00
Arseny Kapoulkine
e3b5e9ce3c XPath: Refactor xpath_node_set short buffer optimization
This change replaces xpath_node_set single element storage with a
single-element array in hopes that this would silence Coverity false
positive about getting a singleton pointer.

Additionally, it refactors _assign member to unify small and large
buffer codepaths since they are basically identical.

Fixes #233 (hopefully)
2018-09-24 20:19:31 -07:00
Arseny Kapoulkine
1a96777b11 tests: Fix XPath denorm tests on Intel compiler
Intel compiler by default sets flush-to-zero flags which causes our
denorm test to produce 0.0. So make sure that denorms work on FPU before
testing the string output.

Fixes #218.
2018-08-13 22:06:57 -07:00
Arseny Kapoulkine
cb4a74d5e5 Minor CMakeLists.txt cleanup
Instead of hardcoding SOVERSION, use CMake variables to set it up.

Closes #220.
2018-08-13 21:38:44 -07:00
Vyacheslav Egorov
c51214f21e Visual Studio Natvis visualization (#227)
* Visual Studio Natvis visualization

* Changed string format to remove separate natvis file for wide character mode

* Display any node type with name and value if any of them are available
2018-08-07 17:03:37 -07:00
Arseny Kapoulkine
6b9c07e6ed tests: Allow document_load_file_special_folder to load empty document
On some Debian systems it looks like we *can* open the current folder as
a file and read its contents, but parsing the result produces an empty
document. We now handle this case as well.

Fixes #225.
2018-07-30 07:32:09 -07:00
Arseny Kapoulkine
514478d1f8 Fix version comment; 190 = 1.9.0 (major.minor.patch)
Fixes #224.
2018-07-28 08:08:45 -07:00
Arseny Kapoulkine
f3139f4c04 Add .gitattributes file
This makes sure the contents of tests/data/ folder does not go through
newline conversion, which breaks tests that rely on some files having LF
and some files having CR+LF.

Fixes #222.
2018-07-23 23:13:02 -07:00
Arseny Kapoulkine
699143c5d4 scripts: Set file permissions when building .zip archive
It looks like zipfile module by default uses the permission mask 0,
which after unpacking on Unix-based systems leads to the files being
inaccessible.

We now explicitly set file mask to rw-r--r-- to match .tar.gz defaults.

Fixes #217.
2018-07-22 18:57:10 -07:00
Wolfgang Stöggl
c12889f7cc Use CMAKE_INSTALL_LIBDIR for pugixml.pc (#215)
- Up to now, the libdir was hardcoded to "lib" inside pugixml.pc and
  the install directory of pugixml.pc was "lib/pkgconfig"
- Adds support for lib and lib64 by using CMAKE_INSTALL_LIBDIR variable
2018-06-26 15:53:42 -07:00
Bernd Amend
12139f587b fix cmake warning "Policy CMP0048 is not set" (#214)
This also bumps the minimum CMake version to 3.0 (from 2.8.12).
2018-06-20 07:55:14 -07:00
Arseny Kapoulkine
e584ea337e docs: Mention that node is a container of children in ranged for section
This is implicitly true due to the following section, but that was
written before C++11 so this does deserve a special mention in ranged
for section as well.

Fixes #210.
2018-05-17 08:04:47 -07:00
Arseny Kapoulkine
51322cffa1 Move CMake build postfix setup behind an off-by-default USE_POSTFIX
This setup can interfere with existing workflows in two ways:

- If the target application used CMake and configured custom postfixes,
this change would override them

- If the target application did *not* use CMake, it'd have to abide by
these conventions even if the target configuration used is unexpected -
for example, the default "preferred" configuration is frequently
RelWithDebugInfo, not Release, which now has a postfix.

Fixes #198.
2018-04-27 08:13:08 -07:00
Arseny Kapoulkine
c53fdab93a Clarify comment in get_strconv_pcdata as well 2018-04-14 23:45:23 -07:00
Arseny Kapoulkine
43b0a6a0a3 Clarify comment in get_strconv_attribute
This might have helped a bit with confusion in #195.
2018-04-14 23:27:59 -07:00
Arseny Kapoulkine
24a7064e57
Update README.md
Add example code
2018-04-12 10:07:26 -07:00
Arseny Kapoulkine
e6dde9cf69 scripts: Use LICENSE file in pugixml.podspec
We no longer need to specify the license boilerplate verbatim since we
have a separate file.
2018-04-12 07:09:14 -07:00
Alexander Straub
4c791586ee Suffixes for different build types (#191) 2018-04-11 08:13:50 -07:00
Arseny Kapoulkine
552773269e Add brief license information back to README.md
Also rename LICENSE to LICENSE.md
2018-04-11 08:12:34 -07:00
Bruno Pagani
61f2180d0f Split LICENSE to a separate file for easier distribution
Also fix two http → https occurrences.
2018-04-11 08:12:34 -07:00
Eli Schwartz
daeb8013b2 cmake: always install the pkg-config file (#193)
There's really never a reason to *not* want this installed. If an option
is needed to specify installing in a versioned subdirectory, this option
should be explicitly described rather than hidden in something else.

As an added bonus, this makes the CMake install code slightly *less*
complicated.
2018-04-09 10:48:53 -07:00
Arseny Kapoulkine
341cea5a32 docs: Fix changelog formatting 2018-04-04 08:26:21 -07:00
Arseny Kapoulkine
8436f2a69b tests: Fix PUGIXML_COMPACT build on some platforms
We need bad_alloc that lives in <new>, not <exception>.
2018-04-04 07:53:16 -07:00
Arseny Kapoulkine
474a4a3f73 tests: Fix PUGIXML_NO_XPATH,PUGIXML_COMPACT build
pugixml.hpp wasn't including the <exception> header in this build but
test code needed it.
2018-04-03 21:56:09 -07:00
Arseny Kapoulkine
5f4afe3bd2 tests: Fix PUGIXML_NO_XPATH build 2018-04-03 21:51:41 -07:00
Arseny Kapoulkine
62728d9c2e tests: Fix PUGIXML_NO_EXCEPTIONS tests 2018-04-02 21:51:04 -07:00
Arseny Kapoulkine
be260a09c1 docs: Regenerate HTML documentation 2018-04-02 21:46:57 -07:00
Arseny Kapoulkine
0c74e117b8 Update version to 1.9 2018-04-02 21:46:14 -07:00
Arseny Kapoulkine
a32585286a tests: Fix PUGIXML_NO_STL build 2018-04-02 21:33:03 -07:00
Arseny Kapoulkine
cff1933ec9 docs: Update changelog 2018-04-02 21:07:58 -07:00
Arseny Kapoulkine
4f9af79850 Work around gcc-8 warning
gcc-8 produces "attribute directive ignored" warning for
no_sanitize("unsigned-integer-overflow"); at some point gcc will
introduce integer sanitizer support and we'll have to do this all over
again but for now just don't emit the attribute.
2018-04-02 21:06:32 -07:00
Arseny Kapoulkine
cb0e8937da docs: Update v1.9 release date to 04.04 2018-04-02 19:15:23 -07:00
Arseny Kapoulkine
951f1ed4ed Add a comment to clarify subtle branch in node_copy_tree 2018-03-29 08:27:56 -07:00
Arseny Kapoulkine
cec32da2b5 docs: Update changelog
Mention ubsan fixes; these fixes probably fix compact mode on some
64-bit architecture where unaligned pointer reads aren't valid as well
but it's probably not very relevant...
2018-03-16 21:34:56 -07:00
Arseny Kapoulkine
fe7b837868 tests: Fix PUGIXML_COMPACT+PUGIXML_WCHAR_MODE tests
Several tests got the buffer size wrong when sizeof(char_t)>1, and one
test didn't meet the carefully tuned allocation criteria under compact
mode due to the hash table usage and had to be changed a bit.
2018-03-16 21:33:26 -07:00
Arseny Kapoulkine
e50672cf37 ubsan: Fix undefined behavior for signed left shift in compact mode
We were using << compact_alignment_log2 instead of * compact_alignment
for symmetry with the encoding where >> is crucial to keep code fast and
round to negative infinity.

For decoding, the results are the same and any reasonable compiler
should convert *4 into <<2 so just use a multiplication - that doesn't
trigger UB on negative numbers.
2018-03-16 21:25:12 -07:00
Arseny Kapoulkine
9540016f6d ubsan: Fix type mismatch for xml_extra_buffer in compact mode
We were using allocate_memory to allocate struct xml_extra_buffer that
contains pointers; with compact mode, this allocation can be misaligned
by 4b with 8b pointers; fix this by manually realigning the pointer.
2018-03-15 23:10:10 -07:00
Arseny Kapoulkine
15fdb838c7 ubsan: Fix type mismatch in compact mode for document data
We were misaligning document data on 64-bit platforms by placing 8b
pointers at 4b offsets; fix this by reserving a full pointer worth of
bytes for page marker.
2018-03-15 23:09:35 -07:00
Arseny Kapoulkine
951c8f15d2 Refactor noexcept macros
Define noexcept using _MSC_VER instead of _MSC_FULL_VER (first release
of MSVC 2015 should have it), remove redundant PUGIXML_HAS_NOEXCEPT and
define PUGIXML_NOEXCEPT_IF_NOT_COMPACT in terms of PUGIXML_NOEXCEPT.
2018-03-15 22:31:13 -07:00
Arseny Kapoulkine
655bc825a1 docs: Add preliminary 1.9 changelog
Still trying to decide if the next version should be 1.9 or 1.8x and
what other changes need to go in.
2018-03-12 19:00:31 -07:00
Matthäus Brandl
9187e6500c Adds noexcept specifiers to the move special members of xml_document,… (#185)
* Adds noexcept specifiers to the move special members of xml_document, but only #ifndef PUGIXML_COMPACT
2018-03-03 10:19:37 -08:00
Matthäus Brandl
8284dbf61d Add noexcept specifiers to move special members where possible (#183)
* Adds a macro definition to be able to use noexcept with supporting compilers

* Adds noexcept specifier to move special members of xpath_node_set, xpath_variable_set and xpath_query, but not of xml_document as it has a throwing implementation
2018-03-01 20:13:43 -08:00
Arseny Kapoulkine
41219a5a20
Merge pull request #184 from brandl-muc/override_for_msvc
Enables usage of override specifier for MSVC compilers
2018-02-27 14:22:52 -08:00
Brandl, Matthäus (MBR)
b8d1d07ad8 Enables usage of override specifier for MSVC compilers (beginning with 17.0 which is the compiler of Visual Studio 2012) 2018-02-27 22:27:15 +01:00
Arseny Kapoulkine
b127cfb18e Fix Texas Instruments compiler warning
Texas Instruments compiler produces this warning for unused template
member functions:

	"pugixml.cpp", line 253: warning #179-D: function
	"pugi::impl::<unnamed>::auto_deleter<T>::release [with
	T=pugi::impl::<unnamed>::xml_stream_chunk<char>]" was declared but
	never referenced

As far as I can tell, this is a compiler issue - these functions should
not be instantiated in the first place; while it's possible to rework
the code to work around this, the changes would be fragile. It seems
best to just disable this warning - we've seen something similar on SNC
(which appears to use the same frontend!..).

Fixes #182.
2018-02-27 08:49:16 -08:00
Arseny Kapoulkine
2ec3579f29 Work around gcc issues with limits.h not defining LLONG_MIN
It looks like there are several cases where this might happen:

- In some MinGW distributions, the LLONG_MIN/etc defines are guarded
with:

	#if !defined(__STRICT_ANSI__) && defined(__GNUC__)

Which means that you don't get them in strict ANSI mode. The previous
workaround was specifically targeted towards this.

- In some GCC distributions (notably GCC 6.3.0 in some configurations),
LLONG_MIN/etc. defines are guarded with:

	#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)

But __STDC_VERSION__ isn't defined as C99 even if you use -std=c++14 -
which is probably technically valid, but not useful.

To work around this, redefine the symbols whenever we are building with
GCC and we need them and they aren't defined - doing this is better than
not building. Instead of hard-coding the constants, use GCC-specific
__LONG_LONG_MAX__ to compute them.

Fixes #181.
2018-02-22 08:15:53 -08:00
Arseny Kapoulkine
9bb468b3a9
Merge pull request #179 from mathstuf/cmake-touchups
Cmake touchups
2018-01-29 11:11:23 -08:00
Ben Boeckel
7fcfb72dcd cmake: keep sources and headers separate 2018-01-29 13:50:31 -05:00
Ben Boeckel
0df7adb680 cmake: set the minimum version before the project call 2018-01-29 13:50:30 -05:00
Arseny Kapoulkine
195494186e build: Add clang/Linux builds to Travis 2018-01-23 07:58:21 -08:00
Arseny Kapoulkine
3f28a5d97a Update all copyright notices to specify year 2018 2018-01-07 20:28:42 -08:00
Arseny Kapoulkine
f360842d48 docs: Fix a typo in dom_tree.png
<mesh> node attribute name is "name", not "mesh".
2017-12-29 17:03:54 -08:00
Arseny Kapoulkine
c2266d7a60
Merge pull request #177 from zeux/osx-fix
tests: Fix OSX test failure
2017-12-22 12:24:44 -08:00
Arseny Kapoulkine
a55f575a03 tests: Fix OSX test failure
Apparently at some point OSX behavior when reading /dev/tty switched
from "can't open the file" to "the file can be opened and 0 bytes can be
read from it" which generates a wrong error and doesn't exercise the
code path we care about.
2017-12-22 11:30:15 -08:00
Arseny Kapoulkine
cb7b78b039 docs: Fixed quickstart links
Fixes #176.
2017-12-22 10:40:42 -08:00
Arseny Kapoulkine
257fbb4e1b Use raw pointers in xml_node::traverse implementation
This makes it a bit faster and matches other internal code better.
2017-11-13 19:29:42 -08:00
Arseny Kapoulkine
344c74a74c XPath: Always allocate xpath_strings on temporary stack for concat
The static_buffer optimization seems to come from the time where the
on-heap buffer was allocated using global memory operations. At this
point the temporary buffer and temporary string storage all come from
the evaluation stack (that can be partially allocated on heap...), so
the extra logic isn't relevant for performance.
2017-11-13 19:10:36 -08:00
Arseny Kapoulkine
7c6d0010b3
Merge pull request #170 from zeux/move
This change implements move ctor and assign support for xml_document.

All node handles remain valid after the move and point to the new document; the only exception is the document node itself (that remains unmoved).

Move is O(document size) in theory because it needs to relocate immediate document children (there is just one in conformant documents) and all memory pages; in practice the memory pages only need the header adjusted, which is ~0.1% of the actual data size.

Move requires no allocations in general, except when using compact mode where some moves need to grow the hash table which can fail (throw).

Fixes #104
2017-11-13 13:24:43 -08:00
Arseny Kapoulkine
3860b5076f Fix -Wshadow warning 2017-11-13 09:27:38 -08:00
Arseny Kapoulkine
58611c8702 tests: Add compact move tests
This helps make sure our error handling logic works and is exercised.
2017-11-13 08:59:16 -08:00
Arseny Kapoulkine
4bd8771c2f Implement correct move error handling for compact mode
In compact mode, we currently can not support zero-allocation moves
since some pointer assignments required during the move need to allocate
hash table slots.

This is mostly applicable to xml_document_struct::first_child, since the
pointer to this element is used as a hash table key, but there are some
contrived cases where parents of root's children need a hash slot and
didn't have it before.

These cases can be fixed by changing the compact encoding to be a bit
more move friendly, but for now it's easier to handle the error and
throw/return during move.

When this happens, the source document doesn't change.
2017-11-13 08:57:16 -08:00
Arseny Kapoulkine
91a3c28862 Add count argument to compact_hash_table::rehash/reserve
This allows us to do a single reserve for a known amount of assignments
that is larger than the default minimum per reserve (16).
2017-11-13 08:37:34 -08:00
Arseny Kapoulkine
6016e2180e CMake: Add __declspec(dllexport) for shared library builds
This makes sure that MSVC shared library build actually exports all the
needed symbols and generates import table.

Somehow, this is actually enough to make pugixml link as a DLL - there's
no need to specify __declspec(dllimport) even though pugixml exports
classes via DLL.

Fixes #113.
2017-11-12 20:21:46 -08:00
Arseny Kapoulkine
492ebc22bc tests: Fix expansion-to-defined warning
This warning is new as of GCC 7 and highlights undefined behavior in the
preprocessor that ASAN detection was relying on.
2017-11-10 21:35:59 -08:00
Arseny Kapoulkine
6fe31d1477 build: Simplify config=sanitize
These days OSX clang supports UB sanitizer so we can just use the same
settings for all systems.
2017-10-29 21:24:04 -07:00
Arseny Kapoulkine
ba9504325e build: Switch fuzz builds to use Clang 5.0 sanitize=fuzzer
The old fuzzer location is deprecated; this also makes it almost trivial
to fuzz, provided that the clang is set up correctly... on Ubuntu 17.10,
a command sequence like this works now:

    sudo apt install clang-5.0
    sudo apt install libfuzzer-5.0
    sudo cp /usr/lib/llvm-5.0/lib/libFuzzer.a /usr/lib/libLLVMFuzzer.a
    CXX=clang++-5.0 make fuzz_parse
2017-10-29 19:54:48 -07:00
Arseny Kapoulkine
0504fa4e90 tests: Add more tests for document move
These tests currently fail for compact mode because of ->reserve()
failing.
2017-10-26 08:36:05 -07:00
Arseny Kapoulkine
3af93a39d7 Clarify a note about compact hash behavior during move
After move some nodes in the hash table can have keys that point to
other; this makes the table somewhat larger but this does not impact
correctness.

The reason is that for us to access a key in the hash table, there
should be a compact_pointer/string object with the state indicating that
it is stored in a hash table, and with the address matching the key. For
this to happen, we had to have put this object into this state which
would mean that we'd overwrite the hash entry with the new, correct
value.

When nodes/pages are being removed, we do not clean up keys from the
hash table - it's safe for the same reason, and thus move doesn't
introduce additional contracts here.
2017-10-20 21:57:14 -07:00
Arseny Kapoulkine
b0fc587a7f tests: Add more move tests
We now check that appending a child to a moved document performs no
allocations - this is already the case, but if we neglected to copy the
allocator state this test would fail.
2017-10-20 21:53:42 -07:00
Arseny Kapoulkine
50bc0d5a69 tests: Adjust move coverage tests
Large test wasn't testing shared parent condition properly - add one
more level of hierarchy so that it works as expected.
2017-09-25 22:54:42 -07:00
Arseny Kapoulkine
26ead385a7 tests: Add more move tests
Add a test that checks that static buffer pointer was moved correctly
by checking if offset_debug still works.
2017-09-25 22:52:26 -07:00
Arseny Kapoulkine
402b967fa9 tests: Add more move tests
Make sure we have coverage for empty documents and for large documents
that trigger compact_shared_parent != root for some pages.
2017-09-25 22:47:10 -07:00
Arseny Kapoulkine
faba4786c0 tests: Add more document move tests
Verify that move doesn't allocate and that it preserves structures
required for tree memory management and append_buffer in tact.
2017-09-25 22:38:30 -07:00
Arseny Kapoulkine
febf25d1af Fix -Wshadow warning 2017-09-25 21:48:37 -07:00
Arseny Kapoulkine
6eb7519dba tests: Add basic move tests
These just verify that move ctor/assignment operator work as expected in
simple cases - there are a number of ways in which the internal
structure can be incorrect...
2017-09-25 21:37:56 -07:00
Arseny Kapoulkine
a567f12d76 Implement move support for xml_document
This change implements the initial version of move construction and
assignment support for documents.

When moving a document to another document, we always make sure move
target is in "clean" state (empty document), and proceed by relocating
all structures in the most efficient way possible.

Complications arise from the fact that the root (document) node is
embedded into xml_document object, so all pointers to it have to change;
this includes parent pointers of all first-level children as well as
allocator pointers in all memory pages and previous pointer in the first
on-heap memory page.

Additionally, compact mode makes everything even more complicated
because some of the pointers we need to update are stored in the hash
table (in fact, document first_child pointer is very likely to be there;
some parent pointers in first-level children will be using
compact_shared_parent but some won't be) which requires allocating a new
hash table which can fail.

Some details of this process are not fully fleshed out, especially for
compact mode; and this definitely requires many tests.
2017-09-25 19:31:18 -07:00
Arseny Kapoulkine
a569e6a737 Switch to sudo=false Travis env 2017-09-24 22:46:48 -07:00
Arseny Kapoulkine
900a1cc943 docs: Clarify Unicode validation behavior
It has always been the case that pugixml does not perform Unicode
validation or name/tag Unicode character class validation, but it wasn't
very obvious from documentation.

Fixes #162
2017-08-29 20:46:30 -07:00
Arseny Kapoulkine
4f2ad720c8 docs: Update encoding conversion description
We support Latin-1 and automatically detect it by parsing the encoding
from document declaration; both of these were omitted from the
description of the automatic detection.

Additionally, the description has been rewritten to be more concise and
a bit more abstract - there's no need to specify the algorithm precisely
here.

Fixes #158.
2017-08-21 20:54:38 -07:00
Arseny Kapoulkine
50952c0a5e scripts: Fix NuGet VS2017 build
Due to a typo in build script v141 binaries were built using VS2015
instead of VS2017.

Fixes #157.
2017-08-20 07:12:09 +01:00
Arseny Kapoulkine
f423cec11b scripts: Disable LTCG for VS2017
Using LTCG restricts the resulting .lib files to a specific compiler
version, causing version conflicts when the compiler gets updated
without changing the toolset version. VS2017 now has two incompatible
compilers, 15.0 and 15.3, both of which use toolset v141...
2017-08-18 21:44:47 +01:00
Arseny Kapoulkine
77d7e60379 Fix Clang/C2 compatibility
Clang/C2 does not implement __builtin_expect; additionally we need to
work around deprecation warnings for fopen by disabling them.
2017-07-17 22:15:35 -07:00
Arseny Kapoulkine
ed86ef32b3 Update README.md
Switch codecov.io URLs to https
2017-06-29 01:03:55 -07:00
Arseny Kapoulkine
cfa64676be Update README.md 2017-06-29 00:53:59 -07:00
Arseny Kapoulkine
f3e0f4249c tests: Add more stream coverage tests
These new tests test that tellg() can fail when being called the second
time, which leads to seekable implementation failing.
2017-06-23 08:44:52 -07:00
Arseny Kapoulkine
4564d31c76 tests: Add stream coverage tests
These tests simulate various error conditions when reading data from
streams - seeks failing in seekable streams, underflow throwing an
exception causing read to set badbit, etc.

This change also adjusts memory thresholds to cause a reliable out of
memory during construction of a final buffer for non-seekable streams.
2017-06-23 07:48:09 -07:00
Arseny Kapoulkine
20a8eced3b tests: Fix PUGIXML_WCHAR_MODE build 2017-06-22 22:18:16 -07:00
Arseny Kapoulkine
3870217381 tests: Add more XPath out of memory tests
This fixes missing coverage in translate_table_generate and
xpath_node_set_raw::append.
2017-06-22 22:11:43 -07:00
Arseny Kapoulkine
5867aff943 tests: Make using namespace more explicit
Hiding using namespace in common.hpp is somewhat surprising so remove
common.hpp and move using namespace into all .cpp files that need it.
2017-06-22 20:41:08 -07:00
Arseny Kapoulkine
4b371e10ee tests: Remove redundant pugi:: qualifier
Most tests have `using namespace pugi` which makes explicit
qualifications unnecessary.
2017-06-22 20:33:02 -07:00
Arseny Kapoulkine
853333cd70 Use PUGI__MSVC_CRT_VERSION instead of _MSC_VER
It's not clear whether we still need PUGI__MSVC_CRT_VERSION, but it's
more consistent for now to use it for _snprintf_s since this is relying
on a CRT extension, not on a compiler feature.
2017-06-22 20:28:06 -07:00
Arseny Kapoulkine
2252927c04 Deprecate xml_document::load(const char*) and xml_node::select_single_node
These functions were deprecated via comments in 1.5 but never got the
deprecated attribute; now is the time!

Using deprecated functions produces a warning; to silence it, this
change moves the relevant tests to a separate translation unit that has
deprecation disabled.
2017-06-22 09:13:10 -07:00
Arseny Kapoulkine
94ef7b3a03 Merge pull request #151 from zeux/nuget
Rework NuGet package building
2017-06-20 21:32:11 -07:00
Arseny Kapoulkine
88d43a7ebc scripts: Refactor nuget_build.ps1
Unify build paths in all MSBuild VS projects and extract common build
logic into functions.

Note that this change changes both VS2010 and VS2013 projects to have
more predictable output paths and fixed output file name (pugixml).
2017-06-20 21:11:35 -07:00
Arseny Kapoulkine
fbc7085c14 scripts: Clarify the linkage settings in package description
Also improve linkage description
2017-06-20 21:11:35 -07:00
Arseny Kapoulkine
d2b0328198 Remove CoApp msi installation
We build NuGet package manually now so we don't need CoApp.
2017-06-20 21:11:35 -07:00
Arseny Kapoulkine
7d651ac3b6 Update .gitignore 2017-06-20 21:11:35 -07:00
Arseny Kapoulkine
a7c4070df7 scripts: Switch to manual NuGet package with both CRT linkages
We'd like to build pugixml with both static & dynamic CRT and put it
all in one NuGet package.

CoApp sort of allows us to do this via dynamic/static pivots, but it
does not let us customize the names of the pivots and additionally has
some bugs with the project setup. Their project modifications are also
much more complicated - really, at this point we should do this
ourselves.

Create a simple native NuGet package with Linkage setting that picks the
right library, and package all libraries appropriately. Note that we use
the unified path syntax to make it simple to just get the right .lib
file from the toolset/platform/configuration/linkage combo.
2017-06-20 21:11:35 -07:00
Arseny Kapoulkine
208e2cf043 Change PUGI__SNPRINTF to use _countof for MSVC
The macro only works correctly when the input argument is an array with
a statically known size - pointers or arrays decayed to pointers won't
work silently.

While this is unlikely to surface issues that aren't caught in
tests/code review, use _countof for MSVC to prevent such code from
compiling.
2017-06-19 07:06:47 -07:00
Arseny Kapoulkine
867bd2583b Merge pull request #150 from zeux/nuget
Add VS2017 to AppVeyor test run
2017-06-18 22:34:08 -07:00
Arseny Kapoulkine
9357837d2e Add VS2017 to AppVeyor test run
This requires moving the list of VS versions out of
autotest-appveyor.ps1 and into appveyor.yml.
2017-06-18 22:20:13 -07:00
Arseny Kapoulkine
7418bd0d79 scripts: Cleanup nuget_build.ps1
Correctly check for error codes and don't run .bat file since it doesn't
work anyway (the variables it sets aren't accessible in PowerShell, and
the path to the script doesn't seem to be the same in VS2017).
2017-06-18 21:11:54 -07:00
Arseny Kapoulkine
ade869ea58 Merge pull request #147 from igagis/master
VS2017 project + NuGet support
2017-06-18 20:49:11 -07:00
Arseny Kapoulkine
0027b6ac79 tests: Improve XPath coverage
Add memory allocation failure test for concact with a very large list
and make sure we have every single axis covered with and without a
predicate, with and without a previous step.
2017-06-16 22:45:42 -07:00
Arseny Kapoulkine
08f102f14c tests: Add even more stream coverage tests
Apparently only narrow character streams had out of memory coverage -
fix that and also split this into a separate test.
2017-06-16 21:38:55 -07:00
Arseny Kapoulkine
86593c0999 tests: Add more stream coverage tests
Cover both char and wchar_t stream loading in a single run instead of
using pugi::char_t.
2017-06-16 17:08:00 -07:00
Arseny Kapoulkine
3aa2b40354 tests: Add more coverage tests for stream loading
Cover more failure cases and simplify the streambuf implementation a
bit.
2017-06-16 16:41:08 -07:00
Arseny Kapoulkine
b6995f06b9 Fix BorlandC compilation
Rename partition to partition3 to resolve conflicts with std::partition.
2017-06-16 00:32:01 -07:00
Arseny Kapoulkine
bd23216420 tests: Improve XPath test coverage
Add more memory allocation failure tests.
2017-06-16 00:29:14 -07:00
Arseny Kapoulkine
a3664ea971 tests: Expand write_flush coverage
Adjust the buffer size to be right on the edge of the overflow, make
sure we actually output &quot; instead of ".
2017-06-16 00:09:32 -07:00
Arseny Kapoulkine
d2892be902 tests: Add xml_buffered_writer coverage test
This test triggers flush() condition for each optimized write() method.
2017-06-15 23:52:56 -07:00
Arseny Kapoulkine
95f013ba80 Refactor snprintf support
Instead of branching code at each invocation site, use variadic macros
to create a wrapping macro that use snprintf for the buffer of a
statically known size.

Variadic macros are supported by all C++11 compilers, as is snprintf;
on MSVC 2005+ we don't necessarily have snprintf, but we can use
_snprintf_s with _TRUNCATE to get the same behavior. In all other cases
we fall back to sprintf, that (theoretically) can lead to a stack buffer
overflow.

In practice all snprintfs used in pugixml use buffers that should be
large enough to never be overflown but snprintf is safe even if this is
not the case.
2017-06-15 23:35:20 -07:00
Arseny Kapoulkine
207bc788e9 Use buffer with a static size in convert_number_to_mantissa_exponent
We use references to arrays elsewhere in the codebase and there's just
one caller for this function so it's easier to fix the size.

This will simplify snprintf refactoring.
2017-06-15 22:58:46 -07:00
Arseny Kapoulkine
cd2804d3ee Merge pull request #145 from noresources/snprintf
use snprintf instead of sprintf
2017-06-15 21:34:04 -07:00
Arseny Kapoulkine
0698810abb Merge pull request #149 from zeux/test-path
Improve code coverage
2017-06-15 21:17:26 -07:00
Arseny Kapoulkine
927d321d90 Exclude unreachable lines from code coverage
codecov.io does not seem to support lcov regex customization;
additionally, we can't just replace unreachable with LCOV_LINE_EXCL
in gcov file - so we have to patch the ##### indicator (which suggests
the line hasn't been hit) with 1.

See also https://github.com/codecov/support/issues/144
2017-06-15 20:58:26 -07:00
Arseny Kapoulkine
b3b44841f0 Mark all assert(false) statements as unreachable
Now we can exclude these from code coverage since it's logically
impossible to hit them in tests.
2017-06-15 09:26:23 -07:00
Arseny Kapoulkine
c40fd364ce tests: Add tests for loading special files
New tests try to load a folder as an XML document, and a device. Both
are intended to exercise some otherwise non-hittable error paths in
load_file implementation.
2017-06-15 07:23:49 -07:00
Ivan Gagis
b66ca4f326 use 2 images to build on appveyor 2017-06-15 11:49:10 +03:00
Ivan Gagis
4dc1054104 use powershell instead of cmd 2017-06-15 11:32:46 +03:00
Ivan Gagis
e944623780 Appveyor image set to VS2017 2017-06-15 11:17:34 +03:00
Ivan Gagis
042eae4c83 Appveyor image set to VS2017 2017-06-15 11:14:28 +03:00
Ivan Gagis
d8f9148d36 set v141 tools environment for building 2017-06-15 11:11:36 +03:00
Ivan Gagis
3a8073cca2 Appveyor image set to VS2017 2017-06-15 11:05:28 +03:00
Ivan Gagis
c7131b01f9 VS2017 project 2017-06-15 10:59:33 +03:00
Arseny Kapoulkine
0fbc043183 tests: Increase compact_pointer coverage
This adds tests that complete branch coverage in compact pointer
encoding/decoding code (previously first_attribute was always encoded
using compact encoding in the entire test suite).
2017-06-14 23:50:21 -07:00
Arseny Kapoulkine
52da6f71d0 Increase the minimum CMake version to 2.8.12
This is a followup to 198900eff4.

target_include_directories was introduced in 2.8.12, thus CMake 2.6 no
longer works.
2017-06-14 23:06:32 -07:00
Renaud Guillard
0d8022eced use snprintf if available, _snprintf or sprintf otherwise 2017-06-11 18:33:28 +02:00
Renaud Guillard
810f1f600d use _snprintf if MSVC 2017-06-05 13:31:58 +02:00
Renaud Guillard
b5e9d933ad use snprintf instead of sprintf 2017-06-04 21:10:19 +02:00
Arseny Kapoulkine
38edf255ae Work around -fsanitize=integer issues
Integer sanitizer is flagging unsigned integer overflow in several
functions in pugixml; unsigned integer overflow is well defined but it
may not necessarily be intended.

Apart from hash functions, both string_to_integer and integer_to_string
use unsigned overflow - string_to_integer uses it to perform
two-complement negation so that the bulk of the operation can run using
unsigned integers. This makes it possible to simplify overflow checking.
Similarly integer_to_string negates the number before generating a
decimal representation, but negating is impossible without unsigned
overflow or special-casing certain integer limits.

For now just silence the integer overflow using a special attribute;
also move unsigned overflow into string_to_integer from get_value_* so
that we have fewer functions marked with the attribute.

Fixes #133.
2017-04-03 23:35:24 -07:00
Arseny Kapoulkine
24d1a4562b Move libFuzzer build to Makefile
Now the only thing fuzz_setup.sh does is installing new clang; if system
clang supports -fsanitize-coverage then fuzz_setup.sh is not required.
2017-04-03 21:09:37 -07:00
Arseny Kapoulkine
0eb1ddb975 tests: Fix fuzz_setup.sh
The script only worked if clang folder was already created.
2017-04-03 20:36:33 -07:00
Arseny Kapoulkine
101f32884f Add missing PUGI__FN to string_to_integer 2017-03-21 22:06:19 -07:00
Arseny Kapoulkine
956be4ca4b Revert "Fix gcc-4.8 compilation warning when using -Wstrict-overflow"
This reverts commit 79109a8546.

This warning does not happen on gcc-4.8.4; the workaround introduces an
unsigned integer overflow which results in a runtime error when compiled
with integer sanitizer.
2017-03-21 21:57:16 -07:00
Arseny Kapoulkine
acfe47ba52 tests: Do not use unsigned underflow in test code
This triggers a runtime error under integer sanitizer
2017-03-21 21:47:22 -07:00
Arseny Kapoulkine
c29940ca72 tests: Fix invalid buffer size
This was triggering an buffer read overflow with asan.
2017-03-21 10:33:20 -07:00
Arseny Kapoulkine
db98a7e28b Fix path to fuzzing corpus 2017-03-21 10:28:20 -07:00
Arseny Kapoulkine
640c94f90d Merge pull request #134 from ogdf/explicit-fallthroughs
Silence g++ 7.0.1 -Wimplicit-fallthrough warnings
2017-03-06 07:43:40 -08:00
Stephan Beyer
87fc170cdf Silence g++ 7.0.1 -Wimplicit-fallthrough warnings
This is accomplished by putting a // fallthrough
comment at the right place.
This seems to be more portable than an attribute-based
solution like [[fallthrough]] or __attribute__((fallthrough)).
2017-03-05 22:12:10 +01:00
Arseny Kapoulkine
8ce4592e15 Simplify compact_hash_table implementation
Instead of a separate implementation for find/insert, use just one that
can do both. This reduces the code size and simplifies code coverage;
the resulting code is close to what we had in terms of performance and
since hash table is a fall back should not affect any real workloads.
2017-03-03 07:11:22 -08:00
Arseny Kapoulkine
03e4b8de92 Merge pull request #132 from zeux/fuzz
Improve fuzzing support
2017-02-11 13:51:39 -08:00
Arseny Kapoulkine
ec984370fb tests: Fix fuzz_setup.sh
Make the file executable, fix Windows newlines and fix clang setup.
2017-02-11 13:17:27 -08:00
Arseny Kapoulkine
ea544eb48b tests: Add fuzzing dictionaries
Hopefully this will allow for better fuzzing coverage
2017-02-11 13:17:02 -08:00
Arseny Kapoulkine
8c62fa9121 tests: Add XPath fuzzing
Only fuzz the parser for now.
2017-02-09 07:37:38 -08:00
Arseny Kapoulkine
8b15ae8015 tests: Add a script to set up fuzzing tools
This downloads a clang build that has support for instrumentation, and also
downloads and compiles libFuzzer.a.
2017-02-09 07:37:04 -08:00
Arseny Kapoulkine
00ef791078 fuzz: Use libFuzzer instead of afl-fuzz
This allows us to have faster fuzz cycles since the fuzzer is in-process.
2017-02-09 07:36:32 -08:00
Arseny Kapoulkine
e748f435e5 tests: Increase the number of translate calls
This should make the test fail on a 32-bit target.
2017-02-09 07:36:32 -08:00
Arseny Kapoulkine
4bab082a27 tests: Fix clang build 2017-02-09 07:36:32 -08:00
Arseny Kapoulkine
ba39838ab5 tests: Add more XPath out of memory tests 2017-02-09 07:36:31 -08:00
Arseny Kapoulkine
d4c456bdef Add invalid type assertion for offset_debug
This will make sure we don't forget to implement offset_debug for new
node types if they ever happen (really it's mostly for consistency).
2017-02-09 07:36:31 -08:00
Arseny Kapoulkine
02c599f52b tests: Increase the number of translate calls
This should make the test fail on a 32-bit target.
2017-02-08 01:18:11 -08:00
Arseny Kapoulkine
b98c914053 tests: Fix clang build 2017-02-08 00:33:51 -08:00
Arseny Kapoulkine
1688f44185 tests: Add more XPath out of memory tests 2017-02-08 00:09:32 -08:00
Arseny Kapoulkine
0991c1d283 Add invalid type assertion for offset_debug
This will make sure we don't forget to implement offset_debug for new
node types if they ever happen (really it's mostly for consistency).
2017-02-07 20:34:49 -08:00
Arseny Kapoulkine
2162a0d80c XPath: Simplify sorting implementation
Instead of a complicated partitioning scheme that tries to maintain the
equal area in the middle, use a scheme where we keep the equal area in
the left part of the array and then move it to the middle.

Since generally sorted arrays don't contain many duplicates this extra
copy is not too expensive, and it significantly simplifies the logic and
maintains good complexity for sorting arrays with many equal elements
nonetheless (unlike Hoare partitioning).

Instead of a median of 9 just use a median of 3 - it performs pretty
much identically on some internal performance tests, despite having a
bit more comparisons in some cases.

Finally, change the insertion sort threshold to 16 elements since that
appears to have slightly better performance.
2017-02-07 00:05:50 -08:00
Arseny Kapoulkine
774d5fe9df XPath: Optimize insertion_sort
The previous implementation opted for doing two comparisons per element
in the sorted case in order to remove one iterator bounds check per
moved element when we actually need to copy. In our case however the
comparator is pretty expensive (except for remove_duplicates which is
fast as it is) so an extra object comparison hurts much more than an
iterator comparison saves.

This makes sorting by document order up to 3% faster for random
sequences.
2017-02-06 19:28:33 -08:00
Arseny Kapoulkine
8cc3144e7b XPath: Remove redundant calls from xml_node::select_nodes et al
Instead of delegating to a method that just forwards the call to
xpath_query call the relevant method directly.
2017-02-05 21:52:30 -08:00
Arseny Kapoulkine
00e39c581a XPath: Remove evaluate_string_impl
It adds one stack frame to string query evaluation and does not really
simplify the code.
2017-02-05 21:50:13 -08:00
Arseny Kapoulkine
a9fe2bb62e Merge pull request #131 from zeux/xpath-noeh
XPath: Remove exceptional control flow
2017-02-05 21:34:54 -08:00
Arseny Kapoulkine
10676b6b85 tests: Add more XPath sorting tests
Cover empty node case - no XPath query can result in that but it's
possible to create a node set with empty nodes manually.
2017-02-05 21:12:55 -08:00
Arseny Kapoulkine
bcc7ed57a2 XPath: Simplify evaluation error flow
Instead of having two checks for out-of-memory when exceptions are
enabled, do just one and decide what to do based on whether we can
throw.
2017-02-03 20:33:40 -08:00
Arseny Kapoulkine
33159924b1 XPath: Clean up out-of-memory parse error handling
Instead of relying on a specific string in the parse result, use
allocator error state to report the error and then convert it to a
string if necessary.

We currently have to manually trigger the OOM error in two places
because we use global allocator in rare cases; we don't really need to
do this so this will be cleaned up later.
2017-02-02 18:40:20 -08:00
Arseny Kapoulkine
faadd460c4 tests: Add more out of memory tests for XPath evaluation 2017-02-02 08:57:02 -08:00
Arseny Kapoulkine
c28ff128d8 tests: Add more embed_pcdata tests 2017-02-02 08:40:34 -08:00
Arseny Kapoulkine
f9f1c86716 tests: Improve parsing coverage
Add tests for PI erroring exactly at the buffer boundary with
non-zero-terminated buffers (so we have to clear the last character
which changes the parsing flow slightly) and a test that makes sure
parse_embed_pcdata works properly with XML fragments where PCDATA can be
at the root level but can't be embedded into the document node.
2017-02-01 21:07:46 -08:00
Arseny Kapoulkine
0e3ccc7396 Remove redundant branch from xml_node::path()
The code works fine regardless of the *j->name check, and omitting this
makes the code more symmetric between the "count" and "write" stage;
additionally this improves coverage - due to how strcpy_insitu works
it's not really possible to get an empty non-NULL name in the node.
2017-02-01 21:05:37 -08:00
Arseny Kapoulkine
e56686f1e5 tests: Remove redundant coverage test
The only point was to try to test all paths where we can run out of
memory while decoding something. It seems like it may be impossible to
actually do this given that we can't run all paths as wchar_t size
detection is done at runtime...
2017-02-01 20:21:14 -08:00
Arseny Kapoulkine
1a3e92a7cc tests: Add more tests to increase coverage
This change adds more thorough tests for attribute conversion as well as
some assorted tests that fix gaps in coverage.
2017-01-31 20:40:50 -08:00
Arseny Kapoulkine
094a0c8ebe tests: Add compact hash table reserve test
This makes sure all .reserve calls failure paths are covered. These
tests don't explicitly test if reserve is present on all paths - this is
much harder to test since not all modifications require reserve to be
called, so we'll have to rely on a combination of automated testing and
sanity checking for this.

Also add more parsing out of memory coverage tests.
2017-01-31 19:19:04 -08:00
Arseny Kapoulkine
41fb880bf0 tests: Add coverage tests for encoding detection
Enumerate successfull cases and also cases where the detection stops
half-way and results in a different detected encoding.
2017-01-31 07:50:39 -08:00
Arseny Kapoulkine
ef64bef5c3 tests: More XPath coverage tests 2017-01-31 00:35:15 -08:00
Arseny Kapoulkine
6ffd2ffc41 tests: Add more DOM coverage tests
Add tests for various corner cases of DOM inspection and modification
routines.
2017-01-31 00:10:20 -08:00
Arseny Kapoulkine
9c7897b8d2 Remove null pointer test from first_element_by_path
All other functions treat null pointer inputs as invalid; now this
function does as well.
2017-01-30 23:55:31 -08:00
Arseny Kapoulkine
a1bc15c8d5 tests: Add more coverage tests
Expand out of memory coverage during XPath parsing and evaluation and
add some other small tests.
2017-01-30 23:52:32 -08:00
Arseny Kapoulkine
f500435cb4 XPath: Remove (re)allocate_throw and setjmp
Now error handling in XPath implementation relies on explicit error
propagation and is converted to an appropriate result at the end.
2017-01-30 22:31:57 -08:00
Arseny Kapoulkine
9e40c58532 XPath: Replace all (re)allocate_throw with (re)allocate_nothrow
This generates some out-of-memory code paths that are not covered by
existing tests, which will need to be resolved later.
2017-01-30 22:28:57 -08:00
Arseny Kapoulkine
60d5688a87 tests: Make predicate out-of-memory test less aggressive
Currently this test has very large runtime and relies on the fact that
the first memory allocation error causes the test to terminate. This
does not work with new behavior of running the query through and
reporting the error at the end, so make the runtime reasonable but still
generate enough memory to blow past the budget.
2017-01-30 22:27:48 -08:00
Arseny Kapoulkine
c370d1190d XPath: Fix reallocate_nothrow to preserve existing state
Instead of rolling back the allocation and trying to allocate again,
explicitly handle inplace reallocate if possible, and allocate a new
block otherwise.

This is going to be important once we use reallocate_nothrow from a
non-throwing context.
2017-01-30 22:10:13 -08:00
Arseny Kapoulkine
1a2e4b88ee XPath: Use nonthrowing allocations in duplicate_string
This requires explicit error handling for xpath_string::data calls.
2017-01-30 21:58:53 -08:00
Arseny Kapoulkine
ac150d504e XPath: Throw std::bad_alloc if we got an out-of-memory error
This allows us to gradually convert exception handling of out-of-memory
during evaluation to a non-throwing approach without changing the
observable behavior.
2017-01-30 21:58:53 -08:00
Arseny Kapoulkine
02cee98492 tests: Add more tests for branch coverage
gcov -b surfaced many lines with partial coverage, where branch is only
ever taken or not taken, or one of the expressions in a complex
conditional is always either true or false. This change adds a series of
tests (mostly focusing on XPath) to reduce the number of partially
covered lines.
2017-01-30 21:58:48 -08:00
Arseny Kapoulkine
cac1d8ad9f tests: Add an error propagation test for XPath
This test is supposed to test error coverage in different expressions
that are nested in other expressions to reduce the number of never-taken
branches in tests (and make sure we aren't missing any).
2017-01-30 11:51:07 -08:00
Arseny Kapoulkine
1b3e8614e7 XPath: Reword brace mismatch errors for clarity 2017-01-30 11:51:07 -08:00
Arseny Kapoulkine
1ed6d2102b XPath: Improve error message for expressions like .[1]
W3C specification does not allow predicates after abbreviated steps.
Currently this results in parsing terminating at the step, which leads
to confusing error messages like "Invalid query" or "Unmatched braces".
2017-01-30 11:51:07 -08:00
Arseny Kapoulkine
bc1e444694 XPath: Track allocation errors more explicitly
Any time an allocation fails xpath_allocator can set an externally
provided bool. The plan is to keep this bool up until evaluation ends,
so that we can use it to discard the potentially malformed result.
2017-01-30 11:51:07 -08:00
Arseny Kapoulkine
298996df11 Enable branch probabilities for gcov 2017-01-30 11:51:07 -08:00
Arseny Kapoulkine
635fe02801 XPath: Provide non-throwing and throwing allocations in xpath_allocator
For both allocate and reallocate, provide both _nothrow and _throw
functions; this change renames allocate() to allocate_throw() (same for
reallocate) to make it easier to change the code to remove throwing
variants.
2017-01-29 22:02:58 -08:00
Arseny Kapoulkine
8aa8e11ba6 tests: Add query out of memory test 2017-01-29 21:53:40 -08:00
Arseny Kapoulkine
6abf1d7c1a XPath: Minor error handling refactoring
Handle node type error before creating expression node
2017-01-29 21:53:23 -08:00
Arseny Kapoulkine
34b8c5908b Add NO_EXCEPTIONS build to Travis 2017-01-29 21:52:42 -08:00
Arseny Kapoulkine
4fa2241d7b XPath: Route out-of-memory errors through the exceptionless path
We currently need to convert error based on the text to a different type
of C++ exceptions when C++ exceptions are enabled.
2017-01-29 21:09:12 -08:00
Arseny Kapoulkine
bd8e2d782e XPath: Forward all node constructors through alloc_node
This allows us to handle OOM during node allocation without triggering
undefined behavior that occurs when placement new gets a NULL pointer.
2017-01-29 21:09:12 -08:00
Arseny Kapoulkine
293fccf3b0 XPath: Do not use exceptions to propagate parsing errors
Instead, return 0 and rely on parsing logic to propagate that all the
way down, and convert result to exception to maintain existing
interface.
2017-01-29 21:09:12 -08:00
Arseny Kapoulkine
7bb433b141 XPath: Assume that every function can fail and return 0
Propagate the failure to the caller manually. This is a first step to
parser structure that does not depend on exceptions or longjmp for error
handling (and thus matches the XML parser). To preserve semantics we'll
have to convert error code to exception later.
2017-01-29 21:09:12 -08:00
Arseny Kapoulkine
d72c0763f9 XPath: Minor parsing refactoring
Simplify function argument parsing by folding arg 0 parsing into the
main loop, reuse expression parsing logic for unary expression
2017-01-29 20:15:14 -08:00
Arseny Kapoulkine
60e580c2a8 XPath: Remove parse_function_helper
It was only used in three places and didn't really make the code more
readable.
2017-01-29 20:04:34 -08:00
Arseny Kapoulkine
f11c4d6847 XPath: alloc_string no longer returns NULL
NULL return value will be reserved for the OOM error indicator.
2017-01-29 20:00:44 -08:00
Arseny Kapoulkine
d3b9e4e1e8 Update copyright year to 2017 2017-01-26 20:12:06 -08:00
Daniel Knibbe
198900eff4 Added target_include_directories() to properly export include directories (#130)
Fixes #126
2017-01-17 09:30:01 -08:00
Arseny Kapoulkine
05edb250ee Work around cray++ compiler issue
It's still not clear as to what exactly makes it emit this error when compiling
string_to_integer:

CC-3059 crayc++: INTERNAL __C_FILE_SCOPE_DATA__, File = <pugixml>/src/pugixml.cpp, Line = 4524, Column = 4
  Expected no overflow in routine.

But a viable workaround for now is to exploit the knowledge that it uses
two-complement arithmetics and invert the sign manually.

Fixes #125.
2016-12-01 20:49:46 -08:00
Arseny Kapoulkine
e3524c90de scripts: Make archive build reproducible
We used to use the current timestamp when building the archive; switch to using
the timestamp of the tag with the version we're packaging.

This requires some monkey patching since tarfile module is always using current
timestamp when writing gzip header...

Also exclude archive.py from archive and simplify release file list in Makefile.
2016-11-28 23:24:27 -08:00
Arseny Kapoulkine
86ed1cf3b9 scripts: Move archive.py from tests 2016-11-27 17:55:41 -08:00
Arseny Kapoulkine
d2deb420bc Fix archive script to set timestamps properly for .tar.gz
By default they are set to Jan 1 1970 which breaks homebrew.

Fixes #124.
2016-11-27 12:09:12 -08:00
Arseny Kapoulkine
91bf70231a docs: Regenerate HTML documentation 2016-11-24 00:23:19 -08:00
Arseny Kapoulkine
5115db7409 tests: Fix unused variable warning in some compilers
The variable is being assigned to but never read when exceptions are
disabled.
2016-11-19 00:19:29 -08:00
Arseny Kapoulkine
8df9f97cda Silence 'cast increases required alignment of target type' warnings
These warnings are emitted on some GCC versions when targeting ARM; the
alignment is guaranteed to be correct due to how page offsets are set up
but the compiler doesn't know.
2016-11-18 09:49:31 -08:00
Arseny Kapoulkine
9366f25136 Rename set_value_convert to set_value_bool
It's too dangerous to overload here - easy to accidentally mix floating point
path with boolean one.
2016-11-17 21:37:27 -08:00
Arseny Kapoulkine
2af2524db5 Fix 'comparison of unsigned expression < 0 is always false' warnings
Unfortunately, some compilers don't suppress these kinds of warnings in
template instantiations; solve this by moving the responsibility for computing
negative bool to the caller.

Also since we're doing that we don't really need to convert to unsigned in the
implementation - might as well have the caller do it, which removes some type
dispatch logic and slightly reduces binary size.
2016-11-17 21:33:54 -08:00
Arseny Kapoulkine
6c2cd5210c scripts: Change VS2013 projects to use /Z7
Put debugging information into the object file so that it can be shipped
with NuGet binaries. Based on the linker settings for the executable
debug info will either be put into the final .PDB or stripped out.

Fixes #110.
2016-11-13 20:45:11 -08:00
Arseny Kapoulkine
80adb4ca5c Set 1.8 release date to (tentatively) Nov 24. 2016-11-13 17:04:33 -08:00
Arseny Kapoulkine
1e23402eb2 Change status_end_element_mismatch to point to closing tag name
Previously the error offset pointed to the first mismatching character, which
can be confusing especially if the start tag name is a prefix of the end tag
name. Instead, move the offset to the first character of the name - that way
it should be more obvious that the problem is that the entire name mismatches.

Fixes #112.
2016-11-13 16:59:14 -08:00
Arseny Kapoulkine
5ca7e7cffc Rewrite archive script into Python
Perl version needed Archive::Zip that for some reason is not installed on WSL by
default. Use this as an opportunity to remove the last Perl script.
2016-11-13 16:52:38 -08:00
Arseny Kapoulkine
c5223be434 tests: Fix MSVC warnings 2016-11-09 21:42:56 -08:00
Arseny Kapoulkine
2d47cde5d6 tests: Add a generalized write-roundtrip test
This test tests two important invariants:

- Every combination of write flags has to result in a valid document
- Parsing that document and saving the result has to result in identical output

We don't test all flags since parse_no_escapes can intentionally result in
malformed documents and other flags aren't relevant for node output.

Also note that we test both no-whitespace and whitespace version to make sure
we don't have unnecessary whitespace added during formatting.
2016-11-09 20:12:25 -08:00
Arseny Kapoulkine
c225b722cf docs: Add documentation for format_no_empty_element_tags
Also add it to the changelog for 1.8
2016-11-09 09:19:19 -08:00
Arseny Kapoulkine
1649b2e6b8 tests: Add a test for format_no_empty_element_tags 2016-11-09 09:12:36 -08:00
Arseny Kapoulkine
cd7e0b04f6 Add format_no_empty_element_tags flag
Setting this flag outputs start and end tag for every element, including empty
elements.

Fixes #118.
2016-11-09 09:11:30 -08:00
Arseny Kapoulkine
c75e3c45e5 Update version to 1.8 everywhere 2016-11-09 09:02:44 -08:00
Arseny Kapoulkine
57ef4ad459 docs: Add changelog draft for 1.8 2016-11-09 08:56:43 -08:00
Arseny Kapoulkine
17a215523c XPath: Fix source indentation
Split some lines into two and add braces in some places to make the code more
readable.
2016-11-08 07:14:59 -08:00
Arseny Kapoulkine
e4c43a0aa2 Move compact hash table pointer setup to xml_document
This keeps all code that creates document/allocator/page structures together.
2016-11-07 19:31:34 -08:00
Arseny Kapoulkine
9bc497267b Remove xml_allocator copying during parsing
The separate copy of allocator state in parser was meant to increase parsing
performance by reducing aliasing/indirection, but benchmarks against the
current source don't indicate that this is worthwhile.

Removing this simplifies the code slightly and makes it possible to move
compact hash table to the allocator.
2016-11-07 08:43:14 -08:00
Arseny Kapoulkine
2f98c62172 Rename xml_document::create/destroy for consistency 2016-11-07 08:22:54 -08:00
Arseny Kapoulkine
70f57fab6d tests: Don't use ranged for loop in move tests
Some compilers support move semantics but don't support ranged for.
2016-11-06 12:14:58 -08:00
Arseny Kapoulkine
0d015e9a2c Reduce MSVC version cutoff for move semantics support
MSVC 2010 supported move semantics (partially - but should be good enough for
our use case).
2016-11-06 11:51:16 -08:00
Arseny Kapoulkine
aa117cce42 Refactor move semantics support detection
Do it in one place and set PUGIXML_HAS_MOVE if it's available.
2016-11-06 11:49:10 -08:00
iFarbod
b3fc28d177 Add VS2013 check for C++11 availability (#121)
VS 2013 supports C++11, but __cplusplus macro isn't updated, and it is 199711 so the old check always fails, even though the compiler supports c++11.
2016-11-06 11:43:03 -08:00
Arseny Kapoulkine
a832e8a5ef Merge pull request #119 from pavelkryukov/master
Add C++11 'override' specifier
2016-10-17 20:36:49 -07:00
Pavel Kryukov
d0b0cc75ad Fix a comment before PUGIXML_OVERRIDE macro 2016-10-18 00:53:00 +03:00
Pavel Kryukov
c7c7349cb7 Add PUGIXML_OVERRIDE to headers of tests 2016-10-13 01:36:12 +03:00
Pavel Kryukov
3b58103157 Add 'override' keyword if C++11 is enabled 2016-10-05 20:11:07 +03:00
Arseny Kapoulkine
f53bddd7d5 Merge pull request #117 from digawp/quickstart-doc-fix
docs: Fix broken link at quickstart page
2016-09-21 23:20:16 -07:00
Diga Widyaprana
ddc8c1a795 Fix broken link 2016-09-22 14:03:13 +08:00
Arseny Kapoulkine
2933a03d09 CMake: Simplify install path logic
Select correct suffix to use for pkg-config
2016-09-20 22:16:47 -07:00
Arseny Kapoulkine
fd896d2476 CMake: Simplify pkg-config support
Merge USEOWNSUBDIR and PKGCONFIG build flags; move the pkg-config source file
to scripts/.
2016-09-20 22:11:42 -07:00
peterbud
0918dd2b99 Adding options PKGCONFIG build options 2016-09-13 21:03:11 +02:00
peterbud
6d69483bbc Adding PKG-CONFIG support
Also creating a separate install directory under INCLUDE and LIB directories
2016-09-12 21:44:20 +02:00
Arseny Kapoulkine
dfe9360cdf Merge pull request #109 from steji113/master
Remove static pivot from NuGet autopkg.
2016-08-08 08:24:20 -07:00
Arseny Kapoulkine
4451ab0b22 Add .codecov.yml to disable PR comments 2016-08-08 08:23:42 -07:00
Stephen Daudell
24ba24a465 Remove static pivot.
This pivot seemed to be causing issues because the NuGet package thought it was actually dynamic.
2016-08-08 10:04:54 -05:00
Arseny Kapoulkine
b9d8f22789 scripts: Fix indentation 2016-08-07 09:12:55 -07:00
Arseny Kapoulkine
55cea93e6c Merge pull request #108 from steji113/master
scripts: Add VS2013 static builds to nuget package
2016-08-07 09:06:41 -07:00
Stephen Daudell
ae984fbd54 Add custom toolset choices. 2016-08-04 14:56:52 -05:00
Stephen Daudell
97a6f65200 Potential fix for build issues. 2016-08-04 14:53:47 -05:00
Stephen Daudell
afe73da928 Expand build to include VS 2013. 2016-08-04 14:36:44 -05:00
Stephen Daudell
4d6556100f Update Nuget autopkg.
Include more configurations in the Nuget package.
2016-08-04 14:30:25 -05:00
Arseny Kapoulkine
bda8b72f81 Remove -b gcov argument
It interferes in a somewhat strange way with codecov reporting
2016-07-28 00:07:41 -05:00
Arseny Kapoulkine
666a01d335 Use references for output variables
While I grew to dislike references for this case, there are other functions in
the source that use references so switch to that for consistency.
2016-07-15 19:12:21 -05:00
Arseny Kapoulkine
5b102d108d tests: Fix clang warning 2016-07-15 18:53:59 -05:00
Arseny Kapoulkine
525b2fe5c3 tests: Add tests for latin1 detection 2016-07-14 23:04:17 -07:00
Arseny Kapoulkine
70d7c7904e Implement encoding detection by name.
This adds about 40 cycles for parsing <?xml version='1.0'?> declaration and
about 70 cycles for parsing <?xml version='1.0' encoding='utf-8'?>, as
measured on a Core i7, which should be negligible for all documents.

Fixes #16.
2016-07-14 22:44:23 -07:00
Arseny Kapoulkine
1d3befeaf8 Makefile: Add -Wcast-qual
It is probably redundant given that we have -Wold-style-cast, but it's better
to warn about casts like this in case we ever need to remove the latter flag.
2016-07-10 18:19:18 -07:00
Arseny Kapoulkine
4dbb564619 Only enable cxx_long_long_type if it is in the list of features
Fixes #99.
2016-06-18 01:51:28 -07:00
Arseny Kapoulkine
eec353c443 Switch to regular AppVeyor image 2016-06-10 21:18:13 -07:00
Arseny Kapoulkine
7699499f25 Add CMakeLists to 'make release' now that it's top-level 2016-06-10 21:12:00 -07:00
Arseny Kapoulkine
53bc83cae7 Merge pull request #90 from jippeholwerda/master
Put CMakeLists.txt in the project root.
2016-06-10 18:26:04 -07:00
Arseny Kapoulkine
937ac8116e Merge pull request #97 from HumMan/master
Add vs2013 projects
2016-05-15 20:19:41 -07:00
Alexsey Zazvonnykh
6439e0c1a1 Add vs2013 projects 2016-04-24 22:38:32 +03:00
Arseny Kapoulkine
2d5980b406 Adjust XML allocation pages to have the exact specified size
Previously the page size was defining the data size, and due to additional
headers (+ recently removed allocation padding) the actual allocation was a bit
bigger.

The problem is that some allocators round 2^N+k allocations to 2^N+M, which can
result in noticeable waste of space. Specifically, on 64-bit OSX allocating the
previous page size (32k+40) resulted in 32k+512 allocation, thereby wasting 472
bytes, or 1.4%.

Now we have the allocation size specified exactly and just recompute the available
data size, which can in small space savings depending on the allocator.
2016-04-14 08:43:06 -07:00
Arseny Kapoulkine
2e0ed8284b Remove extra space in an empty tag for format_raw
When using format_raw the space in the empty tag (<node />) is the only
character that does not have to be there; so format_raw almost results in
a minimal XML but not quite.

It's pretty unlikely that this is crucial for any users - the formatting
change should be benign, and it's better to improve format_raw than to add
yet another flag.

Fixes #87.
2016-04-14 00:30:24 -07:00
Arseny Kapoulkine
c6539ccef0 Refactor auto_deleter now that we only need to support one signature
Also rename auto_deleter_fclose to close_file.
2016-04-03 13:30:34 -07:00
Arseny Kapoulkine
54f87d3b59 Merge pull request #92 from QUSpilPrgm/master
Do not assume that fclose can be converted to int(*)(FILE*)
2016-04-03 13:27:12 -07:00
Arseny Kapoulkine
dba7932000 Fix AppVeyor build 2016-03-27 20:51:54 -07:00
QUSpilPrgm
0564d55e19 Do not assume that fclose can be converted to int(*)(FILE*) because some compilers use a special calling convention for stdlib functions like fclose 2016-03-24 17:33:10 +01:00
Jippe Holwerda
4469a32970 Change paths according to new CMakeLists.txt location. 2016-02-25 20:38:07 +01:00
Jippe Holwerda
806c75652a Put CMakeLists.txt in the project root.
Having CMakeLists.txt in the project root makes it so much easier to use pugixml
as an external dependency in another CMake project.
2016-02-25 19:30:03 +01:00
Arseny Kapoulkine
8b60bbdce4 scripts: Update license year 2016-02-13 13:07:53 -08:00
Arseny Kapoulkine
4bbf6255dd scripts: Rename CocoaPods script to match NuGet naming
Also remove top-level LICENSE file since .podspec already has it.
2016-02-13 13:07:19 -08:00
Arseny Kapoulkine
44c251fbc3 Merge pull request #85 from igagis/master
scripts: Add CocoaPods package
2016-02-13 13:05:41 -08:00
Ivan Gagis
b709f15d18 embed license to podspec, as LICENSE file is not in 1.7 tag, cocoapods errors otherwise. Get sources from zeux github 2016-02-03 19:29:40 +02:00
Ivan Gagis
4215a0a159 LICENSE, podspec 2016-02-03 19:09:24 +02:00
Arseny Kapoulkine
607e46f209 Refactor conversion from integer to string
Unify the implementations by automatically deducing the unsigned type from its
signed counterpart. That allows us to use a templated function instead of
duplicating code.
2016-02-02 10:44:35 -08:00
Arseny Kapoulkine
ac4a84df4d docs: Add documentation for long setters 2016-02-02 08:52:47 -08:00
Arseny Kapoulkine
d2e72ee05a tests: Add tests for long setters 2016-02-02 08:49:32 -08:00
Arseny Kapoulkine
f441c63ea4 Implement set/set_value/operator= for long types
This makes the coverage for basic numeric types complete (sans long double).

Fixes #78.
2016-02-02 08:39:45 -08:00
Arseny Kapoulkine
c712dd84ba Specify std=c++11 explicitly in Travis configurations
That way the defaults in the Makefile only matter for local runs.
2016-01-26 21:43:48 -08:00
Arseny Kapoulkine
c3d27daf8e Merge pull request #83 from ogdf/use-real-standards-only
Add cxxstd Makefile argument for testing C++ standards
2016-01-26 20:28:10 -08:00
Stephan Beyer
e017a22fe0 Let Travis CI perform C++98-based tests 2016-01-26 22:14:58 +01:00
Stephan Beyer
6bbbdb7d7e Make cxxstd an argument to Makefile
This determines the used C++ standard.
If you do not want to use a specific C++ standard, use cxxstd=any.
The default is set to c++11.

The "define" PUGIXML_NO_CXX11 is removed from the Makefile
since it is not used in the code anyways.
2016-01-26 22:14:58 +01:00
Stephan Beyer
fb647f69a2 Let Travis CI use Ubuntu trusty
This allows to perform C++11-based tests on the Linux.
2016-01-26 21:53:16 +01:00
Stephan Beyer
fc9073289f test_parse.cpp: add newline to last line
This is necessary in order to comply with the C++03 standard.
2016-01-24 19:47:06 +01:00
Arseny Kapoulkine
e133764f33 Merge pull request #81 from ogdf/whitespace-issues
Fix whitespace issues
2016-01-24 08:56:06 -08:00
Stephan Beyer
f7aa65db8a Fix whitespace issues
Git warns when it finds "whitespace errors". This commit gets
rid of these whitespace errors for code and adoc files.
2016-01-24 14:05:44 +01:00
Arseny Kapoulkine
7f91301946 Change header format in non-compact mode to store page offset
This utilizes the fact that pages are of limited size so we can store offset
from the object to the page in a few bits - we currently use 24 although that's
excessive given that pages are limited to ~512k.

This has several benefits:

- Pages do not have to be 64b aligned any more - this simplifies allocation flow
and frees up 40-50 bytes from xml_document::_memory.

- Header now has 8 bits available for metadata for both compact and default mode
which makes it possible to store type as-is (allowing easy type extension and
removing one add/sub operation from type checks).

- One extra bit is easily available for future metadata extension (in addition
to the bit for type encoding that could be reclaimed if necessary).

- Allocators that return 4b-aligned memory on 64-bit platforms work fine if
misaligned reads are supported.

The downside is that there is one or two extra instructions on the allocation
path. This does not seem to hurt parsing performance.
2016-01-20 21:51:02 -08:00
Arseny Kapoulkine
7aef75f43d docs: Adjust as_int documentation to match implementation
Also remove the description of behavior for trailing non-numeric characters.
It's likely this will become a parse error in the future so better leave it
as unspecified for now.

Fixes #80.
2016-01-19 21:17:08 -08:00
Arseny Kapoulkine
c388dbeba4 Merge pull request #79 from zeux/embed-pcdata
Add parse_embed_pcdata flag

This flag determines if plain character data is be stored in the parent element's value. This significantly changes the structure of the document; this flag is only recommended for parsing documents with a lot of PCDATA nodes in a very memory-constrained environment.

Most high-level APIs continue to work; code that inspects DOM using first_child()/value() will have to be adapted.
2016-01-14 07:52:40 -08:00
Arseny Kapoulkine
4f3be76167 Preserve order semantics for child_value/text when using parse_embed_pcdata
The performance cost is probably negligible and this means we treat embedded
value as the first child consistently.
2016-01-12 20:41:37 -08:00
Arseny Kapoulkine
85238132d3 docs: Add parse_embed_pcdata documentation 2016-01-12 20:38:45 -08:00
Arseny Kapoulkine
71d3a797f4 Adjust parse_embed_pcdata documentation
Since round-tripping should not be a problem any more don't mention it.
2016-01-12 20:18:12 -08:00
Arseny Kapoulkine
fc6c8633dd tests: Add test for parse_embed_pcdata 2016-01-12 20:16:29 -08:00
Arseny Kapoulkine
bcddf36559 Only save first PCDATA contents in the element
This change fixes an important ordering issue - if element node has a PCDATA
child *after* other elements, it's impossible to tell which order the children
were in.

Since the goal of PCDATA embedding is to save memory when it's the only child,
only apply the optimization to the first child. This seems to fix all
roundtripping issues so the only caveat is that the DOM structure is different.
2016-01-12 20:01:44 -08:00
Arseny Kapoulkine
df2a0ad28b Implement output support for embedded PCDATA values
This is a bit awkward since preserving correct indentation structure requires
a bit of extra work, and the closing tag has to be written by _start function
to correctly process the rest of the tree.
2016-01-09 17:46:42 -08:00
Arseny Kapoulkine
85d8b225f2 Support XPath string value for parse_embed_pcdata 2016-01-08 08:41:38 -08:00
Arseny Kapoulkine
8b01f8923c Support xml_node::child_value/text for parse_embed_pcdata 2016-01-08 08:40:56 -08:00
Arseny Kapoulkine
2874f6f21d Add initial support for parse_embed_pcdata
When this flag is true, PCDATA value is saved to the parent element instead of
allocating a new node.

This prevents some documents from round-tripping since it loses information,
but can provide a significant memory reduction and parsing speedup for some
documents.
2016-01-08 08:37:26 -08:00
Arseny Kapoulkine
ad3b492c1a docs: Regenerate HTML documentation 2015-12-31 17:22:41 +03:00
Arseny Kapoulkine
5f58e9bd0c Update all license/copyright texts to 2016 2015-12-31 17:22:21 +03:00
Arseny Kapoulkine
af7177e77d docs: Use ISO-8601 for changelog dates 2015-12-31 17:11:54 +03:00
Arseny Kapoulkine
03b1b6a5c3 scripts: Fix default value for STATIC_CRT option
Also refactor to use the same case and run after common options.
2015-12-30 23:58:03 +03:00
Arseny Kapoulkine
6a22a28730 Merge pull request #70 from nirbar/master
scripts: Allow linking static CRT libraries on Windows

Use the solution from CMake FAQ to specify correct command-line arguments.
2015-12-30 23:54:58 +03:00
Arseny Kapoulkine
1bcf12402e Work around Clang Wstring-conversion warnings
(!"string") triggers the warning however (false && "string") does not.

Fixes #75.
2015-12-29 21:43:24 +03:00
nir.bar
3dadebf10e Merge branch 'master' of github.com:nirbar/pugixml 2015-12-03 13:19:52 +02:00
nir.bar
0d111976e1 Add CMake option on MSVC- STATIC_CRT 2015-12-03 12:33:44 +02:00
Arseny Kapoulkine
2cf599b310 Work around MinGW versions with non-C99 compliant headers
Apparently some MinGW distributions have a compiler that's recent enough to
support C++11 but limits.h header that incorrectly omits LLONG limits in
strict ANSI mode, since it guards the definitions with:

	#if !defined(__STRICT_ANSI__) && defined(__GNUC__)

We can just define these symbols ourselves in this specific case.

Fixes #66.
2015-11-13 09:09:43 -08:00
Arseny Kapoulkine
94c08f27c6 tests: Fix Borland C++ 5.4 compilation
The tests now compile fine but crash on the first floating-point exception
despite our attempts to disable them in main()...
2015-10-25 13:44:26 -07:00
Arseny Kapoulkine
fe58041a61 Fix Borland C++ 5.4 compilation
It does not have stdint.h and has some C++ parsing issues.
2015-10-25 12:57:43 -07:00
Arseny Kapoulkine
39149fd5bd Reduce Travis build matrix 2015-10-24 14:15:47 -07:00
Arseny Kapoulkine
0fe295aa9c Build NuGet package on AppVeyor 2015-10-23 11:11:49 -07:00
Arseny Kapoulkine
a3a9d53860 docs: Fix CDATA example
Fixes #61.
2015-10-19 20:55:39 -07:00
Arseny Kapoulkine
7d2842e670 docs: Add iOS to the list of supported platforms 2015-10-19 00:11:10 -07:00
Arseny Kapoulkine
5b2f014fc7 docs: Update packaging info 2015-10-18 21:01:14 -07:00
Arseny Kapoulkine
0c8024920f docs: Update release date 2015-10-18 20:13:52 -07:00
Arseny Kapoulkine
471f2260d0 docs: Rewrite Portability section 2015-10-18 18:23:17 -07:00
Arseny Kapoulkine
af3cd2e7b6 Add config=analyze 2015-10-18 18:00:17 -07:00
Arseny Kapoulkine
d27a64338e Add release build to Travis 2015-10-18 17:54:17 -07:00
Arseny Kapoulkine
e7f1e3d9dd Fix wchar mode 2015-10-18 17:52:45 -07:00
Arseny Kapoulkine
e45c173f73 Fix MWCW issue with compact mode 2015-10-18 16:10:30 -07:00
Arseny Kapoulkine
18483b024c Fix Borland C++ issues with compact mode 2015-10-18 16:09:31 -07:00
Arseny Kapoulkine
00d9f98ccc Work around DMC compilation error
For some reason reference to a fixed-size array works in two other places
but not in this one...
2015-10-18 15:58:16 -07:00
Arseny Kapoulkine
75a811a4f7 Fix 'cast increases required alignment of type' warnings
These show up when building with Wcast-align for ARM.
2015-10-18 15:51:02 -07:00
Arseny Kapoulkine
cd4eadcc2b Use -pedantic instead of -Wpedantic
Travis CI strikes once more.
2015-10-17 14:24:20 -07:00
Arseny Kapoulkine
3ac9555d8d Enable a few more warnings 2015-10-17 14:21:56 -07:00
Arseny Kapoulkine
65df1ef955 Fix XPath query move ctor/operator
It now also moves parse result.
2015-10-17 14:16:46 -07:00
Arseny Kapoulkine
cf8cfb30ce Fix 'signed/unsigned comparison' warning in wchar mode
Only happens on GCC 3.4 for some reason.
2015-10-17 12:58:04 -07:00
Arseny Kapoulkine
fd605bc9a7 tests: Fix GCC warning
Fix "this decimal constant is unsigned only in ISO C90".
2015-10-17 12:20:21 -07:00
Arseny Kapoulkine
1298c8db79 Fix -Wshadow warning 2015-10-17 12:14:04 -07:00
Arseny Kapoulkine
809f992f83 Fix MSVC6 header-only build
name_sentry dtor results in multiple symbol definition errors in MSVC6.
2015-10-17 10:51:20 -07:00
Arseny Kapoulkine
0e09571f21 Fix integer overflow detection with leading zeros
Since they don't contribute to the resulting value just skip them before
parsing. This matches the behavior of strtol/strtoll and results in more
intuitive behavior.
2015-10-17 10:33:50 -07:00
Arseny Kapoulkine
e8e54ea5de Use explicit tests in set_Name/set_value
Node type enum is not used as an array index anywhere else; the code is not
very readable and the value of this "optimization" is questionable.

The conditions are arranged so that in all normal cases the first comparison
returns true anyway.
2015-10-17 10:26:57 -07:00
Arseny Kapoulkine
122157eb0e Fix argument mismatch in integer parsing
The minneg argument is supposed to be the absolute value of the minimum negative
representable number. In case of two-complement arithmetic, it's the same as the
value itself but it's better to be explicit and negate the argument.
2015-10-17 10:14:52 -07:00
Arseny Kapoulkine
4230292830 Add compact_hash_table assertions 2015-10-17 10:13:40 -07:00
Arseny Kapoulkine
67702277e6 docs: Add a note about moving xpath_query 2015-10-17 08:59:41 -07:00
Arseny Kapoulkine
384db6ba29 Refactor output buffer encoding
Share the implementation for different encodings. We still need two functions
because endian_swap on uint8_t is ambiguous...
2015-10-12 09:15:01 -07:00
Arseny Kapoulkine
9aa28f1d05 docs: Regenerate HTML documentation 2015-10-10 13:51:34 -07:00
Arseny Kapoulkine
2ebd15b5d7 scripts: Use changelog URL as release notes 2015-10-10 13:51:01 -07:00
Arseny Kapoulkine
6b26a9a7f6 docs: Correct the acknowledgment section 2015-10-10 13:42:56 -07:00
Arseny Kapoulkine
f010cabb44 scripts: Use /Z7 for NuGet package
This avoids linker warning when building the final executable and we don't
have to package the .PDB file.
2015-10-10 13:32:40 -07:00
Arseny Kapoulkine
537aea56c6 tests: Fix version check :) 2015-10-10 13:07:53 -07:00
Arseny Kapoulkine
540424bd76 Add .gitignore 2015-10-10 13:05:04 -07:00
Arseny Kapoulkine
6fa0b39390 docs: Update changelog for 1.7 2015-10-10 13:04:06 -07:00
Arseny Kapoulkine
285fec31fc Fix 'make release' after clean checkout 2015-10-10 12:35:40 -07:00
Arseny Kapoulkine
0cfdba262e Update version to 1.7 2015-10-10 12:34:35 -07:00
Arseny Kapoulkine
99599f73e4 scripts: Fix NuGet description formatting 2015-10-10 11:53:58 -07:00
Arseny Kapoulkine
3147190f3d scripts: Cleanup NuGet packaging
Move pugixml project file for VS2015 to scripts/ and unify the output file
structure similar to old VS201x projects. Remove test projects and solution
since they are not required for building.

Provide more accurate information in the package script and handle build
errors during package construction properly.
2015-10-10 11:42:25 -07:00
Arseny Kapoulkine
c356bb071f Merge branch 'master' of https://github.com/igagis/pugixml into nuget 2015-10-10 10:55:22 -07:00
Arseny Kapoulkine
3e9cf53ea7 tests: Add a test for empty xpath_query ctor 2015-10-09 20:53:02 -07:00
Arseny Kapoulkine
bfc0f346b4 Refactor utf_decoder classes
Instead of functions with different names (e.g. decode_utf8_block), split
utf_decoder class into multiple classes with ::process static function.

This makes it easier to share code for decoding different encodings.
2015-10-09 20:46:39 -07:00
Ivan Gagis
ea190c8bd2 changed nuget name to pugixml without lib prefix 2015-10-08 13:33:54 +03:00
Arseny Kapoulkine
8ebab20fa5 Use correct type for lead in decode_utf16_block
This does not affect correctness but makes code more uniform.
2015-10-07 23:35:23 -07:00
Arseny Kapoulkine
e51a1a38e8 Refactor decode_utfN_block and decode_latin1_block
Make sure the looping structure is the same as in decode_utf8_block.
2015-10-07 22:42:37 -07:00
Arseny Kapoulkine
9f0a57a8f4 Simplify file/stream loading flow
Instead of calling xml_document public functions just call implementation of
load_buffer_inplace_own. This makes it so we only call reset() once during
load_file/load.
2015-10-07 22:06:43 -07:00
igagis
1402820ed0 Delete ReadMe.txt 2015-10-07 22:06:52 +03:00
Ivan Gagis
48beabdb3f nuget package scripts 2015-10-07 22:03:12 +03:00
Ivan Gagis
b112341a64 VisualStudio 2015 solution added 2015-10-07 21:46:35 +03:00
Arseny Kapoulkine
6e5163ba3e tests: Add a copy of header-only test
This makes sure we get linking errors whenever a symbol is not marked as inline
in header-only mode.
2015-10-06 07:26:24 -07:00
Arseny Kapoulkine
299e0b07c9 Merge pull request #58 from Breush/patch-1
Fixed missing PUGI__FN
2015-10-06 07:22:32 -07:00
A. Breust
dd2166ee27 Fixed missing PUGI__FN 2015-10-06 15:13:34 +02:00
Arseny Kapoulkine
2cda053345 scripts: Enable C++11 in CMakeLists
We now make sure that in CMake builds we have long long support. This requires
CMake 3.1 for target_compile_features.

Fixes #53 (as long as packages use this CMake script... most of them do)
2015-09-23 08:41:42 -07:00
Arseny Kapoulkine
3229e67712 Fix parsing of integers that start with +
This matches the format strtol supports.
2015-09-21 00:35:57 -07:00
Arseny Kapoulkine
b0b84277fa Merge pull request #56 from zeux/travis-osx
Add OSX to Travis CI config
2015-09-20 12:01:10 -07:00
Arseny Kapoulkine
d2252c5634 build: Reduce the build matrix
We don't need to test gcc on OSX
2015-09-20 11:48:31 -07:00
Arseny Kapoulkine
2ae191fe6f build: Add OSX to Travis config 2015-09-20 11:31:58 -07:00
Arseny Kapoulkine
1b2c1914b2 Fix signed/unsigned warnings for MSVC 2015-09-20 10:58:51 -07:00
Arseny Kapoulkine
5b86a8f612 tests: Add tests for integer overflow during conversion
These tests are only testing attribute as_int in hopes that xml_text uses the
same underlying implementation (which it does).
2015-09-20 10:48:30 -07:00
Arseny Kapoulkine
ec0c9c5561 Implement custom string to integer conversion
This makes conversion significantly faster and removes more CRT dependencies;
in particular, to support long long pugixml only requires the type itself (and
the division operator...).

New implementation is up to 3x faster on short decimal numbers.

Note that unlike the old implementation, new implementation correctly handles
overflow and underflow and clamps the value to the representable range. This
means that there are some behavior changes - e.g. previously as_uint on "-1"
would return INT_MAX instead of 0.

In addition to CRT issues, for platforms with 64-bit long old implementation
incorrectly truncated from long to int or unsigned int, so even if CRT clamped
the values the result would have been incorrect.
2015-09-20 10:43:38 -07:00
Arseny Kapoulkine
bda55c818c Remove extra const from operator= declaration
This does not really matter too much but it's better to be consistent.
2015-09-20 00:48:40 -07:00
Arseny Kapoulkine
25cce38f50 Inline widen_ascii to get rid of an extra strlen call
Also since this function is only used once and is not defined in regular mode
to avoid warnings this simplifies code a bit.
2015-09-20 00:47:20 -07:00
Arseny Kapoulkine
9c539f92ab Eliminate redundant strlen calls during set_value/set
Since we use manual integer conversion we know the length of the string.

This makes set_value(int) ~30% faster for 4-digit numbers.
2015-09-20 00:43:37 -07:00
Arseny Kapoulkine
5750b7cc19 Force callers of strcpy_insitu to compute string length
This makes it possible to avoid calling strlen if we already know the string
size.
2015-09-20 00:19:30 -07:00
Arseny Kapoulkine
131c1a159c Implement integer to string conversion manually
This reduces the amount of non-standard C++ functionality pugixml may be using
by avoiding sprintf with %lld; additionally this implementation is significantly
faster (4-5x) than sprintf, mostly due to avoiding format string parsing and
stream setup that commonly happens in CRT implementations.

This comes at the expense of requiring long long division/remainder operations
if PUGIXML_USE_LONG_LONG is defined which will surely bite me one day.
2015-09-20 00:03:02 -07:00
Arseny Kapoulkine
234c2f3657 tests: Convert several files to Unix line endings
They were still using Windows EOL by mistake
2015-09-19 00:14:18 -07:00
Arseny Kapoulkine
d62b2541d7 Update README.md 2015-08-25 10:42:59 -07:00
Arseny Kapoulkine
abdba2235d build: Fix -o gcov option
Also upload just pugixml.cpp.gcov to codecov to avoid issues the script has
with old gcov.
2015-08-25 10:36:44 -07:00
Arseny Kapoulkine
c7acc6d1f4 build: Rework config=coverage to be more robust
Use find -exec instead of xargs to work around differences between xargs on OSX
and Linux.

Use -b option of gcov - for some reason gcov on Travis can't find .gcno files
otherwise (old version?).

And finally enable config=coverage again.
2015-08-25 09:57:21 -07:00
Arseny Kapoulkine
9865f042ed build: Disable config=coverage for now 2015-08-25 09:25:32 -07:00
Arseny Kapoulkine
ff85f2106c build: Actually use config=coverage 2015-08-25 08:18:13 -07:00
Arseny Kapoulkine
440116a75b build: Test codecov.io integration 2015-08-25 08:14:26 -07:00
Arseny Kapoulkine
1d854cd420 build: Simplify coverage configuration
Use -coverage option and keep NDEBUG off
2015-08-25 08:14:20 -07:00
Arseny Kapoulkine
ce4ac17780 docs: Clarify UTF-8 vs wchar_t memory efficiency 2015-08-14 07:55:24 -07:00
Arseny Kapoulkine
c55e551235 docs: Add PUGIXML_COMPACT documentation
Also add PUGIXML_COMPACT to pugiconfig.hpp
2015-08-14 07:55:24 -07:00
Arseny Kapoulkine
fd0467c568 Minor get_integer_base optimization
Remove an extra branch.
2015-08-14 07:55:24 -07:00
Arseny Kapoulkine
f738675f1d Fix two UB sanitizer false positives
Change the expression to reference the array element indirectly. The memory
block can be bigger than the structure so it's invalid to use static data[]
size for bounds checking.
2015-07-26 21:04:52 -07:00
Arseny Kapoulkine
bd7a8fa4bf XPath: Increase memory block alignment to 8 bytes
To be more precise, the memory block is now aligned to be able to reliably
allocate objects with both double and pointer fields. If there is a platform
with a 4-byte double and a 4-byte pointer, the memory block alignment there will
stay the same after this change.

Fixes #48.
2015-07-25 17:08:19 -04:00
Arseny Kapoulkine
e8fdd1303c tests: Fix test allocator to provide fundamental alignment
Previously test allocator only guaranteed alignment enough for a pointer.

On some platforms (e.g. SPARC) double has to be aligned to 8 bytes but pointers
can have a size of 4 bytes. This commit increases allocation header to fix that.

In practical terms the allocation header is now always 8 bytes.
2015-07-25 17:04:17 -04:00
Arseny Kapoulkine
66f242a4a9 XPath: Refactor block allocation
Extract memory page size and block alignment into named constants.
2015-07-25 17:01:30 -04:00
Arseny Kapoulkine
a562bf6d3c tests: Only enable page heap on x86/x64
This fixes tests in PUGIXML_NO_XPATH mode on SPARC64 (#48).

SPARC does not allow unaligned accesses - e.g. you can't read an unaligned int.
Normally pugixml does not perform unaligned integer/pointer accesses, but page
heap can allocate blocks that are not aligned so that we can detect a single-
byte read/write overrun.

Additionally, the hardcoded page size we're currently using is really system
specific - on SPARC the page size can be 8 Kb instead of 4 Kb so mprotect can
fail.
2015-07-25 14:19:08 -04:00
Arseny Kapoulkine
4460da54a1 XPath: Split optimize into optimize and optimize_self
This makes the code slightly more readable, but more importantly it fixes a
false positive in Clang static analyzer.

Fixes #47.
2015-07-22 21:07:44 -07:00
Arseny Kapoulkine
d4fedd6775 docs: Clarify hash_value behavior
Fixes #43.
2015-06-24 09:45:26 -07:00
Arseny Kapoulkine
238b786bfe Makefile now supports Xcode 7 ASAN
All other sanitizers are still unavailable so only enable them on non-OSX
systems.
2015-06-13 00:00:08 -07:00
Arseny Kapoulkine
d04df2a48b Fix Clang 3.7 compatibility
Apparently Clang 3.7 implements C++ DR 1748 that makes placement new with null
pointer undefined behavior. Which renders all C++ programs that rely on this
invalid. Which includes pugixml.

This is not very likely to happen in the wild because the allocations that are
subject to this in pugixml are relatively small, but tests break because of
this.

Fix the issue by adding null pointer checks (that are completely redundant in
all current compilers except Clang 3.7 but it's not like there is another
option).
2015-06-12 23:59:35 -07:00
Arseny Kapoulkine
97afc16ef2 tests: Add newline at the end of file 2015-05-22 20:20:03 -07:00
Arseny Kapoulkine
2a1aa9663b Fix MSVC7 compilation
Work around a name lookup bug by pulling auto_deleter name in the local
scope. We could also move auto_deleter to pugi:: namespace, but that
pollutes it unnecessarily for other compilers.
2015-05-22 18:05:30 -07:00
Arseny Kapoulkine
fc1dcab79d tests: Fix MSVC6 compilation 2015-05-22 08:43:36 -07:00
Arseny Kapoulkine
677e95010e Move default value handling into as_ functions
This makes get_value_* simpler and also works around DMC compilation issue.
2015-05-22 08:42:32 -07:00
Arseny Kapoulkine
243839012a XPath: Use strtod instead of atof
This makes code more consistent between wchar/utf8 mode.
2015-05-20 08:31:00 -07:00
Arseny Kapoulkine
e2358e5e3b tests: Split fp roundtrip test into float and double 2015-05-20 08:05:43 -07:00
Arseny Kapoulkine
f828eae3ea Implement xml_node::attribute with a hint
Extra argument 'hint' is used to start the attribute lookup; if the attribute
is not found the lookup is restarted from the beginning of the attriubte list.

This allows to optimize attribute lookups if you need to get many attributes
from the node and can make assumptions about the likely ordering. The code is
correct regardless of the order, but it is faster than using vanilla lookups
if the order matches the calling order.

Fixes #30.
2015-05-14 08:04:06 -07:00
Arseny Kapoulkine
01f627a4d7 tests: Fix address sanitizer detection for GCC 2015-05-12 21:49:44 -07:00
Arseny Kapoulkine
107239c927 Add config=sanitize support to Makefile 2015-05-12 20:57:57 -07:00
Arseny Kapoulkine
59ce480f96 Add Visual Studio 2015 to AppVeyor 2015-05-12 20:55:59 -07:00
Arseny Kapoulkine
7342c5ed8c tests: Disable page allocator if address sanitizer is active
Address sanitizer can detect underflows so we don't really need the custom
allocator.

Additionally, custom allocator can return memory that is not pointer-aligned;
this causes undefined behavior sanitizer to complain.
2015-05-12 20:16:51 -07:00
Arseny Kapoulkine
9f7994ed71 tests: Fix clang 3.7 warning
Work around -Wself-move using ref-deref.
2015-05-12 20:02:53 -07:00
Arseny Kapoulkine
708952d84e Update README.md 2015-05-03 19:15:47 -07:00
Arseny Kapoulkine
51faffa238 Update README.md 2015-05-03 19:12:23 -07:00
Arseny Kapoulkine
272c80f67c Switch Travis CI to use Docker 2015-05-03 18:40:21 -07:00
Arseny Kapoulkine
86548e14bd Fix NO_STL+NO_XPATH mode
auto_deleter is now used in all modes so we can't exclude it from compilation.
2015-05-03 17:58:20 -07:00
Arseny Kapoulkine
cff35dfa31 tests: Fix MSVC6 compatibility
Apply the usual workaround for for scoping issues. Also fix integer conversion
warning for BorlandC.
2015-05-03 17:58:20 -07:00
Arseny Kapoulkine
873c8e5011 Merge pull request #42 from zeux/compact
Implement compact mode.

This introduces a new storage mode that dramatically reduces node size at some performance cost.
The mode is enabled by defining PUGIXML_COMPACT. This does not change API/ABI - all existing functionality still works.

The pointers are stored using delta encoding and bytes, with some additional tricks to make encoding more optimal for e.g. parent pointer and string pointers. Since the node is fixed size, we have to fall back to a hash table if the pointer does not fit. Thus all DOM operations still have amortized complexity - constant number of operations if you don't need the hash table and amortized constant if you do.

Aside from some performance loss (which is inevitable since decoding takes time), the only other caveat is that we can't remove entries from the hash table - so in some edge cases with a lot of node removals the peak memory consumption can grow indefinitely. In theory we can implement this later; it's unclear that this is useful at this point.

The resulting node/attribute sizes are as follows:
non-compact node: 28b 32-bit, 56b 64-bit
compact node: 12b 32/64-bit
non-compact attribute: 20b 32-bit, 40b 64-bit
compact attribute: 8b 32/64-bit
2015-05-03 11:42:19 -07:00
Arseny Kapoulkine
9597265a12 Cleanup before merge 2015-05-03 11:02:42 -07:00
Arseny Kapoulkine
b1965061af Fix MSVC warning 2015-05-03 09:21:23 -07:00
Arseny Kapoulkine
f67e761970 Fix MSVC build 2015-05-02 16:41:21 -07:00
Arseny Kapoulkine
20e2041f14 Reorder conditions in compact_string implementation
Now compact_string matches compact_pointer_parent.

Turns out PUGI__UNLIKELY is good at reordering conditions but usually does not
really affect performance. Since MSVC should treat "if" branches as taken and
does not support branch probabilities, don't use them if we don't need to.
2015-05-02 15:57:46 -07:00
Arseny Kapoulkine
f8915c8eab Minor refactoring 2015-05-02 15:47:59 -07:00
Arseny Kapoulkine
fa8663c066 Revise marker deletion strategy
Instead of checking if the object being removed allocated a marker, mark the
marker block as deleted immediately upon allocation. This simplifies the logic
and prevents extra markers from being inserted if we allocate/deallocate the
same node indefinitely.

Also change marker pointer type to uint32_t*.
2015-05-02 15:40:30 -07:00
Arseny Kapoulkine
613301ce51 Optimize compact_string
First assignment uses a fast path; second assignment uses a specialized
path as well.
2015-05-02 14:52:27 -07:00
Arseny Kapoulkine
19d43d39fc tests: Add one more page reclamation test 2015-05-02 09:45:26 -07:00
Arseny Kapoulkine
b1578e32a5 Fix node deallocation
When we deallocate nodes/attributes that allocated the marker we have to
adjust the size accordingly, and dismiss the marker in case it gets
overwritten with something else...
2015-05-02 09:38:14 -07:00
Arseny Kapoulkine
dec4267fb1 Implement efficient compact_header storage
Header is now just 2 bytes, with optional additonal 4 bytes that are only
allocated for every 85 nodes / 128 attributes.
2015-05-02 08:59:47 -07:00
Arseny Kapoulkine
e4c539a869 Implement compact_string with shared storage 2015-05-01 22:47:53 -07:00
Arseny Kapoulkine
3915f7b144 Rename compact_string to compact_string_fat 2015-05-01 21:09:26 -07:00
Arseny Kapoulkine
bc5eb22b71 Revert to name/value storage inside node
This temporarily increases the node size to 16 bytes - we'll bring it back.

It allows us to remove the horrible node_pi hack and to reduce the amount of
changes against master. This comes at the price of not decreasing basline
xml_node_struct size.

The compact xml_node_struct is also increased by this change but a followup
change will reduce *both* xml_attribute_struct and xml_node_struct (to 8/12
bytes).
2015-05-01 20:03:17 -07:00
Arseny Kapoulkine
dede617d9f tests: Fix spurious failures in compact mode
The memory_large_allocations test sometimes classified hash allocations
as page allocations since hash table could reach 512 entries.
2015-04-29 09:21:04 -07:00
Arseny Kapoulkine
b2399f5ab5 Refactor offset_debug
Split a long line into multiple statements.
2015-04-29 09:20:08 -07:00
Arseny Kapoulkine
44e4f17348 Change xml_node_struct field order to match compact
Also remove useless comments.
2015-04-22 09:53:04 -07:00
Arseny Kapoulkine
3643b505a6 Fix node_pi memory leak 2015-04-22 08:38:52 -07:00
Arseny Kapoulkine
4223b4a3f0 Make xml_node::value() structure consistent with set_* 2015-04-22 08:30:53 -07:00
Arseny Kapoulkine
e4e2259646 Remove compact_header::operator uintptr_t
We used this in two cases - to get the page pointer and to test flags.

We now use PUGI__GETPAGE for getting the page pointer and operator& to test
flags - this makes getting node type significantly faster since it does not
require page pointer reconstruction.
2015-04-22 08:26:47 -07:00
Arseny Kapoulkine
12744fd1fa Remove redundant has_value check 2015-04-22 07:52:20 -07:00
Arseny Kapoulkine
b87160013b Use has_name/has_value in set_name/set_value 2015-04-22 07:51:02 -07:00
Arseny Kapoulkine
4649914447 Optimize and refactor compact_pointer implementations
Clarify the offset applied when encoding the pointer difference.
Make decoding diff slightly more clear - no effect on performance.

Adjust branch weighting in compact_string encoding - 0.5% faster.
Use uint16_t in compact_pointer_parent - 2% faster.
2015-04-22 07:36:32 -07:00
Arseny Kapoulkine
33b2efe318 Optimize xml_allocator::reserve()
Make sure compact_hash_table::rehash() is not inlined - that way reserve() is
inlined so the fast path has no extra function calls.

Also use subtraction instead of multiplication when checking capacity.
2015-04-21 23:02:44 -07:00
Arseny Kapoulkine
52bcb4ecd6 tests: Adjust allocation thresholds to fix tests 2015-04-21 21:35:54 -07:00
Arseny Kapoulkine
f9983ea2ed Merge branch 'master' into compact 2015-04-21 21:27:44 -07:00
Arseny Kapoulkine
a6cc636a6b tests: Fix MSVC warnings 2015-04-21 21:07:58 -07:00
Arseny Kapoulkine
250d020e9b Use -std=c++0x instead of -std=c++11 2015-04-21 20:46:33 -07:00
Arseny Kapoulkine
8d4544f2e1 Enable C++11 in Makefile 2015-04-21 20:32:40 -07:00
Arseny Kapoulkine
4eadece45f tests: Add move semantics tests
Also test ranged for and copying big xpath_variable_set objects (to make
sure we actually handle hash collisions properly)
2015-04-21 19:44:19 -07:00
Arseny Kapoulkine
83b894b8f1 XPath: Implement move semantics support
xpath_query, xpath_node_set and xpath_variable_set are now moveable.

This is a nice performance optimization for variable/node sets, and enables
storing xpath_query in containers without using pointers (it's only possible
now since the query is not copyable).
2015-04-21 19:42:31 -07:00
Arseny Kapoulkine
a414c5c52d Fix compilation warning in some configurations 2015-04-21 10:02:26 -07:00
Arseny Kapoulkine
cbf3807ad4 Implement copy ctor/assignment for xpath_variable_set
xpath_variable_set is essentially an associative container; it's about time it
became copyable.

Implementation is slightly tricky due to out of memory handling. Both copy ctor
and assignment operator have strong exception guarantee (even if exceptions are
disabled! which translates to "roll back on allocation errors").
2015-04-15 23:22:31 -07:00
Arseny Kapoulkine
70a78b2fa5 tests: Fix Linux build 2015-04-15 22:11:13 -07:00
Arseny Kapoulkine
bb3aee447b tests: Use malloc for OSX/Linux page heap
Switch to malloc and manually aligning the pointer to the page boundary.

mmap is much slower than malloc; this change makes tests ~4x faster.
2015-04-15 21:44:52 -07:00
Arseny Kapoulkine
8c8940430a Minor xpath_variable refactoring
The type of the variable is now initialized correctly in the ctor, so that there
is no interim invalid state.
2015-04-15 08:34:14 -07:00
Arseny Kapoulkine
5158ee903b Fix xpath_node_set assignment to provide strong exception guarantee
Since the type of the set was updated before assignment, assigning in
out-of-memory condition could change the type to not match the content.
2015-04-14 19:23:36 -07:00
Arseny Kapoulkine
2badcbb674 Explicitly call xml_buffered_writer::flush()
If xml_writer::write throws an exception while being called from flush(), the
exception is thrown from destructor. Clang in C++11 mode calls std::terminate
in this case.
2015-04-14 19:11:26 -07:00
Arseny Kapoulkine
e977f04fe2 docs: Add format_indent_attributes documentation
Slightly reword format_indent description.
2015-04-13 21:50:24 -07:00
Arseny Kapoulkine
2a3435274f Refactor format_indent_attributes implementation
Fix code style and revert redundant parameters/whitespace changes.

Also remove format_each_attribute_on_new_line - we're only introducing one
extra formatting flag. The flag implies format_indent but does not include its
bitmask.

Also add a few more tests.

Fixes #14.
2015-04-13 21:49:08 -07:00
Arseny Kapoulkine
950693be7f Merge branch 'AlignAttributesEachOnSeparateLine' of git://github.com/halex2005/pugixml into indent_attributes 2015-04-13 20:56:18 -07:00
Arseny Kapoulkine
f241318f9c Add branch name to AppVeyor version 2015-04-13 20:38:52 -07:00
Arseny Kapoulkine
cb786665d4 tests: Add PUGIXML_COMPACT to AppVeyor 2015-04-13 20:36:04 -07:00
Arseny Kapoulkine
ed2c822643 Merge branch 'master' into compact 2015-04-13 20:35:26 -07:00
Arseny Kapoulkine
1c4098a7d9 Remove all files for the Jamplus-based build system
End of an era.

Make can be used for regular development (Linux/OSX), documentation building
and release packaging.
CMake can be used for regular development (Windows); it's also used by some
Linux distributions.

Continuous integration is now performed by Travis CI and AppVeyor.
2015-04-13 20:30:14 -07:00
Arseny Kapoulkine
baacd81907 Fix AppVeyor script path 2015-04-13 20:10:45 -07:00
Arseny Kapoulkine
218ddd0376 Add AppVeyor build scripts 2015-04-13 20:03:49 -07:00
Arseny Kapoulkine
05032b4c06 scripts: Add an option for building tests with CMake 2015-04-13 20:02:09 -07:00
halex2005
5d66ae9fb9 add tests for aligning each attribute on next line 2015-04-14 00:56:42 +05:00
halex2005
6766f35338 add align each attribute on new line support with format_indent_attribute 2015-04-14 00:56:23 +05:00
Arseny Kapoulkine
054b0b447e Merge branch 'master' into compact 2015-04-12 22:09:45 -07:00
Arseny Kapoulkine
9539c488c2 Fix unused variable warning
Also fix test in wchar_t mode.
2015-04-12 22:06:17 -07:00
Arseny Kapoulkine
f04b56e178 Permit custom allocation function to throw
Ensure that all the necessary cleanup is performed in case the allocation fails
with an exception - files are closed, buffers are reclaimed, etc.

Any test that triggers a simulated out-of-memory condition is ran once again
with a throwing allocation function. Unobserved std::bad_alloc count as test
failures and require CHECK_ALLOC_FAIL macro.

Fixes #17.
2015-04-12 21:46:48 -07:00
Arseny Kapoulkine
5edeaf6765 tests: Add more out of memory tests
Also add tests that verify save_file for absence of FILE leaks.
2015-04-12 21:27:12 -07:00
Arseny Kapoulkine
6c11a0c693 Fix compilation and tests after merge. 2015-04-12 03:14:08 -07:00
Arseny Kapoulkine
a19da1c246 Merge branch 'master' into compact 2015-04-12 03:05:58 -07:00
Arseny Kapoulkine
a0d065cd22 Implment copyless copy for attributes
Previously attributes that were copied with their node used string sharing,
but standalone attributes that were copied using xml_node::*_copy(xml_attribute)
were not.
2015-04-12 03:03:56 -07:00
Arseny Kapoulkine
c5d07e2c28 tests: Add a test that verifies absence of file leaks
If an out of memory error happens in load_file there's a danger of leaking
the FILE object. Since there is a limited supply of the objects we can easily
test that the leak does not happen.
2015-04-12 02:34:48 -07:00
Arseny Kapoulkine
2537cccad3 tests: Fix some Coverity issues 2015-04-12 02:17:20 -07:00
Arseny Kapoulkine
d6f7766172 Optimize xml_node::path() to use 1 allocation
Instead of reallocating the string for every tree level just do two passes
over the ancestor chain.
2015-04-12 02:12:15 -07:00
Arseny Kapoulkine
99afee1832 Move zero-termination out of as_utf8_end
as_utf8_end was used with std::string, where writing an extra zero-terminating
character should *probably* always work (at least if size is positive) but is
not ideal.

The only place that needed to zero-terminate was convert_path_heap.
2015-04-12 01:32:25 -07:00
Arseny Kapoulkine
3da7d68617 Fix Travis CI build. 2015-04-11 22:52:41 -07:00
Arseny Kapoulkine
4e004176ba tests: Improve out-of-memory tests
Previously there was no guarantee that the tests that check for out of memory
handling behavior are actually correct - e.g. that they correctly simulate out
of memory conditions.

Now every simulated out of memory condition has to be "guarded" using
CHECK_ALLOC_FAIL. It makes sure that every piece of code that is supposed to
cause out-of-memory does so, and that no other code runs out of memory
unnoticed.
2015-04-11 22:46:08 -07:00
Arseny Kapoulkine
37467c13bf tests: Add a test for throwing from xml_writer::write
We currently don't allocate/modify any state so there are no issues with this.
2015-04-11 22:44:42 -07:00
Arseny Kapoulkine
e2e5bc906a Use -fno-exceptions flag for PUGIXML_NO_EXCEPTIONS build
This makes sure that no exception handling mechanisms are used if
PUGXML_NO_EXCEPTIONS is defined.
2015-04-11 22:42:27 -07:00
Arseny Kapoulkine
814443b147 Fix exception type for out-of-memory for XPath variables
When parsing XPath variables, we need to perform a heap allocation; if it
fails, an xpath_exception instead of bad_alloc used to be thrown.

Now we throw the exception of a correct type so that xpath_exception means
'parsing error'.
2015-04-11 22:40:30 -07:00
Arseny Kapoulkine
03ea04c32a tests: Use char_t instead of wchar_t 2015-04-11 00:33:35 -07:00
Arseny Kapoulkine
29fef9aca2 tests: Add more out of memory tests
This provides more coverage for #17.
2015-04-11 00:16:39 -07:00
Arseny Kapoulkine
e90d2ac8ba Merge branch 'master' into compact 2015-04-10 22:26:57 -07:00
Arseny Kapoulkine
405fefc877 Update README.md 2015-04-10 20:59:07 -07:00
Arseny Kapoulkine
6457f09412 Merge branch 'master' into compact 2015-03-13 08:12:46 -07:00
Arseny Kapoulkine
50822aa2ac Fix optimized string header encoding for compact mode
Since in compact mode we only ever have a guaranteed alignment on 4, the pages
are limited to 256k even if pointers are 64 bit.
2015-03-10 21:15:13 -07:00
Arseny Kapoulkine
f81d7cc018 Merge branch 'master' into compact 2015-03-10 20:44:06 -07:00
Arseny Kapoulkine
e5ecbd63ce Merge branch 'master' into compact 2015-01-16 21:48:50 -08:00
Arseny Kapoulkine
93c3ab4649 Merge branch 'master' into compact 2014-11-27 00:25:16 -08:00
Arseny Kapoulkine
4b8da65be9 Add allocator reserve for copying
Since copying no longer relies on child insertion we have to also reserve
space in the hash table for the allocator so that pointer manipulations are
guaranteed to succeed.
2014-11-20 23:49:59 -08:00
Arseny Kapoulkine
db8df4a566 Merge branch 'master' into compact 2014-11-20 23:47:16 -08:00
Arseny Kapoulkine
cca23e6363 Reduce required page alignment to 32
Since we no longer have a name/value pair in nodes we need one less bit to
represent allocated flags. This reduces the page overhead by 32 bytes.
2014-11-08 20:05:12 +01:00
Arseny Kapoulkine
c74dc33604 Merge branch 'master' into compact 2014-11-07 21:02:44 +01:00
Arseny Kapoulkine
5cad3652d9 Fix compact mode compilation
Clang and gcc seem to treat string literals differently...
2014-11-06 10:02:27 +01:00
Arseny Kapoulkine
50bfdb1856 tests: Fix all tests for compact mode
Memory allocation behavior is different in compact mode so tests that rely
on current behavior have to be adjusted.
2014-11-06 09:59:07 +01:00
Arseny Kapoulkine
393cc28481 Add compact build configuration to Travis 2014-11-06 09:34:13 +01:00
Arseny Kapoulkine
56349939e4 Verify that compact page encoding is safe
Since page size can be customized let's do a special validation check for
compact encoding. Right now it's redundant since page size is limited by
64k in alloc_string, but that may change in the future.
2014-11-06 09:33:05 +01:00
Arseny Kapoulkine
224b9b7ba7 Add a separate storage class for PI nodes
This allows us to add pi value to restore target support for PI nodes without
increasing the memory usage for other nodes.

Right now the PI node has a separate header that's used for allocated bit;
this allows us to reduce header bitcount in the future.
2014-11-06 09:20:34 +01:00
Arseny Kapoulkine
f39a73f6e1 Fix gcc warnings in compact mode 2014-11-04 10:05:31 +01:00
Arseny Kapoulkine
b2a0ae13b6 Merge branch 'master' into compact 2014-11-04 09:58:04 +01:00
Arseny Kapoulkine
650c67a663 Fix compilation after merge. 2014-10-28 20:14:17 -07:00
Arseny Kapoulkine
a49f932b61 Merge branch 'master' into compact 2014-10-28 20:11:06 -07:00
Arseny Kapoulkine
21695288ec Fix compact mode 2014-10-21 23:32:44 -07:00
Arseny Kapoulkine
a55dfd3afa Merge branch 'master' into compact 2014-10-21 23:23:17 -07:00
Arseny Kapoulkine
457522a836 Merge branch 'master' into compact 2014-10-20 22:24:25 -07:00
Arseny Kapoulkine
d7ac5e2e0c Merge branch 'master' into compact 2014-10-20 20:34:28 -07:00
Arseny Kapoulkine
fcd1876a21 Fix compact mode for 64-bit architectures 2014-10-11 01:35:24 -07:00
Arseny Kapoulkine
52371bf5fe Compact implementation refactoring
Remove compact stats and tags, replace pointer hash with murmur3 32-bit
finalizer.
2014-10-11 00:55:39 -07:00
Arseny Kapoulkine
97451b2eee Merge branch 'master' into compact 2014-10-10 19:35:09 -07:00
Arseny Kapoulkine
7795f00fba tests: Reenable all tests for compact mode 2014-10-10 19:32:40 -07:00
Arseny Kapoulkine
e6dd761ca3 Split hash table operations into reserve and insert
Insert is now unsafe - since we don't have a way to handle rehash()
failures transparently we need to reserve space beforehand. Reserve is now
called before every tree-mutating operations and it guarantees that we
can perform 16 arbitrary pointer mutations after that.

This fixes all test crashes with compact mode.
2014-10-10 19:31:30 -07:00
Arseny Kapoulkine
fbaab4dcad Move compact_hash_table before xml_allocator.
This helps streamline class dependencies and will make subsequent changes
smaller.
2014-10-10 19:29:25 -07:00
Arseny Kapoulkine
89575f352a Merge branch 'master' into compact 2014-10-10 19:27:25 -07:00
Arseny Kapoulkine
224e702d1f Change compact_pointer_parent to use 2 bytes
Parent pointers need to be able to reach everywhere within a page to
minimize shared parent pointer reuse unless it's absolutely necessary.
This reduces parent hash utilization on all test cases to <1%.

Rename compact_parent to compact_shared_parent.
2014-10-09 08:45:35 -07:00
Arseny Kapoulkine
58282fd36f Optimize compact_pointer_parent
We now no longer need the compact_alignment type so replace it with a
constant.
2014-10-08 08:42:37 -07:00
Arseny Kapoulkine
80d6f5a7d0 Rework compact_pointer implementation
Split the implementation into a generic one with adjustable range and a
special implementation for parent (may need to use 2 bytes on that one
later).

Optimize compact_string and compact_pointer to use minimal amount of math
and move slow hash paths into no-inline functions so that compiler can
inline the fast-paths.

Merge compact_pointer_generic and compact_pointer_forward and optimize.
2014-10-07 21:14:38 -07:00
Arseny Kapoulkine
43622107d7 Remove PUGI__COMPACT helper
Also remove get() methods on pointer wrappers - this makes the surface
area smaller so we can create more of them easier.
2014-10-07 20:01:19 -07:00
Arseny Kapoulkine
edb57c96a8 Switch to a 3-byte representation for compact strings
To make this possible name and value in the node structure had to be
merged into one contents field. Not sure what to do with node_pi, since it
is the only type that required both.
2014-10-06 22:25:49 -07:00
Arseny Kapoulkine
5d7ec0a178 tests: Temporarily disable tests that are failing in compact mode 2014-10-05 23:58:41 -07:00
Arseny Kapoulkine
45a1b74335 Initial compact storage prototype
The storage uses one hash table for fallbacks and simple difference
encoding for node and string pointers.

This is a work in progress implementation - while node pointers seem to
work properly, string encoding is inefficient and parent pointers could
use more tuning.

No performance or compatibility work has been done either.
2014-10-05 23:58:02 -07:00
111 changed files with 14176 additions and 7393 deletions

7
.codecov.yml Normal file
View file

@ -0,0 +1,7 @@
comment: false
coverage:
status:
project:
default:
informational: true
patch: off

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
tests/data/* -text

8
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,8 @@
---
name: Bug report
about: Create a report if you believe you've found a bug in this project; please use GitHub Discussions instead if you think the bug may be in your code.
title: ''
labels: bug
assignees: ''
---

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Help and support
url: https://github.com/zeux/pugixml/discussions
about: Please use GitHub Discussions if you have questions or need help.

View file

@ -0,0 +1,8 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---

52
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,52 @@
name: build
on:
push:
branches:
- 'master'
pull_request:
jobs:
unix:
strategy:
matrix:
os: [ubuntu, macos]
compiler: [g++, clang++]
defines: [standard, PUGIXML_WCHAR_MODE, PUGIXML_COMPACT, PUGIXML_NO_EXCEPTIONS]
exclude:
- os: macos
compiler: g++
name: ${{matrix.os}} (${{matrix.compiler}}, ${{matrix.defines}})
runs-on: ${{matrix.os}}-latest
steps:
- uses: actions/checkout@v1
- name: make test
run: |
export CXX=${{matrix.compiler}}
make test cxxstd=c++11 defines=${{matrix.defines}} config=release -j2
make test cxxstd=c++98 defines=${{matrix.defines}} config=debug -j2
make test defines=${{matrix.defines}} config=sanitize -j2
- name: make coverage
if: ${{!(matrix.os == 'ubuntu' && matrix.compiler == 'clang++')}} # linux/clang produces coverage info gcov can't parse
run: |
export CXX=${{matrix.compiler}}
make test defines=${{matrix.defines}} config=coverage -j2
bash <(curl -s https://codecov.io/bash) -f pugixml.cpp.gcov -X search -t ${{secrets.CODECOV_TOKEN}} -B ${{github.ref}}
windows:
runs-on: windows-latest
strategy:
matrix:
arch: [Win32, x64]
defines: [standard, PUGIXML_WCHAR_MODE, PUGIXML_COMPACT, PUGIXML_NO_EXCEPTIONS]
steps:
- uses: actions/checkout@v1
- name: cmake configure
run: cmake . -DPUGIXML_BUILD_TESTS=ON -D${{matrix.defines}}=ON -A ${{matrix.arch}}
- name: cmake test
shell: bash # necessary for fail-fast
run: |
cmake --build . -- -property:Configuration=Debug -verbosity:minimal
Debug/pugixml-check.exe
cmake --build . -- -property:Configuration=Release -verbosity:minimal
Release/pugixml-check.exe

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/build/
/.vscode/

View file

@ -1,8 +0,0 @@
language: cpp
compiler:
- clang
- gcc
env:
- DEFINES=standard
- DEFINES=PUGIXML_WCHAR_MODE
script: make test defines=$DEFINES -j2

263
CMakeLists.txt Normal file
View file

@ -0,0 +1,263 @@
cmake_minimum_required(VERSION 3.4)
project(pugixml VERSION 1.13 LANGUAGES CXX)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(GNUInstallDirs)
include(CTest)
cmake_dependent_option(PUGIXML_USE_VERSIONED_LIBDIR
"Use a private subdirectory to install the headers and libraries" OFF
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
cmake_dependent_option(PUGIXML_USE_POSTFIX
"Use separate postfix for each configuration to make sure you can install multiple build outputs" OFF
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
cmake_dependent_option(PUGIXML_STATIC_CRT
"Use static MSVC RT libraries" OFF
"MSVC" OFF)
cmake_dependent_option(PUGIXML_BUILD_TESTS
"Build pugixml tests" OFF
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
# Custom build defines
set(PUGIXML_BUILD_DEFINES CACHE STRING "Build defines for custom options")
separate_arguments(PUGIXML_BUILD_DEFINES)
# Technically not needed for this file. This is builtin CMAKE global variable.
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
# Expose option to build PUGIXML as static as well when the global BUILD_SHARED_LIBS variable is set
cmake_dependent_option(PUGIXML_BUILD_SHARED_AND_STATIC_LIBS
"Build both shared and static libraries" OFF
"BUILD_SHARED_LIBS" OFF)
# Expose options from the pugiconfig.hpp
option(PUGIXML_WCHAR_MODE "Enable wchar_t mode" OFF)
option(PUGIXML_COMPACT "Enable compact mode" OFF)
# Advanced options from pugiconfig.hpp
option(PUGIXML_NO_XPATH "Disable XPath" OFF)
option(PUGIXML_NO_STL "Disable STL" OFF)
option(PUGIXML_NO_EXCEPTIONS "Disable Exceptions" OFF)
mark_as_advanced(PUGIXML_NO_XPATH PUGIXML_NO_STL PUGIXML_NO_EXCEPTIONS)
# Policy configuration
if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW) # Enables use of MSVC_RUNTIME_LIBRARY
endif()
set(PUGIXML_PUBLIC_DEFINITIONS
$<$<BOOL:${PUGIXML_WCHAR_MODE}>:PUGIXML_WCHAR_MODE>
$<$<BOOL:${PUGIXML_COMPACT}>:PUGIXML_COMPACT>
$<$<BOOL:${PUGIXML_NO_XPATH}>:PUGIXML_NO_XPATH>
$<$<BOOL:${PUGIXML_NO_STL}>:PUGIXML_NO_STL>
$<$<BOOL:${PUGIXML_NO_EXCEPTIONS}>:PUGIXML_NO_EXCEPTIONS>)
# This is used to backport a CMake 3.15 feature, but is also forwards compatible
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
set(CMAKE_MSVC_RUNTIME_LIBRARY
MultiThreaded$<$<CONFIG:Debug>:Debug>$<$<NOT:$<BOOL:${PUGIXML_STATIC_CRT}>>:DLL>)
endif()
if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
if (PUGIXML_USE_POSTFIX)
set(CMAKE_RELWITHDEBINFO_POSTFIX _r)
set(CMAKE_MINSIZEREL_POSTFIX _m)
set(CMAKE_DEBUG_POSTFIX _d)
endif()
if (CMAKE_VERSION VERSION_LESS 3.15)
set(msvc-rt $<TARGET_PROPERTY:MSVC_RUNTIME_LIBRARY>)
set(msvc-rt-mtd-shared $<STREQUAL:${msvc-rt},MultiThreadedDebugDLL>)
set(msvc-rt-mtd-static $<STREQUAL:${msvc-rt},MultiThreadedDebug>)
set(msvc-rt-mt-shared $<STREQUAL:${msvc-rt},MultiThreadedDLL>)
set(msvc-rt-mt-static $<STREQUAL:${msvc-rt},MultiThreaded>)
unset(msvc-rt)
set(msvc-rt-mtd-shared $<${msvc-rt-mtd-shared}:-MDd>)
set(msvc-rt-mtd-static $<${msvc-rt-mtd-static}:-MTd>)
set(msvc-rt-mt-shared $<${msvc-rt-mt-shared}:-MD>)
set(msvc-rt-mt-static $<${msvc-rt-mt-static}:-MT>)
endif()
set(versioned-dir $<$<BOOL:${PUGIXML_USE_VERSIONED_LIBDIR}>:/pugixml-${PROJECT_VERSION}>)
set(libs)
if (BUILD_SHARED_LIBS)
add_library(pugixml-shared SHARED
${PROJECT_SOURCE_DIR}/scripts/pugixml_dll.rc
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
add_library(pugixml::shared ALIAS pugixml-shared)
list(APPEND libs pugixml-shared)
string(CONCAT pugixml.msvc $<OR:
$<STREQUAL:${CMAKE_CXX_COMPILER_FRONTEND_VARIANT},MSVC>,
$<CXX_COMPILER_ID:MSVC>
>)
set_property(TARGET pugixml-shared PROPERTY EXPORT_NAME shared)
target_include_directories(pugixml-shared
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
target_compile_definitions(pugixml-shared
PUBLIC
${PUGIXML_BUILD_DEFINES}
${PUGIXML_PUBLIC_DEFINITIONS}
PRIVATE
PUGIXML_API=$<IF:${pugixml.msvc},__declspec\(dllexport\),__attribute__\(\(visibility\("default"\)\)\)>
)
target_compile_options(pugixml-shared
PRIVATE
${msvc-rt-mtd-shared}
${msvc-rt-mtd-static}
${msvc-rt-mt-shared}
${msvc-rt-mt-static})
endif()
if (NOT BUILD_SHARED_LIBS OR PUGIXML_BUILD_SHARED_AND_STATIC_LIBS)
add_library(pugixml-static STATIC
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
add_library(pugixml::static ALIAS pugixml-static)
list(APPEND libs pugixml-static)
set_property(TARGET pugixml-static PROPERTY EXPORT_NAME static)
target_include_directories(pugixml-static
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
target_compile_definitions(pugixml-static
PUBLIC
${PUGIXML_BUILD_DEFINES}
${PUGIXML_PUBLIC_DEFINITIONS})
target_compile_options(pugixml-static
PRIVATE
${msvc-rt-mtd-shared}
${msvc-rt-mtd-static}
${msvc-rt-mt-shared}
${msvc-rt-mt-static})
endif()
if (BUILD_SHARED_LIBS)
set(pugixml-alias pugixml-shared)
else()
set(pugixml-alias pugixml-static)
endif()
add_library(pugixml INTERFACE)
target_link_libraries(pugixml INTERFACE ${pugixml-alias})
add_library(pugixml::pugixml ALIAS pugixml)
set_target_properties(${libs}
PROPERTIES
MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY}
EXCLUDE_FROM_ALL ON
POSITION_INDEPENDENT_CODE ON
SOVERSION ${PROJECT_VERSION_MAJOR}
VERSION ${PROJECT_VERSION}
OUTPUT_NAME pugixml)
set_target_properties(${libs}
PROPERTIES
EXCLUDE_FROM_ALL OFF)
set(install-targets pugixml ${libs})
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/scripts/pugixml-config.cmake.in"
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}
NO_CHECK_REQUIRED_COMPONENTS_MACRO
NO_SET_AND_CHECK_MACRO)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/pugixml-config-version.cmake"
COMPATIBILITY SameMajorVersion)
if (PUGIXML_USE_POSTFIX)
if(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
set(LIB_POSTFIX ${CMAKE_RELWITHDEBINFO_POSTFIX})
elseif(CMAKE_BUILD_TYPE MATCHES MinSizeRel)
set(LIB_POSTFIX ${CMAKE_MINSIZEREL_POSTFIX})
elseif(CMAKE_BUILD_TYPE MATCHES Debug)
set(LIB_POSTFIX ${CMAKE_DEBUG_POSTFIX})
endif()
endif()
configure_file(scripts/pugixml.pc.in pugixml.pc @ONLY)
if (NOT DEFINED PUGIXML_RUNTIME_COMPONENT)
set(PUGIXML_RUNTIME_COMPONENT Runtime)
endif()
if (NOT DEFINED PUGIXML_LIBRARY_COMPONENT)
set(PUGIXML_LIBRARY_COMPONENT Library)
endif()
if (NOT DEFINED PUGIXML_DEVELOPMENT_COMPONENT)
set(PUGIXML_DEVELOPMENT_COMPONENT Development)
endif()
set(namelink-component)
if (NOT CMAKE_VERSION VERSION_LESS 3.12)
set(namelink-component NAMELINK_COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
endif()
install(TARGETS ${install-targets}
EXPORT pugixml-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${PUGIXML_RUNTIME_COMPONENT}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${PUGIXML_LIBRARY_COMPONENT} ${namelink-component}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir})
install(EXPORT pugixml-targets
NAMESPACE pugixml::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
export(EXPORT pugixml-targets
NAMESPACE pugixml::)
install(FILES
"${PROJECT_BINARY_DIR}/pugixml-config-version.cmake"
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
install(FILES ${PROJECT_BINARY_DIR}/pugixml.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
install(
FILES
"${PROJECT_SOURCE_DIR}/src/pugiconfig.hpp"
"${PROJECT_SOURCE_DIR}/src/pugixml.hpp"
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir} COMPONENT ${PUGIXML_DEVELOPMENT_COMPONENT})
if (PUGIXML_BUILD_TESTS)
set(fuzz-pattern "tests/fuzz_*.cpp")
set(test-pattern "tests/*.cpp")
if (CMAKE_VERSION VERSION_GREATER 3.11)
list(INSERT fuzz-pattern 0 CONFIGURE_DEPENDS)
list(INSERT test-pattern 0 CONFIGURE_DEPENDS)
endif()
file(GLOB test-sources ${test-pattern})
file(GLOB fuzz-sources ${fuzz-pattern})
list(REMOVE_ITEM test-sources ${fuzz-sources})
add_custom_target(check
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure)
add_executable(pugixml-check ${test-sources})
add_test(NAME pugixml::test
COMMAND pugixml-check
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_dependencies(check pugixml-check)
target_link_libraries(pugixml-check
PRIVATE
pugixml::pugixml)
endif()

View file

@ -1,169 +0,0 @@
# Latest jamplus is needed to use this
# Targets:
# pugixml - build pugixml library
# tests - build pugixml test suite
# run_tests - run pugixml test suite
# coverage - get test suite coverage
# Options:
# toolset=name - select toolset
# supported toolsets: mingw*, msvc*
# default toolset/configuration
if ( ! $(toolset) )
{
if ( $(OS) = SOLARIS )
{
toolset = suncc ;
}
else if ( $(UNIX) )
{
local GCCVERSION = [ Subst [ Shell "gcc -dumpversion" ] : $(NEWLINE) ] ;
toolset = "gcc"$(GCCVERSION) ;
}
else
{
toolset = msvc ;
}
}
if ( ! $(configuration) )
{
configuration = "debug" ;
}
if ( ! $(defines) )
{
defines = "PUGIXML_STANDARD" ;
}
# coverage options
if ( $(toolset:I=^mingw) || $(toolset:I=^gcc) )
{
CCFLAGS = -fprofile-arcs -ftest-coverage ;
LDFLAGS = -fprofile-arcs ;
if $(fullcoverage)
{
GCOVFLAGS = --branch-probabilities --function-summaries ;
}
else
{
GCOVFLAGS = --no-output ;
}
}
# build folder
BUILD = build ;
# enable dependency cache
DEPCACHE.standard = $(BUILD)/.depcache ;
# rules
include "Jamrules.jam" ;
# split define sets into list
local DEFINESETS = [ Split $(defines) : ':' ] ;
# split configurations into list
local CONFIGURATIONS = [ Split $(configuration) : ',' ] ;
for CONFIG in $(CONFIGURATIONS)
{
for DEFINESET in $(DEFINESETS)
{
local DEFINES = [ Split $(DEFINESET) : ',' ] ;
# build folder
local CFGBUILD = $(BUILD)/$(toolset)/$(DEFINES:J=_)/$(CONFIG) ;
# compilation options
local CFGFLAGS = $(CCFLAGS) [ GetCFlags $(CONFIG) : $(DEFINES) ] ;
# build library
local PUGIXML = $(CFGBUILD)/pugixml.lib ;
Library $(PUGIXML) : src/pugixml.cpp : $(CFGFLAGS) ;
Alias pugixml : $(PUGIXML) ;
# build tests
local TESTS = $(CFGBUILD)/tests.exe ;
local TEST_SOURCES = [ Glob tests : *.cpp ] ;
TEST_SOURCES -= [ Glob tests : fuzz_*.cpp ] ;
Application $(TESTS) : $(TEST_SOURCES) : $(CFGFLAGS) : $(PUGIXML) ;
Alias tests : $(TESTS) ;
# run tests
Test $(TESTS)_run : $(TESTS) ;
Alias run_tests : $(TESTS)_run ;
# gather coverage
Coverage $(TESTS)_coverage : $(PUGIXML) ;
Alias coverage : $(TESTS)_coverage ;
GCOVFLAGS on $(TESTS)_coverage = $(GCOVFLAGS) -o $(CFGBUILD)/src ; # because stupid gcov can't find files via relative paths
# add special autotest markers to build log
if $(autotest)
{
COVPREFIX on $(TESTS)_coverage = "... autotest $(CONFIG) [$(DEFINESET)]" ;
}
# gather coverage after tests run
Depends $(TESTS)_coverage : $(TESTS)_run ;
}
}
# documentation
Documentation docs/manual.html : docs/manual.qbk : docs/manual.xsl ;
Documentation docs/quickstart.html : docs/quickstart.qbk : docs/quickstart.xsl ;
Alias docs : docs/manual.html docs/quickstart.html ;
# samples
for SAMPLE in [ Glob docs/samples : *.cpp ]
{
local CONFIG = "debug" ;
local DEFINES = "PUGIXML_STANDARD" ;
# build folder
local CFGBUILD = $(BUILD)/$(toolset)/$(DEFINES:J=_)/$(CONFIG) ;
# compilation options
local CFGFLAGS = $(CCFLAGS) [ GetCFlags $(CONFIG) : $(DEFINES) ] ;
CFGFLAGS += -I src ;
# build and run sample
local EXECUTABLE = $(CFGBUILD)/samples/$(SAMPLE:B).exe ;
local PUGIXML = $(CFGBUILD)/pugixml.lib ;
Application $(EXECUTABLE) : $(SAMPLE) : $(CFGFLAGS) : $(PUGIXML) ;
RunSampleAction $(EXECUTABLE)_run : $(EXECUTABLE) ;
Depends $(EXECUTABLE)_run : $(EXECUTABLE) ;
Depends samples : $(EXECUTABLE)_run ;
}
# release
VERSION = 1.6 ;
RELEASE_FILES =
[ Glob contrib : *.cpp *.hpp ]
[ Glob src : *.cpp *.hpp ]
[ Glob docs : *.html *.css ]
[ Glob docs/samples : *.cpp *.hpp *.xml ]
[ Glob docs/images : *.png ]
[ Glob docs/manual : *.html ]
@("scripts/**":W=:X=svn)
readme.txt
;
actions ArchiveAction
{
perl tests/archive.pl $(<) $(>)
}
ArchiveAction pugixml-$(VERSION).zip : $(RELEASE_FILES) ;
ArchiveAction pugixml-$(VERSION).tar.gz : $(RELEASE_FILES) ;
Depends release : pugixml-$(VERSION).zip pugixml-$(VERSION).tar.gz : $(RELEASE_FILES) ;
NotFile release ;

File diff suppressed because it is too large Load diff

24
LICENSE.md Normal file
View file

@ -0,0 +1,24 @@
MIT License
Copyright (c) 2006-2022 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View file

@ -3,16 +3,18 @@ MAKEFLAGS+=-r
config=debug
defines=standard
cxxstd=c++11
# set cxxstd=any to disable use of -std=...
BUILD=build/make-$(CXX)-$(config)-$(defines)
BUILD=build/make-$(CXX)-$(config)-$(defines)-$(cxxstd)
SOURCES=src/pugixml.cpp $(filter-out tests/fuzz_%,$(wildcard tests/*.cpp))
EXECUTABLE=$(BUILD)/test
VERSION=$(shell sed -n 's/.*version \(.*\).*/\1/p' src/pugiconfig.hpp)
RELEASE=$(shell git ls-files src docs/*.html docs/*.css docs/samples docs/images scripts contrib readme.txt)
RELEASE=$(filter-out scripts/archive.py docs/%.adoc,$(shell git ls-files docs scripts src CMakeLists.txt LICENSE.md readme.txt))
CXXFLAGS=-g -Wall -Wextra -Werror -pedantic
CXXFLAGS=-g -Wall -Wextra -Werror -pedantic -Wundef -Wshadow -Wcast-align -Wcast-qual -Wold-style-cast -Wdouble-promotion
LDFLAGS=
ifeq ($(config),release)
@ -20,9 +22,17 @@ ifeq ($(config),release)
endif
ifeq ($(config),coverage)
CXXFLAGS+=-DNDEBUG
CXXFLAGS+=-fprofile-arcs -ftest-coverage
LDFLAGS+=-fprofile-arcs
CXXFLAGS+=-coverage
LDFLAGS+=-coverage
endif
ifeq ($(config),sanitize)
CXXFLAGS+=-fsanitize=address,undefined -fno-sanitize=float-divide-by-zero,float-cast-overflow -fno-sanitize-recover=all
LDFLAGS+=-fsanitize=address,undefined
endif
ifeq ($(config),analyze)
CXXFLAGS+=--analyze
endif
ifneq ($(defines),standard)
@ -30,25 +40,33 @@ ifneq ($(defines),standard)
CXXFLAGS+=-D $(subst $(COMMA), -D ,$(defines))
endif
ifneq ($(findstring PUGIXML_NO_EXCEPTIONS,$(defines)),)
CXXFLAGS+=-fno-exceptions
endif
ifneq ($(cxxstd),any)
CXXFLAGS+=-std=$(cxxstd)
endif
OBJECTS=$(SOURCES:%=$(BUILD)/%.o)
all: $(EXECUTABLE)
ifeq ($(config),coverage)
test: $(EXECUTABLE)
-@find $(BUILD) -name '*.gcda' | xargs rm
-@find $(BUILD) -name '*.gcda' -exec rm {} +
./$(EXECUTABLE)
@gcov -b -c $(BUILD)/src/pugixml.cpp.gcda | sed -e '/./{H;$!d;}' -e 'x;/pugixml.cpp/!d;'
@ls *.gcov | grep -v pugixml.cpp.gcov | xargs rm
@gcov -b -o $(BUILD)/src/ pugixml.cpp.gcda | sed -e '/./{H;$!d;}' -e 'x;/pugixml.cpp/!d;'
@find . -name '*.gcov' -and -not -name 'pugixml.cpp.gcov' -exec rm {} +
@sed -i -e "s/#####\(.*\)\(\/\/ unreachable.*\)/ 1\1\2/" pugixml.cpp.gcov
else
test: $(EXECUTABLE)
./$(EXECUTABLE)
endif
fuzz:
@mkdir -p $(BUILD)
$(AFL)/afl-clang++ tests/fuzz_parse.cpp tests/allocator.cpp src/pugixml.cpp $(CXXFLAGS) -o $(BUILD)/fuzz_parse
$(AFL)/afl-fuzz -i tests/data_fuzz_parse -o $(BUILD)/fuzz_parse_out -x $(AFL)/testcases/_extras/xml/ -- $(BUILD)/fuzz_parse @@
fuzz_%: $(BUILD)/fuzz_%
@mkdir -p build/$@
$< build/$@ tests/data_fuzz_$* -max_len=1024 -dict=tests/fuzz_$*.dict
clean:
rm -rf $(BUILD)
@ -58,11 +76,16 @@ release: build/pugixml-$(VERSION).tar.gz build/pugixml-$(VERSION).zip
docs: docs/quickstart.html docs/manual.html
build/pugixml-%: .FORCE | $(RELEASE)
perl tests/archive.pl $@ $|
@mkdir -p $(BUILD)
TIMESTAMP=`git show v$(VERSION) -s --format=%ct` && python3 scripts/archive.py $@ pugixml-$(VERSION) $$TIMESTAMP $|
$(EXECUTABLE): $(OBJECTS)
$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
$(BUILD)/fuzz_%: tests/fuzz_%.cpp src/pugixml.cpp
@mkdir -p $(BUILD)
$(CXX) $(CXXFLAGS) -fsanitize=address,fuzzer $^ -o $@
$(BUILD)/%.o: %
@mkdir -p $(dir $@)
$(CXX) $< $(CXXFLAGS) -c -MMD -MP -o $@

View file

@ -1,4 +1,4 @@
pugixml [![Build Status](https://travis-ci.org/zeux/pugixml.png?branch=master)](https://travis-ci.org/zeux/pugixml)
pugixml [![Actions Status](https://github.com/zeux/pugixml/workflows/build/badge.svg)](https://github.com/zeux/pugixml/actions) [![Build status](https://ci.appveyor.com/api/projects/status/9hdks1doqvq8pwe7/branch/master?svg=true)](https://ci.appveyor.com/project/zeux/pugixml) [![codecov.io](https://codecov.io/github/zeux/pugixml/coverage.svg?branch=master)](https://codecov.io/github/zeux/pugixml?branch=master) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg)
=======
pugixml is a C++ XML processing library, which consists of a DOM-like interface with rich traversal/modification
@ -12,33 +12,61 @@ 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](https://pugixml.org/docs/quickstart.html), that aims to provide enough information to start using the library;
* [Complete reference manual](https://pugixml.org/docs/manual.html), that describes all features of the library in detail.
Youre 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.
## Example
Here's an example of how code using pugixml looks; it opens an XML file, goes over all Tool nodes and prints tools that have a Timeout attribute greater than 0:
```c++
#include "pugixml.hpp"
#include <iostream>
int main()
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file("xgconsole.xml");
if (!result)
return -1;
for (pugi::xml_node tool: doc.child("Profile").child("Tools").children("Tool"))
{
int timeout = tool.attribute("Timeout").as_int();
if (timeout > 0)
std::cout << "Tool " << tool.attribute("Filename").value() << " has timeout " << timeout << "\n";
}
}
```
And the same example using XPath:
```c++
#include "pugixml.hpp"
#include <iostream>
int main()
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file("xgconsole.xml");
if (!result)
return -1;
pugi::xpath_node_set tools_with_timeout = doc.select_nodes("/Profile/Tools/Tool[@Timeout > 0]");
for (pugi::xpath_node node: tools_with_timeout)
{
pugi::xml_node tool = node.node();
std::cout << "Tool " << tool.attribute("Filename").value() <<
" has timeout " << tool.attribute("Timeout").as_int() << "\n";
}
}
```
## License
This library is available to anybody free of charge, under the terms of MIT License:
Copyright (c) 2006-2015 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
This library is available to anybody free of charge, under the terms of MIT License (see LICENSE.md).

9
SECURITY.md Normal file
View file

@ -0,0 +1,9 @@
# Security Policy
## Supported Versions
Please verify that the vulnerabilities reported can be reproduced on the [latest released version](https://github.com/zeux/pugixml/releases).
## Reporting a Vulnerability
Vulnerabilities can be reported via e-mail to the [project maintainer](https://github.com/zeux).

25
appveyor.yml Normal file
View file

@ -0,0 +1,25 @@
image:
- Visual Studio 2022
- Visual Studio 2019
- Visual Studio 2017
- Visual Studio 2015
version: "{branch}-{build}"
build_script:
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2013") { .\scripts\nuget_build.ps1 2013}
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\scripts\nuget_build.ps1 2015}
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") { .\scripts\nuget_build.ps1 2017}
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") { .\scripts\nuget_build.ps1 2019}
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2022") { .\scripts\nuget_build.ps1 2022}
test_script:
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { .\tests\autotest-appveyor.ps1 9 10 11 12 14 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") { .\tests\autotest-appveyor.ps1 15 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") { .\tests\autotest-appveyor.ps1 19 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2022") { .\tests\autotest-appveyor.ps1 22 }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { & C:\cygwin\bin\bash.exe -c "PATH=/usr/bin:/usr/local/bin:$PATH; make config=coverage test && bash <(curl -s https://codecov.io/bash) -f pugixml.cpp.gcov 2>&1" }
- ps: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { & C:\cygwin\bin\bash.exe -c "PATH=/usr/bin:/usr/local/bin:$PATH; make config=coverage defines=PUGIXML_WCHAR_MODE test && bash <(curl -s https://codecov.io/bash) -f pugixml.cpp.gcov 2>&1" }
artifacts:
- path: .\scripts\*.nupkg

View file

@ -1,63 +0,0 @@
/*
* Boost.Foreach support for pugixml classes.
* This file is provided to the public domain.
* Written by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
*/
#ifndef HEADER_PUGIXML_FOREACH_HPP
#define HEADER_PUGIXML_FOREACH_HPP
#include <boost/range/iterator.hpp>
#include "pugixml.hpp"
/*
* These types add support for BOOST_FOREACH macro to xml_node and xml_document classes (child iteration only).
* Example usage:
* BOOST_FOREACH(xml_node n, doc) {}
*/
namespace boost
{
template<> struct range_mutable_iterator<pugi::xml_node>
{
typedef pugi::xml_node::iterator type;
};
template<> struct range_const_iterator<pugi::xml_node>
{
typedef pugi::xml_node::iterator type;
};
template<> struct range_mutable_iterator<pugi::xml_document>
{
typedef pugi::xml_document::iterator type;
};
template<> struct range_const_iterator<pugi::xml_document>
{
typedef pugi::xml_document::iterator type;
};
}
/*
* These types add support for BOOST_FOREACH macro to xml_node and xml_document classes (child/attribute iteration).
* Example usage:
* BOOST_FOREACH(xml_node n, children(doc)) {}
* BOOST_FOREACH(xml_node n, attributes(doc)) {}
*/
namespace pugi
{
inline xml_object_range<xml_node_iterator> children(const pugi::xml_node& node)
{
return node.children();
}
inline xml_object_range<xml_attribute_iterator> attributes(const pugi::xml_node& node)
{
return node.attributes();
}
}
#endif

View file

@ -1,7 +1,7 @@
website <http://pugixml.org>; repository <http://github.com/zeux/pugixml>
website <https://pugixml.org>; repository <https://github.com/zeux/pugixml>
:toc: right
:source-highlighter: pygments
:source-language: c++
:sectanchors:
:sectlinks:
:imagesdir: images
:imagesdir: images

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8 KiB

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@ include::config.adoc[]
[[introduction]]
== Introduction
http://pugixml.org/[pugixml] is a light-weight C{plus}{plus} XML processing library. It consists of a DOM-like interface with rich traversal/modification capabilities, an extremely fast XML parser which constructs the DOM tree from an XML file/buffer, and an XPath 1.0 implementation for complex data-driven tree queries. Full Unicode support is also available, with two Unicode interface variants and conversions between different Unicode encodings (which happen automatically during parsing/saving). The library is extremely portable and easy to integrate and use. pugixml is developed and maintained since 2006 and has many users. All code is distributed under the <<license,MIT license>>, making it completely free to use in both open-source and proprietary applications.
https://pugixml.org/[pugixml] is a light-weight C{plus}{plus} XML processing library. It consists of a DOM-like interface with rich traversal/modification capabilities, an extremely fast XML parser which constructs the DOM tree from an XML file/buffer, and an XPath 1.0 implementation for complex data-driven tree queries. Full Unicode support is also available, with two Unicode interface variants and conversions between different Unicode encodings (which happen automatically during parsing/saving). The library is extremely portable and easy to integrate and use. pugixml is developed and maintained since 2006 and has many users. All code is distributed under the <<license,MIT license>>, making it completely free to use in both open-source and proprietary applications.
pugixml enables very fast, convenient and memory-efficient XML document processing. However, since pugixml has a DOM parser, it can't process XML documents that do not fit in memory; also the parser is a non-validating one, so if you need DTD/Schema validation, the library is not for you.
@ -24,8 +24,8 @@ https://github.com/zeux/pugixml/releases/download/v{version}/pugixml-{version}.t
The distribution contains library source, documentation (the guide you're reading now and the manual) and some code examples. After downloading the distribution, install pugixml by extracting all files from the compressed archive.
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. 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 <xml/thirdparty/pugixml/src/pugixml.hpp>`).
The easiest way to build pugixml is to compile the source file, `pugixml.cpp`, along with the existing library/executable. This process depends on the method of building your application; for example, if you're using Microsoft Visual Studio footnote:[All trademarks used are properties of their respective owners.], Apple Xcode, Code::Blocks or any other IDE, just add `pugixml.cpp` to one of your projects. There are other building methods available, including building pugixml as a standalone static/shared library; link:manual/install.html#install.building[read the manual] for further information.
The easiest way to build pugixml is to compile the source file, `pugixml.cpp`, along with the existing library/executable. This process depends on the method of building your application; for example, if you're using Microsoft Visual Studio footnote:[All trademarks used are properties of their respective owners.], Apple Xcode, Code::Blocks or any other IDE, just *add `pugixml.cpp` to one of your projects*. There are other building methods available, including building pugixml as a standalone static/shared library; link:manual.html#install.building[read the manual] for further information.
[[dom]]
== Document object model
@ -54,7 +54,7 @@ There is a special value of `xml_node` type, known as null node or empty node. I
`xml_attribute` is the handle to an XML attribute; it has the same semantics as `xml_node`, i.e. there can be several `xml_attribute` handles pointing to the same underlying object and there is a special null attribute value, which propagates to function results.
There are two choices of interface and internal representation when configuring pugixml: you can either choose the UTF-8 (also called char) interface or UTF-16/32 (also called wchar_t) one. The choice is controlled via `PUGIXML_WCHAR_MODE` define; you can set it via `pugiconfig.hpp` or via preprocessor options. All tree functions that work with strings work with either C-style null terminated strings or STL strings of the selected character type. link:manual/dom.html#dom.unicode[Read the manual] for additional information on Unicode interface.
There are two choices of interface and internal representation when configuring pugixml: you can either choose the UTF-8 (also called char) interface or UTF-16/32 (also called wchar_t) one. The choice is controlled via `PUGIXML_WCHAR_MODE` define; you can set it via `pugiconfig.hpp` or via preprocessor options. All tree functions that work with strings work with either C-style null terminated strings or STL strings of the selected character type. link:manual.html#dom.unicode[Read the manual] for additional information on Unicode interface.
[[loading]]
== Loading document
@ -67,7 +67,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]
----
`load_file`, as well as other loading functions, destroys the existing document tree and then tries to load the new tree from the specified file. The result of the operation is returned in an `xml_parse_result` object; this object contains the operation status, and the related information (i.e. last successfully parsed position in the input file, if parsing fails).
@ -78,7 +78,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]
----
Sometimes XML data should be loaded from some other source than file, i.e. HTTP URL; also you may want to load XML data from file using non-standard functions, i.e. to use your virtual file system facilities or to load XML from gzip-compressed files. These scenarios either require loading document from memory, in which case you should prepare a contiguous memory block with all XML data and to pass it to one of buffer loading functions, or loading document from C{plus}{plus} IOstream, in which case you should provide an object which implements `std::istream` or `std::wistream` interface.
@ -240,7 +240,7 @@ This is a simple example of custom writer for saving document data to STL string
include::samples/save_custom_writer.cpp[tags=code]
----
While the previously described functions save the whole document to the destination, it is easy to save a single subtree. Instead of calling `xml_document::save`, just call `xml_node::print` function on the target node. You can save node contents to C{plus}{plus} IOstream object or custom writer in this way. Saving a subtree slightly differs from saving the whole document; link:manual/saving.html#saving.subtree[read the manual] for more information.
While the previously described functions save the whole document to the destination, it is easy to save a single subtree. Instead of calling `xml_document::save`, just call `xml_node::print` function on the target node. You can save node contents to C{plus}{plus} IOstream object or custom writer in this way. Saving a subtree slightly differs from saving the whole document; link:manual.html#saving.subtree[read the manual] for more information.
[[feedback]]
== Feedback
@ -255,7 +255,7 @@ If filing an issue is not possible due to privacy or other concerns, you can con
The pugixml library is distributed under the MIT license:
....
Copyright (c) 2006-2015 Arseny Kapoulkine
Copyright (c) 2006-2022 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@ -280,8 +280,8 @@ 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 (https://pugixml.org).
pugixml is Copyright (C) 2006-2022 Arseny Kapoulkine.
....
This software is based on pugixml library (http://pugixml.org).
pugixml is Copyright (C) 2006-2015 Arseny Kapoulkine.
....

File diff suppressed because it is too large Load diff

View file

@ -48,7 +48,7 @@ bool preprocess(pugi::xml_node node)
bool load_preprocess(pugi::xml_document& doc, const char* path)
{
pugi::xml_parse_result result = doc.load_file(path, pugi::parse_default | pugi::parse_pi); // for <?include?>
return result ? preprocess(doc) : false;
}
// end::code[]

View file

@ -15,7 +15,7 @@ int main()
decl.append_attribute("encoding") = "UTF-8";
decl.append_attribute("standalone") = "no";
// <?xml version="1.0" encoding="UTF-8" standalone="no"?>
// <?xml version="1.0" encoding="UTF-8" standalone="no"?>
// <foo bar="baz">
// <call>hey</call>
// </foo>

View file

@ -1,7 +1,7 @@
pugixml 1.6 - an XML processing library
pugixml 1.13 - an XML processing library
Copyright (C) 2006-2015, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
Report bugs and download new versions at http://pugixml.org/
Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
Report bugs and download new versions at https://pugixml.org/
This is the distribution of pugixml, which is a C++ XML processing library,
which consists of a DOM-like interface with rich traversal/modification
@ -13,8 +13,6 @@ automatically during parsing/saving).
The distribution contains the following folders:
contrib/ - various contributions to pugixml
docs/ - documentation
docs/samples - pugixml usage examples
docs/quickstart.html - quick start guide
@ -28,7 +26,7 @@ The distribution contains the following folders:
This library is distributed under the MIT License:
Copyright (c) 2006-2015 Arseny Kapoulkine
Copyright (c) 2006-2022 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation

View file

@ -1,34 +0,0 @@
project(pugixml)
cmake_minimum_required(VERSION 2.6)
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
set(BUILD_DEFINES "" CACHE STRING "Build defines")
# Pre-defines standard install locations on *nix systems.
include(GNUInstallDirs)
mark_as_advanced(CLEAR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR)
set(HEADERS ../src/pugixml.hpp ../src/pugiconfig.hpp)
set(SOURCES ${HEADERS} ../src/pugixml.cpp)
if(DEFINED BUILD_DEFINES)
add_definitions(${BUILD_DEFINES})
endif()
if(BUILD_SHARED_LIBS)
add_library(pugixml SHARED ${SOURCES})
else()
add_library(pugixml STATIC ${SOURCES})
endif()
set_target_properties(pugixml PROPERTIES VERSION 1.6 SOVERSION 1)
install(TARGETS pugixml EXPORT pugixml-config
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(EXPORT pugixml-config DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml)

54
scripts/archive.py Normal file
View file

@ -0,0 +1,54 @@
import io
import os.path
import sys
import tarfile
import time
import zipfile
def read_file(path, use_crlf):
with open(path, 'rb') as file:
data = file.read()
if b'\0' not in data:
data = data.replace(b'\r', b'')
if use_crlf:
data = data.replace(b'\n', b'\r\n')
return data
def write_zip(target, arcprefix, timestamp, sources):
with zipfile.ZipFile(target, 'w') as archive:
for source in sorted(sources):
data = read_file(source, use_crlf = True)
path = os.path.join(arcprefix, source)
info = zipfile.ZipInfo(path)
info.date_time = time.localtime(timestamp)
info.compress_type = zipfile.ZIP_DEFLATED
info.external_attr = 0o644 << 16
archive.writestr(info, data)
def write_tar(target, arcprefix, timestamp, sources, compression):
with tarfile.open(target, 'w:' + compression) as archive:
for source in sorted(sources):
data = read_file(source, use_crlf = False)
path = os.path.join(arcprefix, source)
info = tarfile.TarInfo(path)
info.size = len(data)
info.mtime = timestamp
archive.addfile(info, io.BytesIO(data))
if len(sys.argv) < 5:
raise RuntimeError('Usage: python archive.py <target> <archive prefix> <timestamp> <source files>')
target, arcprefix, timestamp = sys.argv[1:4]
sources = sys.argv[4:]
# tarfile._Stream._init_write_gz always writes current time to gzip header
time.time = lambda: timestamp
if target.endswith('.zip'):
write_zip(target, arcprefix, int(timestamp), sources)
elif target.endswith('.tar.gz') or target.endswith('.tar.bz2'):
write_tar(target, arcprefix, int(timestamp), sources, compression = os.path.splitext(target)[1][1:])
else:
raise NotImplementedError('File type not supported: ' + target)

4
scripts/cocoapods_push.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
#Push to igagis repo for now
pod repo push igagis pugixml.podspec --use-libraries --verbose

View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="pugi::xml_node">
<DisplayString Condition="_root">{_root}</DisplayString>
<DisplayString Condition="!_root">none</DisplayString>
<Expand>
<ExpandedItem Condition="_root">_root</ExpandedItem>
</Expand>
</Type>
<Type Name="pugi::xml_node_struct">
<DisplayString Condition="name &amp;&amp; value">{(pugi::xml_node_type)(header &amp; 0xf),en} name={name,na} value={value,na}</DisplayString>
<DisplayString Condition="name">{(pugi::xml_node_type)(header &amp; 0xf),en} name={name,na}</DisplayString>
<DisplayString Condition="value">{(pugi::xml_node_type)(header &amp; 0xf),en} value={value,na}</DisplayString>
<DisplayString>{(pugi::xml_node_type)(header &amp; 0xf),en}</DisplayString>
<Expand>
<Item Name="value" Condition="value">value,na</Item>
<Synthetic Name="attributes" Condition="first_attribute">
<Expand>
<CustomListItems>
<Variable Name="curr" InitialValue="first_attribute" />
<Loop Condition="curr">
<Item Name="{curr->name,na}">curr,view(child)na</Item>
<Exec>curr = curr->next_attribute</Exec>
</Loop>
</CustomListItems>
</Expand>
</Synthetic>
<LinkedListItems>
<HeadPointer>first_child</HeadPointer>
<NextPointer>next_sibling</NextPointer>
<ValueNode>this,na</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="pugi::xml_attribute">
<DisplayString Condition="_attr">{_attr}</DisplayString>
<DisplayString Condition="!_attr">none</DisplayString>
<Expand>
<ExpandedItem Condition="_attr">_attr</ExpandedItem>
</Expand>
</Type>
<Type Name="pugi::xml_attribute_struct">
<DisplayString ExcludeView="child">{name,na} = {value,na}</DisplayString>
<DisplayString>{value,na}</DisplayString>
<Expand>
<Item Name="name">name,na</Item>
<Item Name="value">value,na</Item>
</Expand>
</Type>
<Type Name="pugi::xpath_node">
<DisplayString Condition="_node._root &amp;&amp; _attribute._attr">{_node,na} "{_attribute._attr->name,na}"="{_attribute._attr->value,na}"</DisplayString>
<DisplayString Condition="_node._root">{_node,na}</DisplayString>
<DisplayString Condition="_attribute._attr">{_attribute}</DisplayString>
<DisplayString>empty</DisplayString>
<Expand HideRawView="1">
<ExpandedItem Condition="_node._root &amp;&amp; !_attribute._attr">_node</ExpandedItem>
<ExpandedItem Condition="!_node._root &amp;&amp; _attribute._attr">_attribute</ExpandedItem>
<Item Name="node" Condition="_node._root &amp;&amp; _attribute._attr">_node,na</Item>
<Item Name="attribute" Condition="_node._root &amp;&amp; _attribute._attr">_attribute,na</Item>
</Expand>
</Type>
<Type Name="pugi::xpath_node_set">
<Expand>
<Item Name="type">_type</Item>
<ArrayItems>
<Size>_end - _begin</Size>
<ValuePointer>_begin</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer>

View file

@ -0,0 +1,506 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="pugi::xml_node">
<DisplayString Condition="_root">{_root}</DisplayString>
<DisplayString Condition="!_root">none</DisplayString>
<Expand>
<ExpandedItem Condition="_root">_root</ExpandedItem>
</Expand>
</Type>
<Type Name="pugi::xml_attribute">
<DisplayString Condition="_attr">{_attr}</DisplayString>
<DisplayString Condition="!_attr">none</DisplayString>
<Expand>
<ExpandedItem Condition="_attr">_attr</ExpandedItem>
</Expand>
</Type>
<Type Name="pugi::xml_node_struct">
<Expand>
<Item Name="type">(pugi::xml_node_type)(header._flags &amp; 15)</Item>
<Item Name="name" Condition="name._data">name,na</Item>
<Item Name="value" Condition="value._data">value,na</Item>
<Synthetic Name="attributes" Condition="first_attribute._data">
<DisplayString>...</DisplayString>
<Expand>
<CustomListItems>
<Variable Name="attribute_this" InitialValue="(size_t)&amp;first_attribute" />
<Variable Name="attribute_data" InitialValue="first_attribute._data" />
<Variable Name="attribute_data_copy" InitialValue="attribute_data" />
<!-- first_attribute struct template arguments -->
<Variable Name="attribute_T1" InitialValue="11" />
<Variable Name="attribute_T2" InitialValue="0" />
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<!-- compact_get_page() -->
<Variable Name="_page" InitialValue="*(char*)(attribute_this - attribute_T1)" />
<Variable Name="page" InitialValue="((attribute_this - attribute_T1 - (_page &lt;&lt; compact_alignment_log2)) - *(unsigned*)(attribute_this - attribute_T1 - (_page &lt;&lt; compact_alignment_log2)))" />
<!-- page->allocator->_hash -->
<Variable Name="allocator" InitialValue="*(size_t*)page" />
<Variable Name="_hash" InitialValue="*(size_t*)(allocator + 2 * sizeof(size_t))" /><!--2 pointer offsetof(allocator, _hash)-->
<Variable Name="_items" InitialValue="*(size_t*)_hash" />
<Variable Name="_capacity" InitialValue="*((size_t*)_hash + 1)" /><!--1 pointer offsetof(_hash, _capacity)-->
<Variable Name="_count" InitialValue="*((size_t*)_hash + 2)" /><!--2 pointer offsetof(_hash, _count)-->
<!-- find() prolog -->
<Variable Name="hashmod" InitialValue="_capacity - 1" />
<Variable Name="h" InitialValue="(unsigned)attribute_this" />
<Variable Name="bucket" InitialValue="0" />
<Variable Name="probe" InitialValue="0" />
<Variable Name="probe_item" InitialValue="(size_t*)0" />
<Variable Name="attribute_real" InitialValue="(pugi::xml_attribute_struct*)0" />
<!-- if _data < 255 -->
<Variable Name="attribute_short" InitialValue="(pugi::xml_attribute_struct*)(((size_t)attribute_this &amp; ~(compact_alignment - 1)) + (attribute_data - 1 + attribute_T2) * compact_alignment)" />
<Variable Name="number" InitialValue="0" />
<!-- Loop over all attributes -->
<Loop Condition="attribute_this &amp;&amp; attribute_data">
<!-- find() hash -->
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>h = h * (0x85ebca6bu)</Exec>
<Exec>h = h ^ (h >> 13)</Exec>
<Exec>h = h * (0xc2b2ae35u)</Exec>
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>bucket = h &amp; hashmod</Exec>
<!-- find() loop -->
<Loop Condition="probe &lt;= hashmod &amp;&amp;_capacity">
<Exec>probe_item = (size_t*)_items + bucket * 2</Exec><!--2 pointer sizeof(item_t)-->
<If Condition="*probe_item == attribute_this || *probe_item == 0">
<Exec>attribute_real = *(pugi::xml_attribute_struct**)(probe_item + 1)</Exec><!--1 pointer offsetof(item_t, value)-->
<Break/>
</If>
<Exec>bucket = (bucket + probe + 1) &amp; hashmod</Exec>
<Exec>probe++</Exec>
</Loop>
<Exec>attribute_data_copy = attribute_data</Exec>
<If Condition="attribute_data_copy &gt;= 255 &amp;&amp; attribute_real">
<Item Name="[{number}]">*attribute_real,view(child)</Item>
<Exec>attribute_this = (size_t)&amp;(*attribute_real).next_attribute</Exec>
<Exec>attribute_data = (*attribute_real).next_attribute._data</Exec>
</If>
<If Condition="attribute_data_copy &lt; 255 &amp;&amp; attribute_short">
<Item Name="[{number}]">*attribute_short,view(child)</Item>
<Exec>attribute_this = (size_t)&amp;(*attribute_short).next_attribute</Exec>
<Exec>attribute_data = (*attribute_short).next_attribute._data</Exec>
</If>
<!-- next_attribute struct template arguments -->
<Exec>attribute_T1 = 7</Exec>
<Exec>attribute_T2 = 0</Exec>
<!-- find() prolog again -->
<Exec>h = (unsigned)attribute_this</Exec>
<Exec>bucket = 0</Exec>
<Exec>probe = 0</Exec>
<Exec>probe_item = (size_t*)0</Exec>
<Exec>attribute_real = (pugi::xml_attribute_struct*)0</Exec>
<Exec>attribute_short = (pugi::xml_attribute_struct*)(((size_t)attribute_this &amp; ~(compact_alignment - 1)) + (attribute_data - 1 + attribute_T2) * compact_alignment)</Exec>
<Exec>number++</Exec>
</Loop>
</CustomListItems>
</Expand>
</Synthetic>
<CustomListItems>
<Variable Name="child_this" InitialValue="&amp;first_child" />
<Variable Name="child_data" InitialValue="first_child._data" />
<Variable Name="child_data_copy" InitialValue="child_data" />
<!-- first_child struct template arguments -->
<Variable Name="child_T1" InitialValue="8" />
<Variable Name="child_T2" InitialValue="0" />
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<!-- compact_get_page() -->
<Variable Name="_page" InitialValue="*(char*)(child_this - child_T1)" />
<Variable Name="page" InitialValue="((child_this - child_T1 - (_page &lt;&lt; compact_alignment_log2)) - *(unsigned*)(child_this - child_T1 - (_page &lt;&lt; compact_alignment_log2)))" />
<!-- page->allocator->_hash -->
<Variable Name="allocator" InitialValue="*(size_t*)page" />
<Variable Name="_hash" InitialValue="*(size_t*)(allocator + 2 * sizeof(size_t))" /><!--2 pointer offsetof(allocator, _hash)-->
<Variable Name="_items" InitialValue="*(size_t*)_hash" />
<Variable Name="_capacity" InitialValue="*((size_t*)_hash + 1)" /><!--1 pointer offsetof(_hash, _capacity)-->
<Variable Name="_count" InitialValue="*((size_t*)_hash + 2)" /><!--2 pointer offsetof(_hash, _count)-->
<!-- find() prolog -->
<Variable Name="hashmod" InitialValue="_capacity - 1" />
<Variable Name="h" InitialValue="(unsigned)child_this" />
<Variable Name="bucket" InitialValue="0" />
<Variable Name="probe" InitialValue="0" />
<Variable Name="probe_item" InitialValue="(size_t*)0" />
<Variable Name="child_real" InitialValue="(pugi::xml_node_struct*)0" />
<!-- if _data < 255 -->
<Variable Name="child_short" InitialValue="(pugi::xml_node_struct*)(((size_t)child_this &amp; ~(compact_alignment - 1)) + (child_data - 1 + child_T2) * compact_alignment)" />
<Variable Name="number" InitialValue="0" />
<Loop Condition="child_this &amp;&amp; child_data">
<!-- find() hash -->
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>h = h * (0x85ebca6bu)</Exec>
<Exec>h = h ^ (h >> 13)</Exec>
<Exec>h = h * (0xc2b2ae35u)</Exec>
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>bucket = h &amp; hashmod</Exec>
<!-- find() loop -->
<Loop Condition="probe &lt;= hashmod &amp;&amp;_capacity">
<Exec>probe_item = (size_t*)_items + bucket * 2</Exec><!--2 pointer sizeof(item_t)-->
<If Condition="*probe_item == child_this || *probe_item == 0">
<Exec>child_real = *(pugi::xml_node_struct**)(probe_item + 1)</Exec><!--1 pointer offsetof(item_t, value)-->
<Break/>
</If>
<Exec>bucket = (bucket + probe + 1) &amp; hashmod</Exec>
<Exec>probe++</Exec>
</Loop>
<Exec>child_data_copy = child_data</Exec>
<If Condition="child_data_copy &gt;= 255 &amp;&amp; child_real">
<Item Name="[{number}]">*child_real,view(child)</Item>
<Exec>child_this = (size_t)&amp;(*child_real).next_sibling</Exec>
<Exec>child_data = (*child_real).next_sibling._data</Exec>
</If>
<If Condition="child_data_copy &lt; 255 &amp;&amp; child_short">
<Item Name="[{number}]">*child_short,view(child)</Item>
<Exec>child_this = (size_t)&amp;(*child_short).next_sibling</Exec>
<Exec>child_data = (*child_short).next_sibling._data</Exec>
</If>
<!-- next_sibling struct template arguments -->
<Exec>child_T1 = 10</Exec>
<Exec>child_T2 = 0</Exec>
<!-- find() prolog again -->
<Exec>h = (unsigned)child_this</Exec>
<Exec>bucket = 0</Exec>
<Exec>probe = 0</Exec>
<Exec>probe_item = (size_t*)0</Exec>
<Exec>child_real = (pugi::xml_node_struct*)0</Exec>
<Exec>child_short = (pugi::xml_node_struct*)(((size_t)child_this &amp; ~(compact_alignment - 1)) + (child_data - 1 + child_T2) * compact_alignment)</Exec>
<Exec>number++</Exec>
</Loop>
</CustomListItems>
<Item Name="next_sibling" ExcludeView="child">next_sibling</Item>
</Expand>
</Type>
<Type Name="pugi::xml_attribute_struct">
<Expand>
<Item Name="name">name,na</Item>
<Item Name="value">value,na</Item>
<CustomListItems ExcludeView="child">
<Variable Name="attribute_this" InitialValue="&amp;next_attribute" />
<Variable Name="attribute_data" InitialValue="next_attribute._data" />
<!-- next_attribute struct template arguments -->
<Variable Name="attribute_T1" InitialValue="7" />
<Variable Name="attribute_T2" InitialValue="0" />
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<!-- compact_get_page() -->
<Variable Name="_page" InitialValue="*(char*)(attribute_this - attribute_T1)" />
<Variable Name="page" InitialValue="((attribute_this - attribute_T1 - (_page &lt;&lt; compact_alignment_log2)) - *(unsigned*)(attribute_this - attribute_T1 - (_page &lt;&lt; compact_alignment_log2)))" />
<!-- page->allocator->_hash -->
<Variable Name="allocator" InitialValue="*(size_t*)page" />
<Variable Name="_hash" InitialValue="*(size_t*)(allocator + 2 * sizeof(size_t))" /><!--2 pointer offsetof(allocator, _hash)-->
<Variable Name="_items" InitialValue="*(size_t*)_hash" />
<Variable Name="_capacity" InitialValue="*((size_t*)_hash + 1)" /><!--1 pointer offsetof(_hash, _capacity)-->
<Variable Name="_count" InitialValue="*((size_t*)_hash + 2)" /><!--2 pointer offsetof(_hash, _count)-->
<!-- find() prolog -->
<Variable Name="hashmod" InitialValue="_capacity - 1" />
<Variable Name="h" InitialValue="(unsigned)attribute_this" />
<Variable Name="bucket" InitialValue="0" />
<Variable Name="probe" InitialValue="0" />
<Variable Name="probe_item" InitialValue="(size_t*)0" />
<Variable Name="attribute_real" InitialValue="(pugi::xml_attribute_struct*)0" />
<!-- if _data < 255 -->
<Variable Name="attribute_short" InitialValue="(pugi::xml_attribute_struct*)(((size_t)attribute_this &amp; ~(compact_alignment - 1)) + (attribute_data - 1 + attribute_T2) * compact_alignment)" />
<!-- find() hash -->
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>h = h * (0x85ebca6bu)</Exec>
<Exec>h = h ^ (h >> 13)</Exec>
<Exec>h = h * (0xc2b2ae35u)</Exec>
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>bucket = h &amp; hashmod</Exec>
<!-- find() loop -->
<Loop Condition="probe &lt;= hashmod &amp;&amp;_capacity">
<Exec>probe_item = (size_t*)_items + bucket * 2</Exec><!--2 pointer sizeof(item_t)-->
<If Condition="*probe_item == attribute_this || *probe_item == 0">
<Exec>attribute_real = *(pugi::xml_attribute_struct**)(probe_item + 1)</Exec><!--1 pointer offsetof(item_t, value)-->
<Break/>
</If>
<Exec>bucket = (bucket + probe + 1) &amp; hashmod</Exec>
<Exec>probe++</Exec>
</Loop>
<If Condition="attribute_data &gt;= 255 &amp;&amp; attribute_real">
<Item Name="next_attribute">*attribute_real</Item>
</If>
<If Condition="attribute_data != 0 &amp;&amp; attribute_data &lt; 255 &amp;&amp; attribute_short">
<Item Name="next_attribute">*attribute_short</Item>
</If>
</CustomListItems>
</Expand>
</Type>
<Type Name="pugi::impl::`anonymous-namespace'::compact_string&lt;*,*&gt;">
<Expand HideRawView="1">
<CustomListItems Condition="_data &amp;&amp; _data &lt; 255">
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<!-- compact_get_page() -->
<Variable Name="_page" InitialValue="*(char*)(this - $T1)" />
<Variable Name="page" InitialValue="((this - $T1 - (_page &lt;&lt; compact_alignment_log2)) - *(unsigned*)(this - $T1 - (_page &lt;&lt; compact_alignment_log2)))" />
<Variable Name="compact_string_base" InitialValue="*(size_t*)(page + 5 * sizeof(void*))" /><!-- 5 pointer offsetof(page, compact_string_base)-->
<Variable Name="base" InitialValue="this - $T2" />
<Variable Name="offset" InitialValue="((*(short*)base - 1) &lt;&lt; 7) + (_data - 1)" />
<Item Name="value">(pugi::char_t*)(compact_string_base + offset * sizeof(pugi::char_t)),na</Item>
</CustomListItems>
<CustomListItems Condition="_data &amp;&amp; _data &gt;= 255">
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<!-- compact_get_page() -->
<Variable Name="_page" InitialValue="*(char*)(this - $T1)" />
<Variable Name="page" InitialValue="((this - $T1 - (_page &lt;&lt; compact_alignment_log2)) - *(unsigned*)(this - $T1 - (_page &lt;&lt; compact_alignment_log2)))" />
<!-- page->allocator->_hash -->
<Variable Name="allocator" InitialValue="*(size_t*)page" />
<Variable Name="_hash" InitialValue="*(size_t*)(allocator + 2 * sizeof(size_t))" /><!--2 pointer offsetof(allocator, _hash)-->
<Variable Name="_items" InitialValue="*(size_t*)_hash" />
<Variable Name="_capacity" InitialValue="*((size_t*)_hash + 1)" /><!--1 pointer offsetof(_hash, _capacity)-->
<Variable Name="_count" InitialValue="*((size_t*)_hash + 2)" /><!--2 pointer offsetof(_hash, _count)-->
<!-- find() prolog -->
<Variable Name="hashmod" InitialValue="_capacity - 1" />
<Variable Name="h" InitialValue="(unsigned)this" />
<Variable Name="bucket" InitialValue="0" />
<Variable Name="probe" InitialValue="0" />
<Variable Name="probe_item" InitialValue="(size_t*)0" />
<!-- find() hash -->
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>h = h * (0x85ebca6bu)</Exec>
<Exec>h = h ^ (h >> 13)</Exec>
<Exec>h = h * (0xc2b2ae35u)</Exec>
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>bucket = h &amp; hashmod</Exec>
<!-- find() loop -->
<Loop Condition="probe &lt;= hashmod &amp;&amp;_capacity">
<Exec>probe_item = (size_t*)_items + bucket * 2</Exec><!--2 pointer sizeof(item_t)-->
<If Condition="*probe_item == this || *probe_item == 0">
<Item Name="value">*(pugi::char_t**)(probe_item + 1)</Item><!--1 pointer offsetof(item_t, value)-->
<Break/>
</If>
<Exec>bucket = (bucket + probe + 1) &amp; hashmod</Exec>
<Exec>probe++</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
<Type Name="pugi::impl::`anonymous-namespace'::compact_pointer&lt;pugi::xml_node_struct,*,*&gt;">
<DisplayString Condition="!_data">nullptr</DisplayString>
<DisplayString Condition="_data">...</DisplayString>
<Expand HideRawView="1">
<CustomListItems Condition="_data &amp;&amp; _data &lt; 255">
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<Item Name="value">*(pugi::xml_node_struct*)(((size_t)this &amp; ~(compact_alignment - 1)) + (_data - 1 + $T2) * compact_alignment)</Item>
</CustomListItems>
<CustomListItems Condition="_data &amp;&amp; _data &gt;= 255">
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<!-- compact_get_page() -->
<Variable Name="_page" InitialValue="*(char*)(this - $T1)" />
<Variable Name="page" InitialValue="((this - $T1 - (_page &lt;&lt; compact_alignment_log2)) - *(unsigned*)(this - $T1 - (_page &lt;&lt; compact_alignment_log2)))" />
<!-- page->allocator->_hash -->
<Variable Name="allocator" InitialValue="*(size_t*)page" />
<Variable Name="_hash" InitialValue="*(size_t*)(allocator + 2 * sizeof(size_t))" /><!--2 pointer offsetof(allocator, _hash)-->
<Variable Name="_items" InitialValue="*(size_t*)_hash" />
<Variable Name="_capacity" InitialValue="*((size_t*)_hash + 1)" /><!--1 pointer offsetof(_hash, _capacity)-->
<Variable Name="_count" InitialValue="*((size_t*)_hash + 2)" /><!--2 pointer offsetof(_hash, _count)-->
<!-- find() prolog -->
<Variable Name="hashmod" InitialValue="_capacity - 1" />
<Variable Name="h" InitialValue="(unsigned)this" />
<Variable Name="bucket" InitialValue="0" />
<Variable Name="probe" InitialValue="0" />
<Variable Name="probe_item" InitialValue="(size_t*)0" />
<!-- find() hash -->
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>h = h * (0x85ebca6bu)</Exec>
<Exec>h = h ^ (h >> 13)</Exec>
<Exec>h = h * (0xc2b2ae35u)</Exec>
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>bucket = h &amp; hashmod</Exec>
<!-- find() loop -->
<Loop Condition="probe &lt;= hashmod &amp;&amp;_capacity">
<Exec>probe_item = (size_t*)_items + bucket * 2</Exec><!--2 pointer sizeof(item_t)-->
<If Condition="*probe_item == this || *probe_item == 0">
<Item Name="value">**(pugi::xml_node_struct**)(probe_item + 1)</Item><!--1 pointer offsetof(item_t, value)-->
<Break/>
</If>
<Exec>bucket = (bucket + probe + 1) &amp; hashmod</Exec>
<Exec>probe++</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
<Type Name="pugi::impl::`anonymous-namespace'::compact_pointer&lt;pugi::xml_attribute_struct,*,*&gt;">
<DisplayString Condition="!_data">nullptr</DisplayString>
<DisplayString Condition="_data">...</DisplayString>
<Expand HideRawView="1">
<CustomListItems Condition="_data &amp;&amp; _data &lt; 255">
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<Item Name="value">*(pugi::xml_attribute_struct*)(((size_t)this &amp; ~(compact_alignment - 1)) + (_data - 1 + $T2) * compact_alignment)</Item>
</CustomListItems>
<CustomListItems Condition="_data &amp;&amp; _data &gt;= 255">
<Variable Name="compact_alignment_log2" InitialValue="2" />
<Variable Name="compact_alignment" InitialValue="1 &lt;&lt; compact_alignment_log2" />
<!-- compact_get_page() -->
<Variable Name="_page" InitialValue="*(char*)(this - $T1)" />
<Variable Name="page" InitialValue="((this - $T1 - (_page &lt;&lt; compact_alignment_log2)) - *(unsigned*)(this - $T1 - (_page &lt;&lt; compact_alignment_log2)))" />
<!-- page->allocator->_hash -->
<Variable Name="allocator" InitialValue="*(size_t*)page" />
<Variable Name="_hash" InitialValue="*(size_t*)(allocator + 2 * sizeof(size_t))" /><!--2 pointer offsetof(allocator, _hash)-->
<Variable Name="_items" InitialValue="*(size_t*)_hash" />
<Variable Name="_capacity" InitialValue="*((size_t*)_hash + 1)" /><!--1 pointer offsetof(_hash, _capacity)-->
<Variable Name="_count" InitialValue="*((size_t*)_hash + 2)" /><!--2 pointer offsetof(_hash, _count)-->
<!-- find() prolog -->
<Variable Name="hashmod" InitialValue="_capacity - 1" />
<Variable Name="h" InitialValue="(unsigned)this" />
<Variable Name="bucket" InitialValue="0" />
<Variable Name="probe" InitialValue="0" />
<Variable Name="probe_item" InitialValue="(size_t*)0" />
<!-- find() hash -->
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>h = h * (0x85ebca6bu)</Exec>
<Exec>h = h ^ (h >> 13)</Exec>
<Exec>h = h * (0xc2b2ae35u)</Exec>
<Exec>h = h ^ (h >> 16)</Exec>
<Exec>bucket = h &amp; hashmod</Exec>
<!-- find() loop -->
<Loop Condition="probe &lt;= hashmod &amp;&amp;_capacity">
<Exec>probe_item = (size_t*)_items + bucket * 2</Exec><!--2 pointer sizeof(item_t)-->
<If Condition="*probe_item == this || *probe_item == 0">
<Item Name="value">**(pugi::xml_attribute_struct**)(probe_item + 1)</Item><!--1 pointer offsetof(item_t, value)-->
<Break/>
</If>
<Exec>bucket = (bucket + probe + 1) &amp; hashmod</Exec>
<Exec>probe++</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
<Type Name="pugi::xpath_node">
<DisplayString Condition="_node._root &amp;&amp; _attribute._attr">{_node,na} {_attribute,na}</DisplayString>
<DisplayString Condition="_node._root">{_node,na}</DisplayString>
<DisplayString Condition="_attribute._attr">{_attribute}</DisplayString>
<DisplayString>empty</DisplayString>
<Expand HideRawView="1">
<ExpandedItem Condition="_node._root &amp;&amp; !_attribute._attr">_node</ExpandedItem>
<ExpandedItem Condition="!_node._root &amp;&amp; _attribute._attr">_attribute</ExpandedItem>
<Item Name="node" Condition="_node._root &amp;&amp; _attribute._attr">_node,na</Item>
<Item Name="attribute" Condition="_node._root &amp;&amp; _attribute._attr">_attribute,na</Item>
</Expand>
</Type>
<Type Name="pugi::xpath_node_set">
<Expand>
<Item Name="type">_type</Item>
<ArrayItems>
<Size>_end - _begin</Size>
<ValuePointer>_begin</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="clr-namespace:Microsoft.Build.Framework.XamlTypes;assembly=Microsoft.Build.Framework">
<Rule Name="ReferencedPackages05032e35-86af-4ab2-a3dc-d3e348583165" PageTemplate="tool" DisplayName="Referenced Packages" SwitchPrefix="/" Order="1">
<Rule.Categories>
<Category Name="pugixml" DisplayName="pugixml" />
</Rule.Categories>
<Rule.DataSource>
<DataSource Persistence="ProjectFile" ItemType="" />
</Rule.DataSource>
<EnumProperty Name="Linkage-pugixml" DisplayName="Linkage" Description="Which version of the runtime library to use for this library" Category="pugixml">
<EnumValue Name="dynamic" DisplayName="Dynamic CRT (/MD, /MDd)" />
<EnumValue Name="static" DisplayName="Static CRT (/MT, /MTd)" />
<EnumValue Name="source" DisplayName="Include pugixml.cpp" />
<EnumValue Name="header" DisplayName="Header Only" />
</EnumProperty>
</Rule>
</ProjectSchemaDefinitions>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Default initializers for properties">
<Linkage-pugixml Condition="'$(Linkage-pugixml)' == ''">dynamic</Linkage-pugixml>
<Configuration-pugixml Condition="$(Configuration.ToLower().IndexOf('debug')) != -1">Debug</Configuration-pugixml>
<Configuration-pugixml Condition="$(Configuration.ToLower().IndexOf('debug')) == -1">Release</Configuration-pugixml>
</PropertyGroup>
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)\pugixml-propertiesui.xml" />
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions Condition="'$(Linkage-pugixml)' == 'header'">PUGIXML_HEADER_ONLY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ResourceCompile>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup Condition="'$(Linkage-pugixml)' == 'source'">
<ClCompile Include="$(MSBuildThisFileDirectory)include\pugixml.cpp"/>
</ItemGroup>
<ItemDefinitionGroup Condition="'$(Linkage-pugixml)' != 'header' AND '$(Linkage-pugixml)' != 'source'">
<Link>
<AdditionalDependencies>$(MSBuildThisFileDirectory)lib/$(Platform)\$(PlatformToolset.Split('_')[0])\$(Linkage-pugixml)\$(Configuration-pugixml)\pugixml.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd">
<metadata>
<id>pugixml</id>
<version>1.13.0-appveyor</version>
<title>pugixml</title>
<authors>Arseny Kapoulkine</authors>
<owners>Arseny Kapoulkine</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://pugixml.org/</projectUrl>
<description>pugixml is a C++ XML processing library, which consists of a DOM-like interface with rich traversal/modification capabilities, an extremely fast XML parser which constructs the DOM tree from an XML file/buffer, and an XPath 1.0 implementation for complex data-driven tree queries. Full Unicode support is also available, with Unicode interface variants and conversions between different Unicode encodings (which happen automatically during parsing/saving).
pugixml is used by a lot of projects, both open-source and proprietary, for performance and easy-to-use interface.
This package contains builds for VS2013, VS2015, VS2017, VS2019 and VS2022, for both statically linked and DLL CRT; you can switch the CRT linkage in Project -> Properties -> Referenced Packages -> pugixml.</description>
<summary>Light-weight, simple and fast XML parser for C++ with XPath support</summary>
<releaseNotes>https://pugixml.org/docs/manual.html#changes</releaseNotes>
<copyright>Copyright (c) 2006-2022 Arseny Kapoulkine</copyright>
<tags>native nativepackage</tags>
</metadata>
</package>

70
scripts/nuget_build.ps1 Normal file
View file

@ -0,0 +1,70 @@
function Run-Command([string]$cmd)
{
Invoke-Expression $cmd
if ($LastExitCode) { exit $LastExitCode }
}
function Force-Copy([string]$from, [string]$to)
{
Write-Host $from "->" $to
New-Item -Force $to | Out-Null
Copy-Item -Force $from $to
if (! $?) { exit 1 }
}
function Build-Version([string]$vs, [string]$toolset, [string]$linkage)
{
$prjsuffix = if ($linkage -eq "static") { "_static" } else { "" }
$cfgsuffix = if ($linkage -eq "static") { "Static" } else { "" }
foreach ($configuration in "Debug","Release")
{
Run-Command "msbuild pugixml_$vs$prjsuffix.vcxproj /t:Rebuild /p:Configuration=$configuration /p:Platform=x86 /v:minimal /nologo"
Run-Command "msbuild pugixml_$vs$prjsuffix.vcxproj /t:Rebuild /p:Configuration=$configuration /p:Platform=x64 /v:minimal /nologo"
Force-Copy "$vs/Win32_$configuration$cfgsuffix/pugixml.lib" "nuget/build/native/lib/Win32/$toolset/$linkage/$configuration/pugixml.lib"
Force-Copy "$vs/x64_$configuration$cfgsuffix/pugixml.lib" "nuget/build/native/lib/x64/$toolset/$linkage/$configuration/pugixml.lib"
}
}
Push-Location
$scriptdir = Split-Path $MyInvocation.MyCommand.Path
cd $scriptdir
Force-Copy "../src/pugiconfig.hpp" "nuget/build/native/include/pugiconfig.hpp"
Force-Copy "../src/pugixml.hpp" "nuget/build/native/include/pugixml.hpp"
Force-Copy "../src/pugixml.cpp" "nuget/build/native/include/pugixml.cpp"
if ($args[0] -eq 2022){
Build-Version "vs2022" "v143" "dynamic"
Build-Version "vs2022" "v143" "static"
} elseif ($args[0] -eq 2019){
Build-Version "vs2019" "v142" "dynamic"
Build-Version "vs2019" "v142" "static"
} elseif ($args[0] -eq 2017){
Build-Version "vs2017" "v141" "dynamic"
Build-Version "vs2017" "v141" "static"
Build-Version "vs2015" "v140" "dynamic"
Build-Version "vs2015" "v140" "static"
Build-Version "vs2013" "v120" "dynamic"
Build-Version "vs2013" "v120" "static"
} elseif($args[0] -eq 2015){
Build-Version "vs2015" "v140" "dynamic"
Build-Version "vs2015" "v140" "static"
Build-Version "vs2013" "v120" "dynamic"
Build-Version "vs2013" "v120" "static"
} elseif($args[0] -eq 2013){
Build-Version "vs2013" "v120" "dynamic"
Build-Version "vs2013" "v120" "static"
}
Run-Command "nuget pack nuget"
Pop-Location

View file

@ -0,0 +1,12 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/pugixml-targets.cmake")
# If the user is not requiring 1.11 (either by explicitly requesting an older
# version or not requesting one at all), provide the old imported target name
# for compatibility.
if (NOT TARGET pugixml AND (NOT DEFINED PACKAGE_FIND_VERSION OR PACKAGE_FIND_VERSION VERSION_LESS "1.11"))
add_library(pugixml INTERFACE IMPORTED)
# Equivalent to target_link_libraries INTERFACE, but compatible with CMake 3.10
set_target_properties(pugixml PROPERTIES INTERFACE_LINK_LIBRARIES pugixml::pugixml)
endif ()

11
scripts/pugixml.pc.in Normal file
View file

@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@@INSTALL_SUFFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@@INSTALL_SUFFIX@
Name: pugixml
Description: Light-weight, simple and fast XML parser for C++ with XPath support.
URL: https://pugixml.org/
Version: @pugixml_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lpugixml@LIB_POSTFIX@

14
scripts/pugixml.podspec Normal file
View file

@ -0,0 +1,14 @@
Pod::Spec.new do |s|
s.name = "pugixml"
s.version = "1.13"
s.summary = "C++ XML parser library."
s.homepage = "https://pugixml.org"
s.license = "MIT"
s.author = { "Arseny Kapoulkine" => "arseny.kapoulkine@gmail.com" }
s.platform = :ios, "7.0"
s.source = { :git => "https://github.com/zeux/pugixml.git", :tag => "v" + s.version.to_s }
s.source_files = "src/**/*.{hpp,cpp}"
s.header_mappings_dir = "src"
end

45
scripts/pugixml_dll.rc Normal file
View file

@ -0,0 +1,45 @@
#include <winver.h>
#define PUGIXML_VERSION_MAJOR 1
#define PUGIXML_VERSION_MINOR 13
#define PUGIXML_VERSION_PATCH 0
#define PUGIXML_VERSION_NUMBER "1.13.0\0"
#if defined(GCC_WINDRES) || defined(__MINGW32__) || defined(__CYGWIN__)
VS_VERSION_INFO VERSIONINFO
#else
VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
#endif
FILEVERSION PUGIXML_VERSION_MAJOR,PUGIXML_VERSION_MINOR,PUGIXML_VERSION_PATCH,0
PRODUCTVERSION PUGIXML_VERSION_MAJOR,PUGIXML_VERSION_MINOR,PUGIXML_VERSION_PATCH,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS 1
#else
FILEFLAGS 0
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE 0 // not used
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
//language ID = U.S. English, char set = Windows, Multilingual
BEGIN
VALUE "CompanyName", "zeux/pugixml\0"
VALUE "FileDescription", "pugixml library\0"
VALUE "FileVersion", PUGIXML_VERSION_NUMBER
VALUE "InternalName", "pugixml.dll\0"
VALUE "LegalCopyright", "Copyright (C) 2006-2022, by Arseny Kapoulkine\0"
VALUE "OriginalFilename", "pugixml.dll\0"
VALUE "ProductName", "pugixml\0"
VALUE "ProductVersion", PUGIXML_VERSION_NUMBER
VALUE "Comments", "For more information visit https://github.com/zeux/pugixml/\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 1252
END
END

View file

@ -64,17 +64,17 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2010\x32\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2010\x32\Debug\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">pugixmld</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2010\x64\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2010\x64\Debug\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pugixmld</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2010\x32\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2010\x32\Release\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2010\Win32_Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2010\Win32_Debug\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2010\x64_Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2010\x64_Debug\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2010\Win32_Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2010\Win32_Release\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2010\x64\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2010\x64\Release\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2010\x64_Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2010\x64_Release\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -93,12 +93,12 @@
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixmld.lib</OutputFile>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDataBaseFileName>$(OutDir)pugixmld.pdb</ProgramDataBaseFileName>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -117,12 +117,12 @@
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixmld.lib</OutputFile>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDataBaseFileName>$(OutDir)pugixmld.pdb</ProgramDataBaseFileName>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

View file

@ -64,18 +64,18 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2010\x32\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2010\x32\DebugStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">pugixmlsd</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2010\x64\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2010\x64\DebugStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pugixmlsd</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2010\x32\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2010\x32\ReleaseStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pugixmls</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2010\x64\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2010\x64\ReleaseStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pugixmls</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2010\Win32_DebugStatic\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2010\Win32_DebugStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2010\x64_DebugStatic\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2010\x64_DebugStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2010\Win32_ReleaseStatic\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2010\Win32_ReleaseStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2010\x64_ReleaseStatic\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2010\x64_ReleaseStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -93,12 +93,12 @@
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixmlsd.lib</OutputFile>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDataBaseFileName>$(OutDir)pugixmlsd.pdb</ProgramDataBaseFileName>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -117,12 +117,12 @@
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixmlsd.lib</OutputFile>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDataBaseFileName>$(OutDir)pugixmlsd.pdb</ProgramDataBaseFileName>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -141,14 +141,14 @@
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixmls.lib</OutputFile>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ProgramDataBaseFileName>$(OutDir)pugixmls.pdb</ProgramDataBaseFileName>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -167,14 +167,14 @@
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixmls.lib</OutputFile>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ProgramDataBaseFileName>$(OutDir)pugixmls.pdb</ProgramDataBaseFileName>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemGroup>

View file

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{89A1E353-E2DC-495C-B403-742BE206ACED}</ProjectGuid>
<RootNamespace>pugixml</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2013\Win32_Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2013\Win32_Debug\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2013\x64_Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2013\x64_Debug\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2013\Win32_Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2013\Win32_Release\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2013\x64_Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2013\x64_Release\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>Full</Optimization>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>Full</Optimization>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugixml.hpp" />
<ClInclude Include="..\src\pugiconfig.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp">
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{89A1E353-E2DC-495C-B403-742BE206ACED}</ProjectGuid>
<RootNamespace>pugixml</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2013\Win32_DebugStatic\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vs2013\Win32_DebugStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2013\x64_DebugStatic\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vs2013\x64_DebugStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2013\Win32_ReleaseStatic\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vs2013\Win32_ReleaseStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pugixml</TargetName>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2013\x64_ReleaseStatic\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vs2013\x64_ReleaseStatic\</IntDir>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>Full</Optimization>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>Full</Optimization>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Lib>
<OutputFile>$(OutDir)pugixml.lib</OutputFile>
</Lib>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ProgramDataBaseFileName>$(OutDir)pugixml.pdb</ProgramDataBaseFileName>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugixml.hpp" />
<ClInclude Include="..\src\pugiconfig.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp">
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2015\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2015\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2015\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2015\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2015\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2015\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2015\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2015\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2015\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2015\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2015\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2015\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2015\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2015\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2015\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2015\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2017\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2017\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2017\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2017\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2017\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2017\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2017\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2017\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2017\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2017\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2017\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2017\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2017\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2017\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2017\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2017\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2019\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2019\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2019\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2019\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2019\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2019\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2019\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2019\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2019\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2019\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2019\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2019\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2019\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2019\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2019\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2019\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2022\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2022\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2022\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2022\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2022\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2022\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2022\$(Platform)_$(Configuration)\</OutDir>
<IntDir>vs2022\$(Platform)_$(Configuration)\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{07CF01C0-B887-499D-AD9C-799CB6A9FE64}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pugixml</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>vs2022\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2022\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>vs2022\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2022\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>vs2022\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2022\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>vs2022\$(Platform)_$(Configuration)Static\</OutDir>
<IntDir>vs2022\$(Platform)_$(Configuration)Static\</IntDir>
<TargetName>pugixml</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\src\pugiconfig.hpp" />
<ClInclude Include="..\src\pugixml.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\pugixml.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,8 +1,8 @@
/**
* pugixml parser - version 1.6
* pugixml parser - version 1.13
* --------------------------------------------------------
* Copyright (C) 2006-2015, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at http://pugixml.org/
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
@ -17,6 +17,9 @@
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to enable compact mode
// #define PUGIXML_COMPACT
// Uncomment this to disable XPath
// #define PUGIXML_NO_XPATH
@ -37,6 +40,9 @@
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
// Tune this constant to adjust max nesting for XPath queries
// #define PUGIXML_XPATH_DEPTH_LIMIT 1024
// Uncomment this to switch to header-only version
// #define PUGIXML_HEADER_ONLY
@ -46,7 +52,7 @@
#endif
/**
* Copyright (c) 2006-2015 Arseny Kapoulkine
* Copyright (c) 2006-2022 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@ -59,7 +65,7 @@
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
/**
* pugixml parser - version 1.6
* pugixml parser - version 1.13
* --------------------------------------------------------
* Copyright (C) 2006-2015, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at http://pugixml.org/
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
@ -11,9 +11,10 @@
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons
// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits
#ifndef PUGIXML_VERSION
// Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons
# define PUGIXML_VERSION 160
# define PUGIXML_VERSION 1130 // 1.13
#endif
// Include user configuration file (this can define various configuration macros)
@ -65,13 +66,62 @@
// If the platform is known to have long long support, enable long long functions
#ifndef PUGIXML_HAS_LONG_LONG
# if defined(__cplusplus) && __cplusplus >= 201103
# if __cplusplus >= 201103
# define PUGIXML_HAS_LONG_LONG
# elif defined(_MSC_VER) && _MSC_VER >= 1400
# define PUGIXML_HAS_LONG_LONG
# endif
#endif
// If the platform is known to have move semantics support, compile move ctor/operator implementation
#ifndef PUGIXML_HAS_MOVE
# if __cplusplus >= 201103
# define PUGIXML_HAS_MOVE
# elif defined(_MSC_VER) && _MSC_VER >= 1600
# define PUGIXML_HAS_MOVE
# endif
#endif
// If C++ is 2011 or higher, add 'noexcept' specifiers
#ifndef PUGIXML_NOEXCEPT
# if __cplusplus >= 201103
# define PUGIXML_NOEXCEPT noexcept
# elif defined(_MSC_VER) && _MSC_VER >= 1900
# define PUGIXML_NOEXCEPT noexcept
# else
# define PUGIXML_NOEXCEPT
# endif
#endif
// Some functions can not be noexcept in compact mode
#ifdef PUGIXML_COMPACT
# define PUGIXML_NOEXCEPT_IF_NOT_COMPACT
#else
# define PUGIXML_NOEXCEPT_IF_NOT_COMPACT PUGIXML_NOEXCEPT
#endif
// If C++ is 2011 or higher, add 'override' qualifiers
#ifndef PUGIXML_OVERRIDE
# if __cplusplus >= 201103
# define PUGIXML_OVERRIDE override
# elif defined(_MSC_VER) && _MSC_VER >= 1700
# define PUGIXML_OVERRIDE override
# else
# define PUGIXML_OVERRIDE
# endif
#endif
// If C++ is 2011 or higher, use 'nullptr'
#ifndef PUGIXML_NULL
# if __cplusplus >= 201103
# define PUGIXML_NULL nullptr
# elif defined(_MSC_VER) && _MSC_VER >= 1600
# define PUGIXML_NULL nullptr
# else
# define PUGIXML_NULL 0
# endif
#endif
// Character interface macros
#ifdef PUGIXML_WCHAR_MODE
# define PUGIXML_TEXT(t) L ## t
@ -133,13 +183,13 @@ namespace pugi
// This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default.
const unsigned int parse_eol = 0x0020;
// This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default.
const unsigned int parse_wconv_attribute = 0x0040;
// This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default.
const unsigned int parse_wnorm_attribute = 0x0080;
// This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default.
const unsigned int parse_declaration = 0x0100;
@ -158,6 +208,11 @@ namespace pugi
// is a valid document. This flag is off by default.
const unsigned int parse_fragment = 0x1000;
// This flag determines if plain character data is be stored in the parent element's value. This significantly changes the structure of
// the document; this flag is only recommended for parsing documents with many PCDATA nodes in memory-constrained environments.
// This flag is off by default.
const unsigned int parse_embed_pcdata = 0x2000;
// The default parsing mode.
// Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded,
// End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules.
@ -184,16 +239,16 @@ namespace pugi
};
// Formatting flags
// Indent the nodes that are written to output stream with as many indentation strings as deep the node is in DOM tree. This flag is on by default.
const unsigned int format_indent = 0x01;
// Write encoding-specific BOM to the output stream. This flag is off by default.
const unsigned int format_write_bom = 0x02;
// Use raw output mode (no indentation and no line breaks are written). This flag is off by default.
const unsigned int format_raw = 0x04;
// Omit default XML declaration even if there is no declaration in the document. This flag is off by default.
const unsigned int format_no_declaration = 0x08;
@ -203,10 +258,25 @@ namespace pugi
// Open file using text mode in xml_document::save_file. This enables special character (i.e. new-line) conversions on some systems. This flag is off by default.
const unsigned int format_save_file_text = 0x20;
// Write every attribute on a new line with appropriate indentation. This flag is off by default.
const unsigned int format_indent_attributes = 0x40;
// Don't output empty element tags, instead writing an explicit start and end tag even if there are no children. This flag is off by default.
const unsigned int format_no_empty_element_tags = 0x80;
// Skip characters belonging to range [0; 32) instead of "&#xNN;" encoding. This flag is off by default.
const unsigned int format_skip_control_chars = 0x100;
// Use single quotes ' instead of double quotes " for enclosing attribute values. This flag is off by default.
const unsigned int format_attribute_single_quote = 0x200;
// The default set of formatting flags.
// Nodes are indented depending on their depth in DOM tree, a default declaration is output if document has none.
const unsigned int format_default = format_indent;
const int default_double_precision = 17;
const int default_float_precision = 9;
// Forward declarations
struct xml_attribute_struct;
struct xml_node_struct;
@ -222,7 +292,7 @@ namespace pugi
class xml_node;
class xml_text;
#ifndef PUGIXML_NO_XPATH
class xpath_node;
class xpath_node_set;
@ -244,6 +314,8 @@ namespace pugi
It begin() const { return _begin; }
It end() const { return _end; }
bool empty() const { return _begin == _end; }
private:
It _begin, _end;
};
@ -265,7 +337,7 @@ namespace pugi
// Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio
xml_writer_file(void* file);
virtual void write(const void* data, size_t size);
virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE;
private:
void* file;
@ -280,7 +352,7 @@ namespace pugi
xml_writer_stream(std::basic_ostream<char, std::char_traits<char> >& stream);
xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream);
virtual void write(const void* data, size_t size);
virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE;
private:
std::basic_ostream<char, std::char_traits<char> >* narrow_stream;
@ -296,13 +368,13 @@ namespace pugi
private:
xml_attribute_struct* _attr;
typedef void (*unspecified_bool_type)(xml_attribute***);
public:
// Default constructor. Constructs an empty attribute.
xml_attribute();
// Constructs attribute from internal pointer
explicit xml_attribute(xml_attribute_struct* attr);
@ -346,13 +418,18 @@ namespace pugi
// Set attribute name/value (returns false if attribute is empty or there is not enough memory)
bool set_name(const char_t* rhs);
bool set_value(const char_t* rhs, size_t sz);
bool set_value(const char_t* rhs);
// Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
bool set_value(int rhs);
bool set_value(unsigned int rhs);
bool set_value(long rhs);
bool set_value(unsigned long rhs);
bool set_value(double rhs);
bool set_value(double rhs, int precision);
bool set_value(float rhs);
bool set_value(float rhs, int precision);
bool set_value(bool rhs);
#ifdef PUGIXML_HAS_LONG_LONG
@ -364,6 +441,8 @@ namespace pugi
xml_attribute& operator=(const char_t* rhs);
xml_attribute& operator=(int rhs);
xml_attribute& operator=(unsigned int rhs);
xml_attribute& operator=(long rhs);
xml_attribute& operator=(unsigned long rhs);
xml_attribute& operator=(double rhs);
xml_attribute& operator=(float rhs);
xml_attribute& operator=(bool rhs);
@ -414,7 +493,7 @@ namespace pugi
// Borland C++ workaround
bool operator!() const;
// Comparison operators (compares wrapped node pointers)
bool operator==(const xml_node& r) const;
bool operator!=(const xml_node& r) const;
@ -435,7 +514,7 @@ namespace pugi
// Get node value, or "" if node is empty or it has no value
// Note: For <node>text</node> node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes.
const char_t* value() const;
// Get attribute list
xml_attribute first_attribute() const;
xml_attribute last_attribute() const;
@ -447,7 +526,7 @@ namespace pugi
// Get next/previous sibling in the children list of the parent node
xml_node next_sibling() const;
xml_node previous_sibling() const;
// Get parent node
xml_node parent() const;
@ -463,6 +542,9 @@ namespace pugi
xml_node next_sibling(const char_t* name) const;
xml_node previous_sibling(const char_t* name) const;
// Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast)
xml_attribute attribute(const char_t* name, xml_attribute& hint) const;
// Get child value of current node; that is, value of the first child node of type PCDATA/CDATA
const char_t* child_value() const;
@ -471,8 +553,9 @@ namespace pugi
// Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
bool set_name(const char_t* rhs);
bool set_value(const char_t* rhs, size_t sz);
bool set_value(const char_t* rhs);
// Add attribute with specified name. Returns added attribute, or empty attribute on errors.
xml_attribute append_attribute(const char_t* name);
xml_attribute prepend_attribute(const char_t* name);
@ -513,10 +596,16 @@ namespace pugi
bool remove_attribute(const xml_attribute& a);
bool remove_attribute(const char_t* name);
// Remove all attributes
bool remove_attributes();
// Remove specified child
bool remove_child(const xml_node& n);
bool remove_child(const char_t* name);
// Remove all children
bool remove_children();
// Parses buffer as an XML document fragment and appends all nodes as children of the current node.
// Copies/converts the buffer, so it may be deleted or changed after the function returns.
// Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory.
@ -526,11 +615,11 @@ namespace pugi
template <typename Predicate> xml_attribute find_attribute(Predicate pred) const
{
if (!_root) return xml_attribute();
for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute())
if (pred(attrib))
return attrib;
return xml_attribute();
}
@ -538,11 +627,11 @@ namespace pugi
template <typename Predicate> xml_node find_child(Predicate pred) const
{
if (!_root) return xml_node();
for (xml_node node = first_child(); node; node = node.next_sibling())
if (pred(node))
return node;
return xml_node();
}
@ -552,7 +641,7 @@ namespace pugi
if (!_root) return xml_node();
xml_node cur = first_child();
while (cur._root && cur._root != _root)
{
if (pred(cur)) return cur;
@ -584,22 +673,22 @@ namespace pugi
// Recursively traverse subtree with xml_tree_walker
bool traverse(xml_tree_walker& walker);
#ifndef PUGIXML_NO_XPATH
// Select single node by evaluating XPath query. Returns first node from the resulting node set.
xpath_node select_node(const char_t* query, xpath_variable_set* variables = 0) const;
xpath_node select_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const;
xpath_node select_node(const xpath_query& query) const;
// Select node set by evaluating XPath query
xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const;
xpath_node_set select_nodes(const xpath_query& query) const;
// (deprecated: use select_node instead) Select single node by evaluating XPath query.
xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const;
xpath_node select_single_node(const xpath_query& query) const;
PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const;
PUGIXML_DEPRECATED xpath_node select_single_node(const xpath_query& query) const;
#endif
// Print subtree using a writer object
void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
@ -690,13 +779,18 @@ namespace pugi
bool as_bool(bool def = false) const;
// Set text (returns false if object is empty or there is not enough memory)
bool set(const char_t* rhs, size_t sz);
bool set(const char_t* rhs);
// Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
bool set(int rhs);
bool set(unsigned int rhs);
bool set(long rhs);
bool set(unsigned long rhs);
bool set(double rhs);
bool set(double rhs, int precision);
bool set(float rhs);
bool set(float rhs, int precision);
bool set(bool rhs);
#ifdef PUGIXML_HAS_LONG_LONG
@ -708,6 +802,8 @@ namespace pugi
xml_text& operator=(const char_t* rhs);
xml_text& operator=(int rhs);
xml_text& operator=(unsigned int rhs);
xml_text& operator=(long rhs);
xml_text& operator=(unsigned long rhs);
xml_text& operator=(double rhs);
xml_text& operator=(float rhs);
xml_text& operator=(bool rhs);
@ -762,10 +858,10 @@ namespace pugi
xml_node& operator*() const;
xml_node* operator->() const;
const xml_node_iterator& operator++();
xml_node_iterator& operator++();
xml_node_iterator operator++(int);
const xml_node_iterator& operator--();
xml_node_iterator& operator--();
xml_node_iterator operator--(int);
};
@ -804,10 +900,10 @@ namespace pugi
xml_attribute& operator*() const;
xml_attribute* operator->() const;
const xml_attribute_iterator& operator++();
xml_attribute_iterator& operator++();
xml_attribute_iterator operator++(int);
const xml_attribute_iterator& operator--();
xml_attribute_iterator& operator--();
xml_attribute_iterator operator--(int);
};
@ -840,10 +936,10 @@ namespace pugi
xml_node& operator*() const;
xml_node* operator->() const;
const xml_named_node_iterator& operator++();
xml_named_node_iterator& operator++();
xml_named_node_iterator operator++(int);
const xml_named_node_iterator& operator--();
xml_named_node_iterator& operator--();
xml_named_node_iterator operator--(int);
private:
@ -861,11 +957,11 @@ namespace pugi
private:
int _depth;
protected:
// Get current traversal depth
int depth() const;
public:
xml_tree_walker();
virtual ~xml_tree_walker();
@ -936,13 +1032,14 @@ namespace pugi
char_t* _buffer;
char _memory[192];
// Non-copyable semantics
xml_document(const xml_document&);
const xml_document& operator=(const xml_document&);
xml_document& operator=(const xml_document&);
void create();
void destroy();
void _create();
void _destroy();
void _move(xml_document& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT;
public:
// Default constructor, makes empty document
@ -951,6 +1048,12 @@ namespace pugi
// Destructor, invalidates all node/attribute handles to this document
~xml_document();
#ifdef PUGIXML_HAS_MOVE
// Move semantics support
xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT;
xml_document& operator=(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT;
#endif
// Removes all nodes, leaving the empty document
void reset();
@ -964,7 +1067,7 @@ namespace pugi
#endif
// (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied.
xml_parse_result load(const char_t* contents, unsigned int options = parse_default);
PUGIXML_DEPRECATED xml_parse_result load(const char_t* contents, unsigned int options = parse_default);
// Load document from zero-terminated string. No encoding conversions are applied.
xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default);
@ -1040,12 +1143,12 @@ namespace pugi
xpath_value_type _type;
xpath_variable* _next;
xpath_variable();
xpath_variable(xpath_value_type type);
// Non-copyable semantics
xpath_variable(const xpath_variable&);
xpath_variable& operator=(const xpath_variable&);
public:
// Get variable name
const char_t* name() const;
@ -1072,17 +1175,29 @@ namespace pugi
private:
xpath_variable* _data[64];
// Non-copyable semantics
xpath_variable_set(const xpath_variable_set&);
xpath_variable_set& operator=(const xpath_variable_set&);
void _assign(const xpath_variable_set& rhs);
void _swap(xpath_variable_set& rhs);
xpath_variable* find(const char_t* name) const;
xpath_variable* _find(const char_t* name) const;
static bool _clone(xpath_variable* var, xpath_variable** out_result);
static void _destroy(xpath_variable* var);
public:
// Default constructor/destructor
xpath_variable_set();
~xpath_variable_set();
// Copy constructor/assignment operator
xpath_variable_set(const xpath_variable_set& rhs);
xpath_variable_set& operator=(const xpath_variable_set& rhs);
#ifdef PUGIXML_HAS_MOVE
// Move semantics support
xpath_variable_set(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT;
xpath_variable_set& operator=(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT;
#endif
// Add a new variable or get the existing one, if the types match
xpath_variable* add(const char_t* name, xpath_value_type type);
@ -1113,28 +1228,37 @@ namespace pugi
public:
// Construct a compiled object from XPath expression.
// If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors.
explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0);
explicit xpath_query(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL);
// Constructor
xpath_query();
// Destructor
~xpath_query();
#ifdef PUGIXML_HAS_MOVE
// Move semantics support
xpath_query(xpath_query&& rhs) PUGIXML_NOEXCEPT;
xpath_query& operator=(xpath_query&& rhs) PUGIXML_NOEXCEPT;
#endif
// Get query expression return type
xpath_value_type return_type() const;
// Evaluate expression as boolean value in the specified context; performs type conversion if necessary.
// If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
bool evaluate_boolean(const xpath_node& n) const;
// Evaluate expression as double value in the specified context; performs type conversion if necessary.
// If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
double evaluate_number(const xpath_node& n) const;
#ifndef PUGIXML_NO_STL
// Evaluate expression as string value in the specified context; performs type conversion if necessary.
// If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
string_t evaluate_string(const xpath_node& n) const;
#endif
// Evaluate expression as string value in the specified context; performs type conversion if necessary.
// At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero).
// If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
@ -1161,8 +1285,14 @@ namespace pugi
// Borland C++ workaround
bool operator!() const;
};
#ifndef PUGIXML_NO_EXCEPTIONS
#if defined(_MSC_VER)
// C4275 can be ignored in Visual C++ if you are deriving
// from a type in the Standard C++ Library
#pragma warning(push)
#pragma warning(disable: 4275)
#endif
// XPath exception class
class PUGIXML_CLASS xpath_exception: public std::exception
{
@ -1174,26 +1304,29 @@ namespace pugi
explicit xpath_exception(const xpath_parse_result& result);
// Get error message
virtual const char* what() const throw();
virtual const char* what() const throw() PUGIXML_OVERRIDE;
// Get parse result
const xpath_parse_result& result() const;
};
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif
// XPath node class (either xml_node or xml_attribute)
class PUGIXML_CLASS xpath_node
{
private:
xml_node _node;
xml_attribute _attribute;
typedef void (*unspecified_bool_type)(xpath_node***);
public:
// Default constructor; constructs empty XPath node
xpath_node();
// Construct XPath node from XML node/attribute
xpath_node(const xml_node& node);
xpath_node(const xml_attribute& attribute, const xml_node& parent);
@ -1201,13 +1334,13 @@ namespace pugi
// Get node/attribute, if any
xml_node node() const;
xml_attribute attribute() const;
// Get parent of contained node/attribute
xml_node parent() const;
// Safe bool conversion operator
operator unspecified_bool_type() const;
// Borland C++ workaround
bool operator!() const;
@ -1233,13 +1366,13 @@ namespace pugi
type_sorted, // Sorted by document order (ascending)
type_sorted_reverse // Sorted by document order (descending)
};
// Constant iterator type
typedef const xpath_node* const_iterator;
// We define non-constant iterator to be the same as constant iterator so that various generic algorithms (i.e. boost foreach) work
typedef const xpath_node* iterator;
// Default constructor. Constructs empty set.
xpath_node_set();
@ -1248,42 +1381,49 @@ namespace pugi
// Destructor
~xpath_node_set();
// Copy constructor/assignment operator
xpath_node_set(const xpath_node_set& ns);
xpath_node_set& operator=(const xpath_node_set& ns);
#ifdef PUGIXML_HAS_MOVE
// Move semantics support
xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT;
xpath_node_set& operator=(xpath_node_set&& rhs) PUGIXML_NOEXCEPT;
#endif
// Get collection type
type_t type() const;
// Get collection size
size_t size() const;
// Indexing operator
const xpath_node& operator[](size_t index) const;
// Collection iterators
const_iterator begin() const;
const_iterator end() const;
// Sort the collection in ascending/descending order by document order
void sort(bool reverse = false);
// Get first node in the collection by document order
xpath_node first() const;
// Check if collection is empty
bool empty() const;
private:
type_t _type;
xpath_node _storage;
xpath_node _storage[1];
xpath_node* _begin;
xpath_node* _end;
void _assign(const_iterator begin, const_iterator end);
void _assign(const_iterator begin, const_iterator end, type_t type);
void _move(xpath_node_set& rhs) PUGIXML_NOEXCEPT;
};
#endif
@ -1291,7 +1431,7 @@ namespace pugi
// Convert wide string to UTF8
std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const wchar_t* str);
std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >& str);
// Convert UTF8 to wide string
std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const char* str);
std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const std::basic_string<char, std::char_traits<char>, std::allocator<char> >& str);
@ -1299,13 +1439,13 @@ namespace pugi
// Memory allocation function interface; returns pointer to allocated memory or NULL on failure
typedef void* (*allocation_function)(size_t size);
// Memory deallocation function interface
typedef void (*deallocation_function)(void* ptr);
// Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions.
void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate);
// Get current memory management functions
allocation_function PUGIXML_FUNCTION get_memory_allocation_function();
deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function();
@ -1341,7 +1481,7 @@ namespace std
#endif
/**
* Copyright (c) 2006-2015 Arseny Kapoulkine
* Copyright (c) 2006-2022 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@ -1354,7 +1494,7 @@ namespace std
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND

View file

@ -2,6 +2,18 @@
#include <string.h>
#include <assert.h>
#include <stdlib.h>
// Address sanitizer
#if defined(__has_feature)
# define ADDRESS_SANITIZER __has_feature(address_sanitizer)
#else
# if defined(__SANITIZE_ADDRESS__)
# define ADDRESS_SANITIZER 1
# else
# define ADDRESS_SANITIZER 0
# endif
#endif
// Low-level allocation functions
#if defined(_WIN32) || defined(_WIN64)
@ -66,7 +78,7 @@ namespace
VirtualProtect(rptr, aligned_size + page_size, PAGE_NOACCESS, &old_flags);
}
}
#elif defined(__APPLE__) || defined(__linux__)
#elif (defined(__APPLE__) || defined(__linux__)) && (defined(__i386) || defined(__x86_64)) && !ADDRESS_SANITIZER
# include <sys/mman.h>
namespace
@ -80,7 +92,9 @@ namespace
void* allocate_page_aligned(size_t size)
{
return mmap(0, size + page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
void* result = malloc(size + page_size);
return reinterpret_cast<void*>(align_to_page(reinterpret_cast<size_t>(result)));
}
void* allocate(size_t size)
@ -111,8 +125,6 @@ namespace
}
}
#else
# include <stdlib.h>
namespace
{
void* allocate(size_t size)
@ -130,14 +142,16 @@ namespace
#endif
// High-level allocation functions
const size_t memory_alignment = sizeof(double) > sizeof(void*) ? sizeof(double) : sizeof(void*);
void* memory_allocate(size_t size)
{
void* result = allocate(size + sizeof(size_t));
void* result = allocate(size + memory_alignment);
if (!result) return 0;
memcpy(result, &size, sizeof(size_t));
return static_cast<size_t*>(result) + 1;
return static_cast<char*>(result) + memory_alignment;
}
size_t memory_size(void* ptr)
@ -145,7 +159,7 @@ size_t memory_size(void* ptr)
assert(ptr);
size_t result;
memcpy(&result, static_cast<size_t*>(ptr) - 1, sizeof(size_t));
memcpy(&result, static_cast<char*>(ptr) - memory_alignment, sizeof(size_t));
return result;
}
@ -156,6 +170,6 @@ void memory_deallocate(void* ptr)
size_t size = memory_size(ptr);
deallocate(static_cast<size_t*>(ptr) - 1, size + sizeof(size_t));
deallocate(static_cast<char*>(ptr) - memory_alignment, size + memory_alignment);
}

View file

@ -1,72 +0,0 @@
#!/usr/bin/perl
use Archive::Tar;
use Archive::Zip;
use File::Basename;
my $target = shift @ARGV;
my @sources = @ARGV;
my $basedir = basename($target, ('.zip', '.tar.gz', '.tgz')) . '/';
my $zip = $target =~ /\.zip$/;
my $arch = $zip ? Archive::Zip->new : Archive::Tar->new;
for $source (sort {$a cmp $b} @sources)
{
my $contents = &readfile_contents($source);
my $meta = &readfile_meta($source);
my $file = $basedir . $source;
if (-T $source)
{
# convert all newlines to Unix format
$contents =~ s/\r//g;
if ($zip)
{
# convert all newlines to Windows format for .zip distribution
$contents =~ s/\n/\r\n/g;
}
}
if ($zip)
{
my $path = $file;
$arch->addDirectory($path) if $path =~ s/\/[^\/]+$/\// && !defined($arch->memberNamed($path));
my $member = $arch->addString($contents, $file);
$member->desiredCompressionMethod(COMPRESSION_DEFLATED);
$member->desiredCompressionLevel(9);
$member->setLastModFileDateTimeFromUnix($$meta{mtime});
}
else
{
$arch->add_data($file, $contents, $meta);
}
}
$zip ? $arch->overwriteAs($target) : $arch->write($target, 9);
sub readfile_contents
{
my $file = shift;
open FILE, $file or die "Can't open $file: $!";
binmode FILE;
my @contents = <FILE>;
close FILE;
return join('', @contents);
}
sub readfile_meta
{
my $file = shift;
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($file);
return {mtime => $mtime};
}

View file

@ -0,0 +1,87 @@
function Invoke-CmdScript($scriptName)
{
$cmdLine = """$scriptName"" $args & set"
& $Env:SystemRoot\system32\cmd.exe /c $cmdLine |
select-string '^([^=]*)=(.*)$' | foreach-object {
$varName = $_.Matches[0].Groups[1].Value
$varValue = $_.Matches[0].Groups[2].Value
set-item Env:$varName $varValue
}
}
$sources = @("src/pugixml.cpp") + (Get-ChildItem -Path "tests/*.cpp" -Exclude "fuzz_*.cpp")
$failed = $FALSE
foreach ($vs in $args)
{
foreach ($arch in "x86","x64")
{
Write-Output "# Setting up VS$vs $arch"
if ($vs -eq 15) {
$vsdevcmdarch = if ($arch -eq "x64") { "amd64" } else { "x86" }
Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" "-arch=$vsdevcmdarch"
}
elseif ($vs -eq 19) {
$vsdevcmdarch = if ($arch -eq "x64") { "amd64" } else { "x86" }
Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\VsDevCmd.bat" "-arch=$vsdevcmdarch"
}
elseif ($vs -eq 22) {
$vsdevcmdarch = if ($arch -eq "x64") { "amd64" } else { "x86" }
Invoke-CmdScript "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd.bat" "-arch=$vsdevcmdarch"
}
else
{
Invoke-CmdScript "C:\Program Files (x86)\Microsoft Visual Studio $vs.0\VC\vcvarsall.bat" $arch
}
if (! $?) { throw "Error setting up VS$vs $arch" }
foreach ($defines in "standard", "PUGIXML_WCHAR_MODE", "PUGIXML_COMPACT")
{
$target = "tests_vs${vs}_${arch}_${defines}"
$deflist = if ($defines -eq "standard") { "" } else { "/D$defines" }
Add-AppveyorTest $target -Outcome Running
Write-Output "# Building $target.exe"
& cmd /c "cl.exe /Fe$target.exe /EHsc /W4 /WX $deflist $sources 2>&1" | Tee-Object -Variable buildOutput
if ($?)
{
Write-Output "# Running $target.exe"
$sw = [Diagnostics.Stopwatch]::StartNew()
& .\$target | Tee-Object -Variable testOutput
if ($?)
{
Write-Output "# Passed"
Update-AppveyorTest $target -Outcome Passed -StdOut ($testOutput | out-string) -Duration $sw.ElapsedMilliseconds
}
else
{
Write-Output "# Failed"
Update-AppveyorTest $target -Outcome Failed -StdOut ($testOutput | out-string) -ErrorMessage "Running failed"
$failed = $TRUE
}
}
else
{
Write-Output "# Failed to build"
Update-AppveyorTest $target -Outcome Failed -StdOut ($buildOutput | out-string) -ErrorMessage "Compilation failed"
$failed = $TRUE
}
}
}
}
if ($failed) { throw "One or more build steps failed" }
Write-Output "# End"

View file

@ -1,10 +0,0 @@
#!/bin/sh
# put this to /etc/rc.d/pugixml-autotest
# don't forget to chmod +x pugixml-autotest and to replace /home/USERNAME with actual path
if [ "$1" = "start" -o "$1" = "faststart" ]
then
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
cd /home/USERNAME/pugixml
perl tests/autotest-remote-host.pl "shutdown -p now" &
fi

View file

@ -1,14 +0,0 @@
#!/bin/sh
# chkconfig: 2345 20 80
# description: pugixml autotest script
# put this to /etc/init.d/pugixml-autotest.sh, then launch
# Debian/Ubuntu: sudo update-rc.d pugixml-autotest.sh defaults 80
# Fedora/RedHat: sudo chkconfig --add pugixml-autotest.sh
# don't forget to chmod +x pugixml-autotest.sh and to replace /home/USERNAME with actual path
if [ "$1" = "start" ]
then
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
cd /home/USERNAME/pugixml
perl tests/autotest-remote-host.pl "shutdown -P now" &
fi

View file

@ -1,150 +0,0 @@
#!/usr/bin/perl
use Config;
sub permute
{
my @defines = @_;
my @result = ('');
foreach $define (@defines)
{
push @result, map { length($_) == 0 ? $define : "$_,$define" } @result;
}
@result;
}
sub gcctoolset
{
my $gccversion = `gcc -dumpversion`;
chomp($gccversion);
my $gcc = "gcc$gccversion";
return ($^O =~ /darwin/) ? ($gcc, "${gcc}_x64", "${gcc}_ppc") : (`uname -m` =~ /64/) ? ("${gcc}_x64") : ($gcc);
}
sub getcpucount
{
return $1 if ($^O =~ /linux/ && `cat /proc/cpuinfo` =~ /cpu cores\s*:\s*(\d+)/);
return $1 if ($^O =~ /freebsd|darwin/ && `sysctl -a` =~ /hw\.ncpu\s*:\s*(\d+)/);
return $1 - 1 if ($^O =~ /solaris/ && `mpstat | wc -l` =~ /(\d+)/);
undef;
}
@alltoolsets = ($^O =~ /MSWin/)
? (bcc, cw, dmc,
ic8, ic9, ic9_x64, ic10, ic10_x64, ic11, ic11_x64,
mingw34, mingw44, mingw45, mingw45_0x, mingw46_x64,
msvc6, msvc7, msvc71, msvc8, msvc8_x64, msvc9, msvc9_x64,
msvc10, msvc10_x64, msvc10_clr, msvc10_clr_x64,
msvc11, msvc11_x64, msvc11_clr, msvc11_clr_x64, msvc11_arm,
msvc12, msvc12_x64, msvc12_clr, msvc12_clr_x64, msvc12_arm,
xbox360, ps3_gcc, ps3_snc, msvc8_wince, bada, blackberry, android, android_stlport)
: ($^O =~ /solaris/)
? (suncc, suncc_x64)
: &gcctoolset();
$fast = scalar grep(/^fast$/, @ARGV);
@toolsets = map { /^fast$/ ? () : ($_) } @ARGV;
@toolsets = @toolsets ? @toolsets : @alltoolsets;
@configurations = (debug, release);
@defines = (PUGIXML_NO_XPATH, PUGIXML_NO_EXCEPTIONS, PUGIXML_NO_STL, PUGIXML_WCHAR_MODE);
$stddefine = 'PUGIXML_STANDARD';
if ($fast)
{
@defines = (PUGIXML_WCHAR_MODE);
@configurations = (debug);
}
@definesets = permute(@defines);
print "### autotest begin " . scalar localtime() . "\n";
# print Git revision info
print "### autotest revision $1\n" if (`git rev-parse HEAD` =~ /(.+)/);
# get CPU info
$cpucount = &getcpucount();
# build all configurations
%results = ();
foreach $toolset (@toolsets)
{
my $cmdline = "jam";
# parallel build on non-windows platforms (since jam can't detect processor count)
$cmdline .= " -j$cpucount" if (defined $cpucount);
# add toolset
$cmdline .= " toolset=$toolset";
# add configurations
$cmdline .= " configuration=" . join(',', @configurations);
# add definesets
$cmdline .= " defines=$stddefine";
foreach $defineset (@definesets)
{
# STLport lacks bad_alloc on Android so skip configurations without PUGIXML_NO_EXCEPTIONS
next if ($toolset eq 'android_stlport' && $defineset !~ /PUGIXML_NO_EXCEPTIONS/);
$cmdline .= ":$defineset" if ($defineset ne '');
# any configuration with prepare but without result is treated as failed
foreach $configuration (@configurations)
{
print "### autotest $Config{archname} $toolset $configuration [$defineset] prepare\n";
}
}
print STDERR "*** testing $toolset... ***\n";
# launch command
print "### autotest launch $cmdline\n";
open PIPE, "$cmdline autotest=on coverage |" || die "$cmdline failed: $!\n";
# parse build output
while (<PIPE>)
{
# ... autotest release [wchar] success
if (/^\.\.\. autotest (\S+) \[(.*?)\] (success|skiprun)/)
{
my $configuration = $1;
my $defineset = ($2 eq $stddefine) ? '' : $2;
my $result = $3;
print "### autotest $Config{archname} $toolset $configuration [$defineset] $result\n";
}
# ... autotest release [wchar] gcov
elsif (/^\.\.\. autotest (\S+) \[(.*?)\] gcov/)
{
my $configuration = $1;
my $defineset = ($2 eq $stddefine) ? '' : $2;
if (/pugixml\.cpp' executed:([^%]+)%/)
{
print "### autotest $Config{archname} $toolset $configuration [$defineset] coverage $1\n";
}
else
{
print;
}
}
else
{
print;
}
}
close PIPE;
}
print "### autotest end " . scalar localtime() . "\n";

View file

@ -1,12 +0,0 @@
#!/bin/sh
# put this to /Library/StartupItems/pugixml-autotest/pugixml-autotest, then create
# file StartupParameters.plist in the same folder with the following contents:
# <plist><dict><key>Provides</key><array><string>pugixml-autotest</string></array></dict></plist>
# don't forget to chmod +x pugixml-autotest and to replace /Users/USERNAME with actual path
if [ "$1" = "start" ]
then
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
cd /Users/USERNAME/pugixml
perl tests/autotest-remote-host.pl "shutdown -h now" &
fi

View file

@ -1,37 +0,0 @@
#!/usr/bin/perl
sub execprint
{
my $cmd = shift;
open PIPE, "$cmd |" || die "$cmd failed: $!\n";
print while (<PIPE>);
close PIPE;
return $?;
}
use IO::Socket;
use Net::Ping;
$exitcmd = shift;
$host = "10.0.2.2";
# wait while network is up
$ping = Net::Ping->new("icmp");
while (!$ping->ping($host))
{
print "### autotest $host is down, retrying...\n";
}
print "### autotest $host is up, connecting...\n";
my $client = new IO::Socket::INET(PeerAddr => "$host:7183");
exit unless $client;
select $client;
&execprint('git pull') == 0 || die "error updating from repo\n";
&execprint('perl tests/autotest-local.pl') == 0 || die "error launching tests\n";
system($exitcmd);

View file

@ -1,33 +0,0 @@
#!/usr/bin/perl
use IO::Socket;
$vm = shift;
$log = shift;
# start virtualbox gui in minimized mode - this should be the first thing we do since this process
# inherits all handles and we want our sockets/log file closed
system("start /min virtualbox --startvm $vm");
# start a server; vm will connect to the server via autotest-remote-host.pl
my $server = new IO::Socket::INET(LocalPort => 7183, Listen => 1);
die "Could not create socket: $!\n" unless $server;
open LOG, ">> $log" || die "Could not open log file: $!\n";
print LOG "Listening for connection...\n";
my $client = $server->accept();
# echo all input to log file
print LOG $_ while (<$client>);
close LOG;
$client->close();
$server->close();
# wait for vm shutdown to decrease peak memory consumption
while (`vboxmanage showvminfo $vm` !~ /State:\s+powered off/)
{
sleep(1);
}

View file

@ -1,229 +0,0 @@
#!/usr/bin/perl
# pretty-printing
sub prettysuffix
{
my $suffix = shift;
return " C++0x" if ($suffix eq '_0x');
return " x64" if ($suffix eq '_x64');
return " CLR" if ($suffix eq '_clr');
return " CLR x64" if ($suffix eq '_clr_x64');
return " PPC" if ($suffix eq '_ppc');
return " WinCE" if ($suffix eq '_wince');
return " ARM" if ($suffix eq '_arm');
return "";
}
sub prettytoolset
{
my $toolset = shift;
return "Borland C++ 5.82" if ($toolset eq 'bcc');
return "Metrowerks CodeWarrior 8" if ($toolset eq 'cw');
return "Digital Mars C++ 8.51" if ($toolset eq 'dmc');
return "Sun C++ 5.10" . prettysuffix($1) if ($toolset =~ /^suncc(.*)$/);
return "Intel C++ Compiler $1.0" . prettysuffix($2) if ($toolset =~ /^ic(\d+)(.*)$/);
return "MinGW (GCC $1.$2)" . prettysuffix($3) if ($toolset =~ /^mingw(\d)(\d)(.*)$/);
return "Microsoft Visual C++ 7.1" if ($toolset eq 'msvc71');
return "Microsoft Visual C++ $1.0" . prettysuffix($2) if ($toolset =~ /^msvc(\d+)(.*)$/);
return "GNU C++ Compiler $1" . prettysuffix($2) if ($toolset =~ /^gcc([\d.]*)(.*)$/);
return "Microsoft Xbox360 Compiler" if ($toolset =~ /^xbox360/);
return "Sony PlayStation3 GCC" if ($toolset =~ /^ps3_gcc/);
return "Sony PlayStation3 SNC" if ($toolset =~ /^ps3_snc/);
return "Android NDK (GCC)" . ($1 eq '_stlport' ? " STLport" : "") if ($toolset =~ /^android(.*)$/);
return "bada SDK (GCC)" if ($toolset =~ /^bada$/);
return "BlackBerry NDK (GCC)" if ($toolset =~ /^blackberry$/);
$toolset;
}
sub prettyplatform
{
my ($platform, $toolset) = @_;
return "solaris" if ($platform =~ /solaris/);
return "macos" if ($platform =~ /darwin/);
return "linux64" if ($platform =~ /64-linux/);
return "linux32" if ($platform =~ /86-linux/);
return "fbsd64" if ($platform =~ /64-freebsd/);
return "fbsd32" if ($platform =~ /86-freebsd/);
return "x360" if ($toolset =~ /^xbox360/);
return "ps3" if ($toolset =~ /^ps3/);
return "arm" if ($toolset =~ /_arm$/);
return "arm" if ($toolset =~ /_wince$/);
return "arm" if ($toolset =~ /^android/);
return "arm" if ($toolset =~ /^bada/);
return "arm" if ($toolset =~ /^blackberry/);
return "win64" if ($platform =~ /MSWin32-x64/);
return "win32" if ($platform =~ /MSWin32/);
$platform;
}
sub prettybox
{
my $enabled = shift;
my $color = $enabled ? "#cccccc" : "#ffffff";
"<td bgcolor='$color' align='center'>" . ($enabled ? "+" : "&nbsp;") . "</td>";
}
# parse build log
%results = ();
%toolsets = ();
%defines = ();
%configurations = ();
sub insertindex
{
my ($hash, $key) = @_;
$$hash{$key} = scalar(keys %$hash) unless defined $$hash{$key};
}
while (<>)
{
### autotest i386-freebsd-64int gcc release [wchar] result 0 97.78 98.85
if (/^### autotest (\S+) (\S+) (\S+) \[(.*?)\] (.*)/)
{
my ($platform, $toolset, $configuration, $defineset, $info) = ($1, $2, $3, $4, $5);
my $fulltool = &prettyplatform($platform, $toolset) . ' ' . &prettytoolset($toolset);
my $fullconf = "$configuration $defineset";
if ($info =~ /^prepare/)
{
$results{$fulltool}{$fullconf}{result} = "";
}
elsif ($info =~ /^success/)
{
$results{$fulltool}{$fullconf}{result} = "success";
}
elsif ($info =~ /^skiprun/)
{
$results{$fulltool}{$fullconf}{result} = "skiprun";
}
elsif ($info =~ /^coverage (\S+)/)
{
$results{$fulltool}{$fullconf}{coverage} = $1;
}
else
{
print STDERR "Unrecognized autotest infoline $_";
}
&insertindex(\%toolsets, $fulltool);
$defines{$_} = 1 foreach (split /,/, $defineset);
&insertindex(\%configurations, $fullconf);
}
elsif (/^### autotest revision (.+)/)
{
if (defined $revision && $revision != $1)
{
print STDERR "Autotest build report contains several revisions: $revision, $1\n";
}
else
{
$revision = $1;
}
}
}
# make arrays of toolsets and configurations
@toolsetarray = ();
@configurationarray = ();
$toolsetarray[$toolsets{$_}] = $_ foreach (keys %toolsets);
$configurationarray[$configurations{$_}] = $_ foreach (keys %configurations);
# print header
$stylesheet = <<END;
table.autotest { border: 1px solid black; border-left: none; border-top: none; }
table.autotest td { border: 1px solid black; border-right: none; border-bottom: none; }
END
print <<END;
<html><head><title>pugixml autotest report</title><style type="text/css"><!-- $stylesheet --></style></head><body>
<h3>pugixml autotest report</h3>
<table border=1 cellspacing=0 cellpadding=4 class="autotest">
END
# print configuration header (release/debug)
print "<tr><td align='right' colspan=2>optimization</td>";
print &prettybox((split /\s+/)[0] eq 'release') foreach (@configurationarray);
print "</tr>\n";
# print defines header (one row for each define)
foreach $define (sort {$a cmp $b} keys %defines)
{
print "<tr><td align='right' colspan=2><small>$define</small></td>";
foreach (@configurationarray)
{
my $present = ($_ =~ /\b$define\b/);
print &prettybox($present);
}
print "</tr>\n";
}
# print data (one row for each toolset)
foreach $tool (@toolsetarray)
{
my ($platform, $toolset) = split(/\s+/, $tool, 2);
print "<tr><td style='border-right: none' align='center'><small>$platform</small></td><td style='border-left: none'><nobr>$toolset</nobr></td>";
foreach (@configurationarray)
{
my $info = $results{$tool}{$_};
if (!defined $$info{result})
{
print "<td bgcolor='#cccccc'>&nbsp;</td>";
}
elsif ($$info{result} eq "success")
{
my $coverage = $$info{coverage};
print "<td bgcolor='#00ff00' align='center'>pass";
if ($coverage > 0)
{
print "<br><font size='-2'>" . ($coverage + 0) . "%</font>";
}
print "</td>";
}
elsif ($$info{result} eq "skiprun")
{
print "<td bgcolor='#ffff80' align='center'>pass</td>"
}
else
{
print "<td bgcolor='#ff0000' align='center'>fail</td>"
}
}
print "</tr>\n";
}
# print footer
$date = localtime;
print <<END;
</table><br>
Generated on $date from Git $revision
</body></html>
END

View file

@ -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

View file

@ -1,8 +0,0 @@
#ifndef HEADER_TEST_COMMON_HPP
#define HEADER_TEST_COMMON_HPP
#include "test.hpp"
using namespace pugi;
#endif

View file

@ -0,0 +1 @@
a/b/c

View file

@ -0,0 +1 @@
sum(nodes) + round(concat(//a[translate(@id, 'abc', '012')]))

View file

@ -0,0 +1 @@
1+2*3 div 4 mod 5-6

View file

@ -0,0 +1 @@
@*/ancestor::*/near-north/*[4]/@*/preceding::text()

View file

@ -0,0 +1 @@
library/nodes[@id=12]/element[@type='translate'][1]

View file

@ -1,16 +1,14 @@
#include "../src/pugixml.hpp"
#include "allocator.hpp"
int main(int argc, const char** argv)
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
pugi::set_memory_management_functions(memory_allocate, memory_deallocate);
pugi::xml_document doc;
for (int i = 1; i < argc; ++i)
{
doc.load_file(argv[i]);
doc.load_file(argv[i], pugi::parse_minimal);
doc.load_file(argv[i], pugi::parse_full);
}
doc.load_buffer(Data, Size);
doc.load_buffer(Data, Size, pugi::parse_minimal);
doc.load_buffer(Data, Size, pugi::parse_full);
return 0;
}

72
tests/fuzz_parse.dict Normal file
View file

@ -0,0 +1,72 @@
#
# AFL dictionary for XML
# ----------------------
#
# Several basic syntax elements and attributes, modeled on libxml2.
#
# Created by Michal Zalewski <lcamtuf@google.com>
#
attr_encoding=" encoding=\"1\""
attr_generic=" a=\"1\""
attr_href=" href=\"1\""
attr_standalone=" standalone=\"no\""
attr_version=" version=\"1\""
attr_xml_base=" xml:base=\"1\""
attr_xml_id=" xml:id=\"1\""
attr_xml_lang=" xml:lang=\"1\""
attr_xml_space=" xml:space=\"1\""
attr_xmlns=" xmlns=\"1\""
entity_builtin="&lt;"
entity_decimal="&#1;"
entity_external="&a;"
entity_hex="&#x1;"
string_any="ANY"
string_brackets="[]"
string_cdata="CDATA"
string_col_fallback=":fallback"
string_col_generic=":a"
string_col_include=":include"
string_dashes="--"
string_empty="EMPTY"
string_empty_dblquotes="\"\""
string_empty_quotes="''"
string_entities="ENTITIES"
string_entity="ENTITY"
string_fixed="#FIXED"
string_id="ID"
string_idref="IDREF"
string_idrefs="IDREFS"
string_implied="#IMPLIED"
string_nmtoken="NMTOKEN"
string_nmtokens="NMTOKENS"
string_notation="NOTATION"
string_parentheses="()"
string_pcdata="#PCDATA"
string_percent="%a"
string_public="PUBLIC"
string_required="#REQUIRED"
string_schema=":schema"
string_system="SYSTEM"
string_ucs4="UCS-4"
string_utf16="UTF-16"
string_utf8="UTF-8"
string_xmlns="xmlns:"
tag_attlist="<!ATTLIST"
tag_cdata="<![CDATA["
tag_close="</a>"
tag_doctype="<!DOCTYPE"
tag_element="<!ELEMENT"
tag_entity="<!ENTITY"
tag_ignore="<![IGNORE["
tag_include="<![INCLUDE["
tag_notation="<!NOTATION"
tag_open="<a>"
tag_open_close="<a />"
tag_open_exclamation="<!"
tag_open_q="<?"
tag_sq2_close="]]>"
tag_xml_q="<?xml?>"

11
tests/fuzz_setup.sh Executable file
View file

@ -0,0 +1,11 @@
#!/bin/bash
sudo apt-get --yes install subversion screen gcc g++ cmake ninja-build golang autoconf libtool apache2 python-dev pkg-config zlib1g-dev libgcrypt11-dev
mkdir -p clang
cd clang
git clone https://chromium.googlesource.com/chromium/src/tools/clang
cd ..
clang/clang/scripts/update.py
sudo cp -rf third_party/llvm-build/Release+Asserts/lib/* /usr/local/lib/
sudo cp -rf third_party/llvm-build/Release+Asserts/bin/* /usr/local/bin

26
tests/fuzz_xpath.cpp Normal file
View file

@ -0,0 +1,26 @@
#include "../src/pugixml.hpp"
#include <stdint.h>
#include <string.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
char* text = new char[Size + 1];
memcpy(text, Data, Size);
text[Size] = 0;
#ifdef PUGIXML_NO_EXCEPTIONS
pugi::xpath_query q(text);
#else
try
{
pugi::xpath_query q(text);
}
catch (pugi::xpath_exception&)
{
}
#endif
delete[] text;
return 0;
}

72
tests/fuzz_xpath.dict Normal file
View file

@ -0,0 +1,72 @@
"boolean"
"count"
"contains"
"concat"
"ceiling"
"false"
"floor"
"id"
"last"
"lang"
"local-name"
"name"
"namespace-uri"
"normalize-space"
"not"
"number"
"position"
"round"
"string"
"string-length"
"starts-with"
"substring-before"
"substring-after"
"substring"
"sum"
"translate"
"true"
"ancestor"
"ancestor-or-self"
"attribute"
"child"
"descendant"
"descendant-or-self"
"following"
"following-sibling"
"namespace"
"parent"
"preceding"
"preceding-sibling"
"self"
"comment"
"node"
"processing-instruction"
"text"
"or"
"and"
"div"
"mod"
">"
">="
"<"
"<="
"!"
"!="
"="
"+"
"-"
"*"
"|"
"$"
"("
")"
"["
"]"
","
"//"
"/"
".."
"."
"@"
"::"
":"

View file

@ -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('', <STDIN>);
# 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";
}

View file

@ -1,7 +1,7 @@
#ifndef HEADER_TEST_HELPERS_HPP
#define HEADER_TEST_HELPERS_HPP
#include "common.hpp"
#include "test.hpp"
#include <utility>

View file

@ -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;
@ -39,22 +41,34 @@ static void* custom_allocate(size_t size)
else
{
void* ptr = memory_allocate(size);
assert(ptr);
if (!ptr) return 0;
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<unsigned int>(g_memory_total_size), static_cast<unsigned int>(g_memory_total_count));
printf("Test %s failed: memory leaks found (%u bytes in %u allocations)\n", test_name, static_cast<unsigned int>(g_memory_total_size), static_cast<unsigned int>(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,16 @@ 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);
if (g_memory_fail_triggered)
{
// run tests that trigger memory failures twice - with an allocator that returns NULL and with an allocator that throws
#ifndef PUGIXML_NO_EXCEPTIONS
total++;
passed += run_test(test, (test->_name + std::string(" (throw)")).c_str(), custom_allocate_throw);
#endif
}
}
unsigned int failed = total - passed;

View file

@ -117,7 +117,7 @@ bool test_xpath_number(const pugi::xpath_node& node, const pugi::char_t* query,
double value = q.evaluate_number(node);
double absolute_error = fabs(value - expected);
const double tolerance = 1e-15f;
const double tolerance = 1e-15;
return absolute_error < tolerance || absolute_error < fabs(expected) * tolerance;
}

View file

@ -5,6 +5,10 @@
#include <setjmp.h>
#ifndef PUGIXML_NO_EXCEPTIONS
#include <new>
#endif
struct test_runner
{
test_runner(const char* name)
@ -78,7 +82,7 @@ struct dummy_fixture {};
{ \
test_runner_##name(): test_runner(#name) {} \
\
virtual void run() \
virtual void run() PUGIXML_OVERRIDE \
{ \
test_runner_helper_##name helper; \
helper.run(); \
@ -112,8 +116,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 +146,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)

150
tests/test_compact.cpp Normal file
View file

@ -0,0 +1,150 @@
#ifdef PUGIXML_COMPACT
#include "test.hpp"
using namespace pugi;
static void overflow_hash_table(xml_document& doc)
{
xml_node n = doc.child(STR("n"));
// compact encoding assumes next_sibling is a forward-only pointer so we can allocate hash entries by reordering nodes
// we allocate enough hash entries to be exactly on the edge of rehash threshold
for (int i = 0; i < 8; ++i)
CHECK(n.prepend_child(node_element));
}
TEST_XML_FLAGS(compact_out_of_memory_string, "<n a='v'/><?n v?>", parse_pi)
{
test_runner::_memory_fail_threshold = 1;
overflow_hash_table(doc);
xml_attribute a = doc.child(STR("n")).attribute(STR("a"));
xml_node pi = doc.last_child();
CHECK_ALLOC_FAIL(CHECK(!pi.set_name(STR("name"))));
CHECK_ALLOC_FAIL(CHECK(!pi.set_value(STR("value"))));
CHECK_ALLOC_FAIL(CHECK(!a.set_name(STR("name"))));
CHECK_ALLOC_FAIL(CHECK(!a.set_value(STR("value"))));
}
TEST_XML(compact_out_of_memory_attribute, "<n a='v'/>")
{
test_runner::_memory_fail_threshold = 1;
overflow_hash_table(doc);
xml_node n = doc.child(STR("n"));
xml_attribute a = n.attribute(STR("a"));
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)));
}
TEST_XML(compact_out_of_memory_attribute_copy, "<n a='v'/>")
{
test_runner::_memory_fail_threshold = 1;
overflow_hash_table(doc);
xml_node n = doc.child(STR("n"));
xml_attribute a = n.attribute(STR("a"));
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_XML(compact_out_of_memory_node, "<n/>")
{
test_runner::_memory_fail_threshold = 1;
overflow_hash_table(doc);
xml_node n = doc.child(STR("n"));
CHECK_ALLOC_FAIL(CHECK(!doc.append_child(node_element)));
CHECK_ALLOC_FAIL(CHECK(!doc.prepend_child(node_element)));
CHECK_ALLOC_FAIL(CHECK(!doc.insert_child_after(node_element, n)));
CHECK_ALLOC_FAIL(CHECK(!doc.insert_child_before(node_element, n)));
}
TEST_XML(compact_out_of_memory_node_copy, "<n/>")
{
test_runner::_memory_fail_threshold = 1;
overflow_hash_table(doc);
xml_node n = doc.child(STR("n"));
CHECK_ALLOC_FAIL(CHECK(!doc.append_copy(n)));
CHECK_ALLOC_FAIL(CHECK(!doc.prepend_copy(n)));
CHECK_ALLOC_FAIL(CHECK(!doc.insert_copy_after(n, n)));
CHECK_ALLOC_FAIL(CHECK(!doc.insert_copy_before(n, n)));
}
TEST_XML(compact_out_of_memory_node_move, "<n/><ne/>")
{
test_runner::_memory_fail_threshold = 1;
overflow_hash_table(doc);
xml_node n = doc.child(STR("n"));
xml_node ne = doc.child(STR("ne"));
CHECK_ALLOC_FAIL(CHECK(!doc.append_move(n)));
CHECK_ALLOC_FAIL(CHECK(!doc.prepend_move(n)));
CHECK_ALLOC_FAIL(CHECK(!doc.insert_move_after(n, ne)));
CHECK_ALLOC_FAIL(CHECK(!doc.insert_move_before(n, ne)));
}
TEST_XML(compact_out_of_memory_remove, "<n a='v'/>")
{
test_runner::_memory_fail_threshold = 1;
overflow_hash_table(doc);
xml_node n = doc.child(STR("n"));
xml_attribute a = n.attribute(STR("a"));
CHECK_ALLOC_FAIL(CHECK(!n.remove_attribute(a)));
CHECK_ALLOC_FAIL(CHECK(!doc.remove_child(n)));
}
TEST_XML(compact_pointer_attribute_list, "<n a='v'/>")
{
xml_node n = doc.child(STR("n"));
xml_attribute a = n.attribute(STR("a"));
// make sure we fill the page with node x
for (int i = 0; i < 1000; ++i)
doc.append_child(STR("x"));
// this requires extended encoding for prev_attribute_c/next_attribute
n.append_attribute(STR("b"));
// this requires extended encoding for first_attribute
n.remove_attribute(a);
CHECK(!n.attribute(STR("a")));
CHECK(n.attribute(STR("b")));
}
TEST_XML(compact_pointer_node_list, "<n/>")
{
xml_node n = doc.child(STR("n"));
// make sure we fill the page with node x
// this requires extended encoding for prev_sibling_c/next_sibling
for (int i = 0; i < 1000; ++i)
doc.append_child(STR("x"));
// this requires extended encoding for first_child
n.append_child(STR("child"));
CHECK(n.child(STR("child")));
}
#endif

25
tests/test_deprecated.cpp Normal file
View file

@ -0,0 +1,25 @@
#define PUGIXML_DEPRECATED // Suppress deprecated declarations to avoid warnings
#include "test.hpp"
using namespace pugi;
TEST(document_deprecated_load)
{
xml_document doc;
CHECK(doc.load(STR("<node/>")));
CHECK_NODE(doc, STR("<node/>"));
}
#ifndef PUGIXML_NO_XPATH
TEST_XML(xpath_api_deprecated_select_single_node, "<node><head/><foo id='1'/><foo/><tail/></node>")
{
xpath_node n1 = doc.select_single_node(STR("node/foo"));
xpath_query q(STR("node/foo"));
xpath_node n2 = doc.select_single_node(q);
CHECK(n1.node().attribute(STR("id")).as_int() == 1);
CHECK(n2.node().attribute(STR("id")).as_int() == 1);
}
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,381 +1,487 @@
#include "common.hpp"
#include "helpers.hpp"
TEST_XML_FLAGS(dom_text_empty, "<node><a>foo</a><b><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("a")).text());
CHECK(node.child(STR("b")).text());
CHECK(!node.child(STR("c")).text());
CHECK(!node.child(STR("d")).text());
CHECK(!xml_node().text());
CHECK(!xml_text());
generic_empty_test(node.child(STR("a")).text());
}
TEST_XML(dom_text_bool_ops, "<node>foo</node>")
{
generic_bool_ops_test(doc.child(STR("node")).text());
}
TEST_XML_FLAGS(dom_text_get, "<node><a>foo</a><b><node/><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
CHECK_STRING(node.child(STR("a")).text().get(), STR("foo"));
CHECK_STRING(node.child(STR("a")).first_child().text().get(), STR("foo"));
CHECK_STRING(node.child(STR("b")).text().get(), STR("bar"));
CHECK_STRING(node.child(STR("b")).last_child().text().get(), STR("bar"));
CHECK_STRING(node.child(STR("c")).text().get(), STR(""));
CHECK_STRING(node.child(STR("c")).first_child().text().get(), STR(""));
CHECK_STRING(node.child(STR("d")).text().get(), STR(""));
CHECK_STRING(xml_node().text().get(), STR(""));
}
TEST_XML_FLAGS(dom_text_as_string, "<node><a>foo</a><b><node/><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
CHECK_STRING(node.child(STR("a")).text().as_string(), STR("foo"));
CHECK_STRING(node.child(STR("a")).first_child().text().as_string(), STR("foo"));
CHECK_STRING(node.child(STR("b")).text().as_string(), STR("bar"));
CHECK_STRING(node.child(STR("b")).last_child().text().as_string(), STR("bar"));
CHECK_STRING(node.child(STR("c")).text().as_string(), STR(""));
CHECK_STRING(node.child(STR("c")).first_child().text().as_string(), STR(""));
CHECK_STRING(node.child(STR("d")).text().as_string(), STR(""));
CHECK_STRING(xml_node().text().as_string(), STR(""));
}
TEST_XML(dom_text_as_int, "<node><text1>1</text1><text2>-1</text2><text3>-2147483648</text3><text4>2147483647</text4><text5>0</text5></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_int() == 0);
CHECK(node.child(STR("text1")).text().as_int() == 1);
CHECK(node.child(STR("text2")).text().as_int() == -1);
CHECK(node.child(STR("text3")).text().as_int() == -2147483647 - 1);
CHECK(node.child(STR("text4")).text().as_int() == 2147483647);
CHECK(node.child(STR("text5")).text().as_int() == 0);
}
TEST_XML(dom_text_as_int_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>-0x20</text4><text5>-0x80000000</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_int() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_int() == 1451);
CHECK(node.child(STR("text3")).text().as_int() == 255);
CHECK(node.child(STR("text4")).text().as_int() == -32);
CHECK(node.child(STR("text5")).text().as_int() == -2147483647 - 1);
CHECK(node.child(STR("text6")).text().as_int() == 0);
}
TEST_XML(dom_text_as_uint, "<node><text1>0</text1><text2>1</text2><text3>2147483647</text3><text4>4294967295</text4><text5>0</text5></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_uint() == 0);
CHECK(node.child(STR("text1")).text().as_uint() == 0);
CHECK(node.child(STR("text2")).text().as_uint() == 1);
CHECK(node.child(STR("text3")).text().as_uint() == 2147483647);
CHECK(node.child(STR("text4")).text().as_uint() == 4294967295u);
CHECK(node.child(STR("text5")).text().as_uint() == 0);
}
TEST_XML(dom_text_as_uint_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>0x20</text4><text5>0xFFFFFFFF</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_uint() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_uint() == 1451);
CHECK(node.child(STR("text3")).text().as_uint() == 255);
CHECK(node.child(STR("text4")).text().as_uint() == 32);
CHECK(node.child(STR("text5")).text().as_uint() == 4294967295u);
CHECK(node.child(STR("text6")).text().as_uint() == 0);
}
TEST_XML(dom_text_as_integer_space, "<node><text1> \t\n1234</text1><text2>\n\t 0x123</text2><text3>- 16</text3><text4>- 0x10</text4></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_int() == 1234);
CHECK(node.child(STR("text2")).text().as_int() == 291);
CHECK(node.child(STR("text3")).text().as_int() == 0);
CHECK(node.child(STR("text4")).text().as_int() == 0);
}
TEST_XML(dom_text_as_float, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_float() == 0);
CHECK_DOUBLE(node.child(STR("text1")).text().as_float(), 0);
CHECK_DOUBLE(node.child(STR("text2")).text().as_float(), 1);
CHECK_DOUBLE(node.child(STR("text3")).text().as_float(), 0.12);
CHECK_DOUBLE(node.child(STR("text4")).text().as_float(), -5.1);
CHECK_DOUBLE(node.child(STR("text5")).text().as_float(), 3e-4);
CHECK_DOUBLE(node.child(STR("text6")).text().as_float(), 3.14159265358979323846);
}
TEST_XML(dom_text_as_double, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_double() == 0);
CHECK_DOUBLE(node.child(STR("text1")).text().as_double(), 0);
CHECK_DOUBLE(node.child(STR("text2")).text().as_double(), 1);
CHECK_DOUBLE(node.child(STR("text3")).text().as_double(), 0.12);
CHECK_DOUBLE(node.child(STR("text4")).text().as_double(), -5.1);
CHECK_DOUBLE(node.child(STR("text5")).text().as_double(), 3e-4);
CHECK_DOUBLE(node.child(STR("text6")).text().as_double(), 3.14159265358979323846);
}
TEST_XML(dom_text_as_bool, "<node><text1>0</text1><text2>1</text2><text3>true</text3><text4>True</text4><text5>Yes</text5><text6>yes</text6><text7>false</text7></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(!xml_text().as_bool());
CHECK(!node.child(STR("text1")).text().as_bool());
CHECK(node.child(STR("text2")).text().as_bool());
CHECK(node.child(STR("text3")).text().as_bool());
CHECK(node.child(STR("text4")).text().as_bool());
CHECK(node.child(STR("text5")).text().as_bool());
CHECK(node.child(STR("text6")).text().as_bool());
CHECK(!node.child(STR("text7")).text().as_bool());
}
#ifdef PUGIXML_HAS_LONG_LONG
TEST_XML(dom_text_as_llong, "<node><text1>1</text1><text2>-1</text2><text3>-9223372036854775808</text3><text4>9223372036854775807</text4><text5>0</text5></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_llong() == 0);
CHECK(node.child(STR("text1")).text().as_llong() == 1);
CHECK(node.child(STR("text2")).text().as_llong() == -1);
CHECK(node.child(STR("text3")).text().as_llong() == -9223372036854775807ll - 1);
CHECK(node.child(STR("text4")).text().as_llong() == 9223372036854775807ll);
CHECK(node.child(STR("text5")).text().as_llong() == 0);
}
TEST_XML(dom_text_as_llong_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>-0x20</text4><text5>-0x8000000000000000</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_llong() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_llong() == 1451);
CHECK(node.child(STR("text3")).text().as_llong() == 255);
CHECK(node.child(STR("text4")).text().as_llong() == -32);
CHECK(node.child(STR("text5")).text().as_llong() == -9223372036854775807ll - 1);
CHECK(node.child(STR("text6")).text().as_llong() == 0);
}
TEST_XML(dom_text_as_ullong, "<node><text1>0</text1><text2>1</text2><text3>9223372036854775807</text3><text4>18446744073709551615</text4><text5>0</text5></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_ullong() == 0);
CHECK(node.child(STR("text1")).text().as_ullong() == 0);
CHECK(node.child(STR("text2")).text().as_ullong() == 1);
CHECK(node.child(STR("text3")).text().as_ullong() == 9223372036854775807ll);
CHECK(node.child(STR("text4")).text().as_ullong() == 18446744073709551615ull);
CHECK(node.child(STR("text5")).text().as_ullong() == 0);
}
TEST_XML(dom_text_as_ullong_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>0x20</text4><text5>0xFFFFFFFFFFFFFFFF</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_ullong() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_ullong() == 1451);
CHECK(node.child(STR("text3")).text().as_ullong() == 255);
CHECK(node.child(STR("text4")).text().as_ullong() == 32);
CHECK(node.child(STR("text5")).text().as_ullong() == 18446744073709551615ull);
CHECK(node.child(STR("text6")).text().as_ullong() == 0);
}
#endif
TEST_XML(dom_text_get_no_state, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
CHECK(!t);
CHECK(t.get() && *t.get() == 0);
CHECK(!node.first_child());
node.append_child(node_pcdata);
CHECK(t);
CHECK_STRING(t.get(), STR(""));
node.first_child().set_value(STR("test"));
CHECK(t);
CHECK_STRING(t.get(), STR("test"));
}
TEST_XML(dom_text_set, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(STR(""));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node></node>"));
t.set(STR("boo"));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(STR("foobarfoobar"));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foobarfoobar</node>"));
}
TEST_XML(dom_text_assign, "<node/>")
{
xml_node node = doc.child(STR("node"));
node.append_child(STR("text1")).text() = STR("v1");
xml_text() = STR("v1");
node.append_child(STR("text2")).text() = -2147483647;
node.append_child(STR("text3")).text() = -2147483647 - 1;
xml_text() = -2147483647 - 1;
node.append_child(STR("text4")).text() = 4294967295u;
node.append_child(STR("text5")).text() = 4294967294u;
xml_text() = 4294967295u;
node.append_child(STR("text6")).text() = 0.5;
xml_text() = 0.5;
node.append_child(STR("text7")).text() = 0.25f;
xml_text() = 0.25f;
node.append_child(STR("text8")).text() = true;
xml_text() = true;
CHECK_NODE(node, STR("<node><text1>v1</text1><text2>-2147483647</text2><text3>-2147483648</text3><text4>4294967295</text4><text5>4294967294</text5><text6>0.5</text6><text7>0.25</text7><text8>true</text8></node>"));
}
TEST_XML(dom_text_set_value, "<node/>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.append_child(STR("text1")).text().set(STR("v1")));
CHECK(!xml_text().set(STR("v1")));
CHECK(node.append_child(STR("text2")).text().set(-2147483647));
CHECK(node.append_child(STR("text3")).text().set(-2147483647 - 1));
CHECK(!xml_text().set(-2147483647 - 1));
CHECK(node.append_child(STR("text4")).text().set(4294967295u));
CHECK(node.append_child(STR("text5")).text().set(4294967294u));
CHECK(!xml_text().set(4294967295u));
CHECK(node.append_child(STR("text6")).text().set(0.5));
CHECK(!xml_text().set(0.5));
CHECK(node.append_child(STR("text7")).text().set(0.25f));
CHECK(!xml_text().set(0.25f));
CHECK(node.append_child(STR("text8")).text().set(true));
CHECK(!xml_text().set(true));
CHECK_NODE(node, STR("<node><text1>v1</text1><text2>-2147483647</text2><text3>-2147483648</text3><text4>4294967295</text4><text5>4294967294</text5><text6>0.5</text6><text7>0.25</text7><text8>true</text8></node>"));
}
#ifdef PUGIXML_HAS_LONG_LONG
TEST_XML(dom_text_assign_llong, "<node/>")
{
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;
node.append_child(STR("text3")).text() = 18446744073709551615ull;
node.append_child(STR("text4")).text() = 18446744073709551614ull;
xml_text() = 18446744073709551615ull;
CHECK_NODE(node, STR("<node><text1>-9223372036854775807</text1><text2>-9223372036854775808</text2><text3>18446744073709551615</text3><text4>18446744073709551614</text4></node>"));
}
TEST_XML(dom_text_set_value_llong, "<node/>")
{
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));
CHECK(node.append_child(STR("text3")).text().set(18446744073709551615ull));
CHECK(node.append_child(STR("text4")).text().set(18446744073709551614ull));
CHECK(!xml_text().set(18446744073709551615ull));
CHECK_NODE(node, STR("<node><text1>-9223372036854775807</text1><text2>-9223372036854775808</text2><text3>18446744073709551615</text3><text4>18446744073709551614</text4></node>"));
}
#endif
TEST_XML(dom_text_middle, "<node><c1>notthisone</c1>text<c2/></node>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
CHECK_STRING(t.get(), STR("text"));
t.set(STR("notext"));
CHECK_NODE(node, STR("<node><c1>notthisone</c1>notext<c2 /></node>"));
CHECK(node.remove_child(t.data()));
CHECK(!t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2 /></node>"));
t.set(STR("yestext"));
CHECK(t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2 />yestext</node>"));
CHECK(t.data() == node.last_child());
}
TEST_XML_FLAGS(dom_text_data, "<node><a>foo</a><b><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("a")).text().data() == node.child(STR("a")).first_child());
CHECK(node.child(STR("b")).text().data() == node.child(STR("b")).first_child());
CHECK(!node.child(STR("c")).text().data());
CHECK(!node.child(STR("d")).text().data());
CHECK(!xml_text().data());
}
TEST(dom_text_defaults)
{
xml_text text;
CHECK_STRING(text.as_string(STR("foo")), STR("foo"));
CHECK(text.as_int(42) == 42);
CHECK(text.as_uint(42) == 42);
CHECK(text.as_double(42) == 42);
CHECK(text.as_float(42) == 42);
CHECK(text.as_bool(true) == true);
#ifdef PUGIXML_HAS_LONG_LONG
CHECK(text.as_llong(42) == 42);
CHECK(text.as_ullong(42) == 42);
#endif
}
#include "test.hpp"
#include "helpers.hpp"
#include <limits.h>
using namespace pugi;
TEST_XML_FLAGS(dom_text_empty, "<node><a>foo</a><b><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("a")).text());
CHECK(node.child(STR("b")).text());
CHECK(!node.child(STR("c")).text());
CHECK(!node.child(STR("d")).text());
CHECK(!xml_node().text());
CHECK(!xml_text());
generic_empty_test(node.child(STR("a")).text());
}
TEST_XML(dom_text_bool_ops, "<node>foo</node>")
{
generic_bool_ops_test(doc.child(STR("node")).text());
}
TEST_XML_FLAGS(dom_text_get, "<node><a>foo</a><b><node/><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
CHECK_STRING(node.child(STR("a")).text().get(), STR("foo"));
CHECK_STRING(node.child(STR("a")).first_child().text().get(), STR("foo"));
CHECK_STRING(node.child(STR("b")).text().get(), STR("bar"));
CHECK_STRING(node.child(STR("b")).last_child().text().get(), STR("bar"));
CHECK_STRING(node.child(STR("c")).text().get(), STR(""));
CHECK_STRING(node.child(STR("c")).first_child().text().get(), STR(""));
CHECK_STRING(node.child(STR("d")).text().get(), STR(""));
CHECK_STRING(xml_node().text().get(), STR(""));
}
TEST_XML_FLAGS(dom_text_as_string, "<node><a>foo</a><b><node/><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
CHECK_STRING(node.child(STR("a")).text().as_string(), STR("foo"));
CHECK_STRING(node.child(STR("a")).first_child().text().as_string(), STR("foo"));
CHECK_STRING(node.child(STR("b")).text().as_string(), STR("bar"));
CHECK_STRING(node.child(STR("b")).last_child().text().as_string(), STR("bar"));
CHECK_STRING(node.child(STR("c")).text().as_string(), STR(""));
CHECK_STRING(node.child(STR("c")).first_child().text().as_string(), STR(""));
CHECK_STRING(node.child(STR("d")).text().as_string(), STR(""));
CHECK_STRING(xml_node().text().as_string(), STR(""));
}
TEST_XML(dom_text_as_int, "<node><text1>1</text1><text2>-1</text2><text3>-2147483648</text3><text4>2147483647</text4><text5>0</text5></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_int() == 0);
CHECK(node.child(STR("text1")).text().as_int() == 1);
CHECK(node.child(STR("text2")).text().as_int() == -1);
CHECK(node.child(STR("text3")).text().as_int() == -2147483647 - 1);
CHECK(node.child(STR("text4")).text().as_int() == 2147483647);
CHECK(node.child(STR("text5")).text().as_int() == 0);
}
TEST_XML(dom_text_as_int_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>-0x20</text4><text5>-0x80000000</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_int() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_int() == 1451);
CHECK(node.child(STR("text3")).text().as_int() == 255);
CHECK(node.child(STR("text4")).text().as_int() == -32);
CHECK(node.child(STR("text5")).text().as_int() == -2147483647 - 1);
CHECK(node.child(STR("text6")).text().as_int() == 0);
}
TEST_XML(dom_text_as_uint, "<node><text1>0</text1><text2>1</text2><text3>2147483647</text3><text4>4294967295</text4><text5>0</text5></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_uint() == 0);
CHECK(node.child(STR("text1")).text().as_uint() == 0);
CHECK(node.child(STR("text2")).text().as_uint() == 1);
CHECK(node.child(STR("text3")).text().as_uint() == 2147483647);
CHECK(node.child(STR("text4")).text().as_uint() == 4294967295u);
CHECK(node.child(STR("text5")).text().as_uint() == 0);
}
TEST_XML(dom_text_as_uint_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>0x20</text4><text5>0xFFFFFFFF</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_uint() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_uint() == 1451);
CHECK(node.child(STR("text3")).text().as_uint() == 255);
CHECK(node.child(STR("text4")).text().as_uint() == 32);
CHECK(node.child(STR("text5")).text().as_uint() == 4294967295u);
CHECK(node.child(STR("text6")).text().as_uint() == 0);
}
TEST_XML(dom_text_as_integer_space, "<node><text1> \t\n1234</text1><text2>\n\t 0x123</text2><text3>- 16</text3><text4>- 0x10</text4></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_int() == 1234);
CHECK(node.child(STR("text2")).text().as_int() == 291);
CHECK(node.child(STR("text3")).text().as_int() == 0);
CHECK(node.child(STR("text4")).text().as_int() == 0);
}
TEST_XML(dom_text_as_float, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_float() == 0);
CHECK_DOUBLE(double(node.child(STR("text1")).text().as_float()), 0);
CHECK_DOUBLE(double(node.child(STR("text2")).text().as_float()), 1);
CHECK_DOUBLE(double(node.child(STR("text3")).text().as_float()), 0.12);
CHECK_DOUBLE(double(node.child(STR("text4")).text().as_float()), -5.1);
CHECK_DOUBLE(double(node.child(STR("text5")).text().as_float()), 3e-4);
CHECK_DOUBLE(double(node.child(STR("text6")).text().as_float()), 3.14159265358979323846);
}
TEST_XML(dom_text_as_double, "<node><text1>0</text1><text2>1</text2><text3>0.12</text3><text4>-5.1</text4><text5>3e-4</text5><text6>3.14159265358979323846</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_double() == 0);
CHECK_DOUBLE(node.child(STR("text1")).text().as_double(), 0);
CHECK_DOUBLE(node.child(STR("text2")).text().as_double(), 1);
CHECK_DOUBLE(node.child(STR("text3")).text().as_double(), 0.12);
CHECK_DOUBLE(node.child(STR("text4")).text().as_double(), -5.1);
CHECK_DOUBLE(node.child(STR("text5")).text().as_double(), 3e-4);
CHECK_DOUBLE(node.child(STR("text6")).text().as_double(), 3.14159265358979323846);
}
TEST_XML(dom_text_as_bool, "<node><text1>0</text1><text2>1</text2><text3>true</text3><text4>True</text4><text5>Yes</text5><text6>yes</text6><text7>false</text7></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(!xml_text().as_bool());
CHECK(!node.child(STR("text1")).text().as_bool());
CHECK(node.child(STR("text2")).text().as_bool());
CHECK(node.child(STR("text3")).text().as_bool());
CHECK(node.child(STR("text4")).text().as_bool());
CHECK(node.child(STR("text5")).text().as_bool());
CHECK(node.child(STR("text6")).text().as_bool());
CHECK(!node.child(STR("text7")).text().as_bool());
}
#ifdef PUGIXML_HAS_LONG_LONG
TEST_XML(dom_text_as_llong, "<node><text1>1</text1><text2>-1</text2><text3>-9223372036854775808</text3><text4>9223372036854775807</text4><text5>0</text5></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_llong() == 0);
CHECK(node.child(STR("text1")).text().as_llong() == 1);
CHECK(node.child(STR("text2")).text().as_llong() == -1);
CHECK(node.child(STR("text3")).text().as_llong() == -9223372036854775807ll - 1);
CHECK(node.child(STR("text4")).text().as_llong() == 9223372036854775807ll);
CHECK(node.child(STR("text5")).text().as_llong() == 0);
}
TEST_XML(dom_text_as_llong_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>-0x20</text4><text5>-0x8000000000000000</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_llong() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_llong() == 1451);
CHECK(node.child(STR("text3")).text().as_llong() == 255);
CHECK(node.child(STR("text4")).text().as_llong() == -32);
CHECK(node.child(STR("text5")).text().as_llong() == -9223372036854775807ll - 1);
CHECK(node.child(STR("text6")).text().as_llong() == 0);
}
TEST_XML(dom_text_as_ullong, "<node><text1>0</text1><text2>1</text2><text3>9223372036854775807</text3><text4>18446744073709551615</text4><text5>0</text5></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(xml_text().as_ullong() == 0);
CHECK(node.child(STR("text1")).text().as_ullong() == 0);
CHECK(node.child(STR("text2")).text().as_ullong() == 1);
CHECK(node.child(STR("text3")).text().as_ullong() == 9223372036854775807ll);
CHECK(node.child(STR("text4")).text().as_ullong() == 18446744073709551615ull);
CHECK(node.child(STR("text5")).text().as_ullong() == 0);
}
TEST_XML(dom_text_as_ullong_hex, "<node><text1>0777</text1><text2>0x5ab</text2><text3>0XFf</text3><text4>0x20</text4><text5>0xFFFFFFFFFFFFFFFF</text5><text6>0x</text6></node>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("text1")).text().as_ullong() == 777); // no octal support! intentional
CHECK(node.child(STR("text2")).text().as_ullong() == 1451);
CHECK(node.child(STR("text3")).text().as_ullong() == 255);
CHECK(node.child(STR("text4")).text().as_ullong() == 32);
CHECK(node.child(STR("text5")).text().as_ullong() == 18446744073709551615ull);
CHECK(node.child(STR("text6")).text().as_ullong() == 0);
}
#endif
TEST_XML(dom_text_get_no_state, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
CHECK(!t);
CHECK(t.get() && *t.get() == 0);
CHECK(!node.first_child());
node.append_child(node_pcdata);
CHECK(t);
CHECK_STRING(t.get(), STR(""));
node.first_child().set_value(STR("test"));
CHECK(t);
CHECK_STRING(t.get(), STR("test"));
}
TEST_XML(dom_text_set, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(STR(""));
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node></node>"));
t.set(STR("boo"));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(STR("foobarfoobar"));
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foobarfoobar</node>"));
}
TEST_XML(dom_text_set_with_size, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(STR(""), 0);
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node></node>"));
t.set(STR("boo"), 3);
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(STR("foobarfoobar"), 12);
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foobarfoobar</node>"));
}
TEST_XML(dom_text_set_partially_with_size, "<node/>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
t.set(STR("foo"), 0);
CHECK(node.first_child().type() == node_pcdata);
CHECK_NODE(node, STR("<node></node>"));
t.set(STR("boofoo"), 3);
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>boo</node>"));
t.set(STR("foobarfoobar"), 3);
CHECK(node.first_child().type() == node_pcdata);
CHECK(node.first_child() == node.last_child());
CHECK_NODE(node, STR("<node>foo</node>"));
}
TEST_XML(dom_text_assign, "<node/>")
{
xml_node node = doc.child(STR("node"));
node.append_child(STR("text1")).text() = STR("v1");
xml_text() = STR("v1");
node.append_child(STR("text2")).text() = -2147483647;
node.append_child(STR("text3")).text() = -2147483647 - 1;
xml_text() = -2147483647 - 1;
node.append_child(STR("text4")).text() = 4294967295u;
node.append_child(STR("text5")).text() = 4294967294u;
xml_text() = 4294967295u;
node.append_child(STR("text6")).text() = 0.5;
xml_text() = 0.5;
node.append_child(STR("text7")).text() = 0.25f;
xml_text() = 0.25f;
node.append_child(STR("text8")).text() = true;
xml_text() = true;
CHECK_NODE(node, STR("<node><text1>v1</text1><text2>-2147483647</text2><text3>-2147483648</text3><text4>4294967295</text4><text5>4294967294</text5><text6>0.5</text6><text7>0.25</text7><text8>true</text8></node>"));
}
TEST_XML(dom_text_set_value, "<node/>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.append_child(STR("text1")).text().set(STR("v1")));
CHECK(!xml_text().set(STR("v1")));
CHECK(node.append_child(STR("text2")).text().set(-2147483647));
CHECK(node.append_child(STR("text3")).text().set(-2147483647 - 1));
CHECK(!xml_text().set(-2147483647 - 1));
CHECK(node.append_child(STR("text4")).text().set(4294967295u));
CHECK(node.append_child(STR("text5")).text().set(4294967294u));
CHECK(!xml_text().set(4294967295u));
CHECK(node.append_child(STR("text6")).text().set(0.5));
CHECK(!xml_text().set(0.5));
CHECK(node.append_child(STR("text7")).text().set(0.25f));
CHECK(!xml_text().set(0.25f));
CHECK(node.append_child(STR("text8")).text().set(true));
CHECK(!xml_text().set(true));
CHECK_NODE(node, STR("<node><text1>v1</text1><text2>-2147483647</text2><text3>-2147483648</text3><text4>4294967295</text4><text5>4294967294</text5><text6>0.5</text6><text7>0.25</text7><text8>true</text8></node>"));
}
#if LONG_MAX > 2147483647
TEST_XML(dom_text_assign_long, "<node/>")
{
xml_node node = doc.child(STR("node"));
node.append_child(STR("text1")).text() = -9223372036854775807l;
node.append_child(STR("text2")).text() = -9223372036854775807l - 1;
xml_text() = -9223372036854775807l - 1;
node.append_child(STR("text3")).text() = 18446744073709551615ul;
node.append_child(STR("text4")).text() = 18446744073709551614ul;
xml_text() = 18446744073709551615ul;
CHECK_NODE(node, STR("<node><text1>-9223372036854775807</text1><text2>-9223372036854775808</text2><text3>18446744073709551615</text3><text4>18446744073709551614</text4></node>"));
}
TEST_XML(dom_text_set_value_long, "<node/>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.append_child(STR("text1")).text().set(-9223372036854775807l));
CHECK(node.append_child(STR("text2")).text().set(-9223372036854775807l - 1));
CHECK(!xml_text().set(-9223372036854775807l - 1));
CHECK(node.append_child(STR("text3")).text().set(18446744073709551615ul));
CHECK(node.append_child(STR("text4")).text().set(18446744073709551614ul));
CHECK(!xml_text().set(18446744073709551615ul));
CHECK_NODE(node, STR("<node><text1>-9223372036854775807</text1><text2>-9223372036854775808</text2><text3>18446744073709551615</text3><text4>18446744073709551614</text4></node>"));
}
#else
TEST_XML(dom_text_assign_long, "<node/>")
{
xml_node node = doc.child(STR("node"));
node.append_child(STR("text1")).text() = -2147483647l;
node.append_child(STR("text2")).text() = -2147483647l - 1;
xml_text() = -2147483647l - 1;
node.append_child(STR("text3")).text() = 4294967295ul;
node.append_child(STR("text4")).text() = 4294967294ul;
xml_text() = 4294967295ul;
CHECK_NODE(node, STR("<node><text1>-2147483647</text1><text2>-2147483648</text2><text3>4294967295</text3><text4>4294967294</text4></node>"));
}
TEST_XML(dom_text_set_value_long, "<node/>")
{
xml_node node = doc.child(STR("node"));
CHECK(node.append_child(STR("text1")).text().set(-2147483647l));
CHECK(node.append_child(STR("text2")).text().set(-2147483647l - 1));
CHECK(!xml_text().set(-2147483647l - 1));
CHECK(node.append_child(STR("text3")).text().set(4294967295ul));
CHECK(node.append_child(STR("text4")).text().set(4294967294ul));
CHECK(!xml_text().set(4294967295ul));
CHECK_NODE(node, STR("<node><text1>-2147483647</text1><text2>-2147483648</text2><text3>4294967295</text3><text4>4294967294</text4></node>"));
}
#endif
#ifdef PUGIXML_HAS_LONG_LONG
TEST_XML(dom_text_assign_llong, "<node/>")
{
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;
node.append_child(STR("text3")).text() = 18446744073709551615ull;
node.append_child(STR("text4")).text() = 18446744073709551614ull;
xml_text() = 18446744073709551615ull;
CHECK_NODE(node, STR("<node><text1>-9223372036854775807</text1><text2>-9223372036854775808</text2><text3>18446744073709551615</text3><text4>18446744073709551614</text4></node>"));
}
TEST_XML(dom_text_set_value_llong, "<node/>")
{
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));
CHECK(node.append_child(STR("text3")).text().set(18446744073709551615ull));
CHECK(node.append_child(STR("text4")).text().set(18446744073709551614ull));
CHECK(!xml_text().set(18446744073709551615ull));
CHECK_NODE(node, STR("<node><text1>-9223372036854775807</text1><text2>-9223372036854775808</text2><text3>18446744073709551615</text3><text4>18446744073709551614</text4></node>"));
}
#endif
TEST_XML(dom_text_middle, "<node><c1>notthisone</c1>text<c2/></node>")
{
xml_node node = doc.child(STR("node"));
xml_text t = node.text();
CHECK_STRING(t.get(), STR("text"));
t.set(STR("notext"));
CHECK_NODE(node, STR("<node><c1>notthisone</c1>notext<c2/></node>"));
CHECK(node.remove_child(t.data()));
CHECK(!t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2/></node>"));
t.set(STR("yestext"));
CHECK(t);
CHECK_NODE(node, STR("<node><c1>notthisone</c1><c2/>yestext</node>"));
CHECK(t.data() == node.last_child());
}
TEST_XML_FLAGS(dom_text_data, "<node><a>foo</a><b><![CDATA[bar]]></b><c><?pi value?></c><d/></node>", parse_default | parse_pi)
{
xml_node node = doc.child(STR("node"));
CHECK(node.child(STR("a")).text().data() == node.child(STR("a")).first_child());
CHECK(node.child(STR("b")).text().data() == node.child(STR("b")).first_child());
CHECK(!node.child(STR("c")).text().data());
CHECK(!node.child(STR("d")).text().data());
CHECK(!xml_text().data());
}
TEST(dom_text_defaults)
{
xml_text text;
CHECK_STRING(text.as_string(STR("foo")), STR("foo"));
CHECK(text.as_int(42) == 42);
CHECK(text.as_uint(42) == 42);
CHECK(text.as_double(42) == 42);
CHECK(text.as_float(42) == 42);
CHECK(text.as_bool(true) == true);
#ifdef PUGIXML_HAS_LONG_LONG
CHECK(text.as_llong(42) == 42);
CHECK(text.as_ullong(42) == 42);
#endif
}

View file

@ -2,7 +2,7 @@
#define _SCL_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_DEPRECATE
#include "common.hpp"
#include "test.hpp"
#include <string.h>
#include <stdio.h>
@ -15,6 +15,8 @@
#include "helpers.hpp"
using namespace pugi;
#ifdef PUGIXML_NO_STL
template <typename I> static I move_iter(I base, int n)
{
@ -57,10 +59,10 @@ TEST_XML(dom_attr_next_previous_attribute, "<node attr1='1' attr2='2' />")
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());
}
@ -137,6 +139,10 @@ TEST_XML(dom_attr_as_integer_space, "<node attr1=' \t1234' attr2='\t 0x123' attr
CHECK(node.attribute(STR("attr2")).as_int() == 291);
CHECK(node.attribute(STR("attr3")).as_int() == 0);
CHECK(node.attribute(STR("attr4")).as_int() == 0);
#ifdef PUGIXML_HAS_LONG_LONG
CHECK(node.attribute(STR("attr1")).as_llong() == 1234);
#endif
}
TEST_XML(dom_attr_as_float, "<node attr1='0' attr2='1' attr3='0.12' attr4='-5.1' attr5='3e-4' attr6='3.14159265358979323846'/>")
@ -144,12 +150,12 @@ TEST_XML(dom_attr_as_float, "<node attr1='0' attr2='1' attr3='0.12' attr4='-5.1'
xml_node node = doc.child(STR("node"));
CHECK(xml_attribute().as_float() == 0);
CHECK_DOUBLE(node.attribute(STR("attr1")).as_float(), 0);
CHECK_DOUBLE(node.attribute(STR("attr2")).as_float(), 1);
CHECK_DOUBLE(node.attribute(STR("attr3")).as_float(), 0.12);
CHECK_DOUBLE(node.attribute(STR("attr4")).as_float(), -5.1);
CHECK_DOUBLE(node.attribute(STR("attr5")).as_float(), 3e-4);
CHECK_DOUBLE(node.attribute(STR("attr6")).as_float(), 3.14159265358979323846);
CHECK_DOUBLE(double(node.attribute(STR("attr1")).as_float()), 0);
CHECK_DOUBLE(double(node.attribute(STR("attr2")).as_float()), 1);
CHECK_DOUBLE(double(node.attribute(STR("attr3")).as_float()), 0.12);
CHECK_DOUBLE(double(node.attribute(STR("attr4")).as_float()), -5.1);
CHECK_DOUBLE(double(node.attribute(STR("attr5")).as_float()), 3e-4);
CHECK_DOUBLE(double(node.attribute(STR("attr6")).as_float()), 3.14159265358979323846);
}
TEST_XML(dom_attr_as_double, "<node attr1='0' attr2='1' attr3='0.12' attr4='-5.1' attr5='3e-4' attr6='3.14159265358979323846'/>")
@ -333,11 +339,11 @@ TEST_XML(dom_attr_iterator_invalidate, "<node><node1 attr1='0'/><node2 attr1='0'
TEST_XML(dom_attr_iterator_const, "<node attr1='0' attr2='1'/>")
{
pugi::xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
const pugi::xml_attribute_iterator i1 = node.attributes_begin();
const pugi::xml_attribute_iterator i2 = ++xml_attribute_iterator(i1);
const pugi::xml_attribute_iterator i3 = ++xml_attribute_iterator(i2);
const xml_attribute_iterator i1 = node.attributes_begin();
const xml_attribute_iterator i2 = ++xml_attribute_iterator(i1);
const xml_attribute_iterator i3 = ++xml_attribute_iterator(i2);
CHECK(*i1 == node.attribute(STR("attr1")));
CHECK(*i2 == node.attribute(STR("attr2")));
@ -455,11 +461,11 @@ TEST_XML(dom_node_iterator_invalidate, "<node><node1><child1/></node1><node2><ch
TEST_XML(dom_node_iterator_const, "<node><child1/><child2/></node>")
{
pugi::xml_node node = doc.child(STR("node"));
xml_node node = doc.child(STR("node"));
const pugi::xml_node_iterator i1 = node.begin();
const pugi::xml_node_iterator i2 = ++xml_node_iterator(i1);
const pugi::xml_node_iterator i3 = ++xml_node_iterator(i2);
const xml_node_iterator i1 = node.begin();
const xml_node_iterator i2 = ++xml_node_iterator(i1);
const xml_node_iterator i3 = ++xml_node_iterator(i2);
CHECK(*i1 == node.child(STR("child1")));
CHECK(*i2 == node.child(STR("child2")));
@ -497,7 +503,7 @@ TEST_XML_FLAGS(dom_node_type, "<?xml?><!DOCTYPE><?pi?><!--comment--><node>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 +522,7 @@ TEST_XML_FLAGS(dom_node_name_value, "<?xml?><!DOCTYPE id><?pi?><!--comment--><no
CHECK_NAME_VALUE(*it++, STR("node"), STR(""));
xml_node_iterator cit = doc.child(STR("node")).begin();
CHECK_NAME_VALUE(*cit++, STR(""), STR("pcdata"));
CHECK_NAME_VALUE(*cit++, STR(""), STR("cdata"));
}
@ -555,10 +561,10 @@ TEST_XML(dom_node_next_previous_sibling, "<node><child1/><child2/><child3/></nod
CHECK(child1.next_sibling() == child2);
CHECK(child3.next_sibling() == xml_node());
CHECK(child1.previous_sibling() == xml_node());
CHECK(child3.previous_sibling() == child2);
CHECK(child1.next_sibling(STR("child3")) == child3);
CHECK(child1.next_sibling(STR("child")) == xml_node());
@ -665,9 +671,9 @@ struct find_predicate_const
struct find_predicate_prefix
{
const pugi::char_t* prefix;
const char_t* prefix;
find_predicate_prefix(const pugi::char_t* prefix_): prefix(prefix_)
find_predicate_prefix(const char_t* prefix_): prefix(prefix_)
{
}
@ -675,7 +681,7 @@ struct find_predicate_prefix
{
#ifdef PUGIXML_WCHAR_MODE
// can't use wcsncmp here because of a bug in DMC
return std::basic_string<pugi::char_t>(obj.name()).compare(0, wcslen(prefix), prefix) == 0;
return std::basic_string<char_t>(obj.name()).compare(0, wcslen(prefix), prefix) == 0;
#else
return strncmp(obj.name(), prefix, strlen(prefix)) == 0;
#endif
@ -728,14 +734,17 @@ TEST_XML(dom_node_find_node, "<node><child1/><child2/></node>")
TEST_XML(dom_node_path, "<node><child1>text<child2/></child1></node>")
{
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"));
doc.append_child(node_element);
CHECK(doc.last_child().path() == STR("/"));
}
#endif
@ -743,7 +752,7 @@ TEST_XML(dom_node_first_element_by_path, "<node><child1>text<child2/></child1></
{
CHECK(xml_node().first_element_by_path(STR("/")) == xml_node());
CHECK(xml_node().first_element_by_path(STR("a")) == xml_node());
CHECK(doc.first_element_by_path(STR("")) == doc);
CHECK(doc.first_element_by_path(STR("/")) == doc);
@ -757,7 +766,7 @@ TEST_XML(dom_node_first_element_by_path, "<node><child1>text<child2/></child1></
#endif
CHECK(doc.first_element_by_path(STR("/node/child2")) == xml_node());
CHECK(doc.first_element_by_path(STR("\\node\\child1"), '\\') == doc.child(STR("node")).child(STR("child1")));
CHECK(doc.child(STR("node")).first_element_by_path(STR("..")) == doc);
@ -775,7 +784,7 @@ TEST_XML(dom_node_first_element_by_path, "<node><child1>text<child2/></child1></
struct test_walker: xml_tree_walker
{
std::basic_string<pugi::char_t> log;
std::basic_string<char_t> log;
unsigned int call_count;
unsigned int stop_count;
@ -783,22 +792,27 @@ struct test_walker: xml_tree_walker
{
}
std::basic_string<pugi::char_t> depthstr() const
std::basic_string<char_t> depthstr() const
{
char buf[32];
#if __cplusplus >= 201103 || defined(__APPLE__) // Xcode 14 warns about use of sprintf in C++98 builds
snprintf(buf, sizeof(buf), "%d", depth());
#else
sprintf(buf, "%d", depth());
#endif
#ifdef PUGIXML_WCHAR_MODE
wchar_t wbuf[32];
std::copy(buf, buf + strlen(buf) + 1, &wbuf[0]);
return std::basic_string<pugi::char_t>(wbuf);
return std::basic_string<char_t>(wbuf);
#else
return std::basic_string<pugi::char_t>(buf);
return std::basic_string<char_t>(buf);
#endif
}
virtual bool begin(xml_node& node)
virtual bool begin(xml_node& node) PUGIXML_OVERRIDE
{
log += STR("|");
log += depthstr();
@ -810,7 +824,7 @@ struct test_walker: xml_tree_walker
return ++call_count != stop_count && xml_tree_walker::begin(node);
}
virtual bool for_each(xml_node& node)
virtual bool for_each(xml_node& node) PUGIXML_OVERRIDE
{
log += STR("|");
log += depthstr();
@ -822,7 +836,7 @@ struct test_walker: xml_tree_walker
return ++call_count != stop_count && xml_tree_walker::end(node);
}
virtual bool end(xml_node& node)
virtual bool end(xml_node& node) PUGIXML_OVERRIDE
{
log += STR("|");
log += depthstr();
@ -919,7 +933,7 @@ TEST_XML_FLAGS(dom_offset_debug, "<?xml?><!DOCTYPE><?pi?><!--comment--><node>pcd
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 +980,7 @@ TEST_XML(dom_internal_object, "<node attr='value'>value</node>")
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 +1002,7 @@ TEST_XML(dom_hash_value, "<node attr='value'>value</node>")
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 +1099,206 @@ TEST_XML(dom_unspecified_bool_coverage, "<node attr='value'>text</node>")
{
xml_node node = doc.first_child();
CHECK(node);
static_cast<void (*)(xml_node***)>(node)(0);
CHECK(node.first_attribute());
static_cast<void (*)(xml_attribute***)>(node.first_attribute())(0);
CHECK(node.text());
static_cast<void (*)(xml_text***)>(node.text())(0);
#ifndef PUGIXML_NO_XPATH
xpath_query q(STR("/node"));
CHECK(q);
static_cast<void (*)(xpath_query***)>(q)(0);
static_cast<void (*)(xpath_node***)>(q.evaluate_node(doc))(0);
xpath_node qn = q.evaluate_node(doc);
CHECK(qn);
static_cast<void (*)(xpath_node***)>(qn)(0);
#endif
}
#if __cplusplus >= 201103
TEST_XML(dom_ranged_for, "<node attr1='1' attr2='2'><test>3</test><fake>5</fake><test>4</test></node>")
{
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, "<node attr1='1' attr2='2' attr3='3' />")
{
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, "<node attr1='-2147483649' attr2='2147483648' attr3='-4294967296' />")
{
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, "<node attr1='-1' attr2='4294967296' attr3='5294967295' attr4='21474836479' />")
{
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, "<node attr1='-0x80000001' attr2='0x80000000' />")
{
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, "<node attr1='-0x1' attr2='0x100000000' attr3='0x123456789' />")
{
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, "<node attr1='0000000000000000000000000000000000000000000000001' />")
{
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, "<node attr1='0x0000000000000000000000000000000000000000000000001' />")
{
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, "<node attr1='-9223372036854775809' attr2='9223372036854775808' attr3='-18446744073709551616' />")
{
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, "<node attr1='-1' attr2='18446744073709551616' attr3='28446744073709551615' attr4='166020696663385964543' />")
{
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, "<node attr1='-0x8000000000000001' attr2='0x8000000000000000' />")
{
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, "<node attr1='-0x1' attr2='0x10000000000000000' attr3='0x12345678923456789' />")
{
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, "<node attr1='0000000000000000000000000000000000000000000000001' />")
{
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, "<node attr1='0x0000000000000000000000000000000000000000000000001' />")
{
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, "<node attr1='+1' attr2='+0xa' />")
{
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
}
TEST(dom_node_anonymous)
{
xml_document doc;
doc.append_child(node_element);
doc.append_child(node_element);
doc.append_child(node_pcdata);
CHECK(doc.child(STR("node")) == xml_node());
CHECK(doc.first_child().next_sibling(STR("node")) == xml_node());
CHECK(doc.last_child().previous_sibling(STR("node")) == xml_node());
CHECK_STRING(doc.child_value(), STR(""));
CHECK_STRING(doc.last_child().child_value(), STR(""));
}

View file

@ -1,13 +1,15 @@
#define PUGIXML_HEADER_ONLY
#define pugi pugih
#include "common.hpp"
#include "test.hpp"
// Check header guards
#include "../src/pugixml.hpp"
#include "../src/pugixml.hpp"
TEST(header_only)
using namespace pugi;
TEST(header_only_1)
{
xml_document doc;
CHECK(doc.load_string(STR("<node/>")));

View file

@ -0,0 +1,21 @@
#define PUGIXML_HEADER_ONLY
#define pugi pugih
#include "test.hpp"
// Check header guards
#include "../src/pugixml.hpp"
#include "../src/pugixml.hpp"
using namespace pugi;
TEST(header_only_2)
{
xml_document doc;
CHECK(doc.load_string(STR("<node/>")));
CHECK_STRING(doc.first_child().name(), STR("node"));
#ifndef PUGIXML_NO_XPATH
CHECK(doc.first_child() == doc.select_node(STR("//*")).node());
#endif
}

View file

@ -1,5 +1,5 @@
// Tests compatibility with string/iostream
#include <string>
#include "../src/pugixml.hpp"
#include <istream>
#include <ostream>
// Tests compatibility with string/iostream
#include <string>
#include "../src/pugixml.hpp"
#include <istream>
#include <ostream>

View file

@ -1,30 +1,40 @@
#include "common.hpp"
#include "test.hpp"
#include "writer_string.hpp"
#include "allocator.hpp"
#include <string>
#include <vector>
using namespace pugi;
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<char*>(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 +47,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("<node />")));
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<pugi::char_t> s(65536, 'x');
std::basic_string<char_t> 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 +78,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,27 +90,27 @@ 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)
{
std::basic_string<pugi::char_t> s(i * 128, 'x');
std::basic_string<char_t> s(i * 128, 'x');
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())
{
pugi::xml_node node;
xml_node node;
// grow
for (node = doc.first_child(); node; node = node.next_sibling())
{
std::basic_string<pugi::char_t> s = node.value();
std::basic_string<char_t> s = node.value();
CHECK(node.set_value((s + s).c_str()));
}
@ -108,7 +118,7 @@ TEST(memory_large_allocations)
// prune
for (node = doc.first_child(); node; )
{
pugi::xml_node next = node.next_sibling().next_sibling();
xml_node next = node.next_sibling().next_sibling();
node.parent().remove_child(node);
@ -116,15 +126,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<xml_node> nodes;
for (size_t i = 0; i < 4000; ++i)
{
xml_node node = doc.append_child(STR("n"));
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);

View file

@ -1,7 +1,9 @@
#include "common.hpp"
#include "test.hpp"
#include "writer_string.hpp"
using namespace pugi;
TEST(parse_pi_skip)
{
xml_document doc;
@ -82,12 +84,22 @@ TEST(parse_pi_error)
CHECK(doc.load_string(STR("<?name&"), flags).status == status_bad_pi);
CHECK(doc.load_string(STR("<?name&?"), flags).status == status_bad_pi);
}
CHECK(doc.load_string(STR("<?xx#?>"), parse_fragment | parse_pi).status == status_bad_pi);
CHECK(doc.load_string(STR("<?name&?>"), parse_fragment | parse_pi).status == status_bad_pi);
CHECK(doc.load_string(STR("<?name& x?>"), parse_fragment | parse_pi).status == status_bad_pi);
}
TEST(parse_pi_error_buffer_boundary)
{
char buf1[] = "<?name?>";
char buf2[] = "<?name?x";
xml_document doc;
CHECK(doc.load_buffer_inplace(buf1, 8, parse_fragment | parse_pi));
CHECK(doc.load_buffer_inplace(buf2, 8, parse_fragment | parse_pi).status == status_bad_pi);
}
TEST(parse_comments_skip)
{
xml_document doc;
@ -235,9 +247,9 @@ TEST(parse_ws_pcdata_skip)
CHECK(!doc.first_child());
CHECK(doc.load_string(STR("<root> <node> </node> </root>"), parse_minimal));
xml_node root = doc.child(STR("root"));
CHECK(root.first_child() == root.last_child());
CHECK(!root.first_child().first_child());
}
@ -280,46 +292,46 @@ TEST(parse_ws_pcdata_permutations)
struct test_data_t
{
unsigned int mask; // 1 = default flags, 2 = parse_ws_pcdata, 4 = parse_ws_pcdata_single
const pugi::char_t* source;
const pugi::char_t* result;
const char_t* source;
const char_t* result;
int nodes; // negative if parsing should fail
};
test_data_t test_data[] =
{
// external pcdata should be discarded (whitespace or not)
{7, STR("ext1<node/>"), STR("<node />"), 2},
{7, STR("ext1<node/>ext2"), STR("<node />"), 2},
{7, STR(" <node/>"), STR("<node />"), 2},
{7, STR("<node/> "), STR("<node />"), 2},
{7, STR(" <node/> "), STR("<node />"), 2},
{7, STR("ext1<node/>"), STR("<node/>"), 2},
{7, STR("ext1<node/>ext2"), STR("<node/>"), 2},
{7, STR(" <node/>"), STR("<node/>"), 2},
{7, STR("<node/> "), STR("<node/>"), 2},
{7, STR(" <node/> "), STR("<node/>"), 2},
// inner pcdata should be preserved
{7, STR("<node>inner</node>"), STR("<node>inner</node>"), 3},
{7, STR("<node>inner1<child/>inner2</node>"), STR("<node>inner1<child />inner2</node>"), 5},
{7, STR("<node>inner1<child/>inner2</node>"), STR("<node>inner1<child/>inner2</node>"), 5},
{7, STR("<node>inner1<child>deep</child>inner2</node>"), STR("<node>inner1<child>deep</child>inner2</node>"), 6},
// empty pcdata nodes should never be created
{7, STR("<node>inner1<child></child>inner2</node>"), STR("<node>inner1<child />inner2</node>"), 5},
{7, STR("<node><child></child>inner2</node>"), STR("<node><child />inner2</node>"), 4},
{7, STR("<node>inner1<child></child></node>"), STR("<node>inner1<child /></node>"), 4},
{7, STR("<node><child></child></node>"), STR("<node><child /></node>"), 3},
{7, STR("<node>inner1<child></child>inner2</node>"), STR("<node>inner1<child/>inner2</node>"), 5},
{7, STR("<node><child></child>inner2</node>"), STR("<node><child/>inner2</node>"), 4},
{7, STR("<node>inner1<child></child></node>"), STR("<node>inner1<child/></node>"), 4},
{7, STR("<node><child></child></node>"), STR("<node><child/></node>"), 3},
// comments, pi or other nodes should not cause pcdata creation either
{7, STR("<node><!----><child><?pi?></child><![CDATA[x]]></node>"), STR("<node><child /><![CDATA[x]]></node>"), 4},
{7, STR("<node><!----><child><?pi?></child><![CDATA[x]]></node>"), STR("<node><child/><![CDATA[x]]></node>"), 4},
// leading/trailing pcdata whitespace should be preserved (note: this will change if parse_ws_pcdata_trim is introduced)
{7, STR("<node>\t \tinner1<child> deep </child>\t\ninner2\n\t</node>"), STR("<node>\t \tinner1<child> deep </child>\t\ninner2\n\t</node>"), 6},
// whitespace-only pcdata preservation depends on the parsing mode
{1, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node><child /><child><deep /></child></node>"), 5},
{1, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node><child/><child><deep/></child></node>"), 5},
{2, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t\n\t</node>"), 13},
{4, STR("<node>\n\t<child> </child>\n\t<child> <deep> </deep> </child>\n\t<!---->\n\t</node>"), STR("<node><child> </child><child><deep> </deep></child></node>"), 7},
// current implementation of parse_ws_pcdata_single has an unfortunate bug; reproduce it here
{4, STR("<node>\t\t<!---->\n\n</node>"), STR("<node>\n\n</node>"), 3},
// error case: terminate PCDATA in the middle
{7, STR("<node>abcdef"), STR("<node>abcdef</node>"), -3},
{5, STR("<node> "), STR("<node />"), -2},
{5, STR("<node> "), STR("<node/>"), -2},
{2, STR("<node> "), STR("<node> </node>"), -3},
// error case: terminate PCDATA as early as possible
{7, STR("<node>"), STR("<node />"), -2},
{7, STR("<node>"), STR("<node/>"), -2},
{7, STR("<node>a"), STR("<node>a</node>"), -3},
{5, STR("<node> "), STR("<node />"), -2},
{5, STR("<node> "), STR("<node/>"), -2},
{2, STR("<node> "), STR("<node> </node>"), -3},
};
@ -349,8 +361,8 @@ TEST(parse_ws_pcdata_fragment_permutations)
struct test_data_t
{
unsigned int mask; // 1 = default flags, 2 = parse_ws_pcdata, 4 = parse_ws_pcdata_single
const pugi::char_t* source;
const pugi::char_t* result;
const char_t* source;
const char_t* result;
int nodes; // negative if parsing should fail
};
@ -360,18 +372,18 @@ TEST(parse_ws_pcdata_fragment_permutations)
{7, STR("ext1"), STR("ext1"), 2},
{5, STR(" "), STR(""), 1},
{2, STR(" "), STR(" "), 2},
{7, STR("ext1<node/>"), STR("ext1<node />"), 3},
{7, STR("<node/>ext2"), STR("<node />ext2"), 3},
{7, STR("ext1<node/>ext2"), STR("ext1<node />ext2"), 4},
{7, STR("ext1<node1/>ext2<node2/>ext3"), STR("ext1<node1 />ext2<node2 />ext3"), 6},
{5, STR(" <node/>"), STR("<node />"), 2},
{2, STR(" <node/>"), STR(" <node />"), 3},
{5, STR("<node/> "), STR("<node />"), 2},
{2, STR("<node/> "), STR("<node /> "), 3},
{5, STR(" <node/> "), STR("<node />"), 2},
{2, STR(" <node/> "), STR(" <node /> "), 4},
{5, STR(" <node1/> <node2/> "), STR("<node1 /><node2 />"), 3},
{2, STR(" <node1/> <node2/> "), STR(" <node1 /> <node2 /> "), 6},
{7, STR("ext1<node/>"), STR("ext1<node/>"), 3},
{7, STR("<node/>ext2"), STR("<node/>ext2"), 3},
{7, STR("ext1<node/>ext2"), STR("ext1<node/>ext2"), 4},
{7, STR("ext1<node1/>ext2<node2/>ext3"), STR("ext1<node1/>ext2<node2/>ext3"), 6},
{5, STR(" <node/>"), STR("<node/>"), 2},
{2, STR(" <node/>"), STR(" <node/>"), 3},
{5, STR("<node/> "), STR("<node/>"), 2},
{2, STR("<node/> "), STR("<node/> "), 3},
{5, STR(" <node/> "), STR("<node/>"), 2},
{2, STR(" <node/> "), STR(" <node/> "), 4},
{5, STR(" <node1/> <node2/> "), STR("<node1/><node2/>"), 3},
{2, STR(" <node1/> <node2/> "), STR(" <node1/> <node2/> "), 6},
};
for (size_t i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
@ -429,8 +441,8 @@ TEST(parse_pcdata_trim)
{
struct test_data_t
{
const pugi::char_t* source;
const pugi::char_t* result;
const char_t* source;
const char_t* result;
unsigned int flags;
};
@ -462,7 +474,7 @@ TEST(parse_pcdata_trim)
xml_document doc;
CHECK(doc.load_string(td.source, td.flags | parse_trim_pcdata));
const pugi::char_t* value = doc.child(STR("node")) ? doc.child_value(STR("node")) : doc.text().get();
const char_t* value = doc.child(STR("node")) ? doc.child_value(STR("node")) : doc.text().get();
CHECK_STRING(value, td.result);
}
}
@ -551,7 +563,7 @@ TEST(parse_escapes_unicode)
CHECK(doc.load_string(STR("<node>&#x03B3;&#x03b3;&#x24B62;</node>"), parse_minimal | parse_escapes));
#ifdef PUGIXML_WCHAR_MODE
const pugi::char_t* v = doc.child_value(STR("node"));
const char_t* v = doc.child_value(STR("node"));
size_t wcharsize = sizeof(wchar_t);
@ -746,18 +758,48 @@ TEST(parse_attribute_quot_inside)
}
}
TEST(parse_attribute_wnorm_coverage)
{
xml_document doc;
CHECK(doc.load_string(STR("<n a1='v' a2=' ' a3='x y' a4='x y' a5='x y' />"), parse_wnorm_attribute));
CHECK_NODE(doc, STR("<n a1=\"v\" a2=\"\" a3=\"x y\" a4=\"x y\" a5=\"x y\"/>"));
CHECK(doc.load_string(STR("<n a1='v' a2=' ' a3='x y' a4='x y' a5='x y' />"), parse_wnorm_attribute | parse_escapes));
CHECK_NODE(doc, STR("<n a1=\"v\" a2=\"\" a3=\"x y\" a4=\"x y\" a5=\"x y\"/>"));
}
TEST(parse_attribute_wconv_coverage)
{
xml_document doc;
CHECK(doc.load_string(STR("<n a1='v' a2='\r' a3='\r\n\n' a4='\n' />"), parse_wconv_attribute));
CHECK_NODE(doc, STR("<n a1=\"v\" a2=\" \" a3=\" \" a4=\" \"/>"));
CHECK(doc.load_string(STR("<n a1='v' a2='\r' a3='\r\n\n' a4='\n' />"), parse_wconv_attribute | parse_escapes));
CHECK_NODE(doc, STR("<n a1=\"v\" a2=\" \" a3=\" \" a4=\" \"/>"));
}
TEST(parse_attribute_eol_coverage)
{
xml_document doc;
CHECK(doc.load_string(STR("<n a1='v' a2='\r' a3='\r\n\n' a4='\n' />"), parse_eol));
CHECK_NODE(doc, STR("<n a1=\"v\" a2=\"&#10;\" a3=\"&#10;&#10;\" a4=\"&#10;\"/>"));
CHECK(doc.load_string(STR("<n a1='v' a2='\r' a3='\r\n\n' a4='\n' />"), parse_eol | parse_escapes));
CHECK_NODE(doc, STR("<n a1=\"v\" a2=\"&#10;\" a3=\"&#10;&#10;\" a4=\"&#10;\"/>"));
}
TEST(parse_tag_single)
{
xml_document doc;
CHECK(doc.load_string(STR("<node/><node /><node\n/>"), parse_minimal));
CHECK_NODE(doc, STR("<node /><node /><node />"));
CHECK_NODE(doc, STR("<node/><node/><node/>"));
}
TEST(parse_tag_hierarchy)
{
xml_document doc;
CHECK(doc.load_string(STR("<node><n1><n2/></n1><n3><n4><n5></n5></n4></n3 \r\n></node>"), parse_minimal));
CHECK_NODE(doc, STR("<node><n1><n2 /></n1><n3><n4><n5 /></n4></n3></node>"));
CHECK_NODE(doc, STR("<node><n1><n2/></n1><n3><n4><n5/></n4></n3></node>"));
}
TEST(parse_tag_error)
@ -855,7 +897,7 @@ TEST(parse_declaration_error)
CHECK(doc.load_string(STR("<?xml>"), flags).status == status_bad_pi);
CHECK(doc.load_string(STR("<?xml version='1>"), flags).status == status_bad_pi);
}
CHECK(doc.load_string(STR("<?xml version='1?>"), parse_fragment | parse_declaration).status == status_bad_attribute);
CHECK(doc.load_string(STR("<foo><?xml version='1'?></foo>"), parse_fragment | parse_declaration).status == status_bad_pi);
}
@ -873,7 +915,7 @@ TEST(parse_out_of_memory)
test_runner::_memory_fail_threshold = 256;
xml_document doc;
CHECK(doc.load_string(STR("<foo a='1'/>")).status == status_out_of_memory);
CHECK_ALLOC_FAIL(CHECK(doc.load_string(STR("<foo a='1'/>")).status == status_out_of_memory));
CHECK(!doc.first_child());
}
@ -893,8 +935,8 @@ 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_NODE(doc.first_child(), STR("<n />"));
CHECK_ALLOC_FAIL(CHECK(doc.load_buffer_inplace(text, sizeof(text)).status == status_out_of_memory));
CHECK_NODE(doc.first_child(), STR("<n/>"));
}
TEST(parse_out_of_memory_halfway_attr)
@ -920,13 +962,47 @@ 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, sizeof(text)).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"));
}
static bool test_offset(const char_t* contents, unsigned int options, pugi::xml_parse_status status, ptrdiff_t offset)
TEST(parse_out_of_memory_conversion)
{
test_runner::_memory_fail_threshold = 1;
xml_document doc;
CHECK_ALLOC_FAIL(CHECK(doc.load_buffer("<foo\x90/>", 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, sizeof(text)).status == status_out_of_memory));
CHECK_NODE(doc.first_child(), STR("<n/>"));
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, xml_parse_status status, ptrdiff_t offset)
{
xml_document doc;
xml_parse_result res = doc.load_string(contents, options);
@ -941,7 +1017,7 @@ TEST(parse_error_offset)
CHECK_OFFSET("<node/>", parse_default, status_ok, 0);
test_runner::_memory_fail_threshold = 1;
CHECK_OFFSET("<node/>", parse_default, status_out_of_memory, 0);
CHECK_ALLOC_FAIL(CHECK_OFFSET("<node/>", parse_default, status_out_of_memory, 0));
test_runner::_memory_fail_threshold = 0;
CHECK_OFFSET("<3d/>", parse_default, status_unrecognized_tag, 1);
@ -971,8 +1047,8 @@ TEST(parse_error_offset)
CHECK_OFFSET("<n></n $>", parse_default, status_bad_end_element, 7);
CHECK_OFFSET("<n></n", parse_default, status_bad_end_element, 5);
CHECK_OFFSET("<no></na>", parse_default, status_end_element_mismatch, 8);
CHECK_OFFSET("<no></nod>", parse_default, status_end_element_mismatch, 9);
CHECK_OFFSET("<no></na>", parse_default, status_end_element_mismatch, 6);
CHECK_OFFSET("<no></nod>", parse_default, status_end_element_mismatch, 6);
}
TEST(parse_result_default)
@ -1105,3 +1181,177 @@ TEST(parse_fuzz_doctype)
xml_document doc;
CHECK(doc.load_buffer(data, sizeof(data)).status == status_bad_doctype);
}
TEST(parse_embed_pcdata)
{
// parse twice - once with default and once with embed_pcdata flags
for (int i = 0; i < 2; ++i)
{
unsigned int flags = (i == 0) ? parse_default : parse_default | parse_embed_pcdata;
xml_document doc;
xml_parse_result res = doc.load_string(STR("<node><key>value</key><child><inner1>value1</inner1><inner2>value2</inner2>outer</child><two>text<data /></two></node>"), flags);
CHECK(res);
xml_node child = doc.child(STR("node")).child(STR("child"));
// parse_embed_pcdata omits PCDATA nodes so DOM is different
if (flags & parse_embed_pcdata)
{
CHECK_STRING(doc.child(STR("node")).child(STR("key")).value(), STR("value"));
CHECK(!doc.child(STR("node")).child(STR("key")).first_child());
}
else
{
CHECK_STRING(doc.child(STR("node")).child(STR("key")).value(), STR(""));
CHECK(doc.child(STR("node")).child(STR("key")).first_child());
CHECK_STRING(doc.child(STR("node")).child(STR("key")).first_child().value(), STR("value"));
}
// higher-level APIs work the same though
CHECK_STRING(child.text().get(), STR("outer"));
CHECK_STRING(child.child(STR("inner1")).text().get(), STR("value1"));
CHECK_STRING(child.child_value(), STR("outer"));
CHECK_STRING(child.child_value(STR("inner2")), STR("value2"));
#ifndef PUGIXML_NO_XPATH
CHECK_XPATH_NUMBER(doc, STR("count(node/child/*[starts-with(., 'value')])"), 2);
#endif
CHECK_NODE(doc, STR("<node><key>value</key><child><inner1>value1</inner1><inner2>value2</inner2>outer</child><two>text<data/></two></node>"));
CHECK_NODE_EX(doc, STR("<node>\n<key>value</key>\n<child>\n<inner1>value1</inner1>\n<inner2>value2</inner2>outer</child>\n<two>text<data />\n</two>\n</node>\n"), STR("\t"), 0);
CHECK_NODE_EX(doc, STR("<node>\n\t<key>value</key>\n\t<child>\n\t\t<inner1>value1</inner1>\n\t\t<inner2>value2</inner2>outer</child>\n\t<two>text<data />\n\t</two>\n</node>\n"), STR("\t"), format_indent);
}
}
TEST_XML_FLAGS(parse_embed_pcdata_fragment, "text", parse_fragment | parse_embed_pcdata)
{
CHECK_NODE(doc, STR("text"));
CHECK(doc.first_child().type() == node_pcdata);
CHECK_STRING(doc.first_child().value(), STR("text"));
}
TEST_XML_FLAGS(parse_embed_pcdata_child, "<n><child/>text</n>", parse_embed_pcdata)
{
xml_node n = doc.child(STR("n"));
CHECK_NODE(doc, STR("<n><child/>text</n>"));
CHECK(n.last_child().type() == node_pcdata);
CHECK_STRING(n.last_child().value(), STR("text"));
}
TEST_XML_FLAGS(parse_embed_pcdata_comment, "<n>text1<!---->text2</n>", parse_embed_pcdata)
{
xml_node n = doc.child(STR("n"));
CHECK_NODE(doc, STR("<n>text1text2</n>"));
CHECK_STRING(n.value(), STR("text1"));
CHECK(n.first_child() == n.last_child());
CHECK(n.last_child().type() == node_pcdata);
CHECK_STRING(n.last_child().value(), STR("text2"));
}
TEST(parse_encoding_detect)
{
char test[] = "<?xml version='1.0' encoding='utf-8'?><n/>";
xml_document doc;
CHECK(doc.load_buffer(test, sizeof(test)));
}
TEST(parse_encoding_detect_latin1)
{
char test0[] = "<?xml version='1.0' encoding='utf-8'?><n/>";
char test1[] = "<?xml version='1.0' encoding='iso-8859-1'?><n/>";
char test2[] = "<?xml version='1.0' encoding = \"latin1\"?><n/>";
char test3[] = "<?xml version='1.0' encoding='ISO-8859-1'?><n/>";
char test4[] = "<?xml version='1.0' encoding = \"LATIN1\"?><n/>";
xml_document doc;
CHECK(doc.load_buffer(test0, sizeof(test0)).encoding == encoding_utf8);
CHECK(doc.load_buffer(test1, sizeof(test1)).encoding == encoding_latin1);
CHECK(doc.load_buffer(test2, sizeof(test2)).encoding == encoding_latin1);
CHECK(doc.load_buffer(test3, sizeof(test3)).encoding == encoding_latin1);
CHECK(doc.load_buffer(test4, sizeof(test4)).encoding == encoding_latin1);
}
TEST(parse_encoding_detect_auto)
{
struct data_t
{
const char* contents;
size_t size;
xml_encoding encoding;
};
const data_t data[] =
{
// BOM
{ "\x00\x00\xfe\xff", 4, encoding_utf32_be },
{ "\xff\xfe\x00\x00", 4, encoding_utf32_le },
{ "\xfe\xff ", 4, encoding_utf16_be },
{ "\xff\xfe ", 4, encoding_utf16_le },
{ "\xef\xbb\xbf ", 4, encoding_utf8 },
// automatic tag detection for < or <?
{ "\x00\x00\x00<\x00\x00\x00n\x00\x00\x00/\x00\x00\x00>", 16, encoding_utf32_be },
{ "<\x00\x00\x00n\x00\x00\x00/\x00\x00\x00>\x00\x00\x00", 16, encoding_utf32_le },
{ "\x00<\x00?\x00n\x00?\x00>", 10, encoding_utf16_be },
{ "<\x00?\x00n\x00?\x00>\x00", 10, encoding_utf16_le },
{ "\x00<\x00n\x00/\x00>", 8, encoding_utf16_be },
{ "<\x00n\x00/\x00>\x00", 8, encoding_utf16_le },
// <?xml encoding
{ "<?xml encoding='latin1'?>", 25, encoding_latin1 },
};
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i)
{
xml_document doc;
xml_parse_result result = doc.load_buffer(data[i].contents, data[i].size, parse_fragment);
CHECK(result);
CHECK(result.encoding == data[i].encoding);
}
}
TEST(parse_encoding_detect_auto_incomplete)
{
struct data_t
{
const char* contents;
size_t size;
xml_encoding encoding;
};
const data_t data[] =
{
// BOM
{ "\x00\x00\xfe ", 4, encoding_utf8 },
{ "\x00\x00 ", 4, encoding_utf8 },
{ "\xff\xfe\x00 ", 4, encoding_utf16_le },
{ "\xfe ", 4, encoding_utf8 },
{ "\xff ", 4, encoding_utf8 },
{ "\xef\xbb ", 4, encoding_utf8 },
{ "\xef ", 4, encoding_utf8 },
// automatic tag detection for < or <?
{ "\x00\x00\x00 ", 4, encoding_utf8 },
{ "<\x00\x00n/\x00>\x00", 8, encoding_utf16_le },
{ "\x00<n\x00\x00/\x00>", 8, encoding_utf16_be },
{ "<\x00?n/\x00>\x00", 8, encoding_utf16_le },
{ "\x00 ", 2, encoding_utf8 },
// <?xml encoding
{ "<?xmC encoding='latin1'?>", 25, encoding_utf8 },
{ "<?xBC encoding='latin1'?>", 25, encoding_utf8 },
{ "<?ABC encoding='latin1'?>", 25, encoding_utf8 },
{ "<_ABC encoding='latin1'/>", 25, encoding_utf8 },
};
for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i)
{
xml_document doc;
xml_parse_result result = doc.load_buffer(data[i].contents, data[i].size, parse_fragment);
CHECK(result);
CHECK(result.encoding == data[i].encoding);
}
}

View file

@ -1,11 +1,13 @@
#define _CRT_SECURE_NO_WARNINGS
#include "common.hpp"
#include "test.hpp"
#include <string.h>
#include <wchar.h>
#include <string>
using namespace pugi;
static xml_parse_result load_concat(xml_document& doc, const char_t* a, const char_t* b = STR(""), const char_t* c = STR(""))
{
char_t buffer[768];
@ -36,9 +38,9 @@ static bool test_doctype_wf(const char_t* decl)
if (!load_concat(doc, STR("a"), decl, STR("b")) || !test_node(doc, STR("ab"), STR(""), format_raw)) return false;
// node pre/postfix
if (!load_concat(doc, STR("<nodea/>"), decl) || !test_node(doc, STR("<nodea />"), STR(""), format_raw)) return false;
if (!load_concat(doc, decl, STR("<nodeb/>")) || !test_node(doc, STR("<nodeb />"), STR(""), format_raw)) return false;
if (!load_concat(doc, STR("<nodea/>"), decl, STR("<nodeb/>")) || !test_node(doc, STR("<nodea /><nodeb />"), STR(""), format_raw)) return false;
if (!load_concat(doc, STR("<nodea/>"), decl) || !test_node(doc, STR("<nodea/>"), STR(""), format_raw)) return false;
if (!load_concat(doc, decl, STR("<nodeb/>")) || !test_node(doc, STR("<nodeb/>"), STR(""), format_raw)) return false;
if (!load_concat(doc, STR("<nodea/>"), decl, STR("<nodeb/>")) || !test_node(doc, STR("<nodea/><nodeb/>"), STR(""), format_raw)) return false;
// check load-store contents preservation
CHECK(doc.load_string(decl, parse_doctype | parse_fragment));
@ -219,7 +221,7 @@ TEST(parse_doctype_xmlconf_ibm_2)
TEST_DOCTYPE_NWF("<!DOCTYPE animal [ <!ELEMENT animal ANY> <!ENTITY % parameterE \"A music file ?>\"> <?music %parameterE; ]>");
TEST_DOCTYPE_NWF("<!DOCTYPE animal [ <!ELEMENT animal ANY> <!ENTITY % parameterE \"leopard EMPTY>\"> <!ELEMENT %parameterE; ]>");
TEST_DOCTYPE_WF("<!DOCTYPE root [ <!ELEMENT root ANY> <!ATTLIST root attr1 CDATA #IMPLIED> <!ATTLIST root attr2 CDATA #IMPLIED> <!ENTITY withlt \"have <lessthan> inside\"> <!ENTITY aIndirect \"&withlt;\"> ]>");
TEST_DOCTYPE_WF("<!DOCTYPE root [ <!ELEMENT root (#PCDATA)> <!--* Mising Name S contentspec in elementdecl *--> <!ELEMENT > ]>");
TEST_DOCTYPE_WF("<!DOCTYPE root [ <!ELEMENT root (#PCDATA)> <!--* Missing Name S contentspec in elementdecl *--> <!ELEMENT > ]>");
TEST_DOCTYPE_WF("<!DOCTYPE root [ <!ELEMENT root (#PCDATA)> <!ELEMENT a ANY> <!ELEMENT b ANY> <!--* extra separator in seq *--> <!ELEMENT aElement ((a|b),,a)? > ]>");
TEST_DOCTYPE_WF("<!DOCTYPE root [ <!ELEMENT root (#PCDATA)> <!ELEMENT a ANY> <!--* Missing white space before Name in AttDef *--> <!ATTLIST a attr1 CDATA \"default\"attr2 ID #required> ]>");
TEST_DOCTYPE_WF("<!DOCTYPE test [ <!ELEMENT test ANY> <!ELEMENT one EMPTY> <!ELEMENT two EMPTY> <!NOTATION this SYSTEM \"alpha\"> <!ATTLIST three attr NOTATION (\"this\") #IMPLIED> ]>");

View file

@ -1,9 +1,11 @@
#ifndef PUGIXML_NO_STL
#include "common.hpp"
#include "test.hpp"
#include <string>
using namespace pugi;
// letters taken from http://www.utf8-chartable.de/
TEST(as_wide_empty)

View file

@ -1,5 +1,5 @@
#include "../src/pugixml.hpp"
#if PUGIXML_VERSION != 160
#error Unexpected pugixml version
#endif
#include "../src/pugixml.hpp"
#if PUGIXML_VERSION != 1130
#error Unexpected pugixml version
#endif

View file

@ -1,9 +1,12 @@
#include "common.hpp"
#include "test.hpp"
#include "writer_string.hpp"
#include <string>
#include <sstream>
#include <stdexcept>
using namespace pugi;
TEST_XML(write_simple, "<node attr='1'><child>text</child></node>")
{
@ -20,6 +23,31 @@ TEST_XML(write_indent, "<node attr='1'><child><sub>text</sub></child></node>")
CHECK_NODE_EX(doc, STR("<node attr=\"1\">\n\t<child>\n\t\t<sub>text</sub>\n\t</child>\n</node>\n"), STR("\t"), format_indent);
}
TEST_XML(write_indent_attributes, "<node attr='1' other='2'><child><sub>text</sub></child></node>")
{
CHECK_NODE_EX(doc, STR("<node\n\tattr=\"1\"\n\tother=\"2\">\n\t<child>\n\t\t<sub>text</sub>\n\t</child>\n</node>\n"), STR("\t"), format_indent_attributes);
}
TEST_XML(write_indent_attributes_empty_element, "<node attr='1' other='2' />")
{
CHECK_NODE_EX(doc, STR("<node\n\tattr=\"1\"\n\tother=\"2\" />\n"), STR("\t"), format_indent_attributes);
}
TEST_XML_FLAGS(write_indent_attributes_declaration, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><node attr='1' other='2' />", parse_full)
{
CHECK_NODE_EX(doc, STR("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<node\n\tattr=\"1\"\n\tother=\"2\" />\n"), STR("\t"), format_indent_attributes);
}
TEST_XML(write_indent_attributes_raw, "<node attr='1' other='2'><child><sub>text</sub></child></node>")
{
CHECK_NODE_EX(doc, STR("<node attr=\"1\" other=\"2\"><child><sub>text</sub></child></node>"), STR("\t"), format_indent_attributes | format_raw);
}
TEST_XML(write_indent_attributes_empty_indent, "<node attr='1' other='2'><child><sub>text</sub></child></node>")
{
CHECK_NODE_EX(doc, STR("<node\nattr=\"1\"\nother=\"2\">\n<child>\n<sub>text</sub>\n</child>\n</node>\n"), STR(""), format_indent_attributes);
}
TEST_XML(write_pcdata, "<node attr='1'><child><sub/>text</child></node>")
{
CHECK_NODE_EX(doc, STR("<node attr=\"1\">\n\t<child>\n\t\t<sub />text</child>\n</node>\n"), STR("\t"), format_indent);
@ -43,6 +71,12 @@ TEST_XML_FLAGS(write_cdata_escape, "<![CDATA[value]]>", parse_cdata | parse_frag
doc.first_child().set_value(STR("1]]>2]]>3"));
CHECK_NODE(doc, STR("<![CDATA[1]]]]><![CDATA[>2]]]]><![CDATA[>3]]>"));
doc.first_child().set_value(STR("1]"));
CHECK_NODE(doc, STR("<![CDATA[1]]]>"));
doc.first_child().set_value(STR("1]]"));
CHECK_NODE(doc, STR("<![CDATA[1]]]]>"));
}
TEST_XML(write_cdata_inner, "<node><![CDATA[value]]></node>")
@ -159,19 +193,35 @@ TEST_XML(write_escape, "<node attr=''>text</node>")
doc.child(STR("node")).attribute(STR("attr")) = STR("<>'\"&\x04\r\n\t");
doc.child(STR("node")).first_child().set_value(STR("<>'\"&\x04\r\n\t"));
CHECK_NODE(doc, STR("<node attr=\"&lt;&gt;'&quot;&amp;&#04;&#13;&#10;\t\">&lt;&gt;'\"&amp;&#04;\r\n\t</node>"));
CHECK_NODE(doc, STR("<node attr=\"&lt;>'&quot;&amp;&#04;&#13;&#10;&#09;\">&lt;&gt;'\"&amp;&#04;\r\n\t</node>"));
CHECK_NODE_EX(doc, STR("<node attr='&lt;>&apos;\"&amp;&#04;&#13;&#10;&#09;'>&lt;&gt;'\"&amp;&#04;\r\n\t</node>"), STR(""), format_raw | format_attribute_single_quote);
}
TEST_XML(write_escape_roundtrip, "<node attr=''>text</node>")
{
doc.child(STR("node")).attribute(STR("attr")) = STR("<>'\"&\x04\r\n\t");
doc.child(STR("node")).first_child().set_value(STR("<>'\"&\x04\r\n\t"));
std::string contents = write_narrow(doc, format_raw, encoding_utf8);
CHECK(doc.load_buffer(contents.c_str(), contents.size()));
// Note: this string is almost identical to the string from write_escape with the exception of \r
// \r in PCDATA doesn't roundtrip because it has to go through newline conversion (which could be disabled, but is active by default)
CHECK_NODE(doc, STR("<node attr=\"&lt;>'&quot;&amp;&#04;&#13;&#10;&#09;\">&lt;&gt;'\"&amp;&#04;\n\t</node>"));
CHECK_NODE_EX(doc, STR("<node attr='&lt;>&apos;\"&amp;&#04;&#13;&#10;&#09;'>&lt;&gt;'\"&amp;&#04;\n\t</node>"), STR(""), format_raw | format_attribute_single_quote);
}
TEST_XML(write_escape_unicode, "<node attr='&#x3c00;'/>")
{
#ifdef PUGIXML_WCHAR_MODE
#ifdef U_LITERALS
CHECK_NODE(doc, STR("<node attr=\"\u3c00\" />"));
CHECK_NODE(doc, STR("<node attr=\"\u3c00\"/>"));
#else
CHECK_NODE(doc, STR("<node attr=\"\x3c00\" />"));
CHECK_NODE(doc, STR("<node attr=\"\x3c00\"/>"));
#endif
#else
CHECK_NODE(doc, STR("<node attr=\"\xe3\xb0\x80\" />"));
CHECK_NODE(doc, STR("<node attr=\"\xe3\xb0\x80\"/>"));
#endif
}
@ -185,12 +235,12 @@ TEST_XML(write_no_escapes, "<node attr=''>text</node>")
struct test_writer: xml_writer
{
std::basic_string<pugi::char_t> contents;
std::basic_string<char_t> contents;
virtual void write(const void* data, size_t size)
virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE
{
CHECK(size % sizeof(pugi::char_t) == 0);
contents.append(static_cast<const pugi::char_t*>(data), size / sizeof(pugi::char_t));
CHECK(size % sizeof(char_t) == 0);
contents.append(static_cast<const char_t*>(data), size / sizeof(char_t));
}
};
@ -230,7 +280,7 @@ TEST_XML(write_print_stream_wide, "<node/>")
TEST_XML(write_huge_chunk, "<node/>")
{
std::basic_string<pugi::char_t> name(10000, STR('n'));
std::basic_string<char_t> name(10000, STR('n'));
doc.child(STR("node")).set_name(name.c_str());
test_writer writer;
@ -359,7 +409,7 @@ TEST(write_encoding_huge_invalid)
TEST(write_unicode_escape)
{
char s_utf8[] = "<\xE2\x82\xAC \xC2\xA2='\"\xF0\xA4\xAD\xA2&#x0a;\"'>&amp;\x14\xF0\xA4\xAD\xA2&lt;</\xE2\x82\xAC>";
xml_document doc;
CHECK(doc.load_buffer(s_utf8, sizeof(s_utf8), parse_default, encoding_utf8));
@ -447,7 +497,7 @@ TEST(write_no_name_element)
root.append_child();
root.append_child().append_child(node_pcdata).set_value(STR("text"));
CHECK_NODE(doc, STR("<:anonymous><:anonymous /><:anonymous>text</:anonymous></:anonymous>"));
CHECK_NODE(doc, STR("<:anonymous><:anonymous/><:anonymous>text</:anonymous></:anonymous>"));
CHECK_NODE_EX(doc, STR("<:anonymous>\n\t<:anonymous />\n\t<:anonymous>text</:anonymous>\n</:anonymous>\n"), STR("\t"), format_default);
}
@ -465,7 +515,7 @@ TEST(write_no_name_attribute)
doc.append_child().set_name(STR("root"));
doc.child(STR("root")).append_attribute(STR(""));
CHECK_NODE(doc, STR("<root :anonymous=\"\" />"));
CHECK_NODE(doc, STR("<root :anonymous=\"\"/>"));
}
TEST(write_print_empty)
@ -491,7 +541,7 @@ TEST(write_print_stream_empty_wide)
TEST(write_stackless)
{
unsigned int count = 20000;
std::basic_string<pugi::char_t> data;
std::basic_string<char_t> data;
for (unsigned int i = 0; i < count; ++i)
data += STR("<a>");
@ -570,7 +620,114 @@ TEST(write_pcdata_whitespace_fixedpoint)
TEST_XML_FLAGS(write_mixed, "<node><child1/><child2>pre<![CDATA[data]]>mid<!--comment--><test/>post<?pi value?>fin</child2><child3/></node>", parse_full)
{
CHECK_NODE(doc, STR("<node><child1 /><child2>pre<![CDATA[data]]>mid<!--comment--><test />post<?pi value?>fin</child2><child3 /></node>"));
CHECK_NODE(doc, STR("<node><child1/><child2>pre<![CDATA[data]]>mid<!--comment--><test/>post<?pi value?>fin</child2><child3/></node>"));
CHECK_NODE_EX(doc, STR("<node>\n<child1 />\n<child2>pre<![CDATA[data]]>mid<!--comment-->\n<test />post<?pi value?>fin</child2>\n<child3 />\n</node>\n"), STR("\t"), 0);
CHECK_NODE_EX(doc, STR("<node>\n\t<child1 />\n\t<child2>pre<![CDATA[data]]>mid<!--comment-->\n\t\t<test />post<?pi value?>fin</child2>\n\t<child3 />\n</node>\n"), STR("\t"), format_indent);
}
TEST_XML(write_no_empty_element_tags, "<node><child1/><child2>text</child2><child3></child3></node>")
{
CHECK_NODE(doc, STR("<node><child1/><child2>text</child2><child3/></node>"));
CHECK_NODE_EX(doc, STR("<node><child1></child1><child2>text</child2><child3></child3></node>"), STR("\t"), format_raw | format_no_empty_element_tags);
CHECK_NODE_EX(doc, STR("<node>\n\t<child1></child1>\n\t<child2>text</child2>\n\t<child3></child3>\n</node>\n"), STR("\t"), format_indent | format_no_empty_element_tags);
}
TEST_XML_FLAGS(write_roundtrip, "<node><child1 attr1='value1' attr2='value2'/><child2 attr='value'>pre<![CDATA[data]]>mid&lt;text&amp;escape<!--comment--><test/>post<?pi value?>fin</child2><child3/></node>", parse_full)
{
const unsigned int flagset[] = { format_indent, format_raw, format_no_declaration, format_indent_attributes, format_no_empty_element_tags, format_attribute_single_quote };
size_t flagcount = sizeof(flagset) / sizeof(flagset[0]);
for (size_t i = 0; i < (size_t(1) << flagcount); ++i)
{
unsigned int flags = 0;
for (size_t j = 0; j < flagcount; ++j)
if (i & (size_t(1) << j))
flags |= flagset[j];
std::string contents = write_narrow(doc, flags, encoding_utf8);
xml_document verify;
CHECK(verify.load_buffer(contents.c_str(), contents.size(), parse_full));
CHECK(test_write_narrow(verify, flags, encoding_utf8, contents.c_str(), contents.size()));
xml_document verifyws;
CHECK(verifyws.load_buffer(contents.c_str(), contents.size(), parse_full | parse_ws_pcdata));
CHECK(test_write_narrow(verifyws, flags, encoding_utf8, contents.c_str(), contents.size()));
}
}
TEST(write_flush_coverage)
{
xml_document doc;
// this creates a node that uses short sequences of lengths 1-6 for output
xml_node n = doc.append_child(STR("n"));
xml_attribute a = n.append_attribute(STR("a"));
xml_attribute b = n.append_attribute(STR("b"));
b.set_value(STR("<&\""));
n.append_child(node_comment);
size_t basel = save_narrow(doc, format_raw, encoding_auto).size();
size_t bufl = 2048;
for (size_t l = 0; l <= basel; ++l)
{
std::basic_string<char_t> pad(bufl - l, STR('v'));
a.set_value(pad.c_str());
std::string s = save_narrow(doc, format_raw, encoding_auto);
CHECK(s.size() == basel + bufl - l);
}
}
#ifndef PUGIXML_NO_EXCEPTIONS
struct throwing_writer: xml_writer
{
virtual void write(const void*, size_t) PUGIXML_OVERRIDE
{
throw std::runtime_error("write failed");
}
};
TEST_XML(write_throw_simple, "<node><child/></node>")
{
try
{
throwing_writer w;
doc.print(w);
CHECK_FORCE_FAIL("Expected exception");
}
catch (std::runtime_error&)
{
}
}
TEST_XML(write_throw_encoding, "<node><child/></node>")
{
try
{
throwing_writer w;
doc.print(w, STR("\t"), format_default, encoding_utf32_be);
CHECK_FORCE_FAIL("Expected exception");
}
catch (std::runtime_error&)
{
}
}
#endif
TEST_XML(write_skip_control_chars, "<a>\f\t\n\x0F\x19</a>")
{
CHECK_NODE_EX(doc.first_child(), STR("<a>\t\n</a>\n"), STR(""), pugi::format_default | pugi::format_skip_control_chars);
}
TEST_XML(write_keep_control_chars, "<a>\f\t\n\x0F\x19</a>")
{
CHECK_NODE_EX(doc.first_child(), STR("<a>&#12;\t\n&#15;&#25;</a>\n"), STR(""), pugi::format_default);
}

View file

@ -1,6 +1,6 @@
#ifndef PUGIXML_NO_XPATH
#include "common.hpp"
#include "test.hpp"
#include <string.h>
#include <wchar.h>
@ -10,6 +10,8 @@
#include <algorithm>
#include <limits>
using namespace pugi;
static void load_document_copy(xml_document& doc, const char_t* text)
{
xml_document source;
@ -18,6 +20,22 @@ static void load_document_copy(xml_document& doc, const char_t* text)
doc.append_copy(source.first_child());
}
template <typename T>
static void random_shuffle(std::vector<T>& v)
{
size_t rng = 2147483647;
for (size_t i = v.size() - 1; i > 0; --i)
{
// Fisher-Yates shuffle
size_t j = rng % (i + 1);
std::swap(v[j], v[i]);
// LCG RNG, constants from Numerical Recipes
rng = rng * 1664525 + 1013904223;
}
}
TEST(xpath_allocator_many_pages)
{
std::basic_string<char_t> query = STR("0");
@ -153,7 +171,7 @@ TEST(xpath_sort_random_medium)
xpath_node_set ns = doc.select_nodes(STR("//node() | //@*"));
std::vector<xpath_node> nsv(ns.begin(), ns.end());
std::random_shuffle(nsv.begin(), nsv.end());
random_shuffle(nsv);
xpath_node_set copy(&nsv[0], &nsv[0] + nsv.size());
copy.sort();
@ -182,7 +200,7 @@ TEST(xpath_sort_random_large)
xpath_node_set ns = doc.select_nodes(STR("//node() | //@*"));
std::vector<xpath_node> nsv(ns.begin(), ns.end());
std::random_shuffle(nsv.begin(), nsv.end());
random_shuffle(nsv);
xpath_node_set copy(&nsv[0], &nsv[0] + nsv.size());
copy.sort();
@ -194,40 +212,40 @@ TEST(xpath_sort_random_large)
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");
const char_t* str_flt_max = STR("340282346638528860000000000000000000000");
const char_t* str_flt_max_dec = STR("340282346638528860000000000000000000000.000000");
const char_t* str_dbl_max = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
const char_t* str_dbl_max_dec = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000");
xml_node c;
// check parsing
CHECK_XPATH_NUMBER(c, str_flt_max, std::numeric_limits<float>::max());
CHECK_XPATH_NUMBER(c, str_flt_max_dec, std::numeric_limits<float>::max());
CHECK_XPATH_NUMBER(c, str_flt_max, double(std::numeric_limits<float>::max()));
CHECK_XPATH_NUMBER(c, str_flt_max_dec, double(std::numeric_limits<float>::max()));
CHECK_XPATH_NUMBER(c, str_dbl_max, std::numeric_limits<double>::max());
CHECK_XPATH_NUMBER(c, str_dbl_max_dec, std::numeric_limits<double>::max());
}
static bool test_xpath_string_prefix(const pugi::xml_node& node, const pugi::char_t* query, const pugi::char_t* expected, size_t match_length)
static bool test_xpath_string_prefix(const xml_node& node, const char_t* query, const char_t* expected, size_t match_length)
{
pugi::xpath_query q(query);
xpath_query q(query);
pugi::char_t result[32];
char_t result[32];
size_t size = q.evaluate_string(result, sizeof(result) / sizeof(result[0]), node);
size_t expected_length = std::char_traits<pugi::char_t>::length(expected);
size_t expected_length = std::char_traits<char_t>::length(expected);
return size == expected_length + 1 && std::char_traits<pugi::char_t>::compare(result, expected, match_length) == 0;
return size == expected_length + 1 && std::char_traits<char_t>::compare(result, expected, match_length) == 0;
}
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");
const char_t* str_flt_max = STR("340282346638528860000000000000000000000");
const char_t* str_flt_max_dec = STR("340282346638528860000000000000000000000.000000");
const char_t* str_dbl_max = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
const char_t* str_dbl_max_dec = STR("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000");
xml_node c;
@ -240,7 +258,7 @@ TEST(xpath_long_numbers_stringize)
TEST(xpath_denorm_numbers)
{
std::basic_string<pugi::char_t> query;
std::basic_string<char_t> query;
// 10^-318 - double denormal
for (int i = 0; i < 106; ++i)
@ -249,7 +267,13 @@ TEST(xpath_denorm_numbers)
query += STR("0.001");
}
CHECK_XPATH_STRING(xml_node(), query.c_str(), STR("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009999987484955998"));
// check if current fpu setup supports denormals
double denorm = xpath_query(query.c_str()).evaluate_number(xml_node());
if (denorm != 0.0)
{
CHECK_XPATH_STRING(xml_node(), query.c_str(), STR("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009999987484955998"));
}
}
TEST_XML(xpath_rexml_1, "<a><b><c id='a'/></b><c id='b'/></a>")
@ -367,6 +391,36 @@ TEST(xpath_large_node_set)
CHECK(ns.size() == 10001);
}
TEST(xpath_out_of_memory_query)
{
test_runner::_memory_fail_threshold = 1;
CHECK_ALLOC_FAIL(xpath_query q(STR("node")));
}
TEST_XML(xpath_out_of_memory_evaluate, "<n/>")
{
test_runner::_memory_fail_threshold = 4196 * sizeof(char_t) + 4096 * 2 + 32768;
std::basic_string<char_t> query = STR("*[concat(\"a\", \"");
query.resize(4196, 'a');
query += STR("\")]");
xpath_query q(query.c_str());
CHECK_ALLOC_FAIL(CHECK(q.evaluate_boolean(doc) == false));
CHECK_ALLOC_FAIL(CHECK_DOUBLE_NAN(q.evaluate_number(doc)));
#ifndef PUGIXML_NO_STL
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(doc).empty()));
#endif
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, doc) == 1));
CHECK_ALLOC_FAIL(CHECK(q.evaluate_node(doc) == xpath_node()));
CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc).empty()));
}
TEST(xpath_out_of_memory_evaluate_concat)
{
test_runner::_memory_fail_threshold = 4196 * sizeof(char_t) + 4096 * 2;
@ -376,21 +430,25 @@ TEST(xpath_out_of_memory_evaluate_concat)
query.resize(4196, 'a');
query += STR("\")");
pugi::xpath_query q(query.c_str());
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_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, xml_node()) == 1));
}
CHECK_FORCE_FAIL("Expected out of memory exception");
}
catch (const std::bad_alloc&)
{
}
#endif
TEST(xpath_out_of_memory_evaluate_concat_list)
{
std::basic_string<char_t> query = STR("concat(");
for (size_t i = 0; i < 500; ++i)
query += STR("\"\",");
query += STR("\"\")");
xpath_query q(query.c_str());
test_runner::_memory_fail_threshold = 1;
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, xml_node()) == 1));
}
TEST(xpath_out_of_memory_evaluate_substring)
@ -402,79 +460,151 @@ TEST(xpath_out_of_memory_evaluate_substring)
query.resize(4196, 'a');
query += STR("\", 1, 4097)");
pugi::xpath_query q(query.c_str());
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, "<node><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/></node>")
TEST_XML(xpath_out_of_memory_evaluate_union, "<node />")
{
// left hand side: size * sizeof(xpath_node) (8 on 32-bit, 16 on 64-bit)
// right hand side: same
// to make sure that when we append right hand side to left hand side, we run out of an XPath stack page (4K), we need slightly more than 2K/8 = 256 nodes on 32-bit, 128 nodes on 64-bit
size_t count = sizeof(void*) == 4 ? 300 : 150;
for (size_t i = 0; i < count; ++i)
doc.first_child().append_child(STR("a"));
xpath_query q(STR("a|a"));
test_runner::_memory_fail_threshold = 1;
CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc.child(STR("node"))).empty()));
}
TEST_XML(xpath_out_of_memory_evaluate_union_hash, "<node />")
{
// left hand side: size * sizeof(xpath_node) (8 on 32-bit, 16 on 64-bit)
// right hand side: same
// hash table: size * 1.5 * sizeof(void*)
// to make sure that when we append right hand side to left hand side, we do *not* run out of an XPath stack page (4K), we need slightly less than 2K/8 = 256 nodes on 32-bit, 128 nodes on 64-bit
size_t count = sizeof(void*) == 4 ? 200 : 100;
for (size_t i = 0; i < count; ++i)
doc.first_child().append_child(STR("a"));
xpath_query q(STR("a|a"));
test_runner::_memory_fail_threshold = 1;
CHECK_ALLOC_FAIL(CHECK(q.evaluate_node_set(doc.child(STR("node"))).empty()));
}
TEST_XML(xpath_out_of_memory_evaluate_predicate, "<node><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/></node>")
{
test_runner::_memory_fail_threshold = 32768 + 4096 * 2;
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)))))))))))))))))))"));
xpath_query q(STR("//a[//a[//a[//a[true()]]]]"));
#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).empty()));
}
TEST_XML(xpath_out_of_memory_evaluate_predicate, "<node><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/><a/></node>")
TEST_XML(xpath_out_of_memory_evaluate_normalize_space_0, "<node> a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z </node>")
{
test_runner::_memory_fail_threshold = 32768 + 4096 * 2;
pugi::xpath_query q(STR("//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[//a[true()]]]]]]]]]]]]]]"));
xpath_query q(STR("concat(normalize-space(), normalize-space(), normalize-space(), normalize-space(), normalize-space(), normalize-space(), normalize-space(), normalize-space())"));
#ifdef PUGIXML_NO_EXCEPTIONS
CHECK(q.evaluate_node_set(doc).empty());
#else
try
{
q.evaluate_node_set(doc);
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, doc.first_child()) == 1));
}
CHECK_FORCE_FAIL("Expected out of memory exception");
}
catch (const std::bad_alloc&)
{
}
#endif
TEST_XML(xpath_out_of_memory_evaluate_normalize_space_1, "<node> a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z </node>")
{
test_runner::_memory_fail_threshold = 32768 + 4096 * 2;
xpath_query q(STR("concat(normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node), normalize-space(node))"));
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, doc) == 1));
}
TEST_XML(xpath_out_of_memory_evaluate_translate, "<node> a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z </node>")
{
test_runner::_memory_fail_threshold = 32768 + 4096 * 2;
xpath_query q(STR("concat(translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'), translate(node, 'a', '\xe9'))"));
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, doc) == 1));
}
TEST_XML(xpath_out_of_memory_evaluate_translate_table, "<node> a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z </node>")
{
test_runner::_memory_fail_threshold = 32768 + 4096 * 2;
xpath_query q(STR("concat(translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'), translate(node, 'a', 'A'))"));
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, doc) == 1));
}
TEST(xpath_out_of_memory_evaluate_string_append)
{
test_runner::_memory_fail_threshold = 32768 + 4096 * 2;
std::basic_string<char_t> literal(5000, 'a');
std::basic_string<char_t> buf;
buf += STR("<n><c>text</c><c>");
buf += literal;
buf += STR("</c></n>");
xml_document doc;
CHECK(doc.load_buffer_inplace(&buf[0], buf.size() * sizeof(char_t)));
xpath_query q(STR("string(n)"));
CHECK(q);
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, doc) == 1));
}
TEST(xpath_out_of_memory_evaluate_number_to_string)
{
test_runner::_memory_fail_threshold = 4096 + 128;
xpath_variable_set vars;
vars.set(STR("x"), 1e+308);
xpath_query q(STR("concat($x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x, $x)"), &vars);
CHECK_ALLOC_FAIL(CHECK(q.evaluate_string(0, 0, xml_node()) == 1));
}
TEST(xpath_memory_concat_massive)
{
pugi::xml_document doc;
pugi::xml_node node = doc.append_child(STR("node"));
xml_document doc;
xml_node node = doc.append_child(STR("node"));
for (int i = 0; i < 5000; ++i)
node.append_child(STR("c")).text().set(i % 10);
pugi::xpath_query q(STR("/"));
xpath_query q(STR("/"));
size_t size = q.evaluate_string(0, 0, node);
CHECK(size == 5001);
}
TEST_XML(xpath_memory_translate_table, "<node>a</node>")
{
test_runner::_memory_fail_threshold = 32768 + 4096 + 128;
// 128b per table => we need 32+ translate calls to exhaust a page
std::basic_string<char_t> query = STR("concat(");
for (int i = 0; i < 64; ++i)
query += STR("translate(.,'a','A'),");
query += STR("'')");
CHECK_ALLOC_FAIL(CHECK(!xpath_query(query.c_str())));
}
TEST_XML(xpath_sort_copy_share, "<node><child1 attr1='value1' attr2='value2'/><child2 attr1='value1'>test</child2></node>")
{
// copy sharing shares the name/value data for nodes that can potentially make document order optimization invalid (silently)
@ -626,6 +756,17 @@ TEST(xpath_sort_crossdoc_different_depth)
CHECK((ns[0] == ns1[0] && ns[1] == ns2[0]) || (ns[0] == ns2[0] && ns[1] == ns1[0]));
}
TEST_XML(xpath_sort_empty_node, "<node><child1/><child2/></node>")
{
xml_node n = doc.child(STR("node"));
xpath_node nodes[] = { n.child(STR("child2")), xml_node(), n.child(STR("child1")), xml_node() };
xpath_node_set ns(nodes, nodes + sizeof(nodes) / sizeof(nodes[0]));
ns.sort();
CHECK(!ns[0] && !ns[1] && ns[2] == nodes[2] && ns[3] == nodes[0]);
}
TEST(xpath_allocate_string_out_of_memory)
{
std::basic_string<char_t> query;
@ -634,20 +775,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
}
@ -672,4 +801,15 @@ TEST(xpath_remove_duplicates)
tester % (2 + i);
}
}
TEST(xpath_anonymous_nodes)
{
xml_document doc;
doc.append_child(node_element);
doc.append_child(node_pi);
CHECK_XPATH_NODESET(doc, STR("/name"));
CHECK_XPATH_NODESET(doc, STR("/processing-instruction('a')"));
CHECK_XPATH_NODESET(doc, STR("/ns:*"));
}
#endif

View file

@ -2,11 +2,14 @@
#include <string.h> // because Borland's STL is braindead, we have to include <string.h> _before_ <string> in order to get memcmp
#include "common.hpp"
#include "test.hpp"
#include "helpers.hpp"
#include <string>
#include <vector>
using namespace pugi;
TEST_XML(xpath_api_select_nodes, "<node><head/><foo/><foo/><tail/></node>")
{
@ -30,12 +33,12 @@ TEST_XML(xpath_api_select_node, "<node><head/><foo id='1'/><foo/><tail/></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);
}
@ -106,6 +109,7 @@ TEST_XML(xpath_api_nodeset_accessors, "<node><foo/><foo/></node>")
TEST_XML(xpath_api_nodeset_copy, "<node><foo/><foo/></node>")
{
xpath_node_set empty;
xpath_node_set set = doc.select_nodes(STR("node/foo"));
xpath_node_set copy1 = set;
@ -119,7 +123,7 @@ TEST_XML(xpath_api_nodeset_copy, "<node><foo/><foo/></node>")
xpath_node_set copy3;
copy3 = set;
copy3 = copy3;
copy3 = xpath_node_set(copy3);
CHECK(copy3.size() == 2);
CHECK_STRING(copy3[0].node().name(), STR("foo"));
@ -131,7 +135,7 @@ TEST_XML(xpath_api_nodeset_copy, "<node><foo/><foo/></node>")
xpath_node_set copy5;
copy5 = set;
copy5 = xpath_node_set();
copy5 = empty;
CHECK(copy5.size() == 0);
}
@ -257,7 +261,7 @@ TEST(xpath_api_evaluate_string)
// test for just enough space
std::basic_string<char_t> 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<char_t> 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 +295,7 @@ TEST(xpath_api_return_type)
TEST(xpath_api_query_bool)
{
xpath_query q(STR("node"));
CHECK(q);
CHECK((!q) == false);
}
@ -300,7 +304,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 +360,7 @@ TEST(xpath_api_exception_what)
CHECK(e.what()[0] != 0);
}
}
#endif
TEST(xpath_api_node_set_ctor_out_of_memory)
{
@ -363,15 +368,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,49 +378,267 @@ 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, "<node><a/><b/></node>")
{
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, "<node><head/><foo id='1'/><foo/><tail/></node>")
TEST(xpath_api_empty)
{
xpath_node n1 = doc.select_single_node(STR("node/foo"));
xml_node c;
xpath_query q(STR("node/foo"));
xpath_node n2 = doc.select_single_node(q);
xpath_query q;
CHECK(!q);
CHECK(!q.evaluate_boolean(c));
}
CHECK(n1.node().attribute(STR("id")).as_int() == 1);
CHECK(n2.node().attribute(STR("id")).as_int() == 1);
#ifdef PUGIXML_HAS_MOVE
TEST_XML(xpath_api_nodeset_move_ctor, "<node><foo/><foo/><bar/></node>")
{
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, "<node><foo/><foo/><bar/></node>")
{
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, "<node><foo/><foo/><bar/></node>")
{
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, "<node><foo/><foo/><bar/></node>")
{
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, "<node><foo/><foo/><bar/></node>")
{
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_XML(xpath_api_nodeset_move_assign_self, "<node><foo/><foo/><bar/></node>")
{
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;
set = std::move(*&set);
}
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<xpath_query> 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 (size_t i = 0; i < qv.size(); ++i)
result += qv[i].evaluate_number(xml_node());
CHECK(result == 45);
}
#endif
#endif

View file

@ -1,12 +1,16 @@
#ifndef PUGIXML_NO_XPATH
#include "common.hpp"
#include "test.hpp"
#include <string>
using namespace pugi;
TEST_XML(xpath_number_number, "<node>123</node>")
{
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 +39,7 @@ TEST_XML(xpath_number_number, "<node>123</node>")
// 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 +48,21 @@ TEST_XML(xpath_number_sum, "<node>123<child>789</child></node><node/>")
{
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 +159,7 @@ TEST(xpath_number_round)
TEST_XML(xpath_boolean_boolean, "<node />")
{
xml_node c;
// boolean with 0 arguments
CHECK_XPATH_FAIL(STR("boolean()"));
@ -182,14 +186,14 @@ TEST_XML(xpath_boolean_boolean, "<node />")
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 +201,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 +212,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 +223,7 @@ TEST(xpath_boolean_false)
TEST_XML(xpath_boolean_lang, "<node xml:lang='en'><child xml:lang='zh-UK'><subchild attr=''/></child></node><foo><bar/></foo>")
{
xml_node c;
// lang with 0 arguments
CHECK_XPATH_FAIL(STR("lang()"));
@ -228,7 +232,7 @@ TEST_XML(xpath_boolean_lang, "<node xml:lang='en'><child xml:lang='zh-UK'><subch
CHECK_XPATH_BOOLEAN(doc.child(STR("foo")), STR("lang('en')"), false);
CHECK_XPATH_BOOLEAN(doc.child(STR("foo")), STR("lang('')"), false);
CHECK_XPATH_BOOLEAN(doc.child(STR("foo")).child(STR("bar")), STR("lang('en')"), false);
// lang with 1 argument, same language/prefix
CHECK_XPATH_BOOLEAN(doc.child(STR("node")), STR("lang('en')"), true);
CHECK_XPATH_BOOLEAN(doc.child(STR("node")).child(STR("child")), STR("lang('zh-uk')"), true);
@ -373,7 +377,7 @@ TEST(xpath_string_substring_before)
// substring-before with 1 argument
CHECK_XPATH_FAIL(STR("substring-before('a')"));
// substring-before with 2 arguments
CHECK_XPATH_STRING(c, STR("substring-before('abc', 'abc')"), STR(""));
CHECK_XPATH_STRING(c, STR("substring-before('abc', 'a')"), STR(""));
@ -382,7 +386,7 @@ TEST(xpath_string_substring_before)
CHECK_XPATH_STRING(c, STR("substring-before('abc', 'c')"), STR("ab"));
CHECK_XPATH_STRING(c, STR("substring-before('abc', '')"), STR(""));
CHECK_XPATH_STRING(c, STR("substring-before('', '')"), STR(""));
// substring-before with 2 arguments, from W3C standard
CHECK_XPATH_STRING(c, STR("substring-before(\"1999/04/01\",\"/\")"), STR("1999"));
@ -399,7 +403,7 @@ TEST(xpath_string_substring_after)
// substring-after with 1 argument
CHECK_XPATH_FAIL(STR("substring-after('a')"));
// substring-after with 2 arguments
CHECK_XPATH_STRING(c, STR("substring-after('abc', 'abc')"), STR(""));
CHECK_XPATH_STRING(c, STR("substring-after('abc', 'a')"), STR("bc"));
@ -430,10 +434,10 @@ TEST(xpath_string_substring)
// substring with 0 arguments
CHECK_XPATH_FAIL(STR("substring()"));
// substring with 1 argument
CHECK_XPATH_FAIL(STR("substring('')"));
// substring with 2 arguments
CHECK_XPATH_STRING(c, STR("substring('abcd', 2)"), STR("bcd"));
CHECK_XPATH_STRING(c, STR("substring('abcd', 1)"), STR("abcd"));
@ -517,7 +521,7 @@ TEST_XML_FLAGS(xpath_string_normalize_space, "<node> \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 +530,7 @@ TEST_XML_FLAGS(xpath_string_normalize_space, "<node> \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 +541,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"));
@ -566,6 +570,7 @@ TEST(xpath_string_translate_table)
CHECK_XPATH_STRING(c, STR("translate('abcd\xe9 ', 'abc', 'ABC')"), STR("ABCd\xe9 "));
CHECK_XPATH_STRING(c, STR("translate('abcd\xe9 ', 'abc\xe9', 'ABC!')"), STR("ABCd! "));
CHECK_XPATH_STRING(c, STR("translate('abcd! ', 'abc!', 'ABC\xe9')"), STR("ABCd\xe9 "));
CHECK_XPATH_STRING(c, STR("translate('abcde', concat('abc', 'd'), 'ABCD')"), STR("ABCDe"));
CHECK_XPATH_STRING(c, STR("translate('abcde', 'abcd', concat('ABC', 'D'))"), STR("ABCDe"));
}
@ -604,7 +609,7 @@ TEST_XML(xpath_nodeset_position, "<node><c1/><c1/><c2/><c3/><c3/><c3/><c3/></nod
CHECK_XPATH_NODESET(n, STR("c1[position() = 3]"));
CHECK_XPATH_NODESET(n, STR("c2/preceding-sibling::node()[position() = 1]")) % 4;
CHECK_XPATH_NODESET(n, STR("c2/preceding-sibling::node()[position() = 2]")) % 3;
// position with 1 argument
CHECK_XPATH_FAIL(STR("position(c)"));
}
@ -640,7 +645,7 @@ TEST_XML(xpath_nodeset_id, "<node id='foo'/>")
// 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 +661,7 @@ TEST_XML_FLAGS(xpath_nodeset_local_name, "<node xmlns:foo='http://foo'><c1>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 +686,7 @@ TEST_XML_FLAGS(xpath_nodeset_namespace_uri, "<node xmlns:foo='http://foo'><c1>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 +715,7 @@ TEST_XML_FLAGS(xpath_nodeset_name, "<node xmlns:foo='http://foo'><c1>text</c1><c
// name with 0 arguments
CHECK_XPATH_STRING(c, STR("name()"), STR(""));
CHECK_XPATH_STRING(n, STR("name()"), STR("node"));
// name with 1 non-node-set argument
CHECK_XPATH_FAIL(STR("name(1)"));
@ -733,7 +738,7 @@ TEST(xpath_function_arguments)
// conversion to string
CHECK_XPATH_NUMBER(c, STR("string-length(12)"), 2);
// conversion to number
CHECK_XPATH_NUMBER(c, STR("round('1.2')"), 1);
CHECK_XPATH_NUMBER(c, STR("round('1.7')"), 2);
@ -741,13 +746,13 @@ TEST(xpath_function_arguments)
// conversion to boolean
CHECK_XPATH_BOOLEAN(c, STR("not('1')"), false);
CHECK_XPATH_BOOLEAN(c, STR("not('')"), true);
// conversion to node set
CHECK_XPATH_FAIL(STR("sum(1)"));
// expression evaluation
CHECK_XPATH_NUMBER(c, STR("round((2 + 2 * 2) div 4)"), 2);
// empty expressions
CHECK_XPATH_FAIL(STR("round(,)"));
CHECK_XPATH_FAIL(STR("substring(,)"));
@ -799,4 +804,41 @@ TEST_XML(xpath_string_concat_translate, "<node>foobar</node>")
CHECK_XPATH_STRING(doc, STR("concat('a', 'b', 'c', translate(node, 'o', 'a'), 'd')"), STR("abcfaabard"));
}
TEST(xpath_unknown_functions)
{
char_t query[] = STR("a()");
for (char ch = 'a'; ch <= 'z'; ++ch)
{
query[0] = ch;
CHECK_XPATH_FAIL(query);
query[0] = char_t(ch - 32);
CHECK_XPATH_FAIL(query);
}
}
TEST(xpath_string_translate_table_out_of_memory)
{
xml_node c;
// our goal is to generate translate table OOM without generating query OOM
std::basic_string<char_t> query = STR("concat(");
size_t count = 20;
for (size_t i = 0; i < count; ++i)
{
if (i != 0) query += STR(",");
query += STR("translate('a','a','A')");
}
query += STR(")");
std::basic_string<char_t> result(count, 'A');
test_runner::_memory_fail_threshold = 5000;
CHECK_ALLOC_FAIL(CHECK_XPATH_STRING(c, query.c_str(), result.c_str()));
}
#endif

View file

@ -1,6 +1,8 @@
#ifndef PUGIXML_NO_XPATH
#include "common.hpp"
#include "test.hpp"
using namespace pugi;
TEST(xpath_operators_arithmetic)
{
@ -63,7 +65,7 @@ TEST(xpath_operators_arithmetic_specials)
CHECK_XPATH_STRING(c, STR("1 div 0 + 100"), STR("Infinity"));
CHECK_XPATH_STRING(c, STR("-1 div 0 + 100"), STR("-Infinity"));
CHECK_XPATH_STRING(c, STR("0 div 0 + 100"), STR("NaN"));
// unary - and multiplication clarifications from recommendations errata
CHECK_XPATH_STRING(c, STR("1 div -0"), STR("-Infinity"));
CHECK_XPATH_STRING(c, STR("-1 div -0"), STR("Infinity"));
@ -99,7 +101,7 @@ TEST(xpath_operators_logical)
CHECK_XPATH_BOOLEAN(c, STR("true() and false()"), false);
CHECK_XPATH_BOOLEAN(c, STR("false() and false()"), false);
CHECK_XPATH_BOOLEAN(c, STR("false() and true()"), false);
// boolean conversion
CHECK_XPATH_BOOLEAN(c, STR("1 or ''"), true);
CHECK_XPATH_BOOLEAN(c, STR("1 and ''"), false);
@ -192,7 +194,7 @@ TEST_XML(xpath_operators_equality_node_set_node_set, "<node><c1><v>a</v><v>b</v>
CHECK_XPATH_BOOLEAN(n, STR("c1/v != c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c2/v != c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != c4/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != c5/v"), true); // (a, b) != (a, b), since a != b, as per XPath spec (comparison operators are so not intutive)
CHECK_XPATH_BOOLEAN(n, STR("c1/v != c5/v"), true); // (a, b) != (a, b), since a != b, as per XPath spec (comparison operators are so not intuitive)
CHECK_XPATH_BOOLEAN(n, STR("c3/v != c6/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v != x"), false);
CHECK_XPATH_BOOLEAN(n, STR("x != c1/v"), false);
@ -225,7 +227,7 @@ TEST_XML(xpath_operators_equality_node_set_primitive, "<node><c1><v>1</v><v>-1</
CHECK_XPATH_BOOLEAN(n, STR("c2/v != 1"), true);
CHECK_XPATH_BOOLEAN(n, STR("1 != c2/v"), true);
#endif
// node set vs string
CHECK_XPATH_BOOLEAN(c, STR("x = '1'"), false);
CHECK_XPATH_BOOLEAN(c, STR("x != '1'"), false);
@ -332,11 +334,21 @@ TEST_XML(xpath_operators_inequality_node_set_node_set, "<node><c1><v>1</v><v>-1<
CHECK_XPATH_BOOLEAN(n, STR("c1/v < c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v <= c3/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v[1] > c1/v[1]"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v[1] < c1/v[1]"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v[1] >= c1/v[1]"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v[1] <= c1/v[1]"), true);
#ifndef MSVC6_NAN_BUG
CHECK_XPATH_BOOLEAN(n, STR("c1/v > c2/v"), false);
CHECK_XPATH_BOOLEAN(n, STR("c1/v >= c2/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v < c2/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c1/v <= c2/v"), true);
CHECK_XPATH_BOOLEAN(n, STR("c2/v[2] < c2/v[2]"), false);
CHECK_XPATH_BOOLEAN(n, STR("c2/v[2] > c2/v[2]"), false);
CHECK_XPATH_BOOLEAN(n, STR("c2/v[2] <= c2/v[2]"), false);
CHECK_XPATH_BOOLEAN(n, STR("c2/v[2] >= c2/v[2]"), false);
#endif
}
@ -423,6 +435,24 @@ TEST_XML(xpath_operators_union, "<node><employee/><employee secretary=''/><emplo
CHECK_XPATH_NODESET(n, STR(". | tail/preceding-sibling::employee | .")) % 2 % 3 % 4 % 6 % 8 % 11;
}
TEST_XML(xpath_operators_union_order, "<node />")
{
xml_node n = doc.child(STR("node"));
n.append_child(STR("c"));
n.prepend_child(STR("b"));
n.append_child(STR("d"));
n.prepend_child(STR("a"));
xpath_node_set ns = n.select_nodes(STR("d | d | b | c | b | a | c | d | b"));
CHECK(ns.size() == 4);
CHECK_STRING(ns[0].node().name(), STR("d"));
CHECK_STRING(ns[1].node().name(), STR("b"));
CHECK_STRING(ns[2].node().name(), STR("c"));
CHECK_STRING(ns[3].node().name(), STR("a"));
}
TEST(xpath_operators_union_error)
{
CHECK_XPATH_FAIL(STR(". | true()"));

Some files were not shown because too many files have changed in this diff Show more