From e9956ae3a6593efc6f8cb344a00432ece51d1574 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 17 Nov 2014 19:52:23 -0800 Subject: Rename xml_document::load to load_string This should completely eliminate the confusion between load and load_file. Of course, for compatibility reasons we have to preserve the old variant - it will be deprecated in a future version and subsequently removed. --- src/pugixml.cpp | 7 ++++++- src/pugixml.hpp | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 884184c..852ccb9 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -5995,7 +5995,7 @@ namespace pugi } #endif - PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) + PUGI__FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options) { // Force native encoding (skip autodetection) #ifdef PUGIXML_WCHAR_MODE @@ -6007,6 +6007,11 @@ 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) + { + return load_string(contents, options); + } + PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) { reset(); diff --git a/src/pugixml.hpp b/src/pugixml.hpp index e252e16..7f52975 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -959,9 +959,12 @@ namespace pugi xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); #endif - // Load document from zero-terminated string. No encoding conversions are applied. + // (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied. xml_parse_result load(const char_t* contents, unsigned int options = parse_default); + // Load document from zero-terminated string. No encoding conversions are applied. + xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default); + // Load document from file xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); -- cgit v1.2.3 From b041e94f29fee9800f02ca6c257fe6cea4eae72a Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 17 Nov 2014 21:47:37 -0800 Subject: Update version to 1.5 --- src/pugiconfig.hpp | 2 +- src/pugixml.cpp | 2 +- src/pugixml.hpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/pugiconfig.hpp b/src/pugiconfig.hpp index 56f1d22..1c216e3 100644 --- a/src/pugiconfig.hpp +++ b/src/pugiconfig.hpp @@ -1,5 +1,5 @@ /** - * pugixml parser - version 1.4 + * pugixml parser - version 1.5 * -------------------------------------------------------- * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at http://pugixml.org/ diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 852ccb9..3f6b2fd 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1,6 +1,6 @@ /** { - * pugixml parser - version 1.4 + * pugixml parser - version 1.5 * -------------------------------------------------------- * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at http://pugixml.org/ diff --git a/src/pugixml.hpp b/src/pugixml.hpp index 7f52975..917ef4a 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1,5 +1,5 @@ /** - * pugixml parser - version 1.4 + * pugixml parser - version 1.5 * -------------------------------------------------------- * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at http://pugixml.org/ @@ -13,7 +13,7 @@ #ifndef PUGIXML_VERSION // Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons -# define PUGIXML_VERSION 140 +# define PUGIXML_VERSION 150 #endif // Include user configuration file (this can define various configuration macros) -- cgit v1.2.3 From 5c5038c264ed7ecb02048257b956e5206c07a566 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 19 Nov 2014 19:50:40 -0800 Subject: Change has_declaration to work on node pointers This is more for consistency with the surrounding code than for performance. --- src/pugixml.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 3f6b2fd..f2f1dd9 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -3658,11 +3658,11 @@ PUGI__NS_BEGIN while (node != root); } - PUGI__FN bool has_declaration(xml_node node) + PUGI__FN bool has_declaration(xml_node_struct* node) { - for (xml_node child = node.first_child(); child; child = child.next_sibling()) + for (xml_node_struct* child = node->first_child; child; child = child->next_sibling) { - xml_node_type type = child.type(); + xml_node_type type = PUGI__NODETYPE(child); if (type == node_declaration) return true; if (type == node_element) return false; @@ -6066,7 +6066,7 @@ namespace pugi #endif } - if (!(flags & format_no_declaration) && !impl::has_declaration(*this)) + if (!(flags & format_no_declaration) && !impl::has_declaration(_root)) { buffered_writer.write_string(PUGIXML_TEXT(" Date: Wed, 19 Nov 2014 20:56:06 -0800 Subject: Add more assertions for page memory handling code --- src/pugixml.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index f2f1dd9..90befd8 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1,5 +1,4 @@ /** -{ * pugixml parser - version 1.5 * -------------------------------------------------------- * Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) @@ -326,7 +325,7 @@ PUGI__NS_BEGIN void* memory = xml_memory::allocate(size + xml_memory_page_alignment); if (!memory) return 0; - // align upwards to page boundary (note: this guarantees at least 1 usable byte before the page) + // align to next page boundary (note: this guarantees at least 1 usable byte before the page) char* page_memory = reinterpret_cast((reinterpret_cast(memory) + xml_memory_page_alignment) & ~(xml_memory_page_alignment - 1)); // prepare page structure @@ -336,6 +335,7 @@ PUGI__NS_BEGIN page->allocator = _root->allocator; // record the offset for freeing the memory block + assert(page_memory > memory && page_memory - static_cast(memory) <= 127); page_memory[-1] = static_cast(page_memory - static_cast(memory)); return page; @@ -5966,6 +5966,7 @@ namespace pugi // destroy dynamic storage, leave sentinel page (it's in static memory) impl::xml_memory_page* root_page = reinterpret_cast(_root->header & impl::xml_memory_page_pointer_mask); assert(root_page && !root_page->prev); + assert(reinterpret_cast(root_page) >= _memory && reinterpret_cast(root_page) < _memory + sizeof(_memory)); for (impl::xml_memory_page* page = root_page->next; page; ) { -- cgit v1.2.3 From c579d99649bae59aaf5344e3d428201113fab1e9 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 19 Nov 2014 20:56:36 -0800 Subject: Prevent depth underflow when printing documents Since depth is unsigned this is actually well-defined but it's better to not have the underflow anyway. --- src/pugixml.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 90befd8..961e5f3 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -3643,11 +3643,12 @@ PUGI__NS_BEGIN } node = node->parent; - depth--; // write closing node if (PUGI__NODETYPE(node) == node_element) { + depth--; + if (indent_length) text_output_indent(writer, indent, indent_length, depth); -- cgit v1.2.3 From 6d048deba8dfb8ccb8122b6c905b08b75f5090bf Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 19 Nov 2014 20:57:22 -0800 Subject: Make sure remove_node fully detaches the node Right now remove_node is only used in contexts where parent is reset after removing but this might be important in the future. --- src/pugixml.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 961e5f3..194c77d 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -711,6 +711,7 @@ PUGI__NS_BEGIN else parent->first_child = node->next_sibling; + node->parent = 0; node->prev_sibling_c = 0; node->next_sibling = 0; } -- cgit v1.2.3 From b8437664a9d6b5697f09611b96951c005ab2554a Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 19 Nov 2014 22:44:08 -0800 Subject: XPath: Minor string operation refactoring Extract end of string to rend and add comments to translate_table. --- src/pugixml.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 194c77d..c15ed6b 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -7435,6 +7435,7 @@ PUGI__NS_BEGIN if (fc >= 128 || tc >= 128) return 0; + // code=128 means "skip character" if (!table[fc]) table[fc] = static_cast(tc ? tc : 128); @@ -7469,6 +7470,8 @@ PUGI__NS_BEGIN { unsigned char code = table[index]; + // code=128 means "skip character" (table size is 128 so 128 can be a special value) + // this code skips these characters without extra branches *write = static_cast(code); write += 1 - (code >> 7); } @@ -9525,9 +9528,10 @@ PUGI__NS_BEGIN const char_t* pos = find_substring(s.c_str(), p.c_str()); if (!pos) return xpath_string(); - const char_t* result = pos + p.length(); + const char_t* rbegin = pos + p.length(); + const char_t* rend = s.c_str() + s.length(); - return s.uses_heap() ? xpath_string::from_heap(result, s.c_str() + s.length(), stack.result) : xpath_string::from_const(result); + return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); } case ast_func_substring_2: @@ -9548,8 +9552,9 @@ PUGI__NS_BEGIN assert(1 <= pos && pos <= s_length + 1); const char_t* rbegin = s.c_str() + (pos - 1); + const char_t* rend = s.c_str() + s.length(); - return s.uses_heap() ? xpath_string::from_heap(rbegin, s.c_str() + s.length(), stack.result) : xpath_string::from_const(rbegin); + return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); } case ast_func_substring_3: -- cgit v1.2.3 From cd62478108860e36b5cab30d85640492d0f32d91 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 19 Nov 2014 22:50:06 -0800 Subject: XPath: Refactor eval_once to use set type This will allow us to implement nodeset_eval_last evaluation mode if necessary without relying on a fragile boolean argument. --- src/pugixml.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index c15ed6b..b69ba2c 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -8436,9 +8436,9 @@ PUGI__NS_BEGIN return false; } - static bool eval_once(bool forward, nodeset_eval_t eval) + static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval) { - return forward ? eval != nodeset_eval_all : eval == nodeset_eval_any; + return type == xpath_node_set::type_sorted ? eval != nodeset_eval_all : eval == nodeset_eval_any; } template static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) @@ -8610,7 +8610,7 @@ PUGI__NS_BEGIN { if (ns.size() == first) return; - bool last_once = eval_once(ns.type() == xpath_node_set::type_sorted, eval); + bool last_once = eval_once(ns.type(), eval); for (xpath_ast_node* pred = _right; pred; pred = pred->_next) pred->apply_predicate(ns, first, stack, !pred->_next && last_once); @@ -9008,7 +9008,7 @@ PUGI__NS_BEGIN template void step_fill(xpath_node_set_raw& ns, const xpath_node& xn, xpath_allocator* alloc, bool once, T v) { const axis_t axis = T::axis; - bool axis_has_attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self); + const bool axis_has_attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self); if (xn.node()) step_fill(ns, xn.node().internal_object(), alloc, once, v); @@ -9019,15 +9019,16 @@ PUGI__NS_BEGIN template xpath_node_set_raw step_do(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval, T v) { const axis_t axis = T::axis; - bool axis_reverse = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling); + const bool axis_reverse = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling); + const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; bool once = (axis == axis_attribute && _test == nodetest_name) || - (!_right && eval_once(!axis_reverse, eval)) || + (!_right && eval_once(axis_type, eval)) || (_right && !_right->_next && _right->_test == predicate_constant_one); xpath_node_set_raw ns; - ns.set_type(axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted); + ns.set_type(axis_type); if (_left) { @@ -9693,7 +9694,7 @@ PUGI__NS_BEGIN // either expression is a number or it contains position() call; sort by document order if (_test != predicate_posinv) set.sort_do(); - bool once = eval_once(set.type() == xpath_node_set::type_sorted, eval); + bool once = eval_once(set.type(), eval); apply_predicate(set, 0, stack, once); -- cgit v1.2.3 From 8f85b1ba7afb77228cffb31452272854abfa931e Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 20 Nov 2014 08:54:03 -0800 Subject: Minor refactoring of tree modification Remove redundant this-> from type() call (argument used to be called type, but it's now type_). Use _root member directly when possible instead of calling internal_object. --- src/pugixml.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index b69ba2c..75b5295 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -4970,7 +4970,7 @@ namespace pugi PUGI__FN xml_node xml_node::append_child(xml_node_type type_) { - if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); if (!n) return xml_node(); @@ -4984,7 +4984,7 @@ namespace pugi PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_) { - if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); if (!n) return xml_node(); @@ -4998,7 +4998,7 @@ namespace pugi PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node) { - if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); if (!node._root || node._root->parent != _root) return xml_node(); xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); @@ -5013,7 +5013,7 @@ namespace pugi PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node) { - if (!impl::allow_insert_child(this->type(), type_)) return xml_node(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); if (!node._root || node._root->parent != _root) return xml_node(); xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); @@ -5066,7 +5066,7 @@ namespace pugi { xml_node result = append_child(proto.type()); - if (result) impl::node_copy_tree(result.internal_object(), proto.internal_object()); + if (result) impl::node_copy_tree(result._root, proto._root); return result; } @@ -5075,7 +5075,7 @@ namespace pugi { xml_node result = prepend_child(proto.type()); - if (result) impl::node_copy_tree(result.internal_object(), proto.internal_object()); + if (result) impl::node_copy_tree(result._root, proto._root); return result; } @@ -5084,7 +5084,7 @@ namespace pugi { xml_node result = insert_child_after(proto.type(), node); - if (result) impl::node_copy_tree(result.internal_object(), proto.internal_object()); + if (result) impl::node_copy_tree(result._root, proto._root); return result; } @@ -5093,7 +5093,7 @@ namespace pugi { xml_node result = insert_child_before(proto.type(), node); - if (result) impl::node_copy_tree(result.internal_object(), proto.internal_object()); + if (result) impl::node_copy_tree(result._root, proto._root); return result; } -- cgit v1.2.3 From a0dc468170a9f429446feafea48fc73ae348b648 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 20 Nov 2014 20:29:21 -0800 Subject: Refactor node type checks for attribute insertion Add allow_insert_attribute (similar to allow_insert_child). --- src/pugixml.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 75b5295..420ac1f 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -3682,6 +3682,11 @@ PUGI__NS_BEGIN return false; } + PUGI__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) { if (parent != node_document && parent != node_element) return false; @@ -4872,7 +4877,7 @@ namespace pugi PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) { - if (type() != node_element && type() != node_declaration) return xml_attribute(); + if (!impl::allow_insert_attribute(type())) return xml_attribute(); xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); if (!a) return xml_attribute(); @@ -4886,7 +4891,7 @@ namespace pugi PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_) { - if (type() != node_element && type() != node_declaration) return xml_attribute(); + if (!impl::allow_insert_attribute(type())) return xml_attribute(); xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); if (!a) return xml_attribute(); @@ -4900,7 +4905,7 @@ namespace pugi PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) { - if (type() != node_element && type() != node_declaration) return xml_attribute(); + if (!impl::allow_insert_attribute(type())) return xml_attribute(); if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); @@ -4915,7 +4920,7 @@ namespace pugi PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) { - if (type() != node_element && type() != node_declaration) return xml_attribute(); + if (!impl::allow_insert_attribute(type())) return xml_attribute(); if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); -- cgit v1.2.3 From 125aa55061ccde4ae7351a9a6c7270a15c9e0204 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 20 Nov 2014 23:39:40 -0800 Subject: Fix node_declaration copying with empty name node_copy_string relied on the fact that target node had an empty name and value. Normally this is a safe assumption (and a good one to make since it makes copying faster), however it was not checked and there was one case when it did not hold. Since we're reusing the logic for inserting nodes, newly inserted declaration nodes had the name set automatically to xml, which in our case violates the assumption and is counter-productive since we'll override the name right after setting it. For now the best solution is to do the same insertion manually - that results in some code duplication that we can refactor later (same logic is partially shared by _move variants anyway so on a level duplicating is not that bad). --- src/pugixml.cpp | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 420ac1f..ff84d44 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -3722,6 +3722,8 @@ PUGI__NS_BEGIN PUGI__FN void node_copy_string(char_t*& dest, uintptr_t& header, uintptr_t header_mask, char_t* source, uintptr_t& source_header, xml_allocator* alloc) { + assert(!dest && (header & header_mask) == 0); + if (source) { if (alloc && (source_header & header_mask) == 0) @@ -5069,38 +5071,60 @@ namespace pugi PUGI__FN xml_node xml_node::append_copy(const xml_node& proto) { - xml_node result = append_child(proto.type()); + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); - if (result) impl::node_copy_tree(result._root, proto._root); + impl::append_node(n._root, _root); + impl::node_copy_tree(n._root, proto._root); - return result; + return n; } PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto) { - xml_node result = prepend_child(proto.type()); + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (result) impl::node_copy_tree(result._root, proto._root); + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); - return result; + impl::prepend_node(n._root, _root); + impl::node_copy_tree(n._root, proto._root); + + return n; } PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) { - xml_node result = insert_child_after(proto.type(), node); + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); - if (result) impl::node_copy_tree(result._root, proto._root); + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); - return result; + impl::insert_node_after(n._root, node._root); + impl::node_copy_tree(n._root, proto._root); + + return n; } PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) { - xml_node result = insert_child_before(proto.type(), node); + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); - if (result) impl::node_copy_tree(result._root, proto._root); + xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); + if (!n) return xml_node(); - return result; + impl::insert_node_before(n._root, node._root); + impl::node_copy_tree(n._root, proto._root); + + return n; } PUGI__FN xml_node xml_node::append_move(const xml_node& moved) -- cgit v1.2.3