1#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
3#ifndef SIMDJSON_CONDITIONAL_INCLUDE
4#define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
5#include "simdjson/generic/ondemand/base.h"
6#include "simdjson/generic/atomparsing.h"
7#include "simdjson/generic/numberparsing.h"
8#include "simdjson/generic/ondemand/json_iterator.h"
9#include "simdjson/generic/ondemand/value_iterator.h"
10#include "simdjson/generic/ondemand/json_type-inl.h"
11#include "simdjson/generic/ondemand/raw_json_string-inl.h"
15namespace SIMDJSON_IMPLEMENTATION {
18#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
19simdjson_inline
bool raw_json_string_is_quote_terminated(
const uint8_t *json, uint32_t max_len)
noexcept {
21 for (uint32_t i = 1; i < max_len; i++) {
24 if (!escaping) {
return true; }
39simdjson_inline value_iterator::value_iterator(
40 json_iterator *json_iter,
42 token_position start_position
43) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
48 SIMDJSON_TRY( start_container(
'{',
"Not an object",
"object") );
49 return started_object();
53 SIMDJSON_TRY( start_container(
'{',
"Not an object",
"object") );
54 return started_root_object();
58 assert_at_container_start();
59#if SIMDJSON_DEVELOPMENT_CHECKS
60 _json_iter->set_start_position(_depth, start_position());
62 if (*_json_iter->peek() ==
'}') {
63 logger::log_value(*_json_iter,
"empty object");
64 _json_iter->return_current_and_advance();
65 SIMDJSON_TRY(end_container());
76 if ( ! _json_iter->streaming() ) {
82 if (*_json_iter->peek_last() !=
'}') {
83 _json_iter->abandon();
92 if ((*_json_iter->peek(_json_iter->end_position()) ==
'}') && (!_json_iter->balanced())) {
93 _json_iter->abandon();
102 auto error = check_root_object();
103 if(error) {
return error; }
104 return started_object();
107simdjson_warn_unused simdjson_inline
error_code value_iterator::end_container() noexcept {
108#if SIMDJSON_CHECK_EOF
112 _json_iter->ascend_to(depth()-1);
120 switch (*_json_iter->return_current_and_advance()) {
122 logger::log_end_value(*_json_iter,
"object");
123 SIMDJSON_TRY( end_container() );
128 return report_error(
TAPE_ERROR,
"Missing comma between object fields");
144 if (at_first_field()) {
157 }
else if (!is_open()) {
158#if SIMDJSON_DEVELOPMENT_CHECKS
181 if ((error = skip_child() )) { abandon();
return error; }
182 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
183#if SIMDJSON_DEVELOPMENT_CHECKS
194 if ((error = field_key().get(actual_key) )) { abandon();
return error; };
197 if ((error = field_value() )) { abandon();
return error; }
207 logger::log_event(*
this,
"match", key, -2);
213 logger::log_event(*
this,
"no match", key, -2);
216 SIMDJSON_TRY( skip_child() );
220 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
227SIMDJSON_PUSH_DISABLE_WARNINGS
228SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
242 token_position search_start = _json_iter->position();
245 bool at_first = at_first_field();
268 }
else if (!is_open()) {
270#if SIMDJSON_DEVELOPMENT_CHECKS
276 SIMDJSON_TRY(reset_object().get(has_value));
296 if ((error = skip_child() )) { abandon();
return error; }
297 search_start = _json_iter->position();
298 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
299#if SIMDJSON_DEVELOPMENT_CHECKS
319 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
327 if ((error = field_key().get(actual_key) )) { abandon();
return error; };
330 if ((error = field_value() )) { abandon();
return error; }
341 logger::log_event(*
this,
"match", key, -2);
347 logger::log_event(*
this,
"no match", key, -2);
350 SIMDJSON_TRY( skip_child() );
354 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
360 if(at_first) {
return false; }
366 SIMDJSON_TRY(reset_object().get(has_value));
368 SIMDJSON_ASSUME(has_value);
369 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
377 error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
380 error = field_value(); SIMDJSON_ASSUME(!error);
391 logger::log_event(*
this,
"match", key, -2);
397 logger::log_event(*
this,
"no match", key, -2);
400 SIMDJSON_TRY( skip_child() );
404 if(_json_iter->position() == search_start) {
return false; }
408 error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
416SIMDJSON_POP_DISABLE_WARNINGS
421 const uint8_t *key = _json_iter->return_current_and_advance();
422 if (*(key++) !=
'"') {
return report_error(
TAPE_ERROR,
"Object key is not a string"); }
429 const uint8_t *k = _json_iter->return_current_and_advance();
430 if (*(k++) !=
'"') {
return report_error(
TAPE_ERROR,
"Object key is not a string"); }
435 const char *q =
reinterpret_cast<const char *
>(_json_iter->peek());
436 do { --q; }
while (*q !=
'"');
438 len =
static_cast<std::size_t
>(q -
reinterpret_cast<const char *
>(k));
445 if (*_json_iter->return_current_and_advance() !=
':') {
return report_error(
TAPE_ERROR,
"Missing colon in object field"); }
446 _json_iter->descend_to(depth()+1);
451 SIMDJSON_TRY( start_container(
'[',
"Not an array",
"array") );
452 return started_array();
456 SIMDJSON_TRY( start_container(
'[',
"Not an array",
"array") );
457 return started_root_array();
460inline std::string value_iterator::to_string() const noexcept {
461 auto answer = std::string(
"value_iterator [ depth : ") + std::to_string(_depth) + std::string(
", ");
462 if(_json_iter !=
nullptr) { answer += _json_iter->to_string(); }
463 answer += std::string(
" ]");
468 assert_at_container_start();
469 if (*_json_iter->peek() ==
']') {
470 logger::log_value(*_json_iter,
"empty array");
471 _json_iter->return_current_and_advance();
472 SIMDJSON_TRY( end_container() );
475 _json_iter->descend_to(depth()+1);
476#if SIMDJSON_DEVELOPMENT_CHECKS
477 _json_iter->set_start_position(_depth, start_position());
487 if ( ! _json_iter->streaming() ) {
493 if (*_json_iter->peek_last() !=
']') {
494 _json_iter->abandon();
503 if ((*_json_iter->peek(_json_iter->end_position()) ==
']') && (!_json_iter->balanced())) {
504 _json_iter->abandon();
513 auto error = check_root_array();
514 if (error) {
return error; }
515 return started_array();
521 logger::log_event(*
this,
"has_next_element");
522 switch (*_json_iter->return_current_and_advance()) {
524 logger::log_end_value(*_json_iter,
"array");
525 SIMDJSON_TRY( end_container() );
528 _json_iter->descend_to(depth()+1);
531 return report_error(
TAPE_ERROR,
"Missing comma between array elements");
535simdjson_warn_unused simdjson_inline
simdjson_result<bool> value_iterator::parse_bool(
const uint8_t *json)
const noexcept {
536 auto not_true = atomparsing::str4ncmp(json,
"true");
537 auto not_false = atomparsing::str4ncmp(json,
"fals") | (json[4] ^
'e');
538 bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
539 if (error) {
return incorrect_type_error(
"Not a boolean"); }
542simdjson_warn_unused simdjson_inline
simdjson_result<bool> value_iterator::parse_null(
const uint8_t *json)
const noexcept {
543 bool is_null_string = !atomparsing::str4ncmp(json,
"null") && jsoncharutils::is_structural_or_whitespace(json[4]);
545 if(!is_null_string && json[0]==
'n') {
return incorrect_type_error(
"Not a null but starts with n"); }
546 return is_null_string;
549simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(
bool allow_replacement)
noexcept {
550 return get_raw_json_string().unescape(json_iter(), allow_replacement);
552template <
typename string_type>
553simdjson_warn_unused simdjson_inline
error_code value_iterator::get_string(string_type& receiver,
bool allow_replacement)
noexcept {
554 std::string_view content;
556 auto saved_string_buf_loc = _json_iter->string_buf_loc();
557 auto err = get_string(allow_replacement).get(content);
558 if (err) {
return err; }
559 internal::assign_utf8(receiver, content);
561 _json_iter->string_buf_loc() = saved_string_buf_loc;
564simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
565 return get_raw_json_string().unescape_wobbly(json_iter());
567simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
568 auto json = peek_scalar(
"string");
569 if (*json !=
'"') {
return incorrect_type_error(
"Not a string"); }
570#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
571 if (_json_iter->allow_incomplete_json()) {
572 const size_t remaining_input_length = _json_iter->remaining_input_length(json);
573 const uint32_t max_len = remaining_input_length < peek_start_length() ? uint32_t(remaining_input_length) : peek_start_length();
574 if (!raw_json_string_is_quote_terminated(json, max_len)) {
579 advance_scalar(
"string");
580 return raw_json_string(json+1);
582simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
583 auto result = numberparsing::parse_unsigned(peek_non_root_scalar(
"uint64"));
584 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"uint64"); }
587simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
588 auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar(
"uint64"));
589 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"uint64"); }
592simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
593 auto result = numberparsing::parse_integer(peek_non_root_scalar(
"int64"));
594 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"int64"); }
597simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
598 auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar(
"int64"));
599 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"int64"); }
602simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
603 auto result = numberparsing::parse_double(peek_non_root_scalar(
"double"));
604 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"double"); }
607simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
608 auto result = numberparsing::parse_double_in_string(peek_non_root_scalar(
"double"));
609 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"double"); }
612simdjson_warn_unused simdjson_inline simdjson_result<float> value_iterator::get_float() noexcept {
613 auto result = numberparsing::parse_float(peek_non_root_scalar(
"float"));
614 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"float"); }
617simdjson_warn_unused simdjson_inline simdjson_result<float> value_iterator::get_float_in_string() noexcept {
618 auto result = numberparsing::parse_float_in_string(peek_non_root_scalar(
"float"));
619 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"float"); }
622simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
623 auto result = parse_bool(peek_non_root_scalar(
"bool"));
624 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"bool"); }
627simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
629 SIMDJSON_TRY(parse_null(peek_non_root_scalar(
"null")).get(is_null_value));
630 if(is_null_value) { advance_non_root_scalar(
"null"); }
631 return is_null_value;
633simdjson_inline
bool value_iterator::is_negative() noexcept {
634 return numberparsing::is_negative(peek_non_root_scalar(
"numbersign"));
636simdjson_inline
bool value_iterator::is_root_negative() noexcept {
637 return numberparsing::is_negative(peek_root_scalar(
"numbersign"));
639simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
640 return numberparsing::is_integer(peek_non_root_scalar(
"integer"));
642simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
643 return numberparsing::get_number_type(peek_non_root_scalar(
"integer"));
645simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
647 error_code error = numberparsing::parse_number(peek_non_root_scalar(
"number"), num);
648 if(error) {
return error; }
652simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(
bool check_trailing)
noexcept {
653 auto max_len = peek_root_length();
654 auto json = peek_root_scalar(
"is_root_integer");
655 uint8_t tmpbuf[20+1+1]{};
657 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
660 auto answer = numberparsing::is_integer(tmpbuf);
664 if(check_trailing && (answer.error() ==
SUCCESS) && (!_json_iter->is_single_token())) {
return TRAILING_CONTENT; }
668simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> value_iterator::get_root_number_type(
bool check_trailing)
noexcept {
669 auto max_len = peek_root_length();
670 auto json = peek_root_scalar(
"number");
674 uint8_t tmpbuf[1074+8+1+1];
675 tmpbuf[1074+8+1] =
'\0';
676 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
677 if(numberparsing::check_if_integer(json, max_len)) {
678 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
679 logger::log_error(*_json_iter, start_position(), depth(),
"Found big integer");
680 return number_type::big_integer;
682 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters and not a big integer");
685 auto answer = numberparsing::get_number_type(tmpbuf);
686 if (check_trailing && (answer.error() ==
SUCCESS) && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
689simdjson_inline simdjson_result<number> value_iterator::get_root_number(
bool check_trailing)
noexcept {
690 auto max_len = peek_root_length();
691 auto json = peek_root_scalar(
"number");
696 uint8_t tmpbuf[1074+8+1+1];
697 tmpbuf[1074+8+1] =
'\0';
698 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
699 if(numberparsing::check_if_integer(json, max_len)) {
700 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
701 logger::log_error(*_json_iter, start_position(), depth(),
"Found big integer");
704 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters and not a big integer");
708 error_code error = numberparsing::parse_number(tmpbuf, num);
709 if(error) {
return error; }
710 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
711 advance_root_scalar(
"number");
714simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(
bool check_trailing,
bool allow_replacement)
noexcept {
715 return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
717template <
typename string_type>
718simdjson_warn_unused simdjson_inline
error_code value_iterator::get_root_string(string_type& receiver,
bool check_trailing,
bool allow_replacement)
noexcept {
719 std::string_view content;
721 auto saved_string_buf_loc = _json_iter->string_buf_loc();
722 auto err = get_root_string(check_trailing, allow_replacement).get(content);
723 if (err) {
return err; }
724 internal::assign_utf8(receiver, content);
726 _json_iter->string_buf_loc() = saved_string_buf_loc;
729simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(
bool check_trailing)
noexcept {
730 return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
732simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(
bool check_trailing)
noexcept {
733 auto json = peek_scalar(
"string");
734 if (*json !=
'"') {
return incorrect_type_error(
"Not a string"); }
735 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
736#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
737 if (_json_iter->allow_incomplete_json()) {
738 const size_t remaining_input_length = _json_iter->remaining_input_length(json);
739 const uint32_t max_len = remaining_input_length < peek_root_length() ? uint32_t(remaining_input_length) : peek_root_length();
740 if (!raw_json_string_is_quote_terminated(json, max_len)) {
745 advance_scalar(
"string");
746 return raw_json_string(json+1);
748simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(
bool check_trailing)
noexcept {
749 auto max_len = peek_root_length();
750 auto json = peek_root_scalar(
"uint64");
751 uint8_t tmpbuf[20+1+1]{};
753 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
754 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
757 auto result = numberparsing::parse_unsigned(tmpbuf);
758 if(result.error() ==
SUCCESS) {
759 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
760 advance_root_scalar(
"uint64");
764simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(
bool check_trailing)
noexcept {
765 auto max_len = peek_root_length();
766 auto json = peek_root_scalar(
"uint64");
767 uint8_t tmpbuf[20+1+1]{};
769 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
770 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
773 auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
774 if(result.error() ==
SUCCESS) {
775 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
776 advance_root_scalar(
"uint64");
780simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(
bool check_trailing)
noexcept {
781 auto max_len = peek_root_length();
782 auto json = peek_root_scalar(
"int64");
783 uint8_t tmpbuf[20+1+1];
785 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
786 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
790 auto result = numberparsing::parse_integer(tmpbuf);
791 if(result.error() ==
SUCCESS) {
792 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
793 advance_root_scalar(
"int64");
797simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(
bool check_trailing)
noexcept {
798 auto max_len = peek_root_length();
799 auto json = peek_root_scalar(
"int64");
800 uint8_t tmpbuf[20+1+1];
802 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
803 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
807 auto result = numberparsing::parse_integer_in_string(tmpbuf);
808 if(result.error() ==
SUCCESS) {
809 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
810 advance_root_scalar(
"int64");
814simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(
bool check_trailing)
noexcept {
815 auto max_len = peek_root_length();
816 auto json = peek_root_scalar(
"double");
820 uint8_t tmpbuf[1074+8+1+1];
821 tmpbuf[1074+8+1] =
'\0';
822 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
823 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters");
826 auto result = numberparsing::parse_double(tmpbuf);
827 if(result.error() ==
SUCCESS) {
828 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
829 advance_root_scalar(
"double");
834simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(
bool check_trailing)
noexcept {
835 auto max_len = peek_root_length();
836 auto json = peek_root_scalar(
"double");
840 uint8_t tmpbuf[1074+8+1+1];
841 tmpbuf[1074+8+1] =
'\0';
842 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
843 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters");
846 auto result = numberparsing::parse_double_in_string(tmpbuf);
847 if(result.error() ==
SUCCESS) {
848 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
849 advance_root_scalar(
"double");
854simdjson_warn_unused simdjson_inline simdjson_result<float> value_iterator::get_root_float(
bool check_trailing)
noexcept {
855 auto max_len = peek_root_length();
856 auto json = peek_root_scalar(
"float");
860 uint8_t tmpbuf[1074+8+1+1];
861 tmpbuf[1074+8+1] =
'\0';
862 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
863 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters");
866 auto result = numberparsing::parse_float(tmpbuf);
867 if(result.error() ==
SUCCESS) {
868 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
869 advance_root_scalar(
"float");
874simdjson_warn_unused simdjson_inline simdjson_result<float> value_iterator::get_root_float_in_string(
bool check_trailing)
noexcept {
875 auto max_len = peek_root_length();
876 auto json = peek_root_scalar(
"float");
877 uint8_t tmpbuf[1074+8+1+1];
878 tmpbuf[1074+8+1] =
'\0';
879 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
880 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters");
883 auto result = numberparsing::parse_float_in_string(tmpbuf);
884 if(result.error() ==
SUCCESS) {
885 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
886 advance_root_scalar(
"float");
891simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(
bool check_trailing)
noexcept {
892 auto max_len = peek_root_length();
893 auto json = peek_root_scalar(
"bool");
897 bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json,
"true") &&
898 (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
899 bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json,
"false") &&
900 (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5])));
901 if(value_true ==
false && value_false ==
false) {
return incorrect_type_error(
"Not a boolean"); }
902 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
903 advance_root_scalar(
"bool");
907simdjson_inline simdjson_result<bool> value_iterator::is_root_null(
bool check_trailing)
noexcept {
908 auto max_len = peek_root_length();
909 auto json = peek_root_scalar(
"null");
910 bool result = (max_len >= 4 && !atomparsing::str4ncmp(json,
"null") &&
911 (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
913 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
914 advance_root_scalar(
"null");
915 }
else if (json[0] ==
'n') {
916 return incorrect_type_error(
"Not a null but starts with n");
921simdjson_warn_unused simdjson_inline
error_code value_iterator::skip_child() noexcept {
922 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
923 SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
925 return _json_iter->skip_child(depth());
930 return { _json_iter, depth()+1, _json_iter->token.position() };
936SIMDJSON_PUSH_DISABLE_WARNINGS
937SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
938simdjson_inline
bool value_iterator::is_open() const noexcept {
939 return _json_iter->depth() >= depth();
941SIMDJSON_POP_DISABLE_WARNINGS
943simdjson_inline
bool value_iterator::at_end() const noexcept {
944 return _json_iter->at_end();
947simdjson_inline
bool value_iterator::at_start() const noexcept {
948 return _json_iter->token.position() == start_position();
951simdjson_inline
bool value_iterator::at_first_field() const noexcept {
952 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
953 return _json_iter->token.position() == start_position() + 1;
956simdjson_inline
void value_iterator::abandon() noexcept {
957 _json_iter->abandon();
960simdjson_warn_unused simdjson_inline
depth_t value_iterator::depth() const noexcept {
963simdjson_warn_unused simdjson_inline
error_code value_iterator::error() const noexcept {
964 return _json_iter->error;
966simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
967 return _json_iter->string_buf_loc();
969simdjson_warn_unused simdjson_inline
const json_iterator &value_iterator::json_iter() const noexcept {
972simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
976simdjson_inline
const uint8_t *value_iterator::peek_start() const noexcept {
977 return _json_iter->peek(start_position());
979simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
980 return _json_iter->peek_length(start_position());
982simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
983 return _json_iter->peek_root_length(start_position());
986simdjson_inline
const uint8_t *value_iterator::peek_scalar(
const char *type)
noexcept {
987 logger::log_value(*_json_iter, start_position(), depth(), type);
989 if (!is_at_start()) {
return peek_start(); }
993 return _json_iter->peek();
996simdjson_inline
void value_iterator::advance_scalar(
const char *type)
noexcept {
997 logger::log_value(*_json_iter, start_position(), depth(), type);
999 if (!is_at_start()) {
return; }
1003 _json_iter->return_current_and_advance();
1004 _json_iter->ascend_to(depth()-1);
1007simdjson_warn_unused simdjson_inline
error_code value_iterator::start_container(uint8_t start_char,
const char *incorrect_type_message,
const char *type)
noexcept {
1008 logger::log_start_value(*_json_iter, start_position(), depth(), type);
1010 const uint8_t *json;
1011 if (!is_at_start()) {
1012#if SIMDJSON_DEVELOPMENT_CHECKS
1015 json = peek_start();
1016 if (*json != start_char) {
return incorrect_type_error(incorrect_type_message); }
1024 json = _json_iter->peek();
1025 if (*json != start_char) {
return incorrect_type_error(incorrect_type_message); }
1026 _json_iter->return_current_and_advance();
1034simdjson_inline
const uint8_t *value_iterator::peek_root_scalar(
const char *type)
noexcept {
1035 logger::log_value(*_json_iter, start_position(), depth(), type);
1036 if (!is_at_start()) {
return peek_start(); }
1039 return _json_iter->peek();
1041simdjson_inline
const uint8_t *value_iterator::peek_non_root_scalar(
const char *type)
noexcept {
1042 logger::log_value(*_json_iter, start_position(), depth(), type);
1043 if (!is_at_start()) {
return peek_start(); }
1045 assert_at_non_root_start();
1046 return _json_iter->peek();
1049simdjson_inline
void value_iterator::advance_root_scalar(
const char *type)
noexcept {
1050 logger::log_value(*_json_iter, start_position(), depth(), type);
1051 if (!is_at_start()) {
return; }
1054 _json_iter->return_current_and_advance();
1055 _json_iter->ascend_to(depth()-1);
1057simdjson_inline
void value_iterator::advance_non_root_scalar(
const char *type)
noexcept {
1058 logger::log_value(*_json_iter, start_position(), depth(), type);
1059 if (!is_at_start()) {
return; }
1061 assert_at_non_root_start();
1062 _json_iter->return_current_and_advance();
1063 _json_iter->ascend_to(depth()-1);
1066simdjson_inline
error_code value_iterator::incorrect_type_error(
const char *message)
const noexcept {
1067 logger::log_error(*_json_iter, start_position(), depth(), message);
1071simdjson_inline
bool value_iterator::is_at_start() const noexcept {
1072 return position() == start_position();
1075simdjson_inline
bool value_iterator::is_at_key() const noexcept {
1082 return _depth == _json_iter->_depth && *_json_iter->peek() ==
'"';
1085simdjson_inline
bool value_iterator::is_at_iterator_start() const noexcept {
1087 auto delta = position() - start_position();
1088 return delta == 1 || delta == 2;
1091inline void value_iterator::assert_at_start() const noexcept {
1092 SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
1093 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
1094 SIMDJSON_ASSUME( _depth > 0 );
1097inline void value_iterator::assert_at_container_start() const noexcept {
1098 SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
1099 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
1100 SIMDJSON_ASSUME( _depth > 0 );
1103inline void value_iterator::assert_at_next() const noexcept {
1104 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
1105 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
1106 SIMDJSON_ASSUME( _depth > 0 );
1109simdjson_inline
void value_iterator::move_at_start() noexcept {
1110 _json_iter->_depth = _depth;
1111 _json_iter->token.set_position(_start_position);
1114simdjson_inline
void value_iterator::move_at_container_start() noexcept {
1115 _json_iter->_depth = _depth;
1116 _json_iter->token.set_position(_start_position + 1);
1119simdjson_inline
void value_iterator::reenter_at(token_position position,
depth_t depth)
noexcept {
1128 SIMDJSON_ASSUME(position !=
nullptr);
1129 SIMDJSON_ASSUME(depth >= 1 && depth < INT32_MAX);
1130 _json_iter->_depth = depth;
1131 _json_iter->token.set_position(position);
1134simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
1135 if(error()) {
return error(); }
1136 move_at_container_start();
1137 return started_array();
1140simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
1141 if(error()) {
return error(); }
1142 move_at_container_start();
1143 return started_object();
1146inline void value_iterator::assert_at_child() const noexcept {
1147 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
1148 SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
1149 SIMDJSON_ASSUME( _depth > 0 );
1152inline void value_iterator::assert_at_root() const noexcept {
1154 SIMDJSON_ASSUME( _depth == 1 );
1157inline void value_iterator::assert_at_non_root_start() const noexcept {
1159 SIMDJSON_ASSUME( _depth > 1 );
1162inline void value_iterator::assert_is_valid() const noexcept {
1163 SIMDJSON_ASSUME( _json_iter !=
nullptr );
1166simdjson_inline
bool value_iterator::is_valid() const noexcept {
1167 return _json_iter !=
nullptr;
1170simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
1171 switch (*peek_start()) {
1183 case '0':
case '1':
case '2':
case '3':
case '4':
1184 case '5':
case '6':
case '7':
case '8':
case '9':
1187 return json_type::unknown;
1191simdjson_inline token_position value_iterator::start_position() const noexcept {
1192 return _start_position;
1195simdjson_inline token_position value_iterator::position() const noexcept {
1196 return _json_iter->position();
1199simdjson_inline token_position value_iterator::end_position() const noexcept {
1200 return _json_iter->end_position();
1203simdjson_inline token_position value_iterator::last_position() const noexcept {
1204 return _json_iter->last_position();
1207simdjson_inline
error_code value_iterator::report_error(
error_code error,
const char *message)
noexcept {
1208 return _json_iter->report_error(error, message);
1217simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value_iterator &&value) noexcept
1218 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(value)) {}
1219simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(
error_code error) noexcept
1220 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(error) {}
A string escaped per JSON rules, terminated with quote (").
simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept
This compares the current instance to the std::string_view target: returns true if they are byte-by-b...
simdjson_warn_unused simdjson_inline simdjson_result< bool > started_array() noexcept
Start an array iteration, after the user has already checked and moved past the [.
simdjson_warn_unused simdjson_inline simdjson_result< bool > start_array() noexcept
Check for an opening [ and start an array iteration.
simdjson_warn_unused simdjson_inline error_code check_root_array() noexcept
Checks whether an array could be started from the root.
simdjson_warn_unused simdjson_inline simdjson_result< bool > has_next_element() noexcept
Moves to the next element in an array.
simdjson_warn_unused simdjson_inline simdjson_result< bool > start_root_array() noexcept
Check for an opening [ and start an array iteration while at the root.
simdjson_warn_unused simdjson_inline simdjson_result< bool > started_root_array() noexcept
Start an array iteration from the root, after the user has already checked and moved past the [.
simdjson_warn_unused simdjson_inline value_iterator child() const noexcept
Get a child value iterator.
simdjson_warn_unused simdjson_inline error_code field_key_with_length(raw_json_string &key, std::size_t &len) noexcept
Get the current field's key together with its raw byte length.
simdjson_warn_unused simdjson_inline simdjson_result< bool > started_object() noexcept
Start an object iteration after the user has already checked and moved past the {.
simdjson_warn_unused simdjson_inline error_code check_root_object() noexcept
Checks whether an object could be started from the root.
simdjson_warn_unused simdjson_inline simdjson_result< bool > start_object() noexcept
Start an object iteration.
simdjson_warn_unused simdjson_inline simdjson_result< bool > find_field_unordered_raw(const std::string_view key) noexcept
Find the field with the given key without regard to order, and without unescaping.
simdjson_warn_unused simdjson_inline simdjson_result< bool > has_next_field() noexcept
Moves to the next field in an object.
simdjson_warn_unused simdjson_inline simdjson_result< raw_json_string > field_key() noexcept
Get the current field's key.
simdjson_warn_unused simdjson_inline simdjson_result< bool > started_root_object() noexcept
Start an object iteration from the root, after the user has already checked and moved past the {.
simdjson_warn_unused simdjson_inline error_code field_value() noexcept
Pass the : in the field and move to its value.
simdjson_warn_unused simdjson_inline simdjson_result< bool > find_field_raw(const std::string_view key) noexcept
Find the next field with the given key, without unescaping.
simdjson_warn_unused simdjson_inline simdjson_result< bool > start_root_object() noexcept
Start an object iteration from the root.
@ boolean
A JSON boolean (true or false)
@ object
A JSON object ( { "a": 1, "b" 2, ... } )
@ number
A JSON number ( 1 or -2.3 or 4.5e6 ...)
@ string
A JSON string ( "a" or "hello world\n" ...)
@ array
A JSON array ( [ 1, 2, 3 ... ] )
int32_t depth_t
Represents the depth of a JSON value (number of nested arrays/objects).
The top level simdjson namespace, containing everything the library provides.
error_code
All possible errors returned by simdjson.
@ INCORRECT_TYPE
JSON element has a different type than user expected.
@ OUT_OF_ORDER_ITERATION
tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1)
@ TAPE_ERROR
Something went wrong, this is a generic error. Fatal/unrecoverable error.
@ STRING_ERROR
Problem while parsing a string.
@ TRAILING_CONTENT
Unexpected trailing content in the JSON input.
@ INCOMPLETE_ARRAY_OR_OBJECT
The document ends early. Fatal/unrecoverable error.
@ NUMBER_ERROR
Problem while parsing a number.
@ BIGINT_ERROR
The integer value exceeds 64 bits.
The result of a simdjson operation that could fail.