diff --git a/include/yaml-cpp/node/detail/iterator.h b/include/yaml-cpp/node/detail/iterator.h index 87469aa05..72139edf5 100644 --- a/include/yaml-cpp/node/detail/iterator.h +++ b/include/yaml-cpp/node/detail/iterator.h @@ -41,7 +41,7 @@ class iterator_base { }; public: - using iterator_category = std::forward_iterator_tag; + using iterator_category = std::bidirectional_iterator_tag; using value_type = V; using difference_type = std::ptrdiff_t; using pointer = V*; @@ -68,6 +68,17 @@ class iterator_base { ++(*this); return iterator_pre; } + + iterator_base& operator--() { + --m_iterator; + return *this; + } + + iterator_base operator--(int) { + iterator_base iterator_pre(*this); + --(*this); + return iterator_pre; + } template bool operator==(const iterator_base& rhs) const { diff --git a/include/yaml-cpp/node/detail/node_iterator.h b/include/yaml-cpp/node/detail/node_iterator.h index 49da91193..cba9726d8 100644 --- a/include/yaml-cpp/node/detail/node_iterator.h +++ b/include/yaml-cpp/node/detail/node_iterator.h @@ -69,7 +69,7 @@ class node_iterator_base { }; public: - using iterator_category = std::forward_iterator_tag; + using iterator_category = std::bidirectional_iterator_tag; using value_type = node_iterator_value; using difference_type = std::ptrdiff_t; using pointer = node_iterator_value*; @@ -140,12 +140,33 @@ class node_iterator_base { return *this; } + node_iterator_base& operator--() { + switch (m_type) { + case iterator_type::NoneType: + break; + case iterator_type::Sequence: + --m_seqIt; + break; + case iterator_type::Map: + --m_mapIt; + m_mapIt = decrement_until_defined(m_mapIt); + break; + } + return *this; + } + node_iterator_base operator++(int) { node_iterator_base iterator_pre(*this); ++(*this); return iterator_pre; } + node_iterator_base operator--(int) { + node_iterator_base iterator_pre(*this); + --(*this); + return iterator_pre; + } + value_type operator*() const { switch (m_type) { case iterator_type::NoneType: @@ -166,6 +187,12 @@ class node_iterator_base { return it; } + MapIter decrement_until_defined(MapIter it) { + while (!is_defined(it)) + --it; + return it; + } + bool is_defined(MapIter it) const { return it->first->is_defined() && it->second->is_defined(); } diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index ea887efd3..4af93afea 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -343,6 +343,17 @@ TEST(NodeTest, MapIteratorWithUndefinedValues) { EXPECT_EQ(1, count); } +TEST(NodeTest, MapIteratorWithUndefinedValuesBackward) { + Node node; + node["key"] = "value"; + node["undefined"]; + + std::size_t count = 0; + for (const_iterator it = node.end(); it != node.begin(); --it) + count++; + EXPECT_EQ(1, count); +} + TEST(NodeTest, DestroyedMapIterator) { Node node; node["key"] = "value"; @@ -395,6 +406,22 @@ TEST(NodeTest, InteratorOnSequence) { EXPECT_EQ(3, count); } +TEST(NodeTest, InteratorOnSequenceBackward) { + Node node; + node[0] = "a"; + node[1] = "b"; + node[2] = "c"; + EXPECT_TRUE(node.IsSequence()); + + std::size_t count = 0; + for (iterator it = node.end(); it != node.begin(); --it) + { + EXPECT_FALSE(prev(it)->IsNull()); + count++; + } + EXPECT_EQ(3, count); +} + TEST(NodeTest, ConstInteratorOnSequence) { Node node; node[0] = "a";