diff --git a/include/simdjson/generic/ondemand/value_iterator-inl.h b/include/simdjson/generic/ondemand/value_iterator-inl.h index 6048ce4d7..9fd2f09ca 100644 --- a/include/simdjson/generic/ondemand/value_iterator-inl.h +++ b/include/simdjson/generic/ondemand/value_iterator-inl.h @@ -441,15 +441,39 @@ simdjson_warn_unused simdjson_really_inline simdjson_result value_iterat return numberparsing::parse_double(advance_non_root_scalar("double")); } simdjson_warn_unused simdjson_really_inline simdjson_result value_iterator::get_bool() noexcept { - auto json = advance_non_root_scalar("bool"); + return parse_bool(peek_start_length(), advance_non_root_scalar("bool")); +} + +simdjson_really_inline simdjson_result value_iterator::parse_bool(uint32_t max_len, const uint8_t *json) const noexcept { + // If we're almost at the end of the document, we can't do our special algorithm + if (simdjson_unlikely(max_len <= 5)) { + if (max_len >= 4) { + if (!atomparsing::str4ncmp(json, "fals") && (max_len == 5 && json[4] == 'e')) { + return simdjson_result(false); + } + if (!atomparsing::str4ncmp(json, "true") && (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))) { + return simdjson_result(true); + } + } + return incorrect_type_error("Not a boolean"); + } + + // Otherwise we use a less branchy algorithm auto not_true = atomparsing::str4ncmp(json, "true"); auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e'); - bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]); - if (error) { return incorrect_type_error("Not a boolean"); } + if ((not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4])) { + return incorrect_type_error("Not a boolean"); + } return simdjson_result(!not_true); } simdjson_really_inline bool value_iterator::is_null() noexcept { - auto json = advance_non_root_scalar("null"); + return parse_null(peek_start_length(), advance_non_root_scalar("null")); +} + +simdjson_really_inline bool value_iterator::parse_null(uint32_t max_len, const uint8_t *json) const noexcept { + if (simdjson_unlikely(max_len <= 4)) { + return max_len == 4 && !atomparsing::str4ncmp(json, "null"); + } return !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]); } @@ -477,23 +501,10 @@ simdjson_warn_unused simdjson_really_inline simdjson_result value_iterat return numberparsing::parse_double(json, json+max_len); } simdjson_warn_unused simdjson_really_inline simdjson_result value_iterator::get_root_bool() noexcept { - auto max_len = peek_start_length(); - auto json = advance_root_scalar("bool"); - if (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && - (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))) { - return simdjson_result(true); - } - if (max_len >= 5 && !atomparsing::str4ncmp(json, "fals") && json[4] == 'e' && - (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))) { - return simdjson_result(false); - } - return incorrect_type_error("Not a boolean"); + return parse_bool(peek_start_length(), advance_root_scalar("bool")); } simdjson_really_inline bool value_iterator::is_root_null() noexcept { - 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[4])); + return parse_null(peek_start_length(), advance_root_scalar("null")); } simdjson_warn_unused simdjson_really_inline error_code value_iterator::skip_child() noexcept { diff --git a/include/simdjson/generic/ondemand/value_iterator.h b/include/simdjson/generic/ondemand/value_iterator.h index 5b791fad9..433259567 100644 --- a/include/simdjson/generic/ondemand/value_iterator.h +++ b/include/simdjson/generic/ondemand/value_iterator.h @@ -289,6 +289,9 @@ protected: inline std::string to_string() const noexcept; simdjson_really_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept; + simdjson_really_inline bool parse_null(uint32_t max_len, const uint8_t *json) const noexcept; + simdjson_really_inline simdjson_result parse_bool(uint32_t max_len, const uint8_t *json) 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) noexcept;