diff --git a/doc/Makefile b/doc/Makefile index b303a7859e..35077b8100 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 8922f96e1e..9511f02cc4 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,8 +4866,8 @@ class basic_json }; public: - /// a random access iterator for the basic_json class - class iterator : public std::iterator + /// a const random access iterator for the basic_json class + class const_iterator : public std::iterator { // allow basic_json class to access m_it friend class basic_json; @@ -4875,17 +4878,17 @@ class basic_json /// 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; + using pointer = typename basic_json::const_pointer; /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::reference; + using reference = typename basic_json::const_reference; /// the category of the iterator using iterator_category = std::bidirectional_iterator_tag; /// default constructor - iterator() = default; + const_iterator() = default; /// constructor for a given JSON instance - iterator(pointer object) : m_object(object) + const_iterator(pointer object) : m_object(object) { switch (m_object->m_type) { @@ -4907,13 +4910,38 @@ class basic_json } } + /// copy constructor given a nonconst iterator + const_iterator(const iterator& other) : m_object(other.m_object) + { + switch (m_object->m_type) + { + case (basic_json::value_t::object): + { + m_it.object_iterator = other.m_it.object_iterator; + break; + } + + case (basic_json::value_t::array): + { + m_it.array_iterator = other.m_it.array_iterator; + break; + } + + default: + { + m_it.primitive_iterator = other.m_it.primitive_iterator; + break; + } + } + } + /// copy constructor - iterator(const iterator& other) noexcept + const_iterator(const const_iterator& other) noexcept : m_object(other.m_object), m_it(other.m_it) {} /// copy assignment - iterator& operator=(iterator other) noexcept ( + const_iterator& operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value and std::is_nothrow_move_constructible::value and @@ -4985,7 +5013,7 @@ class basic_json public: /// return a reference to the value pointed to by the iterator - reference operator*() + reference operator*() const { switch (m_object->m_type) { @@ -5019,7 +5047,7 @@ class basic_json } /// dereference the iterator - pointer operator->() + pointer operator->() const { switch (m_object->m_type) { @@ -5033,11 +5061,6 @@ class basic_json 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()) @@ -5053,36 +5076,16 @@ class basic_json } /// post-increment (it++) - iterator operator++(int) + const_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; - } - } + ++(*this); return result; } /// pre-increment (++it) - iterator& operator++() + const_iterator& operator++() { switch (m_object->m_type) { @@ -5109,36 +5112,16 @@ class basic_json } /// post-decrement (it--) - iterator operator--(int) + const_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; - } - } + --(*this); return result; } /// pre-decrement (--it) - iterator& operator--() + const_iterator& operator--() { switch (m_object->m_type) { @@ -5165,7 +5148,7 @@ class basic_json } /// comparison: equal - bool operator==(const iterator& other) const + bool operator==(const const_iterator& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) @@ -5193,13 +5176,13 @@ class basic_json } /// comparison: not equal - bool operator!=(const iterator& other) const + bool operator!=(const const_iterator& other) const { return not operator==(other); } /// comparison: smaller - bool operator<(const iterator& other) const + bool operator<(const const_iterator& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) @@ -5227,25 +5210,25 @@ class basic_json } /// comparison: less than or equal - bool operator<=(const iterator& other) const + bool operator<=(const const_iterator& other) const { return not other.operator < (*this); } /// comparison: greater than - bool operator>(const iterator& other) const + bool operator>(const const_iterator& other) const { return not operator<=(other); } /// comparison: greater than or equal - bool operator>=(const iterator& other) const + bool operator>=(const const_iterator& other) const { return not operator<(other); } /// add to iterator - iterator& operator+=(difference_type i) + const_iterator& operator+=(difference_type i) { switch (m_object->m_type) { @@ -5271,13 +5254,13 @@ class basic_json } /// subtract from iterator - iterator& operator-=(difference_type i) + const_iterator& operator-=(difference_type i) { return operator+=(-i); } /// add to iterator - iterator operator+(difference_type i) + const_iterator operator+(difference_type i) { auto result = *this; result += i; @@ -5285,7 +5268,7 @@ class basic_json } /// subtract from iterator - iterator operator-(difference_type i) + const_iterator operator-(difference_type i) { auto result = *this; result -= i; @@ -5293,14 +5276,13 @@ class basic_json } /// return difference - difference_type operator-(const iterator& other) const + difference_type operator-(const 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): @@ -5316,7 +5298,7 @@ class basic_json } /// access to successor - reference operator[](difference_type n) + reference operator[](difference_type n) const { switch (m_object->m_type) { @@ -5366,8 +5348,8 @@ class basic_json } } - /// return the key of an iterator - reference value() + /// return the value of an iterator + reference value() const { return operator*(); } @@ -5379,401 +5361,96 @@ class basic_json internal_iterator m_it = internal_iterator(); }; - /// a const random access iterator for the basic_json class - class const_iterator : public std::iterator + /// a random access iterator for the basic_json class + class iterator : public const_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::const_pointer; - /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::const_reference; - /// the category of the iterator - using iterator_category = std::bidirectional_iterator_tag; + using base_iterator = const_iterator; + using pointer = typename basic_json::pointer; + using reference = typename basic_json::reference; /// default constructor - const_iterator() = default; + iterator() = default; /// constructor for a given JSON instance - const_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 given a nonconst iterator - const_iterator(const iterator& other) : m_object(other.m_object) - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = other.m_it.object_iterator; - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator = other.m_it.array_iterator; - break; - } - - default: - { - m_it.primitive_iterator = other.m_it.primitive_iterator; - break; - } - } - } + iterator(pointer object) noexcept : base_iterator(object) + {} /// copy constructor - const_iterator(const const_iterator& other) noexcept - : m_object(other.m_object), m_it(other.m_it) + iterator(const iterator& other) noexcept + : base_iterator(other) {} /// copy assignment - const_iterator& operator=(const_iterator other) noexcept( + 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); + base_iterator::operator=(other); return *this; } - private: - /// set the iterator to the first value - void set_begin() + /// return a reference to the value pointed to by the iterator + reference operator*() { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } + return const_cast(base_iterator::operator*()); + } - case (basic_json::value_t::array): - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } + /// dereference the iterator + pointer operator->() + { + return const_cast(base_iterator::operator->()); + } - case (basic_json::value_t::null): - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } + /// post-increment (it++) + iterator operator++(int) + { + iterator result = *this; + base_iterator::operator++(); + return result; + } - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } + /// pre-increment (++it) + iterator& operator++() + { + base_iterator::operator++(); + return *this; } - /// set the iterator past the last value - void set_end() + /// post-decrement (it--) + iterator operator--(int) { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } + iterator result = *this; + base_iterator::operator--(); + return result; + } - 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*() const - { - 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->() const - { - 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; - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return m_object; - } - else - { - throw std::out_of_range("cannot get value"); - } - } - } - } - - /// post-increment (it++) - const_iterator operator++(int) - { - auto result = *this; - ++(*this); - - return result; - } - - /// pre-increment (++it) - const_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--) - const_iterator operator--(int) - { - auto result = *this; - --(*this); - - return result; - } - - /// pre-decrement (--it) - const_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 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 const_iterator& other) const - { - return not operator==(other); - } - - /// comparison: smaller - bool operator<(const 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 const_iterator& other) const - { - return not other.operator < (*this); - } - - /// comparison: greater than - bool operator>(const const_iterator& other) const - { - return not operator<=(other); - } - - /// comparison: greater than or equal - bool operator>=(const const_iterator& other) const - { - return not operator<(other); - } + /// pre-decrement (--it) + iterator& operator--() + { + base_iterator::operator--(); + return *this; + } /// add to iterator - const_iterator& operator+=(difference_type i) + 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; - } - } - + base_iterator::operator+=(i); return *this; } /// subtract from iterator - const_iterator& operator-=(difference_type i) + iterator& operator-=(difference_type i) { - return operator+=(-i); + base_iterator::operator-=(i); + return *this; } /// add to iterator - const_iterator operator+(difference_type i) + iterator operator+(difference_type i) { auto result = *this; result += i; @@ -5781,163 +5458,82 @@ class basic_json } /// subtract from iterator - const_iterator operator-(difference_type i) + iterator operator-(difference_type i) { auto result = *this; result -= i; return result; } - /// return difference - difference_type operator-(const const_iterator& other) const + 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"); - } - - 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; - } - } + return base_iterator::operator-(other); } /// access to successor reference operator[](difference_type n) const { - 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 const_cast(base_iterator::operator[](n)); } /// return the value of an iterator reference value() const { - return operator*(); + return const_cast(base_iterator::value()); } - - private: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - 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 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 base_iterator = std::reverse_iterator; + using reference = typename Base::reference; /// create reverse iterator from iterator - reverse_iterator(const typename base_iterator::iterator_type& it) + json_reverse_iterator(const typename base_iterator::iterator_type& it) : base_iterator(it) {} /// create reverse iterator from base class - reverse_iterator(const base_iterator& it) : base_iterator(it) {} + json_reverse_iterator(const base_iterator& it) : base_iterator(it) {} /// post-increment (it++) - reverse_iterator operator++(int) + json_reverse_iterator operator++(int) { return base_iterator::operator++(1); } /// pre-increment (++it) - reverse_iterator& operator++() + json_reverse_iterator& operator++() { base_iterator::operator++(); return *this; } /// post-decrement (it--) - reverse_iterator operator--(int) + json_reverse_iterator operator--(int) { return base_iterator::operator--(1); } /// pre-decrement (--it) - reverse_iterator& operator--() + json_reverse_iterator& operator--() { base_iterator::operator--(); return *this; } /// add to iterator - reverse_iterator& operator+=(difference_type i) + json_reverse_iterator& operator+=(difference_type i) { base_iterator::operator+=(i); return *this; } /// add to iterator - reverse_iterator operator+(difference_type i) const + json_reverse_iterator operator+(difference_type i) const { auto result = *this; result += i; @@ -5945,7 +5541,7 @@ class basic_json } /// subtract from iterator - reverse_iterator operator-(difference_type i) const + 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 4dfab366a1..59b7e20dd5 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,8 +4866,8 @@ class basic_json }; public: - /// a random access iterator for the basic_json class - class iterator : public std::iterator + /// a const random access iterator for the basic_json class + class const_iterator : public std::iterator { // allow basic_json class to access m_it friend class basic_json; @@ -4875,17 +4878,17 @@ class basic_json /// 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; + using pointer = typename basic_json::const_pointer; /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::reference; + using reference = typename basic_json::const_reference; /// the category of the iterator using iterator_category = std::bidirectional_iterator_tag; /// default constructor - iterator() = default; + const_iterator() = default; /// constructor for a given JSON instance - iterator(pointer object) : m_object(object) + const_iterator(pointer object) : m_object(object) { switch (m_object->m_type) { @@ -4907,13 +4910,38 @@ class basic_json } } + /// copy constructor given a nonconst iterator + const_iterator(const iterator& other) : m_object(other.m_object) + { + switch (m_object->m_type) + { + case (basic_json::value_t::object): + { + m_it.object_iterator = other.m_it.object_iterator; + break; + } + + case (basic_json::value_t::array): + { + m_it.array_iterator = other.m_it.array_iterator; + break; + } + + default: + { + m_it.primitive_iterator = other.m_it.primitive_iterator; + break; + } + } + } + /// copy constructor - iterator(const iterator& other) noexcept + const_iterator(const const_iterator& other) noexcept : m_object(other.m_object), m_it(other.m_it) {} /// copy assignment - iterator& operator=(iterator other) noexcept ( + const_iterator& operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value and std::is_nothrow_move_constructible::value and @@ -4985,7 +5013,7 @@ class basic_json public: /// return a reference to the value pointed to by the iterator - reference operator*() + reference operator*() const { switch (m_object->m_type) { @@ -5019,7 +5047,7 @@ class basic_json } /// dereference the iterator - pointer operator->() + pointer operator->() const { switch (m_object->m_type) { @@ -5033,11 +5061,6 @@ class basic_json 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()) @@ -5053,36 +5076,16 @@ class basic_json } /// post-increment (it++) - iterator operator++(int) + const_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; - } - } + ++(*this); return result; } /// pre-increment (++it) - iterator& operator++() + const_iterator& operator++() { switch (m_object->m_type) { @@ -5109,36 +5112,16 @@ class basic_json } /// post-decrement (it--) - iterator operator--(int) + const_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; - } - } + --(*this); return result; } /// pre-decrement (--it) - iterator& operator--() + const_iterator& operator--() { switch (m_object->m_type) { @@ -5165,7 +5148,7 @@ class basic_json } /// comparison: equal - bool operator==(const iterator& other) const + bool operator==(const const_iterator& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) @@ -5193,13 +5176,13 @@ class basic_json } /// comparison: not equal - bool operator!=(const iterator& other) const + bool operator!=(const const_iterator& other) const { return not operator==(other); } /// comparison: smaller - bool operator<(const iterator& other) const + bool operator<(const const_iterator& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) @@ -5227,25 +5210,25 @@ class basic_json } /// comparison: less than or equal - bool operator<=(const iterator& other) const + bool operator<=(const const_iterator& other) const { return not other.operator < (*this); } /// comparison: greater than - bool operator>(const iterator& other) const + bool operator>(const const_iterator& other) const { return not operator<=(other); } /// comparison: greater than or equal - bool operator>=(const iterator& other) const + bool operator>=(const const_iterator& other) const { return not operator<(other); } /// add to iterator - iterator& operator+=(difference_type i) + const_iterator& operator+=(difference_type i) { switch (m_object->m_type) { @@ -5271,13 +5254,13 @@ class basic_json } /// subtract from iterator - iterator& operator-=(difference_type i) + const_iterator& operator-=(difference_type i) { return operator+=(-i); } /// add to iterator - iterator operator+(difference_type i) + const_iterator operator+(difference_type i) { auto result = *this; result += i; @@ -5285,7 +5268,7 @@ class basic_json } /// subtract from iterator - iterator operator-(difference_type i) + const_iterator operator-(difference_type i) { auto result = *this; result -= i; @@ -5293,14 +5276,13 @@ class basic_json } /// return difference - difference_type operator-(const iterator& other) const + difference_type operator-(const 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): @@ -5316,7 +5298,7 @@ class basic_json } /// access to successor - reference operator[](difference_type n) + reference operator[](difference_type n) const { switch (m_object->m_type) { @@ -5366,8 +5348,8 @@ class basic_json } } - /// return the key of an iterator - reference value() + /// return the value of an iterator + reference value() const { return operator*(); } @@ -5379,401 +5361,96 @@ class basic_json internal_iterator m_it = internal_iterator(); }; - /// a const random access iterator for the basic_json class - class const_iterator : public std::iterator + /// a random access iterator for the basic_json class + class iterator : public const_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::const_pointer; - /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::const_reference; - /// the category of the iterator - using iterator_category = std::bidirectional_iterator_tag; + using base_iterator = const_iterator; + using pointer = typename basic_json::pointer; + using reference = typename basic_json::reference; /// default constructor - const_iterator() = default; + iterator() = default; /// constructor for a given JSON instance - const_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 given a nonconst iterator - const_iterator(const iterator& other) : m_object(other.m_object) - { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = other.m_it.object_iterator; - break; - } - - case (basic_json::value_t::array): - { - m_it.array_iterator = other.m_it.array_iterator; - break; - } - - default: - { - m_it.primitive_iterator = other.m_it.primitive_iterator; - break; - } - } - } + iterator(pointer object) noexcept : base_iterator(object) + {} /// copy constructor - const_iterator(const const_iterator& other) noexcept - : m_object(other.m_object), m_it(other.m_it) + iterator(const iterator& other) noexcept + : base_iterator(other) {} /// copy assignment - const_iterator& operator=(const_iterator other) noexcept( + 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); + base_iterator::operator=(other); return *this; } - private: - /// set the iterator to the first value - void set_begin() + /// return a reference to the value pointed to by the iterator + reference operator*() { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } + return const_cast(base_iterator::operator*()); + } - case (basic_json::value_t::array): - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } + /// dereference the iterator + pointer operator->() + { + return const_cast(base_iterator::operator->()); + } - case (basic_json::value_t::null): - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } + /// post-increment (it++) + iterator operator++(int) + { + iterator result = *this; + base_iterator::operator++(); + return result; + } - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } + /// pre-increment (++it) + iterator& operator++() + { + base_iterator::operator++(); + return *this; } - /// set the iterator past the last value - void set_end() + /// post-decrement (it--) + iterator operator--(int) { - switch (m_object->m_type) - { - case (basic_json::value_t::object): - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } + iterator result = *this; + base_iterator::operator--(); + return result; + } - 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*() const - { - 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->() const - { - 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; - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return m_object; - } - else - { - throw std::out_of_range("cannot get value"); - } - } - } - } - - /// post-increment (it++) - const_iterator operator++(int) - { - auto result = *this; - ++(*this); - - return result; - } - - /// pre-increment (++it) - const_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--) - const_iterator operator--(int) - { - auto result = *this; - --(*this); - - return result; - } - - /// pre-decrement (--it) - const_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 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 const_iterator& other) const - { - return not operator==(other); - } - - /// comparison: smaller - bool operator<(const 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 const_iterator& other) const - { - return not other.operator < (*this); - } - - /// comparison: greater than - bool operator>(const const_iterator& other) const - { - return not operator<=(other); - } - - /// comparison: greater than or equal - bool operator>=(const const_iterator& other) const - { - return not operator<(other); - } + /// pre-decrement (--it) + iterator& operator--() + { + base_iterator::operator--(); + return *this; + } /// add to iterator - const_iterator& operator+=(difference_type i) + 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; - } - } - + base_iterator::operator+=(i); return *this; } /// subtract from iterator - const_iterator& operator-=(difference_type i) + iterator& operator-=(difference_type i) { - return operator+=(-i); + base_iterator::operator-=(i); + return *this; } /// add to iterator - const_iterator operator+(difference_type i) + iterator operator+(difference_type i) { auto result = *this; result += i; @@ -5781,163 +5458,82 @@ class basic_json } /// subtract from iterator - const_iterator operator-(difference_type i) + iterator operator-(difference_type i) { auto result = *this; result -= i; return result; } - /// return difference - difference_type operator-(const const_iterator& other) const + 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"); - } - - 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; - } - } + return base_iterator::operator-(other); } /// access to successor reference operator[](difference_type n) const { - 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 const_cast(base_iterator::operator[](n)); } /// return the value of an iterator reference value() const { - return operator*(); + return const_cast(base_iterator::value()); } - - private: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - 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 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 base_iterator = std::reverse_iterator; + using reference = typename Base::reference; /// create reverse iterator from iterator - reverse_iterator(const typename base_iterator::iterator_type& it) + json_reverse_iterator(const typename base_iterator::iterator_type& it) : base_iterator(it) {} /// create reverse iterator from base class - reverse_iterator(const base_iterator& it) : base_iterator(it) {} + json_reverse_iterator(const base_iterator& it) : base_iterator(it) {} /// post-increment (it++) - reverse_iterator operator++(int) + json_reverse_iterator operator++(int) { return base_iterator::operator++(1); } /// pre-increment (++it) - reverse_iterator& operator++() + json_reverse_iterator& operator++() { base_iterator::operator++(); return *this; } /// post-decrement (it--) - reverse_iterator operator--(int) + json_reverse_iterator operator--(int) { return base_iterator::operator--(1); } /// pre-decrement (--it) - reverse_iterator& operator--() + json_reverse_iterator& operator--() { base_iterator::operator--(); return *this; } /// add to iterator - reverse_iterator& operator+=(difference_type i) + json_reverse_iterator& operator+=(difference_type i) { base_iterator::operator+=(i); return *this; } /// add to iterator - reverse_iterator operator+(difference_type i) const + json_reverse_iterator operator+(difference_type i) const { auto result = *this; result += i; @@ -5945,7 +5541,7 @@ class basic_json } /// subtract from iterator - reverse_iterator operator-(difference_type i) const + 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 //