Safety: check index of scalar values before use

This commit is contained in:
John Keiser
2020-12-11 11:55:32 -08:00
parent 6b02b06581
commit 73c7b7db3d
8 changed files with 98 additions and 65 deletions
@@ -8,8 +8,8 @@ simdjson_really_inline document::document(ondemand::json_iterator &&_iter) noexc
logger::log_start_value(iter, "document");
}
simdjson_really_inline void document::assert_at_start() const noexcept {
iter.assert_at_start();
simdjson_really_inline void document::assert_at_root() const noexcept {
iter.assert_at_root();
}
simdjson_really_inline document document::start(json_iterator &&iter) noexcept {
return document(std::forward<json_iterator>(iter));
@@ -19,8 +19,8 @@ simdjson_really_inline value document::as_value() noexcept {
return as_value_iterator();
}
simdjson_really_inline value_iterator document::as_value_iterator() noexcept {
assert_at_start();
return value_iterator(&iter, 1);
assert_at_root();
return value_iterator(&iter, 1, iter.token.checkpoint());
}
simdjson_really_inline simdjson_result<array> document::get_array() & noexcept {
@@ -30,15 +30,12 @@ simdjson_really_inline simdjson_result<object> document::get_object() & noexcept
return as_value().get_object();
}
simdjson_really_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
assert_at_start();
return as_value_iterator().require_root_uint64();
}
simdjson_really_inline simdjson_result<int64_t> document::get_int64() noexcept {
assert_at_start();
return as_value_iterator().require_root_int64();
}
simdjson_really_inline simdjson_result<double> document::get_double() noexcept {
assert_at_start();
return as_value_iterator().require_root_double();
}
simdjson_really_inline simdjson_result<std::string_view> document::get_string() & noexcept {
@@ -48,11 +45,9 @@ simdjson_really_inline simdjson_result<raw_json_string> document::get_raw_json_s
return as_value().get_raw_json_string();
}
simdjson_really_inline simdjson_result<bool> document::get_bool() noexcept {
assert_at_start();
return as_value_iterator().require_root_bool();
}
simdjson_really_inline bool document::is_null() noexcept {
assert_at_start();
return as_value_iterator().is_root_null();
}
+1 -1
View File
@@ -232,7 +232,7 @@ protected:
simdjson_really_inline value_iterator as_value_iterator() noexcept;
static simdjson_really_inline document start(ondemand::json_iterator &&iter) noexcept;
simdjson_really_inline void assert_at_start() const noexcept;
simdjson_really_inline void assert_at_root() const noexcept;
//
// Fields
@@ -90,11 +90,11 @@ simdjson_warn_unused simdjson_really_inline error_code json_iterator::skip_child
return report_error(TAPE_ERROR, "not enough close braces");
}
simdjson_really_inline bool json_iterator::at_start() const noexcept {
return token.index == &parser->dom_parser.structural_indexes[0];
simdjson_really_inline bool json_iterator::at_root() const noexcept {
return token.index == parser->dom_parser.structural_indexes.get();
}
simdjson_really_inline void json_iterator::assert_at_start() const noexcept {
simdjson_really_inline void json_iterator::assert_at_root() const noexcept {
SIMDJSON_ASSUME( _depth == 1 );
// Visual Studio Clang treats unique_ptr.get() as "side effecting."
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
@@ -60,12 +60,12 @@ public:
/**
* Tell whether the iterator is still at the start
*/
simdjson_really_inline bool at_start() const noexcept;
simdjson_really_inline bool at_root() const noexcept;
/**
* Assert if the iterator is not at the start
*/
simdjson_really_inline void assert_at_start() const noexcept;
simdjson_really_inline void assert_at_root() const noexcept;
/**
* Tell whether the iterator is at the EOF mark
@@ -39,6 +39,10 @@ simdjson_really_inline bool token_iterator::operator<=(const token_iterator &oth
return index <= other.index;
}
simdjson_really_inline const uint32_t *token_iterator::checkpoint() const noexcept {
return index;
}
} // namespace ondemand
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace simdjson
@@ -49,6 +49,11 @@ public:
*/
simdjson_really_inline const uint8_t *advance() noexcept;
/**
* Save the current index to be restored later.
*/
simdjson_really_inline const uint32_t *checkpoint() const noexcept;
// NOTE: we don't support a full C++ iterator interface, because we expect people to make
// different calls to advance the iterator based on *their own* state.
@@ -77,6 +82,7 @@ protected:
const uint32_t *index{};
friend class json_iterator;
friend class value_iterator;
friend simdjson_really_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta) noexcept;
};
@@ -2,20 +2,21 @@ namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace ondemand {
simdjson_really_inline value_iterator::value_iterator(json_iterator *json_iter, depth_t depth) noexcept
simdjson_really_inline value_iterator::value_iterator(json_iterator *json_iter, depth_t depth, const uint32_t *start_index) noexcept
: _json_iter{json_iter},
_depth{depth}
_depth{depth},
_start_index{start_index}
{
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_object() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
assert_at_start();
if (*_json_iter->advance() != '{') { logger::log_error(*_json_iter, "Not an object"); return INCORRECT_TYPE; }
return started_object();
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_start_object() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
assert_at_start();
if (*_json_iter->peek() != '{') { logger::log_error(*_json_iter, "Not an object"); return INCORRECT_TYPE; }
_json_iter->advance();
@@ -23,8 +24,6 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
}
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
if (*_json_iter->peek() == '}') {
logger::log_value(*_json_iter, "empty object");
_json_iter->advance();
@@ -37,7 +36,7 @@ simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object(
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
assert_at_next();
switch (*_json_iter->advance()) {
case '}':
@@ -54,7 +53,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::find_field_raw(const char *key) noexcept {
// We assume we are sitting at a key: at "key": <value>
SIMDJSON_ASSUME( _json_iter->_depth == _depth+1 );
assert_at_child();
bool has_next;
do {
@@ -81,7 +80,8 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
}
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth+1 );
logger::log_event(*this, "hi");
assert_at_child();
const uint8_t *key = _json_iter->advance();
if (*(key++) != '"') { return _json_iter->report_error(TAPE_ERROR, "Object key is not a string"); }
@@ -89,21 +89,21 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> val
}
simdjson_warn_unused simdjson_really_inline error_code value_iterator::field_value() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth+1 );
assert_at_child();
if (*_json_iter->advance() != ':') { return _json_iter->report_error(TAPE_ERROR, "Missing colon in object field"); }
return SUCCESS;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_array() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0);
assert_at_start();
if (*_json_iter->advance() != '[') { logger::log_error(*_json_iter, "Not an array"); return INCORRECT_TYPE; }
return started_array();
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_start_array() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0);
assert_at_start();
if (*_json_iter->peek() != '[') { logger::log_error(*_json_iter, "Not an array"); return INCORRECT_TYPE; }
_json_iter->advance();
@@ -111,8 +111,6 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
}
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
if (*_json_iter->peek() == ']') {
logger::log_value(*_json_iter, "empty array");
_json_iter->advance();
@@ -125,7 +123,7 @@ simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array()
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
assert_at_next();
switch (*_json_iter->advance()) {
case ']':
@@ -147,7 +145,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<std::string_view> va
return require_raw_json_string().unescape(_json_iter->string_buf_loc());
}
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::try_get_raw_json_string() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
assert_at_start();
logger::log_value(*_json_iter, "string", "", 0);
auto json = _json_iter->peek();
@@ -157,7 +155,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> val
return raw_json_string(json+1);
}
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::require_raw_json_string() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
assert_at_start();
logger::log_value(*_json_iter, "string", "", 0);
auto json = _json_iter->advance();
@@ -166,7 +164,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> val
return raw_json_string(json+1);
}
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_uint64() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
logger::log_value(*_json_iter, "uint64", "", 0);
uint64_t result;
@@ -176,14 +174,14 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iter
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::require_uint64() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
logger::log_value(*_json_iter, "uint64", "", 0);
_json_iter->ascend_to(depth()-1);
return numberparsing::parse_unsigned(_json_iter->advance());
}
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_int64() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
logger::log_value(*_json_iter, "int64", "", 0);
int64_t result;
@@ -193,14 +191,14 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_itera
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::require_int64() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
logger::log_value(*_json_iter, "int64", "", 0);
_json_iter->ascend_to(depth()-1);
return numberparsing::parse_integer(_json_iter->advance());
}
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_double() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
logger::log_value(*_json_iter, "double", "", 0);
double result;
@@ -210,7 +208,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterat
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::require_double() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
logger::log_value(*_json_iter, "double", "", 0);
_json_iter->ascend_to(depth()-1);
@@ -225,7 +223,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
return simdjson_result<bool>(!not_true);
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_get_bool() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
bool result;
SIMDJSON_TRY( parse_bool(_json_iter->peek()).get(result) );
@@ -234,7 +232,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::require_bool() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
_json_iter->ascend_to(depth()-1);
return parse_bool(_json_iter->advance());
@@ -247,7 +245,7 @@ simdjson_really_inline bool value_iterator::is_null(const uint8_t *json) const n
return false;
}
simdjson_really_inline bool value_iterator::is_null() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
if (is_null(_json_iter->peek())) {
_json_iter->advance();
@@ -257,7 +255,7 @@ simdjson_really_inline bool value_iterator::is_null() noexcept {
return false;
}
simdjson_really_inline bool value_iterator::require_null() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
assert_at_non_root_start();
_json_iter->ascend_to(depth()-1);
return is_null(_json_iter->advance());
@@ -266,8 +264,6 @@ simdjson_really_inline bool value_iterator::require_null() noexcept {
constexpr const uint32_t MAX_INT_LENGTH = 1024;
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::parse_root_uint64(const uint8_t *json, uint32_t max_len) const noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
uint8_t tmpbuf[20+1]; // <20 digits> is the longest possible unsigned integer
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 20 characters"); return NUMBER_ERROR; }
logger::log_value(*_json_iter, "uint64", "", 0);
@@ -276,7 +272,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iter
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_root_uint64() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
uint64_t result;
SIMDJSON_TRY( parse_root_uint64(_json_iter->peek(), _json_iter->peek_length()).get(result) );
@@ -284,14 +280,12 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iter
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::require_root_uint64() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
auto max_len = _json_iter->peek_length();
return parse_root_uint64(_json_iter->advance(), max_len);
}
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::parse_root_int64(const uint8_t *json, uint32_t max_len) const noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
uint8_t tmpbuf[20+1]; // -<19 digits> is the longest possible integer
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 20 characters"); return NUMBER_ERROR; }
logger::log_value(*_json_iter, "int64", "", 0);
@@ -300,7 +294,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_itera
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_root_int64() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
int64_t result;
SIMDJSON_TRY( parse_root_int64(_json_iter->peek(), _json_iter->peek_length()).get(result) );
@@ -308,14 +302,12 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_itera
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::require_root_int64() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
auto max_len = _json_iter->peek_length();
return parse_root_int64(_json_iter->advance(), max_len);
}
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::parse_root_double(const uint8_t *json, uint32_t max_len) const noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
// Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/, 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest number: -0.<fraction>e-308.
uint8_t tmpbuf[1074+8+1];
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 1082 characters"); return NUMBER_ERROR; }
@@ -325,7 +317,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterat
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_root_double() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
double result;
SIMDJSON_TRY( parse_root_double(_json_iter->peek(), _json_iter->peek_length()).get(result) );
@@ -333,20 +325,18 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterat
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::require_root_double() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
auto max_len = _json_iter->peek_length();
return parse_root_double(_json_iter->advance(), max_len);
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::parse_root_bool(const uint8_t *json, uint32_t max_len) const noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
uint8_t tmpbuf[5+1];
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Not a boolean"); return INCORRECT_TYPE; }
return parse_bool(tmpbuf);
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_get_root_bool() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
bool result;
SIMDJSON_TRY( parse_root_bool(_json_iter->peek(), _json_iter->peek_length()).get(result) );
@@ -354,38 +344,39 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
return result;
}
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::require_root_bool() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
auto max_len = _json_iter->peek_length();
return parse_root_bool(_json_iter->advance(), max_len);
}
simdjson_really_inline bool value_iterator::is_root_null(const uint8_t *json, uint32_t max_len) const noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
uint8_t tmpbuf[4+1];
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { return false; }
return is_null(tmpbuf);
}
simdjson_really_inline bool value_iterator::is_root_null() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
if (!is_root_null(_json_iter->peek(), _json_iter->peek_length())) { return false; }
_json_iter->advance();
return true;
}
simdjson_really_inline bool value_iterator::require_root_null() noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
assert_at_root();
auto max_len = _json_iter->peek_length();
return is_root_null(_json_iter->advance(), max_len);
}
simdjson_warn_unused simdjson_really_inline error_code value_iterator::skip_child() noexcept {
SIMDJSON_ASSUME( _json_iter->token.index > _start_index );
SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
return _json_iter->skip_child(depth());
}
simdjson_really_inline value_iterator value_iterator::child() const noexcept {
SIMDJSON_ASSUME( _json_iter->_depth == _depth+1 );
return { _json_iter, depth()+1 };
assert_at_child();
return { _json_iter, depth()+1, _json_iter->token.checkpoint() };
}
simdjson_really_inline bool value_iterator::is_open() const noexcept {
@@ -413,6 +404,35 @@ simdjson_warn_unused simdjson_really_inline json_iterator &value_iterator::json_
return *_json_iter;
}
simdjson_really_inline void value_iterator::assert_at_start() const noexcept {
SIMDJSON_ASSUME( _json_iter->token.index == _start_index );
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
SIMDJSON_ASSUME( _depth > 0 );
}
simdjson_really_inline void value_iterator::assert_at_next() const noexcept {
SIMDJSON_ASSUME( _json_iter->token.index > _start_index );
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
SIMDJSON_ASSUME( _depth > 0 );
}
simdjson_really_inline void value_iterator::assert_at_child() const noexcept {
SIMDJSON_ASSUME( _json_iter->token.index > _start_index );
SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
SIMDJSON_ASSUME( _depth > 0 );
}
simdjson_really_inline void value_iterator::assert_at_root() const noexcept {
assert_at_start();
SIMDJSON_ASSUME( _depth == 1 );
}
simdjson_really_inline void value_iterator::assert_at_non_root_start() const noexcept {
assert_at_start();
SIMDJSON_ASSUME( _depth > 1 );
}
} // namespace ondemand
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace simdjson
@@ -23,6 +23,8 @@ protected:
json_iterator *_json_iter{};
/** The depth of this value */
depth_t _depth{};
/** The starting token index for this value */
const uint32_t *_start_index{};
public:
simdjson_really_inline value_iterator() noexcept = default;
@@ -246,7 +248,7 @@ public:
/** @} */
protected:
simdjson_really_inline value_iterator(json_iterator *json_iter, depth_t depth) noexcept;
simdjson_really_inline value_iterator(json_iterator *json_iter, depth_t depth, const uint32_t *start_index) noexcept;
simdjson_really_inline bool is_null(const uint8_t *json) const noexcept;
simdjson_really_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
simdjson_really_inline bool is_root_null(const uint8_t *json, uint32_t max_len) const noexcept;
@@ -255,6 +257,12 @@ protected:
simdjson_really_inline simdjson_result<int64_t> parse_root_int64(const uint8_t *json, uint32_t max_len) const noexcept;
simdjson_really_inline simdjson_result<double> parse_root_double(const uint8_t *json, uint32_t max_len) const noexcept;
simdjson_really_inline void assert_at_start() const noexcept;
simdjson_really_inline void assert_at_root() const noexcept;
simdjson_really_inline void assert_at_child() const noexcept;
simdjson_really_inline void assert_at_next() const noexcept;
simdjson_really_inline void assert_at_non_root_start() const noexcept;
friend class document;
friend class object;
friend class array;