diff options
-rw-r--r-- | src/pugixml.cpp | 54 | ||||
-rw-r--r-- | src/pugixml.hpp | 16 | ||||
-rw-r--r-- | tests/test_dom_traverse.cpp | 49 |
3 files changed, 81 insertions, 38 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 848b4cb..149b5d9 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -4038,7 +4038,7 @@ namespace pugi PUGI__FN xml_object_range<xml_named_node_iterator> xml_node::children(const char_t* name_) const { - return xml_object_range<xml_named_node_iterator>(xml_named_node_iterator(child(name_), name_), xml_named_node_iterator()); + return xml_object_range<xml_named_node_iterator>(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_)); } PUGI__FN xml_object_range<xml_attribute_iterator> xml_node::attributes() const @@ -5133,36 +5133,40 @@ namespace pugi { } - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _node(node), _name(name) + PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _wrap(node), _parent(node.parent()), _name(name) + { + } + + PUGI__FN xml_named_node_iterator::xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name): _wrap(ref), _parent(parent), _name(name) { } PUGI__FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const { - return _node == rhs._node; + return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; } PUGI__FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const { - return _node != rhs._node; + return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; } PUGI__FN xml_node& xml_named_node_iterator::operator*() const { - assert(_node._root); - return _node; + assert(_wrap._root); + return _wrap; } PUGI__FN xml_node* xml_named_node_iterator::operator->() const { - assert(_node._root); - return const_cast<xml_node*>(&_node); // BCC32 workaround + assert(_wrap._root); + return const_cast<xml_node*>(&_wrap); // BCC32 workaround } PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator++() { - assert(_node._root); - _node = _node.next_sibling(_name); + assert(_wrap._root); + _wrap = _wrap.next_sibling(_name); return *this; } @@ -5173,6 +5177,28 @@ namespace pugi return temp; } + PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator--() + { + if (_wrap._root) + _wrap = _wrap.previous_sibling(_name); + else + { + _wrap = _parent.last_child(); + + if (!impl::strequal(_wrap.name(), _name)) + _wrap = _wrap.previous_sibling(_name); + } + + return *this; + } + + PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator--(int) + { + xml_named_node_iterator temp = *this; + --*this; + return temp; + } + PUGI__FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) { } @@ -5481,9 +5507,9 @@ namespace std return std::bidirectional_iterator_tag(); } - PUGI__FN std::forward_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&) + PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&) { - return std::forward_iterator_tag(); + return std::bidirectional_iterator_tag(); } } #endif @@ -5502,9 +5528,9 @@ namespace std return std::bidirectional_iterator_tag(); } - PUGI__FN std::forward_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) + PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) { - return std::forward_iterator_tag(); + return std::bidirectional_iterator_tag(); } } #endif diff --git a/src/pugixml.hpp b/src/pugixml.hpp index f14c710..db1507a 100644 --- a/src/pugixml.hpp +++ b/src/pugixml.hpp @@ -753,6 +753,8 @@ namespace pugi // Named node range helper class PUGIXML_CLASS xml_named_node_iterator { + friend class xml_node; + public: // Iterator traits typedef ptrdiff_t difference_type; @@ -761,7 +763,7 @@ namespace pugi typedef xml_node& reference; #ifndef PUGIXML_NO_STL - typedef std::forward_iterator_tag iterator_category; + typedef std::bidirectional_iterator_tag iterator_category; #endif // Default constructor @@ -780,9 +782,15 @@ namespace pugi const xml_named_node_iterator& operator++(); xml_named_node_iterator operator++(int); + const xml_named_node_iterator& operator--(); + xml_named_node_iterator operator--(int); + private: - mutable xml_node _node; + mutable xml_node _wrap; + xml_node _parent; const char_t* _name; + + xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name); }; // Abstract tree walker class (see xml_node::traverse) @@ -1234,7 +1242,7 @@ namespace std // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&); std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&); - std::forward_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&); } #endif @@ -1244,7 +1252,7 @@ namespace std // Workarounds for (non-standard) iterator category detection std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&); std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&); - std::forward_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&); } #endif diff --git a/tests/test_dom_traverse.cpp b/tests/test_dom_traverse.cpp index 1668174..9c7c9ec 100644 --- a/tests/test_dom_traverse.cpp +++ b/tests/test_dom_traverse.cpp @@ -22,12 +22,6 @@ template <typename I> static I move_iter(I base, int n) else while (n++) --base; return base; } - -static xml_named_node_iterator move_iter(xml_named_node_iterator base, int n) -{ - while (n--) ++base; - return base; -} #else template <typename I> static I move_iter(I base, int n) { @@ -919,36 +913,51 @@ TEST_XML(dom_hash_value, "<node attr='value'>value</node>") CHECK(attr_copy.hash_value() == attr.hash_value()); } -TEST_XML(dom_node_named_iterator, "<node><node1><child/></node1><node2><child/><child/></node2><node3/></node>") +TEST_XML(dom_node_named_iterator, "<node><node1><child/></node1><node2><child/><child/></node2><node3/><node4><child/><x/></node4></node>") { xml_node node1 = doc.child(STR("node")).child(STR("node1")); xml_node node2 = doc.child(STR("node")).child(STR("node2")); xml_node node3 = doc.child(STR("node")).child(STR("node3")); + xml_node node4 = doc.child(STR("node")).child(STR("node4")); CHECK(xml_named_node_iterator(xml_node(), STR("child")) == xml_named_node_iterator()); - xml_named_node_iterator it1(node1.child(STR("child")), STR("child")); - CHECK(move_iter(it1, 1) == xml_named_node_iterator()); - CHECK(*it1 == node1.child(STR("child"))); - CHECK_STRING(it1->name(), STR("child")); + xml_object_range<xml_named_node_iterator> r1 = node1.children(STR("child")); + xml_object_range<xml_named_node_iterator> r2 = node2.children(STR("child")); + xml_object_range<xml_named_node_iterator> r3 = node3.children(STR("child")); + xml_object_range<xml_named_node_iterator> r4 = node4.children(STR("child")); - xml_named_node_iterator it2(node2.child(STR("child")), STR("child")); - CHECK(move_iter(it2, 1) != xml_named_node_iterator()); - CHECK(move_iter(it2, 2) == xml_named_node_iterator()); - CHECK(*it2 == node2.first_child()); - CHECK(*move_iter(it2, 1) == node2.last_child()); + CHECK(r1.begin() != r1.end()); + CHECK(*r1.begin() == node1.first_child()); + CHECK(r1.begin() == move_iter(r1.end(), -1)); + CHECK(move_iter(r1.begin(), 1) == r1.end()); - xml_named_node_iterator it3(node3.child(STR("child")), STR("child")); - CHECK(it3 == xml_named_node_iterator()); + CHECK(r2.begin() != r2.end()); + CHECK(*r2.begin() == node2.first_child()); + CHECK(*move_iter(r2.begin(), 1) == node2.last_child()); + CHECK(r2.begin() == move_iter(r2.end(), -2)); + CHECK(move_iter(r2.begin(), 1) == move_iter(r2.end(), -1)); + CHECK(move_iter(r2.begin(), 2) == r2.end()); - xml_named_node_iterator it = xml_named_node_iterator(node1.child(STR("child")), STR("child")); + CHECK(r3.begin() == r3.end()); + CHECK(!(r3.begin() != r3.end())); + + CHECK(r4.begin() != r4.end()); + CHECK(*r4.begin() == node4.first_child()); + CHECK(r4.begin() == move_iter(r4.end(), -1)); + CHECK(move_iter(r4.begin(), 1) == r4.end()); + + xml_named_node_iterator it = r1.begin(); xml_named_node_iterator itt = it; CHECK(itt == it); CHECK(itt++ == it); - CHECK(itt == xml_named_node_iterator()); + CHECK(itt == r1.end()); CHECK(itt != it); CHECK(itt == ++it); + + CHECK(itt-- == r1.end()); + CHECK(itt == r1.begin()); } |