summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pugixml.cpp49
-rw-r--r--src/pugixml.hpp2
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