diff options
-rw-r--r-- | src/pugixml.cpp | 49 | ||||
-rw-r--r-- | src/pugixml.hpp | 2 |
2 files changed, 42 insertions, 9 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 3979eb9..8af8dab 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1,3 +1,4 @@ +#pragma pack(push, 16) /** * pugixml parser - version 1.4 * -------------------------------------------------------- @@ -539,13 +540,15 @@ PUGI__NS_BEGIN struct xml_document_struct: public xml_node_struct, public xml_allocator { - xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0) + xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0), document_buffer_order_valid(true) { } const char_t* buffer; xml_extra_buffer* extra_buffers; + + bool document_buffer_order_valid; }; inline xml_allocator& get_allocator(const xml_node_struct* node) @@ -554,6 +557,13 @@ PUGI__NS_BEGIN return *reinterpret_cast<xml_memory_page*>(node->header & xml_memory_page_pointer_mask)->allocator; } + + template <typename Object> inline xml_document_struct& get_document(const Object* object) + { + assert(object); + + return *static_cast<xml_document_struct*>(reinterpret_cast<xml_memory_page*>(object->header & xml_memory_page_pointer_mask)->allocator); + } PUGI__NS_END // Low-level DOM operations @@ -5038,6 +5048,9 @@ namespace pugi { if (!impl::allow_move(*this, moved)) return xml_node(); + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).document_buffer_order_valid = false; + impl::remove_node(moved._root); impl::append_node(moved._root, _root); @@ -5048,6 +5061,9 @@ namespace pugi { if (!impl::allow_move(*this, moved)) return xml_node(); + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).document_buffer_order_valid = false; + impl::remove_node(moved._root); impl::prepend_node(moved._root, _root); @@ -5060,6 +5076,9 @@ namespace pugi if (!node._root || node._root->parent != _root) return xml_node(); if (moved._root == node._root) return xml_node(); + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).document_buffer_order_valid = false; + impl::remove_node(moved._root); impl::insert_node_after(moved._root, node._root); @@ -5072,6 +5091,9 @@ namespace pugi if (!node._root || node._root->parent != _root) return xml_node(); if (moved._root == node._root) return xml_node(); + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).document_buffer_order_valid = false; + impl::remove_node(moved._root); impl::insert_node_before(moved._root, node._root); @@ -5129,6 +5151,9 @@ namespace pugi // get document node impl::xml_document_struct* doc = static_cast<impl::xml_document_struct*>(root()._root); assert(doc); + + // disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense + doc->document_buffer_order_valid = false; // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later) impl::xml_memory_page* page = 0; @@ -6842,14 +6867,18 @@ PUGI__NS_BEGIN return parent && node == parent; } - PUGI__FN const void* document_order(const xpath_node& xnode) + PUGI__FN const void* document_buffer_order(const xpath_node& xnode) { xml_node_struct* node = xnode.node().internal_object(); if (node) { - if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return node->name; - if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return node->value; + if (get_document(node).document_buffer_order_valid) + { + if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return node->name; + if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return node->value; + } + return 0; } @@ -6857,8 +6886,12 @@ PUGI__NS_BEGIN if (attr) { - if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return attr->name; - if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return attr->value; + if (get_document(attr).document_buffer_order_valid) + { + if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return attr->name; + if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return attr->value; + } + return 0; } @@ -6870,8 +6903,8 @@ PUGI__NS_BEGIN bool operator()(const xpath_node& lhs, const xpath_node& rhs) const { // optimized document order based check - const void* lo = document_order(lhs); - const void* ro = document_order(rhs); + const void* lo = document_buffer_order(lhs); + const void* ro = document_buffer_order(rhs); if (lo && ro) return lo < ro; diff --git a/src/pugixml.hpp b/src/pugixml.hpp index ba480cd..28b7aa3 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -926,7 +926,7 @@ namespace pugi private: char_t* _buffer; - // sizeof(xml_memory_page) + sizeof(xml_document_struct) + xml_memory_page_alignment + 1 void* in case compiler inserts padding + // sizeof(xml_memory_page) + sizeof(xml_document_struct) + xml_memory_page_alignment char _memory[sizeof(void*) * 20 + 64]; // Non-copyable semantics |