diff --git a/thirdparty/pugixml/pugixml/src/pugiconfig.hpp b/thirdparty/pugixml/pugixml/src/pugiconfig.hpp index 0713b0efbb..3dc839da6e 100644 --- a/thirdparty/pugixml/pugixml/src/pugiconfig.hpp +++ b/thirdparty/pugixml/pugixml/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/thirdparty/pugixml/pugixml/src/pugixml.cpp b/thirdparty/pugixml/pugixml/src/pugixml.cpp index 60b55da3ab..89123c75d0 100644 --- a/thirdparty/pugixml/pugixml/src/pugixml.cpp +++ b/thirdparty/pugixml/pugixml/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 <new> +// For load_file +#if defined(__linux__) || defined(__APPLE__) +#include <sys/stat.h> +#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 <typename T> deallocation_function xml_memory_management_function_storage<T>::deallocate = default_deallocate; typedef xml_memory_management_function_storage<int> 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<size_t>(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 <typename T> 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<unsigned int>(reinterpret_cast<uintptr_t>(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<char*>(object) - reinterpret_cast<char*>(page)) << 8) | (flags)) + #define PUGI_IMPL_GETHEADER_IMPL(object, page, flags) (((reinterpret_cast<char*>(object) - reinterpret_cast<char*>(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<impl::xml_memory_page*>(const_cast<void*>(static_cast<const void*>(reinterpret_cast<const char*>(&header) - (header >> 8)))) + #define PUGI_IMPL_GETPAGE_IMPL(header) static_cast<impl::xml_memory_page*>(const_cast<void*>(static_cast<const void*>(reinterpret_cast<const char*>(&header) - (header >> 8)))) #endif - #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header) - #define PUGI__NODETYPE(n) static_cast<xml_node_type>((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<xml_node_type>((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<char*>(_root) + sizeof(xml_memory_page) + _busy_size; @@ -564,7 +577,7 @@ PUGI__NS_BEGIN // adjust for marker ptrdiff_t offset = static_cast<char*>(result) - reinterpret_cast<char*>(out_page->compact_page_marker); - if (PUGI__UNLIKELY(static_cast<uintptr_t>(offset) >= 256 * xml_memory_block_alignment)) + if (PUGI_IMPL_UNLIKELY(static_cast<uintptr_t>(offset) >= 256 * xml_memory_block_alignment)) { // insert new marker uint32_t* marker = static_cast<uint32_t*>(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<char*>(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<char*>(this) - reinterpret_cast<char*>(page->compact_page_marker)); assert(offset % compact_alignment == 0 && static_cast<uintptr_t>(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<const compact_header*>(static_cast<const char*>(object) - header_offset); return header->get_page(); } - template <int header_offset, typename T> PUGI__FN_NO_INLINE T* compact_get_value(const void* object) + template <int header_offset, typename T> PUGI_IMPL_FN_NO_INLINE T* compact_get_value(const void* object) { return static_cast<T*>(compact_get_page(object, header_offset)->allocator->_hash->find(object)); } - template <int header_offset, typename T> PUGI__FN_NO_INLINE void compact_set_value(const void* object, T* value) + template <int header_offset, typename T> 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 <typename Object> inline xml_document_struct& get_document(const Object* object) { assert(object); - return *static_cast<xml_document_struct*>(PUGI__GETPAGE(object)->allocator); + return *static_cast<xml_document_struct*>(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<uint16_t>(((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<wchar_t>(endian_swap(static_cast<wchar_selector<sizeof(wchar_t)>::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<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct)) + #define PUGI_IMPL_IS_CHARTYPE_IMPL(c, ct, table) ((static_cast<unsigned int>(c) < 128 ? table[static_cast<unsigned int>(c)] : table[128]) & (ct)) #else - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(c)] & (ct)) + #define PUGI_IMPL_IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast<unsigned char>(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<unsigned char*>(&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<const char_t*>(contents); size_t length = size / sizeof(char_t); @@ -2104,7 +2131,7 @@ PUGI__NS_BEGIN return true; } - template <typename D> PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) + template <typename D> 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<const typename D::type*>(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 <typename D> PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) + template <typename D> 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<const typename D::type*>(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<const uint8_t*>(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<uint8_t*>(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<wchar_t> as_wide_impl(const char* str, size_t size) + PUGI_IMPL_FN std::basic_string<wchar_t> as_wide_impl(const char* str, size_t size) { const uint8_t* data = reinterpret_cast<const uint8_t*>(str); @@ -2356,12 +2383,14 @@ PUGI__NS_BEGIN } template <typename String, typename Header> - 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<char_t*>(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<char_t*>(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 == '!') // '<!...' { s = parse_exclamation(s, cursor, optmsk, endch); if (!s) return s; } - else if (*s == 0 && endch == '?') PUGI__THROW_ERROR(status_bad_pi, s); - else PUGI__THROW_ERROR(status_unrecognized_tag, s); + else if (*s == 0 && endch == '?') PUGI_IMPL_THROW_ERROR(status_bad_pi, s); + else PUGI_IMPL_THROW_ERROR(status_unrecognized_tag, s); } else { mark = s; // Save this offset while searching for a terminator. - PUGI__SKIPWS(); // Eat whitespace if no genuine PCDATA here. + PUGI_IMPL_SKIPWS(); // Eat whitespace if no genuine PCDATA here. if (*s == '<' || !*s) { // We skipped some whitespace characters because otherwise we would take the tag branch instead of PCDATA one assert(mark != s); - if (!PUGI__OPTSET(parse_ws_pcdata | parse_ws_pcdata_single) || PUGI__OPTSET(parse_trim_pcdata)) + if (!PUGI_IMPL_OPTSET(parse_ws_pcdata | parse_ws_pcdata_single) || PUGI_IMPL_OPTSET(parse_trim_pcdata)) { continue; } - else if (PUGI__OPTSET(parse_ws_pcdata_single)) + else if (PUGI_IMPL_OPTSET(parse_ws_pcdata_single)) { if (s[0] != '<' || s[1] != '/' || cursor->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 <typename D, typename T> PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T) + template <typename D, typename T> 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<const typename D::type*>(data), length, dest, T()); return static_cast<size_t>(end - dest) * sizeof(*dest); } - template <typename D, typename T> 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 <typename D, typename T> 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<const typename D::type*>(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<unsigned int>(static_cast<uint16_t>(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<size_t>(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 <typename String, typename Header> - 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 <typename U> PUGI__FN PUGI__UNSIGNED_OVERFLOW U string_to_integer(const char_t* value, U minv, U maxv) + template <typename U> 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<size_t>(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<unsigned int>(value, static_cast<unsigned int>(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<unsigned int>(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<float>(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<unsigned long long>(value, static_cast<unsigned long long>(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<unsigned long long>(value, 0, ULLONG_MAX); } #endif - template <typename U> PUGI__FN PUGI__UNSIGNED_OVERFLOW char_t* integer_to_string(char_t* begin, char_t* end, U value, bool negative) + template <typename U> 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 <typename String, typename Header> - 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 <typename U, typename String, typename Header> - 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 <typename String, typename Header> - 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 <typename String, typename Header> - 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 <typename String, typename Header> - 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<void> 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 <typename T> PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream<T>& stream, void** out_buffer, size_t* out_size) + template <typename T> PUGI_IMPL_FN xml_parse_status load_stream_data_noseek(std::basic_istream<T>& stream, void** out_buffer, size_t* out_size) { auto_deleter<xml_stream_chunk<T> > chunks(0, xml_stream_chunk<T>::destroy); @@ -4919,7 +4982,7 @@ PUGI__NS_BEGIN return status_ok; } - template <typename T> PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream<T>& stream, void** out_buffer, size_t* out_size) + template <typename T> PUGI_IMPL_FN xml_parse_status load_stream_data_seek(std::basic_istream<T>& stream, void** out_buffer, size_t* out_size) { // get length of remaining data in stream typename std::basic_istream<T>::pos_type pos = stream.tellg(); @@ -4955,7 +5018,7 @@ PUGI__NS_BEGIN return status_ok; } - template <typename T> PUGI__FN xml_parse_result load_stream_impl(xml_document_struct* doc, std::basic_istream<T>& stream, unsigned int options, xml_encoding encoding, char_t** out_buffer) + template <typename T> PUGI_IMPL_FN xml_parse_result load_stream_impl(xml_document_struct* doc, std::basic_istream<T>& 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*>(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<char, std::char_traits<char> >& stream): narrow_stream(&stream), wide_stream(0) + PUGI_IMPL_FN xml_writer_stream::xml_writer_stream(std::basic_ostream<char, std::char_traits<char> >& stream): narrow_stream(&stream), wide_stream(0) { } - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream): narrow_stream(0), wide_stream(&stream) + PUGI_IMPL_FN xml_writer_stream::xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& 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<size_t>(reinterpret_cast<uintptr_t>(_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<unsigned int>(_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<unsigned int>(_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<unsigned long>(_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<unsigned long>(_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<unsigned long long>(_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_iterator> xml_node::children() const + PUGI_IMPL_FN xml_object_range<xml_node_iterator> xml_node::children() const { return xml_object_range<xml_node_iterator>(begin(), end()); } - PUGI__FN xml_object_range<xml_named_node_iterator> xml_node::children(const char_t* name_) const + PUGI_IMPL_FN xml_object_range<xml_named_node_iterator> xml_node::children(const char_t* name_) const { return xml_object_range<xml_named_node_iterator>(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_)); } - PUGI__FN xml_object_range<xml_attribute_iterator> xml_node::attributes() const + PUGI_IMPL_FN xml_object_range<xml_attribute_iterator> xml_node::attributes() const { return xml_object_range<xml_attribute_iterator>(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<void*>(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<size_t>(path_segment_end - path_segment))) + const char_t* jname = j->name; + if (jname && impl::strequalrange(jname, path_segment, static_cast<size_t>(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<size_t>(reinterpret_cast<uintptr_t>(_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<char, std::char_traits<char> >& 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<char, std::char_traits<char> >& 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<wchar_t, std::char_traits<wchar_t> >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const + PUGI_IMPL_FN void xml_node::print(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& 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<unsigned int>(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<unsigned int>(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<unsigned long>(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<unsigned long>(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<unsigned long long>(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<xml_node*>(&_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<xml_attribute*>(&_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<xml_node*>(&_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<char*>(_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<char*>(root_page) >= _memory && reinterpret_cast<char*>(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<impl::xml_document_struct*>(_root); impl::xml_document_struct* other = static_cast<impl::xml_document_struct*>(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<char, std::char_traits<char> >& stream, unsigned int options, xml_encoding encoding) + PUGI_IMPL_FN xml_parse_result xml_document::load(std::basic_istream<char, std::char_traits<char> >& stream, unsigned int options, xml_encoding encoding) { reset(); return impl::load_stream_impl(static_cast<impl::xml_document_struct*>(_root), stream, options, encoding, &_buffer); } - PUGI__FN xml_parse_result xml_document::load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options) + PUGI_IMPL_FN xml_parse_result xml_document::load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& 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<impl::xml_document_struct*>(_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<impl::xml_document_struct*>(_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<impl::xml_document_struct*>(_root), _root, const_cast<void*>(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<impl::xml_document_struct*>(_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<impl::xml_document_struct*>(_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<char, std::char_traits<char> >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const + PUGI_IMPL_FN void xml_document::save(std::basic_ostream<char, std::char_traits<char> >& 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<wchar_t, std::char_traits<wchar_t> >& stream, const char_t* indent, unsigned int flags) const + PUGI_IMPL_FN void xml_document::save(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& 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> 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> 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<wchar_t>& str) + PUGI_IMPL_FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t>& str) { return impl::as_utf8_impl(str.c_str(), str.size()); } - PUGI__FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const char* str) + PUGI_IMPL_FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const char* str) { assert(str); return impl::as_wide_impl(str, strlen(str)); } - PUGI__FN std::basic_string<wchar_t> PUGIXML_FUNCTION as_wide(const std::string& str) + PUGI_IMPL_FN std::basic_string<wchar_t> 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 <typename T> bool operator()(const T& lhs, const T& rhs) const @@ -7443,7 +7639,7 @@ PUGI__NS_BEGIN rhs = temp; } - template <typename I, typename Pred> PUGI__FN I min_element(I begin, I end, const Pred& pred) + template <typename I, typename Pred> 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 <typename I> PUGI__FN void reverse(I begin, I end) + template <typename I> PUGI_IMPL_FN void reverse(I begin, I end) { while (end - begin > 1) swap(*begin++, *--end); } - template <typename I> PUGI__FN I unique(I begin, I end) + template <typename I> 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 <typename T, typename Pred> PUGI__FN void insertion_sort(T* begin, T* end, const Pred& pred) + template <typename T, typename Pred> 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 <typename T, typename Pred> PUGI__FN void partition3(T* begin, T* end, T pivot, const Pred& pred, T** out_eqbeg, T** out_eqend) + template <typename T, typename Pred> 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 <typename I, typename Pred> PUGI__FN void sort(I begin, I end, const Pred& pred) + template <typename I, typename Pred> 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<unsigned int>(ch - 'A') < 26 ? static_cast<char_t>(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<size_t>(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<unsigned char*>(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 <typename T> PUGI__FN T* new_xpath_variable(const char_t* name) + template <typename T> 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 <typename T> PUGI__FN void delete_xpath_variable(T* var) + template <typename T> 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<size_t>(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<size_t>(_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<const impl::xpath_variable_boolean*>(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<const impl::xpath_variable_number*>(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<const impl::xpath_variable_string*>(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<const impl::xpath_variable_node_set*>(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::xpath_query_impl*>(_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::xpath_query_impl*>(_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::xpath_query_impl*>(_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::xpath_query_impl*>(_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/thirdparty/pugixml/pugixml/src/pugixml.hpp b/thirdparty/pugixml/pugixml/src/pugixml.hpp index 579f143990..d17a7e6930 100644 --- a/thirdparty/pugixml/pugixml/src/pugixml.hpp +++ b/thirdparty/pugixml/pugixml/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<xml_node_iterator> children() const; - xml_object_range<xml_named_node_iterator> children(const char_t* name) const; xml_object_range<xml_attribute_iterator> 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<xml_named_node_iterator> 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