diff --git a/src/json.hpp b/src/json.hpp index bad8f7ee..2c6a53fa 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -96,6 +96,8 @@ class basic_json // forward declarations class iterator; class const_iterator; + class reverse_iterator; + class const_reverse_iterator; /*! @brief the type of elements in a basic_json container @@ -151,13 +153,13 @@ class basic_json @brief a reverse iterator for a basic_json container @ingroup reversiblecontainer */ - using reverse_iterator = std::reverse_iterator; + using reverse_iterator = basic_json::reverse_iterator; /*! @brief a const reverse iterator for a basic_json container @ingroup reversiblecontainer */ - using const_reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = basic_json::const_reverse_iterator; /// returns the allocator associated with the container @@ -2561,6 +2563,7 @@ class basic_json } } + /// return the key of an object iterator inline typename object_t::key_type key() const { switch (m_object->m_type) @@ -2577,6 +2580,7 @@ class basic_json } } + /// return the key of an iterator inline reference value() { return operator*(); @@ -3096,6 +3100,7 @@ class basic_json } } + /// return the key of an object iterator inline typename object_t::key_type key() const { switch (m_object->m_type) @@ -3112,6 +3117,7 @@ class basic_json } } + /// return the value of an iterator inline reference value() const { return operator*(); @@ -3124,6 +3130,48 @@ class basic_json internal_iterator m_it; }; + /// a reverse random access iterator for the basic_json class + class reverse_iterator : private std::reverse_iterator + { + public: + inline reverse_iterator(const typename std::reverse_iterator::iterator_type& + it) + : std::reverse_iterator(it) {} + + /// return the key of an object iterator + inline typename object_t::key_type key() const + { + return this->base().key(); + } + + /// return the value of an iterator + inline reference value() const + { + return this->base().operator * (); + } + }; + + /// a const reverse random access iterator for the basic_json class + class const_reverse_iterator : private std::reverse_iterator + { + public: + inline const_reverse_iterator(const typename + std::reverse_iterator::iterator_type& it) + : std::reverse_iterator(it) {} + + /// return the key of an object iterator + inline typename object_t::key_type key() const + { + return this->base().key(); + } + + /// return the value of an iterator + inline reference value() const + { + return this->base().operator * (); + } + }; + private: ////////////////////// diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index df00587d..8063c02e 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -96,6 +96,8 @@ class basic_json // forward declarations class iterator; class const_iterator; + class reverse_iterator; + class const_reverse_iterator; /*! @brief the type of elements in a basic_json container @@ -151,13 +153,13 @@ class basic_json @brief a reverse iterator for a basic_json container @ingroup reversiblecontainer */ - using reverse_iterator = std::reverse_iterator; + using reverse_iterator = basic_json::reverse_iterator; /*! @brief a const reverse iterator for a basic_json container @ingroup reversiblecontainer */ - using const_reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = basic_json::const_reverse_iterator; /// returns the allocator associated with the container @@ -2561,6 +2563,7 @@ class basic_json } } + /// return the key of an object iterator inline typename object_t::key_type key() const { switch (m_object->m_type) @@ -2577,6 +2580,7 @@ class basic_json } } + /// return the key of an iterator inline reference value() { return operator*(); @@ -3096,6 +3100,7 @@ class basic_json } } + /// return the key of an object iterator inline typename object_t::key_type key() const { switch (m_object->m_type) @@ -3112,6 +3117,7 @@ class basic_json } } + /// return the value of an iterator inline reference value() const { return operator*(); @@ -3124,6 +3130,48 @@ class basic_json internal_iterator m_it; }; + /// a reverse random access iterator for the basic_json class + class reverse_iterator : private std::reverse_iterator + { + public: + inline reverse_iterator(const typename std::reverse_iterator::iterator_type& + it) + : std::reverse_iterator(it) {} + + /// return the key of an object iterator + inline typename object_t::key_type key() const + { + return this->base().key(); + } + + /// return the value of an iterator + inline reference value() const + { + return this->base().operator * (); + } + }; + + /// a const reverse random access iterator for the basic_json class + class const_reverse_iterator : private std::reverse_iterator + { + public: + inline const_reverse_iterator(const typename + std::reverse_iterator::iterator_type& it) + : std::reverse_iterator(it) {} + + /// return the key of an object iterator + inline typename object_t::key_type key() const + { + return this->base().key(); + } + + /// return the value of an iterator + inline reference value() const + { + return this->base().operator * (); + } + }; + private: ////////////////////// diff --git a/test/unit.cpp b/test/unit.cpp index b5bdac60..bc9edc24 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -2810,6 +2810,13 @@ TEST_CASE("iterators") CHECK(it.value() == json(true)); CHECK_THROWS_AS(cit.key(), std::domain_error); CHECK(cit.value() == json(true)); + + auto rit = j.rend(); + auto crit = j.rend(); + CHECK_THROWS_AS(rit.key(), std::domain_error); + CHECK(rit.value() == json(true)); + CHECK_THROWS_AS(crit.key(), std::domain_error); + CHECK(crit.value() == json(true)); } } @@ -3001,6 +3008,13 @@ TEST_CASE("iterators") CHECK(it.value() == json("hello world")); CHECK_THROWS_AS(cit.key(), std::domain_error); CHECK(cit.value() == json("hello world")); + + auto rit = j.rend(); + auto crit = j.rend(); + CHECK_THROWS_AS(rit.key(), std::domain_error); + CHECK(rit.value() == json("hello world")); + CHECK_THROWS_AS(crit.key(), std::domain_error); + CHECK(crit.value() == json("hello world")); } } @@ -3185,6 +3199,13 @@ TEST_CASE("iterators") CHECK(it.value() == json(1)); CHECK_THROWS_AS(cit.key(), std::domain_error); CHECK(cit.value() == json(1)); + + auto rit = j.rend(); + auto crit = j.rend(); + CHECK_THROWS_AS(rit.key(), std::domain_error); + CHECK(rit.value() == json(1)); + CHECK_THROWS_AS(crit.key(), std::domain_error); + CHECK(crit.value() == json(1)); } } @@ -3369,6 +3390,13 @@ TEST_CASE("iterators") CHECK(it.value() == json(1)); CHECK(cit.key() == "A"); CHECK(cit.value() == json(1)); + + auto rit = j.rend(); + auto crit = j.rend(); + CHECK(rit.key() == "A"); + CHECK(rit.value() == json(1)); + CHECK(crit.key() == "A"); + CHECK(crit.value() == json(1)); } } @@ -3560,6 +3588,13 @@ TEST_CASE("iterators") CHECK(it.value() == json(23)); CHECK_THROWS_AS(cit.key(), std::domain_error); CHECK(cit.value() == json(23)); + + auto rit = j.rend(); + auto crit = j.rend(); + CHECK_THROWS_AS(rit.key(), std::domain_error); + CHECK(rit.value() == json(23)); + CHECK_THROWS_AS(crit.key(), std::domain_error); + CHECK(crit.value() == json(23)); } } @@ -3751,6 +3786,13 @@ TEST_CASE("iterators") CHECK(it.value() == json(23.42)); CHECK_THROWS_AS(cit.key(), std::domain_error); CHECK(cit.value() == json(23.42)); + + auto rit = j.rend(); + auto crit = j.rend(); + CHECK_THROWS_AS(rit.key(), std::domain_error); + CHECK(rit.value() == json(23.42)); + CHECK_THROWS_AS(crit.key(), std::domain_error); + CHECK(crit.value() == json(23.42)); } } @@ -3812,6 +3854,13 @@ TEST_CASE("iterators") CHECK_THROWS_AS(it.value(), std::out_of_range); CHECK_THROWS_AS(cit.key(), std::domain_error); CHECK_THROWS_AS(cit.value(), std::out_of_range); + + auto rit = j.rend(); + auto crit = j.rend(); + CHECK_THROWS_AS(rit.key(), std::domain_error); + CHECK_THROWS_AS(rit.value(), std::out_of_range); + CHECK_THROWS_AS(crit.key(), std::domain_error); + CHECK_THROWS_AS(crit.value(), std::out_of_range); } } }