Merge pull request #1414 from simdjson/jkeiser/array-assert
Fix #1409 (assert when trying to get one value as multiple types)
This commit is contained in:
commit
3f2639a655
|
@ -423,7 +423,7 @@ simdjson_really_inline error_code parse_exponent(simdjson_unused const uint8_t *
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
simdjson_really_inline int significant_digits(const uint8_t * start_digits, int digit_count) {
|
||||
simdjson_really_inline size_t significant_digits(const uint8_t * start_digits, size_t digit_count) {
|
||||
// It is possible that the integer had an overflow.
|
||||
// We have to handle the case where we have 0.0000somenumber.
|
||||
const uint8_t *start = start_digits;
|
||||
|
@ -431,11 +431,11 @@ simdjson_really_inline int significant_digits(const uint8_t * start_digits, int
|
|||
start++;
|
||||
}
|
||||
// we over-decrement by one when there is a '.'
|
||||
return digit_count - int(start - start_digits);
|
||||
return digit_count - size_t(start - start_digits);
|
||||
}
|
||||
|
||||
template<typename W>
|
||||
simdjson_really_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, int digit_count, int64_t exponent, W &writer) {
|
||||
simdjson_really_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer) {
|
||||
// If we frequently had to deal with long strings of digits,
|
||||
// we could extend our code by using a 128-bit integer instead
|
||||
// of a 64-bit integer. However, this is uncommon in practice.
|
||||
|
@ -529,7 +529,8 @@ simdjson_really_inline error_code parse_number(const uint8_t *const src, W &writ
|
|||
while (parse_digit(*p, i)) { p++; }
|
||||
|
||||
// If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
|
||||
int digit_count = int(p - start_digits);
|
||||
// Optimization note: size_t is expected to be unsigned.
|
||||
size_t digit_count = size_t(p - start_digits);
|
||||
if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return INVALID_NUMBER(src); }
|
||||
|
||||
//
|
||||
|
@ -549,23 +550,23 @@ simdjson_really_inline error_code parse_number(const uint8_t *const src, W &writ
|
|||
SIMDJSON_TRY( parse_exponent(src, p, exponent) );
|
||||
}
|
||||
if (is_float) {
|
||||
const bool clean_end = jsoncharutils::is_structural_or_whitespace(*p);
|
||||
const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
|
||||
SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
|
||||
if (!clean_end) { return INVALID_NUMBER(src); }
|
||||
if (dirty_end) { return INVALID_NUMBER(src); }
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// The longest negative 64-bit number is 19 digits.
|
||||
// The longest positive 64-bit number is 20 digits.
|
||||
// We do it this way so we don't trigger this branch unless we must.
|
||||
int longest_digit_count = negative ? 19 : 20;
|
||||
size_t longest_digit_count = negative ? 19 : 20;
|
||||
if (digit_count > longest_digit_count) { return INVALID_NUMBER(src); }
|
||||
if (digit_count == longest_digit_count) {
|
||||
if (negative) {
|
||||
// Anything negative above INT64_MAX+1 is invalid
|
||||
if (i > uint64_t(INT64_MAX)+1) { return INVALID_NUMBER(src); }
|
||||
WRITE_INTEGER(~i+1, src, writer);
|
||||
if (!jsoncharutils::is_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
|
||||
if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
|
||||
return SUCCESS;
|
||||
// Positive overflow check:
|
||||
// - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
|
||||
|
@ -588,16 +589,81 @@ simdjson_really_inline error_code parse_number(const uint8_t *const src, W &writ
|
|||
} else {
|
||||
WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
|
||||
}
|
||||
if (!jsoncharutils::is_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
|
||||
if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// SAX functions
|
||||
// Inlineable functions
|
||||
namespace {
|
||||
|
||||
// This table can be used to characterize the final character of an integer
|
||||
// string. For JSON structural character and allowable white space characters,
|
||||
// we return SUCCESS. For 'e', '.' and 'E', we return INCORRECT_TYPE. Otherwise
|
||||
// we return NUMBER_ERROR.
|
||||
// Optimization note: we could easily reduce the size of the table by half (to 128)
|
||||
// at the cost of an extra branch.
|
||||
// Optimization note: we want the values to use at most 8 bits (not, e.g., 32 bits):
|
||||
static_assert(error_code(uint8_t(NUMBER_ERROR))== NUMBER_ERROR, "bad NUMBER_ERROR cast");
|
||||
static_assert(error_code(uint8_t(SUCCESS))== SUCCESS, "bad NUMBER_ERROR cast");
|
||||
static_assert(error_code(uint8_t(INCORRECT_TYPE))== INCORRECT_TYPE, "bad NUMBER_ERROR cast");
|
||||
|
||||
const uint8_t integer_string_finisher[256] = {
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
|
||||
SUCCESS, NUMBER_ERROR, NUMBER_ERROR, SUCCESS, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, SUCCESS, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, SUCCESS,
|
||||
NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, SUCCESS, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, INCORRECT_TYPE,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, SUCCESS, NUMBER_ERROR, SUCCESS, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, INCORRECT_TYPE, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, SUCCESS, NUMBER_ERROR,
|
||||
SUCCESS, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR, NUMBER_ERROR,
|
||||
NUMBER_ERROR};
|
||||
|
||||
// Parse any number from 0 to 18,446,744,073,709,551,615
|
||||
simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept {
|
||||
const uint8_t *p = src;
|
||||
|
||||
//
|
||||
// Parse the integer part.
|
||||
//
|
||||
|
@ -607,13 +673,23 @@ simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned(
|
|||
while (parse_digit(*p, i)) { p++; }
|
||||
|
||||
// If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
|
||||
int digit_count = int(p - start_digits);
|
||||
if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return NUMBER_ERROR; }
|
||||
if (!jsoncharutils::is_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
|
||||
|
||||
// Optimization note: size_t is expected to be unsigned.
|
||||
size_t digit_count = size_t(p - start_digits);
|
||||
// The longest positive 64-bit number is 20 digits.
|
||||
// We do it this way so we don't trigger this branch unless we must.
|
||||
if (digit_count > 20) { return NUMBER_ERROR; }
|
||||
// Optimization note: the compiler can probably merge
|
||||
// ((digit_count == 0) || (digit_count > 20))
|
||||
// into a single branch since digit_count is unsigned.
|
||||
if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
|
||||
// Here digit_count > 0.
|
||||
if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
|
||||
// We can do the following...
|
||||
// if (!jsoncharutils::is_structural_or_whitespace(*p)) {
|
||||
// return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
|
||||
// }
|
||||
// as a single table lookup:
|
||||
if (integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
|
||||
|
||||
if (digit_count == 20) {
|
||||
// Positive overflow check:
|
||||
// - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
|
||||
|
@ -627,7 +703,7 @@ simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned(
|
|||
// - Therefore, if the number is positive and lower than that, it's overflow.
|
||||
// - The value we are looking at is less than or equal to 9,223,372,036,854,775,808 (INT64_MAX).
|
||||
//
|
||||
if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return NUMBER_ERROR; }
|
||||
if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
|
||||
}
|
||||
|
||||
return i;
|
||||
|
@ -650,19 +726,28 @@ simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer(co
|
|||
while (parse_digit(*p, i)) { p++; }
|
||||
|
||||
// If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
|
||||
int digit_count = int(p - start_digits);
|
||||
if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return NUMBER_ERROR; }
|
||||
if (!jsoncharutils::is_structural_or_whitespace(*p)) { return NUMBER_ERROR; }
|
||||
|
||||
// Optimization note: size_t is expected to be unsigned.
|
||||
size_t digit_count = size_t(p - start_digits);
|
||||
// The longest negative 64-bit number is 19 digits.
|
||||
// The longest positive 64-bit number is 20 digits.
|
||||
// We do it this way so we don't trigger this branch unless we must.
|
||||
int longest_digit_count = negative ? 19 : 20;
|
||||
if (digit_count > longest_digit_count) { return NUMBER_ERROR; }
|
||||
size_t longest_digit_count = negative ? 19 : 20;
|
||||
// Optimization note: the compiler can probably merge
|
||||
// ((digit_count == 0) || (digit_count > longest_digit_count))
|
||||
// into a single branch since digit_count is unsigned.
|
||||
if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
|
||||
// Here digit_count > 0.
|
||||
if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
|
||||
// We can do the following...
|
||||
// if (!jsoncharutils::is_structural_or_whitespace(*p)) {
|
||||
// return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
|
||||
// }
|
||||
// as a single table lookup:
|
||||
if(integer_string_finisher[*p] != SUCCESS) { return error_code(integer_string_finisher[*p]); }
|
||||
if (digit_count == longest_digit_count) {
|
||||
if(negative) {
|
||||
if (negative) {
|
||||
// Anything negative above INT64_MAX+1 is invalid
|
||||
if (i > uint64_t(INT64_MAX)+1) { return NUMBER_ERROR; }
|
||||
if (i > uint64_t(INT64_MAX)+1) { return INCORRECT_TYPE; }
|
||||
return ~i+1;
|
||||
|
||||
// Positive overflow check:
|
||||
|
@ -677,7 +762,7 @@ simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer(co
|
|||
// - Therefore, if the number is positive and lower than that, it's overflow.
|
||||
// - The value we are looking at is less than or equal to 9,223,372,036,854,775,808 (INT64_MAX).
|
||||
//
|
||||
} else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return NUMBER_ERROR; }
|
||||
} else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
|
||||
}
|
||||
|
||||
return negative ? (~i+1) : i;
|
||||
|
@ -699,7 +784,8 @@ simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(cons
|
|||
bool leading_zero = (i == 0);
|
||||
while (parse_digit(*p, i)) { p++; }
|
||||
// no integer digits, or 0123 (zero must be solo)
|
||||
if ( p == src || (leading_zero && p != src+1)) { return NUMBER_ERROR; }
|
||||
if ( p == src ) { return INCORRECT_TYPE; }
|
||||
if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
|
||||
|
||||
//
|
||||
// Parse the decimal part.
|
||||
|
|
|
@ -50,11 +50,6 @@ simdjson_really_inline simdjson_result<array> array::start(value_iterator &iter)
|
|||
SIMDJSON_TRY( iter.start_array().get(has_value) );
|
||||
return array(iter);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<array> array::try_start(value_iterator &iter) noexcept {
|
||||
simdjson_unused bool has_value;
|
||||
SIMDJSON_TRY( iter.try_start_array().get(has_value) );
|
||||
return array(iter);
|
||||
}
|
||||
simdjson_really_inline array array::started(value_iterator &iter) noexcept {
|
||||
simdjson_unused bool has_value = iter.started_array();
|
||||
return array(iter);
|
||||
|
|
|
@ -41,14 +41,6 @@ protected:
|
|||
* @error INCORRECT_TYPE if the iterator is not at [.
|
||||
*/
|
||||
static simdjson_really_inline simdjson_result<array> start(value_iterator &iter) noexcept;
|
||||
/**
|
||||
* Begin array iteration.
|
||||
*
|
||||
* @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
|
||||
* resulting array.
|
||||
* @error INCORRECT_TYPE if the iterator is not at [.
|
||||
*/
|
||||
static simdjson_really_inline simdjson_result<array> try_start(value_iterator &iter) noexcept;
|
||||
/**
|
||||
* Begin array iteration.
|
||||
*
|
||||
|
|
|
@ -21,20 +21,28 @@ static simdjson_really_inline char printable_char(char c) {
|
|||
simdjson_really_inline void log_event(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 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, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
|
||||
log_line(iter, index, depth, "", type, detail);
|
||||
}
|
||||
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_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
|
||||
log_line(iter, index, depth, "+", type, detail);
|
||||
if (LOG_ENABLED) { log_depth++; }
|
||||
}
|
||||
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++;
|
||||
if (LOG_ENABLED) { log_depth++; }
|
||||
}
|
||||
|
||||
simdjson_really_inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
|
||||
log_depth--;
|
||||
if (LOG_ENABLED) { log_depth--; }
|
||||
log_line(iter, "-", type, "", delta, depth_delta);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -45,22 +53,26 @@ simdjson_really_inline void log_error(const json_iterator &iter, token_position
|
|||
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);
|
||||
}
|
||||
|
||||
simdjson_really_inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
|
||||
log_value(iter.json_iter(), type, detail, delta, depth_delta);
|
||||
}
|
||||
|
||||
simdjson_really_inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
|
||||
log_start_value(iter.json_iter(), type, delta, depth_delta);
|
||||
}
|
||||
|
||||
simdjson_really_inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
|
||||
log_end_value(iter.json_iter(), type, delta, depth_delta);
|
||||
}
|
||||
|
||||
simdjson_really_inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
|
||||
log_error(iter.json_iter(), error, detail, delta, depth_delta);
|
||||
}
|
||||
|
||||
simdjson_really_inline void log_headers() noexcept {
|
||||
log_depth = 0;
|
||||
if (LOG_ENABLED) {
|
||||
log_depth = 0;
|
||||
printf("\n");
|
||||
printf("| %-*s ", LOG_EVENT_LEN, "Event");
|
||||
printf("| %-*s ", LOG_BUFFER_LEN, "Buffer");
|
||||
|
|
|
@ -14,15 +14,16 @@ namespace logger {
|
|||
#endif
|
||||
|
||||
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, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail) 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_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, token_position index, depth_t depth, const char *type, std::string_view detail="") 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_start_value(const json_iterator &iter, token_position 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, token_position index, depth_t depth, const char *error, const char *detail="") 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_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;
|
||||
|
|
|
@ -38,11 +38,6 @@ simdjson_really_inline simdjson_result<object> object::start(value_iterator &ite
|
|||
SIMDJSON_TRY( iter.start_object().get(has_value) );
|
||||
return object(iter);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<object> object::try_start(value_iterator &iter) noexcept {
|
||||
simdjson_unused bool has_value;
|
||||
SIMDJSON_TRY( iter.try_start_object().get(has_value) );
|
||||
return object(iter);
|
||||
}
|
||||
simdjson_really_inline object object::started(value_iterator &iter) noexcept {
|
||||
simdjson_unused bool has_value = iter.started_object();
|
||||
return iter;
|
||||
|
|
|
@ -72,7 +72,6 @@ public:
|
|||
|
||||
protected:
|
||||
static simdjson_really_inline simdjson_result<object> start(value_iterator &iter) noexcept;
|
||||
static simdjson_really_inline simdjson_result<object> try_start(value_iterator &iter) noexcept;
|
||||
static simdjson_really_inline object started(value_iterator &iter) noexcept;
|
||||
static simdjson_really_inline object resume(const value_iterator &iter) noexcept;
|
||||
simdjson_really_inline object(const value_iterator &iter) noexcept;
|
||||
|
|
|
@ -13,26 +13,13 @@ simdjson_really_inline value value::resume(const value_iterator &iter) noexcept
|
|||
return iter;
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<array> value::get_array() && noexcept {
|
||||
simdjson_really_inline simdjson_result<array> value::get_array() noexcept {
|
||||
return array::start(iter);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<array> value::get_array() & noexcept {
|
||||
return array::try_start(iter);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<object> value::get_object() && noexcept {
|
||||
simdjson_really_inline simdjson_result<object> value::get_object() noexcept {
|
||||
return object::start(iter);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<object> value::get_object() & noexcept {
|
||||
return object::try_start(iter);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<object> value::start_or_resume_object() & noexcept {
|
||||
if (iter.at_start()) {
|
||||
return get_object();
|
||||
} else {
|
||||
return object::resume(iter);
|
||||
}
|
||||
}
|
||||
simdjson_really_inline simdjson_result<object> value::start_or_resume_object() && noexcept {
|
||||
simdjson_really_inline simdjson_result<object> value::start_or_resume_object() noexcept {
|
||||
if (iter.at_start()) {
|
||||
return get_object();
|
||||
} else {
|
||||
|
@ -62,44 +49,25 @@ simdjson_really_inline bool value::is_null() noexcept {
|
|||
return iter.is_null();
|
||||
}
|
||||
|
||||
template<> simdjson_really_inline simdjson_result<array> value::get() & noexcept { return get_array(); }
|
||||
template<> simdjson_really_inline simdjson_result<object> value::get() & noexcept { return get_object(); }
|
||||
template<> simdjson_really_inline simdjson_result<raw_json_string> value::get() & noexcept { return get_raw_json_string(); }
|
||||
template<> simdjson_really_inline simdjson_result<std::string_view> value::get() & noexcept { return get_string(); }
|
||||
template<> simdjson_really_inline simdjson_result<double> value::get() & noexcept { return get_double(); }
|
||||
template<> simdjson_really_inline simdjson_result<uint64_t> value::get() & noexcept { return get_uint64(); }
|
||||
template<> simdjson_really_inline simdjson_result<int64_t> value::get() & noexcept { return get_int64(); }
|
||||
template<> simdjson_really_inline simdjson_result<bool> value::get() & noexcept { return get_bool(); }
|
||||
template<> simdjson_really_inline simdjson_result<array> value::get() noexcept { return get_array(); }
|
||||
template<> simdjson_really_inline simdjson_result<object> value::get() noexcept { return get_object(); }
|
||||
template<> simdjson_really_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
|
||||
template<> simdjson_really_inline simdjson_result<std::string_view> value::get() noexcept { return get_string(); }
|
||||
template<> simdjson_really_inline simdjson_result<double> value::get() noexcept { return get_double(); }
|
||||
template<> simdjson_really_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
|
||||
template<> simdjson_really_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
|
||||
template<> simdjson_really_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
|
||||
|
||||
template<> simdjson_really_inline simdjson_result<value> value::get() && noexcept { return std::forward<value>(*this); }
|
||||
template<> simdjson_really_inline simdjson_result<array> value::get() && noexcept { return std::forward<value>(*this).get_array(); }
|
||||
template<> simdjson_really_inline simdjson_result<object> value::get() && noexcept { return std::forward<value>(*this).get_object(); }
|
||||
template<> simdjson_really_inline simdjson_result<raw_json_string> value::get() && noexcept { return std::forward<value>(*this).get_raw_json_string(); }
|
||||
template<> simdjson_really_inline simdjson_result<std::string_view> value::get() && noexcept { return std::forward<value>(*this).get_string(); }
|
||||
template<> simdjson_really_inline simdjson_result<double> value::get() && noexcept { return std::forward<value>(*this).get_double(); }
|
||||
template<> simdjson_really_inline simdjson_result<uint64_t> value::get() && noexcept { return std::forward<value>(*this).get_uint64(); }
|
||||
template<> simdjson_really_inline simdjson_result<int64_t> value::get() && noexcept { return std::forward<value>(*this).get_int64(); }
|
||||
template<> simdjson_really_inline simdjson_result<bool> value::get() && noexcept { return std::forward<value>(*this).get_bool(); }
|
||||
|
||||
template<typename T> simdjson_really_inline error_code value::get(T &out) & noexcept {
|
||||
template<typename T> simdjson_really_inline error_code value::get(T &out) noexcept {
|
||||
return get<T>().get(out);
|
||||
}
|
||||
template<typename T> simdjson_really_inline error_code value::get(T &out) && noexcept {
|
||||
return std::forward<value>(*this).get<T>().get(out);
|
||||
}
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
simdjson_really_inline value::operator array() && noexcept(false) {
|
||||
return std::forward<value>(*this).get_array();
|
||||
simdjson_really_inline value::operator array() noexcept(false) {
|
||||
return get_array();
|
||||
}
|
||||
simdjson_really_inline value::operator array() & noexcept(false) {
|
||||
return std::forward<value>(*this).get_array();
|
||||
}
|
||||
simdjson_really_inline value::operator object() && noexcept(false) {
|
||||
return std::forward<value>(*this).get_object();
|
||||
}
|
||||
simdjson_really_inline value::operator object() & noexcept(false) {
|
||||
return std::forward<value>(*this).get_object();
|
||||
simdjson_really_inline value::operator object() noexcept(false) {
|
||||
return get_object();
|
||||
}
|
||||
simdjson_really_inline value::operator uint64_t() noexcept(false) {
|
||||
return get_uint64();
|
||||
|
@ -128,44 +96,26 @@ simdjson_really_inline simdjson_result<array_iterator> value::end() & noexcept {
|
|||
return {};
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(std::string_view key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(std::string_view key) noexcept {
|
||||
return start_or_resume_object().find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(std::string_view key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object().find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(const char *key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(const char *key) noexcept {
|
||||
return start_or_resume_object().find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(const char *key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object().find_field(key);
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(std::string_view key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(std::string_view key) noexcept {
|
||||
return start_or_resume_object().find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(std::string_view key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object().find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(const char *key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(const char *key) noexcept {
|
||||
return start_or_resume_object().find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(const char *key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object().find_field_unordered(key);
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](std::string_view key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](std::string_view key) noexcept {
|
||||
return start_or_resume_object()[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](std::string_view key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object()[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](const char *key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](const char *key) noexcept {
|
||||
return start_or_resume_object()[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](const char *key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object()[key];
|
||||
}
|
||||
|
||||
} // namespace ondemand
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
|
@ -197,73 +147,41 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_
|
|||
return {};
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(std::string_view key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(std::string_view key) noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(std::string_view key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(const char *key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(const char *key) noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(const char *key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).find_field(key);
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(std::string_view key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(std::string_view key) noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(std::string_view key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(const char *key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(const char *key) noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(const char *key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).find_field_unordered(key);
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](std::string_view key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](std::string_view key) noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](std::string_view key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first)[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](const char *key) & noexcept {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](const char *key) noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](const char *key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first)[key];
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_array() & noexcept {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_array() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_array();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_array() && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).get_array();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_object() & noexcept {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_object() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_object();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_object() && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).get_object();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_uint64() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_uint64();
|
||||
|
@ -293,59 +211,34 @@ simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::v
|
|||
return first.is_null();
|
||||
}
|
||||
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get() & noexcept {
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get<T>();
|
||||
}
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get() && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).get<T>();
|
||||
}
|
||||
template<typename T> simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get(T &out) & noexcept {
|
||||
template<typename T> simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get(T &out) noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get<T>(out);
|
||||
}
|
||||
template<typename T> simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get(T &out) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).get<T>(out);
|
||||
}
|
||||
|
||||
template<> simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>() & noexcept {
|
||||
template<> simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::move(first);
|
||||
}
|
||||
template<> simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>() && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first);
|
||||
}
|
||||
template<> simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>(SIMDJSON_IMPLEMENTATION::ondemand::value &out) & noexcept {
|
||||
template<> simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>(SIMDJSON_IMPLEMENTATION::ondemand::value &out) noexcept {
|
||||
if (error()) { return error(); }
|
||||
out = first;
|
||||
return SUCCESS;
|
||||
}
|
||||
template<> simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>(SIMDJSON_IMPLEMENTATION::ondemand::value &out) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
out = std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false) {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false) {
|
||||
if (error()) { throw simdjson_error(error()); }
|
||||
return first;
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() && noexcept(false) {
|
||||
if (error()) { throw simdjson_error(error()); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false) {
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::object() noexcept(false) {
|
||||
if (error()) { throw simdjson_error(error()); }
|
||||
return first;
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::object() && noexcept(false) {
|
||||
if (error()) { throw simdjson_error(error()); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator uint64_t() noexcept(false) {
|
||||
if (error()) { throw simdjson_error(error()); }
|
||||
return first;
|
||||
|
|
|
@ -30,9 +30,7 @@ public:
|
|||
* @returns A value of the given type, parsed from the JSON.
|
||||
* @returns INCORRECT_TYPE If the JSON value is not the given type.
|
||||
*/
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> get() & noexcept;
|
||||
/** @overload template<typename T> simdjson_result<T> get() & noexcept */
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> get() && noexcept;
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> get() noexcept;
|
||||
|
||||
/**
|
||||
* Get this value as the given type.
|
||||
|
@ -43,9 +41,7 @@ public:
|
|||
* @returns INCORRECT_TYPE If the JSON value is not an object.
|
||||
* @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
|
||||
*/
|
||||
template<typename T> simdjson_really_inline error_code get(T &out) & noexcept;
|
||||
/** @overload template<typename T> error_code get(T &out) & noexcept */
|
||||
template<typename T> simdjson_really_inline error_code get(T &out) && noexcept;
|
||||
template<typename T> simdjson_really_inline error_code get(T &out) noexcept;
|
||||
|
||||
/**
|
||||
* Cast this JSON value to an array.
|
||||
|
@ -53,9 +49,7 @@ public:
|
|||
* @returns An object that can be used to iterate the array.
|
||||
* @returns INCORRECT_TYPE If the JSON value is not an array.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<array> get_array() && noexcept;
|
||||
/** @overload simdjson_really_inline operator get_array() && noexcept(false); */
|
||||
simdjson_really_inline simdjson_result<array> get_array() & noexcept;
|
||||
simdjson_really_inline simdjson_result<array> get_array() noexcept;
|
||||
|
||||
/**
|
||||
* Cast this JSON value to an object.
|
||||
|
@ -63,9 +57,7 @@ public:
|
|||
* @returns An object that can be used to look up or iterate fields.
|
||||
* @returns INCORRECT_TYPE If the JSON value is not an object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<object> get_object() && noexcept;
|
||||
/** @overload simdjson_really_inline operator object() && noexcept(false); */
|
||||
simdjson_really_inline simdjson_result<object> get_object() & noexcept;
|
||||
simdjson_really_inline simdjson_result<object> get_object() noexcept;
|
||||
|
||||
/**
|
||||
* Cast this JSON value to an unsigned integer.
|
||||
|
@ -136,18 +128,14 @@ public:
|
|||
* @returns An object that can be used to iterate the array.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
|
||||
*/
|
||||
simdjson_really_inline operator array() && noexcept(false);
|
||||
/** @overload simdjson_really_inline operator array() && noexcept(false); */
|
||||
simdjson_really_inline operator array() & noexcept(false);
|
||||
simdjson_really_inline operator array() noexcept(false);
|
||||
/**
|
||||
* Cast this JSON value to an object.
|
||||
*
|
||||
* @returns An object that can be used to look up or iterate fields.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
|
||||
*/
|
||||
simdjson_really_inline operator object() && noexcept(false);
|
||||
/** @overload simdjson_really_inline operator object() && noexcept(false); */
|
||||
simdjson_really_inline operator object() & noexcept(false);
|
||||
simdjson_really_inline operator object() noexcept(false);
|
||||
/**
|
||||
* Cast this JSON value to an unsigned integer.
|
||||
*
|
||||
|
@ -234,13 +222,9 @@ public:
|
|||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(const char *key) && noexcept;
|
||||
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(const char *key) noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object, without regard to key order.
|
||||
|
@ -261,21 +245,13 @@ public:
|
|||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(const char *key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](const char *key) && noexcept;
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(const char *key) noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](const char *key) noexcept;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -303,9 +279,7 @@ protected:
|
|||
/**
|
||||
* Get the object, starting or resuming it as necessary
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<object> start_or_resume_object() & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<object> start_or_resume_object() & noexcept; */
|
||||
simdjson_really_inline simdjson_result<object> start_or_resume_object() && noexcept;
|
||||
simdjson_really_inline simdjson_result<object> start_or_resume_object() noexcept;
|
||||
|
||||
// simdjson_really_inline void log_value(const char *type) const noexcept;
|
||||
// simdjson_really_inline void log_error(const char *message) const noexcept;
|
||||
|
@ -334,11 +308,8 @@ public:
|
|||
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||
simdjson_really_inline simdjson_result() noexcept = default;
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() && noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & noexcept;
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() && noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() noexcept;
|
||||
|
||||
simdjson_really_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||
simdjson_really_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||
|
@ -348,17 +319,13 @@ public:
|
|||
simdjson_really_inline simdjson_result<bool> get_bool() noexcept;
|
||||
simdjson_really_inline bool is_null() noexcept;
|
||||
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> get() & noexcept;
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> get() && noexcept;
|
||||
template<typename T> simdjson_really_inline simdjson_result<T> get() noexcept;
|
||||
|
||||
template<typename T> simdjson_really_inline error_code get(T &out) & noexcept;
|
||||
template<typename T> simdjson_really_inline error_code get(T &out) && noexcept;
|
||||
template<typename T> simdjson_really_inline error_code get(T &out) noexcept;
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() && noexcept(false);
|
||||
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
|
||||
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() && noexcept(false);
|
||||
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
|
||||
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false);
|
||||
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() noexcept(false);
|
||||
simdjson_really_inline operator uint64_t() noexcept(false);
|
||||
simdjson_really_inline operator int64_t() noexcept(false);
|
||||
simdjson_really_inline operator double() noexcept(false);
|
||||
|
@ -390,13 +357,9 @@ public:
|
|||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) && noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object, without regard to key order.
|
||||
|
@ -417,21 +380,13 @@ public:
|
|||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) && noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) noexcept;
|
||||
};
|
||||
|
||||
} // namespace simdjson
|
||||
|
|
|
@ -10,20 +10,12 @@ simdjson_really_inline value_iterator::value_iterator(json_iterator *json_iter,
|
|||
}
|
||||
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_object() noexcept {
|
||||
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 {
|
||||
assert_at_start();
|
||||
|
||||
if (*_json_iter->peek() != '{') { logger::log_error(*_json_iter, "Not an object"); return INCORRECT_TYPE; }
|
||||
_json_iter->advance();
|
||||
if (*advance_container_start("object") != '{') { return incorrect_type_error("Not an object"); }
|
||||
return started_object();
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object() noexcept {
|
||||
assert_at_container_start();
|
||||
if (*_json_iter->peek() == '}') {
|
||||
logger::log_value(*_json_iter, "empty object");
|
||||
_json_iter->advance();
|
||||
|
@ -256,21 +248,12 @@ simdjson_warn_unused simdjson_really_inline error_code value_iterator::field_val
|
|||
}
|
||||
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_array() noexcept {
|
||||
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 {
|
||||
assert_at_start();
|
||||
|
||||
if (*_json_iter->peek() != '[') { logger::log_error(*_json_iter, "Not an array"); return INCORRECT_TYPE; }
|
||||
_json_iter->advance();
|
||||
if (*advance_container_start("array") != '[') { return incorrect_type_error("Not an array"); }
|
||||
return started_array();
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array() noexcept {
|
||||
assert_at_container_start();
|
||||
if (*_json_iter->peek() == ']') {
|
||||
logger::log_value(*_json_iter, "empty array");
|
||||
_json_iter->advance();
|
||||
|
@ -313,7 +296,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<std::string_view> va
|
|||
return get_raw_json_string().unescape(_json_iter->string_buf_loc());
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
|
||||
auto json = advance_scalar("string");
|
||||
auto json = advance_start("string");
|
||||
if (*json != '"') { return incorrect_type_error("Not a string"); }
|
||||
return raw_json_string(json+1);
|
||||
}
|
||||
|
@ -342,21 +325,21 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> val
|
|||
return get_raw_json_string();
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::get_root_uint64() noexcept {
|
||||
auto max_len = peek_scalar_length();
|
||||
auto max_len = peek_start_length();
|
||||
auto json = advance_root_scalar("uint64");
|
||||
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, _start_position, depth(), "Root number more than 20 characters"); return NUMBER_ERROR; }
|
||||
return numberparsing::parse_unsigned(tmpbuf);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::get_root_int64() noexcept {
|
||||
auto max_len = peek_scalar_length();
|
||||
auto max_len = peek_start_length();
|
||||
auto json = advance_root_scalar("int64");
|
||||
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, _start_position, depth(), "Root number more than 20 characters"); return NUMBER_ERROR; }
|
||||
return numberparsing::parse_integer(tmpbuf);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::get_root_double() noexcept {
|
||||
auto max_len = peek_scalar_length();
|
||||
auto max_len = peek_start_length();
|
||||
auto json = advance_root_scalar("double");
|
||||
// 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];
|
||||
|
@ -364,14 +347,14 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterat
|
|||
return numberparsing::parse_double(tmpbuf);
|
||||
}
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::get_root_bool() noexcept {
|
||||
auto max_len = peek_scalar_length();
|
||||
auto max_len = peek_start_length();
|
||||
auto json = advance_root_scalar("bool");
|
||||
uint8_t tmpbuf[5+1];
|
||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { return incorrect_type_error("Not a boolean"); }
|
||||
return parse_bool(tmpbuf);
|
||||
}
|
||||
simdjson_really_inline bool value_iterator::is_root_null() noexcept {
|
||||
auto max_len = peek_scalar_length();
|
||||
auto max_len = peek_start_length();
|
||||
auto json = advance_root_scalar("null");
|
||||
return max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
|
||||
(max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[5]));
|
||||
|
@ -427,17 +410,17 @@ 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 {
|
||||
simdjson_really_inline const uint8_t *value_iterator::peek_start() const noexcept {
|
||||
return _json_iter->peek(_start_position);
|
||||
}
|
||||
simdjson_really_inline uint32_t value_iterator::peek_scalar_length() const noexcept {
|
||||
simdjson_really_inline uint32_t value_iterator::peek_start_length() const noexcept {
|
||||
return _json_iter->peek_length(_start_position);
|
||||
}
|
||||
|
||||
simdjson_really_inline const uint8_t *value_iterator::advance_scalar(const char *type) const noexcept {
|
||||
simdjson_really_inline const uint8_t *value_iterator::advance_start(const char *type) const noexcept {
|
||||
logger::log_value(*_json_iter, _start_position, depth(), type);
|
||||
// If we're not at the position anymore, we don't want to advance the cursor.
|
||||
if (!is_at_start()) { return peek_scalar(); }
|
||||
if (!is_at_start()) { return peek_start(); }
|
||||
|
||||
// Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
|
||||
assert_at_start();
|
||||
|
@ -445,9 +428,19 @@ simdjson_really_inline const uint8_t *value_iterator::advance_scalar(const char
|
|||
_json_iter->ascend_to(depth()-1);
|
||||
return result;
|
||||
}
|
||||
simdjson_really_inline const uint8_t *value_iterator::advance_container_start(const char *type) const noexcept {
|
||||
// If we're not at the position anymore, we don't want to advance the cursor.
|
||||
if (is_at_container_start()) { return peek_start(); }
|
||||
|
||||
logger::log_start_value(*_json_iter, _start_position, depth(), type);
|
||||
|
||||
// Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
|
||||
assert_at_start();
|
||||
return _json_iter->advance();
|
||||
}
|
||||
simdjson_really_inline const uint8_t *value_iterator::advance_root_scalar(const char *type) const noexcept {
|
||||
logger::log_value(*_json_iter, _start_position, depth(), type);
|
||||
if (!is_at_start()) { return peek_scalar(); }
|
||||
if (!is_at_start()) { return peek_start(); }
|
||||
|
||||
assert_at_root();
|
||||
auto result = _json_iter->advance();
|
||||
|
@ -456,7 +449,7 @@ simdjson_really_inline const uint8_t *value_iterator::advance_root_scalar(const
|
|||
}
|
||||
simdjson_really_inline const uint8_t *value_iterator::advance_non_root_scalar(const char *type) const noexcept {
|
||||
logger::log_value(*_json_iter, _start_position, depth(), type);
|
||||
if (!is_at_start()) { return peek_scalar(); }
|
||||
if (!is_at_start()) { return peek_start(); }
|
||||
|
||||
assert_at_non_root_start();
|
||||
auto result = _json_iter->advance();
|
||||
|
@ -472,6 +465,9 @@ simdjson_really_inline error_code value_iterator::incorrect_type_error(const cha
|
|||
simdjson_really_inline bool value_iterator::is_at_start() const noexcept {
|
||||
return _json_iter->token.index == _start_position;
|
||||
}
|
||||
simdjson_really_inline bool value_iterator::is_at_container_start() const noexcept {
|
||||
return _json_iter->token.index == _start_position + 1;
|
||||
}
|
||||
|
||||
simdjson_really_inline void value_iterator::assert_at_start() const noexcept {
|
||||
SIMDJSON_ASSUME( _json_iter->token.index == _start_position );
|
||||
|
@ -479,6 +475,12 @@ simdjson_really_inline void value_iterator::assert_at_start() const noexcept {
|
|||
SIMDJSON_ASSUME( _depth > 0 );
|
||||
}
|
||||
|
||||
simdjson_really_inline void value_iterator::assert_at_container_start() const noexcept {
|
||||
SIMDJSON_ASSUME( _json_iter->token.index == _start_position + 1 );
|
||||
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_position );
|
||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
|
||||
|
|
|
@ -208,13 +208,6 @@ public:
|
|||
* @error INCORRECT_TYPE If there is no [.
|
||||
*/
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> start_array() noexcept;
|
||||
/**
|
||||
* Check for an opening [ and start an array iteration.
|
||||
*
|
||||
* @returns Whether the array had any elements (returns false for empty).
|
||||
* @error INCORRECT_TYPE If there is no [.
|
||||
*/
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> try_start_array() noexcept;
|
||||
|
||||
/**
|
||||
* Start an array iteration after the user has already checked and moved past the [.
|
||||
|
@ -278,16 +271,19 @@ protected:
|
|||
simdjson_really_inline bool parse_null(const uint8_t *json) const noexcept;
|
||||
simdjson_really_inline simdjson_result<bool> parse_bool(const uint8_t *json) 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 *peek_start() const noexcept;
|
||||
simdjson_really_inline uint32_t peek_start_length() const noexcept;
|
||||
simdjson_really_inline const uint8_t *advance_start(const char *type) const noexcept;
|
||||
simdjson_really_inline const uint8_t *advance_container_start(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 bool is_at_container_start() const noexcept;
|
||||
simdjson_really_inline void assert_at_start() const noexcept;
|
||||
simdjson_really_inline void assert_at_container_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;
|
||||
|
|
|
@ -4,14 +4,16 @@ include_directories(..)
|
|||
add_subdirectory(compilation_failure_tests)
|
||||
|
||||
add_cpp_test(ondemand_active_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_array_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_compilation_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_dom_api_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_error_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_key_string_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_number_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_object_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_ordering_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_parse_api_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_readme_examples LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_scalar_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_twitter_tests LABELS ondemand acceptance per_implementation)
|
||||
|
||||
if(HAVE_POSIX_FORK AND HAVE_POSIX_WAIT) # assert tests use fork and wait, which aren't on MSVC
|
||||
|
@ -20,8 +22,8 @@ endif()
|
|||
|
||||
# Copy the simdjson dll into the tests directory
|
||||
if(MSVC)
|
||||
add_custom_command(TARGET ondemand_dom_api_tests POST_BUILD # Adds a post-build event
|
||||
add_custom_command(TARGET ondemand_parse_api_tests POST_BUILD # Adds a post-build event
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake -E copy_if_different..."
|
||||
"$<TARGET_FILE:simdjson>" # <--this is in-file
|
||||
"$<TARGET_FILE_DIR:ondemand_dom_api_tests>") # <--this is out-file path
|
||||
"$<TARGET_FILE_DIR:ondemand_parse_api_tests>") # <--this is out-file path
|
||||
endif(MSVC)
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
#include "simdjson.h"
|
||||
#include "test_ondemand.h"
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
namespace array_tests {
|
||||
using namespace std;
|
||||
|
||||
bool iterate_array() {
|
||||
TEST_START();
|
||||
const auto json = R"([ 1, 10, 100 ])"_padded;
|
||||
const uint64_t expected_value[] = { 1, 10, 100 };
|
||||
|
||||
SUBTEST("ondemand::array", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::array array;
|
||||
ASSERT_SUCCESS( doc_result.get(array) );
|
||||
|
||||
size_t i=0;
|
||||
for (auto value : array) {
|
||||
int64_t actual;
|
||||
ASSERT_SUCCESS( value.get(actual) );
|
||||
ASSERT_EQUAL(actual, expected_value[i]);
|
||||
i++;
|
||||
}
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::array>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::array> array = doc_result.get_array();
|
||||
size_t i=0;
|
||||
for (simdjson_unused auto value : array) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
size_t i=0;
|
||||
for (simdjson_unused auto value : doc) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
size_t i=0;
|
||||
for (simdjson_unused auto value : doc_result) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_array_partial_children() {
|
||||
TEST_START();
|
||||
auto json = R"(
|
||||
[
|
||||
0,
|
||||
[],
|
||||
{},
|
||||
{ "x": 3, "y": 33 },
|
||||
{ "x": 4, "y": 44 },
|
||||
{ "x": 5, "y": 55 },
|
||||
{ "x": 6, "y": 66 },
|
||||
[ 7, 77, 777 ],
|
||||
[ 8, 88, 888 ],
|
||||
{ "a": [ { "b": [ 9, 99 ], "c": 999 }, 9999 ], "d": 99999 },
|
||||
10
|
||||
]
|
||||
)"_padded;
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
size_t i = 0;
|
||||
for (auto value : doc_result) {
|
||||
ASSERT_SUCCESS(value);
|
||||
|
||||
switch (i) {
|
||||
case 0: {
|
||||
std::cout << " - After ignoring empty scalar ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
std::cout << " - After ignoring empty array ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
std::cout << " - After ignoring empty object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
// Break after using first value in child object
|
||||
case 3: {
|
||||
for (auto [ child_field, error ] : value.get_object()) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(child_field.key(), "x");
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child_field.value().get(x) );
|
||||
ASSERT_EQUAL(x, 3);
|
||||
break; // Break after the first value
|
||||
}
|
||||
std::cout << " - After using first value in child object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Break without using first value in child object
|
||||
case 4: {
|
||||
for (auto [ child_field, error ] : value.get_object()) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(child_field.key(), "x");
|
||||
break;
|
||||
}
|
||||
std::cout << " - After reaching (but not using) first value in child object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Only look up one field in child object
|
||||
case 5: {
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( value["x"].get(x) );
|
||||
ASSERT_EQUAL( x, 5 );
|
||||
std::cout << " - After looking up one field in child object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Only look up one field in child object, but don't use it
|
||||
case 6: {
|
||||
ASSERT_SUCCESS( value["x"] );
|
||||
std::cout << " - After looking up (but not using) one field in child object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Break after first value in child array
|
||||
case 7: {
|
||||
for (auto [ child_value, error ] : value) {
|
||||
ASSERT_SUCCESS(error);
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child_value.get(x) );
|
||||
ASSERT_EQUAL( x, 7 );
|
||||
break;
|
||||
}
|
||||
std::cout << " - After using first value in child array ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Break without using first value in child array
|
||||
case 8: {
|
||||
for (auto child_value : value) {
|
||||
ASSERT_SUCCESS(child_value);
|
||||
break;
|
||||
}
|
||||
std::cout << " - After reaching (but not using) first value in child array ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Break out of multiple child loops
|
||||
case 9: {
|
||||
for (auto child1 : value.get_object()) {
|
||||
for (auto child2 : child1.value().get_array()) {
|
||||
for (auto child3 : child2.get_object()) {
|
||||
for (auto child4 : child3.value().get_array()) {
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child4.get(x) );
|
||||
ASSERT_EQUAL( x, 9 );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
std::cout << " - After breaking out of quadruply-nested arrays and objects ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Test the actual value
|
||||
case 10: {
|
||||
uint64_t actual_value;
|
||||
ASSERT_SUCCESS( value.get(actual_value) );
|
||||
ASSERT_EQUAL( actual_value, 10 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
ASSERT_EQUAL( i, 11 ); // Make sure we found all the keys we expected
|
||||
return true;
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iterate_empty_array() {
|
||||
TEST_START();
|
||||
auto json = "[]"_padded;
|
||||
SUBTEST("ondemand::array", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::array array;
|
||||
ASSERT_SUCCESS( doc_result.get(array) );
|
||||
for (simdjson_unused auto value : array) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::array>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::array> array_result = doc_result.get_array();
|
||||
for (simdjson_unused auto value : array_result) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
for (simdjson_unused auto value : doc) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
for (simdjson_unused auto value : doc_result) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
bool iterate_array_exception() {
|
||||
TEST_START();
|
||||
auto json = R"([ 1, 10, 100 ])"_padded;
|
||||
const uint64_t expected_value[] = { 1, 10, 100 };
|
||||
|
||||
ASSERT_TRUE(test_ondemand_doc(json, [&](auto doc_result) {
|
||||
size_t i=0;
|
||||
for (int64_t actual : doc_result) { ASSERT_EQUAL(actual, expected_value[i]); i++; }
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_empty_object_exception() {
|
||||
TEST_START();
|
||||
auto json = R"({})"_padded;
|
||||
|
||||
ASSERT_TRUE(test_ondemand_doc(json, [&](auto doc_result) {
|
||||
for (simdjson_unused ondemand::field field : doc_result.get_object()) {
|
||||
TEST_FAIL("Unexpected field");
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_empty_array_exception() {
|
||||
TEST_START();
|
||||
auto json = "[]"_padded;
|
||||
|
||||
ASSERT_TRUE(test_ondemand_doc(json, [&](auto doc_result) {
|
||||
for (simdjson_unused ondemand::value value : doc_result) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
bool run() {
|
||||
return
|
||||
iterate_array() &&
|
||||
iterate_empty_array() &&
|
||||
iterate_array_partial_children() &&
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
iterate_array_exception() &&
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
true;
|
||||
}
|
||||
|
||||
} // namespace dom_api_tests
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return test_main(argc, argv, array_tests::run);
|
||||
}
|
|
@ -39,9 +39,9 @@ namespace error_tests {
|
|||
TEST_START();
|
||||
TEST_CAST_ERROR("[]", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("[]", bool, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("[]", int64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("[]", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("[]", double, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("[]", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("[]", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("[]", double, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("[]", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("[]", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -51,9 +51,9 @@ namespace error_tests {
|
|||
TEST_START();
|
||||
TEST_CAST_ERROR("{}", array, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("{}", bool, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("{}", int64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("{}", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("{}", double, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("{}", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("{}", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("{}", double, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("{}", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("{}", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -63,9 +63,9 @@ namespace error_tests {
|
|||
TEST_START();
|
||||
TEST_CAST_ERROR("true", array, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("true", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("true", int64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("true", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("true", double, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("true", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("true", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("true", double, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("true", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("true", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -75,9 +75,9 @@ namespace error_tests {
|
|||
TEST_START();
|
||||
TEST_CAST_ERROR("false", array, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("false", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("false", int64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("false", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("false", double, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("false", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("false", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("false", double, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("false", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("false", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -87,9 +87,9 @@ namespace error_tests {
|
|||
TEST_START();
|
||||
TEST_CAST_ERROR("null", array, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("null", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("null", int64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("null", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("null", double, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("null", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("null", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("null", double, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("null", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("null", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -110,7 +110,7 @@ namespace error_tests {
|
|||
TEST_CAST_ERROR("-1", array, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-1", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-1", bool, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-1", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("-1", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-1", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-1", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -121,8 +121,8 @@ namespace error_tests {
|
|||
TEST_CAST_ERROR("1.1", array, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("1.1", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("1.1", bool, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("1.1", int64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("1.1", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("1.1", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("1.1", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("1.1", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("1.1", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -133,8 +133,8 @@ namespace error_tests {
|
|||
TEST_CAST_ERROR("-9223372036854775809", array, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-9223372036854775809", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-9223372036854775809", bool, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-9223372036854775809", int64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("-9223372036854775809", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("-9223372036854775809", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-9223372036854775809", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-9223372036854775809", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("-9223372036854775809", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -146,7 +146,7 @@ namespace error_tests {
|
|||
TEST_CAST_ERROR("9223372036854775808", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("9223372036854775808", bool, INCORRECT_TYPE);
|
||||
// TODO BUG: this should be an error but is presently not
|
||||
// TEST_CAST_ERROR("9223372036854775808", int64, NUMBER_ERROR);
|
||||
// TEST_CAST_ERROR("9223372036854775808", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("9223372036854775808", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("9223372036854775808", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -157,9 +157,8 @@ namespace error_tests {
|
|||
TEST_CAST_ERROR("18446744073709551616", array, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("18446744073709551616", object, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("18446744073709551616", bool, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("18446744073709551616", int64, NUMBER_ERROR);
|
||||
// TODO BUG: this should be an error but is presently not
|
||||
// TEST_CAST_ERROR("18446744073709551616", uint64, NUMBER_ERROR);
|
||||
TEST_CAST_ERROR("18446744073709551616", int64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("18446744073709551616", uint64, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("18446744073709551616", string, INCORRECT_TYPE);
|
||||
TEST_CAST_ERROR("18446744073709551616", raw_json_string, INCORRECT_TYPE);
|
||||
TEST_SUCCEED();
|
||||
|
@ -238,43 +237,43 @@ namespace error_tests {
|
|||
bool top_level_array_iterate_error() {
|
||||
TEST_START();
|
||||
ONDEMAND_SUBTEST("missing comma", "[1 1]", assert_iterate(doc, { int64_t(1) }, { TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", "[1,,1]", assert_iterate(doc, { int64_t(1) }, { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", "[,]", assert_iterate(doc, { NUMBER_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", "[,,]", assert_iterate(doc, { NUMBER_ERROR, NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", "[1,,1]", assert_iterate(doc, { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", "[,]", assert_iterate(doc, { INCORRECT_TYPE }));
|
||||
ONDEMAND_SUBTEST("extra comma ", "[,,]", assert_iterate(doc, { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR }));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
bool top_level_array_iterate_unclosed_error() {
|
||||
TEST_START();
|
||||
ONDEMAND_SUBTEST("unclosed extra comma", "[,", assert_iterate(doc, { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", "[1 ", assert_iterate(doc, { int64_t(1) }, { TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed extra comma", "[,", assert_iterate(doc, { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", "[1 ", assert_iterate(doc, { int64_t(1) }, { TAPE_ERROR }));
|
||||
// TODO These pass the user values that may run past the end of the buffer if they aren't careful
|
||||
// In particular, if the padding is decorated with the wrong values, we could cause overrun!
|
||||
ONDEMAND_SUBTEST("unclosed extra comma", "[,,", assert_iterate(doc, { NUMBER_ERROR, NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", "[1,", assert_iterate(doc, { int64_t(1) }, { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", "[1", assert_iterate(doc, { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", "[", assert_iterate(doc, { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed extra comma", "[,,", assert_iterate(doc, { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", "[1,", assert_iterate(doc, { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", "[1", assert_iterate(doc, { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", "[", assert_iterate(doc, { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool array_iterate_error() {
|
||||
TEST_START();
|
||||
ONDEMAND_SUBTEST("missing comma", R"({ "a": [1 1] })", assert_iterate(doc["a"], { int64_t(1) }, { TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", R"({ "a": [1,,1] })", assert_iterate(doc["a"], { int64_t(1) }, { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", R"({ "a": [1,,] })", assert_iterate(doc["a"], { int64_t(1) }, { NUMBER_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", R"({ "a": [,] })", assert_iterate(doc["a"], { NUMBER_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", R"({ "a": [,,] })", assert_iterate(doc["a"], { NUMBER_ERROR, NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", R"({ "a": [1,,1] })", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("extra comma ", R"({ "a": [1,,] })", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE }));
|
||||
ONDEMAND_SUBTEST("extra comma ", R"({ "a": [,] })", assert_iterate(doc["a"], { INCORRECT_TYPE }));
|
||||
ONDEMAND_SUBTEST("extra comma ", R"({ "a": [,,] })", assert_iterate(doc["a"], { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR }));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
bool array_iterate_unclosed_error() {
|
||||
TEST_START();
|
||||
ONDEMAND_SUBTEST("unclosed extra comma", R"({ "a": [,)", assert_iterate(doc["a"], { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed extra comma", R"({ "a": [,,)", assert_iterate(doc["a"], { NUMBER_ERROR, NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed extra comma", R"({ "a": [,)", assert_iterate(doc["a"], { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed extra comma", R"({ "a": [,,)", assert_iterate(doc["a"], { INCORRECT_TYPE, INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1 )", assert_iterate(doc["a"], { int64_t(1) }, { TAPE_ERROR }));
|
||||
// TODO These pass the user values that may run past the end of the buffer if they aren't careful
|
||||
// In particular, if the padding is decorated with the wrong values, we could cause overrun!
|
||||
ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1,)", assert_iterate(doc["a"], { int64_t(1) }, { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1,)", assert_iterate(doc["a"], { int64_t(1) }, { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", R"({ "a": [1)", assert_iterate(doc["a"], { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", R"({ "a": [)", assert_iterate(doc["a"], { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed ", R"({ "a": [)", assert_iterate(doc["a"], { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -317,7 +316,7 @@ namespace error_tests {
|
|||
TEST_START();
|
||||
ONDEMAND_SUBTEST("missing colon", R"({ "a" 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("missing key ", R"({ : 1, "b": 2 })", assert_iterate_object(doc.get_object(), { TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("missing value", R"({ "a": , "b": 2 })", assert_iterate_object(doc.get_object(), { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("missing value", R"({ "a": , "b": 2 })", assert_iterate_object(doc.get_object(), { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("missing comma", R"({ "a": 1 "b": 2 })", assert_iterate_object(doc.get_object(), { "a" }, { int64_t(1) }, { TAPE_ERROR }));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
@ -337,7 +336,7 @@ namespace error_tests {
|
|||
// TODO These next two pass the user a value that may run past the end of the buffer if they aren't careful.
|
||||
// In particular, if the padding is decorated with the wrong values, we could cause overrun!
|
||||
ONDEMAND_SUBTEST("unclosed", R"({ "a": 1 )", assert_iterate_object(doc.get_object(), { "a" }, { int64_t(1) }, { TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed", R"({ "a": )", assert_iterate_object(doc.get_object(), { NUMBER_ERROR, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed", R"({ "a": )", assert_iterate_object(doc.get_object(), { INCORRECT_TYPE, TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed", R"({ "a" )", assert_iterate_object(doc.get_object(), { TAPE_ERROR }));
|
||||
ONDEMAND_SUBTEST("unclosed", R"({ )", assert_iterate_object(doc.get_object(), { TAPE_ERROR }));
|
||||
TEST_SUCCEED();
|
||||
|
@ -399,6 +398,177 @@ namespace error_tests {
|
|||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool get_fail_then_succeed_bool() {
|
||||
TEST_START();
|
||||
auto json = R"({ "val" : true })"_padded;
|
||||
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc) {
|
||||
simdjson_result<ondemand::value> val = doc["val"];
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_SUCCESS( val.get_bool() );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( doc["val"].get(val) );
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_SUCCESS( val.get_bool() );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
json = R"(true)"_padded;
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](simdjson_result<ondemand::document> val) {
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_SUCCESS( val.get_bool());
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::document val;
|
||||
ASSERT_SUCCESS( std::move(doc).get(val) ); // Get everything that can fail in both forward and backwards order
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_SUCCESS( val.get_bool() );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool get_fail_then_succeed_null() {
|
||||
TEST_START();
|
||||
auto json = R"({ "val" : null })"_padded;
|
||||
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc) {
|
||||
simdjson_result<ondemand::value> val = doc["val"];
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( doc["val"].get(val) );
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
json = R"(null)"_padded;
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](simdjson_result<ondemand::document> val) {
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::document val;
|
||||
ASSERT_SUCCESS( std::move(doc).get(val) ); // Get everything that can fail in both forward and backwards order
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
|
||||
//
|
||||
// Do it again for bool
|
||||
//
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool run() {
|
||||
return
|
||||
empty_document_error() &&
|
||||
|
@ -416,6 +586,8 @@ namespace error_tests {
|
|||
object_lookup_miss_unclosed_error() &&
|
||||
object_lookup_miss_wrong_key_type_error() &&
|
||||
object_lookup_miss_next_error() &&
|
||||
get_fail_then_succeed_bool() &&
|
||||
get_fail_then_succeed_null() &&
|
||||
true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace simdjson;
|
||||
|
||||
namespace dom_api_tests {
|
||||
namespace object_tests {
|
||||
using namespace std;
|
||||
|
||||
bool iterate_object() {
|
||||
|
@ -39,48 +39,6 @@ namespace dom_api_tests {
|
|||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_array() {
|
||||
TEST_START();
|
||||
const auto json = R"([ 1, 10, 100 ])"_padded;
|
||||
const uint64_t expected_value[] = { 1, 10, 100 };
|
||||
|
||||
SUBTEST("ondemand::array", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::array array;
|
||||
ASSERT_SUCCESS( doc_result.get(array) );
|
||||
size_t i=0;
|
||||
for (auto value : array) {
|
||||
int64_t actual;
|
||||
ASSERT_SUCCESS( value.get(actual) );
|
||||
ASSERT_EQUAL(actual, expected_value[i]);
|
||||
i++;
|
||||
}
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::array>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::array> array = doc_result.get_array();
|
||||
size_t i=0;
|
||||
for (simdjson_unused auto value : array) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
size_t i=0;
|
||||
for (simdjson_unused auto value : doc) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
size_t i=0;
|
||||
for (simdjson_unused auto value : doc_result) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_object_partial_children() {
|
||||
TEST_START();
|
||||
auto json = R"(
|
||||
|
@ -235,143 +193,6 @@ namespace dom_api_tests {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool iterate_array_partial_children() {
|
||||
TEST_START();
|
||||
auto json = R"(
|
||||
[
|
||||
0,
|
||||
[],
|
||||
{},
|
||||
{ "x": 3, "y": 33 },
|
||||
{ "x": 4, "y": 44 },
|
||||
{ "x": 5, "y": 55 },
|
||||
{ "x": 6, "y": 66 },
|
||||
[ 7, 77, 777 ],
|
||||
[ 8, 88, 888 ],
|
||||
{ "a": [ { "b": [ 9, 99 ], "c": 999 }, 9999 ], "d": 99999 },
|
||||
10
|
||||
]
|
||||
)"_padded;
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
size_t i = 0;
|
||||
for (auto value : doc_result) {
|
||||
ASSERT_SUCCESS(value);
|
||||
|
||||
switch (i) {
|
||||
case 0: {
|
||||
std::cout << " - After ignoring empty scalar ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
std::cout << " - After ignoring empty array ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
std::cout << " - After ignoring empty object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
// Break after using first value in child object
|
||||
case 3: {
|
||||
for (auto [ child_field, error ] : value.get_object()) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(child_field.key(), "x");
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child_field.value().get(x) );
|
||||
ASSERT_EQUAL(x, 3);
|
||||
break; // Break after the first value
|
||||
}
|
||||
std::cout << " - After using first value in child object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Break without using first value in child object
|
||||
case 4: {
|
||||
for (auto [ child_field, error ] : value.get_object()) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(child_field.key(), "x");
|
||||
break;
|
||||
}
|
||||
std::cout << " - After reaching (but not using) first value in child object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Only look up one field in child object
|
||||
case 5: {
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( value["x"].get(x) );
|
||||
ASSERT_EQUAL( x, 5 );
|
||||
std::cout << " - After looking up one field in child object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Only look up one field in child object, but don't use it
|
||||
case 6: {
|
||||
ASSERT_SUCCESS( value["x"] );
|
||||
std::cout << " - After looking up (but not using) one field in child object ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Break after first value in child array
|
||||
case 7: {
|
||||
for (auto [ child_value, error ] : value) {
|
||||
ASSERT_SUCCESS(error);
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child_value.get(x) );
|
||||
ASSERT_EQUAL( x, 7 );
|
||||
break;
|
||||
}
|
||||
std::cout << " - After using first value in child array ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Break without using first value in child array
|
||||
case 8: {
|
||||
for (auto child_value : value) {
|
||||
ASSERT_SUCCESS(child_value);
|
||||
break;
|
||||
}
|
||||
std::cout << " - After reaching (but not using) first value in child array ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Break out of multiple child loops
|
||||
case 9: {
|
||||
for (auto child1 : value.get_object()) {
|
||||
for (auto child2 : child1.value().get_array()) {
|
||||
for (auto child3 : child2.get_object()) {
|
||||
for (auto child4 : child3.value().get_array()) {
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child4.get(x) );
|
||||
ASSERT_EQUAL( x, 9 );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
std::cout << " - After breaking out of quadruply-nested arrays and objects ..." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Test the actual value
|
||||
case 10: {
|
||||
uint64_t actual_value;
|
||||
ASSERT_SUCCESS( value.get(actual_value) );
|
||||
ASSERT_EQUAL( actual_value, 10 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
ASSERT_EQUAL( i, 11 ); // Make sure we found all the keys we expected
|
||||
return true;
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool object_index_partial_children() {
|
||||
TEST_START();
|
||||
auto json = R"(
|
||||
|
@ -635,234 +456,6 @@ namespace dom_api_tests {
|
|||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_empty_array() {
|
||||
TEST_START();
|
||||
auto json = "[]"_padded;
|
||||
SUBTEST("ondemand::array", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::array array;
|
||||
ASSERT_SUCCESS( doc_result.get(array) );
|
||||
for (simdjson_unused auto value : array) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::array>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::array> array_result = doc_result.get_array();
|
||||
for (simdjson_unused auto value : array_result) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
for (simdjson_unused auto value : doc) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
for (simdjson_unused auto value : doc_result) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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 whitespace_json = std::string(json) + " ";
|
||||
std::cout << "- JSON: " << whitespace_json << endl;
|
||||
SUBTEST( "simdjson_result<document>", test_ondemand_doc(whitespace_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(whitespace_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) + "]";
|
||||
std::cout << "- JSON: " << array_json << endl;
|
||||
SUBTEST( "simdjson_result<value>", test_ondemand_doc(array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (simdjson_result<ondemand::value> val_result : doc_result) {
|
||||
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);
|
||||
return true;
|
||||
}));
|
||||
SUBTEST( "value", test_ondemand_doc(array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (simdjson_result<ondemand::value> val_result : doc_result) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( val_result.get(val) );
|
||||
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);
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
padded_string whitespace_array_json = std::string("[") + std::string(json) + " ]";
|
||||
std::cout << "- JSON: " << whitespace_array_json << endl;
|
||||
SUBTEST( "simdjson_result<value>", test_ondemand_doc(whitespace_array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (simdjson_result<ondemand::value> val_result : doc_result) {
|
||||
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);
|
||||
return true;
|
||||
}));
|
||||
SUBTEST( "value", test_ondemand_doc(whitespace_array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (simdjson_result<ondemand::value> val_result : doc_result) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( val_result.get(val) );
|
||||
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);
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool string_value() {
|
||||
TEST_START();
|
||||
// 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() {
|
||||
TEST_START();
|
||||
if (!test_scalar_value<int64_t> ("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value<uint64_t>("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value<double> ("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value<int64_t> ("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value<uint64_t>("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value<double> ("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value<int64_t> ("-1"_padded, -1)) { return false; }
|
||||
if (!test_scalar_value<double> ("-1"_padded, -1)) { return false; }
|
||||
if (!test_scalar_value<double> ("1.1"_padded, 1.1)) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool boolean_values() {
|
||||
TEST_START();
|
||||
if (!test_scalar_value<bool> ("true"_padded, true)) { return false; }
|
||||
if (!test_scalar_value<bool> ("false"_padded, false)) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool null_value() {
|
||||
TEST_START();
|
||||
auto json = "null"_padded;
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
ASSERT_EQUAL( doc.is_null(), true );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ASSERT_EQUAL( doc_result.is_null(), true );
|
||||
return true;
|
||||
}));
|
||||
json = "[null]"_padded;
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (auto value_result : doc_result) {
|
||||
ondemand::value value;
|
||||
ASSERT_SUCCESS( value_result.get(value) );
|
||||
ASSERT_EQUAL( value.is_null(), true );
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL( count, 1 );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (auto value_result : doc_result) {
|
||||
ASSERT_EQUAL( value_result.is_null(), true );
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL( count, 1 );
|
||||
return true;
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool object_index() {
|
||||
TEST_START();
|
||||
auto json = R"({ "a": 1, "b": 2, "c/d": 3})"_padded;
|
||||
|
@ -1140,20 +733,6 @@ namespace dom_api_tests {
|
|||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_array_exception() {
|
||||
TEST_START();
|
||||
auto json = R"([ 1, 10, 100 ])"_padded;
|
||||
const uint64_t expected_value[] = { 1, 10, 100 };
|
||||
|
||||
ASSERT_TRUE(test_ondemand_doc(json, [&](auto doc_result) {
|
||||
size_t i=0;
|
||||
for (int64_t actual : doc_result) { ASSERT_EQUAL(actual, expected_value[i]); i++; }
|
||||
ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_empty_object_exception() {
|
||||
TEST_START();
|
||||
auto json = R"({})"_padded;
|
||||
|
@ -1168,65 +747,6 @@ namespace dom_api_tests {
|
|||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool iterate_empty_array_exception() {
|
||||
TEST_START();
|
||||
auto json = "[]"_padded;
|
||||
|
||||
ASSERT_TRUE(test_ondemand_doc(json, [&](auto doc_result) {
|
||||
for (simdjson_unused ondemand::value value : doc_result) { TEST_FAIL("Unexpected value"); }
|
||||
return true;
|
||||
}));
|
||||
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool test_scalar_value_exception(const padded_string &json, const T &expected) {
|
||||
std::cout << "- JSON: " << json << endl;
|
||||
SUBTEST( "document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ASSERT_EQUAL( expected, T(doc_result) );
|
||||
return true;
|
||||
}));
|
||||
padded_string array_json = std::string("[") + std::string(json) + "]";
|
||||
std::cout << "- JSON: " << array_json << endl;
|
||||
SUBTEST( "value", test_ondemand_doc(array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (T actual : doc_result) {
|
||||
ASSERT_EQUAL( expected, actual );
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL(count, 1);
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
bool string_value_exception() {
|
||||
TEST_START();
|
||||
return test_scalar_value_exception(R"("hi")"_padded, std::string_view("hi"));
|
||||
}
|
||||
|
||||
bool numeric_values_exception() {
|
||||
TEST_START();
|
||||
if (!test_scalar_value_exception<int64_t> ("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value_exception<uint64_t>("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value_exception<double> ("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value_exception<int64_t> ("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value_exception<uint64_t>("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value_exception<double> ("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value_exception<int64_t> ("-1"_padded, -1)) { return false; }
|
||||
if (!test_scalar_value_exception<double> ("-1"_padded, -1)) { return false; }
|
||||
if (!test_scalar_value_exception<double> ("1.1"_padded, 1.1)) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool boolean_values_exception() {
|
||||
TEST_START();
|
||||
if (!test_scalar_value_exception<bool> ("true"_padded, true)) { return false; }
|
||||
if (!test_scalar_value_exception<bool> ("false"_padded, false)) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
bool object_index_exception() {
|
||||
TEST_START();
|
||||
auto json = R"({ "a": 1, "b": 2, "c/d": 3})"_padded;
|
||||
|
@ -1255,35 +775,24 @@ namespace dom_api_tests {
|
|||
|
||||
bool run() {
|
||||
return
|
||||
iterate_array() &&
|
||||
iterate_empty_array() &&
|
||||
iterate_object() &&
|
||||
iterate_empty_object() &&
|
||||
string_value() &&
|
||||
numeric_values() &&
|
||||
boolean_values() &&
|
||||
null_value() &&
|
||||
object_index() &&
|
||||
object_find_field_unordered() &&
|
||||
object_find_field() &&
|
||||
nested_object_index() &&
|
||||
iterate_object_partial_children() &&
|
||||
iterate_array_partial_children() &&
|
||||
object_index_partial_children() &&
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
iterate_object_exception() &&
|
||||
iterate_array_exception() &&
|
||||
string_value_exception() &&
|
||||
numeric_values_exception() &&
|
||||
boolean_values_exception() &&
|
||||
object_index_exception() &&
|
||||
nested_object_index_exception() &&
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
true;
|
||||
}
|
||||
|
||||
} // namespace dom_api_tests
|
||||
} // namespace object_tests
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return test_main(argc, argv, dom_api_tests::run);
|
||||
return test_main(argc, argv, object_tests::run);
|
||||
}
|
|
@ -0,0 +1,278 @@
|
|||
#include "simdjson.h"
|
||||
#include "test_ondemand.h"
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
namespace scalar_tests {
|
||||
using namespace std;
|
||||
|
||||
template<typename T>
|
||||
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 whitespace_json = std::string(json) + " ";
|
||||
std::cout << "- JSON: " << whitespace_json << endl;
|
||||
SUBTEST( "simdjson_result<document>", test_ondemand_doc(whitespace_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(whitespace_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) + "]";
|
||||
std::cout << "- JSON: " << array_json << endl;
|
||||
SUBTEST( "simdjson_result<value>", test_ondemand_doc(array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (simdjson_result<ondemand::value> val_result : doc_result) {
|
||||
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);
|
||||
return true;
|
||||
}));
|
||||
SUBTEST( "value", test_ondemand_doc(array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (simdjson_result<ondemand::value> val_result : doc_result) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( val_result.get(val) );
|
||||
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);
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
padded_string whitespace_array_json = std::string("[") + std::string(json) + " ]";
|
||||
std::cout << "- JSON: " << whitespace_array_json << endl;
|
||||
SUBTEST( "simdjson_result<value>", test_ondemand_doc(whitespace_array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (simdjson_result<ondemand::value> val_result : doc_result) {
|
||||
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);
|
||||
return true;
|
||||
}));
|
||||
SUBTEST( "value", test_ondemand_doc(whitespace_array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (simdjson_result<ondemand::value> val_result : doc_result) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( val_result.get(val) );
|
||||
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);
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool string_value() {
|
||||
TEST_START();
|
||||
// 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() {
|
||||
TEST_START();
|
||||
if (!test_scalar_value<int64_t> ("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value<uint64_t>("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value<double> ("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value<int64_t> ("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value<uint64_t>("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value<double> ("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value<int64_t> ("-1"_padded, -1)) { return false; }
|
||||
if (!test_scalar_value<double> ("-1"_padded, -1)) { return false; }
|
||||
if (!test_scalar_value<double> ("1.1"_padded, 1.1)) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool boolean_values() {
|
||||
TEST_START();
|
||||
if (!test_scalar_value<bool> ("true"_padded, true)) { return false; }
|
||||
if (!test_scalar_value<bool> ("false"_padded, false)) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool null_value() {
|
||||
TEST_START();
|
||||
auto json = "null"_padded;
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
ASSERT_EQUAL( doc.is_null(), true );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ASSERT_EQUAL( doc_result.is_null(), true );
|
||||
return true;
|
||||
}));
|
||||
json = "[null]"_padded;
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (auto value_result : doc_result) {
|
||||
ondemand::value value;
|
||||
ASSERT_SUCCESS( value_result.get(value) );
|
||||
ASSERT_EQUAL( value.is_null(), true );
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL( count, 1 );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (auto value_result : doc_result) {
|
||||
ASSERT_EQUAL( value_result.is_null(), true );
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL( count, 1 );
|
||||
return true;
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
template<typename T>
|
||||
bool test_scalar_value_exception(const padded_string &json, const T &expected) {
|
||||
std::cout << "- JSON: " << json << endl;
|
||||
SUBTEST( "document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ASSERT_EQUAL( expected, T(doc_result) );
|
||||
return true;
|
||||
}));
|
||||
padded_string array_json = std::string("[") + std::string(json) + "]";
|
||||
std::cout << "- JSON: " << array_json << endl;
|
||||
SUBTEST( "value", test_ondemand_doc(array_json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (T actual : doc_result) {
|
||||
ASSERT_EQUAL( expected, actual );
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL(count, 1);
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
bool string_value_exception() {
|
||||
TEST_START();
|
||||
return test_scalar_value_exception(R"("hi")"_padded, std::string_view("hi"));
|
||||
}
|
||||
|
||||
bool numeric_values_exception() {
|
||||
TEST_START();
|
||||
if (!test_scalar_value_exception<int64_t> ("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value_exception<uint64_t>("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value_exception<double> ("0"_padded, 0)) { return false; }
|
||||
if (!test_scalar_value_exception<int64_t> ("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value_exception<uint64_t>("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value_exception<double> ("1"_padded, 1)) { return false; }
|
||||
if (!test_scalar_value_exception<int64_t> ("-1"_padded, -1)) { return false; }
|
||||
if (!test_scalar_value_exception<double> ("-1"_padded, -1)) { return false; }
|
||||
if (!test_scalar_value_exception<double> ("1.1"_padded, 1.1)) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool boolean_values_exception() {
|
||||
TEST_START();
|
||||
if (!test_scalar_value_exception<bool> ("true"_padded, true)) { return false; }
|
||||
if (!test_scalar_value_exception<bool> ("false"_padded, false)) { return false; }
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
bool run() {
|
||||
return
|
||||
string_value() &&
|
||||
numeric_values() &&
|
||||
boolean_values() &&
|
||||
null_value() &&
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
string_value_exception() &&
|
||||
numeric_values_exception() &&
|
||||
boolean_values_exception() &&
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
true;
|
||||
}
|
||||
|
||||
} // namespace scalar_tests
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return test_main(argc, argv, scalar_tests::run);
|
||||
}
|
|
@ -48,7 +48,7 @@ template<typename T>
|
|||
simdjson_really_inline bool assert_success(const T &actual, const char *operation = "result") {
|
||||
simdjson::error_code error = to_error_code(actual);
|
||||
if (error) {
|
||||
std::cerr << "FAIL: " << operation << " returned error: " << error << std::endl;
|
||||
std::cerr << "FAIL: " << operation << " returned error: " << error << " (" << int(error) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue