From 7cf4964e482594e3d3f8ca49a82ac068dd6acd5c Mon Sep 17 00:00:00 2001 From: pugixml Upstream Date: Thu, 7 Sep 2023 11:55:13 -0700 Subject: [PATCH] pugixml 2023-09-07 (db78afc2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code extracted from: https://github.com/zeux/pugixml.git at commit db78afc2b7d8f043b4bc6b185635d949ea2ed2a8 (v1.14). Upstream Shortlog ----------------- Andy Maloney (2): 058fc601 Fix weak vtable warning regarding xml_writer b047f46e {cmake} Fix deprecation warning by updating min version to 3.5 Arseny Kapoulkine (42): f388c465 Optimize compact mode: reuse access in insert/remove fad2d5e4 Optimize compact mode: xml_attribute/xml_node implementation 2fa9158b Optimize compact mode: xml_text 33a75c73 Fix memory leak during OOM in convert_buffer 832a4f49 Use more idiomatic code in this codebase ab8453c5 tests: Use snprintf instead of sprintf 3b5c1fb0 tests: Fix MSVC 2005 build 521b2cd8 Add issue templates to try to route questions to Discussions 0cb4f025 Final tweaks after #522 444963e2 Fix error handling in xml_document::save_file 76dcd894 Update version number in preparation for 1.13 0ef3da1e Update release notes and manual for 1.13 c5b288d9 Update HTML documentation 3bd1f452 Fix version check in test 8be081fb Fix Xcode 14 sprintf deprecation warning b6b74724 Adjust the workaround for -pedantic mode and fix tests e11e0c96 Fix comment typo. 1dc3266f docs: Add missing documentation for xml_node::attribute with hint c2c61a59 Add a cautionary comment to xml_node::children(name) a469fa2c Add assertion about header-dest relation to strcpy_insitu 02930331 docs: Add a note to parse_fragment documentation e383ce5d docs: Update HTML documentation d3199a0c Fix get_file_size behavior inconsistency for folders a13b5cc0 Use stricter subset for now to avoid compat issues with Unix-like platforms 750e2032 build: Fix CMake PUGIXML_STATIC_CRT behavior 980cf57f XPath: Account for non-English locales during number->string conversion c72a210f tests: Add more tests for empty text setup 0189471a docs: Fix up grammar 37ba937e Fix code style and simplify conditions f31ad2c1 tests: Add more tests for parse_merge_pcdata 6749789e Fix interaction between parse_merge_pcdata and append_buffer e9d17a04 Streamline conditions with else if 5a33d2b1 docs: Add forgotten set_name overloads to API reference bf42c4c5 Reorder set_value/set size_t overloads and change sz to size efb76c11 docs: Update external XPath links dfb2b7f7 Cache ~last position of merged PCDATA 58616a29 Avoid store-load penalty on cursor->parent 30adb171 Use memmove instead of strcat ff569859 Rename merged to merged_pcdata for clarity. 1a9a41b0 Update copyright year (2022 => 2023) bd70bd76 docs: Update release notes and regenerate HTML documentation db78afc2 Update version to 1.14 everywhere David Korczynski (2): 5cfa7f90 Add Github CIFuzz action 7e8a42ee CI: decrease fuzzing time from 300s to 30s David Seifert (1): 36aa487e Fix `-Wreserved-macro-identifier` Ferenc Géczi (5): f3273712 Add overloads with size_t type argument 09e7cc9b Add test for xml_text::set with size argument d3594023 Add xml_text::set test with size set to substring 19052844 Add test for xml_node::set_value with size argument 39e16928 Add test for xml_attribute::set_value with size argument Izzy Muerte (1): ab8af530 Fix exported symbols under clang-cl (Closes #503) Matthäus Brandl (1): f7de3248 Enable usage of nullptr for MSVC 16 and newer (MSVS 2010) Milian Wolff (1): 173a2634 Correctly set default visibility on non-windows compilers Sergey Abramov (1): 1e963630 Fix compilation errors on old GCC (2.95.3, 3.3.5) Stefan Roellin (1): f4d4316e Add overloads with size_t type argument TodorHryn (1): 6fbf3214 Fix memory leak Viktor Govako (1): effc46f0 Added bool set_value(const char_t* rhs, size_t sz). Vineeth (1): 3ad133a2 Review Changes jiangqucheng (1): ddd3cfa4 #556 fix makefile err in some env vineeth-11316 (3): e15adbe7 Intial Commit for merge_pcdata 068aa22b documentation Change a2825220 Final Commit --- src/pugiconfig.hpp | 6 +- src/pugixml.cpp | 2023 ++++++++++++++++++++++++-------------------- src/pugixml.hpp | 27 +- 3 files changed, 1134 insertions(+), 922 deletions(-) diff --git a/src/pugiconfig.hpp b/src/pugiconfig.hpp index 0713b0efbb..3dc839da6e 100644 --- a/src/pugiconfig.hpp +++ b/src/pugiconfig.hpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.12 + * pugixml parser - version 1.14 * -------------------------------------------------------- - * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2023, 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 @@ -52,7 +52,7 @@ #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2023 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 60b55da3ab..89123c75d0 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.12 + * pugixml parser - version 1.14 * -------------------------------------------------------- - * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2023, 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 @@ -40,6 +40,11 @@ // For placement new #include +// For load_file +#if defined(__linux__) || defined(__APPLE__) +#include +#endif + #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4127) // conditional expression is constant @@ -82,39 +87,39 @@ // Inlining controls #if defined(_MSC_VER) && _MSC_VER >= 1300 -# define PUGI__NO_INLINE __declspec(noinline) +# define PUGI_IMPL_NO_INLINE __declspec(noinline) #elif defined(__GNUC__) -# define PUGI__NO_INLINE __attribute__((noinline)) +# define PUGI_IMPL_NO_INLINE __attribute__((noinline)) #else -# define PUGI__NO_INLINE +# define PUGI_IMPL_NO_INLINE #endif // Branch weight controls #if defined(__GNUC__) && !defined(__c2__) -# define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0) +# define PUGI_IMPL_UNLIKELY(cond) __builtin_expect(cond, 0) #else -# define PUGI__UNLIKELY(cond) (cond) +# define PUGI_IMPL_UNLIKELY(cond) (cond) #endif // Simple static assertion -#define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; } +#define PUGI_IMPL_STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; } // Digital Mars C++ bug workaround for passing char loaded from memory via stack #ifdef __DMC__ -# define PUGI__DMC_VOLATILE volatile +# define PUGI_IMPL_DMC_VOLATILE volatile #else -# define PUGI__DMC_VOLATILE +# define PUGI_IMPL_DMC_VOLATILE #endif // Integer sanitizer workaround; we only apply this for clang since gcc8 has no_sanitize but not unsigned-integer-overflow and produces "attribute directive ignored" warnings #if defined(__clang__) && defined(__has_attribute) # if __has_attribute(no_sanitize) -# define PUGI__UNSIGNED_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow"))) +# define PUGI_IMPL_UNSIGNED_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow"))) # else -# define PUGI__UNSIGNED_OVERFLOW +# define PUGI_IMPL_UNSIGNED_OVERFLOW # endif #else -# define PUGI__UNSIGNED_OVERFLOW +# define PUGI_IMPL_UNSIGNED_OVERFLOW #endif // Borland C++ bug workaround for not defining ::memcpy depending on header include order (can't always use std::memcpy because some compilers don't have it at all) @@ -124,6 +129,12 @@ using std::memmove; using std::memset; #endif +// Old versions of GCC do not define ::malloc and ::free depending on header include order +#if defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)) +using std::malloc; +using std::free; +#endif + // Some MinGW/GCC versions have headers that erroneously omit LLONG_MIN/LLONG_MAX/ULLONG_MAX definitions from limits.h in some configurations #if defined(PUGIXML_HAS_LONG_LONG) && defined(__GNUC__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX) # define LLONG_MIN (-LLONG_MAX - 1LL) @@ -133,36 +144,38 @@ using std::memset; // In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features #if defined(_MSC_VER) && !defined(__S3E__) && !defined(_WIN32_WCE) -# define PUGI__MSVC_CRT_VERSION _MSC_VER +# define PUGI_IMPL_MSVC_CRT_VERSION _MSC_VER #elif defined(_WIN32_WCE) -# define PUGI__MSVC_CRT_VERSION 1310 // MSVC7.1 +# define PUGI_IMPL_MSVC_CRT_VERSION 1310 // MSVC7.1 #endif // Not all platforms have snprintf; we define a wrapper that uses snprintf if possible. This only works with buffers with a known size. #if __cplusplus >= 201103 -# define PUGI__SNPRINTF(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__) -#elif defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 -# define PUGI__SNPRINTF(buf, ...) _snprintf_s(buf, _countof(buf), _TRUNCATE, __VA_ARGS__) +# define PUGI_IMPL_SNPRINTF(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__) +#elif defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 +# define PUGI_IMPL_SNPRINTF(buf, ...) _snprintf_s(buf, _countof(buf), _TRUNCATE, __VA_ARGS__) +#elif defined(__APPLE__) && __clang_major__ >= 14 // Xcode 14 marks sprintf as deprecated while still using C++98 by default +# define PUGI_IMPL_SNPRINTF(buf, fmt, arg1, arg2) snprintf(buf, sizeof(buf), fmt, arg1, arg2) #else -# define PUGI__SNPRINTF sprintf +# define PUGI_IMPL_SNPRINTF sprintf #endif // We put implementation details into an anonymous namespace in source mode, but have to keep it in non-anonymous namespace in header-only mode to prevent binary bloat. #ifdef PUGIXML_HEADER_ONLY -# define PUGI__NS_BEGIN namespace pugi { namespace impl { -# define PUGI__NS_END } } -# define PUGI__FN inline -# define PUGI__FN_NO_INLINE inline +# define PUGI_IMPL_NS_BEGIN namespace pugi { namespace impl { +# define PUGI_IMPL_NS_END } } +# define PUGI_IMPL_FN inline +# define PUGI_IMPL_FN_NO_INLINE inline #else # if defined(_MSC_VER) && _MSC_VER < 1300 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces -# define PUGI__NS_BEGIN namespace pugi { namespace impl { -# define PUGI__NS_END } } +# define PUGI_IMPL_NS_BEGIN namespace pugi { namespace impl { +# define PUGI_IMPL_NS_END } } # else -# define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace { -# define PUGI__NS_END } } } +# define PUGI_IMPL_NS_BEGIN namespace pugi { namespace impl { namespace { +# define PUGI_IMPL_NS_END } } } # endif -# define PUGI__FN -# define PUGI__FN_NO_INLINE PUGI__NO_INLINE +# define PUGI_IMPL_FN +# define PUGI_IMPL_FN_NO_INLINE PUGI_IMPL_NO_INLINE #endif // uintptr_t @@ -182,13 +195,13 @@ namespace pugi #endif // Memory allocation -PUGI__NS_BEGIN - PUGI__FN void* default_allocate(size_t size) +PUGI_IMPL_NS_BEGIN + PUGI_IMPL_FN void* default_allocate(size_t size) { return malloc(size); } - PUGI__FN void default_deallocate(void* ptr) + PUGI_IMPL_FN void default_deallocate(void* ptr) { free(ptr); } @@ -206,12 +219,12 @@ PUGI__NS_BEGIN template deallocation_function xml_memory_management_function_storage::deallocate = default_deallocate; typedef xml_memory_management_function_storage xml_memory; -PUGI__NS_END +PUGI_IMPL_NS_END // String utilities -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN // Get string length - PUGI__FN size_t strlength(const char_t* s) + PUGI_IMPL_FN size_t strlength(const char_t* s) { assert(s); @@ -223,7 +236,7 @@ PUGI__NS_BEGIN } // Compare two strings - PUGI__FN bool strequal(const char_t* src, const char_t* dst) + PUGI_IMPL_FN bool strequal(const char_t* src, const char_t* dst) { assert(src && dst); @@ -235,7 +248,7 @@ PUGI__NS_BEGIN } // Compare lhs with [rhs_begin, rhs_end) - PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) + PUGI_IMPL_FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) { for (size_t i = 0; i < count; ++i) if (lhs[i] != rhs[i]) @@ -245,7 +258,7 @@ PUGI__NS_BEGIN } // Get length of wide string, even if CRT lacks wide character support - PUGI__FN size_t strlength_wide(const wchar_t* s) + PUGI_IMPL_FN size_t strlength_wide(const wchar_t* s) { assert(s); @@ -257,10 +270,10 @@ PUGI__NS_BEGIN return static_cast(end - s); #endif } -PUGI__NS_END +PUGI_IMPL_NS_END // auto_ptr-like object for exception recovery -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN template struct auto_deleter { typedef void (*D)(T*); @@ -284,10 +297,10 @@ PUGI__NS_BEGIN return result; } }; -PUGI__NS_END +PUGI_IMPL_NS_END #ifdef PUGIXML_COMPACT -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN class compact_hash_table { public: @@ -378,7 +391,7 @@ PUGI__NS_BEGIN return 0; } - static PUGI__UNSIGNED_OVERFLOW unsigned int hash(const void* key) + static PUGI_IMPL_UNSIGNED_OVERFLOW unsigned int hash(const void* key) { unsigned int h = static_cast(reinterpret_cast(key) & 0xffffffff); @@ -393,7 +406,7 @@ PUGI__NS_BEGIN } }; - PUGI__FN_NO_INLINE bool compact_hash_table::rehash(size_t count) + PUGI_IMPL_FN_NO_INLINE bool compact_hash_table::rehash(size_t count) { size_t capacity = 32; while (count >= capacity - capacity / 4) @@ -423,10 +436,10 @@ PUGI__NS_BEGIN return true; } -PUGI__NS_END +PUGI_IMPL_NS_END #endif -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN #ifdef PUGIXML_COMPACT static const uintptr_t xml_memory_block_alignment = 4; #else @@ -444,16 +457,16 @@ PUGI__NS_BEGIN static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask; #ifdef PUGIXML_COMPACT - #define PUGI__GETHEADER_IMPL(object, page, flags) // unused - #define PUGI__GETPAGE_IMPL(header) (header).get_page() + #define PUGI_IMPL_GETHEADER_IMPL(object, page, flags) // unused + #define PUGI_IMPL_GETPAGE_IMPL(header) (header).get_page() #else - #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast(object) - reinterpret_cast(page)) << 8) | (flags)) + #define PUGI_IMPL_GETHEADER_IMPL(object, page, flags) (((reinterpret_cast(object) - reinterpret_cast(page)) << 8) | (flags)) // this macro casts pointers through void* to avoid 'cast increases required alignment of target type' warnings - #define PUGI__GETPAGE_IMPL(header) static_cast(const_cast(static_cast(reinterpret_cast(&header) - (header >> 8)))) + #define PUGI_IMPL_GETPAGE_IMPL(header) static_cast(const_cast(static_cast(reinterpret_cast(&header) - (header >> 8)))) #endif - #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header) - #define PUGI__NODETYPE(n) static_cast((n)->header & impl::xml_memory_page_type_mask) + #define PUGI_IMPL_GETPAGE(n) PUGI_IMPL_GETPAGE_IMPL((n)->header) + #define PUGI_IMPL_NODETYPE(n) static_cast((n)->header & impl::xml_memory_page_type_mask) struct xml_allocator; @@ -543,7 +556,7 @@ PUGI__NS_BEGIN void* allocate_memory(size_t size, xml_memory_page*& out_page) { - if (PUGI__UNLIKELY(_busy_size + size > xml_memory_page_size)) + if (PUGI_IMPL_UNLIKELY(_busy_size + size > xml_memory_page_size)) return allocate_memory_oob(size, out_page); void* buf = reinterpret_cast(_root) + sizeof(xml_memory_page) + _busy_size; @@ -564,7 +577,7 @@ PUGI__NS_BEGIN // adjust for marker ptrdiff_t offset = static_cast(result) - reinterpret_cast(out_page->compact_page_marker); - if (PUGI__UNLIKELY(static_cast(offset) >= 256 * xml_memory_block_alignment)) + if (PUGI_IMPL_UNLIKELY(static_cast(offset) >= 256 * xml_memory_block_alignment)) { // insert new marker uint32_t* marker = static_cast(result); @@ -641,7 +654,7 @@ PUGI__NS_BEGIN { static const size_t max_encoded_offset = (1 << 16) * xml_memory_block_alignment; - PUGI__STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset); + PUGI_IMPL_STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset); // allocate memory for string and header block size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); @@ -707,7 +720,7 @@ PUGI__NS_BEGIN #endif }; - PUGI__FN_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page) + PUGI_IMPL_FN_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page) { const size_t large_allocation_threshold = xml_memory_page_size / 4; @@ -744,10 +757,10 @@ PUGI__NS_BEGIN return reinterpret_cast(page) + sizeof(xml_memory_page); } -PUGI__NS_END +PUGI_IMPL_NS_END #ifdef PUGIXML_COMPACT -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN static const uintptr_t compact_alignment_log2 = 2; static const uintptr_t compact_alignment = 1 << compact_alignment_log2; @@ -756,7 +769,7 @@ PUGI__NS_BEGIN public: compact_header(xml_memory_page* page, unsigned int flags) { - PUGI__STATIC_ASSERT(xml_memory_block_alignment == compact_alignment); + PUGI_IMPL_STATIC_ASSERT(xml_memory_block_alignment == compact_alignment); ptrdiff_t offset = (reinterpret_cast(this) - reinterpret_cast(page->compact_page_marker)); assert(offset % compact_alignment == 0 && static_cast(offset) < 256 * compact_alignment); @@ -794,19 +807,19 @@ PUGI__NS_BEGIN unsigned char _flags; }; - PUGI__FN xml_memory_page* compact_get_page(const void* object, int header_offset) + PUGI_IMPL_FN xml_memory_page* compact_get_page(const void* object, int header_offset) { const compact_header* header = reinterpret_cast(static_cast(object) - header_offset); return header->get_page(); } - template PUGI__FN_NO_INLINE T* compact_get_value(const void* object) + template PUGI_IMPL_FN_NO_INLINE T* compact_get_value(const void* object) { return static_cast(compact_get_page(object, header_offset)->allocator->_hash->find(object)); } - template PUGI__FN_NO_INLINE void compact_set_value(const void* object, T* value) + template PUGI_IMPL_FN_NO_INLINE void compact_set_value(const void* object, T* value) { compact_get_page(object, header_offset)->allocator->_hash->insert(object, value); } @@ -904,7 +917,7 @@ PUGI__NS_BEGIN { xml_memory_page* page = compact_get_page(this, header_offset); - if (PUGI__UNLIKELY(page->compact_shared_parent == 0)) + if (PUGI_IMPL_UNLIKELY(page->compact_shared_parent == 0)) page->compact_shared_parent = value; if (page->compact_shared_parent == value) @@ -971,7 +984,7 @@ PUGI__NS_BEGIN { xml_memory_page* page = compact_get_page(this, header_offset); - if (PUGI__UNLIKELY(page->compact_string_base == 0)) + if (PUGI_IMPL_UNLIKELY(page->compact_string_base == 0)) page->compact_string_base = value; ptrdiff_t offset = value - page->compact_string_base; @@ -1043,7 +1056,7 @@ PUGI__NS_BEGIN private: unsigned char _data; }; -PUGI__NS_END +PUGI_IMPL_NS_END #endif #ifdef PUGIXML_COMPACT @@ -1053,7 +1066,7 @@ namespace pugi { xml_attribute_struct(impl::xml_memory_page* page): header(page, 0), namevalue_base(0) { - PUGI__STATIC_ASSERT(sizeof(xml_attribute_struct) == 8); + PUGI_IMPL_STATIC_ASSERT(sizeof(xml_attribute_struct) == 8); } impl::compact_header header; @@ -1071,7 +1084,7 @@ namespace pugi { xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type), namevalue_base(0) { - PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 12); + PUGI_IMPL_STATIC_ASSERT(sizeof(xml_node_struct) == 12); } impl::compact_header header; @@ -1098,7 +1111,7 @@ namespace pugi { xml_attribute_struct(impl::xml_memory_page* page): name(0), value(0), prev_attribute_c(0), next_attribute(0) { - header = PUGI__GETHEADER_IMPL(this, page, 0); + header = PUGI_IMPL_GETHEADER_IMPL(this, page, 0); } uintptr_t header; @@ -1114,7 +1127,7 @@ namespace pugi { xml_node_struct(impl::xml_memory_page* page, xml_node_type type): name(0), value(0), parent(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) { - header = PUGI__GETHEADER_IMPL(this, page, type); + header = PUGI_IMPL_GETHEADER_IMPL(this, page, type); } uintptr_t header; @@ -1134,7 +1147,7 @@ namespace pugi } #endif -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN struct xml_extra_buffer { char_t* buffer; @@ -1160,19 +1173,19 @@ PUGI__NS_BEGIN { assert(object); - return *PUGI__GETPAGE(object)->allocator; + return *PUGI_IMPL_GETPAGE(object)->allocator; } template inline xml_document_struct& get_document(const Object* object) { assert(object); - return *static_cast(PUGI__GETPAGE(object)->allocator); + return *static_cast(PUGI_IMPL_GETPAGE(object)->allocator); } -PUGI__NS_END +PUGI_IMPL_NS_END // Low-level DOM operations -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) { xml_memory_page* page; @@ -1199,7 +1212,7 @@ PUGI__NS_BEGIN if (a->header & impl::xml_memory_page_value_allocated_mask) alloc.deallocate_string(a->value); - alloc.deallocate_memory(a, sizeof(xml_attribute_struct), PUGI__GETPAGE(a)); + alloc.deallocate_memory(a, sizeof(xml_attribute_struct), PUGI_IMPL_GETPAGE(a)); } inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) @@ -1228,7 +1241,7 @@ PUGI__NS_BEGIN child = next; } - alloc.deallocate_memory(n, sizeof(xml_node_struct), PUGI__GETPAGE(n)); + alloc.deallocate_memory(n, sizeof(xml_node_struct), PUGI_IMPL_GETPAGE(n)); } inline void append_node(xml_node_struct* child, xml_node_struct* node) @@ -1276,12 +1289,14 @@ PUGI__NS_BEGIN child->parent = parent; - if (node->next_sibling) - node->next_sibling->prev_sibling_c = child; + xml_node_struct* next = node->next_sibling; + + if (next) + next->prev_sibling_c = child; else parent->first_child->prev_sibling_c = child; - child->next_sibling = node->next_sibling; + child->next_sibling = next; child->prev_sibling_c = node; node->next_sibling = child; @@ -1293,12 +1308,14 @@ PUGI__NS_BEGIN child->parent = parent; - if (node->prev_sibling_c->next_sibling) - node->prev_sibling_c->next_sibling = child; + xml_node_struct* prev = node->prev_sibling_c; + + if (prev->next_sibling) + prev->next_sibling = child; else parent->first_child = child; - child->prev_sibling_c = node->prev_sibling_c; + child->prev_sibling_c = prev; child->next_sibling = node; node->prev_sibling_c = child; @@ -1308,15 +1325,18 @@ PUGI__NS_BEGIN { xml_node_struct* parent = node->parent; - if (node->next_sibling) - node->next_sibling->prev_sibling_c = node->prev_sibling_c; + xml_node_struct* next = node->next_sibling; + xml_node_struct* prev = node->prev_sibling_c; + + if (next) + next->prev_sibling_c = prev; else - parent->first_child->prev_sibling_c = node->prev_sibling_c; + parent->first_child->prev_sibling_c = prev; - if (node->prev_sibling_c->next_sibling) - node->prev_sibling_c->next_sibling = node->next_sibling; + if (prev->next_sibling) + prev->next_sibling = next; else - parent->first_child = node->next_sibling; + parent->first_child = next; node->parent = 0; node->prev_sibling_c = 0; @@ -1360,45 +1380,52 @@ PUGI__NS_BEGIN inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) { - if (place->next_attribute) - place->next_attribute->prev_attribute_c = attr; + xml_attribute_struct* next = place->next_attribute; + + if (next) + next->prev_attribute_c = attr; else node->first_attribute->prev_attribute_c = attr; - attr->next_attribute = place->next_attribute; + attr->next_attribute = next; attr->prev_attribute_c = place; place->next_attribute = attr; } inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) { - if (place->prev_attribute_c->next_attribute) - place->prev_attribute_c->next_attribute = attr; + xml_attribute_struct* prev = place->prev_attribute_c; + + if (prev->next_attribute) + prev->next_attribute = attr; else node->first_attribute = attr; - attr->prev_attribute_c = place->prev_attribute_c; + attr->prev_attribute_c = prev; attr->next_attribute = place; place->prev_attribute_c = attr; } inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node) { - if (attr->next_attribute) - attr->next_attribute->prev_attribute_c = attr->prev_attribute_c; + xml_attribute_struct* next = attr->next_attribute; + xml_attribute_struct* prev = attr->prev_attribute_c; + + if (next) + next->prev_attribute_c = prev; else - node->first_attribute->prev_attribute_c = attr->prev_attribute_c; + node->first_attribute->prev_attribute_c = prev; - if (attr->prev_attribute_c->next_attribute) - attr->prev_attribute_c->next_attribute = attr->next_attribute; + if (prev->next_attribute) + prev->next_attribute = next; else - node->first_attribute = attr->next_attribute; + node->first_attribute = next; attr->prev_attribute_c = 0; attr->next_attribute = 0; } - PUGI__FN_NO_INLINE xml_node_struct* append_new_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) + PUGI_IMPL_FN_NO_INLINE xml_node_struct* append_new_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) { if (!alloc.reserve()) return 0; @@ -1410,7 +1437,7 @@ PUGI__NS_BEGIN return child; } - PUGI__FN_NO_INLINE xml_attribute_struct* append_new_attribute(xml_node_struct* node, xml_allocator& alloc) + PUGI_IMPL_FN_NO_INLINE xml_attribute_struct* append_new_attribute(xml_node_struct* node, xml_allocator& alloc) { if (!alloc.reserve()) return 0; @@ -1421,10 +1448,10 @@ PUGI__NS_BEGIN return attr; } -PUGI__NS_END +PUGI_IMPL_NS_END // Helper classes for code generation -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN struct opt_false { enum { value = 0 }; @@ -1434,10 +1461,10 @@ PUGI__NS_BEGIN { enum { value = 1 }; }; -PUGI__NS_END +PUGI_IMPL_NS_END // Unicode utilities -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN inline uint16_t endian_swap(uint16_t value) { return static_cast(((value & 0xff) << 8) | (value >> 8)); @@ -1819,15 +1846,15 @@ PUGI__NS_BEGIN }; #ifdef PUGIXML_WCHAR_MODE - PUGI__FN void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length) + PUGI_IMPL_FN void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length) { for (size_t i = 0; i < length; ++i) result[i] = static_cast(endian_swap(static_cast::type>(data[i]))); } #endif -PUGI__NS_END +PUGI_IMPL_NS_END -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN enum chartype_t { ct_parse_pcdata = 1, // \0, &, \r, < @@ -1893,24 +1920,24 @@ PUGI__NS_BEGIN }; #ifdef PUGIXML_WCHAR_MODE - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast(c) < 128 ? table[static_cast(c)] : table[128]) & (ct)) + #define PUGI_IMPL_IS_CHARTYPE_IMPL(c, ct, table) ((static_cast(c) < 128 ? table[static_cast(c)] : table[128]) & (ct)) #else - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast(c)] & (ct)) + #define PUGI_IMPL_IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast(c)] & (ct)) #endif - #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table) - #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table) + #define PUGI_IMPL_IS_CHARTYPE(c, ct) PUGI_IMPL_IS_CHARTYPE_IMPL(c, ct, chartype_table) + #define PUGI_IMPL_IS_CHARTYPEX(c, ct) PUGI_IMPL_IS_CHARTYPE_IMPL(c, ct, chartypex_table) - PUGI__FN bool is_little_endian() + PUGI_IMPL_FN bool is_little_endian() { unsigned int ui = 1; return *reinterpret_cast(&ui) == 1; } - PUGI__FN xml_encoding get_wchar_encoding() + PUGI_IMPL_FN xml_encoding get_wchar_encoding() { - PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); + PUGI_IMPL_STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); if (sizeof(wchar_t) == 2) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; @@ -1918,13 +1945,13 @@ PUGI__NS_BEGIN return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; } - PUGI__FN bool parse_declaration_encoding(const uint8_t* data, size_t size, const uint8_t*& out_encoding, size_t& out_length) + PUGI_IMPL_FN bool parse_declaration_encoding(const uint8_t* data, size_t size, const uint8_t*& out_encoding, size_t& out_length) { - #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; } - #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; } + #define PUGI_IMPL_SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; } + #define PUGI_IMPL_SCANCHARTYPE(ct) { while (offset < size && PUGI_IMPL_IS_CHARTYPE(data[offset], ct)) offset++; } // check if we have a non-empty XML declaration - if (size < 6 || !((data[0] == '<') & (data[1] == '?') & (data[2] == 'x') & (data[3] == 'm') & (data[4] == 'l') && PUGI__IS_CHARTYPE(data[5], ct_space))) + if (size < 6 || !((data[0] == '<') & (data[1] == '?') & (data[2] == 'x') & (data[3] == 'm') & (data[4] == 'l') && PUGI_IMPL_IS_CHARTYPE(data[5], ct_space))) return false; // scan XML declaration until the encoding field @@ -1939,28 +1966,28 @@ PUGI__NS_BEGIN size_t offset = i; // encoding follows the version field which can't contain 'en' so this has to be the encoding if XML is well formed - PUGI__SCANCHAR('e'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('c'); PUGI__SCANCHAR('o'); - PUGI__SCANCHAR('d'); PUGI__SCANCHAR('i'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('g'); + PUGI_IMPL_SCANCHAR('e'); PUGI_IMPL_SCANCHAR('n'); PUGI_IMPL_SCANCHAR('c'); PUGI_IMPL_SCANCHAR('o'); + PUGI_IMPL_SCANCHAR('d'); PUGI_IMPL_SCANCHAR('i'); PUGI_IMPL_SCANCHAR('n'); PUGI_IMPL_SCANCHAR('g'); // S? = S? - PUGI__SCANCHARTYPE(ct_space); - PUGI__SCANCHAR('='); - PUGI__SCANCHARTYPE(ct_space); + PUGI_IMPL_SCANCHARTYPE(ct_space); + PUGI_IMPL_SCANCHAR('='); + PUGI_IMPL_SCANCHARTYPE(ct_space); // the only two valid delimiters are ' and " uint8_t delimiter = (offset < size && data[offset] == '"') ? '"' : '\''; - PUGI__SCANCHAR(delimiter); + PUGI_IMPL_SCANCHAR(delimiter); size_t start = offset; out_encoding = data + offset; - PUGI__SCANCHARTYPE(ct_symbol); + PUGI_IMPL_SCANCHARTYPE(ct_symbol); out_length = offset - start; - PUGI__SCANCHAR(delimiter); + PUGI_IMPL_SCANCHAR(delimiter); return true; } @@ -1968,11 +1995,11 @@ PUGI__NS_BEGIN return false; - #undef PUGI__SCANCHAR - #undef PUGI__SCANCHARTYPE + #undef PUGI_IMPL_SCANCHAR + #undef PUGI_IMPL_SCANCHARTYPE } - PUGI__FN xml_encoding guess_buffer_encoding(const uint8_t* data, size_t size) + PUGI_IMPL_FN xml_encoding guess_buffer_encoding(const uint8_t* data, size_t size) { // skip encoding autodetection if input buffer is too small if (size < 4) return encoding_utf8; @@ -2020,7 +2047,7 @@ PUGI__NS_BEGIN return encoding_utf8; } - PUGI__FN xml_encoding get_buffer_encoding(xml_encoding encoding, const void* contents, size_t size) + PUGI_IMPL_FN xml_encoding get_buffer_encoding(xml_encoding encoding, const void* contents, size_t size) { // replace wchar encoding with utf implementation if (encoding == encoding_wchar) return get_wchar_encoding(); @@ -2040,7 +2067,7 @@ PUGI__NS_BEGIN return guess_buffer_encoding(data, size); } - PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + PUGI_IMPL_FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) { size_t length = size / sizeof(char_t); @@ -2069,13 +2096,13 @@ PUGI__NS_BEGIN } #ifdef PUGIXML_WCHAR_MODE - PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re) + PUGI_IMPL_FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re) { return (le == encoding_utf16_be && re == encoding_utf16_le) || (le == encoding_utf16_le && re == encoding_utf16_be) || (le == encoding_utf32_be && re == encoding_utf32_le) || (le == encoding_utf32_le && re == encoding_utf32_be); } - PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + PUGI_IMPL_FN bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) { const char_t* data = static_cast(contents); size_t length = size / sizeof(char_t); @@ -2104,7 +2131,7 @@ PUGI__NS_BEGIN return true; } - template PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) + template PUGI_IMPL_FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) { const typename D::type* data = static_cast(contents); size_t data_length = size / sizeof(typename D::type); @@ -2129,7 +2156,7 @@ PUGI__NS_BEGIN return true; } - PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) + PUGI_IMPL_FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) { // get native encoding xml_encoding wchar_encoding = get_wchar_encoding(); @@ -2174,7 +2201,7 @@ PUGI__NS_BEGIN return false; } #else - template PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) + template PUGI_IMPL_FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) { const typename D::type* data = static_cast(contents); size_t data_length = size / sizeof(typename D::type); @@ -2199,7 +2226,7 @@ PUGI__NS_BEGIN return true; } - PUGI__FN size_t get_latin1_7bit_prefix_length(const uint8_t* data, size_t size) + PUGI_IMPL_FN size_t get_latin1_7bit_prefix_length(const uint8_t* data, size_t size) { for (size_t i = 0; i < size; ++i) if (data[i] > 127) @@ -2208,7 +2235,7 @@ PUGI__NS_BEGIN return size; } - PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + PUGI_IMPL_FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) { const uint8_t* data = static_cast(contents); size_t data_length = size; @@ -2245,7 +2272,7 @@ PUGI__NS_BEGIN return true; } - PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) + PUGI_IMPL_FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) { // fast path: no conversion required if (encoding == encoding_utf8) @@ -2280,13 +2307,13 @@ PUGI__NS_BEGIN } #endif - PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length) + PUGI_IMPL_FN size_t as_utf8_begin(const wchar_t* str, size_t length) { // get length in utf8 characters return wchar_decoder::process(str, length, 0, utf8_counter()); } - PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) + PUGI_IMPL_FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) { // convert to utf8 uint8_t* begin = reinterpret_cast(buffer); @@ -2298,7 +2325,7 @@ PUGI__NS_BEGIN } #ifndef PUGIXML_NO_STL - PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length) + PUGI_IMPL_FN std::string as_utf8_impl(const wchar_t* str, size_t length) { // first pass: get length in utf8 characters size_t size = as_utf8_begin(str, length); @@ -2313,7 +2340,7 @@ PUGI__NS_BEGIN return result; } - PUGI__FN std::basic_string as_wide_impl(const char* str, size_t size) + PUGI_IMPL_FN std::basic_string as_wide_impl(const char* str, size_t size) { const uint8_t* data = reinterpret_cast(str); @@ -2356,12 +2383,14 @@ PUGI__NS_BEGIN } template - PUGI__FN bool strcpy_insitu(String& dest, Header& header, uintptr_t header_mask, const char_t* source, size_t source_length) + PUGI_IMPL_FN bool strcpy_insitu(String& dest, Header& header, uintptr_t header_mask, const char_t* source, size_t source_length) { + assert((header & header_mask) == 0 || dest); // header bit indicates whether dest was previously allocated + if (source_length == 0) { // empty string and null pointer are equivalent, so just deallocate old memory - xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator; + xml_allocator* alloc = PUGI_IMPL_GETPAGE_IMPL(header)->allocator; if (header & header_mask) alloc->deallocate_string(dest); @@ -2381,7 +2410,7 @@ PUGI__NS_BEGIN } else { - xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator; + xml_allocator* alloc = PUGI_IMPL_GETPAGE_IMPL(header)->allocator; if (!alloc->reserve()) return false; @@ -2446,7 +2475,7 @@ PUGI__NS_BEGIN } }; - PUGI__FN char_t* strconv_escape(char_t* s, gap& g) + PUGI_IMPL_FN char_t* strconv_escape(char_t* s, gap& g) { char_t* stre = s + 1; @@ -2587,25 +2616,25 @@ PUGI__NS_BEGIN } // Parser utilities - #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) - #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; } - #define PUGI__OPTSET(OPT) ( optmsk & (OPT) ) - #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); } - #define PUGI__POPNODE() { cursor = cursor->parent; } - #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; } - #define PUGI__SCANWHILE(X) { while (X) ++s; } - #define PUGI__SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI__UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI__UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI__UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI__UNLIKELY(!(X))) { s += 3; break; } s += 4; } } - #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; } - #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(0) - #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); } - - PUGI__FN char_t* strconv_comment(char_t* s, char_t endch) + #define PUGI_IMPL_ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) + #define PUGI_IMPL_SKIPWS() { while (PUGI_IMPL_IS_CHARTYPE(*s, ct_space)) ++s; } + #define PUGI_IMPL_OPTSET(OPT) ( optmsk & (OPT) ) + #define PUGI_IMPL_PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI_IMPL_THROW_ERROR(status_out_of_memory, s); } + #define PUGI_IMPL_POPNODE() { cursor = cursor->parent; } + #define PUGI_IMPL_SCANFOR(X) { while (*s != 0 && !(X)) ++s; } + #define PUGI_IMPL_SCANWHILE(X) { while (X) ++s; } + #define PUGI_IMPL_SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI_IMPL_UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI_IMPL_UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI_IMPL_UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI_IMPL_UNLIKELY(!(X))) { s += 3; break; } s += 4; } } + #define PUGI_IMPL_ENDSEG() { ch = *s; *s = 0; ++s; } + #define PUGI_IMPL_THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(0) + #define PUGI_IMPL_CHECK_ERROR(err, m) { if (*s == 0) PUGI_IMPL_THROW_ERROR(err, m); } + + PUGI_IMPL_FN char_t* strconv_comment(char_t* s, char_t endch) { gap g; while (true) { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment)); + PUGI_IMPL_SCANWHILE_UNROLL(!PUGI_IMPL_IS_CHARTYPE(ss, ct_parse_comment)); if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair { @@ -2613,7 +2642,7 @@ PUGI__NS_BEGIN if (*s == '\n') g.push(s, 1); } - else if (s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')) // comment ends here + else if (s[0] == '-' && s[1] == '-' && PUGI_IMPL_ENDSWITH(s[2], '>')) // comment ends here { *g.flush(s) = 0; @@ -2627,13 +2656,13 @@ PUGI__NS_BEGIN } } - PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch) + PUGI_IMPL_FN char_t* strconv_cdata(char_t* s, char_t endch) { gap g; while (true) { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata)); + PUGI_IMPL_SCANWHILE_UNROLL(!PUGI_IMPL_IS_CHARTYPE(ss, ct_parse_cdata)); if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair { @@ -2641,7 +2670,7 @@ PUGI__NS_BEGIN if (*s == '\n') g.push(s, 1); } - else if (s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')) // CDATA ends here + else if (s[0] == ']' && s[1] == ']' && PUGI_IMPL_ENDSWITH(s[2], '>')) // CDATA ends here { *g.flush(s) = 0; @@ -2667,14 +2696,14 @@ PUGI__NS_BEGIN while (true) { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_pcdata)); + PUGI_IMPL_SCANWHILE_UNROLL(!PUGI_IMPL_IS_CHARTYPE(ss, ct_parse_pcdata)); if (*s == '<') // PCDATA ends here { char_t* end = g.flush(s); if (opt_trim::value) - while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) + while (end > begin && PUGI_IMPL_IS_CHARTYPE(end[-1], ct_space)) --end; *end = 0; @@ -2696,7 +2725,7 @@ PUGI__NS_BEGIN char_t* end = g.flush(s); if (opt_trim::value) - while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) + while (end > begin && PUGI_IMPL_IS_CHARTYPE(end[-1], ct_space)) --end; *end = 0; @@ -2708,9 +2737,9 @@ PUGI__NS_BEGIN } }; - PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) + PUGI_IMPL_FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) { - PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800); + PUGI_IMPL_STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800); switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (trim eol escapes); this simultaneously checks 3 options from assertion above { @@ -2735,37 +2764,37 @@ PUGI__NS_BEGIN gap g; // trim leading whitespaces - if (PUGI__IS_CHARTYPE(*s, ct_space)) + if (PUGI_IMPL_IS_CHARTYPE(*s, ct_space)) { char_t* str = s; do ++str; - while (PUGI__IS_CHARTYPE(*str, ct_space)); + while (PUGI_IMPL_IS_CHARTYPE(*str, ct_space)); g.push(s, str - s); } while (true) { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space)); + PUGI_IMPL_SCANWHILE_UNROLL(!PUGI_IMPL_IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space)); if (*s == end_quote) { char_t* str = g.flush(s); do *str-- = 0; - while (PUGI__IS_CHARTYPE(*str, ct_space)); + while (PUGI_IMPL_IS_CHARTYPE(*str, ct_space)); return s + 1; } - else if (PUGI__IS_CHARTYPE(*s, ct_space)) + else if (PUGI_IMPL_IS_CHARTYPE(*s, ct_space)) { *s++ = ' '; - if (PUGI__IS_CHARTYPE(*s, ct_space)) + if (PUGI_IMPL_IS_CHARTYPE(*s, ct_space)) { char_t* str = s + 1; - while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str; + while (PUGI_IMPL_IS_CHARTYPE(*str, ct_space)) ++str; g.push(s, str - s); } @@ -2788,7 +2817,7 @@ PUGI__NS_BEGIN while (true) { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws)); + PUGI_IMPL_SCANWHILE_UNROLL(!PUGI_IMPL_IS_CHARTYPE(ss, ct_parse_attr_ws)); if (*s == end_quote) { @@ -2796,7 +2825,7 @@ PUGI__NS_BEGIN return s + 1; } - else if (PUGI__IS_CHARTYPE(*s, ct_space)) + else if (PUGI_IMPL_IS_CHARTYPE(*s, ct_space)) { if (*s == '\r') { @@ -2824,7 +2853,7 @@ PUGI__NS_BEGIN while (true) { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); + PUGI_IMPL_SCANWHILE_UNROLL(!PUGI_IMPL_IS_CHARTYPE(ss, ct_parse_attr)); if (*s == end_quote) { @@ -2856,7 +2885,7 @@ PUGI__NS_BEGIN while (true) { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); + PUGI_IMPL_SCANWHILE_UNROLL(!PUGI_IMPL_IS_CHARTYPE(ss, ct_parse_attr)); if (*s == end_quote) { @@ -2877,9 +2906,9 @@ PUGI__NS_BEGIN } }; - PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask) + PUGI_IMPL_FN strconv_attribute_t get_strconv_attribute(unsigned int optmask) { - PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); + PUGI_IMPL_STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); switch ((optmask >> 4) & 15) // get bitmask for flags (wnorm wconv eol escapes); this simultaneously checks 4 options from assertion above { @@ -2935,8 +2964,8 @@ PUGI__NS_BEGIN { // quoted string char_t ch = *s++; - PUGI__SCANFOR(*s == ch); - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + PUGI_IMPL_SCANFOR(*s == ch); + if (!*s) PUGI_IMPL_THROW_ERROR(status_bad_doctype, s); s++; } @@ -2944,20 +2973,20 @@ PUGI__NS_BEGIN { // s += 2; - PUGI__SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + PUGI_IMPL_SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype + if (!*s) PUGI_IMPL_THROW_ERROR(status_bad_doctype, s); s += 2; } else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-') { s += 4; - PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + PUGI_IMPL_SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype + if (!*s) PUGI_IMPL_THROW_ERROR(status_bad_doctype, s); s += 3; } - else PUGI__THROW_ERROR(status_bad_doctype, s); + else PUGI_IMPL_THROW_ERROR(status_bad_doctype, s); return s; } @@ -2990,7 +3019,7 @@ PUGI__NS_BEGIN else s++; } - PUGI__THROW_ERROR(status_bad_doctype, s); + PUGI_IMPL_THROW_ERROR(status_bad_doctype, s); } char_t* parse_doctype_group(char_t* s, char_t endch) @@ -3034,7 +3063,7 @@ PUGI__NS_BEGIN else s++; } - if (depth != 0 || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s); + if (depth != 0 || endch != '>') PUGI_IMPL_THROW_ERROR(status_bad_doctype, s); return s; } @@ -3052,31 +3081,31 @@ PUGI__NS_BEGIN { ++s; - if (PUGI__OPTSET(parse_comments)) + if (PUGI_IMPL_OPTSET(parse_comments)) { - PUGI__PUSHNODE(node_comment); // Append a new node on the tree. + PUGI_IMPL_PUSHNODE(node_comment); // Append a new node on the tree. cursor->value = s; // Save the offset. } - if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments)) + if (PUGI_IMPL_OPTSET(parse_eol) && PUGI_IMPL_OPTSET(parse_comments)) { s = strconv_comment(s, endch); - if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value); + if (!s) PUGI_IMPL_THROW_ERROR(status_bad_comment, cursor->value); } else { // Scan for terminating '-->'. - PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_comment, s); + PUGI_IMPL_SCANFOR(s[0] == '-' && s[1] == '-' && PUGI_IMPL_ENDSWITH(s[2], '>')); + PUGI_IMPL_CHECK_ERROR(status_bad_comment, s); - if (PUGI__OPTSET(parse_comments)) + if (PUGI_IMPL_OPTSET(parse_comments)) *s = 0; // Zero-terminate this segment at the first terminating '-'. s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'. } } - else PUGI__THROW_ERROR(status_bad_comment, s); + else PUGI_IMPL_THROW_ERROR(status_bad_comment, s); } else if (*s == '[') { @@ -3085,22 +3114,22 @@ PUGI__NS_BEGIN { ++s; - if (PUGI__OPTSET(parse_cdata)) + if (PUGI_IMPL_OPTSET(parse_cdata)) { - PUGI__PUSHNODE(node_cdata); // Append a new node on the tree. + PUGI_IMPL_PUSHNODE(node_cdata); // Append a new node on the tree. cursor->value = s; // Save the offset. - if (PUGI__OPTSET(parse_eol)) + if (PUGI_IMPL_OPTSET(parse_eol)) { s = strconv_cdata(s, endch); - if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value); + if (!s) PUGI_IMPL_THROW_ERROR(status_bad_cdata, cursor->value); } else { // Scan for terminating ']]>'. - PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_cdata, s); + PUGI_IMPL_SCANFOR(s[0] == ']' && s[1] == ']' && PUGI_IMPL_ENDSWITH(s[2], '>')); + PUGI_IMPL_CHECK_ERROR(status_bad_cdata, s); *s++ = 0; // Zero-terminate this segment. } @@ -3108,21 +3137,21 @@ PUGI__NS_BEGIN else // Flagged for discard, but we still have to scan for the terminator. { // Scan for terminating ']]>'. - PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_cdata, s); + PUGI_IMPL_SCANFOR(s[0] == ']' && s[1] == ']' && PUGI_IMPL_ENDSWITH(s[2], '>')); + PUGI_IMPL_CHECK_ERROR(status_bad_cdata, s); ++s; } s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'. } - else PUGI__THROW_ERROR(status_bad_cdata, s); + else PUGI_IMPL_THROW_ERROR(status_bad_cdata, s); } - else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && PUGI__ENDSWITH(s[6], 'E')) + else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && PUGI_IMPL_ENDSWITH(s[6], 'E')) { s -= 2; - if (cursor->parent) PUGI__THROW_ERROR(status_bad_doctype, s); + if (cursor->parent) PUGI_IMPL_THROW_ERROR(status_bad_doctype, s); char_t* mark = s + 9; @@ -3132,18 +3161,18 @@ PUGI__NS_BEGIN assert((*s == 0 && endch == '>') || *s == '>'); if (*s) *s++ = 0; - if (PUGI__OPTSET(parse_doctype)) + if (PUGI_IMPL_OPTSET(parse_doctype)) { - while (PUGI__IS_CHARTYPE(*mark, ct_space)) ++mark; + while (PUGI_IMPL_IS_CHARTYPE(*mark, ct_space)) ++mark; - PUGI__PUSHNODE(node_doctype); + PUGI_IMPL_PUSHNODE(node_doctype); cursor->value = mark; } } - else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s); - else if (*s == 0 && endch == '[') PUGI__THROW_ERROR(status_bad_cdata, s); - else PUGI__THROW_ERROR(status_unrecognized_tag, s); + else if (*s == 0 && endch == '-') PUGI_IMPL_THROW_ERROR(status_bad_comment, s); + else if (*s == 0 && endch == '[') PUGI_IMPL_THROW_ERROR(status_bad_cdata, s); + else PUGI_IMPL_THROW_ERROR(status_unrecognized_tag, s); return s; } @@ -3160,50 +3189,50 @@ PUGI__NS_BEGIN // read PI target char_t* target = s; - if (!PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_pi, s); + if (!PUGI_IMPL_IS_CHARTYPE(*s, ct_start_symbol)) PUGI_IMPL_THROW_ERROR(status_bad_pi, s); - PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol)); - PUGI__CHECK_ERROR(status_bad_pi, s); + PUGI_IMPL_SCANWHILE(PUGI_IMPL_IS_CHARTYPE(*s, ct_symbol)); + PUGI_IMPL_CHECK_ERROR(status_bad_pi, s); // determine node type; stricmp / strcasecmp is not portable bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s; - if (declaration ? PUGI__OPTSET(parse_declaration) : PUGI__OPTSET(parse_pi)) + if (declaration ? PUGI_IMPL_OPTSET(parse_declaration) : PUGI_IMPL_OPTSET(parse_pi)) { if (declaration) { // disallow non top-level declarations - if (cursor->parent) PUGI__THROW_ERROR(status_bad_pi, s); + if (cursor->parent) PUGI_IMPL_THROW_ERROR(status_bad_pi, s); - PUGI__PUSHNODE(node_declaration); + PUGI_IMPL_PUSHNODE(node_declaration); } else { - PUGI__PUSHNODE(node_pi); + PUGI_IMPL_PUSHNODE(node_pi); } cursor->name = target; - PUGI__ENDSEG(); + PUGI_IMPL_ENDSEG(); // parse value/attributes if (ch == '?') { // empty node - if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_pi, s); + if (!PUGI_IMPL_ENDSWITH(*s, '>')) PUGI_IMPL_THROW_ERROR(status_bad_pi, s); s += (*s == '>'); - PUGI__POPNODE(); + PUGI_IMPL_POPNODE(); } - else if (PUGI__IS_CHARTYPE(ch, ct_space)) + else if (PUGI_IMPL_IS_CHARTYPE(ch, ct_space)) { - PUGI__SKIPWS(); + PUGI_IMPL_SKIPWS(); // scan for tag end char_t* value = s; - PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); - PUGI__CHECK_ERROR(status_bad_pi, s); + PUGI_IMPL_SCANFOR(s[0] == '?' && PUGI_IMPL_ENDSWITH(s[1], '>')); + PUGI_IMPL_CHECK_ERROR(status_bad_pi, s); if (declaration) { @@ -3218,20 +3247,20 @@ PUGI__NS_BEGIN // store value and step over > cursor->value = value; - PUGI__POPNODE(); + PUGI_IMPL_POPNODE(); - PUGI__ENDSEG(); + PUGI_IMPL_ENDSEG(); s += (*s == '>'); } } - else PUGI__THROW_ERROR(status_bad_pi, s); + else PUGI_IMPL_THROW_ERROR(status_bad_pi, s); } else { // scan for tag end - PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); - PUGI__CHECK_ERROR(status_bad_pi, s); + PUGI_IMPL_SCANFOR(s[0] == '?' && PUGI_IMPL_ENDSWITH(s[1], '>')); + PUGI_IMPL_CHECK_ERROR(status_bad_pi, s); s += (s[1] == '>' ? 2 : 1); } @@ -3250,6 +3279,7 @@ PUGI__NS_BEGIN char_t ch = 0; xml_node_struct* cursor = root; char_t* mark = s; + char_t* merged_pcdata = s; while (*s != 0) { @@ -3258,39 +3288,39 @@ PUGI__NS_BEGIN ++s; LOC_TAG: - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // '<#...' + if (PUGI_IMPL_IS_CHARTYPE(*s, ct_start_symbol)) // '<#...' { - PUGI__PUSHNODE(node_element); // Append a new node to the tree. + PUGI_IMPL_PUSHNODE(node_element); // Append a new node to the tree. cursor->name = s; - PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. - PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. + PUGI_IMPL_SCANWHILE_UNROLL(PUGI_IMPL_IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. + PUGI_IMPL_ENDSEG(); // Save char in 'ch', terminate & step over. if (ch == '>') { // end of tag } - else if (PUGI__IS_CHARTYPE(ch, ct_space)) + else if (PUGI_IMPL_IS_CHARTYPE(ch, ct_space)) { LOC_ATTRIBUTES: while (true) { - PUGI__SKIPWS(); // Eat any whitespace. + PUGI_IMPL_SKIPWS(); // Eat any whitespace. - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #... + if (PUGI_IMPL_IS_CHARTYPE(*s, ct_start_symbol)) // <... #... { xml_attribute_struct* a = append_new_attribute(cursor, *alloc); // Make space for this attribute. - if (!a) PUGI__THROW_ERROR(status_out_of_memory, s); + if (!a) PUGI_IMPL_THROW_ERROR(status_out_of_memory, s); a->name = s; // Save the offset. - PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. - PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. + PUGI_IMPL_SCANWHILE_UNROLL(PUGI_IMPL_IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. + PUGI_IMPL_ENDSEG(); // Save char in 'ch', terminate & step over. - if (PUGI__IS_CHARTYPE(ch, ct_space)) + if (PUGI_IMPL_IS_CHARTYPE(ch, ct_space)) { - PUGI__SKIPWS(); // Eat any whitespace. + PUGI_IMPL_SKIPWS(); // Eat any whitespace. ch = *s; ++s; @@ -3298,7 +3328,7 @@ PUGI__NS_BEGIN if (ch == '=') // '<... #=...' { - PUGI__SKIPWS(); // Eat any whitespace. + PUGI_IMPL_SKIPWS(); // Eat any whitespace. if (*s == '"' || *s == '\'') // '<... #="...' { @@ -3308,16 +3338,16 @@ PUGI__NS_BEGIN s = strconv_attribute(s, ch); - if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value); + if (!s) PUGI_IMPL_THROW_ERROR(status_bad_attribute, a->value); // After this line the loop continues from the start; // Whitespaces, / and > are ok, symbols and EOF are wrong, // everything else will be detected - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_attribute, s); + if (PUGI_IMPL_IS_CHARTYPE(*s, ct_start_symbol)) PUGI_IMPL_THROW_ERROR(status_bad_attribute, s); } - else PUGI__THROW_ERROR(status_bad_attribute, s); + else PUGI_IMPL_THROW_ERROR(status_bad_attribute, s); } - else PUGI__THROW_ERROR(status_bad_attribute, s); + else PUGI_IMPL_THROW_ERROR(status_bad_attribute, s); } else if (*s == '/') { @@ -3325,16 +3355,16 @@ PUGI__NS_BEGIN if (*s == '>') { - PUGI__POPNODE(); + PUGI_IMPL_POPNODE(); s++; break; } else if (*s == 0 && endch == '>') { - PUGI__POPNODE(); + PUGI_IMPL_POPNODE(); break; } - else PUGI__THROW_ERROR(status_bad_start_element, s); + else PUGI_IMPL_THROW_ERROR(status_bad_start_element, s); } else if (*s == '>') { @@ -3346,16 +3376,16 @@ PUGI__NS_BEGIN { break; } - else PUGI__THROW_ERROR(status_bad_start_element, s); + else PUGI_IMPL_THROW_ERROR(status_bad_start_element, s); } // !!! } else if (ch == '/') // '<#.../' { - if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_start_element, s); + if (!PUGI_IMPL_ENDSWITH(*s, '>')) PUGI_IMPL_THROW_ERROR(status_bad_start_element, s); - PUGI__POPNODE(); // Pop. + PUGI_IMPL_POPNODE(); // Pop. s += (*s == '>'); } @@ -3364,9 +3394,9 @@ PUGI__NS_BEGIN // we stepped over null terminator, backtrack & handle closing tag --s; - if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s); + if (endch != '>') PUGI_IMPL_THROW_ERROR(status_bad_start_element, s); } - else PUGI__THROW_ERROR(status_bad_start_element, s); + else PUGI_IMPL_THROW_ERROR(status_bad_start_element, s); } else if (*s == '/') { @@ -3375,30 +3405,30 @@ PUGI__NS_BEGIN mark = s; char_t* name = cursor->name; - if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, mark); + if (!name) PUGI_IMPL_THROW_ERROR(status_end_element_mismatch, mark); - while (PUGI__IS_CHARTYPE(*s, ct_symbol)) + while (PUGI_IMPL_IS_CHARTYPE(*s, ct_symbol)) { - if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, mark); + if (*s++ != *name++) PUGI_IMPL_THROW_ERROR(status_end_element_mismatch, mark); } if (*name) { - if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s); - else PUGI__THROW_ERROR(status_end_element_mismatch, mark); + if (*s == 0 && name[0] == endch && name[1] == 0) PUGI_IMPL_THROW_ERROR(status_bad_end_element, s); + else PUGI_IMPL_THROW_ERROR(status_end_element_mismatch, mark); } - PUGI__POPNODE(); // Pop. + PUGI_IMPL_POPNODE(); // Pop. - PUGI__SKIPWS(); + PUGI_IMPL_SKIPWS(); if (*s == 0) { - if (endch != '>') PUGI__THROW_ERROR(status_bad_end_element, s); + if (endch != '>') PUGI_IMPL_THROW_ERROR(status_bad_end_element, s); } else { - if (*s != '>') PUGI__THROW_ERROR(status_bad_end_element, s); + if (*s != '>') PUGI_IMPL_THROW_ERROR(status_bad_end_element, s); ++s; } } @@ -3408,62 +3438,79 @@ PUGI__NS_BEGIN if (!s) return s; assert(cursor); - if (PUGI__NODETYPE(cursor) == node_declaration) goto LOC_ATTRIBUTES; + if (PUGI_IMPL_NODETYPE(cursor) == node_declaration) goto LOC_ATTRIBUTES; } else if (*s == '!') // 'first_child) continue; } } - if (!PUGI__OPTSET(parse_trim_pcdata)) + if (!PUGI_IMPL_OPTSET(parse_trim_pcdata)) s = mark; - if (cursor->parent || PUGI__OPTSET(parse_fragment)) + if (cursor->parent || PUGI_IMPL_OPTSET(parse_fragment)) { - if (PUGI__OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value) + char_t* parsed_pcdata = s; + + s = strconv_pcdata(s); + + if (PUGI_IMPL_OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value) { - cursor->value = s; // Save the offset. + cursor->value = parsed_pcdata; // Save the offset. } - else + else if (PUGI_IMPL_OPTSET(parse_merge_pcdata) && cursor->first_child && PUGI_IMPL_NODETYPE(cursor->first_child->prev_sibling_c) == node_pcdata) { - PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. + assert(merged_pcdata >= cursor->first_child->prev_sibling_c->value); + + // Catch up to the end of last parsed value; only needed for the first fragment. + merged_pcdata += strlength(merged_pcdata); - cursor->value = s; // Save the offset. + size_t length = strlength(parsed_pcdata); - PUGI__POPNODE(); // Pop since this is a standalone. + // Must use memmove instead of memcpy as this move may overlap + memmove(merged_pcdata, parsed_pcdata, (length + 1) * sizeof(char_t)); + merged_pcdata += length; } + else + { + xml_node_struct* prev_cursor = cursor; + PUGI_IMPL_PUSHNODE(node_pcdata); // Append a new node on the tree. - s = strconv_pcdata(s); + cursor->value = parsed_pcdata; // Save the offset. + merged_pcdata = parsed_pcdata; // Used for parse_merge_pcdata above, cheaper to save unconditionally + + cursor = prev_cursor; // Pop since this is a standalone. + } if (!*s) break; } else { - PUGI__SCANFOR(*s == '<'); // '...<' + PUGI_IMPL_SCANFOR(*s == '<'); // '...<' if (!*s) break; ++s; @@ -3475,7 +3522,7 @@ PUGI__NS_BEGIN } // check that last tag is closed - if (cursor != root) PUGI__THROW_ERROR(status_end_element_mismatch, s); + if (cursor != root) PUGI_IMPL_THROW_ERROR(status_end_element_mismatch, s); return s; } @@ -3497,7 +3544,7 @@ PUGI__NS_BEGIN { while (node) { - if (PUGI__NODETYPE(node) == node_element) return true; + if (PUGI_IMPL_NODETYPE(node) == node_element) return true; node = node->next_sibling; } @@ -3509,7 +3556,7 @@ PUGI__NS_BEGIN { // early-out for empty documents if (length == 0) - return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element); + return make_parse_result(PUGI_IMPL_OPTSET(parse_fragment) ? status_ok : status_no_document_element); // get last child of the root before parsing xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0; @@ -3537,9 +3584,9 @@ PUGI__NS_BEGIN return make_parse_result(status_unrecognized_tag, length - 1); // check if there are any element nodes parsed - xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0; + xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child + 0; - if (!PUGI__OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed)) + if (!PUGI_IMPL_OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed)) return make_parse_result(status_no_document_element, length - 1); } else @@ -3554,7 +3601,7 @@ PUGI__NS_BEGIN }; // Output facilities - PUGI__FN xml_encoding get_write_native_encoding() + PUGI_IMPL_FN xml_encoding get_write_native_encoding() { #ifdef PUGIXML_WCHAR_MODE return get_wchar_encoding(); @@ -3563,7 +3610,7 @@ PUGI__NS_BEGIN #endif } - PUGI__FN xml_encoding get_write_encoding(xml_encoding encoding) + PUGI_IMPL_FN xml_encoding get_write_encoding(xml_encoding encoding) { // replace wchar encoding with utf implementation if (encoding == encoding_wchar) return get_wchar_encoding(); @@ -3581,18 +3628,18 @@ PUGI__NS_BEGIN return encoding_utf8; } - template PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T) + template PUGI_IMPL_FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T) { - PUGI__STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type)); + PUGI_IMPL_STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type)); typename T::value_type end = D::process(reinterpret_cast(data), length, dest, T()); return static_cast(end - dest) * sizeof(*dest); } - template PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T, bool opt_swap) + template PUGI_IMPL_FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T, bool opt_swap) { - PUGI__STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type)); + PUGI_IMPL_STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type)); typename T::value_type end = D::process(reinterpret_cast(data), length, dest, T()); @@ -3606,7 +3653,7 @@ PUGI__NS_BEGIN } #ifdef PUGIXML_WCHAR_MODE - PUGI__FN size_t get_valid_length(const char_t* data, size_t length) + PUGI_IMPL_FN size_t get_valid_length(const char_t* data, size_t length) { if (length < 1) return 0; @@ -3614,7 +3661,7 @@ PUGI__NS_BEGIN return (sizeof(wchar_t) == 2 && static_cast(static_cast(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length; } - PUGI__FN size_t convert_buffer_output(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) + PUGI_IMPL_FN size_t convert_buffer_output(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) { // only endian-swapping is required if (need_endian_swap_utf(encoding, get_wchar_encoding())) @@ -3652,7 +3699,7 @@ PUGI__NS_BEGIN return 0; } #else - PUGI__FN size_t get_valid_length(const char_t* data, size_t length) + PUGI_IMPL_FN size_t get_valid_length(const char_t* data, size_t length) { if (length < 5) return 0; @@ -3668,7 +3715,7 @@ PUGI__NS_BEGIN return length; } - PUGI__FN size_t convert_buffer_output(char_t* /* r_char */, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) + PUGI_IMPL_FN size_t convert_buffer_output(char_t* /* r_char */, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) { if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) { @@ -3700,7 +3747,7 @@ PUGI__NS_BEGIN public: xml_buffered_writer(xml_writer& writer_, xml_encoding user_encoding): writer(writer_), bufsize(0), encoding(get_write_encoding(user_encoding)) { - PUGI__STATIC_ASSERT(bufcapacity >= 8); + PUGI_IMPL_STATIC_ASSERT(bufcapacity >= 8); } size_t flush() @@ -3906,14 +3953,14 @@ PUGI__NS_BEGIN xml_encoding encoding; }; - PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) + PUGI_IMPL_FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) { while (*s) { const char_t* prev = s; // While *s is a usual symbol - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type)); + PUGI_IMPL_SCANWHILE_UNROLL(!PUGI_IMPL_IS_CHARTYPEX(ss, type)); writer.write_buffer(prev, static_cast(s - prev)); @@ -3958,7 +4005,7 @@ PUGI__NS_BEGIN } } - PUGI__FN void text_output(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) + PUGI_IMPL_FN void text_output(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) { if (flags & format_no_escapes) writer.write_string(s); @@ -3966,7 +4013,7 @@ PUGI__NS_BEGIN text_output_escaped(writer, s, type, flags); } - PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s) + PUGI_IMPL_FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s) { do { @@ -3988,7 +4035,7 @@ PUGI__NS_BEGIN while (*s); } - PUGI__FN void text_output_indent(xml_buffered_writer& writer, const char_t* indent, size_t indent_length, unsigned int depth) + PUGI_IMPL_FN void text_output_indent(xml_buffered_writer& writer, const char_t* indent, size_t indent_length, unsigned int depth) { switch (indent_length) { @@ -4028,7 +4075,7 @@ PUGI__NS_BEGIN } } - PUGI__FN void node_output_comment(xml_buffered_writer& writer, const char_t* s) + PUGI_IMPL_FN void node_output_comment(xml_buffered_writer& writer, const char_t* s) { writer.write('<', '!', '-', '-'); @@ -4053,7 +4100,7 @@ PUGI__NS_BEGIN writer.write('-', '-', '>'); } - PUGI__FN void node_output_pi_value(xml_buffered_writer& writer, const char_t* s) + PUGI_IMPL_FN void node_output_pi_value(xml_buffered_writer& writer, const char_t* s) { while (*s) { @@ -4074,7 +4121,7 @@ PUGI__NS_BEGIN } } - PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) + PUGI_IMPL_FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) { const char_t* default_name = PUGIXML_TEXT(":anonymous"); const char_t enquotation_char = (flags & format_attribute_single_quote) ? '\'' : '"'; @@ -4102,7 +4149,7 @@ PUGI__NS_BEGIN } } - PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) + PUGI_IMPL_FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) { const char_t* default_name = PUGIXML_TEXT(":anonymous"); const char_t* name = node->name ? node->name + 0 : default_name; @@ -4164,7 +4211,7 @@ PUGI__NS_BEGIN } } - PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node) + PUGI_IMPL_FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node) { const char_t* default_name = PUGIXML_TEXT(":anonymous"); const char_t* name = node->name ? node->name + 0 : default_name; @@ -4174,11 +4221,11 @@ PUGI__NS_BEGIN writer.write('>'); } - PUGI__FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + PUGI_IMPL_FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) { const char_t* default_name = PUGIXML_TEXT(":anonymous"); - switch (PUGI__NODETYPE(node)) + switch (PUGI_IMPL_NODETYPE(node)) { case node_pcdata: text_output(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""), ctx_special_pcdata, flags); @@ -4236,7 +4283,7 @@ PUGI__NS_BEGIN indent_indent = 2 }; - PUGI__FN void node_output(xml_buffered_writer& writer, xml_node_struct* root, const char_t* indent, unsigned int flags, unsigned int depth) + PUGI_IMPL_FN void node_output(xml_buffered_writer& writer, xml_node_struct* root, const char_t* indent, unsigned int flags, unsigned int depth) { size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ? strlength(indent) : 0; unsigned int indent_flags = indent_indent; @@ -4248,7 +4295,7 @@ PUGI__NS_BEGIN assert(node); // begin writing current node - if (PUGI__NODETYPE(node) == node_pcdata || PUGI__NODETYPE(node) == node_cdata) + if (PUGI_IMPL_NODETYPE(node) == node_pcdata || PUGI_IMPL_NODETYPE(node) == node_cdata) { node_output_simple(writer, node, flags); @@ -4262,7 +4309,7 @@ PUGI__NS_BEGIN if ((indent_flags & indent_indent) && indent_length) text_output_indent(writer, indent, indent_length, depth); - if (PUGI__NODETYPE(node) == node_element) + if (PUGI_IMPL_NODETYPE(node) == node_element) { indent_flags = indent_newline | indent_indent; @@ -4277,7 +4324,7 @@ PUGI__NS_BEGIN continue; } } - else if (PUGI__NODETYPE(node) == node_document) + else if (PUGI_IMPL_NODETYPE(node) == node_document) { indent_flags = indent_indent; @@ -4307,7 +4354,7 @@ PUGI__NS_BEGIN node = node->parent; // write closing node - if (PUGI__NODETYPE(node) == node_element) + if (PUGI_IMPL_NODETYPE(node) == node_element) { depth--; @@ -4329,11 +4376,11 @@ PUGI__NS_BEGIN writer.write('\n'); } - PUGI__FN bool has_declaration(xml_node_struct* node) + PUGI_IMPL_FN bool has_declaration(xml_node_struct* node) { for (xml_node_struct* child = node->first_child; child; child = child->next_sibling) { - xml_node_type type = PUGI__NODETYPE(child); + xml_node_type type = PUGI_IMPL_NODETYPE(child); if (type == node_declaration) return true; if (type == node_element) return false; @@ -4342,7 +4389,7 @@ PUGI__NS_BEGIN return false; } - PUGI__FN bool is_attribute_of(xml_attribute_struct* attr, xml_node_struct* node) + PUGI_IMPL_FN bool is_attribute_of(xml_attribute_struct* attr, xml_node_struct* node) { for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) if (a == attr) @@ -4351,12 +4398,12 @@ PUGI__NS_BEGIN return false; } - PUGI__FN bool allow_insert_attribute(xml_node_type parent) + PUGI_IMPL_FN bool allow_insert_attribute(xml_node_type parent) { return parent == node_element || parent == node_declaration; } - PUGI__FN bool allow_insert_child(xml_node_type parent, xml_node_type child) + PUGI_IMPL_FN bool allow_insert_child(xml_node_type parent, xml_node_type child) { if (parent != node_document && parent != node_element) return false; if (child == node_document || child == node_null) return false; @@ -4365,7 +4412,7 @@ PUGI__NS_BEGIN return true; } - PUGI__FN bool allow_move(xml_node parent, xml_node child) + PUGI_IMPL_FN bool allow_move(xml_node parent, xml_node child) { // check that child can be a child of parent if (!allow_insert_child(parent.type(), child.type())) @@ -4390,9 +4437,9 @@ PUGI__NS_BEGIN } template - PUGI__FN void node_copy_string(String& dest, Header& header, uintptr_t header_mask, char_t* source, Header& source_header, xml_allocator* alloc) + PUGI_IMPL_FN void node_copy_string(String& dest, Header& header, uintptr_t header_mask, char_t* source, Header& source_header, xml_allocator* alloc) { - assert(!dest && (header & header_mask) == 0); + assert(!dest && (header & header_mask) == 0); // copies are performed into fresh nodes if (source) { @@ -4409,7 +4456,7 @@ PUGI__NS_BEGIN } } - PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc) + PUGI_IMPL_FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc) { node_copy_string(dn->name, dn->header, xml_memory_page_name_allocated_mask, sn->name, sn->header, shared_alloc); node_copy_string(dn->value, dn->header, xml_memory_page_value_allocated_mask, sn->value, sn->header, shared_alloc); @@ -4426,7 +4473,7 @@ PUGI__NS_BEGIN } } - PUGI__FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn) + PUGI_IMPL_FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn) { xml_allocator& alloc = get_allocator(dn); xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : 0; @@ -4444,7 +4491,7 @@ PUGI__NS_BEGIN // when a tree is copied into one of the descendants, we need to skip that subtree to avoid an infinite loop if (sit != dn) { - xml_node_struct* copy = append_new_node(dit, alloc, PUGI__NODETYPE(sit)); + xml_node_struct* copy = append_new_node(dit, alloc, PUGI_IMPL_NODETYPE(sit)); if (copy) { @@ -4480,7 +4527,7 @@ PUGI__NS_BEGIN assert(!sit || dit == dn->parent); } - PUGI__FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa) + PUGI_IMPL_FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa) { xml_allocator& alloc = get_allocator(da); xml_allocator* shared_alloc = (&alloc == &get_allocator(sa)) ? &alloc : 0; @@ -4491,18 +4538,18 @@ PUGI__NS_BEGIN inline bool is_text_node(xml_node_struct* node) { - xml_node_type type = PUGI__NODETYPE(node); + xml_node_type type = PUGI_IMPL_NODETYPE(node); return type == node_pcdata || type == node_cdata; } // get value with conversion functions - template PUGI__FN PUGI__UNSIGNED_OVERFLOW U string_to_integer(const char_t* value, U minv, U maxv) + template PUGI_IMPL_FN PUGI_IMPL_UNSIGNED_OVERFLOW U string_to_integer(const char_t* value, U minv, U maxv) { U result = 0; const char_t* s = value; - while (PUGI__IS_CHARTYPE(*s, ct_space)) + while (PUGI_IMPL_IS_CHARTYPE(*s, ct_space)) s++; bool negative = (*s == '-'); @@ -4557,7 +4604,7 @@ PUGI__NS_BEGIN size_t digits = static_cast(s - start); - PUGI__STATIC_ASSERT(sizeof(U) == 8 || sizeof(U) == 4 || sizeof(U) == 2); + PUGI_IMPL_STATIC_ASSERT(sizeof(U) == 8 || sizeof(U) == 4 || sizeof(U) == 2); const size_t max_digits10 = sizeof(U) == 8 ? 20 : sizeof(U) == 4 ? 10 : 5; const char_t max_lead = sizeof(U) == 8 ? '1' : sizeof(U) == 4 ? '4' : '6'; @@ -4579,17 +4626,17 @@ PUGI__NS_BEGIN return (overflow || result > maxv) ? maxv : result; } - PUGI__FN int get_value_int(const char_t* value) + PUGI_IMPL_FN int get_value_int(const char_t* value) { return string_to_integer(value, static_cast(INT_MIN), INT_MAX); } - PUGI__FN unsigned int get_value_uint(const char_t* value) + PUGI_IMPL_FN unsigned int get_value_uint(const char_t* value) { return string_to_integer(value, 0, UINT_MAX); } - PUGI__FN double get_value_double(const char_t* value) + PUGI_IMPL_FN double get_value_double(const char_t* value) { #ifdef PUGIXML_WCHAR_MODE return wcstod(value, 0); @@ -4598,7 +4645,7 @@ PUGI__NS_BEGIN #endif } - PUGI__FN float get_value_float(const char_t* value) + PUGI_IMPL_FN float get_value_float(const char_t* value) { #ifdef PUGIXML_WCHAR_MODE return static_cast(wcstod(value, 0)); @@ -4607,7 +4654,7 @@ PUGI__NS_BEGIN #endif } - PUGI__FN bool get_value_bool(const char_t* value) + PUGI_IMPL_FN bool get_value_bool(const char_t* value) { // only look at first char char_t first = *value; @@ -4617,18 +4664,18 @@ PUGI__NS_BEGIN } #ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long get_value_llong(const char_t* value) + PUGI_IMPL_FN long long get_value_llong(const char_t* value) { return string_to_integer(value, static_cast(LLONG_MIN), LLONG_MAX); } - PUGI__FN unsigned long long get_value_ullong(const char_t* value) + PUGI_IMPL_FN unsigned long long get_value_ullong(const char_t* value) { return string_to_integer(value, 0, ULLONG_MAX); } #endif - template PUGI__FN PUGI__UNSIGNED_OVERFLOW char_t* integer_to_string(char_t* begin, char_t* end, U value, bool negative) + template PUGI_IMPL_FN PUGI_IMPL_UNSIGNED_OVERFLOW char_t* integer_to_string(char_t* begin, char_t* end, U value, bool negative) { char_t* result = end - 1; U rest = negative ? 0 - value : value; @@ -4650,7 +4697,7 @@ PUGI__NS_BEGIN // set value with conversion functions template - PUGI__FN bool set_value_ascii(String& dest, Header& header, uintptr_t header_mask, char* buf) + PUGI_IMPL_FN bool set_value_ascii(String& dest, Header& header, uintptr_t header_mask, char* buf) { #ifdef PUGIXML_WCHAR_MODE char_t wbuf[128]; @@ -4666,7 +4713,7 @@ PUGI__NS_BEGIN } template - PUGI__FN bool set_value_integer(String& dest, Header& header, uintptr_t header_mask, U value, bool negative) + PUGI_IMPL_FN bool set_value_integer(String& dest, Header& header, uintptr_t header_mask, U value, bool negative) { char_t buf[64]; char_t* end = buf + sizeof(buf) / sizeof(buf[0]); @@ -4676,30 +4723,30 @@ PUGI__NS_BEGIN } template - PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, float value, int precision) + PUGI_IMPL_FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, float value, int precision) { char buf[128]; - PUGI__SNPRINTF(buf, "%.*g", precision, double(value)); + PUGI_IMPL_SNPRINTF(buf, "%.*g", precision, double(value)); return set_value_ascii(dest, header, header_mask, buf); } template - PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, double value, int precision) + PUGI_IMPL_FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, double value, int precision) { char buf[128]; - PUGI__SNPRINTF(buf, "%.*g", precision, value); + PUGI_IMPL_SNPRINTF(buf, "%.*g", precision, value); return set_value_ascii(dest, header, header_mask, buf); } template - PUGI__FN bool set_value_bool(String& dest, Header& header, uintptr_t header_mask, bool value) + PUGI_IMPL_FN bool set_value_bool(String& dest, Header& header, uintptr_t header_mask, bool value) { return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"), value ? 4 : 5); } - PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer) + PUGI_IMPL_FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer) { // check input buffer if (!contents && size) return make_parse_result(status_io_error); @@ -4707,6 +4754,9 @@ PUGI__NS_BEGIN // get actual encoding xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size); + // if convert_buffer below throws bad_alloc, we still need to deallocate contents if we own it + auto_deleter contents_guard(own ? contents : 0, xml_memory::deallocate); + // get private buffer char_t* buffer = 0; size_t length = 0; @@ -4714,6 +4764,9 @@ PUGI__NS_BEGIN // coverity[var_deref_model] if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); + // after this we either deallocate contents (below) or hold on to it via doc->buffer, so we don't need to guard it + contents_guard.release(); + // delete original buffer if we performed a conversion if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents); @@ -4733,9 +4786,19 @@ PUGI__NS_BEGIN } // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick - PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) + PUGI_IMPL_FN xml_parse_status get_file_size(FILE* file, size_t& out_result) { - #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 + #if defined(__linux__) || defined(__APPLE__) + // this simultaneously retrieves the file size and file mode (to guard against loading non-files) + struct stat st; + if (fstat(fileno(file), &st) != 0) return status_io_error; + + // anything that's not a regular file doesn't have a coherent length + if (!S_ISREG(st.st_mode)) return status_io_error; + + typedef off_t length_type; + length_type length = st.st_size; + #elif defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 // there are 64-bit versions of fseek/ftell, let's use them typedef __int64 length_type; @@ -4773,7 +4836,7 @@ PUGI__NS_BEGIN } // This function assumes that buffer has extra sizeof(char_t) writable bytes after size - PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding) + PUGI_IMPL_FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding) { // We only need to zero-terminate if encoding conversion does not do it for us #ifdef PUGIXML_WCHAR_MODE @@ -4797,7 +4860,7 @@ PUGI__NS_BEGIN return size; } - PUGI__FN xml_parse_result load_file_impl(xml_document_struct* doc, FILE* file, unsigned int options, xml_encoding encoding, char_t** out_buffer) + PUGI_IMPL_FN xml_parse_result load_file_impl(xml_document_struct* doc, FILE* file, unsigned int options, xml_encoding encoding, char_t** out_buffer) { if (!file) return make_parse_result(status_file_not_found); @@ -4826,7 +4889,7 @@ PUGI__NS_BEGIN return load_buffer_impl(doc, doc, contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding, true, true, out_buffer); } - PUGI__FN void close_file(FILE* file) + PUGI_IMPL_FN void close_file(FILE* file) { fclose(file); } @@ -4865,7 +4928,7 @@ PUGI__NS_BEGIN T data[xml_memory_page_size / sizeof(T)]; }; - template PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream& stream, void** out_buffer, size_t* out_size) + template PUGI_IMPL_FN xml_parse_status load_stream_data_noseek(std::basic_istream& stream, void** out_buffer, size_t* out_size) { auto_deleter > chunks(0, xml_stream_chunk::destroy); @@ -4919,7 +4982,7 @@ PUGI__NS_BEGIN return status_ok; } - template PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream& stream, void** out_buffer, size_t* out_size) + template PUGI_IMPL_FN xml_parse_status load_stream_data_seek(std::basic_istream& stream, void** out_buffer, size_t* out_size) { // get length of remaining data in stream typename std::basic_istream::pos_type pos = stream.tellg(); @@ -4955,7 +5018,7 @@ PUGI__NS_BEGIN return status_ok; } - template PUGI__FN xml_parse_result load_stream_impl(xml_document_struct* doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding, char_t** out_buffer) + template PUGI_IMPL_FN xml_parse_result load_stream_impl(xml_document_struct* doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding, char_t** out_buffer) { void* buffer = 0; size_t size = 0; @@ -4981,10 +5044,10 @@ PUGI__NS_BEGIN } #endif -#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) - PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) +#if defined(PUGI_IMPL_MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) + PUGI_IMPL_FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) { -#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 +#if defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 FILE* file = 0; return _wfopen_s(&file, path, mode) == 0 ? file : 0; #else @@ -4992,7 +5055,7 @@ PUGI__NS_BEGIN #endif } #else - PUGI__FN char* convert_path_heap(const wchar_t* str) + PUGI_IMPL_FN char* convert_path_heap(const wchar_t* str) { assert(str); @@ -5013,7 +5076,7 @@ PUGI__NS_BEGIN return result; } - PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) + PUGI_IMPL_FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) { // there is no standard function to open wide paths, so our best bet is to try utf8 path char* path_utf8 = convert_path_heap(path); @@ -5033,9 +5096,9 @@ PUGI__NS_BEGIN } #endif - PUGI__FN FILE* open_file(const char* path, const char* mode) + PUGI_IMPL_FN FILE* open_file(const char* path, const char* mode) { -#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 +#if defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 FILE* file = 0; return fopen_s(&file, path, mode) == 0 ? file : 0; #else @@ -5043,14 +5106,14 @@ PUGI__NS_BEGIN #endif } - PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) + PUGI_IMPL_FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) { if (!file) return false; xml_writer_file writer(file); doc.save(writer, indent, flags, encoding); - return ferror(file) == 0; + return fflush(file) == 0 && ferror(file) == 0; } struct name_null_sentry @@ -5068,30 +5131,34 @@ PUGI__NS_BEGIN node->name = name; } }; -PUGI__NS_END +PUGI_IMPL_NS_END namespace pugi { - PUGI__FN xml_writer_file::xml_writer_file(void* file_): file(file_) + PUGI_IMPL_FN xml_writer::~xml_writer() { } - PUGI__FN void xml_writer_file::write(const void* data, size_t size) + PUGI_IMPL_FN xml_writer_file::xml_writer_file(void* file_): file(file_) + { + } + + PUGI_IMPL_FN void xml_writer_file::write(const void* data, size_t size) { size_t result = fwrite(data, 1, size, static_cast(file)); (void)!result; // unfortunately we can't do proper error handling here } #ifndef PUGIXML_NO_STL - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) + PUGI_IMPL_FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) { } - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) + PUGI_IMPL_FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) { } - PUGI__FN void xml_writer_stream::write(const void* data, size_t size) + PUGI_IMPL_FN void xml_writer_stream::write(const void* data, size_t size) { if (narrow_stream) { @@ -5108,291 +5175,328 @@ namespace pugi } #endif - PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0) + PUGI_IMPL_FN xml_tree_walker::xml_tree_walker(): _depth(0) { } - PUGI__FN xml_tree_walker::~xml_tree_walker() + PUGI_IMPL_FN xml_tree_walker::~xml_tree_walker() { } - PUGI__FN int xml_tree_walker::depth() const + PUGI_IMPL_FN int xml_tree_walker::depth() const { return _depth; } - PUGI__FN bool xml_tree_walker::begin(xml_node&) + PUGI_IMPL_FN bool xml_tree_walker::begin(xml_node&) { return true; } - PUGI__FN bool xml_tree_walker::end(xml_node&) + PUGI_IMPL_FN bool xml_tree_walker::end(xml_node&) { return true; } - PUGI__FN xml_attribute::xml_attribute(): _attr(0) + PUGI_IMPL_FN xml_attribute::xml_attribute(): _attr(0) { } - PUGI__FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr) + PUGI_IMPL_FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr) { } - PUGI__FN static void unspecified_bool_xml_attribute(xml_attribute***) + PUGI_IMPL_FN static void unspecified_bool_xml_attribute(xml_attribute***) { } - PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type() const + PUGI_IMPL_FN xml_attribute::operator xml_attribute::unspecified_bool_type() const { return _attr ? unspecified_bool_xml_attribute : 0; } - PUGI__FN bool xml_attribute::operator!() const + PUGI_IMPL_FN bool xml_attribute::operator!() const { return !_attr; } - PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const + PUGI_IMPL_FN bool xml_attribute::operator==(const xml_attribute& r) const { return (_attr == r._attr); } - PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const + PUGI_IMPL_FN bool xml_attribute::operator!=(const xml_attribute& r) const { return (_attr != r._attr); } - PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const + PUGI_IMPL_FN bool xml_attribute::operator<(const xml_attribute& r) const { return (_attr < r._attr); } - PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const + PUGI_IMPL_FN bool xml_attribute::operator>(const xml_attribute& r) const { return (_attr > r._attr); } - PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const + PUGI_IMPL_FN bool xml_attribute::operator<=(const xml_attribute& r) const { return (_attr <= r._attr); } - PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const + PUGI_IMPL_FN bool xml_attribute::operator>=(const xml_attribute& r) const { return (_attr >= r._attr); } - PUGI__FN xml_attribute xml_attribute::next_attribute() const + PUGI_IMPL_FN xml_attribute xml_attribute::next_attribute() const { - return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); + if (!_attr) return xml_attribute(); + return xml_attribute(_attr->next_attribute); } - PUGI__FN xml_attribute xml_attribute::previous_attribute() const + PUGI_IMPL_FN xml_attribute xml_attribute::previous_attribute() const { - return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); + if (!_attr) return xml_attribute(); + xml_attribute_struct* prev = _attr->prev_attribute_c; + return prev->next_attribute ? xml_attribute(prev) : xml_attribute(); } - PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const + PUGI_IMPL_FN const char_t* xml_attribute::as_string(const char_t* def) const { - return (_attr && _attr->value) ? _attr->value + 0 : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? value : def; } - PUGI__FN int xml_attribute::as_int(int def) const + PUGI_IMPL_FN int xml_attribute::as_int(int def) const { - return (_attr && _attr->value) ? impl::get_value_int(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_int(value) : def; } - PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const + PUGI_IMPL_FN unsigned int xml_attribute::as_uint(unsigned int def) const { - return (_attr && _attr->value) ? impl::get_value_uint(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_uint(value) : def; } - PUGI__FN double xml_attribute::as_double(double def) const + PUGI_IMPL_FN double xml_attribute::as_double(double def) const { - return (_attr && _attr->value) ? impl::get_value_double(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_double(value) : def; } - PUGI__FN float xml_attribute::as_float(float def) const + PUGI_IMPL_FN float xml_attribute::as_float(float def) const { - return (_attr && _attr->value) ? impl::get_value_float(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_float(value) : def; } - PUGI__FN bool xml_attribute::as_bool(bool def) const + PUGI_IMPL_FN bool xml_attribute::as_bool(bool def) const { - return (_attr && _attr->value) ? impl::get_value_bool(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_bool(value) : def; } #ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long xml_attribute::as_llong(long long def) const + PUGI_IMPL_FN long long xml_attribute::as_llong(long long def) const { - return (_attr && _attr->value) ? impl::get_value_llong(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_llong(value) : def; } - PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const + PUGI_IMPL_FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const { - return (_attr && _attr->value) ? impl::get_value_ullong(_attr->value) : def; + if (!_attr) return def; + const char_t* value = _attr->value; + return value ? impl::get_value_ullong(value) : def; } #endif - PUGI__FN bool xml_attribute::empty() const + PUGI_IMPL_FN bool xml_attribute::empty() const { return !_attr; } - PUGI__FN const char_t* xml_attribute::name() const + PUGI_IMPL_FN const char_t* xml_attribute::name() const { - return (_attr && _attr->name) ? _attr->name + 0 : PUGIXML_TEXT(""); + if (!_attr) return PUGIXML_TEXT(""); + const char_t* name = _attr->name; + return name ? name : PUGIXML_TEXT(""); } - PUGI__FN const char_t* xml_attribute::value() const + PUGI_IMPL_FN const char_t* xml_attribute::value() const { - return (_attr && _attr->value) ? _attr->value + 0 : PUGIXML_TEXT(""); + if (!_attr) return PUGIXML_TEXT(""); + const char_t* value = _attr->value; + return value ? value : PUGIXML_TEXT(""); } - PUGI__FN size_t xml_attribute::hash_value() const + PUGI_IMPL_FN size_t xml_attribute::hash_value() const { return static_cast(reinterpret_cast(_attr) / sizeof(xml_attribute_struct)); } - PUGI__FN xml_attribute_struct* xml_attribute::internal_object() const + PUGI_IMPL_FN xml_attribute_struct* xml_attribute::internal_object() const { return _attr; } - PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(const char_t* rhs) { set_value(rhs); return *this; } - PUGI__FN xml_attribute& xml_attribute::operator=(int rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(int rhs) { set_value(rhs); return *this; } - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned int rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(unsigned int rhs) { set_value(rhs); return *this; } - PUGI__FN xml_attribute& xml_attribute::operator=(long rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(long rhs) { set_value(rhs); return *this; } - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(unsigned long rhs) { set_value(rhs); return *this; } - PUGI__FN xml_attribute& xml_attribute::operator=(double rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(double rhs) { set_value(rhs); return *this; } - PUGI__FN xml_attribute& xml_attribute::operator=(float rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(float rhs) { set_value(rhs); return *this; } - PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(bool rhs) { set_value(rhs); return *this; } #ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(long long rhs) { set_value(rhs); return *this; } - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long long rhs) + PUGI_IMPL_FN xml_attribute& xml_attribute::operator=(unsigned long long rhs) { set_value(rhs); return *this; } #endif - PUGI__FN bool xml_attribute::set_name(const char_t* rhs) + PUGI_IMPL_FN bool xml_attribute::set_name(const char_t* rhs) { if (!_attr) return false; return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); } - PUGI__FN bool xml_attribute::set_value(const char_t* rhs) + PUGI_IMPL_FN bool xml_attribute::set_name(const char_t* rhs, size_t size) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, size); + } + + PUGI_IMPL_FN bool xml_attribute::set_value(const char_t* rhs) { if (!_attr) return false; return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); } - PUGI__FN bool xml_attribute::set_value(int rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(const char_t* rhs, size_t size) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, size); + } + + PUGI_IMPL_FN bool xml_attribute::set_value(int rhs) { if (!_attr) return false; return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); } - PUGI__FN bool xml_attribute::set_value(unsigned int rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(unsigned int rhs) { if (!_attr) return false; return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false); } - PUGI__FN bool xml_attribute::set_value(long rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(long rhs) { if (!_attr) return false; return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); } - PUGI__FN bool xml_attribute::set_value(unsigned long rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(unsigned long rhs) { if (!_attr) return false; return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false); } - PUGI__FN bool xml_attribute::set_value(double rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(double rhs) { if (!_attr) return false; return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, default_double_precision); } - PUGI__FN bool xml_attribute::set_value(double rhs, int precision) + PUGI_IMPL_FN bool xml_attribute::set_value(double rhs, int precision) { if (!_attr) return false; return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, precision); } - PUGI__FN bool xml_attribute::set_value(float rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(float rhs) { if (!_attr) return false; return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, default_float_precision); } - PUGI__FN bool xml_attribute::set_value(float rhs, int precision) + PUGI_IMPL_FN bool xml_attribute::set_value(float rhs, int precision) { if (!_attr) return false; return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, precision); } - PUGI__FN bool xml_attribute::set_value(bool rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(bool rhs) { if (!_attr) return false; @@ -5400,14 +5504,14 @@ namespace pugi } #ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN bool xml_attribute::set_value(long long rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(long long rhs) { if (!_attr) return false; return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); } - PUGI__FN bool xml_attribute::set_value(unsigned long long rhs) + PUGI_IMPL_FN bool xml_attribute::set_value(unsigned long long rhs) { if (!_attr) return false; @@ -5416,171 +5520,190 @@ namespace pugi #endif #ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs) + PUGI_IMPL_FN bool operator&&(const xml_attribute& lhs, bool rhs) { return (bool)lhs && rhs; } - PUGI__FN bool operator||(const xml_attribute& lhs, bool rhs) + PUGI_IMPL_FN bool operator||(const xml_attribute& lhs, bool rhs) { return (bool)lhs || rhs; } #endif - PUGI__FN xml_node::xml_node(): _root(0) + PUGI_IMPL_FN xml_node::xml_node(): _root(0) { } - PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p) + PUGI_IMPL_FN xml_node::xml_node(xml_node_struct* p): _root(p) { } - PUGI__FN static void unspecified_bool_xml_node(xml_node***) + PUGI_IMPL_FN static void unspecified_bool_xml_node(xml_node***) { } - PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const + PUGI_IMPL_FN xml_node::operator xml_node::unspecified_bool_type() const { return _root ? unspecified_bool_xml_node : 0; } - PUGI__FN bool xml_node::operator!() const + PUGI_IMPL_FN bool xml_node::operator!() const { return !_root; } - PUGI__FN xml_node::iterator xml_node::begin() const + PUGI_IMPL_FN xml_node::iterator xml_node::begin() const { return iterator(_root ? _root->first_child + 0 : 0, _root); } - PUGI__FN xml_node::iterator xml_node::end() const + PUGI_IMPL_FN xml_node::iterator xml_node::end() const { return iterator(0, _root); } - PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const + PUGI_IMPL_FN xml_node::attribute_iterator xml_node::attributes_begin() const { return attribute_iterator(_root ? _root->first_attribute + 0 : 0, _root); } - PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const + PUGI_IMPL_FN xml_node::attribute_iterator xml_node::attributes_end() const { return attribute_iterator(0, _root); } - PUGI__FN xml_object_range xml_node::children() const + PUGI_IMPL_FN xml_object_range xml_node::children() const { return xml_object_range(begin(), end()); } - PUGI__FN xml_object_range xml_node::children(const char_t* name_) const + PUGI_IMPL_FN xml_object_range xml_node::children(const char_t* name_) const { return xml_object_range(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_)); } - PUGI__FN xml_object_range xml_node::attributes() const + PUGI_IMPL_FN xml_object_range xml_node::attributes() const { return xml_object_range(attributes_begin(), attributes_end()); } - PUGI__FN bool xml_node::operator==(const xml_node& r) const + PUGI_IMPL_FN bool xml_node::operator==(const xml_node& r) const { return (_root == r._root); } - PUGI__FN bool xml_node::operator!=(const xml_node& r) const + PUGI_IMPL_FN bool xml_node::operator!=(const xml_node& r) const { return (_root != r._root); } - PUGI__FN bool xml_node::operator<(const xml_node& r) const + PUGI_IMPL_FN bool xml_node::operator<(const xml_node& r) const { return (_root < r._root); } - PUGI__FN bool xml_node::operator>(const xml_node& r) const + PUGI_IMPL_FN bool xml_node::operator>(const xml_node& r) const { return (_root > r._root); } - PUGI__FN bool xml_node::operator<=(const xml_node& r) const + PUGI_IMPL_FN bool xml_node::operator<=(const xml_node& r) const { return (_root <= r._root); } - PUGI__FN bool xml_node::operator>=(const xml_node& r) const + PUGI_IMPL_FN bool xml_node::operator>=(const xml_node& r) const { return (_root >= r._root); } - PUGI__FN bool xml_node::empty() const + PUGI_IMPL_FN bool xml_node::empty() const { return !_root; } - PUGI__FN const char_t* xml_node::name() const + PUGI_IMPL_FN const char_t* xml_node::name() const { - return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT(""); + if (!_root) return PUGIXML_TEXT(""); + const char_t* name = _root->name; + return name ? name : PUGIXML_TEXT(""); } - PUGI__FN xml_node_type xml_node::type() const + PUGI_IMPL_FN xml_node_type xml_node::type() const { - return _root ? PUGI__NODETYPE(_root) : node_null; + return _root ? PUGI_IMPL_NODETYPE(_root) : node_null; } - PUGI__FN const char_t* xml_node::value() const + PUGI_IMPL_FN const char_t* xml_node::value() const { - return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT(""); + if (!_root) return PUGIXML_TEXT(""); + const char_t* value = _root->value; + return value ? value : PUGIXML_TEXT(""); } - PUGI__FN xml_node xml_node::child(const char_t* name_) const + PUGI_IMPL_FN xml_node xml_node::child(const char_t* name_) const { if (!_root) return xml_node(); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) + return xml_node(i); + } return xml_node(); } - PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const + PUGI_IMPL_FN xml_attribute xml_node::attribute(const char_t* name_) const { if (!_root) return xml_attribute(); for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) - if (i->name && impl::strequal(name_, i->name)) + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) return xml_attribute(i); + } return xml_attribute(); } - PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const + PUGI_IMPL_FN xml_node xml_node::next_sibling(const char_t* name_) const { if (!_root) return xml_node(); for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) + return xml_node(i); + } return xml_node(); } - PUGI__FN xml_node xml_node::next_sibling() const + PUGI_IMPL_FN xml_node xml_node::next_sibling() const { return _root ? xml_node(_root->next_sibling) : xml_node(); } - PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const + PUGI_IMPL_FN xml_node xml_node::previous_sibling(const char_t* name_) const { if (!_root) return xml_node(); for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) + return xml_node(i); + } return xml_node(); } - PUGI__FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const + PUGI_IMPL_FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const { xml_attribute_struct* hint = hint_._attr; @@ -5591,94 +5714,108 @@ namespace pugi // optimistically search from hint up until the end for (xml_attribute_struct* i = hint; i; i = i->next_attribute) - if (i->name && impl::strequal(name_, i->name)) + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) { // update hint to maximize efficiency of searching for consecutive attributes hint_._attr = i->next_attribute; return xml_attribute(i); } + } // wrap around and search from the first attribute until the hint // 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute) - if (j->name && impl::strequal(name_, j->name)) + { + const char_t* jname = j->name; + if (jname && impl::strequal(name_, jname)) { // update hint to maximize efficiency of searching for consecutive attributes hint_._attr = j->next_attribute; return xml_attribute(j); } + } return xml_attribute(); } - PUGI__FN xml_node xml_node::previous_sibling() const + PUGI_IMPL_FN xml_node xml_node::previous_sibling() const { if (!_root) return xml_node(); - - if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); - else return xml_node(); + xml_node_struct* prev = _root->prev_sibling_c; + return prev->next_sibling ? xml_node(prev) : xml_node(); } - PUGI__FN xml_node xml_node::parent() const + PUGI_IMPL_FN xml_node xml_node::parent() const { return _root ? xml_node(_root->parent) : xml_node(); } - PUGI__FN xml_node xml_node::root() const + PUGI_IMPL_FN xml_node xml_node::root() const { return _root ? xml_node(&impl::get_document(_root)) : xml_node(); } - PUGI__FN xml_text xml_node::text() const + PUGI_IMPL_FN xml_text xml_node::text() const { return xml_text(_root); } - PUGI__FN const char_t* xml_node::child_value() const + PUGI_IMPL_FN const char_t* xml_node::child_value() const { if (!_root) return PUGIXML_TEXT(""); // element nodes can have value if parse_embed_pcdata was used - if (PUGI__NODETYPE(_root) == node_element && _root->value) + if (PUGI_IMPL_NODETYPE(_root) == node_element && _root->value) return _root->value; for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (impl::is_text_node(i) && i->value) - return i->value; + { + const char_t* ivalue = i->value; + if (impl::is_text_node(i) && ivalue) + return ivalue; + } return PUGIXML_TEXT(""); } - PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const + PUGI_IMPL_FN const char_t* xml_node::child_value(const char_t* name_) const { return child(name_).child_value(); } - PUGI__FN xml_attribute xml_node::first_attribute() const + PUGI_IMPL_FN xml_attribute xml_node::first_attribute() const { - return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); + if (!_root) return xml_attribute(); + return xml_attribute(_root->first_attribute); } - PUGI__FN xml_attribute xml_node::last_attribute() const + PUGI_IMPL_FN xml_attribute xml_node::last_attribute() const { - return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); + if (!_root) return xml_attribute(); + xml_attribute_struct* first = _root->first_attribute; + return first ? xml_attribute(first->prev_attribute_c) : xml_attribute(); } - PUGI__FN xml_node xml_node::first_child() const + PUGI_IMPL_FN xml_node xml_node::first_child() const { - return _root ? xml_node(_root->first_child) : xml_node(); + if (!_root) return xml_node(); + return xml_node(_root->first_child); } - PUGI__FN xml_node xml_node::last_child() const + PUGI_IMPL_FN xml_node xml_node::last_child() const { - return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); + if (!_root) return xml_node(); + xml_node_struct* first = _root->first_child; + return first ? xml_node(first->prev_sibling_c) : xml_node(); } - PUGI__FN bool xml_node::set_name(const char_t* rhs) + PUGI_IMPL_FN bool xml_node::set_name(const char_t* rhs) { - xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; + xml_node_type type_ = _root ? PUGI_IMPL_NODETYPE(_root) : node_null; if (type_ != node_element && type_ != node_pi && type_ != node_declaration) return false; @@ -5686,9 +5823,19 @@ namespace pugi return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); } - PUGI__FN bool xml_node::set_value(const char_t* rhs) + PUGI_IMPL_FN bool xml_node::set_name(const char_t* rhs, size_t size) { - xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; + xml_node_type type_ = _root ? PUGI_IMPL_NODETYPE(_root) : node_null; + + if (type_ != node_element && type_ != node_pi && type_ != node_declaration) + return false; + + return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, size); + } + + PUGI_IMPL_FN bool xml_node::set_value(const char_t* rhs) + { + xml_node_type type_ = _root ? PUGI_IMPL_NODETYPE(_root) : node_null; if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype) return false; @@ -5696,7 +5843,17 @@ namespace pugi return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); } - PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) + PUGI_IMPL_FN bool xml_node::set_value(const char_t* rhs, size_t size) + { + xml_node_type type_ = _root ? PUGI_IMPL_NODETYPE(_root) : node_null; + + if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype) + return false; + + return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, size); + } + + PUGI_IMPL_FN xml_attribute xml_node::append_attribute(const char_t* name_) { if (!impl::allow_insert_attribute(type())) return xml_attribute(); @@ -5713,7 +5870,7 @@ namespace pugi return a; } - PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_) + PUGI_IMPL_FN xml_attribute xml_node::prepend_attribute(const char_t* name_) { if (!impl::allow_insert_attribute(type())) return xml_attribute(); @@ -5730,7 +5887,7 @@ namespace pugi return a; } - PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) + PUGI_IMPL_FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) { if (!impl::allow_insert_attribute(type())) return xml_attribute(); if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); @@ -5748,7 +5905,7 @@ namespace pugi return a; } - PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) + PUGI_IMPL_FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) { if (!impl::allow_insert_attribute(type())) return xml_attribute(); if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); @@ -5766,7 +5923,7 @@ namespace pugi return a; } - PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto) + PUGI_IMPL_FN xml_attribute xml_node::append_copy(const xml_attribute& proto) { if (!proto) return xml_attribute(); if (!impl::allow_insert_attribute(type())) return xml_attribute(); @@ -5783,7 +5940,7 @@ namespace pugi return a; } - PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto) + PUGI_IMPL_FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto) { if (!proto) return xml_attribute(); if (!impl::allow_insert_attribute(type())) return xml_attribute(); @@ -5800,7 +5957,7 @@ namespace pugi return a; } - PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr) + PUGI_IMPL_FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr) { if (!proto) return xml_attribute(); if (!impl::allow_insert_attribute(type())) return xml_attribute(); @@ -5818,7 +5975,7 @@ namespace pugi return a; } - PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr) + PUGI_IMPL_FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr) { if (!proto) return xml_attribute(); if (!impl::allow_insert_attribute(type())) return xml_attribute(); @@ -5836,7 +5993,7 @@ namespace pugi return a; } - PUGI__FN xml_node xml_node::append_child(xml_node_type type_) + PUGI_IMPL_FN xml_node xml_node::append_child(xml_node_type type_) { if (!impl::allow_insert_child(type(), type_)) return xml_node(); @@ -5853,7 +6010,7 @@ namespace pugi return n; } - PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_) + PUGI_IMPL_FN xml_node xml_node::prepend_child(xml_node_type type_) { if (!impl::allow_insert_child(type(), type_)) return xml_node(); @@ -5870,7 +6027,7 @@ namespace pugi return n; } - PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node) + PUGI_IMPL_FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node) { if (!impl::allow_insert_child(type(), type_)) return xml_node(); if (!node._root || node._root->parent != _root) return xml_node(); @@ -5888,7 +6045,7 @@ namespace pugi return n; } - PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node) + PUGI_IMPL_FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node) { if (!impl::allow_insert_child(type(), type_)) return xml_node(); if (!node._root || node._root->parent != _root) return xml_node(); @@ -5906,7 +6063,7 @@ namespace pugi return n; } - PUGI__FN xml_node xml_node::append_child(const char_t* name_) + PUGI_IMPL_FN xml_node xml_node::append_child(const char_t* name_) { xml_node result = append_child(node_element); @@ -5915,7 +6072,7 @@ namespace pugi return result; } - PUGI__FN xml_node xml_node::prepend_child(const char_t* name_) + PUGI_IMPL_FN xml_node xml_node::prepend_child(const char_t* name_) { xml_node result = prepend_child(node_element); @@ -5924,7 +6081,7 @@ namespace pugi return result; } - PUGI__FN xml_node xml_node::insert_child_after(const char_t* name_, const xml_node& node) + PUGI_IMPL_FN xml_node xml_node::insert_child_after(const char_t* name_, const xml_node& node) { xml_node result = insert_child_after(node_element, node); @@ -5933,7 +6090,7 @@ namespace pugi return result; } - PUGI__FN xml_node xml_node::insert_child_before(const char_t* name_, const xml_node& node) + PUGI_IMPL_FN xml_node xml_node::insert_child_before(const char_t* name_, const xml_node& node) { xml_node result = insert_child_before(node_element, node); @@ -5942,7 +6099,7 @@ namespace pugi return result; } - PUGI__FN xml_node xml_node::append_copy(const xml_node& proto) + PUGI_IMPL_FN xml_node xml_node::append_copy(const xml_node& proto) { xml_node_type type_ = proto.type(); if (!impl::allow_insert_child(type(), type_)) return xml_node(); @@ -5959,7 +6116,7 @@ namespace pugi return n; } - PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto) + PUGI_IMPL_FN xml_node xml_node::prepend_copy(const xml_node& proto) { xml_node_type type_ = proto.type(); if (!impl::allow_insert_child(type(), type_)) return xml_node(); @@ -5976,7 +6133,7 @@ namespace pugi return n; } - PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) + PUGI_IMPL_FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) { xml_node_type type_ = proto.type(); if (!impl::allow_insert_child(type(), type_)) return xml_node(); @@ -5994,7 +6151,7 @@ namespace pugi return n; } - PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) + PUGI_IMPL_FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) { xml_node_type type_ = proto.type(); if (!impl::allow_insert_child(type(), type_)) return xml_node(); @@ -6012,7 +6169,7 @@ namespace pugi return n; } - PUGI__FN xml_node xml_node::append_move(const xml_node& moved) + PUGI_IMPL_FN xml_node xml_node::append_move(const xml_node& moved) { if (!impl::allow_move(*this, moved)) return xml_node(); @@ -6028,7 +6185,7 @@ namespace pugi return moved; } - PUGI__FN xml_node xml_node::prepend_move(const xml_node& moved) + PUGI_IMPL_FN xml_node xml_node::prepend_move(const xml_node& moved) { if (!impl::allow_move(*this, moved)) return xml_node(); @@ -6044,7 +6201,7 @@ namespace pugi return moved; } - PUGI__FN xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node) + PUGI_IMPL_FN xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node) { if (!impl::allow_move(*this, moved)) return xml_node(); if (!node._root || node._root->parent != _root) return xml_node(); @@ -6062,7 +6219,7 @@ namespace pugi return moved; } - PUGI__FN xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node) + PUGI_IMPL_FN xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node) { if (!impl::allow_move(*this, moved)) return xml_node(); if (!node._root || node._root->parent != _root) return xml_node(); @@ -6080,12 +6237,12 @@ namespace pugi return moved; } - PUGI__FN bool xml_node::remove_attribute(const char_t* name_) + PUGI_IMPL_FN bool xml_node::remove_attribute(const char_t* name_) { return remove_attribute(attribute(name_)); } - PUGI__FN bool xml_node::remove_attribute(const xml_attribute& a) + PUGI_IMPL_FN bool xml_node::remove_attribute(const xml_attribute& a) { if (!_root || !a._attr) return false; if (!impl::is_attribute_of(a._attr, _root)) return false; @@ -6099,7 +6256,7 @@ namespace pugi return true; } - PUGI__FN bool xml_node::remove_attributes() + PUGI_IMPL_FN bool xml_node::remove_attributes() { if (!_root) return false; @@ -6120,12 +6277,12 @@ namespace pugi return true; } - PUGI__FN bool xml_node::remove_child(const char_t* name_) + PUGI_IMPL_FN bool xml_node::remove_child(const char_t* name_) { return remove_child(child(name_)); } - PUGI__FN bool xml_node::remove_child(const xml_node& n) + PUGI_IMPL_FN bool xml_node::remove_child(const xml_node& n) { if (!_root || !n._root || n._root->parent != _root) return false; @@ -6138,7 +6295,7 @@ namespace pugi return true; } - PUGI__FN bool xml_node::remove_children() + PUGI_IMPL_FN bool xml_node::remove_children() { if (!_root) return false; @@ -6159,11 +6316,14 @@ namespace pugi return true; } - PUGI__FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) { // append_buffer is only valid for elements/documents if (!impl::allow_insert_child(type(), node_element)) return impl::make_parse_result(status_append_invalid_root); + // append buffer can not merge PCDATA into existing PCDATA nodes + if ((options & parse_merge_pcdata) != 0 && last_child().type() == node_pcdata) return impl::make_parse_result(status_append_invalid_root); + // get document node impl::xml_document_struct* doc = &impl::get_document(_root); @@ -6194,35 +6354,52 @@ namespace pugi return impl::load_buffer_impl(doc, _root, const_cast(contents), size, options, encoding, false, false, &extra->buffer); } - PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const + PUGI_IMPL_FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const { if (!_root) return xml_node(); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) + { + const char_t* iname = i->name; + if (iname && impl::strequal(name_, iname)) { for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) - return xml_node(i); + { + const char_t* aname = a->name; + if (aname && impl::strequal(attr_name, aname)) + { + const char_t* avalue = a->value; + if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT(""))) + return xml_node(i); + } + } } + } return xml_node(); } - PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const + PUGI_IMPL_FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const { if (!_root) return xml_node(); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) - return xml_node(i); + { + const char_t* aname = a->name; + if (aname && impl::strequal(attr_name, aname)) + { + const char_t* avalue = a->value; + if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT(""))) + return xml_node(i); + } + } return xml_node(); } #ifndef PUGIXML_NO_STL - PUGI__FN string_t xml_node::path(char_t delimiter) const + PUGI_IMPL_FN string_t xml_node::path(char_t delimiter) const { if (!_root) return string_t(); @@ -6230,8 +6407,9 @@ namespace pugi for (xml_node_struct* i = _root; i; i = i->parent) { + const char_t* iname = i->name; offset += (i != _root); - offset += i->name ? impl::strlength(i->name) : 0; + offset += iname ? impl::strlength(iname) : 0; } string_t result; @@ -6242,12 +6420,13 @@ namespace pugi if (j != _root) result[--offset] = delimiter; - if (j->name) + const char_t* jname = j->name; + if (jname) { - size_t length = impl::strlength(j->name); + size_t length = impl::strlength(jname); offset -= length; - memcpy(&result[offset], j->name, length * sizeof(char_t)); + memcpy(&result[offset], jname, length * sizeof(char_t)); } } @@ -6257,7 +6436,7 @@ namespace pugi } #endif - PUGI__FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const + PUGI_IMPL_FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const { xml_node context = path_[0] == delimiter ? root() : *this; @@ -6285,7 +6464,8 @@ namespace pugi { for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling) { - if (j->name && impl::strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) + const char_t* jname = j->name; + if (jname && impl::strequalrange(jname, path_segment, static_cast(path_segment_end - path_segment))) { xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); @@ -6297,7 +6477,7 @@ namespace pugi } } - PUGI__FN bool xml_node::traverse(xml_tree_walker& walker) + PUGI_IMPL_FN bool xml_node::traverse(xml_tree_walker& walker) { walker._depth = -1; @@ -6344,17 +6524,17 @@ namespace pugi return walker.end(arg_end); } - PUGI__FN size_t xml_node::hash_value() const + PUGI_IMPL_FN size_t xml_node::hash_value() const { return static_cast(reinterpret_cast(_root) / sizeof(xml_node_struct)); } - PUGI__FN xml_node_struct* xml_node::internal_object() const + PUGI_IMPL_FN xml_node_struct* xml_node::internal_object() const { return _root; } - PUGI__FN void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + PUGI_IMPL_FN void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const { if (!_root) return; @@ -6366,14 +6546,14 @@ namespace pugi } #ifndef PUGIXML_NO_STL - PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + PUGI_IMPL_FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const { xml_writer_stream writer(stream); print(writer, indent, flags, encoding, depth); } - PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const + PUGI_IMPL_FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const { xml_writer_stream writer(stream); @@ -6381,7 +6561,7 @@ namespace pugi } #endif - PUGI__FN ptrdiff_t xml_node::offset_debug() const + PUGI_IMPL_FN ptrdiff_t xml_node::offset_debug() const { if (!_root) return -1; @@ -6413,27 +6593,27 @@ namespace pugi } #ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_node& lhs, bool rhs) + PUGI_IMPL_FN bool operator&&(const xml_node& lhs, bool rhs) { return (bool)lhs && rhs; } - PUGI__FN bool operator||(const xml_node& lhs, bool rhs) + PUGI_IMPL_FN bool operator||(const xml_node& lhs, bool rhs) { return (bool)lhs || rhs; } #endif - PUGI__FN xml_text::xml_text(xml_node_struct* root): _root(root) + PUGI_IMPL_FN xml_text::xml_text(xml_node_struct* root): _root(root) { } - PUGI__FN xml_node_struct* xml_text::_data() const + PUGI_IMPL_FN xml_node_struct* xml_text::_data() const { if (!_root || impl::is_text_node(_root)) return _root; // element nodes can have value if parse_embed_pcdata was used - if (PUGI__NODETYPE(_root) == node_element && _root->value) + if (PUGI_IMPL_NODETYPE(_root) == node_element && _root->value) return _root; for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling) @@ -6443,7 +6623,7 @@ namespace pugi return 0; } - PUGI__FN xml_node_struct* xml_text::_data_new() + PUGI_IMPL_FN xml_node_struct* xml_text::_data_new() { xml_node_struct* d = _data(); if (d) return d; @@ -6451,158 +6631,174 @@ namespace pugi return xml_node(_root).append_child(node_pcdata).internal_object(); } - PUGI__FN xml_text::xml_text(): _root(0) + PUGI_IMPL_FN xml_text::xml_text(): _root(0) { } - PUGI__FN static void unspecified_bool_xml_text(xml_text***) + PUGI_IMPL_FN static void unspecified_bool_xml_text(xml_text***) { } - PUGI__FN xml_text::operator xml_text::unspecified_bool_type() const + PUGI_IMPL_FN xml_text::operator xml_text::unspecified_bool_type() const { return _data() ? unspecified_bool_xml_text : 0; } - PUGI__FN bool xml_text::operator!() const + PUGI_IMPL_FN bool xml_text::operator!() const { return !_data(); } - PUGI__FN bool xml_text::empty() const + PUGI_IMPL_FN bool xml_text::empty() const { return _data() == 0; } - PUGI__FN const char_t* xml_text::get() const + PUGI_IMPL_FN const char_t* xml_text::get() const { xml_node_struct* d = _data(); - - return (d && d->value) ? d->value + 0 : PUGIXML_TEXT(""); + if (!d) return PUGIXML_TEXT(""); + const char_t* value = d->value; + return value ? value : PUGIXML_TEXT(""); } - PUGI__FN const char_t* xml_text::as_string(const char_t* def) const + PUGI_IMPL_FN const char_t* xml_text::as_string(const char_t* def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? d->value + 0 : def; + if (!d) return def; + const char_t* value = d->value; + return value ? value : def; } - PUGI__FN int xml_text::as_int(int def) const + PUGI_IMPL_FN int xml_text::as_int(int def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_int(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_int(value) : def; } - PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const + PUGI_IMPL_FN unsigned int xml_text::as_uint(unsigned int def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_uint(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_uint(value) : def; } - PUGI__FN double xml_text::as_double(double def) const + PUGI_IMPL_FN double xml_text::as_double(double def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_double(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_double(value) : def; } - PUGI__FN float xml_text::as_float(float def) const + PUGI_IMPL_FN float xml_text::as_float(float def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_float(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_float(value) : def; } - PUGI__FN bool xml_text::as_bool(bool def) const + PUGI_IMPL_FN bool xml_text::as_bool(bool def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_bool(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_bool(value) : def; } #ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long xml_text::as_llong(long long def) const + PUGI_IMPL_FN long long xml_text::as_llong(long long def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_llong(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_llong(value) : def; } - PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const + PUGI_IMPL_FN unsigned long long xml_text::as_ullong(unsigned long long def) const { xml_node_struct* d = _data(); - - return (d && d->value) ? impl::get_value_ullong(d->value) : def; + if (!d) return def; + const char_t* value = d->value; + return value ? impl::get_value_ullong(value) : def; } #endif - PUGI__FN bool xml_text::set(const char_t* rhs) + PUGI_IMPL_FN bool xml_text::set(const char_t* rhs) { xml_node_struct* dn = _data_new(); return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)) : false; } - PUGI__FN bool xml_text::set(int rhs) + PUGI_IMPL_FN bool xml_text::set(const char_t* rhs, size_t size) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, size) : false; + } + + PUGI_IMPL_FN bool xml_text::set(int rhs) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; } - PUGI__FN bool xml_text::set(unsigned int rhs) + PUGI_IMPL_FN bool xml_text::set(unsigned int rhs) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false; } - PUGI__FN bool xml_text::set(long rhs) + PUGI_IMPL_FN bool xml_text::set(long rhs) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; } - PUGI__FN bool xml_text::set(unsigned long rhs) + PUGI_IMPL_FN bool xml_text::set(unsigned long rhs) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false; } - PUGI__FN bool xml_text::set(float rhs) + PUGI_IMPL_FN bool xml_text::set(float rhs) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, default_float_precision) : false; } - PUGI__FN bool xml_text::set(float rhs, int precision) + PUGI_IMPL_FN bool xml_text::set(float rhs, int precision) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) : false; } - PUGI__FN bool xml_text::set(double rhs) + PUGI_IMPL_FN bool xml_text::set(double rhs) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, default_double_precision) : false; } - PUGI__FN bool xml_text::set(double rhs, int precision) + PUGI_IMPL_FN bool xml_text::set(double rhs, int precision) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) : false; } - PUGI__FN bool xml_text::set(bool rhs) + PUGI_IMPL_FN bool xml_text::set(bool rhs) { xml_node_struct* dn = _data_new(); @@ -6610,14 +6806,14 @@ namespace pugi } #ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN bool xml_text::set(long long rhs) + PUGI_IMPL_FN bool xml_text::set(long long rhs) { xml_node_struct* dn = _data_new(); return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; } - PUGI__FN bool xml_text::set(unsigned long long rhs) + PUGI_IMPL_FN bool xml_text::set(unsigned long long rhs) { xml_node_struct* dn = _data_new(); @@ -6625,256 +6821,256 @@ namespace pugi } #endif - PUGI__FN xml_text& xml_text::operator=(const char_t* rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(const char_t* rhs) { set(rhs); return *this; } - PUGI__FN xml_text& xml_text::operator=(int rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(int rhs) { set(rhs); return *this; } - PUGI__FN xml_text& xml_text::operator=(unsigned int rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(unsigned int rhs) { set(rhs); return *this; } - PUGI__FN xml_text& xml_text::operator=(long rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(long rhs) { set(rhs); return *this; } - PUGI__FN xml_text& xml_text::operator=(unsigned long rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(unsigned long rhs) { set(rhs); return *this; } - PUGI__FN xml_text& xml_text::operator=(double rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(double rhs) { set(rhs); return *this; } - PUGI__FN xml_text& xml_text::operator=(float rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(float rhs) { set(rhs); return *this; } - PUGI__FN xml_text& xml_text::operator=(bool rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(bool rhs) { set(rhs); return *this; } #ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN xml_text& xml_text::operator=(long long rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(long long rhs) { set(rhs); return *this; } - PUGI__FN xml_text& xml_text::operator=(unsigned long long rhs) + PUGI_IMPL_FN xml_text& xml_text::operator=(unsigned long long rhs) { set(rhs); return *this; } #endif - PUGI__FN xml_node xml_text::data() const + PUGI_IMPL_FN xml_node xml_text::data() const { return xml_node(_data()); } #ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_text& lhs, bool rhs) + PUGI_IMPL_FN bool operator&&(const xml_text& lhs, bool rhs) { return (bool)lhs && rhs; } - PUGI__FN bool operator||(const xml_text& lhs, bool rhs) + PUGI_IMPL_FN bool operator||(const xml_text& lhs, bool rhs) { return (bool)lhs || rhs; } #endif - PUGI__FN xml_node_iterator::xml_node_iterator() + PUGI_IMPL_FN xml_node_iterator::xml_node_iterator() { } - PUGI__FN xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent()) + PUGI_IMPL_FN xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent()) { } - PUGI__FN xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) + PUGI_IMPL_FN xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) { } - PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const + PUGI_IMPL_FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const { return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; } - PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const + PUGI_IMPL_FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const { return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; } - PUGI__FN xml_node& xml_node_iterator::operator*() const + PUGI_IMPL_FN xml_node& xml_node_iterator::operator*() const { assert(_wrap._root); return _wrap; } - PUGI__FN xml_node* xml_node_iterator::operator->() const + PUGI_IMPL_FN xml_node* xml_node_iterator::operator->() const { assert(_wrap._root); return const_cast(&_wrap); // BCC5 workaround } - PUGI__FN xml_node_iterator& xml_node_iterator::operator++() + PUGI_IMPL_FN xml_node_iterator& xml_node_iterator::operator++() { assert(_wrap._root); _wrap._root = _wrap._root->next_sibling; return *this; } - PUGI__FN xml_node_iterator xml_node_iterator::operator++(int) + PUGI_IMPL_FN xml_node_iterator xml_node_iterator::operator++(int) { xml_node_iterator temp = *this; ++*this; return temp; } - PUGI__FN xml_node_iterator& xml_node_iterator::operator--() + PUGI_IMPL_FN xml_node_iterator& xml_node_iterator::operator--() { _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child(); return *this; } - PUGI__FN xml_node_iterator xml_node_iterator::operator--(int) + PUGI_IMPL_FN xml_node_iterator xml_node_iterator::operator--(int) { xml_node_iterator temp = *this; --*this; return temp; } - PUGI__FN xml_attribute_iterator::xml_attribute_iterator() + PUGI_IMPL_FN xml_attribute_iterator::xml_attribute_iterator() { } - PUGI__FN xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent) + PUGI_IMPL_FN xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent) { } - PUGI__FN xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) + PUGI_IMPL_FN xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) { } - PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const + PUGI_IMPL_FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const { return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root; } - PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const + PUGI_IMPL_FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const { return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root; } - PUGI__FN xml_attribute& xml_attribute_iterator::operator*() const + PUGI_IMPL_FN xml_attribute& xml_attribute_iterator::operator*() const { assert(_wrap._attr); return _wrap; } - PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const + PUGI_IMPL_FN xml_attribute* xml_attribute_iterator::operator->() const { assert(_wrap._attr); return const_cast(&_wrap); // BCC5 workaround } - PUGI__FN xml_attribute_iterator& xml_attribute_iterator::operator++() + PUGI_IMPL_FN xml_attribute_iterator& xml_attribute_iterator::operator++() { assert(_wrap._attr); _wrap._attr = _wrap._attr->next_attribute; return *this; } - PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator++(int) + PUGI_IMPL_FN xml_attribute_iterator xml_attribute_iterator::operator++(int) { xml_attribute_iterator temp = *this; ++*this; return temp; } - PUGI__FN xml_attribute_iterator& xml_attribute_iterator::operator--() + PUGI_IMPL_FN xml_attribute_iterator& xml_attribute_iterator::operator--() { _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute(); return *this; } - PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator--(int) + PUGI_IMPL_FN xml_attribute_iterator xml_attribute_iterator::operator--(int) { xml_attribute_iterator temp = *this; --*this; return temp; } - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(): _name(0) + PUGI_IMPL_FN xml_named_node_iterator::xml_named_node_iterator(): _name(0) { } - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _wrap(node), _parent(node.parent()), _name(name) + PUGI_IMPL_FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _wrap(node), _parent(node.parent()), _name(name) { } - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name): _wrap(ref), _parent(parent), _name(name) + PUGI_IMPL_FN xml_named_node_iterator::xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name): _wrap(ref), _parent(parent), _name(name) { } - PUGI__FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const + PUGI_IMPL_FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const { return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; } - PUGI__FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const + PUGI_IMPL_FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const { return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; } - PUGI__FN xml_node& xml_named_node_iterator::operator*() const + PUGI_IMPL_FN xml_node& xml_named_node_iterator::operator*() const { assert(_wrap._root); return _wrap; } - PUGI__FN xml_node* xml_named_node_iterator::operator->() const + PUGI_IMPL_FN xml_node* xml_named_node_iterator::operator->() const { assert(_wrap._root); return const_cast(&_wrap); // BCC5 workaround } - PUGI__FN xml_named_node_iterator& xml_named_node_iterator::operator++() + PUGI_IMPL_FN xml_named_node_iterator& xml_named_node_iterator::operator++() { assert(_wrap._root); _wrap = _wrap.next_sibling(_name); return *this; } - PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator++(int) + PUGI_IMPL_FN xml_named_node_iterator xml_named_node_iterator::operator++(int) { xml_named_node_iterator temp = *this; ++*this; return temp; } - PUGI__FN xml_named_node_iterator& xml_named_node_iterator::operator--() + PUGI_IMPL_FN xml_named_node_iterator& xml_named_node_iterator::operator--() { if (_wrap._root) _wrap = _wrap.previous_sibling(_name); @@ -6889,23 +7085,23 @@ namespace pugi return *this; } - PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator--(int) + PUGI_IMPL_FN xml_named_node_iterator xml_named_node_iterator::operator--(int) { xml_named_node_iterator temp = *this; --*this; return temp; } - PUGI__FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) + PUGI_IMPL_FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) { } - PUGI__FN xml_parse_result::operator bool() const + PUGI_IMPL_FN xml_parse_result::operator bool() const { return status == status_ok; } - PUGI__FN const char* xml_parse_result::description() const + PUGI_IMPL_FN const char* xml_parse_result::description() const { switch (status) { @@ -6936,24 +7132,24 @@ namespace pugi } } - PUGI__FN xml_document::xml_document(): _buffer(0) + PUGI_IMPL_FN xml_document::xml_document(): _buffer(0) { _create(); } - PUGI__FN xml_document::~xml_document() + PUGI_IMPL_FN xml_document::~xml_document() { _destroy(); } #ifdef PUGIXML_HAS_MOVE - PUGI__FN xml_document::xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT: _buffer(0) + PUGI_IMPL_FN xml_document::xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT: _buffer(0) { _create(); _move(rhs); } - PUGI__FN xml_document& xml_document::operator=(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT + PUGI_IMPL_FN xml_document& xml_document::operator=(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT { if (this == &rhs) return *this; @@ -6965,20 +7161,20 @@ namespace pugi } #endif - PUGI__FN void xml_document::reset() + PUGI_IMPL_FN void xml_document::reset() { _destroy(); _create(); } - PUGI__FN void xml_document::reset(const xml_document& proto) + PUGI_IMPL_FN void xml_document::reset(const xml_document& proto) { reset(); impl::node_copy_tree(_root, proto._root); } - PUGI__FN void xml_document::_create() + PUGI_IMPL_FN void xml_document::_create() { assert(!_root); @@ -6990,7 +7186,7 @@ namespace pugi #endif // initialize sentinel page - PUGI__STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + page_offset <= sizeof(_memory)); + PUGI_IMPL_STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + page_offset <= sizeof(_memory)); // prepare page structure impl::xml_memory_page* page = impl::xml_memory_page::construct(_memory); @@ -7021,7 +7217,7 @@ namespace pugi assert(reinterpret_cast(_root) + sizeof(impl::xml_document_struct) <= _memory + sizeof(_memory)); } - PUGI__FN void xml_document::_destroy() + PUGI_IMPL_FN void xml_document::_destroy() { assert(_root); @@ -7039,7 +7235,7 @@ namespace pugi } // destroy dynamic storage, leave sentinel page (it's in static memory) - impl::xml_memory_page* root_page = PUGI__GETPAGE(_root); + impl::xml_memory_page* root_page = PUGI_IMPL_GETPAGE(_root); assert(root_page && !root_page->prev); assert(reinterpret_cast(root_page) >= _memory && reinterpret_cast(root_page) < _memory + sizeof(_memory)); @@ -7061,7 +7257,7 @@ namespace pugi } #ifdef PUGIXML_HAS_MOVE - PUGI__FN void xml_document::_move(xml_document& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT + PUGI_IMPL_FN void xml_document::_move(xml_document& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT { impl::xml_document_struct* doc = static_cast(_root); impl::xml_document_struct* other = static_cast(rhs._root); @@ -7095,7 +7291,7 @@ namespace pugi // move allocation state // note that other->_root may point to the embedded document page, in which case we should keep original (empty) state - if (other->_root != PUGI__GETPAGE(other)) + if (other->_root != PUGI_IMPL_GETPAGE(other)) { doc->_root = other->_root; doc->_busy_size = other->_busy_size; @@ -7116,10 +7312,10 @@ namespace pugi #endif // move page structure - impl::xml_memory_page* doc_page = PUGI__GETPAGE(doc); + impl::xml_memory_page* doc_page = PUGI_IMPL_GETPAGE(doc); assert(doc_page && !doc_page->prev && !doc_page->next); - impl::xml_memory_page* other_page = PUGI__GETPAGE(other); + impl::xml_memory_page* other_page = PUGI_IMPL_GETPAGE(other); assert(other_page && !other_page->prev); // relink pages since root page is embedded into xml_document @@ -7166,20 +7362,20 @@ namespace pugi } // reset other document - new (other) impl::xml_document_struct(PUGI__GETPAGE(other)); + new (other) impl::xml_document_struct(PUGI_IMPL_GETPAGE(other)); rhs._buffer = 0; } #endif #ifndef PUGIXML_NO_STL - PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) { reset(); return impl::load_stream_impl(static_cast(_root), stream, options, encoding, &_buffer); } - PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) + PUGI_IMPL_FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) { reset(); @@ -7187,7 +7383,7 @@ namespace pugi } #endif - PUGI__FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options) + PUGI_IMPL_FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options) { // Force native encoding (skip autodetection) #ifdef PUGIXML_WCHAR_MODE @@ -7199,12 +7395,12 @@ namespace pugi return load_buffer(contents, impl::strlength(contents) * sizeof(char_t), options, encoding); } - PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) + PUGI_IMPL_FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) { return load_string(contents, options); } - PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) { reset(); @@ -7214,7 +7410,7 @@ namespace pugi return impl::load_file_impl(static_cast(_root), file.data, options, encoding, &_buffer); } - PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding) { reset(); @@ -7224,28 +7420,28 @@ namespace pugi return impl::load_file_impl(static_cast(_root), file.data, options, encoding, &_buffer); } - PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) { reset(); return impl::load_buffer_impl(static_cast(_root), _root, const_cast(contents), size, options, encoding, false, false, &_buffer); } - PUGI__FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding) { reset(); return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, false, &_buffer); } - PUGI__FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding) { reset(); return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, true, &_buffer); } - PUGI__FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const + PUGI_IMPL_FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const { impl::xml_buffered_writer buffered_writer(writer, encoding); @@ -7274,14 +7470,14 @@ namespace pugi } #ifndef PUGIXML_NO_STL - PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const + PUGI_IMPL_FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const { xml_writer_stream writer(stream); save(writer, indent, flags, encoding); } - PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const + PUGI_IMPL_FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const { xml_writer_stream writer(stream); @@ -7289,71 +7485,71 @@ namespace pugi } #endif - PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const + PUGI_IMPL_FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const { using impl::auto_deleter; // MSVC7 workaround auto_deleter file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); - return impl::save_file_impl(*this, file.data, indent, flags, encoding); + return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0; } - PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const + PUGI_IMPL_FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const { using impl::auto_deleter; // MSVC7 workaround auto_deleter file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file); - return impl::save_file_impl(*this, file.data, indent, flags, encoding); + return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0; } - PUGI__FN xml_node xml_document::document_element() const + PUGI_IMPL_FN xml_node xml_document::document_element() const { assert(_root); for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (PUGI__NODETYPE(i) == node_element) + if (PUGI_IMPL_NODETYPE(i) == node_element) return xml_node(i); return xml_node(); } #ifndef PUGIXML_NO_STL - PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str) + PUGI_IMPL_FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str) { assert(str); return impl::as_utf8_impl(str, impl::strlength_wide(str)); } - PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string& str) + PUGI_IMPL_FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string& str) { return impl::as_utf8_impl(str.c_str(), str.size()); } - PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const char* str) + PUGI_IMPL_FN std::basic_string PUGIXML_FUNCTION as_wide(const char* str) { assert(str); return impl::as_wide_impl(str, strlen(str)); } - PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const std::string& str) + PUGI_IMPL_FN std::basic_string PUGIXML_FUNCTION as_wide(const std::string& str) { return impl::as_wide_impl(str.c_str(), str.size()); } #endif - PUGI__FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate) + PUGI_IMPL_FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate) { impl::xml_memory::allocate = allocate; impl::xml_memory::deallocate = deallocate; } - PUGI__FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function() + PUGI_IMPL_FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function() { return impl::xml_memory::allocate; } - PUGI__FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function() + PUGI_IMPL_FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function() { return impl::xml_memory::deallocate; } @@ -7363,17 +7559,17 @@ namespace pugi namespace std { // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&) + PUGI_IMPL_FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&) { return std::bidirectional_iterator_tag(); } - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&) + PUGI_IMPL_FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&) { return std::bidirectional_iterator_tag(); } - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&) + PUGI_IMPL_FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&) { return std::bidirectional_iterator_tag(); } @@ -7384,17 +7580,17 @@ namespace std namespace std { // Workarounds for (non-standard) iterator category detection - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&) + PUGI_IMPL_FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&) { return std::bidirectional_iterator_tag(); } - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&) + PUGI_IMPL_FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&) { return std::bidirectional_iterator_tag(); } - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) + PUGI_IMPL_FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) { return std::bidirectional_iterator_tag(); } @@ -7403,7 +7599,7 @@ namespace std #ifndef PUGIXML_NO_XPATH // STL replacements -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN struct equal_to { template bool operator()(const T& lhs, const T& rhs) const @@ -7443,7 +7639,7 @@ PUGI__NS_BEGIN rhs = temp; } - template PUGI__FN I min_element(I begin, I end, const Pred& pred) + template PUGI_IMPL_FN I min_element(I begin, I end, const Pred& pred) { I result = begin; @@ -7454,13 +7650,13 @@ PUGI__NS_BEGIN return result; } - template PUGI__FN void reverse(I begin, I end) + template PUGI_IMPL_FN void reverse(I begin, I end) { while (end - begin > 1) swap(*begin++, *--end); } - template PUGI__FN I unique(I begin, I end) + template PUGI_IMPL_FN I unique(I begin, I end) { // fast skip head while (end - begin > 1 && *begin != *(begin + 1)) @@ -7485,7 +7681,7 @@ PUGI__NS_BEGIN return write + 1; } - template PUGI__FN void insertion_sort(T* begin, T* end, const Pred& pred) + template PUGI_IMPL_FN void insertion_sort(T* begin, T* end, const Pred& pred) { if (begin == end) return; @@ -7519,7 +7715,7 @@ PUGI__NS_BEGIN return middle; } - template PUGI__FN void partition3(T* begin, T* end, T pivot, const Pred& pred, T** out_eqbeg, T** out_eqend) + template PUGI_IMPL_FN void partition3(T* begin, T* end, T pivot, const Pred& pred, T** out_eqbeg, T** out_eqend) { // invariant: array is split into 4 groups: = < ? > (each variable denotes the boundary between the groups) T* eq = begin; @@ -7546,7 +7742,7 @@ PUGI__NS_BEGIN *out_eqend = gt; } - template PUGI__FN void sort(I begin, I end, const Pred& pred) + template PUGI_IMPL_FN void sort(I begin, I end, const Pred& pred) { // sort large chunks while (end - begin > 16) @@ -7576,7 +7772,7 @@ PUGI__NS_BEGIN insertion_sort(begin, end, pred); } - PUGI__FN bool hash_insert(const void** table, size_t size, const void* key) + PUGI_IMPL_FN bool hash_insert(const void** table, size_t size, const void* key) { assert(key); @@ -7610,10 +7806,10 @@ PUGI__NS_BEGIN assert(false && "Hash table is full"); // unreachable return false; } -PUGI__NS_END +PUGI_IMPL_NS_END // Allocator used for AST and evaluation stacks -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN static const size_t xpath_memory_page_size = #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE PUGIXML_MEMORY_XPATH_PAGE_SIZE @@ -7809,10 +8005,10 @@ PUGI__NS_BEGIN temp.release(); } }; -PUGI__NS_END +PUGI_IMPL_NS_END // String class -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN class xpath_string { const char_t* _buffer; @@ -7947,10 +8143,10 @@ PUGI__NS_BEGIN return _uses_heap; } }; -PUGI__NS_END +PUGI_IMPL_NS_END -PUGI__NS_BEGIN - PUGI__FN bool starts_with(const char_t* string, const char_t* pattern) +PUGI_IMPL_NS_BEGIN + PUGI_IMPL_FN bool starts_with(const char_t* string, const char_t* pattern) { while (*pattern && *string == *pattern) { @@ -7961,7 +8157,7 @@ PUGI__NS_BEGIN return *pattern == 0; } - PUGI__FN const char_t* find_char(const char_t* s, char_t c) + PUGI_IMPL_FN const char_t* find_char(const char_t* s, char_t c) { #ifdef PUGIXML_WCHAR_MODE return wcschr(s, c); @@ -7970,7 +8166,7 @@ PUGI__NS_BEGIN #endif } - PUGI__FN const char_t* find_substring(const char_t* s, const char_t* p) + PUGI_IMPL_FN const char_t* find_substring(const char_t* s, const char_t* p) { #ifdef PUGIXML_WCHAR_MODE // MSVC6 wcsstr bug workaround (if s is empty it always returns 0) @@ -7981,12 +8177,12 @@ PUGI__NS_BEGIN } // Converts symbol to lower case, if it is an ASCII one - PUGI__FN char_t tolower_ascii(char_t ch) + PUGI_IMPL_FN char_t tolower_ascii(char_t ch) { return static_cast(ch - 'A') < 26 ? static_cast(ch | ' ') : ch; } - PUGI__FN xpath_string string_value(const xpath_node& na, xpath_allocator* alloc) + PUGI_IMPL_FN xpath_string string_value(const xpath_node& na, xpath_allocator* alloc) { if (na.attribute()) return xpath_string::from_const(na.attribute().value()); @@ -8040,7 +8236,7 @@ PUGI__NS_BEGIN } } - PUGI__FN bool node_is_before_sibling(xml_node_struct* ln, xml_node_struct* rn) + PUGI_IMPL_FN bool node_is_before_sibling(xml_node_struct* ln, xml_node_struct* rn) { assert(ln->parent == rn->parent); @@ -8064,7 +8260,7 @@ PUGI__NS_BEGIN return !rs; } - PUGI__FN bool node_is_before(xml_node_struct* ln, xml_node_struct* rn) + PUGI_IMPL_FN bool node_is_before(xml_node_struct* ln, xml_node_struct* rn) { // find common ancestor at the same depth, if any xml_node_struct* lp = ln; @@ -8107,14 +8303,14 @@ PUGI__NS_BEGIN return node_is_before_sibling(ln, rn); } - PUGI__FN bool node_is_ancestor(xml_node_struct* parent, xml_node_struct* node) + PUGI_IMPL_FN bool node_is_ancestor(xml_node_struct* parent, xml_node_struct* node) { while (node && node != parent) node = node->parent; return parent && node == parent; } - PUGI__FN const void* document_buffer_order(const xpath_node& xnode) + PUGI_IMPL_FN const void* document_buffer_order(const xpath_node& xnode) { xml_node_struct* node = xnode.node().internal_object(); @@ -8199,10 +8395,10 @@ PUGI__NS_BEGIN } }; - PUGI__FN double gen_nan() + PUGI_IMPL_FN double gen_nan() { #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24)) - PUGI__STATIC_ASSERT(sizeof(float) == sizeof(uint32_t)); + PUGI_IMPL_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t)); typedef uint32_t UI; // BCC5 workaround union { float f; UI i; } u; u.i = 0x7fc00000; @@ -8214,9 +8410,9 @@ PUGI__NS_BEGIN #endif } - PUGI__FN bool is_nan(double value) + PUGI_IMPL_FN bool is_nan(double value) { - #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) + #if defined(PUGI_IMPL_MSVC_CRT_VERSION) || defined(__BORLANDC__) return !!_isnan(value); #elif defined(fpclassify) && defined(FP_NAN) return fpclassify(value) == FP_NAN; @@ -8227,9 +8423,9 @@ PUGI__NS_BEGIN #endif } - PUGI__FN const char_t* convert_number_to_string_special(double value) + PUGI_IMPL_FN const char_t* convert_number_to_string_special(double value) { - #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) + #if defined(PUGI_IMPL_MSVC_CRT_VERSION) || defined(__BORLANDC__) if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0; if (_isnan(value)) return PUGIXML_TEXT("NaN"); return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); @@ -8259,12 +8455,12 @@ PUGI__NS_BEGIN #endif } - PUGI__FN bool convert_number_to_boolean(double value) + PUGI_IMPL_FN bool convert_number_to_boolean(double value) { return (value != 0 && !is_nan(value)); } - PUGI__FN void truncate_zeros(char* begin, char* end) + PUGI_IMPL_FN void truncate_zeros(char* begin, char* end) { while (begin != end && end[-1] == '0') end--; @@ -8272,8 +8468,8 @@ PUGI__NS_BEGIN } // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent -#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 - PUGI__FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent) +#if defined(PUGI_IMPL_MSVC_CRT_VERSION) && PUGI_IMPL_MSVC_CRT_VERSION >= 1400 + PUGI_IMPL_FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent) { // get base values int sign, exponent; @@ -8287,10 +8483,10 @@ PUGI__NS_BEGIN *out_exponent = exponent; } #else - PUGI__FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent) + PUGI_IMPL_FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent) { // get a scientific notation value with IEEE DBL_DIG decimals - PUGI__SNPRINTF(buffer, "%.*e", DBL_DIG, value); + PUGI_IMPL_SNPRINTF(buffer, "%.*e", DBL_DIG, value); // get the exponent (possibly negative) char* exponent_string = strchr(buffer, 'e'); @@ -8300,7 +8496,7 @@ PUGI__NS_BEGIN // extract mantissa string: skip sign char* mantissa = buffer[0] == '-' ? buffer + 1 : buffer; - assert(mantissa[0] != '0' && mantissa[1] == '.'); + assert(mantissa[0] != '0' && (mantissa[1] == '.' || mantissa[1] == ',')); // divide mantissa by 10 to eliminate integer part mantissa[1] = mantissa[0]; @@ -8316,7 +8512,7 @@ PUGI__NS_BEGIN } #endif - PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator* alloc) + PUGI_IMPL_FN xpath_string convert_number_to_string(double value, xpath_allocator* alloc) { // try special number conversion const char_t* special = convert_number_to_string_special(value); @@ -8383,10 +8579,10 @@ PUGI__NS_BEGIN return xpath_string::from_heap_preallocated(result, s); } - PUGI__FN bool check_string_to_number_format(const char_t* string) + PUGI_IMPL_FN bool check_string_to_number_format(const char_t* string) { // parse leading whitespace - while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; + while (PUGI_IMPL_IS_CHARTYPE(*string, ct_space)) ++string; // parse sign if (*string == '-') ++string; @@ -8394,26 +8590,26 @@ PUGI__NS_BEGIN if (!*string) return false; // if there is no integer part, there should be a decimal part with at least one digit - if (!PUGI__IS_CHARTYPEX(string[0], ctx_digit) && (string[0] != '.' || !PUGI__IS_CHARTYPEX(string[1], ctx_digit))) return false; + if (!PUGI_IMPL_IS_CHARTYPEX(string[0], ctx_digit) && (string[0] != '.' || !PUGI_IMPL_IS_CHARTYPEX(string[1], ctx_digit))) return false; // parse integer part - while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; + while (PUGI_IMPL_IS_CHARTYPEX(*string, ctx_digit)) ++string; // parse decimal part if (*string == '.') { ++string; - while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; + while (PUGI_IMPL_IS_CHARTYPEX(*string, ctx_digit)) ++string; } // parse trailing whitespace - while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; + while (PUGI_IMPL_IS_CHARTYPE(*string, ct_space)) ++string; return *string == 0; } - PUGI__FN double convert_string_to_number(const char_t* string) + PUGI_IMPL_FN double convert_string_to_number(const char_t* string) { // check string format if (!check_string_to_number_format(string)) return gen_nan(); @@ -8426,7 +8622,7 @@ PUGI__NS_BEGIN #endif } - PUGI__FN bool convert_string_to_number_scratch(char_t (&buffer)[32], const char_t* begin, const char_t* end, double* out_result) + PUGI_IMPL_FN bool convert_string_to_number_scratch(char_t (&buffer)[32], const char_t* begin, const char_t* end, double* out_result) { size_t length = static_cast(end - begin); char_t* scratch = buffer; @@ -8450,24 +8646,24 @@ PUGI__NS_BEGIN return true; } - PUGI__FN double round_nearest(double value) + PUGI_IMPL_FN double round_nearest(double value) { return floor(value + 0.5); } - PUGI__FN double round_nearest_nzero(double value) + PUGI_IMPL_FN double round_nearest_nzero(double value) { // same as round_nearest, but returns -0 for [-0.5, -0] // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0) return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5); } - PUGI__FN const char_t* qualified_name(const xpath_node& node) + PUGI_IMPL_FN const char_t* qualified_name(const xpath_node& node) { return node.attribute() ? node.attribute().name() : node.node().name(); } - PUGI__FN const char_t* local_name(const xpath_node& node) + PUGI_IMPL_FN const char_t* local_name(const xpath_node& node) { const char_t* name = qualified_name(node); const char_t* p = find_char(name, ':'); @@ -8498,7 +8694,7 @@ PUGI__NS_BEGIN } }; - PUGI__FN const char_t* namespace_uri(xml_node node) + PUGI_IMPL_FN const char_t* namespace_uri(xml_node node) { namespace_uri_predicate pred = node.name(); @@ -8516,7 +8712,7 @@ PUGI__NS_BEGIN return PUGIXML_TEXT(""); } - PUGI__FN const char_t* namespace_uri(xml_attribute attr, xml_node parent) + PUGI_IMPL_FN const char_t* namespace_uri(xml_attribute attr, xml_node parent) { namespace_uri_predicate pred = attr.name(); @@ -8537,12 +8733,12 @@ PUGI__NS_BEGIN return PUGIXML_TEXT(""); } - PUGI__FN const char_t* namespace_uri(const xpath_node& node) + PUGI_IMPL_FN const char_t* namespace_uri(const xpath_node& node) { return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node()); } - PUGI__FN char_t* normalize_space(char_t* buffer) + PUGI_IMPL_FN char_t* normalize_space(char_t* buffer) { char_t* write = buffer; @@ -8550,10 +8746,10 @@ PUGI__NS_BEGIN { char_t ch = *it++; - if (PUGI__IS_CHARTYPE(ch, ct_space)) + if (PUGI_IMPL_IS_CHARTYPE(ch, ct_space)) { // replace whitespace sequence with single space - while (PUGI__IS_CHARTYPE(*it, ct_space)) it++; + while (PUGI_IMPL_IS_CHARTYPE(*it, ct_space)) it++; // avoid leading spaces if (write != buffer) *write++ = ' '; @@ -8562,7 +8758,7 @@ PUGI__NS_BEGIN } // remove trailing space - if (write != buffer && PUGI__IS_CHARTYPE(write[-1], ct_space)) write--; + if (write != buffer && PUGI_IMPL_IS_CHARTYPE(write[-1], ct_space)) write--; // zero-terminate *write = 0; @@ -8570,13 +8766,13 @@ PUGI__NS_BEGIN return write; } - PUGI__FN char_t* translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length) + PUGI_IMPL_FN char_t* translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length) { char_t* write = buffer; while (*buffer) { - PUGI__DMC_VOLATILE char_t ch = *buffer++; + PUGI_IMPL_DMC_VOLATILE char_t ch = *buffer++; const char_t* pos = find_char(from, ch); @@ -8592,7 +8788,7 @@ PUGI__NS_BEGIN return write; } - PUGI__FN unsigned char* translate_table_generate(xpath_allocator* alloc, const char_t* from, const char_t* to) + PUGI_IMPL_FN unsigned char* translate_table_generate(xpath_allocator* alloc, const char_t* from, const char_t* to) { unsigned char table[128] = {0}; @@ -8624,7 +8820,7 @@ PUGI__NS_BEGIN return static_cast(result); } - PUGI__FN char_t* translate_table(char_t* buffer, const unsigned char* table) + PUGI_IMPL_FN char_t* translate_table(char_t* buffer, const unsigned char* table) { char_t* write = buffer; @@ -8706,7 +8902,7 @@ PUGI__NS_BEGIN static const xpath_node_set dummy_node_set; - PUGI__FN PUGI__UNSIGNED_OVERFLOW unsigned int hash_string(const char_t* str) + PUGI_IMPL_FN PUGI_IMPL_UNSIGNED_OVERFLOW unsigned int hash_string(const char_t* str) { // Jenkins one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time) unsigned int result = 0; @@ -8725,7 +8921,7 @@ PUGI__NS_BEGIN return result; } - template PUGI__FN T* new_xpath_variable(const char_t* name) + template PUGI_IMPL_FN T* new_xpath_variable(const char_t* name) { size_t length = strlength(name); if (length == 0) return 0; // empty variable names are invalid @@ -8741,7 +8937,7 @@ PUGI__NS_BEGIN return result; } - PUGI__FN xpath_variable* new_xpath_variable(xpath_value_type type, const char_t* name) + PUGI_IMPL_FN xpath_variable* new_xpath_variable(xpath_value_type type, const char_t* name) { switch (type) { @@ -8762,13 +8958,13 @@ PUGI__NS_BEGIN } } - template PUGI__FN void delete_xpath_variable(T* var) + template PUGI_IMPL_FN void delete_xpath_variable(T* var) { var->~T(); xml_memory::deallocate(var); } - PUGI__FN void delete_xpath_variable(xpath_value_type type, xpath_variable* var) + PUGI_IMPL_FN void delete_xpath_variable(xpath_value_type type, xpath_variable* var) { switch (type) { @@ -8793,7 +8989,7 @@ PUGI__NS_BEGIN } } - PUGI__FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs) + PUGI_IMPL_FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs) { switch (rhs->type()) { @@ -8815,7 +9011,7 @@ PUGI__NS_BEGIN } } - PUGI__FN bool get_variable_scratch(char_t (&buffer)[32], xpath_variable_set* set, const char_t* begin, const char_t* end, xpath_variable** out_result) + PUGI_IMPL_FN bool get_variable_scratch(char_t (&buffer)[32], xpath_variable_set* set, const char_t* begin, const char_t* end, xpath_variable** out_result) { size_t length = static_cast(end - begin); char_t* scratch = buffer; @@ -8838,11 +9034,11 @@ PUGI__NS_BEGIN return true; } -PUGI__NS_END +PUGI_IMPL_NS_END // Internal node set class -PUGI__NS_BEGIN - PUGI__FN xpath_node_set::type_t xpath_get_order(const xpath_node* begin, const xpath_node* end) +PUGI_IMPL_NS_BEGIN + PUGI_IMPL_FN xpath_node_set::type_t xpath_get_order(const xpath_node* begin, const xpath_node* end) { if (end - begin < 2) return xpath_node_set::type_sorted; @@ -8858,7 +9054,7 @@ PUGI__NS_BEGIN return first ? xpath_node_set::type_sorted : xpath_node_set::type_sorted_reverse; } - PUGI__FN xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool rev) + PUGI_IMPL_FN xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool rev) { xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; @@ -8881,7 +9077,7 @@ PUGI__NS_BEGIN return order; } - PUGI__FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type) + PUGI_IMPL_FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type) { if (begin == end) return xpath_node(); @@ -9035,7 +9231,7 @@ PUGI__NS_BEGIN } }; - PUGI__FN_NO_INLINE void xpath_node_set_raw::push_back_grow(const xpath_node& node, xpath_allocator* alloc) + PUGI_IMPL_FN_NO_INLINE void xpath_node_set_raw::push_back_grow(const xpath_node& node, xpath_allocator* alloc) { size_t capacity = static_cast(_eos - _begin); @@ -9054,9 +9250,9 @@ PUGI__NS_BEGIN // push *_end++ = node; } -PUGI__NS_END +PUGI_IMPL_NS_END -PUGI__NS_BEGIN +PUGI_IMPL_NS_BEGIN struct xpath_context { xpath_node n; @@ -9138,7 +9334,7 @@ PUGI__NS_BEGIN { const char_t* cur = _cur; - while (PUGI__IS_CHARTYPE(*cur, ct_space)) ++cur; + while (PUGI_IMPL_IS_CHARTYPE(*cur, ct_space)) ++cur; // save lexeme position for error reporting _cur_lexeme_pos = cur; @@ -9220,17 +9416,17 @@ PUGI__NS_BEGIN case '$': cur += 1; - if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) + if (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_start_symbol)) { _cur_lexeme_contents.begin = cur; - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + while (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_symbol)) cur++; - if (cur[0] == ':' && PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // qname + if (cur[0] == ':' && PUGI_IMPL_IS_CHARTYPEX(cur[1], ctx_symbol)) // qname { cur++; // : - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + while (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_symbol)) cur++; } _cur_lexeme_contents.end = cur; @@ -9293,13 +9489,13 @@ PUGI__NS_BEGIN cur += 2; _cur_lexeme = lex_double_dot; } - else if (PUGI__IS_CHARTYPEX(*(cur+1), ctx_digit)) + else if (PUGI_IMPL_IS_CHARTYPEX(*(cur+1), ctx_digit)) { _cur_lexeme_contents.begin = cur; // . ++cur; - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + while (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_digit)) cur++; _cur_lexeme_contents.end = cur; @@ -9353,28 +9549,28 @@ PUGI__NS_BEGIN break; default: - if (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) + if (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_digit)) { _cur_lexeme_contents.begin = cur; - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + while (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_digit)) cur++; if (*cur == '.') { cur++; - while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + while (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_digit)) cur++; } _cur_lexeme_contents.end = cur; _cur_lexeme = lex_number; } - else if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) + else if (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_start_symbol)) { _cur_lexeme_contents.begin = cur; - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + while (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_symbol)) cur++; if (cur[0] == ':') { @@ -9382,11 +9578,11 @@ PUGI__NS_BEGIN { cur += 2; // :* } - else if (PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // namespace test qname + else if (PUGI_IMPL_IS_CHARTYPEX(cur[1], ctx_symbol)) // namespace test qname { cur++; // : - while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + while (PUGI_IMPL_IS_CHARTYPEX(*cur, ctx_symbol)) cur++; } } @@ -9798,7 +9994,8 @@ PUGI__NS_BEGIN xpath_node* last = ns.begin() + first; - xpath_context c(xpath_node(), 1, size); + xpath_node cn; + xpath_context c(cn, 1, size); double er = expr->eval_number(c, stack); @@ -9885,7 +10082,7 @@ PUGI__NS_BEGIN { assert(n); - xml_node_type type = PUGI__NODETYPE(n); + xml_node_type type = PUGI_IMPL_NODETYPE(n); switch (_test) { @@ -11908,7 +12105,7 @@ PUGI__NS_BEGIN // This is either a function call, or not - if not, we shall proceed with location path const char_t* state = _lexer.state(); - while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state; + while (PUGI_IMPL_IS_CHARTYPE(*state, ct_space)) ++state; if (*state != '(') return parse_location_path(); @@ -12151,7 +12348,7 @@ PUGI__NS_BEGIN bool oom; }; - PUGI__FN impl::xpath_ast_node* evaluate_node_set_prepare(xpath_query_impl* impl) + PUGI_IMPL_FN impl::xpath_ast_node* evaluate_node_set_prepare(xpath_query_impl* impl) { if (!impl) return 0; @@ -12169,91 +12366,91 @@ PUGI__NS_BEGIN return impl->root; } -PUGI__NS_END +PUGI_IMPL_NS_END namespace pugi { #ifndef PUGIXML_NO_EXCEPTIONS - PUGI__FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_) + PUGI_IMPL_FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_) { assert(_result.error); } - PUGI__FN const char* xpath_exception::what() const throw() + PUGI_IMPL_FN const char* xpath_exception::what() const throw() { return _result.error; } - PUGI__FN const xpath_parse_result& xpath_exception::result() const + PUGI_IMPL_FN const xpath_parse_result& xpath_exception::result() const { return _result; } #endif - PUGI__FN xpath_node::xpath_node() + PUGI_IMPL_FN xpath_node::xpath_node() { } - PUGI__FN xpath_node::xpath_node(const xml_node& node_): _node(node_) + PUGI_IMPL_FN xpath_node::xpath_node(const xml_node& node_): _node(node_) { } - PUGI__FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_) + PUGI_IMPL_FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_) { } - PUGI__FN xml_node xpath_node::node() const + PUGI_IMPL_FN xml_node xpath_node::node() const { return _attribute ? xml_node() : _node; } - PUGI__FN xml_attribute xpath_node::attribute() const + PUGI_IMPL_FN xml_attribute xpath_node::attribute() const { return _attribute; } - PUGI__FN xml_node xpath_node::parent() const + PUGI_IMPL_FN xml_node xpath_node::parent() const { return _attribute ? _node : _node.parent(); } - PUGI__FN static void unspecified_bool_xpath_node(xpath_node***) + PUGI_IMPL_FN static void unspecified_bool_xpath_node(xpath_node***) { } - PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type() const + PUGI_IMPL_FN xpath_node::operator xpath_node::unspecified_bool_type() const { return (_node || _attribute) ? unspecified_bool_xpath_node : 0; } - PUGI__FN bool xpath_node::operator!() const + PUGI_IMPL_FN bool xpath_node::operator!() const { return !(_node || _attribute); } - PUGI__FN bool xpath_node::operator==(const xpath_node& n) const + PUGI_IMPL_FN bool xpath_node::operator==(const xpath_node& n) const { return _node == n._node && _attribute == n._attribute; } - PUGI__FN bool xpath_node::operator!=(const xpath_node& n) const + PUGI_IMPL_FN bool xpath_node::operator!=(const xpath_node& n) const { return _node != n._node || _attribute != n._attribute; } #ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xpath_node& lhs, bool rhs) + PUGI_IMPL_FN bool operator&&(const xpath_node& lhs, bool rhs) { return (bool)lhs && rhs; } - PUGI__FN bool operator||(const xpath_node& lhs, bool rhs) + PUGI_IMPL_FN bool operator||(const xpath_node& lhs, bool rhs) { return (bool)lhs || rhs; } #endif - PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_, type_t type_) + PUGI_IMPL_FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_, type_t type_) { assert(begin_ <= end_); @@ -12285,7 +12482,7 @@ namespace pugi } #ifdef PUGIXML_HAS_MOVE - PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs) PUGIXML_NOEXCEPT + PUGI_IMPL_FN void xpath_node_set::_move(xpath_node_set& rhs) PUGIXML_NOEXCEPT { _type = rhs._type; _storage[0] = rhs._storage[0]; @@ -12298,27 +12495,27 @@ namespace pugi } #endif - PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(_storage), _end(_storage) + PUGI_IMPL_FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(_storage), _end(_storage) { } - PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_unsorted), _begin(_storage), _end(_storage) + PUGI_IMPL_FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_unsorted), _begin(_storage), _end(_storage) { _assign(begin_, end_, type_); } - PUGI__FN xpath_node_set::~xpath_node_set() + PUGI_IMPL_FN xpath_node_set::~xpath_node_set() { if (_begin != _storage) impl::xml_memory::deallocate(_begin); } - PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(_storage), _end(_storage) + PUGI_IMPL_FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(_storage), _end(_storage) { _assign(ns._begin, ns._end, ns._type); } - PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) + PUGI_IMPL_FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) { if (this == &ns) return *this; @@ -12328,12 +12525,12 @@ namespace pugi } #ifdef PUGIXML_HAS_MOVE - PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT: _type(type_unsorted), _begin(_storage), _end(_storage) + PUGI_IMPL_FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT: _type(type_unsorted), _begin(_storage), _end(_storage) { _move(rhs); } - PUGI__FN xpath_node_set& xpath_node_set::operator=(xpath_node_set&& rhs) PUGIXML_NOEXCEPT + PUGI_IMPL_FN xpath_node_set& xpath_node_set::operator=(xpath_node_set&& rhs) PUGIXML_NOEXCEPT { if (this == &rhs) return *this; @@ -12346,66 +12543,66 @@ namespace pugi } #endif - PUGI__FN xpath_node_set::type_t xpath_node_set::type() const + PUGI_IMPL_FN xpath_node_set::type_t xpath_node_set::type() const { return _type; } - PUGI__FN size_t xpath_node_set::size() const + PUGI_IMPL_FN size_t xpath_node_set::size() const { return _end - _begin; } - PUGI__FN bool xpath_node_set::empty() const + PUGI_IMPL_FN bool xpath_node_set::empty() const { return _begin == _end; } - PUGI__FN const xpath_node& xpath_node_set::operator[](size_t index) const + PUGI_IMPL_FN const xpath_node& xpath_node_set::operator[](size_t index) const { assert(index < size()); return _begin[index]; } - PUGI__FN xpath_node_set::const_iterator xpath_node_set::begin() const + PUGI_IMPL_FN xpath_node_set::const_iterator xpath_node_set::begin() const { return _begin; } - PUGI__FN xpath_node_set::const_iterator xpath_node_set::end() const + PUGI_IMPL_FN xpath_node_set::const_iterator xpath_node_set::end() const { return _end; } - PUGI__FN void xpath_node_set::sort(bool reverse) + PUGI_IMPL_FN void xpath_node_set::sort(bool reverse) { _type = impl::xpath_sort(_begin, _end, _type, reverse); } - PUGI__FN xpath_node xpath_node_set::first() const + PUGI_IMPL_FN xpath_node xpath_node_set::first() const { return impl::xpath_first(_begin, _end, _type); } - PUGI__FN xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0) + PUGI_IMPL_FN xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0) { } - PUGI__FN xpath_parse_result::operator bool() const + PUGI_IMPL_FN xpath_parse_result::operator bool() const { return error == 0; } - PUGI__FN const char* xpath_parse_result::description() const + PUGI_IMPL_FN const char* xpath_parse_result::description() const { return error ? error : "No error"; } - PUGI__FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(0) + PUGI_IMPL_FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(0) { } - PUGI__FN const char_t* xpath_variable::name() const + PUGI_IMPL_FN const char_t* xpath_variable::name() const { switch (_type) { @@ -12427,33 +12624,33 @@ namespace pugi } } - PUGI__FN xpath_value_type xpath_variable::type() const + PUGI_IMPL_FN xpath_value_type xpath_variable::type() const { return _type; } - PUGI__FN bool xpath_variable::get_boolean() const + PUGI_IMPL_FN bool xpath_variable::get_boolean() const { return (_type == xpath_type_boolean) ? static_cast(this)->value : false; } - PUGI__FN double xpath_variable::get_number() const + PUGI_IMPL_FN double xpath_variable::get_number() const { return (_type == xpath_type_number) ? static_cast(this)->value : impl::gen_nan(); } - PUGI__FN const char_t* xpath_variable::get_string() const + PUGI_IMPL_FN const char_t* xpath_variable::get_string() const { const char_t* value = (_type == xpath_type_string) ? static_cast(this)->value : 0; return value ? value : PUGIXML_TEXT(""); } - PUGI__FN const xpath_node_set& xpath_variable::get_node_set() const + PUGI_IMPL_FN const xpath_node_set& xpath_variable::get_node_set() const { return (_type == xpath_type_node_set) ? static_cast(this)->value : impl::dummy_node_set; } - PUGI__FN bool xpath_variable::set(bool value) + PUGI_IMPL_FN bool xpath_variable::set(bool value) { if (_type != xpath_type_boolean) return false; @@ -12461,7 +12658,7 @@ namespace pugi return true; } - PUGI__FN bool xpath_variable::set(double value) + PUGI_IMPL_FN bool xpath_variable::set(double value) { if (_type != xpath_type_number) return false; @@ -12469,7 +12666,7 @@ namespace pugi return true; } - PUGI__FN bool xpath_variable::set(const char_t* value) + PUGI_IMPL_FN bool xpath_variable::set(const char_t* value) { if (_type != xpath_type_string) return false; @@ -12490,7 +12687,7 @@ namespace pugi return true; } - PUGI__FN bool xpath_variable::set(const xpath_node_set& value) + PUGI_IMPL_FN bool xpath_variable::set(const xpath_node_set& value) { if (_type != xpath_type_node_set) return false; @@ -12498,19 +12695,19 @@ namespace pugi return true; } - PUGI__FN xpath_variable_set::xpath_variable_set() + PUGI_IMPL_FN xpath_variable_set::xpath_variable_set() { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) _data[i] = 0; } - PUGI__FN xpath_variable_set::~xpath_variable_set() + PUGI_IMPL_FN xpath_variable_set::~xpath_variable_set() { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) _destroy(_data[i]); } - PUGI__FN xpath_variable_set::xpath_variable_set(const xpath_variable_set& rhs) + PUGI_IMPL_FN xpath_variable_set::xpath_variable_set(const xpath_variable_set& rhs) { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) _data[i] = 0; @@ -12518,7 +12715,7 @@ namespace pugi _assign(rhs); } - PUGI__FN xpath_variable_set& xpath_variable_set::operator=(const xpath_variable_set& rhs) + PUGI_IMPL_FN xpath_variable_set& xpath_variable_set::operator=(const xpath_variable_set& rhs) { if (this == &rhs) return *this; @@ -12528,7 +12725,7 @@ namespace pugi } #ifdef PUGIXML_HAS_MOVE - PUGI__FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT + PUGI_IMPL_FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) { @@ -12537,7 +12734,7 @@ namespace pugi } } - PUGI__FN xpath_variable_set& xpath_variable_set::operator=(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT + PUGI_IMPL_FN xpath_variable_set& xpath_variable_set::operator=(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) { @@ -12551,7 +12748,7 @@ namespace pugi } #endif - PUGI__FN void xpath_variable_set::_assign(const xpath_variable_set& rhs) + PUGI_IMPL_FN void xpath_variable_set::_assign(const xpath_variable_set& rhs) { xpath_variable_set temp; @@ -12562,7 +12759,7 @@ namespace pugi _swap(temp); } - PUGI__FN void xpath_variable_set::_swap(xpath_variable_set& rhs) + PUGI_IMPL_FN void xpath_variable_set::_swap(xpath_variable_set& rhs) { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) { @@ -12573,7 +12770,7 @@ namespace pugi } } - PUGI__FN xpath_variable* xpath_variable_set::_find(const char_t* name) const + PUGI_IMPL_FN xpath_variable* xpath_variable_set::_find(const char_t* name) const { const size_t hash_size = sizeof(_data) / sizeof(_data[0]); size_t hash = impl::hash_string(name) % hash_size; @@ -12586,7 +12783,7 @@ namespace pugi return 0; } - PUGI__FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result) + PUGI_IMPL_FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result) { xpath_variable* last = 0; @@ -12613,7 +12810,7 @@ namespace pugi return true; } - PUGI__FN void xpath_variable_set::_destroy(xpath_variable* var) + PUGI_IMPL_FN void xpath_variable_set::_destroy(xpath_variable* var) { while (var) { @@ -12625,7 +12822,7 @@ namespace pugi } } - PUGI__FN xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type) + PUGI_IMPL_FN xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type) { const size_t hash_size = sizeof(_data) / sizeof(_data[0]); size_t hash = impl::hash_string(name) % hash_size; @@ -12648,41 +12845,41 @@ namespace pugi return result; } - PUGI__FN bool xpath_variable_set::set(const char_t* name, bool value) + PUGI_IMPL_FN bool xpath_variable_set::set(const char_t* name, bool value) { xpath_variable* var = add(name, xpath_type_boolean); return var ? var->set(value) : false; } - PUGI__FN bool xpath_variable_set::set(const char_t* name, double value) + PUGI_IMPL_FN bool xpath_variable_set::set(const char_t* name, double value) { xpath_variable* var = add(name, xpath_type_number); return var ? var->set(value) : false; } - PUGI__FN bool xpath_variable_set::set(const char_t* name, const char_t* value) + PUGI_IMPL_FN bool xpath_variable_set::set(const char_t* name, const char_t* value) { xpath_variable* var = add(name, xpath_type_string); return var ? var->set(value) : false; } - PUGI__FN bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value) + PUGI_IMPL_FN bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value) { xpath_variable* var = add(name, xpath_type_node_set); return var ? var->set(value) : false; } - PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name) + PUGI_IMPL_FN xpath_variable* xpath_variable_set::get(const char_t* name) { return _find(name); } - PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const + PUGI_IMPL_FN const xpath_variable* xpath_variable_set::get(const char_t* name) const { return _find(name); } - PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) + PUGI_IMPL_FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) { impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create(); @@ -12720,18 +12917,18 @@ namespace pugi } } - PUGI__FN xpath_query::xpath_query(): _impl(0) + PUGI_IMPL_FN xpath_query::xpath_query(): _impl(0) { } - PUGI__FN xpath_query::~xpath_query() + PUGI_IMPL_FN xpath_query::~xpath_query() { if (_impl) impl::xpath_query_impl::destroy(static_cast(_impl)); } #ifdef PUGIXML_HAS_MOVE - PUGI__FN xpath_query::xpath_query(xpath_query&& rhs) PUGIXML_NOEXCEPT + PUGI_IMPL_FN xpath_query::xpath_query(xpath_query&& rhs) PUGIXML_NOEXCEPT { _impl = rhs._impl; _result = rhs._result; @@ -12739,7 +12936,7 @@ namespace pugi rhs._result = xpath_parse_result(); } - PUGI__FN xpath_query& xpath_query::operator=(xpath_query&& rhs) PUGIXML_NOEXCEPT + PUGI_IMPL_FN xpath_query& xpath_query::operator=(xpath_query&& rhs) PUGIXML_NOEXCEPT { if (this == &rhs) return *this; @@ -12755,14 +12952,14 @@ namespace pugi } #endif - PUGI__FN xpath_value_type xpath_query::return_type() const + PUGI_IMPL_FN xpath_value_type xpath_query::return_type() const { if (!_impl) return xpath_type_none; return static_cast(_impl)->root->rettype(); } - PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const + PUGI_IMPL_FN bool xpath_query::evaluate_boolean(const xpath_node& n) const { if (!_impl) return false; @@ -12783,7 +12980,7 @@ namespace pugi return r; } - PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const + PUGI_IMPL_FN double xpath_query::evaluate_number(const xpath_node& n) const { if (!_impl) return impl::gen_nan(); @@ -12805,7 +13002,7 @@ namespace pugi } #ifndef PUGIXML_NO_STL - PUGI__FN string_t xpath_query::evaluate_string(const xpath_node& n) const + PUGI_IMPL_FN string_t xpath_query::evaluate_string(const xpath_node& n) const { if (!_impl) return string_t(); @@ -12827,7 +13024,7 @@ namespace pugi } #endif - PUGI__FN size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const + PUGI_IMPL_FN size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const { impl::xpath_context c(n, 1, 1); impl::xpath_stack_data sd; @@ -12857,7 +13054,7 @@ namespace pugi return full_size; } - PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const + PUGI_IMPL_FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const { impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast(_impl)); if (!root) return xpath_node_set(); @@ -12879,7 +13076,7 @@ namespace pugi return xpath_node_set(r.begin(), r.end(), r.type()); } - PUGI__FN xpath_node xpath_query::evaluate_node(const xpath_node& n) const + PUGI_IMPL_FN xpath_node xpath_query::evaluate_node(const xpath_node& n) const { impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast(_impl)); if (!root) return xpath_node(); @@ -12901,54 +13098,54 @@ namespace pugi return r.first(); } - PUGI__FN const xpath_parse_result& xpath_query::result() const + PUGI_IMPL_FN const xpath_parse_result& xpath_query::result() const { return _result; } - PUGI__FN static void unspecified_bool_xpath_query(xpath_query***) + PUGI_IMPL_FN static void unspecified_bool_xpath_query(xpath_query***) { } - PUGI__FN xpath_query::operator xpath_query::unspecified_bool_type() const + PUGI_IMPL_FN xpath_query::operator xpath_query::unspecified_bool_type() const { return _impl ? unspecified_bool_xpath_query : 0; } - PUGI__FN bool xpath_query::operator!() const + PUGI_IMPL_FN bool xpath_query::operator!() const { return !_impl; } - PUGI__FN xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables) const + PUGI_IMPL_FN xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables) const { xpath_query q(query, variables); return q.evaluate_node(*this); } - PUGI__FN xpath_node xml_node::select_node(const xpath_query& query) const + PUGI_IMPL_FN xpath_node xml_node::select_node(const xpath_query& query) const { return query.evaluate_node(*this); } - PUGI__FN xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const + PUGI_IMPL_FN xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const { xpath_query q(query, variables); return q.evaluate_node_set(*this); } - PUGI__FN xpath_node_set xml_node::select_nodes(const xpath_query& query) const + PUGI_IMPL_FN xpath_node_set xml_node::select_nodes(const xpath_query& query) const { return query.evaluate_node_set(*this); } - PUGI__FN xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const + PUGI_IMPL_FN xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const { xpath_query q(query, variables); return q.evaluate_node(*this); } - PUGI__FN xpath_node xml_node::select_single_node(const xpath_query& query) const + PUGI_IMPL_FN xpath_node xml_node::select_single_node(const xpath_query& query) const { return query.evaluate_node(*this); } @@ -12971,40 +13168,40 @@ namespace pugi #endif // Undefine all local macros (makes sure we're not leaking macros in header-only mode) -#undef PUGI__NO_INLINE -#undef PUGI__UNLIKELY -#undef PUGI__STATIC_ASSERT -#undef PUGI__DMC_VOLATILE -#undef PUGI__UNSIGNED_OVERFLOW -#undef PUGI__MSVC_CRT_VERSION -#undef PUGI__SNPRINTF -#undef PUGI__NS_BEGIN -#undef PUGI__NS_END -#undef PUGI__FN -#undef PUGI__FN_NO_INLINE -#undef PUGI__GETHEADER_IMPL -#undef PUGI__GETPAGE_IMPL -#undef PUGI__GETPAGE -#undef PUGI__NODETYPE -#undef PUGI__IS_CHARTYPE_IMPL -#undef PUGI__IS_CHARTYPE -#undef PUGI__IS_CHARTYPEX -#undef PUGI__ENDSWITH -#undef PUGI__SKIPWS -#undef PUGI__OPTSET -#undef PUGI__PUSHNODE -#undef PUGI__POPNODE -#undef PUGI__SCANFOR -#undef PUGI__SCANWHILE -#undef PUGI__SCANWHILE_UNROLL -#undef PUGI__ENDSEG -#undef PUGI__THROW_ERROR -#undef PUGI__CHECK_ERROR +#undef PUGI_IMPL_NO_INLINE +#undef PUGI_IMPL_UNLIKELY +#undef PUGI_IMPL_STATIC_ASSERT +#undef PUGI_IMPL_DMC_VOLATILE +#undef PUGI_IMPL_UNSIGNED_OVERFLOW +#undef PUGI_IMPL_MSVC_CRT_VERSION +#undef PUGI_IMPL_SNPRINTF +#undef PUGI_IMPL_NS_BEGIN +#undef PUGI_IMPL_NS_END +#undef PUGI_IMPL_FN +#undef PUGI_IMPL_FN_NO_INLINE +#undef PUGI_IMPL_GETHEADER_IMPL +#undef PUGI_IMPL_GETPAGE_IMPL +#undef PUGI_IMPL_GETPAGE +#undef PUGI_IMPL_NODETYPE +#undef PUGI_IMPL_IS_CHARTYPE_IMPL +#undef PUGI_IMPL_IS_CHARTYPE +#undef PUGI_IMPL_IS_CHARTYPEX +#undef PUGI_IMPL_ENDSWITH +#undef PUGI_IMPL_SKIPWS +#undef PUGI_IMPL_OPTSET +#undef PUGI_IMPL_PUSHNODE +#undef PUGI_IMPL_POPNODE +#undef PUGI_IMPL_SCANFOR +#undef PUGI_IMPL_SCANWHILE +#undef PUGI_IMPL_SCANWHILE_UNROLL +#undef PUGI_IMPL_ENDSEG +#undef PUGI_IMPL_THROW_ERROR +#undef PUGI_IMPL_CHECK_ERROR #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2023 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/src/pugixml.hpp b/src/pugixml.hpp index 579f143990..d17a7e6930 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1,7 +1,7 @@ /** - * pugixml parser - version 1.12 + * pugixml parser - version 1.14 * -------------------------------------------------------- - * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2006-2023, 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 @@ -14,7 +14,7 @@ // 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 PUGIXML_VERSION 1120 // 1.12 +# define PUGIXML_VERSION 1140 // 1.14 #endif // Include user configuration file (this can define various configuration macros) @@ -115,6 +115,8 @@ #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 @@ -210,6 +212,10 @@ namespace pugi // 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; + + // This flag determines whether determines whether the the two pcdata should be merged or not, if no intermediatory data are parsed in the document. + // This flag is off by default. + const unsigned int parse_merge_pcdata = 0x4000; // The default parsing mode. // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, @@ -322,7 +328,7 @@ namespace pugi class PUGIXML_CLASS xml_writer { public: - virtual ~xml_writer() {} + virtual ~xml_writer(); // Write memory chunk into stream/file/whatever virtual void write(const void* data, size_t size) = 0; @@ -416,7 +422,9 @@ 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_name(const char_t* rhs, size_t size); bool set_value(const char_t* rhs); + bool set_value(const char_t* rhs, size_t size); // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") bool set_value(int rhs); @@ -550,7 +558,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_name(const char_t* rhs, size_t size); bool set_value(const char_t* rhs); + bool set_value(const char_t* rhs, size_t size); // Add attribute with specified name. Returns added attribute, or empty attribute on errors. xml_attribute append_attribute(const char_t* name); @@ -708,9 +718,12 @@ namespace pugi // Range-based for support xml_object_range children() const; - xml_object_range children(const char_t* name) const; xml_object_range attributes() const; + // Range-based for support for all children with the specified name + // Note: name pointer must have a longer lifetime than the returned object; be careful with passing temporaries! + xml_object_range children(const char_t* name) const; + // Get node offset in parsed file/string (in char_t units) for debugging purposes ptrdiff_t offset_debug() const; @@ -776,6 +789,7 @@ namespace pugi // Set text (returns false if object is empty or there is not enough memory) bool set(const char_t* rhs); + bool set(const char_t* rhs, size_t size); // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") bool set(int rhs); @@ -922,6 +936,7 @@ namespace pugi xml_named_node_iterator(); // Construct an iterator which points to the specified node + // Note: name pointer is stored in the iterator and must have a longer lifetime than iterator itself xml_named_node_iterator(const xml_node& node, const char_t* name); // Iterator operators @@ -1476,7 +1491,7 @@ namespace std #endif /** - * Copyright (c) 2006-2022 Arseny Kapoulkine + * Copyright (c) 2006-2023 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation