Fix bug where iterators didn't always report errors

This commit is contained in:
John Keiser 2021-02-20 14:39:54 -08:00
parent 74d6658f39
commit b352b903e7
6 changed files with 30 additions and 17 deletions

View File

@ -62,7 +62,7 @@ simdjson_really_inline simdjson_result<array_iterator> array::begin() noexcept {
return array_iterator(iter);
}
simdjson_really_inline simdjson_result<array_iterator> array::end() noexcept {
return array_iterator();
return array_iterator(iter);
}
} // namespace ondemand

View File

@ -37,6 +37,7 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_
) noexcept
: SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>(value))
{
first.iter.assert_is_valid();
}
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::simdjson_result(error_code error) noexcept
: SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>({}, error)
@ -44,20 +45,21 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_
}
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::operator*() noexcept {
if (this->error()) { this->second = SUCCESS; return this->error(); }
return *this->first;
if (error()) { return error(); }
return *first;
}
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::operator==(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &other) const noexcept {
if (this->error()) { return true; }
return this->first == other.first;
if (!first.iter.is_valid()) { return !error(); }
return first == other.first;
}
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::operator!=(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &other) const noexcept {
if (this->error()) { return false; }
return this->first != other.first;
if (!first.iter.is_valid()) { return error(); }
return first != other.first;
}
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::operator++() noexcept {
if (this->error()) { return *this; }
++(this->first);
// Clear the error if there is one, so we don't yield it twice
if (error()) { second = SUCCESS; return *this; }
++(first);
return *this;
}

View File

@ -58,7 +58,7 @@ simdjson_really_inline simdjson_result<object_iterator> object::begin() noexcept
return object_iterator(iter);
}
simdjson_really_inline simdjson_result<object_iterator> object::end() noexcept {
return object_iterator();
return object_iterator(iter);
}
} // namespace ondemand

View File

@ -97,6 +97,7 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object
) noexcept
: implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>(value))
{
first.iter.assert_is_valid();
}
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
: implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>({}, error)
@ -104,22 +105,23 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object
}
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator*() noexcept {
if (error()) { second = SUCCESS; return error(); }
if (error()) { return error(); }
return *first;
}
// Assumes it's being compared with the end. true if depth < iter->depth.
// If we're iterating and there is an error, return the error once.
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator==(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &other) const noexcept {
if (error()) { return true; }
if (!first.iter.is_valid()) { return !error(); }
return first == other.first;
}
// Assumes it's being compared with the end. true if depth >= iter->depth.
// If we're iterating and there is an error, return the error once.
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator!=(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &other) const noexcept {
if (error()) { return false; }
if (!first.iter.is_valid()) { return error(); }
return first != other.first;
}
// Checks for ']' and ','
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator++() noexcept {
if (error()) { return *this; }
// Clear the error if there is one, so we don't yield it twice
if (error()) { second = SUCCESS; return *this; }
++first;
return *this;
}

View File

@ -422,7 +422,6 @@ simdjson_really_inline void value_iterator::abandon() noexcept {
_json_iter->abandon();
}
simdjson_warn_unused simdjson_really_inline depth_t value_iterator::depth() const noexcept {
return _depth;
}
@ -539,6 +538,13 @@ simdjson_really_inline void value_iterator::assert_at_non_root_start() const noe
SIMDJSON_ASSUME( _depth > 1 );
}
simdjson_really_inline void value_iterator::assert_is_valid() const noexcept {
SIMDJSON_ASSUME( _json_iter != nullptr );
}
simdjson_really_inline bool value_iterator::is_valid() const noexcept {
return _json_iter;
}
} // namespace ondemand
} // namespace SIMDJSON_IMPLEMENTATION

View File

@ -263,6 +263,9 @@ public:
simdjson_really_inline const json_iterator &json_iter() const noexcept;
simdjson_really_inline json_iterator &json_iter() noexcept;
simdjson_really_inline void assert_is_valid() const noexcept;
simdjson_really_inline bool is_valid() const noexcept;
/** @} */
protected: