From 5c813b614fa3237f7cf71766070c61b5b56052fb Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 14 Jul 2015 21:21:08 +0200 Subject: [PATCH] closes #104 and integrates code from #93 Iterators are now implemented via const_iterators and reverse_iterator and const_reverse_iterator now share a template class. Thanks a lot! --- doc/Makefile | 2 +- src/json.hpp | 791 +++++++++------------------------------------- src/json.hpp.re2c | 791 +++++++++------------------------------------- 3 files changed, 297 insertions(+), 1287 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index b303a785..35077b81 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -54,7 +54,7 @@ doxygen: create_output create_links gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html -upload: doxygen check_output +upload: clean doxygen check_output cd html ; ../git-update-ghpages nlohmann/json rm -fr html open http://nlohmann.github.io/json/ diff --git a/src/json.hpp b/src/json.hpp index 8922f96e..9511f02c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -172,14 +172,17 @@ class basic_json /// the type of an element const pointer using const_pointer = typename std::allocator_traits::const_pointer; + // forward declaration + template class json_reverse_iterator; + /// an iterator for a basic_json container class iterator; /// a const iterator for a basic_json container class const_iterator; /// a reverse iterator for a basic_json container - class reverse_iterator; + using reverse_iterator = json_reverse_iterator; /// a const reverse iterator for a basic_json container - class const_reverse_iterator; + using const_reverse_iterator = json_reverse_iterator; /// @} @@ -4863,522 +4866,6 @@ class basic_json }; public: - /// a random access iterator for the basic_json class - class iterator : public std::iterator - { - // allow basic_json class to access m_it - friend class basic_json; - - public: - /// the type of the values when the iterator is dereferenced - using value_type = typename basic_json::value_type; - /// a type to represent differences between iterators - using difference_type = typename basic_json::difference_type; - /// defines a pointer to the type iterated over (value_type) - using pointer = typename basic_json::pointer; - /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::reference; - /// the category of the iterator - using iterator_category = std::bidirectional_iterator_tag; - - /// default constructor - iterator() = default; - - /// constructor for a given JSON instance - iterator(pointer object) : m_object(object) - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = typename object_t::iterator(); - break; - } - case (basic_json::value_t::array): - { - m_it.array_iterator = typename array_t::iterator(); - break; - } - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } - } - } - - /// copy constructor - iterator(const iterator& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /// copy assignment - iterator& operator=(iterator other) noexcept ( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_object, other.m_object); - std::swap(m_it, other.m_it); - return *this; - } - - private: - /// set the iterator to the first value - void set_begin() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } - - case (basic_json::value_t::null): - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } - - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } - } - - /// set the iterator past the last value - void set_end() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator = m_object->m_value.array->end(); - break; - } - - default: - { - m_it.primitive_iterator.set_end(); - break; - } - } - } - - public: - /// return a reference to the value pointed to by the iterator - reference operator*() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - return m_it.object_iterator->second; - } - - case (basic_json::value_t::array): - { - return *m_it.array_iterator; - } - - case (basic_json::value_t::null): - { - throw std::out_of_range("cannot get value"); - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return *m_object; - } - else - { - throw std::out_of_range("cannot get value"); - } - } - } - } - - /// dereference the iterator - pointer operator->() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - return &(m_it.object_iterator->second); - } - - case (basic_json::value_t::array): - { - return &*m_it.array_iterator; - } - - case (basic_json::value_t::null): - { - throw std::out_of_range("cannot get value"); - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return m_object; - } - else - { - throw std::out_of_range("cannot get value"); - } - } - } - } - - /// post-increment (it++) - iterator operator++(int) - { - auto result = *this; - - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator++; - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator++; - break; - } - - default: - { - m_it.primitive_iterator++; - break; - } - } - - return result; - } - - /// pre-increment (++it) - iterator& operator++() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - ++m_it.object_iterator; - break; - } - - case (basic_json::value_t::array): - { - ++m_it.array_iterator; - break; - } - - default: - { - ++m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /// post-decrement (it--) - iterator operator--(int) - { - auto result = *this; - - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator--; - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator--; - break; - } - - default: - { - m_it.primitive_iterator--; - break; - } - } - - return result; - } - - /// pre-decrement (--it) - iterator& operator--() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - --m_it.object_iterator; - break; - } - - case (basic_json::value_t::array): - { - --m_it.array_iterator; - break; - } - - default: - { - --m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /// comparison: equal - bool operator==(const iterator& other) const - { - // if objects are not the same, the comparison is undefined - if (m_object != other.m_object) - { - throw std::domain_error("cannot compare iterators of different containers"); - } - - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - return (m_it.object_iterator == other.m_it.object_iterator); - } - - case (basic_json::value_t::array): - { - return (m_it.array_iterator == other.m_it.array_iterator); - } - - default: - { - return (m_it.primitive_iterator == other.m_it.primitive_iterator); - } - } - } - - /// comparison: not equal - bool operator!=(const iterator& other) const - { - return not operator==(other); - } - - /// comparison: smaller - bool operator<(const iterator& other) const - { - // if objects are not the same, the comparison is undefined - if (m_object != other.m_object) - { - throw std::domain_error("cannot compare iterators of different containers"); - } - - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - throw std::domain_error("cannot use operator< for object iterators"); - } - - case (basic_json::value_t::array): - { - return (m_it.array_iterator < other.m_it.array_iterator); - } - - default: - { - return (m_it.primitive_iterator < other.m_it.primitive_iterator); - } - } - } - - /// comparison: less than or equal - bool operator<=(const iterator& other) const - { - return not other.operator < (*this); - } - - /// comparison: greater than - bool operator>(const iterator& other) const - { - return not operator<=(other); - } - - /// comparison: greater than or equal - bool operator>=(const iterator& other) const - { - return not operator<(other); - } - - /// add to iterator - iterator& operator+=(difference_type i) - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - throw std::domain_error("cannot use operator+= for object iterators"); - } - - case (basic_json::value_t::array): - { - m_it.array_iterator += i; - break; - } - - default: - { - m_it.primitive_iterator += i; - break; - } - } - - return *this; - } - - /// subtract from iterator - iterator& operator-=(difference_type i) - { - return operator+=(-i); - } - - /// add to iterator - iterator operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - iterator operator-(difference_type i) - { - auto result = *this; - result -= i; - return result; - } - - /// return difference - difference_type operator-(const iterator& other) const - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - throw std::domain_error("cannot use operator- for object iterators"); - return 0; - } - - case (basic_json::value_t::array): - { - return m_it.array_iterator - other.m_it.array_iterator; - } - - default: - { - return m_it.primitive_iterator - other.m_it.primitive_iterator; - } - } - } - - /// access to successor - reference operator[](difference_type n) - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - throw std::domain_error("cannot use operator[] for object iterators"); - } - - case (basic_json::value_t::array): - { - return *(m_it.array_iterator + n); - } - - case (basic_json::value_t::null): - { - throw std::out_of_range("cannot get value"); - } - - default: - { - if (m_it.primitive_iterator == -n) - { - return *m_object; - } - else - { - throw std::out_of_range("cannot get value"); - } - } - } - } - - /// return the key of an object iterator - typename object_t::key_type key() const - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - return m_it.object_iterator->first; - } - - default: - { - throw std::domain_error("cannot use key() for non-object iterators"); - } - } - } - - /// return the key of an iterator - reference value() - { - return operator*(); - } - - private: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - internal_iterator m_it = internal_iterator(); - }; - /// a const random access iterator for the basic_json class class const_iterator : public std::iterator { @@ -5874,70 +5361,96 @@ class basic_json internal_iterator m_it = internal_iterator(); }; - /*! - @brief a reverse random access iterator for the basic_json class - - The reverse iterator is realized with the `std::reverse_iterator` adaptor. - This adaptor does not automatically inherit all functionality from the - base iterator class, so some functions need to be explicitly implemented - by either delegating them to the base class or by using the `base()` - function to access the underlying base iterator. - - The following operators are implicitly inherited: - - - `operator==`, `operator!=`, `operator<`, `operator<=`, `operator>`, - `operator>=` - - `operator-=` - - `operator->`, `operator*` - */ - class reverse_iterator : public std::reverse_iterator + /// a random access iterator for the basic_json class + class iterator : public const_iterator { public: - /// shortcut to the reverse iterator adaptor - using base_iterator = std::reverse_iterator; + using base_iterator = const_iterator; + using pointer = typename basic_json::pointer; + using reference = typename basic_json::reference; - /// create reverse iterator from iterator - reverse_iterator(const typename base_iterator::iterator_type& it) - : base_iterator(it) {} + /// default constructor + iterator() = default; - /// create reverse iterator from base class - reverse_iterator(const base_iterator& it) : base_iterator(it) {} + /// constructor for a given JSON instance + iterator(pointer object) noexcept : base_iterator(object) + {} + + /// copy constructor + iterator(const iterator& other) noexcept + : base_iterator(other) + {} + + /// copy assignment + iterator& operator=(iterator other) noexcept( + std::is_nothrow_move_constructible::value and + std::is_nothrow_move_assignable::value and + std::is_nothrow_move_constructible::value and + std::is_nothrow_move_assignable::value + ) + { + base_iterator::operator=(other); + return *this; + } + + /// return a reference to the value pointed to by the iterator + reference operator*() + { + return const_cast(base_iterator::operator*()); + } + + /// dereference the iterator + pointer operator->() + { + return const_cast(base_iterator::operator->()); + } /// post-increment (it++) - reverse_iterator operator++(int) + iterator operator++(int) { - return base_iterator::operator++(1); + iterator result = *this; + base_iterator::operator++(); + return result; } /// pre-increment (++it) - reverse_iterator& operator++() + iterator& operator++() { base_iterator::operator++(); return *this; } /// post-decrement (it--) - reverse_iterator operator--(int) + iterator operator--(int) { - return base_iterator::operator--(1); + iterator result = *this; + base_iterator::operator--(); + return result; } /// pre-decrement (--it) - reverse_iterator& operator--() + iterator& operator--() { base_iterator::operator--(); return *this; } /// add to iterator - reverse_iterator& operator+=(difference_type i) + iterator& operator+=(difference_type i) { base_iterator::operator+=(i); return *this; } + /// subtract from iterator + iterator& operator-=(difference_type i) + { + base_iterator::operator-=(i); + return *this; + } + /// add to iterator - reverse_iterator operator+(difference_type i) const + iterator operator+(difference_type i) { auto result = *this; result += i; @@ -5945,7 +5458,90 @@ class basic_json } /// subtract from iterator - reverse_iterator operator-(difference_type i) const + iterator operator-(difference_type i) + { + auto result = *this; + result -= i; + return result; + } + + difference_type operator-(const iterator& other) const + { + return base_iterator::operator-(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return const_cast(base_iterator::operator[](n)); + } + + /// return the value of an iterator + reference value() const + { + return const_cast(base_iterator::value()); + } + }; + + /// a template for a reverse iterator class + template + class json_reverse_iterator : public std::reverse_iterator + { + public: + /// shortcut to the reverse iterator adaptor + using base_iterator = std::reverse_iterator; + using reference = typename Base::reference; + + /// create reverse iterator from iterator + json_reverse_iterator(const typename base_iterator::iterator_type& it) + : base_iterator(it) {} + + /// create reverse iterator from base class + json_reverse_iterator(const base_iterator& it) : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator operator++(int) + { + return base_iterator::operator++(1); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + base_iterator::operator++(); + return *this; + } + + /// post-decrement (it--) + json_reverse_iterator operator--(int) + { + return base_iterator::operator--(1); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + base_iterator::operator--(); + return *this; + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + base_iterator::operator+=(i); + return *this; + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const { auto result = *this; result -= i; @@ -5953,7 +5549,7 @@ class basic_json } /// return difference - difference_type operator-(const reverse_iterator& other) const + difference_type operator-(const json_reverse_iterator& other) const { return this->base() - other.base(); } @@ -5979,97 +5575,6 @@ class basic_json } }; - /// a const reverse random access iterator for the basic_json class - class const_reverse_iterator : public std::reverse_iterator - { - public: - /// shortcut to the reverse iterator adaptor - using base_iterator = std::reverse_iterator; - - /// create reverse iterator from iterator - const_reverse_iterator(const typename base_iterator::iterator_type& it) - : base_iterator(it) {} - - /// create reverse iterator from base class - const_reverse_iterator(const base_iterator& it) : base_iterator(it) {} - - /// post-increment (it++) - const_reverse_iterator operator++(int) - { - return base_iterator::operator++(1); - } - - /// pre-increment (++it) - const_reverse_iterator& operator++() - { - base_iterator::operator++(); - return *this; - } - - /// post-decrement (it--) - const_reverse_iterator operator--(int) - { - return base_iterator::operator--(1); - } - - /// pre-decrement (--it) - const_reverse_iterator& operator--() - { - base_iterator::operator--(); - return *this; - } - - /// add to iterator - const_reverse_iterator& operator+=(difference_type i) - { - base_iterator::operator+=(i); - return *this; - } - - /// add to iterator - const_reverse_iterator operator+(difference_type i) const - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - const_reverse_iterator operator-(difference_type i) const - { - auto result = *this; - result -= i; - return result; - } - - /// return difference - difference_type operator-(const const_reverse_iterator& other) const - { - return this->base() - other.base(); - } - - /// access to successor - const_reference operator[](difference_type n) const - { - return *(this->operator+(n)); - } - - /// return the key of an object iterator - typename object_t::key_type key() const - { - auto it = --this->base(); - return it.key(); - } - - /// return the value of an iterator - const_reference value() const - { - auto it = --this->base(); - return it.operator * (); - } - }; - - private: ////////////////////// // lexer and parser // diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 4dfab366..59b7e20d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -172,14 +172,17 @@ class basic_json /// the type of an element const pointer using const_pointer = typename std::allocator_traits::const_pointer; + // forward declaration + template class json_reverse_iterator; + /// an iterator for a basic_json container class iterator; /// a const iterator for a basic_json container class const_iterator; /// a reverse iterator for a basic_json container - class reverse_iterator; + using reverse_iterator = json_reverse_iterator; /// a const reverse iterator for a basic_json container - class const_reverse_iterator; + using const_reverse_iterator = json_reverse_iterator; /// @} @@ -4863,522 +4866,6 @@ class basic_json }; public: - /// a random access iterator for the basic_json class - class iterator : public std::iterator - { - // allow basic_json class to access m_it - friend class basic_json; - - public: - /// the type of the values when the iterator is dereferenced - using value_type = typename basic_json::value_type; - /// a type to represent differences between iterators - using difference_type = typename basic_json::difference_type; - /// defines a pointer to the type iterated over (value_type) - using pointer = typename basic_json::pointer; - /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::reference; - /// the category of the iterator - using iterator_category = std::bidirectional_iterator_tag; - - /// default constructor - iterator() = default; - - /// constructor for a given JSON instance - iterator(pointer object) : m_object(object) - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = typename object_t::iterator(); - break; - } - case (basic_json::value_t::array): - { - m_it.array_iterator = typename array_t::iterator(); - break; - } - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } - } - } - - /// copy constructor - iterator(const iterator& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /// copy assignment - iterator& operator=(iterator other) noexcept ( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_object, other.m_object); - std::swap(m_it, other.m_it); - return *this; - } - - private: - /// set the iterator to the first value - void set_begin() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } - - case (basic_json::value_t::null): - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } - - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } - } - - /// set the iterator past the last value - void set_end() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator = m_object->m_value.array->end(); - break; - } - - default: - { - m_it.primitive_iterator.set_end(); - break; - } - } - } - - public: - /// return a reference to the value pointed to by the iterator - reference operator*() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - return m_it.object_iterator->second; - } - - case (basic_json::value_t::array): - { - return *m_it.array_iterator; - } - - case (basic_json::value_t::null): - { - throw std::out_of_range("cannot get value"); - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return *m_object; - } - else - { - throw std::out_of_range("cannot get value"); - } - } - } - } - - /// dereference the iterator - pointer operator->() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - return &(m_it.object_iterator->second); - } - - case (basic_json::value_t::array): - { - return &*m_it.array_iterator; - } - - case (basic_json::value_t::null): - { - throw std::out_of_range("cannot get value"); - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return m_object; - } - else - { - throw std::out_of_range("cannot get value"); - } - } - } - } - - /// post-increment (it++) - iterator operator++(int) - { - auto result = *this; - - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator++; - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator++; - break; - } - - default: - { - m_it.primitive_iterator++; - break; - } - } - - return result; - } - - /// pre-increment (++it) - iterator& operator++() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - ++m_it.object_iterator; - break; - } - - case (basic_json::value_t::array): - { - ++m_it.array_iterator; - break; - } - - default: - { - ++m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /// post-decrement (it--) - iterator operator--(int) - { - auto result = *this; - - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator--; - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator--; - break; - } - - default: - { - m_it.primitive_iterator--; - break; - } - } - - return result; - } - - /// pre-decrement (--it) - iterator& operator--() - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - --m_it.object_iterator; - break; - } - - case (basic_json::value_t::array): - { - --m_it.array_iterator; - break; - } - - default: - { - --m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /// comparison: equal - bool operator==(const iterator& other) const - { - // if objects are not the same, the comparison is undefined - if (m_object != other.m_object) - { - throw std::domain_error("cannot compare iterators of different containers"); - } - - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - return (m_it.object_iterator == other.m_it.object_iterator); - } - - case (basic_json::value_t::array): - { - return (m_it.array_iterator == other.m_it.array_iterator); - } - - default: - { - return (m_it.primitive_iterator == other.m_it.primitive_iterator); - } - } - } - - /// comparison: not equal - bool operator!=(const iterator& other) const - { - return not operator==(other); - } - - /// comparison: smaller - bool operator<(const iterator& other) const - { - // if objects are not the same, the comparison is undefined - if (m_object != other.m_object) - { - throw std::domain_error("cannot compare iterators of different containers"); - } - - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - throw std::domain_error("cannot use operator< for object iterators"); - } - - case (basic_json::value_t::array): - { - return (m_it.array_iterator < other.m_it.array_iterator); - } - - default: - { - return (m_it.primitive_iterator < other.m_it.primitive_iterator); - } - } - } - - /// comparison: less than or equal - bool operator<=(const iterator& other) const - { - return not other.operator < (*this); - } - - /// comparison: greater than - bool operator>(const iterator& other) const - { - return not operator<=(other); - } - - /// comparison: greater than or equal - bool operator>=(const iterator& other) const - { - return not operator<(other); - } - - /// add to iterator - iterator& operator+=(difference_type i) - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - throw std::domain_error("cannot use operator+= for object iterators"); - } - - case (basic_json::value_t::array): - { - m_it.array_iterator += i; - break; - } - - default: - { - m_it.primitive_iterator += i; - break; - } - } - - return *this; - } - - /// subtract from iterator - iterator& operator-=(difference_type i) - { - return operator+=(-i); - } - - /// add to iterator - iterator operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - iterator operator-(difference_type i) - { - auto result = *this; - result -= i; - return result; - } - - /// return difference - difference_type operator-(const iterator& other) const - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - throw std::domain_error("cannot use operator- for object iterators"); - return 0; - } - - case (basic_json::value_t::array): - { - return m_it.array_iterator - other.m_it.array_iterator; - } - - default: - { - return m_it.primitive_iterator - other.m_it.primitive_iterator; - } - } - } - - /// access to successor - reference operator[](difference_type n) - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - throw std::domain_error("cannot use operator[] for object iterators"); - } - - case (basic_json::value_t::array): - { - return *(m_it.array_iterator + n); - } - - case (basic_json::value_t::null): - { - throw std::out_of_range("cannot get value"); - } - - default: - { - if (m_it.primitive_iterator == -n) - { - return *m_object; - } - else - { - throw std::out_of_range("cannot get value"); - } - } - } - } - - /// return the key of an object iterator - typename object_t::key_type key() const - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - return m_it.object_iterator->first; - } - - default: - { - throw std::domain_error("cannot use key() for non-object iterators"); - } - } - } - - /// return the key of an iterator - reference value() - { - return operator*(); - } - - private: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - internal_iterator m_it = internal_iterator(); - }; - /// a const random access iterator for the basic_json class class const_iterator : public std::iterator { @@ -5874,70 +5361,96 @@ class basic_json internal_iterator m_it = internal_iterator(); }; - /*! - @brief a reverse random access iterator for the basic_json class - - The reverse iterator is realized with the `std::reverse_iterator` adaptor. - This adaptor does not automatically inherit all functionality from the - base iterator class, so some functions need to be explicitly implemented - by either delegating them to the base class or by using the `base()` - function to access the underlying base iterator. - - The following operators are implicitly inherited: - - - `operator==`, `operator!=`, `operator<`, `operator<=`, `operator>`, - `operator>=` - - `operator-=` - - `operator->`, `operator*` - */ - class reverse_iterator : public std::reverse_iterator + /// a random access iterator for the basic_json class + class iterator : public const_iterator { public: - /// shortcut to the reverse iterator adaptor - using base_iterator = std::reverse_iterator; + using base_iterator = const_iterator; + using pointer = typename basic_json::pointer; + using reference = typename basic_json::reference; - /// create reverse iterator from iterator - reverse_iterator(const typename base_iterator::iterator_type& it) - : base_iterator(it) {} + /// default constructor + iterator() = default; - /// create reverse iterator from base class - reverse_iterator(const base_iterator& it) : base_iterator(it) {} + /// constructor for a given JSON instance + iterator(pointer object) noexcept : base_iterator(object) + {} + + /// copy constructor + iterator(const iterator& other) noexcept + : base_iterator(other) + {} + + /// copy assignment + iterator& operator=(iterator other) noexcept( + std::is_nothrow_move_constructible::value and + std::is_nothrow_move_assignable::value and + std::is_nothrow_move_constructible::value and + std::is_nothrow_move_assignable::value + ) + { + base_iterator::operator=(other); + return *this; + } + + /// return a reference to the value pointed to by the iterator + reference operator*() + { + return const_cast(base_iterator::operator*()); + } + + /// dereference the iterator + pointer operator->() + { + return const_cast(base_iterator::operator->()); + } /// post-increment (it++) - reverse_iterator operator++(int) + iterator operator++(int) { - return base_iterator::operator++(1); + iterator result = *this; + base_iterator::operator++(); + return result; } /// pre-increment (++it) - reverse_iterator& operator++() + iterator& operator++() { base_iterator::operator++(); return *this; } /// post-decrement (it--) - reverse_iterator operator--(int) + iterator operator--(int) { - return base_iterator::operator--(1); + iterator result = *this; + base_iterator::operator--(); + return result; } /// pre-decrement (--it) - reverse_iterator& operator--() + iterator& operator--() { base_iterator::operator--(); return *this; } /// add to iterator - reverse_iterator& operator+=(difference_type i) + iterator& operator+=(difference_type i) { base_iterator::operator+=(i); return *this; } + /// subtract from iterator + iterator& operator-=(difference_type i) + { + base_iterator::operator-=(i); + return *this; + } + /// add to iterator - reverse_iterator operator+(difference_type i) const + iterator operator+(difference_type i) { auto result = *this; result += i; @@ -5945,7 +5458,90 @@ class basic_json } /// subtract from iterator - reverse_iterator operator-(difference_type i) const + iterator operator-(difference_type i) + { + auto result = *this; + result -= i; + return result; + } + + difference_type operator-(const iterator& other) const + { + return base_iterator::operator-(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return const_cast(base_iterator::operator[](n)); + } + + /// return the value of an iterator + reference value() const + { + return const_cast(base_iterator::value()); + } + }; + + /// a template for a reverse iterator class + template + class json_reverse_iterator : public std::reverse_iterator + { + public: + /// shortcut to the reverse iterator adaptor + using base_iterator = std::reverse_iterator; + using reference = typename Base::reference; + + /// create reverse iterator from iterator + json_reverse_iterator(const typename base_iterator::iterator_type& it) + : base_iterator(it) {} + + /// create reverse iterator from base class + json_reverse_iterator(const base_iterator& it) : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator operator++(int) + { + return base_iterator::operator++(1); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + base_iterator::operator++(); + return *this; + } + + /// post-decrement (it--) + json_reverse_iterator operator--(int) + { + return base_iterator::operator--(1); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + base_iterator::operator--(); + return *this; + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + base_iterator::operator+=(i); + return *this; + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const { auto result = *this; result -= i; @@ -5953,7 +5549,7 @@ class basic_json } /// return difference - difference_type operator-(const reverse_iterator& other) const + difference_type operator-(const json_reverse_iterator& other) const { return this->base() - other.base(); } @@ -5979,97 +5575,6 @@ class basic_json } }; - /// a const reverse random access iterator for the basic_json class - class const_reverse_iterator : public std::reverse_iterator - { - public: - /// shortcut to the reverse iterator adaptor - using base_iterator = std::reverse_iterator; - - /// create reverse iterator from iterator - const_reverse_iterator(const typename base_iterator::iterator_type& it) - : base_iterator(it) {} - - /// create reverse iterator from base class - const_reverse_iterator(const base_iterator& it) : base_iterator(it) {} - - /// post-increment (it++) - const_reverse_iterator operator++(int) - { - return base_iterator::operator++(1); - } - - /// pre-increment (++it) - const_reverse_iterator& operator++() - { - base_iterator::operator++(); - return *this; - } - - /// post-decrement (it--) - const_reverse_iterator operator--(int) - { - return base_iterator::operator--(1); - } - - /// pre-decrement (--it) - const_reverse_iterator& operator--() - { - base_iterator::operator--(); - return *this; - } - - /// add to iterator - const_reverse_iterator& operator+=(difference_type i) - { - base_iterator::operator+=(i); - return *this; - } - - /// add to iterator - const_reverse_iterator operator+(difference_type i) const - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - const_reverse_iterator operator-(difference_type i) const - { - auto result = *this; - result -= i; - return result; - } - - /// return difference - difference_type operator-(const const_reverse_iterator& other) const - { - return this->base() - other.base(); - } - - /// access to successor - const_reference operator[](difference_type n) const - { - return *(this->operator+(n)); - } - - /// return the key of an object iterator - typename object_t::key_type key() const - { - auto it = --this->base(); - return it.key(); - } - - /// return the value of an iterator - const_reference value() const - { - auto it = --this->base(); - return it.operator * (); - } - }; - - private: ////////////////////// // lexer and parser //