Support reading scalars out of order
This commit is contained in:
parent
66db102c70
commit
0f515785c6
|
@ -177,6 +177,7 @@ protected:
|
|||
friend class parser;
|
||||
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;
|
||||
friend simdjson_really_inline void logger::log_line(const json_iterator &iter, const uint32_t *index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail) noexcept;
|
||||
}; // json_iterator
|
||||
|
||||
} // namespace ondemand
|
||||
|
|
|
@ -24,6 +24,9 @@ simdjson_really_inline void log_event(const json_iterator &iter, const char *typ
|
|||
simdjson_really_inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
|
||||
log_line(iter, "", type, detail, delta, depth_delta);
|
||||
}
|
||||
simdjson_really_inline void log_value(const json_iterator &iter, const uint32_t *index, depth_t depth, const char *type, std::string_view detail) noexcept {
|
||||
log_line(iter, index, depth, "", type, detail);
|
||||
}
|
||||
simdjson_really_inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
|
||||
log_line(iter, "+", type, "", delta, depth_delta);
|
||||
log_depth++;
|
||||
|
@ -35,6 +38,9 @@ simdjson_really_inline void log_end_value(const json_iterator &iter, const char
|
|||
simdjson_really_inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
|
||||
log_line(iter, "ERROR: ", error, detail, delta, depth_delta);
|
||||
}
|
||||
simdjson_really_inline void log_error(const json_iterator &iter, const uint32_t *index, depth_t depth, const char *error, const char *detail) noexcept {
|
||||
log_line(iter, index, depth, "ERROR: ", error, detail);
|
||||
}
|
||||
|
||||
simdjson_really_inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
|
||||
log_event(iter.json_iter(), type, detail, delta, depth_delta);
|
||||
|
@ -76,8 +82,12 @@ simdjson_really_inline void log_headers() noexcept {
|
|||
}
|
||||
|
||||
simdjson_really_inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta) noexcept {
|
||||
log_line(iter, iter.token.index+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail);
|
||||
}
|
||||
simdjson_really_inline void log_line(const json_iterator &iter, const uint32_t *index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail) noexcept {
|
||||
if (LOG_ENABLED) {
|
||||
const int indent = (log_depth+depth_delta)*2;
|
||||
const int indent = depth*2;
|
||||
const auto buf = iter.token.buf;
|
||||
printf("| %*s%s%-*s ",
|
||||
indent, "",
|
||||
title_prefix,
|
||||
|
@ -86,21 +96,23 @@ simdjson_really_inline void log_line(const json_iterator &iter, const char *titl
|
|||
{
|
||||
// Print the current structural.
|
||||
printf("| ");
|
||||
auto current_structural = &buf[*index];
|
||||
for (int i=0;i<LOG_BUFFER_LEN;i++) {
|
||||
printf("%c", printable_char(iter.peek(delta)[i]));
|
||||
printf("%c", printable_char(current_structural[i]));
|
||||
}
|
||||
printf(" ");
|
||||
}
|
||||
{
|
||||
// Print the next structural.
|
||||
printf("| ");
|
||||
auto next_structural = &buf[*(index+1)];
|
||||
for (int i=0;i<LOG_SMALL_BUFFER_LEN;i++) {
|
||||
printf("%c", printable_char(iter.peek(delta+1)[i]));
|
||||
printf("%c", printable_char(next_structural[i]));
|
||||
}
|
||||
printf(" ");
|
||||
}
|
||||
// printf("| %5u ", iter.token.peek_index(delta+1));
|
||||
printf("| %5u ", iter.depth());
|
||||
// printf("| %5u ", *(index+1));
|
||||
printf("| %5u ", depth);
|
||||
printf("| %.*s ", int(detail.size()), detail.data());
|
||||
printf("|\n");
|
||||
fflush(stdout);
|
||||
|
|
|
@ -15,11 +15,14 @@ namespace logger {
|
|||
|
||||
static simdjson_really_inline void log_headers() noexcept;
|
||||
static simdjson_really_inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta) noexcept;
|
||||
static simdjson_really_inline void log_line(const json_iterator &iter, const uint32_t *index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail) noexcept;
|
||||
static simdjson_really_inline void log_event(const json_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
|
||||
static simdjson_really_inline void log_value(const json_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
|
||||
static simdjson_really_inline void log_value(const json_iterator &iter, const uint32_t *index, depth_t depth, const char *type, std::string_view detail="") noexcept;
|
||||
static simdjson_really_inline void log_start_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
|
||||
static simdjson_really_inline void log_end_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
|
||||
static simdjson_really_inline void log_error(const json_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
|
||||
static simdjson_really_inline void log_error(const json_iterator &iter, const uint32_t *index, depth_t depth, const char *error, const char *detail="") noexcept;
|
||||
|
||||
static simdjson_really_inline void log_event(const value_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
|
||||
static simdjson_really_inline void log_value(const value_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
|
||||
|
|
|
@ -90,6 +90,7 @@ protected:
|
|||
friend class value_iterator;
|
||||
friend class object;
|
||||
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;
|
||||
friend simdjson_really_inline void logger::log_line(const json_iterator &iter, const uint32_t *index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail) noexcept;
|
||||
};
|
||||
|
||||
} // namespace ondemand
|
||||
|
|
|
@ -305,209 +305,142 @@ 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 {
|
||||
assert_at_start();
|
||||
|
||||
logger::log_value(*_json_iter, "string", "", 0);
|
||||
auto json = _json_iter->peek();
|
||||
if (*json != '"') { logger::log_error(*_json_iter, "Not a string"); return INCORRECT_TYPE; }
|
||||
_json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
auto json = peek_scalar();
|
||||
if (*json != '"') { return incorrect_type_error("Not a string"); }
|
||||
advance_scalar("string");
|
||||
return raw_json_string(json+1);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::require_raw_json_string() noexcept {
|
||||
assert_at_start();
|
||||
|
||||
logger::log_value(*_json_iter, "string", "", 0);
|
||||
auto json = _json_iter->advance();
|
||||
if (*json != '"') { logger::log_error(*_json_iter, "Not a string"); return INCORRECT_TYPE; }
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
auto json = advance_scalar("string");
|
||||
if (*json != '"') { return incorrect_type_error("Not a string"); }
|
||||
return raw_json_string(json+1);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_uint64() noexcept {
|
||||
assert_at_non_root_start();
|
||||
|
||||
logger::log_value(*_json_iter, "uint64", "", 0);
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_uint64() noexcept {
|
||||
uint64_t result;
|
||||
SIMDJSON_TRY( numberparsing::parse_unsigned(_json_iter->peek()).get(result) );
|
||||
_json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
SIMDJSON_TRY( numberparsing::parse_unsigned(peek_scalar()).get(result) );
|
||||
advance_non_root_scalar("uint64");
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::require_uint64() noexcept {
|
||||
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());
|
||||
return numberparsing::parse_unsigned(advance_non_root_scalar("uint64"));
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_int64() noexcept {
|
||||
assert_at_non_root_start();
|
||||
|
||||
logger::log_value(*_json_iter, "int64", "", 0);
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_int64() noexcept {
|
||||
int64_t result;
|
||||
SIMDJSON_TRY( numberparsing::parse_integer(_json_iter->peek()).get(result) );
|
||||
_json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
SIMDJSON_TRY( numberparsing::parse_integer(peek_scalar()).get(result) );
|
||||
advance_non_root_scalar("int64");
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::require_int64() noexcept {
|
||||
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());
|
||||
return numberparsing::parse_integer(advance_non_root_scalar("int64"));
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_double() noexcept {
|
||||
assert_at_non_root_start();
|
||||
|
||||
logger::log_value(*_json_iter, "double", "", 0);
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_double() noexcept {
|
||||
double result;
|
||||
SIMDJSON_TRY( numberparsing::parse_double(_json_iter->peek()).get(result) );
|
||||
_json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
SIMDJSON_TRY( numberparsing::parse_double(peek_scalar()).get(result) );
|
||||
advance_non_root_scalar("double");
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::require_double() noexcept {
|
||||
assert_at_non_root_start();
|
||||
|
||||
logger::log_value(*_json_iter, "double", "", 0);
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
return numberparsing::parse_double(_json_iter->advance());
|
||||
return numberparsing::parse_double(advance_non_root_scalar("double"));
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
|
||||
logger::log_value(*_json_iter, "bool", "");
|
||||
auto not_true = atomparsing::str4ncmp(json, "true");
|
||||
auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
|
||||
bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
|
||||
if (error) { logger::log_error(*_json_iter, "Not a boolean"); return INCORRECT_TYPE; }
|
||||
if (error) { return incorrect_type_error("Not a boolean"); }
|
||||
return simdjson_result<bool>(!not_true);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_get_bool() noexcept {
|
||||
assert_at_non_root_start();
|
||||
|
||||
bool result;
|
||||
SIMDJSON_TRY( parse_bool(_json_iter->peek()).get(result) );
|
||||
_json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
SIMDJSON_TRY( parse_bool(peek_scalar()).get(result) );
|
||||
advance_non_root_scalar("bool");
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::require_bool() noexcept {
|
||||
assert_at_non_root_start();
|
||||
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
return parse_bool(_json_iter->advance());
|
||||
return parse_bool(advance_non_root_scalar("bool"));
|
||||
}
|
||||
simdjson_really_inline bool value_iterator::is_null(const uint8_t *json) const noexcept {
|
||||
if (!atomparsing::str4ncmp(json, "null")) {
|
||||
logger::log_value(*_json_iter, "null", "");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return !atomparsing::str4ncmp(json, "null");
|
||||
}
|
||||
simdjson_really_inline bool value_iterator::is_null() noexcept {
|
||||
assert_at_non_root_start();
|
||||
|
||||
if (is_null(_json_iter->peek())) {
|
||||
_json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
if (is_null(peek_scalar())) {
|
||||
advance_non_root_scalar("null");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
simdjson_really_inline bool value_iterator::require_null() noexcept {
|
||||
assert_at_non_root_start();
|
||||
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
return is_null(_json_iter->advance());
|
||||
return is_null(advance_non_root_scalar("null"));
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
auto result = numberparsing::parse_unsigned(tmpbuf);
|
||||
if (result.error()) { logger::log_error(*_json_iter, "Error parsing unsigned integer"); }
|
||||
return result;
|
||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, _start_index, depth(), "Root number more than 20 characters"); return NUMBER_ERROR; }
|
||||
return numberparsing::parse_unsigned(tmpbuf);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_root_uint64() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
uint64_t result;
|
||||
SIMDJSON_TRY( parse_root_uint64(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
||||
_json_iter->advance();
|
||||
SIMDJSON_TRY( parse_root_uint64(peek_scalar(), peek_scalar_length()).get(result) );
|
||||
advance_root_scalar("uint64");
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::require_root_uint64() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
auto max_len = _json_iter->peek_length();
|
||||
return parse_root_uint64(_json_iter->advance(), max_len);
|
||||
auto max_len = peek_scalar_length();
|
||||
return parse_root_uint64(advance_root_scalar("uint64"), 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 {
|
||||
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);
|
||||
auto result = numberparsing::parse_integer(tmpbuf);
|
||||
if (result.error()) { logger::log_error(*_json_iter, "Error parsing integer"); }
|
||||
return result;
|
||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, _start_index, depth(), "Root number more than 20 characters"); return NUMBER_ERROR; }
|
||||
return numberparsing::parse_integer(tmpbuf);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_root_int64() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
int64_t result;
|
||||
SIMDJSON_TRY( parse_root_int64(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
||||
_json_iter->advance();
|
||||
SIMDJSON_TRY( parse_root_int64(peek_scalar(), peek_scalar_length()).get(result) );
|
||||
advance_root_scalar("int64");
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::require_root_int64() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
auto max_len = _json_iter->peek_length();
|
||||
return parse_root_int64(_json_iter->advance(), max_len);
|
||||
auto max_len = peek_scalar_length();
|
||||
return parse_root_int64(advance_root_scalar("int64"), 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 {
|
||||
// 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; }
|
||||
logger::log_value(*_json_iter, "double", "", 0);
|
||||
auto result = numberparsing::parse_double(tmpbuf);
|
||||
if (result.error()) { logger::log_error(*_json_iter, "Error parsing double"); }
|
||||
return result;
|
||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, _start_index, depth(), "Root number more than 1082 characters"); return NUMBER_ERROR; }
|
||||
return numberparsing::parse_double(tmpbuf);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_root_double() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
double result;
|
||||
SIMDJSON_TRY( parse_root_double(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
||||
_json_iter->advance();
|
||||
SIMDJSON_TRY( parse_root_double(peek_scalar(), peek_scalar_length()).get(result) );
|
||||
advance_root_scalar("double");
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::require_root_double() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
auto max_len = _json_iter->peek_length();
|
||||
return parse_root_double(_json_iter->advance(), max_len);
|
||||
auto max_len = peek_scalar_length();
|
||||
return parse_root_double(advance_root_scalar("double"), 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 {
|
||||
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; }
|
||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { return incorrect_type_error("Not a boolean"); }
|
||||
return parse_bool(tmpbuf);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_get_root_bool() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
bool result;
|
||||
SIMDJSON_TRY( parse_root_bool(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
||||
_json_iter->advance();
|
||||
SIMDJSON_TRY( parse_root_bool(peek_scalar(), peek_scalar_length()).get(result) );
|
||||
advance_root_scalar("bool");
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::require_root_bool() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
auto max_len = _json_iter->peek_length();
|
||||
return parse_root_bool(_json_iter->advance(), max_len);
|
||||
auto max_len = peek_scalar_length();
|
||||
return parse_root_bool(advance_root_scalar("bool"), max_len);
|
||||
}
|
||||
simdjson_really_inline bool value_iterator::is_root_null(const uint8_t *json, uint32_t max_len) const noexcept {
|
||||
uint8_t tmpbuf[4+1];
|
||||
|
@ -515,17 +448,13 @@ simdjson_really_inline bool value_iterator::is_root_null(const uint8_t *json, ui
|
|||
return is_null(tmpbuf);
|
||||
}
|
||||
simdjson_really_inline bool value_iterator::is_root_null() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
if (!is_root_null(_json_iter->peek(), _json_iter->peek_length())) { return false; }
|
||||
_json_iter->advance();
|
||||
if (!is_root_null(peek_scalar(), peek_scalar_length())) { return false; }
|
||||
advance_root_scalar("null");
|
||||
return true;
|
||||
}
|
||||
simdjson_really_inline bool value_iterator::require_root_null() noexcept {
|
||||
assert_at_root();
|
||||
|
||||
auto max_len = _json_iter->peek_length();
|
||||
return is_root_null(_json_iter->advance(), max_len);
|
||||
auto max_len = peek_scalar_length();
|
||||
return is_root_null(advance_root_scalar("null"), max_len);
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_really_inline error_code value_iterator::skip_child() noexcept {
|
||||
|
@ -577,6 +506,50 @@ simdjson_warn_unused simdjson_really_inline json_iterator &value_iterator::json_
|
|||
return *_json_iter;
|
||||
}
|
||||
|
||||
simdjson_really_inline const uint8_t *value_iterator::peek_scalar() const noexcept {
|
||||
return &_json_iter->token.buf[*_start_index];
|
||||
}
|
||||
simdjson_really_inline uint32_t value_iterator::peek_scalar_length() const noexcept {
|
||||
return *(_start_index+1) - *_start_index;
|
||||
}
|
||||
|
||||
simdjson_really_inline const uint8_t *value_iterator::advance_scalar(const char *type) const noexcept {
|
||||
logger::log_value(*_json_iter, _start_index, depth(), type);
|
||||
if (!is_at_start()) { return peek_scalar(); }
|
||||
|
||||
assert_at_start();
|
||||
auto result = _json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
return result;
|
||||
}
|
||||
simdjson_really_inline const uint8_t *value_iterator::advance_root_scalar(const char *type) const noexcept {
|
||||
logger::log_value(*_json_iter, _start_index, depth(), type);
|
||||
if (is_at_start()) { return peek_scalar(); }
|
||||
|
||||
assert_at_root();
|
||||
auto result = _json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
return result;
|
||||
}
|
||||
simdjson_really_inline const uint8_t *value_iterator::advance_non_root_scalar(const char *type) const noexcept {
|
||||
logger::log_value(*_json_iter, _start_index, depth(), type);
|
||||
if (is_at_start()) { return peek_scalar(); }
|
||||
|
||||
assert_at_non_root_start();
|
||||
auto result = _json_iter->advance();
|
||||
_json_iter->ascend_to(depth()-1);
|
||||
return result;
|
||||
}
|
||||
|
||||
simdjson_really_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
|
||||
logger::log_error(*_json_iter, _start_index, depth(), message);
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
|
||||
simdjson_really_inline bool value_iterator::is_at_start() const noexcept {
|
||||
return _json_iter->token.index == _start_index;
|
||||
}
|
||||
|
||||
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 );
|
||||
|
|
|
@ -292,6 +292,15 @@ 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 const uint8_t *peek_scalar() const noexcept;
|
||||
simdjson_really_inline uint32_t peek_scalar_length() const noexcept;
|
||||
simdjson_really_inline const uint8_t *advance_scalar(const char *type) const noexcept;
|
||||
simdjson_really_inline const uint8_t *advance_root_scalar(const char *type) const noexcept;
|
||||
simdjson_really_inline const uint8_t *advance_non_root_scalar(const char *type) const noexcept;
|
||||
|
||||
simdjson_really_inline error_code incorrect_type_error(const char *message) const noexcept;
|
||||
|
||||
simdjson_really_inline bool is_at_start() 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;
|
||||
|
|
|
@ -664,18 +664,28 @@ namespace dom_api_tests {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
bool test_scalar_value(const padded_string &json, const T &expected) {
|
||||
bool test_scalar_value(const padded_string &json, const T &expected, bool test_twice=true) {
|
||||
std::cout << "- JSON: " << json << endl;
|
||||
SUBTEST( "simdjson_result<document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
T actual;
|
||||
ASSERT_SUCCESS( doc_result.get(actual) );
|
||||
ASSERT_EQUAL( expected, actual );
|
||||
// Test it twice (scalars can be retrieved more than once)
|
||||
if (test_twice) {
|
||||
ASSERT_SUCCESS( doc_result.get(actual) );
|
||||
ASSERT_EQUAL( expected, actual );
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
SUBTEST( "document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
T actual;
|
||||
ASSERT_SUCCESS( doc_result.get(actual) );
|
||||
ASSERT_EQUAL( expected, actual );
|
||||
// Test it twice (scalars can be retrieved more than once)
|
||||
if (test_twice) {
|
||||
ASSERT_SUCCESS( doc_result.get(actual) );
|
||||
ASSERT_EQUAL( expected, actual );
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
padded_string array_json = std::string("[") + std::string(json) + "]";
|
||||
|
@ -686,6 +696,11 @@ namespace dom_api_tests {
|
|||
T actual;
|
||||
ASSERT_SUCCESS( val_result.get(actual) );
|
||||
ASSERT_EQUAL(expected, actual);
|
||||
// Test it twice (scalars can be retrieved more than once)
|
||||
if (test_twice) {
|
||||
ASSERT_SUCCESS( val_result.get(actual) );
|
||||
ASSERT_EQUAL(expected, actual);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL(count, 1);
|
||||
|
@ -699,6 +714,11 @@ namespace dom_api_tests {
|
|||
T actual;
|
||||
ASSERT_SUCCESS( val.get(actual) );
|
||||
ASSERT_EQUAL(expected, actual);
|
||||
// Test it twice (scalars can be retrieved more than once)
|
||||
if (test_twice) {
|
||||
ASSERT_SUCCESS( val.get(actual) );
|
||||
ASSERT_EQUAL(expected, actual);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL(count, 1);
|
||||
|
@ -706,9 +726,14 @@ namespace dom_api_tests {
|
|||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool string_value() {
|
||||
TEST_START();
|
||||
return test_scalar_value(R"("hi")"_padded, std::string_view("hi"));
|
||||
// We can't retrieve a small string twice because it will blow out the string buffer
|
||||
if (!test_scalar_value(R"("hi")"_padded, std::string_view("hi"), false)) { return false; }
|
||||
// ... unless the document is big enough to have a big string buffer :)
|
||||
if (!test_scalar_value(R"("hi" )"_padded, std::string_view("hi"))) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool numeric_values() {
|
||||
|
|
|
@ -108,8 +108,8 @@ namespace ordering_tests {
|
|||
double x{0};
|
||||
double y{0};
|
||||
double z{0};
|
||||
for (ondemand::object point_object : doc["coordinates"]) {
|
||||
for (auto field : point_object) {
|
||||
for (auto point_object : doc["coordinates"]) {
|
||||
for (auto field : point_object.get_object()) {
|
||||
if (field.key() == "z") { z += double(field.value()); }
|
||||
else if (field.key() == "x") { x += double(field.value()); }
|
||||
else if (field.key() == "y") { y += double(field.value()); }
|
||||
|
@ -117,6 +117,31 @@ namespace ordering_tests {
|
|||
}
|
||||
return (x == 1.1) && (y == 2.2) && (z == 3.3);
|
||||
}
|
||||
|
||||
bool use_values_out_of_order_after_array() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto doc = parser.iterate(json);
|
||||
simdjson_result<ondemand::value> x{}, y{}, z{};
|
||||
for (auto point_object : doc["coordinates"]) {
|
||||
x = point_object["x"];
|
||||
y = point_object["y"];
|
||||
z = point_object["z"];
|
||||
}
|
||||
return (double(x) == 1.1) && (double(z) == 3.3) && (double(y) == 2.2);
|
||||
}
|
||||
|
||||
bool use_object_multiple_times_out_of_order() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto json2 = "{\"coordinates\":{\"x\":1.1,\"y\":2.2,\"z\":3.3}}"_padded;
|
||||
auto doc = parser.iterate(json2);
|
||||
auto x = doc["coordinates"]["x"];
|
||||
auto y = doc["coordinates"]["y"];
|
||||
auto z = doc["coordinates"]["z"];
|
||||
return (double(x) == 1.1) && (double(z) == 3.3) && (double(y) == 2.2);
|
||||
}
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
bool run() {
|
||||
|
@ -129,6 +154,8 @@ namespace ordering_tests {
|
|||
out_of_order_object_find_field_unordered() &&
|
||||
out_of_order_object_find_field() &&
|
||||
foreach_object_field_lookup() &&
|
||||
use_values_out_of_order_after_array() &&
|
||||
use_object_multiple_times_out_of_order() &&
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue