From 6766f35338fafca445faf3c8a271ef558d6ec963 Mon Sep 17 00:00:00 2001 From: halex2005 Date: Tue, 14 Apr 2015 00:56:23 +0500 Subject: add align each attribute on new line support with format_indent_attribute --- src/pugixml.cpp | 33 ++++++++++++++++++++++----------- src/pugixml.hpp | 3 +++ 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 7c463cc..bf5835f 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -3480,13 +3480,26 @@ PUGI__NS_BEGIN } } - PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + 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) { const char_t* default_name = PUGIXML_TEXT(":anonymous"); + bool eachAttributeOnNewLine = PUGI__NODETYPE(node) != node_declaration + && (flags & format_indent) + && (flags & format_each_attribute_on_new_line) + && (flags & format_raw) == 0; + for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) { - writer.write(' '); + if (eachAttributeOnNewLine) + { + writer.write('\n'); + text_output_indent(writer, indent, indent_length, depth + 1); + } + else + { + writer.write(' '); + } writer.write_string(a->name ? a->name : default_name); writer.write('=', '"'); @@ -3497,7 +3510,7 @@ PUGI__NS_BEGIN } } - PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + 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) { const char_t* default_name = PUGIXML_TEXT(":anonymous"); const char_t* name = node->name ? node->name : default_name; @@ -3506,18 +3519,16 @@ PUGI__NS_BEGIN writer.write_string(name); if (node->first_attribute) - node_output_attributes(writer, node, flags); + node_output_attributes(writer, node, indent, indent_length, flags, depth); if (!node->first_child) { writer.write(' ', '/', '>'); - return false; } else { writer.write('>'); - return true; } } @@ -3532,7 +3543,7 @@ PUGI__NS_BEGIN writer.write('>'); } - PUGI__FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + PUGI__FN void node_output_simple(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"); @@ -3566,7 +3577,7 @@ PUGI__NS_BEGIN case node_declaration: writer.write('<', '?'); writer.write_string(node->name ? node->name : default_name); - node_output_attributes(writer, node, flags); + node_output_attributes(writer, node, indent, indent_length, flags, depth); writer.write('?', '>'); break; @@ -3608,7 +3619,7 @@ PUGI__NS_BEGIN // begin writing current node if (PUGI__NODETYPE(node) == node_pcdata || PUGI__NODETYPE(node) == node_cdata) { - node_output_simple(writer, node, flags); + node_output_simple(writer, node, indent, indent_length, flags, depth); indent_flags = 0; } @@ -3624,7 +3635,7 @@ PUGI__NS_BEGIN { indent_flags = indent_newline | indent_indent; - if (node_output_start(writer, node, flags)) + if (node_output_start(writer, node, indent, indent_length, flags, depth)) { node = node->first_child; depth++; @@ -3643,7 +3654,7 @@ PUGI__NS_BEGIN } else { - node_output_simple(writer, node, flags); + node_output_simple(writer, node, indent, indent_length, flags, depth); indent_flags = indent_newline | indent_indent; } diff --git a/src/pugixml.hpp b/src/pugixml.hpp index d59f864..36ed955 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -203,9 +203,12 @@ namespace pugi // Open file using text mode in xml_document::save_file. This enables special character (i.e. new-line) conversions on some systems. This flag is off by default. const unsigned int format_save_file_text = 0x20; + // Set each attribute to new line + const unsigned int format_each_attribute_on_new_line = 0x40; // The default set of formatting flags. // Nodes are indented depending on their depth in DOM tree, a default declaration is output if document has none. const unsigned int format_default = format_indent; + const unsigned int format_indent_attributes = format_indent | format_each_attribute_on_new_line; // Forward declarations struct xml_attribute_struct; -- cgit v1.2.3 From 2a3435274f0d7d0e3ccb4417e143e5957e820332 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 13 Apr 2015 21:21:26 -0700 Subject: Refactor format_indent_attributes implementation Fix code style and revert redundant parameters/whitespace changes. Also remove format_each_attribute_on_new_line - we're only introducing one extra formatting flag. The flag implies format_indent but does not include its bitmask. Also add a few more tests. Fixes #14. --- src/pugixml.cpp | 25 ++++++++++++------------- src/pugixml.hpp | 8 ++++---- 2 files changed, 16 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index bf5835f..590d07f 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -3480,26 +3480,23 @@ 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__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"); - bool eachAttributeOnNewLine = PUGI__NODETYPE(node) != node_declaration - && (flags & format_indent) - && (flags & format_each_attribute_on_new_line) - && (flags & format_raw) == 0; - for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) { - if (eachAttributeOnNewLine) + if ((flags & (format_indent_attributes | format_raw)) == format_indent_attributes) { writer.write('\n'); + text_output_indent(writer, indent, indent_length, depth + 1); } else { writer.write(' '); } + writer.write_string(a->name ? a->name : default_name); writer.write('=', '"'); @@ -3510,7 +3507,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__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 : default_name; @@ -3524,11 +3521,13 @@ PUGI__NS_BEGIN if (!node->first_child) { writer.write(' ', '/', '>'); + return false; } else { writer.write('>'); + return true; } } @@ -3543,7 +3542,7 @@ PUGI__NS_BEGIN writer.write('>'); } - PUGI__FN void node_output_simple(xml_buffered_writer &writer, xml_node_struct *node, const char_t *indent, size_t indent_length, unsigned int flags, unsigned int depth) + PUGI__FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) { const char_t* default_name = PUGIXML_TEXT(":anonymous"); @@ -3577,7 +3576,7 @@ PUGI__NS_BEGIN case node_declaration: writer.write('<', '?'); writer.write_string(node->name ? node->name : default_name); - node_output_attributes(writer, node, indent, indent_length, flags, depth); + node_output_attributes(writer, node, PUGIXML_TEXT(""), 0, flags | format_raw, 0); writer.write('?', '>'); break; @@ -3607,7 +3606,7 @@ PUGI__NS_BEGIN PUGI__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_raw)) == format_indent) ? strlength(indent) : 0; + size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ? strlength(indent) : 0; unsigned int indent_flags = indent_indent; xml_node_struct* node = root; @@ -3619,7 +3618,7 @@ PUGI__NS_BEGIN // begin writing current node if (PUGI__NODETYPE(node) == node_pcdata || PUGI__NODETYPE(node) == node_cdata) { - node_output_simple(writer, node, indent, indent_length, flags, depth); + node_output_simple(writer, node, flags); indent_flags = 0; } @@ -3654,7 +3653,7 @@ PUGI__NS_BEGIN } else { - node_output_simple(writer, node, indent, indent_length, flags, depth); + node_output_simple(writer, node, flags); indent_flags = indent_newline | indent_indent; } diff --git a/src/pugixml.hpp b/src/pugixml.hpp index 36ed955..02ca86b 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -203,13 +203,13 @@ namespace pugi // Open file using text mode in xml_document::save_file. This enables special character (i.e. new-line) conversions on some systems. This flag is off by default. const unsigned int format_save_file_text = 0x20; - // Set each attribute to new line - const unsigned int format_each_attribute_on_new_line = 0x40; + // Write every attribute on a new line with appropriate indentation. This flag is off by default. + const unsigned int format_indent_attributes = 0x40; + // The default set of formatting flags. // Nodes are indented depending on their depth in DOM tree, a default declaration is output if document has none. const unsigned int format_default = format_indent; - const unsigned int format_indent_attributes = format_indent | format_each_attribute_on_new_line; - + // Forward declarations struct xml_attribute_struct; struct xml_node_struct; -- cgit v1.2.3 From 2badcbb6743ff803c9cd82db77a1d8a50802058f Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 14 Apr 2015 19:11:26 -0700 Subject: Explicitly call xml_buffered_writer::flush() If xml_writer::write throws an exception while being called from flush(), the exception is thrown from destructor. Clang in C++11 mode calls std::terminate in this case. --- src/pugixml.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 590d07f..1c1b539 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -3115,11 +3115,6 @@ PUGI__NS_BEGIN PUGI__STATIC_ASSERT(bufcapacity >= 8); } - ~xml_buffered_writer() - { - flush(); - } - size_t flush() { flush(buffer, bufsize); @@ -5496,6 +5491,8 @@ namespace pugi impl::xml_buffered_writer buffered_writer(writer, encoding); impl::node_output(buffered_writer, _root, indent, flags, depth); + + buffered_writer.flush(); } #ifndef PUGIXML_NO_STL @@ -6205,6 +6202,8 @@ namespace pugi } impl::node_output(buffered_writer, _root, indent, flags, 0); + + buffered_writer.flush(); } #ifndef PUGIXML_NO_STL -- cgit v1.2.3 From 5158ee903be463c189a80715f92235ceb04871a7 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 14 Apr 2015 19:19:13 -0700 Subject: Fix xpath_node_set assignment to provide strong exception guarantee Since the type of the set was updated before assignment, assigning in out-of-memory condition could change the type to not match the content. --- src/pugixml.cpp | 17 +++++++++-------- src/pugixml.hpp | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 1c1b539..fbe13f6 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -11025,7 +11025,7 @@ namespace pugi } #endif - PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_) + PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_, type_t type_) { assert(begin_ <= end_); @@ -11041,6 +11041,7 @@ namespace pugi _begin = &_storage; _end = &_storage + size_; + _type = type_; } else { @@ -11064,6 +11065,7 @@ namespace pugi // finalize _begin = storage; _end = storage + size_; + _type = type_; } } @@ -11071,9 +11073,9 @@ namespace pugi { } - PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_), _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) { - _assign(begin_, end_); + _assign(begin_, end_, type_); } PUGI__FN xpath_node_set::~xpath_node_set() @@ -11081,17 +11083,16 @@ namespace pugi if (_begin != &_storage) impl::xml_memory::deallocate(_begin); } - PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(ns._type), _begin(&_storage), _end(&_storage) + PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(&_storage), _end(&_storage) { - _assign(ns._begin, ns._end); + _assign(ns._begin, ns._end, ns._type); } PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) { if (this == &ns) return *this; - - _type = ns._type; - _assign(ns._begin, ns._end); + + _assign(ns._begin, ns._end, ns._type); return *this; } diff --git a/src/pugixml.hpp b/src/pugixml.hpp index 02ca86b..b56f66a 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1286,7 +1286,7 @@ namespace pugi xpath_node* _begin; xpath_node* _end; - void _assign(const_iterator begin, const_iterator end); + void _assign(const_iterator begin, const_iterator end, type_t type); }; #endif -- cgit v1.2.3 From 8c8940430ac0d0f82add6fb028ffe9712c9669e8 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 15 Apr 2015 08:32:22 -0700 Subject: Minor xpath_variable refactoring The type of the variable is now initialized correctly in the ctor, so that there is no interim invalid state. --- src/pugixml.cpp | 19 ++++++++++++------- src/pugixml.hpp | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index fbe13f6..078a39c 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -7626,7 +7626,7 @@ PUGI__NS_BEGIN struct xpath_variable_boolean: xpath_variable { - xpath_variable_boolean(): value(false) + xpath_variable_boolean(): xpath_variable(xpath_type_boolean), value(false) { } @@ -7636,7 +7636,7 @@ PUGI__NS_BEGIN struct xpath_variable_number: xpath_variable { - xpath_variable_number(): value(0) + xpath_variable_number(): xpath_variable(xpath_type_number), value(0) { } @@ -7646,7 +7646,7 @@ PUGI__NS_BEGIN struct xpath_variable_string: xpath_variable { - xpath_variable_string(): value(0) + xpath_variable_string(): xpath_variable(xpath_type_string), value(0) { } @@ -7661,6 +7661,10 @@ PUGI__NS_BEGIN struct xpath_variable_node_set: xpath_variable { + xpath_variable_node_set(): xpath_variable(xpath_type_node_set) + { + } + xpath_node_set value; char_t name[1]; }; @@ -11080,7 +11084,8 @@ namespace pugi PUGI__FN xpath_node_set::~xpath_node_set() { - if (_begin != &_storage) impl::xml_memory::deallocate(_begin); + 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) @@ -11152,7 +11157,7 @@ namespace pugi return error ? error : "No error"; } - PUGI__FN xpath_variable::xpath_variable(): _type(xpath_type_none), _next(0) + PUGI__FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(0) { } @@ -11251,7 +11256,8 @@ namespace pugi PUGI__FN xpath_variable_set::xpath_variable_set() { - for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) _data[i] = 0; + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + _data[i] = 0; } PUGI__FN xpath_variable_set::~xpath_variable_set() @@ -11299,7 +11305,6 @@ namespace pugi if (result) { - result->_type = type; result->_next = _data[hash]; _data[hash] = result; diff --git a/src/pugixml.hpp b/src/pugixml.hpp index b56f66a..a7154f1 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1043,7 +1043,7 @@ namespace pugi xpath_value_type _type; xpath_variable* _next; - xpath_variable(); + xpath_variable(xpath_value_type type); // Non-copyable semantics xpath_variable(const xpath_variable&); -- cgit v1.2.3 From cbf3807ad4e93441d4a4324d1c21099ca644fac7 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 15 Apr 2015 23:22:31 -0700 Subject: Implement copy ctor/assignment for xpath_variable_set xpath_variable_set is essentially an associative container; it's about time it became copyable. Implementation is slightly tricky due to out of memory handling. Both copy ctor and assignment operator have strong exception guarantee (even if exceptions are disabled! which translates to "roll back on allocation errors"). --- src/pugixml.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/pugixml.hpp | 13 +++++--- 2 files changed, 100 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 078a39c..ce47fce 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -7758,6 +7758,28 @@ PUGI__NS_BEGIN } } + PUGI__FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs) + { + switch (rhs->type()) + { + case xpath_type_node_set: + return lhs->set(static_cast(rhs)->value); + + case xpath_type_number: + return lhs->set(static_cast(rhs)->value); + + case xpath_type_string: + return lhs->set(static_cast(rhs)->value); + + case xpath_type_boolean: + return lhs->set(static_cast(rhs)->value); + + default: + assert(!"Invalid variable type"); + return false; + } + } + 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) { size_t length = static_cast(end - begin); @@ -11277,7 +11299,46 @@ namespace pugi } } - PUGI__FN xpath_variable* xpath_variable_set::find(const char_t* name) const + PUGI__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; + + _assign(rhs); + } + + PUGI__FN xpath_variable_set& xpath_variable_set::operator=(const xpath_variable_set& rhs) + { + if (this == &rhs) return *this; + + _assign(rhs); + + return *this; + } + + PUGI__FN void xpath_variable_set::_assign(const xpath_variable_set& rhs) + { + xpath_variable_set temp; + + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + if (rhs._data[i] && !_clone(rhs._data[i], &temp._data[i])) + return; + + _swap(temp); + } + + PUGI__FN void xpath_variable_set::_swap(xpath_variable_set& rhs) + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + { + xpath_variable* chain = _data[i]; + + _data[i] = rhs._data[i]; + rhs._data[i] = chain; + } + } + + PUGI__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; @@ -11290,6 +11351,33 @@ namespace pugi return 0; } + PUGI__FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result) + { + xpath_variable* last = 0; + + while (var) + { + // allocate storage for new variable + xpath_variable* nvar = impl::new_xpath_variable(var->_type, var->name()); + if (!nvar) return false; + + // link the variable to the result immediately to handle failures gracefully + if (last) + last->_next = nvar; + else + *out_result = nvar; + + last = nvar; + + // copy the value; this can fail due to out-of-memory conditions + if (!impl::copy_xpath_variable(nvar, var)) return false; + + var = var->_next; + } + + return true; + } + PUGI__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]); @@ -11339,12 +11427,12 @@ namespace pugi PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name) { - return find(name); + return _find(name); } PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const { - return find(name); + return _find(name); } PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) diff --git a/src/pugixml.hpp b/src/pugixml.hpp index a7154f1..b8b8946 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -1075,17 +1075,22 @@ namespace pugi private: xpath_variable* _data[64]; - // Non-copyable semantics - xpath_variable_set(const xpath_variable_set&); - xpath_variable_set& operator=(const xpath_variable_set&); + void _assign(const xpath_variable_set& rhs); + void _swap(xpath_variable_set& rhs); + + xpath_variable* _find(const char_t* name) const; - xpath_variable* find(const char_t* name) const; + static bool _clone(xpath_variable* var, xpath_variable** out_result); public: // Default constructor/destructor xpath_variable_set(); ~xpath_variable_set(); + // Copy constructor/assignment operator + xpath_variable_set(const xpath_variable_set& rhs); + xpath_variable_set& operator=(const xpath_variable_set& rhs); + // Add a new variable or get the existing one, if the types match xpath_variable* add(const char_t* name, xpath_value_type type); -- cgit v1.2.3 From a414c5c52d50714d5e88f743760a5d83cd37c1a1 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 21 Apr 2015 10:02:26 -0700 Subject: Fix compilation warning in some configurations --- src/pugixml.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index ce47fce..d98df3e 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1691,6 +1691,7 @@ PUGI__NS_BEGIN assert(begin + size == end); (void)!end; + (void)!size; } #ifndef PUGIXML_NO_STL -- cgit v1.2.3 From 83b894b8f17e8c09eb21675983be0656301d2d99 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Tue, 21 Apr 2015 19:42:31 -0700 Subject: XPath: Implement move semantics support xpath_query, xpath_node_set and xpath_variable_set are now moveable. This is a nice performance optimization for variable/node sets, and enables storing xpath_query in containers without using pointers (it's only possible now since the query is not copyable). --- src/pugixml.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++++++++------- src/pugixml.hpp | 25 ++++++++++++- 2 files changed, 119 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/pugixml.cpp b/src/pugixml.cpp index d98df3e..37c61bb 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -11096,6 +11096,20 @@ namespace pugi } } +#if __cplusplus >= 201103 + PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs) + { + _type = rhs._type; + _storage = rhs._storage; + _begin = (rhs._begin == &rhs._storage) ? &_storage : rhs._begin; + _end = _begin + (rhs._end - rhs._begin); + + rhs._type = type_unsorted; + rhs._begin = &rhs._storage; + rhs._end = rhs._begin; + } +#endif + PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage) { } @@ -11125,6 +11139,25 @@ namespace pugi return *this; } +#if __cplusplus >= 201103 + PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs): _type(type_unsorted), _begin(&_storage), _end(&_storage) + { + _move(rhs); + } + + PUGI__FN xpath_node_set& xpath_node_set::operator=(xpath_node_set&& rhs) + { + if (this == &rhs) return *this; + + if (_begin != &_storage) + impl::xml_memory::deallocate(_begin); + + _move(rhs); + + return *this; + } +#endif + PUGI__FN xpath_node_set::type_t xpath_node_set::type() const { return _type; @@ -11286,18 +11319,7 @@ namespace pugi PUGI__FN xpath_variable_set::~xpath_variable_set() { for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) - { - xpath_variable* var = _data[i]; - - while (var) - { - xpath_variable* next = var->_next; - - impl::delete_xpath_variable(var->_type, var); - - var = next; - } - } + _destroy(_data[i]); } PUGI__FN xpath_variable_set::xpath_variable_set(const xpath_variable_set& rhs) @@ -11317,6 +11339,30 @@ namespace pugi return *this; } +#if __cplusplus >= 201103 + PUGI__FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs) + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + { + _data[i] = rhs._data[i]; + rhs._data[i] = 0; + } + } + + PUGI__FN xpath_variable_set& xpath_variable_set::operator=(xpath_variable_set&& rhs) + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + { + _destroy(_data[i]); + + _data[i] = rhs._data[i]; + rhs._data[i] = 0; + } + + return *this; + } +#endif + PUGI__FN void xpath_variable_set::_assign(const xpath_variable_set& rhs) { xpath_variable_set temp; @@ -11379,6 +11425,18 @@ namespace pugi return true; } + PUGI__FN void xpath_variable_set::_destroy(xpath_variable* var) + { + while (var) + { + xpath_variable* next = var->_next; + + impl::delete_xpath_variable(var->_type, var); + + var = next; + } + } + PUGI__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]); @@ -11464,12 +11522,37 @@ namespace pugi } } + PUGI__FN xpath_query::xpath_query(): _impl(0) + { + } + PUGI__FN xpath_query::~xpath_query() { if (_impl) impl::xpath_query_impl::destroy(static_cast(_impl)); } +#if __cplusplus >= 201103 + PUGI__FN xpath_query::xpath_query(xpath_query&& rhs) + { + _impl = rhs._impl; + rhs._impl = 0; + } + + xpath_query& xpath_query::operator=(xpath_query&& rhs) + { + if (this == &rhs) return *this; + + if (_impl) + impl::xpath_query_impl::destroy(static_cast(_impl)); + + _impl = rhs._impl; + rhs._impl = 0; + + return *this; + } +#endif + PUGI__FN xpath_value_type xpath_query::return_type() const { if (!_impl) return xpath_type_none; diff --git a/src/pugixml.hpp b/src/pugixml.hpp index b8b8946..0f79fb7 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -65,7 +65,7 @@ // If the platform is known to have long long support, enable long long functions #ifndef PUGIXML_HAS_LONG_LONG -# if defined(__cplusplus) && __cplusplus >= 201103 +# if __cplusplus >= 201103 # define PUGIXML_HAS_LONG_LONG # elif defined(_MSC_VER) && _MSC_VER >= 1400 # define PUGIXML_HAS_LONG_LONG @@ -1081,6 +1081,7 @@ namespace pugi xpath_variable* _find(const char_t* name) const; static bool _clone(xpath_variable* var, xpath_variable** out_result); + static void _destroy(xpath_variable* var); public: // Default constructor/destructor @@ -1091,6 +1092,12 @@ namespace pugi xpath_variable_set(const xpath_variable_set& rhs); xpath_variable_set& operator=(const xpath_variable_set& rhs); + #if __cplusplus >= 201103 + // Move semantics support + xpath_variable_set(xpath_variable_set&& rhs); + xpath_variable_set& operator=(xpath_variable_set&& rhs); + #endif + // Add a new variable or get the existing one, if the types match xpath_variable* add(const char_t* name, xpath_value_type type); @@ -1123,9 +1130,18 @@ namespace pugi // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0); + // Constructor + xpath_query(); + // Destructor ~xpath_query(); + #if __cplusplus >= 201103 + // Move semantics support + xpath_query(xpath_query&& rhs); + xpath_query& operator=(xpath_query&& rhs); + #endif + // Get query expression return type xpath_value_type return_type() const; @@ -1261,6 +1277,12 @@ namespace pugi xpath_node_set(const xpath_node_set& ns); xpath_node_set& operator=(const xpath_node_set& ns); + #if __cplusplus >= 201103 + // Move semantics support + xpath_node_set(xpath_node_set&& rhs); + xpath_node_set& operator=(xpath_node_set&& rhs); + #endif + // Get collection type type_t type() const; @@ -1292,6 +1314,7 @@ namespace pugi xpath_node* _end; void _assign(const_iterator begin, const_iterator end, type_t type); + void _move(xpath_node_set& rhs); }; #endif -- cgit v1.2.3