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!
This commit is contained in:
Niels 2015-07-14 21:21:08 +02:00
parent 1c8d5dc211
commit 5c813b614f
3 changed files with 297 additions and 1287 deletions

View file

@ -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/

View file

@ -172,14 +172,17 @@ class basic_json
/// the type of an element const pointer
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
// forward declaration
template<typename Base> 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<typename basic_json::iterator>;
/// a const reverse iterator for a basic_json container
class const_reverse_iterator;
using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
/// @}
@ -4863,522 +4866,6 @@ class basic_json
};
public:
/// a random access iterator for the basic_json class
class iterator : public std::iterator<std::random_access_iterator_tag, basic_json>
{
// 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<pointer>::value and
std::is_nothrow_move_assignable<pointer>::value and
std::is_nothrow_move_constructible<internal_iterator>::value and
std::is_nothrow_move_assignable<internal_iterator>::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<std::random_access_iterator_tag, const basic_json>
{
@ -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<typename basic_json::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<typename basic_json::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<pointer>::value and
std::is_nothrow_move_assignable<pointer>::value and
std::is_nothrow_move_constructible<internal_iterator>::value and
std::is_nothrow_move_assignable<internal_iterator>::value
)
{
base_iterator::operator=(other);
return *this;
}
/// return a reference to the value pointed to by the iterator
reference operator*()
{
return const_cast<reference>(base_iterator::operator*());
}
/// dereference the iterator
pointer operator->()
{
return const_cast<pointer>(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<reference>(base_iterator::operator[](n));
}
/// return the value of an iterator
reference value() const
{
return const_cast<reference>(base_iterator::value());
}
};
/// a template for a reverse iterator class
template<typename Base>
class json_reverse_iterator : public std::reverse_iterator<Base>
{
public:
/// shortcut to the reverse iterator adaptor
using base_iterator = std::reverse_iterator<Base>;
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<typename basic_json::const_iterator>
{
public:
/// shortcut to the reverse iterator adaptor
using base_iterator = std::reverse_iterator<typename basic_json::const_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 //

View file

@ -172,14 +172,17 @@ class basic_json
/// the type of an element const pointer
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
// forward declaration
template<typename Base> 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<typename basic_json::iterator>;
/// a const reverse iterator for a basic_json container
class const_reverse_iterator;
using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
/// @}
@ -4863,522 +4866,6 @@ class basic_json
};
public:
/// a random access iterator for the basic_json class
class iterator : public std::iterator<std::random_access_iterator_tag, basic_json>
{
// 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<pointer>::value and
std::is_nothrow_move_assignable<pointer>::value and
std::is_nothrow_move_constructible<internal_iterator>::value and
std::is_nothrow_move_assignable<internal_iterator>::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<std::random_access_iterator_tag, const basic_json>
{
@ -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<typename basic_json::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<typename basic_json::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<pointer>::value and
std::is_nothrow_move_assignable<pointer>::value and
std::is_nothrow_move_constructible<internal_iterator>::value and
std::is_nothrow_move_assignable<internal_iterator>::value
)
{
base_iterator::operator=(other);
return *this;
}
/// return a reference to the value pointed to by the iterator
reference operator*()
{
return const_cast<reference>(base_iterator::operator*());
}
/// dereference the iterator
pointer operator->()
{
return const_cast<pointer>(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<reference>(base_iterator::operator[](n));
}
/// return the value of an iterator
reference value() const
{
return const_cast<reference>(base_iterator::value());
}
};
/// a template for a reverse iterator class
template<typename Base>
class json_reverse_iterator : public std::reverse_iterator<Base>
{
public:
/// shortcut to the reverse iterator adaptor
using base_iterator = std::reverse_iterator<Base>;
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<typename basic_json::const_iterator>
{
public:
/// shortcut to the reverse iterator adaptor
using base_iterator = std::reverse_iterator<typename basic_json::const_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 //