cleanup and documentation
diff --git a/src/json.hpp b/src/json.hpp
index 9d2305d..46edec6 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -1785,6 +1785,8 @@
@param[in] first begin of the range to copy from (included)
@param[in] last end of the range to copy from (excluded)
+ @pre Iterators @a first and @a last must be initialized.
+
@throw std::domain_error if iterators are not compatible; that is, do not
belong to the same JSON value; example: `"iterators are not compatible"`
@throw std::out_of_range if iterators are for a primitive type (number,
@@ -1807,14 +1809,20 @@
std::is_same<InputIT, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
- basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
+ basic_json(InputIT first, InputIT last)
{
+ assert(first.m_object != nullptr);
+ assert(last.m_object != nullptr);
+
// make sure iterator fits the current value
if (first.m_object != last.m_object)
{
throw std::domain_error("iterators are not compatible");
}
+ // copy type from first iterator
+ m_type = first.m_object->m_type;
+
// check if iterator range is complete for primitive values
switch (m_type)
{
@@ -1841,35 +1849,30 @@
{
case value_t::number_integer:
{
- assert(first.m_object != nullptr);
m_value.number_integer = first.m_object->m_value.number_integer;
break;
}
case value_t::number_unsigned:
{
- assert(first.m_object != nullptr);
m_value.number_unsigned = first.m_object->m_value.number_unsigned;
break;
}
case value_t::number_float:
{
- assert(first.m_object != nullptr);
m_value.number_float = first.m_object->m_value.number_float;
break;
}
case value_t::boolean:
{
- assert(first.m_object != nullptr);
m_value.boolean = first.m_object->m_value.boolean;
break;
}
case value_t::string:
{
- assert(first.m_object != nullptr);
m_value = *first.m_object->m_value.string;
break;
}
@@ -1888,7 +1891,6 @@
default:
{
- assert(first.m_object != nullptr);
throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
}
}
@@ -6561,6 +6563,12 @@
This class implements a const iterator for the @ref basic_json class. From
this class, the @ref iterator class is derived.
+ @note An iterator is called *initialized* when a pointer to a JSON value
+ has been set (e.g., by a constructor or a copy assignment). If the
+ iterator is default-constructed, it is *uninitialized* and most
+ methods are undefined. The library uses assertions to detect calls
+ on uninitialized iterators.
+
@requirement The class satisfies the following concept requirements:
- [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
The iterator that can be moved to point (forward and backward) to any
@@ -6588,7 +6596,12 @@
/// default constructor
const_iterator() = default;
- /// constructor for a given JSON instance
+ /*!
+ @brief constructor for a given JSON instance
+ @param[in] object pointer to a JSON object for this iterator
+ @pre object != nullptr
+ @post The iterator is initialized; i.e. `m_object != nullptr`.
+ */
explicit const_iterator(pointer object) noexcept
: m_object(object)
{
@@ -6616,40 +6629,53 @@
}
}
- /// copy constructor given a nonconst iterator
+ /*!
+ @brief copy constructor given a non-const iterator
+ @param[in] other iterator to copy from
+ @note It is not checked whether @a other is initialized.
+ */
explicit const_iterator(const iterator& other) noexcept
: m_object(other.m_object)
{
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
+ if (m_object != nullptr)
{
- case basic_json::value_t::object:
+ switch (m_object->m_type)
{
- m_it.object_iterator = other.m_it.object_iterator;
- break;
- }
+ 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;
- }
+ 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;
+ default:
+ {
+ m_it.primitive_iterator = other.m_it.primitive_iterator;
+ break;
+ }
}
}
}
- /// copy constructor
+ /*!
+ @brief copy constructor
+ @param[in] other iterator to copy from
+ @note It is not checked whether @a other is initialized.
+ */
const_iterator(const const_iterator& other) noexcept
: m_object(other.m_object), m_it(other.m_it)
{}
- /// copy assignment
+ /*!
+ @brief copy assignment
+ @param[in,out] other iterator to copy from
+ @note It is not checked whether @a other is initialized.
+ */
const_iterator& operator=(const_iterator other) noexcept(
std::is_nothrow_move_constructible<pointer>::value and
std::is_nothrow_move_assignable<pointer>::value and
@@ -6663,7 +6689,10 @@
}
private:
- /// set the iterator to the first value
+ /*!
+ @brief set the iterator to the first value
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
void set_begin() noexcept
{
assert(m_object != nullptr);
@@ -6699,7 +6728,10 @@
}
}
- /// set the iterator past the last value
+ /*!
+ @brief set the iterator past the last value
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
void set_end() noexcept
{
assert(m_object != nullptr);
@@ -6729,7 +6761,10 @@
}
public:
- /// return a reference to the value pointed to by the iterator
+ /*!
+ @brief return a reference to the value pointed to by the iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
reference operator*() const
{
assert(m_object != nullptr);
@@ -6769,7 +6804,10 @@
}
}
- /// dereference the iterator
+ /*!
+ @brief dereference the iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
pointer operator->() const
{
assert(m_object != nullptr);
@@ -6804,7 +6842,10 @@
}
}
- /// post-increment (it++)
+ /*!
+ @brief post-increment (it++)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator operator++(int)
{
auto result = *this;
@@ -6812,7 +6853,10 @@
return result;
}
- /// pre-increment (++it)
+ /*!
+ @brief pre-increment (++it)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator& operator++()
{
assert(m_object != nullptr);
@@ -6841,7 +6885,10 @@
return *this;
}
- /// post-decrement (it--)
+ /*!
+ @brief post-decrement (it--)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator operator--(int)
{
auto result = *this;
@@ -6849,7 +6896,10 @@
return result;
}
- /// pre-decrement (--it)
+ /*!
+ @brief pre-decrement (--it)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator& operator--()
{
assert(m_object != nullptr);
@@ -6878,7 +6928,10 @@
return *this;
}
- /// comparison: equal
+ /*!
+ @brief comparison: equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator==(const const_iterator& other) const
{
// if objects are not the same, the comparison is undefined
@@ -6908,13 +6961,19 @@
}
}
- /// comparison: not equal
+ /*!
+ @brief comparison: not equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator!=(const const_iterator& other) const
{
return not operator==(other);
}
- /// comparison: smaller
+ /*!
+ @brief comparison: smaller
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator<(const const_iterator& other) const
{
// if objects are not the same, the comparison is undefined
@@ -6944,25 +7003,37 @@
}
}
- /// comparison: less than or equal
+ /*!
+ @brief comparison: less than or equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator<=(const const_iterator& other) const
{
return not other.operator < (*this);
}
- /// comparison: greater than
+ /*!
+ @brief comparison: greater than
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator>(const const_iterator& other) const
{
return not operator<=(other);
}
- /// comparison: greater than or equal
+ /*!
+ @brief comparison: greater than or equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator>=(const const_iterator& other) const
{
return not operator<(other);
}
- /// add to iterator
+ /*!
+ @brief add to iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator& operator+=(difference_type i)
{
assert(m_object != nullptr);
@@ -6990,13 +7061,19 @@
return *this;
}
- /// subtract from iterator
+ /*!
+ @brief subtract from iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator& operator-=(difference_type i)
{
return operator+=(-i);
}
- /// add to iterator
+ /*!
+ @brief add to iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator operator+(difference_type i)
{
auto result = *this;
@@ -7004,7 +7081,10 @@
return result;
}
- /// subtract from iterator
+ /*!
+ @brief subtract from iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator operator-(difference_type i)
{
auto result = *this;
@@ -7012,7 +7092,10 @@
return result;
}
- /// return difference
+ /*!
+ @brief return difference
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
difference_type operator-(const const_iterator& other) const
{
assert(m_object != nullptr);
@@ -7036,7 +7119,10 @@
}
}
- /// access to successor
+ /*!
+ @brief access to successor
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
reference operator[](difference_type n) const
{
assert(m_object != nullptr);
@@ -7072,7 +7158,10 @@
}
}
- /// return the key of an object iterator
+ /*!
+ @brief return the key of an object iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
typename object_t::key_type key() const
{
assert(m_object != nullptr);
@@ -7087,7 +7176,10 @@
}
}
- /// return the value of an iterator
+ /*!
+ @brief return the value of an iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
reference value() const
{
return operator*();
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 537d4f4..7bc0f36 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -1785,6 +1785,8 @@
@param[in] first begin of the range to copy from (included)
@param[in] last end of the range to copy from (excluded)
+ @pre Iterators @a first and @a last must be initialized.
+
@throw std::domain_error if iterators are not compatible; that is, do not
belong to the same JSON value; example: `"iterators are not compatible"`
@throw std::out_of_range if iterators are for a primitive type (number,
@@ -1807,14 +1809,20 @@
std::is_same<InputIT, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
- basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
+ basic_json(InputIT first, InputIT last)
{
+ assert(first.m_object != nullptr);
+ assert(last.m_object != nullptr);
+
// make sure iterator fits the current value
if (first.m_object != last.m_object)
{
throw std::domain_error("iterators are not compatible");
}
+ // copy type from first iterator
+ m_type = first.m_object->m_type;
+
// check if iterator range is complete for primitive values
switch (m_type)
{
@@ -1841,35 +1849,30 @@
{
case value_t::number_integer:
{
- assert(first.m_object != nullptr);
m_value.number_integer = first.m_object->m_value.number_integer;
break;
}
case value_t::number_unsigned:
{
- assert(first.m_object != nullptr);
m_value.number_unsigned = first.m_object->m_value.number_unsigned;
break;
}
case value_t::number_float:
{
- assert(first.m_object != nullptr);
m_value.number_float = first.m_object->m_value.number_float;
break;
}
case value_t::boolean:
{
- assert(first.m_object != nullptr);
m_value.boolean = first.m_object->m_value.boolean;
break;
}
case value_t::string:
{
- assert(first.m_object != nullptr);
m_value = *first.m_object->m_value.string;
break;
}
@@ -1888,7 +1891,6 @@
default:
{
- assert(first.m_object != nullptr);
throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
}
}
@@ -6561,6 +6563,12 @@
This class implements a const iterator for the @ref basic_json class. From
this class, the @ref iterator class is derived.
+ @note An iterator is called *initialized* when a pointer to a JSON value
+ has been set (e.g., by a constructor or a copy assignment). If the
+ iterator is default-constructed, it is *uninitialized* and most
+ methods are undefined. The library uses assertions to detect calls
+ on uninitialized iterators.
+
@requirement The class satisfies the following concept requirements:
- [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
The iterator that can be moved to point (forward and backward) to any
@@ -6588,7 +6596,12 @@
/// default constructor
const_iterator() = default;
- /// constructor for a given JSON instance
+ /*!
+ @brief constructor for a given JSON instance
+ @param[in] object pointer to a JSON object for this iterator
+ @pre object != nullptr
+ @post The iterator is initialized; i.e. `m_object != nullptr`.
+ */
explicit const_iterator(pointer object) noexcept
: m_object(object)
{
@@ -6616,40 +6629,53 @@
}
}
- /// copy constructor given a nonconst iterator
+ /*!
+ @brief copy constructor given a non-const iterator
+ @param[in] other iterator to copy from
+ @note It is not checked whether @a other is initialized.
+ */
explicit const_iterator(const iterator& other) noexcept
: m_object(other.m_object)
{
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
+ if (m_object != nullptr)
{
- case basic_json::value_t::object:
+ switch (m_object->m_type)
{
- m_it.object_iterator = other.m_it.object_iterator;
- break;
- }
+ 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;
- }
+ 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;
+ default:
+ {
+ m_it.primitive_iterator = other.m_it.primitive_iterator;
+ break;
+ }
}
}
}
- /// copy constructor
+ /*!
+ @brief copy constructor
+ @param[in] other iterator to copy from
+ @note It is not checked whether @a other is initialized.
+ */
const_iterator(const const_iterator& other) noexcept
: m_object(other.m_object), m_it(other.m_it)
{}
- /// copy assignment
+ /*!
+ @brief copy assignment
+ @param[in,out] other iterator to copy from
+ @note It is not checked whether @a other is initialized.
+ */
const_iterator& operator=(const_iterator other) noexcept(
std::is_nothrow_move_constructible<pointer>::value and
std::is_nothrow_move_assignable<pointer>::value and
@@ -6663,7 +6689,10 @@
}
private:
- /// set the iterator to the first value
+ /*!
+ @brief set the iterator to the first value
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
void set_begin() noexcept
{
assert(m_object != nullptr);
@@ -6699,7 +6728,10 @@
}
}
- /// set the iterator past the last value
+ /*!
+ @brief set the iterator past the last value
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
void set_end() noexcept
{
assert(m_object != nullptr);
@@ -6729,7 +6761,10 @@
}
public:
- /// return a reference to the value pointed to by the iterator
+ /*!
+ @brief return a reference to the value pointed to by the iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
reference operator*() const
{
assert(m_object != nullptr);
@@ -6769,7 +6804,10 @@
}
}
- /// dereference the iterator
+ /*!
+ @brief dereference the iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
pointer operator->() const
{
assert(m_object != nullptr);
@@ -6804,7 +6842,10 @@
}
}
- /// post-increment (it++)
+ /*!
+ @brief post-increment (it++)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator operator++(int)
{
auto result = *this;
@@ -6812,7 +6853,10 @@
return result;
}
- /// pre-increment (++it)
+ /*!
+ @brief pre-increment (++it)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator& operator++()
{
assert(m_object != nullptr);
@@ -6841,7 +6885,10 @@
return *this;
}
- /// post-decrement (it--)
+ /*!
+ @brief post-decrement (it--)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator operator--(int)
{
auto result = *this;
@@ -6849,7 +6896,10 @@
return result;
}
- /// pre-decrement (--it)
+ /*!
+ @brief pre-decrement (--it)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator& operator--()
{
assert(m_object != nullptr);
@@ -6878,7 +6928,10 @@
return *this;
}
- /// comparison: equal
+ /*!
+ @brief comparison: equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator==(const const_iterator& other) const
{
// if objects are not the same, the comparison is undefined
@@ -6908,13 +6961,19 @@
}
}
- /// comparison: not equal
+ /*!
+ @brief comparison: not equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator!=(const const_iterator& other) const
{
return not operator==(other);
}
- /// comparison: smaller
+ /*!
+ @brief comparison: smaller
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator<(const const_iterator& other) const
{
// if objects are not the same, the comparison is undefined
@@ -6944,25 +7003,37 @@
}
}
- /// comparison: less than or equal
+ /*!
+ @brief comparison: less than or equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator<=(const const_iterator& other) const
{
return not other.operator < (*this);
}
- /// comparison: greater than
+ /*!
+ @brief comparison: greater than
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator>(const const_iterator& other) const
{
return not operator<=(other);
}
- /// comparison: greater than or equal
+ /*!
+ @brief comparison: greater than or equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
bool operator>=(const const_iterator& other) const
{
return not operator<(other);
}
- /// add to iterator
+ /*!
+ @brief add to iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator& operator+=(difference_type i)
{
assert(m_object != nullptr);
@@ -6990,13 +7061,19 @@
return *this;
}
- /// subtract from iterator
+ /*!
+ @brief subtract from iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator& operator-=(difference_type i)
{
return operator+=(-i);
}
- /// add to iterator
+ /*!
+ @brief add to iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator operator+(difference_type i)
{
auto result = *this;
@@ -7004,7 +7081,10 @@
return result;
}
- /// subtract from iterator
+ /*!
+ @brief subtract from iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
const_iterator operator-(difference_type i)
{
auto result = *this;
@@ -7012,7 +7092,10 @@
return result;
}
- /// return difference
+ /*!
+ @brief return difference
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
difference_type operator-(const const_iterator& other) const
{
assert(m_object != nullptr);
@@ -7036,7 +7119,10 @@
}
}
- /// access to successor
+ /*!
+ @brief access to successor
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
reference operator[](difference_type n) const
{
assert(m_object != nullptr);
@@ -7072,7 +7158,10 @@
}
}
- /// return the key of an object iterator
+ /*!
+ @brief return the key of an object iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
typename object_t::key_type key() const
{
assert(m_object != nullptr);
@@ -7087,7 +7176,10 @@
}
}
- /// return the value of an iterator
+ /*!
+ @brief return the value of an iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
reference value() const
{
return operator*();