diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pugixml.cpp | 261 | ||||
-rw-r--r-- | src/pugixml.hpp | 47 |
2 files changed, 263 insertions, 45 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 5c39775..b2c13f5 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -2235,6 +2235,7 @@ PUGI__NS_BEGIN assert(begin + size == end); (void)!end; + (void)!size; } #ifndef PUGIXML_NO_STL @@ -3663,11 +3664,6 @@ PUGI__NS_BEGIN PUGI__STATIC_ASSERT(bufcapacity >= 8); } - ~xml_buffered_writer() - { - flush(); - } - size_t flush() { flush(buffer, bufsize); @@ -4028,13 +4024,23 @@ 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"); for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) { - writer.write(' '); + 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('=', '"'); @@ -4045,7 +4051,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->contents ? node->contents : default_name; @@ -4054,7 +4060,7 @@ 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) { @@ -4114,7 +4120,7 @@ PUGI__NS_BEGIN case node_declaration: writer.write('<', '?'); writer.write_string(node->contents ? node->contents : default_name); - node_output_attributes(writer, node, flags); + node_output_attributes(writer, node, PUGIXML_TEXT(""), 0, flags | format_raw, 0); writer.write('?', '>'); break; @@ -4144,7 +4150,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; @@ -4172,7 +4178,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++; @@ -6145,6 +6151,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 @@ -6844,6 +6852,8 @@ namespace pugi } impl::node_output(buffered_writer, _root, indent, flags, 0); + + buffered_writer.flush(); } #ifndef PUGIXML_NO_STL @@ -8265,7 +8275,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) { } @@ -8275,7 +8285,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) { } @@ -8285,7 +8295,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) { } @@ -8300,6 +8310,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]; }; @@ -8393,6 +8407,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<const xpath_variable_node_set*>(rhs)->value); + + case xpath_type_number: + return lhs->set(static_cast<const xpath_variable_number*>(rhs)->value); + + case xpath_type_string: + return lhs->set(static_cast<const xpath_variable_string*>(rhs)->value); + + case xpath_type_boolean: + return lhs->set(static_cast<const xpath_variable_boolean*>(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<size_t>(end - begin); @@ -11664,7 +11700,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_); @@ -11680,6 +11716,7 @@ namespace pugi _begin = &_storage; _end = &_storage + size_; + _type = type_; } else { @@ -11703,38 +11740,72 @@ namespace pugi // finalize _begin = storage; _end = storage + size_; + _type = type_; } } +#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) { } - 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() { - 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(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; } +#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; @@ -11790,7 +11861,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) { } @@ -11889,27 +11960,80 @@ 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() { 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) + { + 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; + } + +#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) { - xpath_variable* var = _data[i]; + _data[i] = rhs._data[i]; + rhs._data[i] = 0; + } + } - while (var) - { - xpath_variable* next = var->_next; + 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]); - impl::delete_xpath_variable(var->_type, var); + _data[i] = rhs._data[i]; + rhs._data[i] = 0; + } - var = next; - } + return *this; + } +#endif + + 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 + 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; @@ -11922,6 +12046,45 @@ 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 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]); @@ -11937,7 +12100,6 @@ namespace pugi if (result) { - result->_type = type; result->_next = _data[hash]; _data[hash] = result; @@ -11972,12 +12134,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) @@ -12008,12 +12170,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::xpath_query_impl*>(_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::xpath_query_impl*>(_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 d59f864..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 @@ -203,10 +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; + // 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; - + // Forward declarations struct xml_attribute_struct; struct xml_node_struct; @@ -1040,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&); @@ -1072,17 +1075,29 @@ 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); + static void _destroy(xpath_variable* var); 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); + + #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); @@ -1115,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; @@ -1253,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; @@ -1283,7 +1313,8 @@ 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); + void _move(xpath_node_set& rhs); }; #endif |