Support reading scalars out of order

This commit is contained in:
John Keiser 2021-01-07 15:20:31 -08:00
parent 66db102c70
commit 0f515785c6
8 changed files with 187 additions and 136 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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 );

View File

@ -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;

View File

@ -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() {

View File

@ -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;
}