diff options
-rw-r--r-- | src/pugixml.cpp | 518 | ||||
-rw-r--r-- | src/pugixml.hpp | 8 |
2 files changed, 265 insertions, 261 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index e24ba3c..192f224 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -90,6 +90,8 @@ typedef __int32 int32_t; # define DMC_VOLATILE #endif +using namespace pugi; + // Memory allocation namespace { @@ -103,15 +105,13 @@ namespace free(ptr); } - pugi::allocation_function global_allocate = default_allocate; - pugi::deallocation_function global_deallocate = default_deallocate; + allocation_function global_allocate = default_allocate; + deallocation_function global_deallocate = default_deallocate; } // String utilities namespace { - using namespace pugi; - // Get string length size_t strlength(const char_t* s) { @@ -184,7 +184,7 @@ namespace } #endif -namespace pugi +namespace { static const size_t xml_memory_page_size = 32768; @@ -396,7 +396,10 @@ namespace pugi out_page = page; return page->data; } +} +namespace pugi +{ /// A 'name=value' XML attribute structure. struct xml_attribute_struct { @@ -447,7 +450,7 @@ namespace pugi const char_t* buffer; }; - inline xml_allocator& get_allocator(const xml_node_struct* node) + static inline xml_allocator& get_allocator(const xml_node_struct* node) { assert(node); @@ -458,8 +461,6 @@ namespace pugi // Low-level DOM operations namespace { - using namespace pugi; - inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) { xml_memory_page* page; @@ -4725,12 +4726,12 @@ namespace pugi namespace std { // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&) + std::bidirectional_iterator_tag _Iter_cat(const xml_node_iterator&) { return std::bidirectional_iterator_tag(); } - std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&) + std::bidirectional_iterator_tag _Iter_cat(const xml_attribute_iterator&) { return std::bidirectional_iterator_tag(); } @@ -4741,12 +4742,12 @@ namespace std namespace std { // Workarounds for (non-standard) iterator category detection - std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&) + std::bidirectional_iterator_tag __iterator_category(const xml_node_iterator&) { return std::bidirectional_iterator_tag(); } - std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&) + std::bidirectional_iterator_tag __iterator_category(const xml_attribute_iterator&) { return std::bidirectional_iterator_tag(); } @@ -4984,7 +4985,7 @@ namespace pstd } // Allocator used for AST and evaluation stacks -namespace pugi +namespace { struct xpath_memory_block { @@ -4999,30 +5000,6 @@ namespace pugi size_t _root_size; public: - static xpath_allocator* create() - { - void* memory = global_allocate(sizeof(xpath_allocator) + sizeof(xpath_memory_block)); - if (!memory) return 0; - - xpath_memory_block* root = reinterpret_cast<xpath_memory_block*>(static_cast<xpath_allocator*>(memory) + 1); - root->next = 0; - - return new (memory) xpath_allocator(root); - } - - static void destroy(void* ptr) - { - if (!ptr) return; - - // free all allocated pages - xpath_allocator* alloc = static_cast<xpath_allocator*>(ptr); - - alloc->release(); - - // free allocator memory (with the first page) - global_deallocate(alloc); - } - xpath_allocator(xpath_memory_block* root, size_t root_size = 0): _root(root), _root_size(root_size) { #ifdef PUGIXML_NO_EXCEPTIONS @@ -5216,8 +5193,6 @@ namespace pugi // String class namespace { - using namespace pugi; - class xpath_string { const char_t* _buffer; @@ -5351,8 +5326,6 @@ namespace namespace { - using namespace pugi; - bool starts_with(const char_t* string, const char_t* pattern) { while (*pattern && *string == *pattern) @@ -6122,8 +6095,6 @@ namespace // Internal node set class namespace { - using namespace pugi; - xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool reverse) { xpath_node_set::type_t order = reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; @@ -6274,196 +6245,8 @@ namespace }; } -namespace pugi +namespace { -#ifndef PUGIXML_NO_EXCEPTIONS - xpath_exception::xpath_exception(const xpath_parse_result& result): _result(result) - { - assert(result.error); - } - - const char* xpath_exception::what() const throw() - { - return _result.error; - } - - const xpath_parse_result& xpath_exception::result() const - { - return _result; - } -#endif - - xpath_node::xpath_node() - { - } - - xpath_node::xpath_node(const xml_node& node): _node(node) - { - } - - xpath_node::xpath_node(const xml_attribute& attribute, const xml_node& parent): _node(attribute ? parent : xml_node()), _attribute(attribute) - { - } - - xml_node xpath_node::node() const - { - return _attribute ? xml_node() : _node; - } - - xml_attribute xpath_node::attribute() const - { - return _attribute; - } - - xml_node xpath_node::parent() const - { - return _attribute ? _node : _node.parent(); - } - - xpath_node::operator xpath_node::unspecified_bool_type() const - { - return (_node || _attribute) ? &xpath_node::_node : 0; - } - - bool xpath_node::operator!() const - { - return !(_node || _attribute); - } - - bool xpath_node::operator==(const xpath_node& n) const - { - return _node == n._node && _attribute == n._attribute; - } - - bool xpath_node::operator!=(const xpath_node& n) const - { - return _node != n._node || _attribute != n._attribute; - } - -#ifdef __BORLANDC__ - bool operator&&(const xpath_node& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - bool operator||(const xpath_node& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - void xpath_node_set::_assign(const_iterator begin, const_iterator end) - { - assert(begin <= end); - - size_t size = static_cast<size_t>(end - begin); - - if (size <= 1) - { - // deallocate old buffer - if (_begin != &_storage) global_deallocate(_begin); - - // use internal buffer - if (begin != end) _storage = *begin; - - _begin = &_storage; - _end = &_storage + size; - } - else - { - // make heap copy - xpath_node* storage = static_cast<xpath_node*>(global_allocate(size * sizeof(xpath_node))); - - if (!storage) - { - #ifdef PUGIXML_NO_EXCEPTIONS - return; - #else - throw std::bad_alloc(); - #endif - } - - memcpy(storage, begin, size * sizeof(xpath_node)); - - // deallocate old buffer - if (_begin != &_storage) global_deallocate(_begin); - - // finalize - _begin = storage; - _end = storage + size; - } - } - - xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage) - { - } - - xpath_node_set::xpath_node_set(const_iterator begin, const_iterator end, type_t type): _type(type), _begin(&_storage), _end(&_storage) - { - _assign(begin, end); - } - - xpath_node_set::~xpath_node_set() - { - if (_begin != &_storage) global_deallocate(_begin); - } - - xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(ns._type), _begin(&_storage), _end(&_storage) - { - _assign(ns._begin, ns._end); - } - - 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); - - return *this; - } - - xpath_node_set::type_t xpath_node_set::type() const - { - return _type; - } - - size_t xpath_node_set::size() const - { - return _end - _begin; - } - - bool xpath_node_set::empty() const - { - return _begin == _end; - } - - const xpath_node& xpath_node_set::operator[](size_t index) const - { - assert(index < size()); - return _begin[index]; - } - - xpath_node_set::const_iterator xpath_node_set::begin() const - { - return _begin; - } - - xpath_node_set::const_iterator xpath_node_set::end() const - { - return _end; - } - - void xpath_node_set::sort(bool reverse) - { - _type = xpath_sort(_begin, _end, _type, reverse); - } - - xpath_node xpath_node_set::first() const - { - return xpath_first(_begin, _end, _type); - } - struct xpath_context { xpath_node n; @@ -9116,6 +8899,197 @@ namespace pugi #endif } }; +} + +namespace pugi +{ +#ifndef PUGIXML_NO_EXCEPTIONS + xpath_exception::xpath_exception(const xpath_parse_result& result): _result(result) + { + assert(result.error); + } + + const char* xpath_exception::what() const throw() + { + return _result.error; + } + + const xpath_parse_result& xpath_exception::result() const + { + return _result; + } +#endif + + xpath_node::xpath_node() + { + } + + xpath_node::xpath_node(const xml_node& node): _node(node) + { + } + + xpath_node::xpath_node(const xml_attribute& attribute, const xml_node& parent): _node(attribute ? parent : xml_node()), _attribute(attribute) + { + } + + xml_node xpath_node::node() const + { + return _attribute ? xml_node() : _node; + } + + xml_attribute xpath_node::attribute() const + { + return _attribute; + } + + xml_node xpath_node::parent() const + { + return _attribute ? _node : _node.parent(); + } + + xpath_node::operator xpath_node::unspecified_bool_type() const + { + return (_node || _attribute) ? &xpath_node::_node : 0; + } + + bool xpath_node::operator!() const + { + return !(_node || _attribute); + } + + bool xpath_node::operator==(const xpath_node& n) const + { + return _node == n._node && _attribute == n._attribute; + } + + bool xpath_node::operator!=(const xpath_node& n) const + { + return _node != n._node || _attribute != n._attribute; + } + +#ifdef __BORLANDC__ + bool operator&&(const xpath_node& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + bool operator||(const xpath_node& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + void xpath_node_set::_assign(const_iterator begin, const_iterator end) + { + assert(begin <= end); + + size_t size = static_cast<size_t>(end - begin); + + if (size <= 1) + { + // deallocate old buffer + if (_begin != &_storage) global_deallocate(_begin); + + // use internal buffer + if (begin != end) _storage = *begin; + + _begin = &_storage; + _end = &_storage + size; + } + else + { + // make heap copy + xpath_node* storage = static_cast<xpath_node*>(global_allocate(size * sizeof(xpath_node))); + + if (!storage) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return; + #else + throw std::bad_alloc(); + #endif + } + + memcpy(storage, begin, size * sizeof(xpath_node)); + + // deallocate old buffer + if (_begin != &_storage) global_deallocate(_begin); + + // finalize + _begin = storage; + _end = storage + size; + } + } + + xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage) + { + } + + xpath_node_set::xpath_node_set(const_iterator begin, const_iterator end, type_t type): _type(type), _begin(&_storage), _end(&_storage) + { + _assign(begin, end); + } + + xpath_node_set::~xpath_node_set() + { + if (_begin != &_storage) global_deallocate(_begin); + } + + xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(ns._type), _begin(&_storage), _end(&_storage) + { + _assign(ns._begin, ns._end); + } + + 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); + + return *this; + } + + xpath_node_set::type_t xpath_node_set::type() const + { + return _type; + } + + size_t xpath_node_set::size() const + { + return _end - _begin; + } + + bool xpath_node_set::empty() const + { + return _begin == _end; + } + + const xpath_node& xpath_node_set::operator[](size_t index) const + { + assert(index < size()); + return _begin[index]; + } + + xpath_node_set::const_iterator xpath_node_set::begin() const + { + return _begin; + } + + xpath_node_set::const_iterator xpath_node_set::end() const + { + return _end; + } + + void xpath_node_set::sort(bool reverse) + { + _type = xpath_sort(_begin, _end, _type, reverse); + } + + xpath_node xpath_node_set::first() const + { + return xpath_first(_begin, _end, _type); + } xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0) { @@ -9320,11 +9294,43 @@ namespace pugi return find(name); } - xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _alloc(0), _root(0) + struct xpath_query_impl + { + static xpath_query_impl* create() + { + void* memory = global_allocate(sizeof(xpath_query_impl) + sizeof(xpath_memory_block)); + if (!memory) return 0; + + xpath_memory_block* root = reinterpret_cast<xpath_memory_block*>(static_cast<xpath_query_impl*>(memory) + 1); + root->next = 0; + + return new (memory) xpath_query_impl(root); + } + + static void destroy(void* ptr) + { + if (!ptr) return; + + // free all allocated pages + static_cast<xpath_query_impl*>(ptr)->alloc.release(); + + // free allocator memory (with the first page) + global_deallocate(ptr); + } + + xpath_query_impl(xpath_memory_block* block): root(0), alloc(block) + { + } + + xpath_ast_node* root; + xpath_allocator alloc; + }; + + xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) { - xpath_allocator* alloc = xpath_allocator::create(); + xpath_query_impl* impl = xpath_query_impl::create(); - if (!alloc) + if (!impl) { #ifdef PUGIXML_NO_EXCEPTIONS _result.error = "Out of memory"; @@ -9334,13 +9340,13 @@ namespace pugi } else { - buffer_holder alloc_holder(alloc, xpath_allocator::destroy); + buffer_holder impl_holder(impl, xpath_query_impl::destroy); - _root = xpath_parser::parse(query, variables, alloc, &_result); + impl->root = xpath_parser::parse(query, variables, &impl->alloc, &_result); - if (_root) + if (impl->root) { - _alloc = static_cast<xpath_allocator*>(alloc_holder.release()); + _impl = static_cast<xpath_query_impl*>(impl_holder.release()); _result.error = 0; } } @@ -9348,19 +9354,19 @@ namespace pugi xpath_query::~xpath_query() { - xpath_allocator::destroy(_alloc); + xpath_query_impl::destroy(_impl); } xpath_value_type xpath_query::return_type() const { - if (!_root) return xpath_type_none; + if (!_impl) return xpath_type_none; - return _root->rettype(); + return _impl->root->rettype(); } bool xpath_query::evaluate_boolean(const xpath_node& n) const { - if (!_root) return false; + if (!_impl) return false; xpath_context c(n, 1, 1); xpath_stack_data sd; @@ -9369,12 +9375,12 @@ namespace pugi if (setjmp(sd.error_handler)) return false; #endif - return _root->eval_boolean(c, sd.stack); + return _impl->root->eval_boolean(c, sd.stack); } double xpath_query::evaluate_number(const xpath_node& n) const { - if (!_root) return gen_nan(); + if (!_impl) return gen_nan(); xpath_context c(n, 1, 1); xpath_stack_data sd; @@ -9383,12 +9389,12 @@ namespace pugi if (setjmp(sd.error_handler)) return gen_nan(); #endif - return _root->eval_number(c, sd.stack); + return _impl->root->eval_number(c, sd.stack); } - static xpath_string evaluate_string_impl(xpath_ast_node* root, const xpath_node& n, xpath_stack_data& sd) + static xpath_string evaluate_string_impl(xpath_query_impl* impl, const xpath_node& n, xpath_stack_data& sd) { - if (!root) return xpath_string(); + if (!impl) return xpath_string(); #ifdef PUGIXML_NO_EXCEPTIONS if (setjmp(sd.error_handler)) return xpath_string(); @@ -9396,7 +9402,7 @@ namespace pugi xpath_context c(n, 1, 1); - return root->eval_string(c, sd.stack); + return impl->root->eval_string(c, sd.stack); } #ifndef PUGIXML_NO_STL @@ -9404,7 +9410,7 @@ namespace pugi { xpath_stack_data sd; - return evaluate_string_impl(_root, n, sd).c_str(); + return evaluate_string_impl(_impl, n, sd).c_str(); } #endif @@ -9412,7 +9418,7 @@ namespace pugi { xpath_stack_data sd; - xpath_string r = evaluate_string_impl(_root, n, sd); + xpath_string r = evaluate_string_impl(_impl, n, sd); size_t full_size = r.length() + 1; @@ -9430,9 +9436,9 @@ namespace pugi xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const { - if (!_root) return xpath_node_set(); + if (!_impl) return xpath_node_set(); - if (_root->rettype() != xpath_type_node_set) + if (_impl->root->rettype() != xpath_type_node_set) { #ifdef PUGIXML_NO_EXCEPTIONS return xpath_node_set(); @@ -9451,7 +9457,7 @@ namespace pugi if (setjmp(sd.error_handler)) return xpath_node_set(); #endif - xpath_node_set_raw r = _root->eval_node_set(c, sd.stack); + xpath_node_set_raw r = _impl->root->eval_node_set(c, sd.stack); return xpath_node_set(r.begin(), r.end(), r.type()); } @@ -9463,12 +9469,12 @@ namespace pugi xpath_query::operator xpath_query::unspecified_bool_type() const { - return _root ? &xpath_query::_root : 0; + return _impl ? &xpath_query::_impl : 0; } bool xpath_query::operator!() const { - return !_root; + return !_impl; } xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const diff --git a/src/pugixml.hpp b/src/pugixml.hpp index cccfb7f..bd6ad5f 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -774,8 +774,7 @@ namespace pugi }; #ifndef PUGIXML_NO_XPATH - class xpath_ast_node; - class xpath_allocator; + struct xpath_query_impl; // XPath query return type enum xpath_value_type @@ -876,11 +875,10 @@ namespace pugi class PUGIXML_CLASS xpath_query { private: - xpath_allocator* _alloc; - xpath_ast_node* _root; + xpath_query_impl* _impl; xpath_parse_result _result; - typedef xpath_ast_node* xpath_query::*unspecified_bool_type; + typedef xpath_query_impl* xpath_query::*unspecified_bool_type; // Non-copyable semantics xpath_query(const xpath_query&); |