1.7/2.4.9: iter_impl, iteration_proxy: drop primitive case lists, share compare preamble (#5891)
Object and array stay the first branches; everything else is the primitive case. operator== and operator< share the different-container check. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
2 files changed
+78
-139
No files matched your search
@@ -108,33 +108,18 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_data.m_type)
|
if (m_object->is_object())
|
||||||
{
|
{
|
||||||
case value_t::object:
|
m_it.object_iterator = typename object_t::iterator();
|
||||||
{
|
}
|
||||||
m_it.object_iterator = typename object_t::iterator();
|
else if (m_object->is_array())
|
||||||
break;
|
{
|
||||||
}
|
m_it.array_iterator = typename array_t::iterator();
|
||||||
|
}
|
||||||
case value_t::array:
|
else
|
||||||
{
|
{
|
||||||
m_it.array_iterator = typename array_t::iterator();
|
// primitive (is_primitive(), including discarded)
|
||||||
break;
|
m_it.primitive_iterator = primitive_iterator_t();
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::null:
|
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
m_it.primitive_iterator = primitive_iterator_t();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,33 +234,28 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_data.m_type)
|
if (m_object->is_object())
|
||||||
{
|
{
|
||||||
case value_t::object:
|
m_it.object_iterator = m_object->m_data.m_value.object->end();
|
||||||
{
|
}
|
||||||
m_it.object_iterator = m_object->m_data.m_value.object->end();
|
else if (m_object->is_array())
|
||||||
break;
|
{
|
||||||
}
|
m_it.array_iterator = m_object->m_data.m_value.array->end();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// primitive (is_primitive(), including discarded)
|
||||||
|
m_it.primitive_iterator.set_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case value_t::array:
|
/// @throw invalid_iterator.212 if @a other points to another container
|
||||||
{
|
template<typename IterImpl>
|
||||||
m_it.array_iterator = m_object->m_data.m_value.array->end();
|
JSON_HEDLEY_ALWAYS_INLINE void check_same_container(const IterImpl& other) const
|
||||||
break;
|
{
|
||||||
}
|
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
|
||||||
|
{
|
||||||
case value_t::null:
|
throw_literal<invalid_iterator>(exception_id::iterators_compare_different_values, "cannot compare iterators of different containers", m_object);
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
m_it.primitive_iterator.set_end();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,10 +404,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
bool operator==(const IterImpl& other) const
|
bool operator==(const IterImpl& other) const
|
||||||
{
|
{
|
||||||
// if objects are not the same, the comparison is undefined
|
// if objects are not the same, the comparison is undefined
|
||||||
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
|
check_same_container(other);
|
||||||
{
|
|
||||||
throw_literal<invalid_iterator>(exception_id::iterators_compare_different_values, "cannot compare iterators of different containers", m_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
// value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
|
// value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
|
||||||
if (m_object == nullptr)
|
if (m_object == nullptr)
|
||||||
@@ -466,10 +443,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
bool operator<(const iter_impl& other) const
|
bool operator<(const iter_impl& other) const
|
||||||
{
|
{
|
||||||
// if objects are not the same, the comparison is undefined
|
// if objects are not the same, the comparison is undefined
|
||||||
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
|
check_same_container(other);
|
||||||
{
|
|
||||||
throw_literal<invalid_iterator>(exception_id::iterators_compare_different_values, "cannot compare iterators of different containers", m_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
// value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
|
// value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
|
||||||
if (m_object == nullptr)
|
if (m_object == nullptr)
|
||||||
@@ -478,25 +452,18 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_object->m_data.m_type)
|
if (m_object->is_object())
|
||||||
{
|
{
|
||||||
case value_t::object:
|
throw_literal<invalid_iterator>(exception_id::iterator_order_on_object, "cannot compare order of object iterators", m_object);
|
||||||
throw_literal<invalid_iterator>(exception_id::iterator_order_on_object, "cannot compare order of object iterators", m_object);
|
|
||||||
|
|
||||||
case value_t::array:
|
|
||||||
return (m_it.array_iterator < other.m_it.array_iterator);
|
|
||||||
|
|
||||||
case value_t::null:
|
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
return (m_it.primitive_iterator < other.m_it.primitive_iterator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_object->is_array())
|
||||||
|
{
|
||||||
|
return (m_it.array_iterator < other.m_it.array_iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
// primitive (is_primitive(), including discarded)
|
||||||
|
return (m_it.primitive_iterator < other.m_it.primitive_iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -534,30 +501,19 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_data.m_type)
|
if (m_object->is_object())
|
||||||
{
|
{
|
||||||
case value_t::object:
|
throw_literal<invalid_iterator>(exception_id::iterator_arithmetic_on_object, "cannot use offsets with object iterators", m_object);
|
||||||
throw_literal<invalid_iterator>(exception_id::iterator_arithmetic_on_object, "cannot use offsets with object iterators", m_object);
|
}
|
||||||
|
|
||||||
case value_t::array:
|
if (m_object->is_array())
|
||||||
{
|
{
|
||||||
std::advance(m_it.array_iterator, i);
|
std::advance(m_it.array_iterator, i);
|
||||||
break;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
case value_t::null:
|
// primitive (is_primitive(), including discarded)
|
||||||
case value_t::string:
|
m_it.primitive_iterator += i;
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
m_it.primitive_iterator += i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@@ -613,25 +569,18 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_data.m_type)
|
if (m_object->is_object())
|
||||||
{
|
{
|
||||||
case value_t::object:
|
throw_literal<invalid_iterator>(exception_id::iterator_arithmetic_on_object, "cannot use offsets with object iterators", m_object);
|
||||||
throw_literal<invalid_iterator>(exception_id::iterator_arithmetic_on_object, "cannot use offsets with object iterators", m_object);
|
|
||||||
|
|
||||||
case value_t::array:
|
|
||||||
return m_it.array_iterator - other.m_it.array_iterator;
|
|
||||||
|
|
||||||
case value_t::null:
|
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
return m_it.primitive_iterator - other.m_it.primitive_iterator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_object->is_array())
|
||||||
|
{
|
||||||
|
return m_it.array_iterator - other.m_it.array_iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
// primitive (is_primitive(), including discarded)
|
||||||
|
return m_it.primitive_iterator - other.m_it.primitive_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -109,35 +109,25 @@ template<typename IteratorType> class iteration_proxy_value
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(anchor.m_object != nullptr);
|
JSON_ASSERT(anchor.m_object != nullptr);
|
||||||
|
|
||||||
switch (anchor.m_object->type())
|
if (anchor.m_object->is_array())
|
||||||
{
|
{
|
||||||
// use integer array index as key
|
// use integer array index as key
|
||||||
case value_t::array:
|
if (array_index != array_index_last)
|
||||||
{
|
{
|
||||||
if (array_index != array_index_last)
|
int_to_string( array_index_str, array_index );
|
||||||
{
|
array_index_last = array_index;
|
||||||
int_to_string( array_index_str, array_index );
|
|
||||||
array_index_last = array_index;
|
|
||||||
}
|
|
||||||
return array_index_str;
|
|
||||||
}
|
}
|
||||||
|
return array_index_str;
|
||||||
// use key from the object
|
|
||||||
case value_t::object:
|
|
||||||
return anchor.key();
|
|
||||||
|
|
||||||
// use an empty key for all primitive types
|
|
||||||
case value_t::null:
|
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
return empty_str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anchor.m_object->is_object())
|
||||||
|
{
|
||||||
|
// use key from the object
|
||||||
|
return anchor.key();
|
||||||
|
}
|
||||||
|
|
||||||
|
// use an empty key for all primitive types
|
||||||
|
return empty_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return value of the iterator
|
/// return value of the iterator
|
||||||
|
|||||||
Reference in new issue
Block a user