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"
15 namespace SIMDJSON_IMPLEMENTATION {
18 simdjson_inline value_iterator::value_iterator(
19 json_iterator *json_iter,
21 token_position start_position
22 ) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
27 SIMDJSON_TRY( start_container(
'{',
"Not an object",
"object") );
28 return started_object();
32 SIMDJSON_TRY( start_container(
'{',
"Not an object",
"object") );
33 return started_root_object();
37 assert_at_container_start();
38 #if SIMDJSON_DEVELOPMENT_CHECKS
39 _json_iter->set_start_position(_depth, start_position());
41 if (*_json_iter->peek() ==
'}') {
42 logger::log_value(*_json_iter,
"empty object");
43 _json_iter->return_current_and_advance();
50 simdjson_warn_unused simdjson_inline
error_code value_iterator::check_root_object() noexcept {
55 if ( ! _json_iter->streaming() ) {
61 if (*_json_iter->peek_last() !=
'}') {
62 _json_iter->abandon();
71 if ((*_json_iter->peek(_json_iter->end_position()) ==
'}') && (!_json_iter->balanced())) {
72 _json_iter->abandon();
81 auto error = check_root_object();
82 if(error) {
return error; }
83 return started_object();
86 simdjson_warn_unused simdjson_inline
error_code value_iterator::end_container() noexcept {
87 #if SIMDJSON_CHECK_EOF
91 _json_iter->ascend_to(depth()-1);
100 switch (*_json_iter->return_current_and_advance()) {
102 logger::log_end_value(*_json_iter,
"object");
103 SIMDJSON_TRY( end_container() );
108 return report_error(
TAPE_ERROR,
"Missing comma between object fields");
112 simdjson_warn_unused simdjson_inline
simdjson_result<bool> value_iterator::find_field_raw(
const std::string_view key) noexcept {
124 if (at_first_field()) {
137 }
else if (!is_open()) {
138 #if SIMDJSON_DEVELOPMENT_CHECKS
161 if ((error = skip_child() )) { abandon();
return error; }
162 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
163 #if SIMDJSON_DEVELOPMENT_CHECKS
174 if ((error = field_key().get(actual_key) )) { abandon();
return error; };
177 if ((error = field_value() )) { abandon();
return error; }
187 logger::log_event(*
this,
"match", key, -2);
193 logger::log_event(*
this,
"no match", key, -2);
196 SIMDJSON_TRY( skip_child() );
200 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
207 SIMDJSON_PUSH_DISABLE_WARNINGS
208 SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
209 simdjson_warn_unused simdjson_inline
simdjson_result<bool> value_iterator::find_field_unordered_raw(
const std::string_view key) noexcept {
222 token_position search_start = _json_iter->position();
225 bool at_first = at_first_field();
248 }
else if (!is_open()) {
250 #if SIMDJSON_DEVELOPMENT_CHECKS
256 SIMDJSON_TRY(reset_object().get(has_value));
276 if ((error = skip_child() )) { abandon();
return error; }
277 search_start = _json_iter->position();
278 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
279 #if SIMDJSON_DEVELOPMENT_CHECKS
299 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
307 if ((error = field_key().get(actual_key) )) { abandon();
return error; };
310 if ((error = field_value() )) { abandon();
return error; }
321 logger::log_event(*
this,
"match", key, -2);
327 logger::log_event(*
this,
"no match", key, -2);
330 SIMDJSON_TRY( skip_child() );
334 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
340 if(at_first) {
return false; }
346 SIMDJSON_TRY(reset_object().get(has_value));
348 SIMDJSON_ASSUME(has_value);
349 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
357 error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
360 error = field_value(); SIMDJSON_ASSUME(!error);
371 logger::log_event(*
this,
"match", key, -2);
377 logger::log_event(*
this,
"no match", key, -2);
380 SIMDJSON_TRY( skip_child() );
384 if(_json_iter->position() == search_start) {
return false; }
388 error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
396 SIMDJSON_POP_DISABLE_WARNINGS
401 const uint8_t *key = _json_iter->return_current_and_advance();
402 if (*(key++) !=
'"') {
return report_error(
TAPE_ERROR,
"Object key is not a string"); }
406 simdjson_warn_unused simdjson_inline
error_code value_iterator::field_value() noexcept {
409 if (*_json_iter->return_current_and_advance() !=
':') {
return report_error(
TAPE_ERROR,
"Missing colon in object field"); }
410 _json_iter->descend_to(depth()+1);
415 SIMDJSON_TRY( start_container(
'[',
"Not an array",
"array") );
416 return started_array();
420 SIMDJSON_TRY( start_container(
'[',
"Not an array",
"array") );
421 return started_root_array();
424 inline std::string value_iterator::to_string() const noexcept {
425 auto answer = std::string(
"value_iterator [ depth : ") + std::to_string(_depth) + std::string(
", ");
426 if(_json_iter !=
nullptr) { answer += _json_iter->to_string(); }
427 answer += std::string(
" ]");
432 assert_at_container_start();
433 if (*_json_iter->peek() ==
']') {
434 logger::log_value(*_json_iter,
"empty array");
435 _json_iter->return_current_and_advance();
436 SIMDJSON_TRY( end_container() );
439 _json_iter->descend_to(depth()+1);
440 #if SIMDJSON_DEVELOPMENT_CHECKS
441 _json_iter->set_start_position(_depth, start_position());
446 simdjson_warn_unused simdjson_inline
error_code value_iterator::check_root_array() noexcept {
451 if ( ! _json_iter->streaming() ) {
457 if (*_json_iter->peek_last() !=
']') {
458 _json_iter->abandon();
467 if ((*_json_iter->peek(_json_iter->end_position()) ==
']') && (!_json_iter->balanced())) {
468 _json_iter->abandon();
477 auto error = check_root_array();
478 if (error) {
return error; }
479 return started_array();
485 logger::log_event(*
this,
"has_next_element");
486 switch (*_json_iter->return_current_and_advance()) {
488 logger::log_end_value(*_json_iter,
"array");
489 SIMDJSON_TRY( end_container() );
492 _json_iter->descend_to(depth()+1);
495 return report_error(
TAPE_ERROR,
"Missing comma between array elements");
499 simdjson_warn_unused simdjson_inline
simdjson_result<bool> value_iterator::parse_bool(
const uint8_t *json)
const noexcept {
500 auto not_true = atomparsing::str4ncmp(json,
"true");
501 auto not_false = atomparsing::str4ncmp(json,
"fals") | (json[4] ^
'e');
502 bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
503 if (error) {
return incorrect_type_error(
"Not a boolean"); }
506 simdjson_warn_unused simdjson_inline
simdjson_result<bool> value_iterator::parse_null(
const uint8_t *json)
const noexcept {
507 bool is_null_string = !atomparsing::str4ncmp(json,
"null") && jsoncharutils::is_structural_or_whitespace(json[4]);
509 if(!is_null_string && json[0]==
'n') {
return incorrect_type_error(
"Not a null but starts with n"); }
510 return is_null_string;
513 simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(
bool allow_replacement) noexcept {
514 return get_raw_json_string().unescape(json_iter(), allow_replacement);
516 template <
typename string_type>
517 simdjson_warn_unused simdjson_inline
error_code value_iterator::get_string(string_type& receiver,
bool allow_replacement) noexcept {
518 std::string_view content;
519 auto err = get_string(allow_replacement).get(content);
520 if (err) {
return err; }
524 simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
525 return get_raw_json_string().unescape_wobbly(json_iter());
527 simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
528 auto json = peek_scalar(
"string");
529 if (*json !=
'"') {
return incorrect_type_error(
"Not a string"); }
530 advance_scalar(
"string");
531 return raw_json_string(json+1);
533 simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
534 auto result = numberparsing::parse_unsigned(peek_non_root_scalar(
"uint64"));
535 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"uint64"); }
538 simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
539 auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar(
"uint64"));
540 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"uint64"); }
543 simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
544 auto result = numberparsing::parse_integer(peek_non_root_scalar(
"int64"));
545 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"int64"); }
548 simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
549 auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar(
"int64"));
550 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"int64"); }
553 simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
554 auto result = numberparsing::parse_double(peek_non_root_scalar(
"double"));
555 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"double"); }
558 simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
559 auto result = numberparsing::parse_double_in_string(peek_non_root_scalar(
"double"));
560 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"double"); }
563 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
564 auto result = parse_bool(peek_non_root_scalar(
"bool"));
565 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"bool"); }
568 simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
570 SIMDJSON_TRY(parse_null(peek_non_root_scalar(
"null")).get(is_null_value));
571 if(is_null_value) { advance_non_root_scalar(
"null"); }
572 return is_null_value;
574 simdjson_inline
bool value_iterator::is_negative() noexcept {
575 return numberparsing::is_negative(peek_non_root_scalar(
"numbersign"));
577 simdjson_inline
bool value_iterator::is_root_negative() noexcept {
578 return numberparsing::is_negative(peek_root_scalar(
"numbersign"));
580 simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
581 return numberparsing::is_integer(peek_non_root_scalar(
"integer"));
583 simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
584 return numberparsing::get_number_type(peek_non_root_scalar(
"integer"));
586 simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
588 error_code error = numberparsing::parse_number(peek_non_root_scalar(
"number"), num);
589 if(error) {
return error; }
593 simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(
bool check_trailing) noexcept {
594 auto max_len = peek_root_length();
595 auto json = peek_root_scalar(
"is_root_integer");
596 uint8_t tmpbuf[20+1+1]{};
598 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
601 auto answer = numberparsing::is_integer(tmpbuf);
605 if(check_trailing && (answer.error() ==
SUCCESS) && (!_json_iter->is_single_token())) {
return TRAILING_CONTENT; }
609 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> value_iterator::get_root_number_type(
bool check_trailing) noexcept {
610 auto max_len = peek_root_length();
611 auto json = peek_root_scalar(
"number");
615 uint8_t tmpbuf[1074+8+1+1];
616 tmpbuf[1074+8+1] =
'\0';
617 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
618 if(numberparsing::check_if_integer(json, max_len)) {
619 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
620 logger::log_error(*_json_iter, start_position(), depth(),
"Found big integer");
621 return number_type::big_integer;
623 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters and not a big integer");
626 auto answer = numberparsing::get_number_type(tmpbuf);
627 if (check_trailing && (answer.error() ==
SUCCESS) && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
630 simdjson_inline simdjson_result<number> value_iterator::get_root_number(
bool check_trailing) noexcept {
631 auto max_len = peek_root_length();
632 auto json = peek_root_scalar(
"number");
637 uint8_t tmpbuf[1074+8+1+1];
638 tmpbuf[1074+8+1] =
'\0';
639 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
640 if(numberparsing::check_if_integer(json, max_len)) {
641 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
642 logger::log_error(*_json_iter, start_position(), depth(),
"Found big integer");
645 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters and not a big integer");
649 error_code error = numberparsing::parse_number(tmpbuf, num);
650 if(error) {
return error; }
651 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
652 advance_root_scalar(
"number");
655 simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(
bool check_trailing,
bool allow_replacement) noexcept {
656 return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
658 template <
typename string_type>
659 simdjson_warn_unused simdjson_inline
error_code value_iterator::get_root_string(string_type& receiver,
bool check_trailing,
bool allow_replacement) noexcept {
660 std::string_view content;
661 auto err = get_root_string(check_trailing, allow_replacement).get(content);
662 if (err) {
return err; }
666 simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(
bool check_trailing) noexcept {
667 return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
669 simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(
bool check_trailing) noexcept {
670 auto json = peek_scalar(
"string");
671 if (*json !=
'"') {
return incorrect_type_error(
"Not a string"); }
672 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
673 advance_scalar(
"string");
674 return raw_json_string(json+1);
676 simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(
bool check_trailing) noexcept {
677 auto max_len = peek_root_length();
678 auto json = peek_root_scalar(
"uint64");
679 uint8_t tmpbuf[20+1+1]{};
681 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
682 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
685 auto result = numberparsing::parse_unsigned(tmpbuf);
686 if(result.error() ==
SUCCESS) {
687 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
688 advance_root_scalar(
"uint64");
692 simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(
bool check_trailing) noexcept {
693 auto max_len = peek_root_length();
694 auto json = peek_root_scalar(
"uint64");
695 uint8_t tmpbuf[20+1+1]{};
697 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
698 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
701 auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
702 if(result.error() ==
SUCCESS) {
703 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
704 advance_root_scalar(
"uint64");
708 simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(
bool check_trailing) noexcept {
709 auto max_len = peek_root_length();
710 auto json = peek_root_scalar(
"int64");
711 uint8_t tmpbuf[20+1+1];
713 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
714 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
718 auto result = numberparsing::parse_integer(tmpbuf);
719 if(result.error() ==
SUCCESS) {
720 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
721 advance_root_scalar(
"int64");
725 simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(
bool check_trailing) noexcept {
726 auto max_len = peek_root_length();
727 auto json = peek_root_scalar(
"int64");
728 uint8_t tmpbuf[20+1+1];
730 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
731 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
735 auto result = numberparsing::parse_integer_in_string(tmpbuf);
736 if(result.error() ==
SUCCESS) {
737 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
738 advance_root_scalar(
"int64");
742 simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(
bool check_trailing) noexcept {
743 auto max_len = peek_root_length();
744 auto json = peek_root_scalar(
"double");
748 uint8_t tmpbuf[1074+8+1+1];
749 tmpbuf[1074+8+1] =
'\0';
750 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
751 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters");
754 auto result = numberparsing::parse_double(tmpbuf);
755 if(result.error() ==
SUCCESS) {
756 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
757 advance_root_scalar(
"double");
762 simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(
bool check_trailing) noexcept {
763 auto max_len = peek_root_length();
764 auto json = peek_root_scalar(
"double");
768 uint8_t tmpbuf[1074+8+1+1];
769 tmpbuf[1074+8+1] =
'\0';
770 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
771 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters");
774 auto result = numberparsing::parse_double_in_string(tmpbuf);
775 if(result.error() ==
SUCCESS) {
776 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
777 advance_root_scalar(
"double");
781 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(
bool check_trailing) noexcept {
782 auto max_len = peek_root_length();
783 auto json = peek_root_scalar(
"bool");
784 uint8_t tmpbuf[5+1+1];
786 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) {
return incorrect_type_error(
"Not a boolean"); }
787 auto result = parse_bool(tmpbuf);
788 if(result.error() ==
SUCCESS) {
789 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
790 advance_root_scalar(
"bool");
794 simdjson_inline simdjson_result<bool> value_iterator::is_root_null(
bool check_trailing) noexcept {
795 auto max_len = peek_root_length();
796 auto json = peek_root_scalar(
"null");
797 bool result = (max_len >= 4 && !atomparsing::str4ncmp(json,
"null") &&
798 (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
800 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
801 advance_root_scalar(
"null");
802 }
else if (json[0] ==
'n') {
803 return incorrect_type_error(
"Not a null but starts with n");
808 simdjson_warn_unused simdjson_inline
error_code value_iterator::skip_child() noexcept {
809 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
810 SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
812 return _json_iter->skip_child(depth());
815 simdjson_inline value_iterator value_iterator::child() const noexcept {
817 return { _json_iter, depth()+1, _json_iter->token.position() };
823 SIMDJSON_PUSH_DISABLE_WARNINGS
824 SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
825 simdjson_inline
bool value_iterator::is_open() const noexcept {
826 return _json_iter->depth() >= depth();
828 SIMDJSON_POP_DISABLE_WARNINGS
830 simdjson_inline
bool value_iterator::at_end() const noexcept {
831 return _json_iter->at_end();
834 simdjson_inline
bool value_iterator::at_start() const noexcept {
835 return _json_iter->token.position() == start_position();
838 simdjson_inline
bool value_iterator::at_first_field() const noexcept {
839 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
840 return _json_iter->token.position() == start_position() + 1;
843 simdjson_inline
void value_iterator::abandon() noexcept {
844 _json_iter->abandon();
847 simdjson_warn_unused simdjson_inline
depth_t value_iterator::depth() const noexcept {
850 simdjson_warn_unused simdjson_inline
error_code value_iterator::error() const noexcept {
851 return _json_iter->error;
853 simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
854 return _json_iter->string_buf_loc();
856 simdjson_warn_unused simdjson_inline
const json_iterator &value_iterator::json_iter() const noexcept {
859 simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
863 simdjson_inline
const uint8_t *value_iterator::peek_start() const noexcept {
864 return _json_iter->peek(start_position());
866 simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
867 return _json_iter->peek_length(start_position());
869 simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
870 return _json_iter->peek_root_length(start_position());
873 simdjson_inline
const uint8_t *value_iterator::peek_scalar(
const char *type) noexcept {
874 logger::log_value(*_json_iter, start_position(), depth(), type);
876 if (!is_at_start()) {
return peek_start(); }
880 return _json_iter->peek();
883 simdjson_inline
void value_iterator::advance_scalar(
const char *type) noexcept {
884 logger::log_value(*_json_iter, start_position(), depth(), type);
886 if (!is_at_start()) {
return; }
890 _json_iter->return_current_and_advance();
891 _json_iter->ascend_to(depth()-1);
894 simdjson_inline
error_code value_iterator::start_container(uint8_t start_char,
const char *incorrect_type_message,
const char *type) noexcept {
895 logger::log_start_value(*_json_iter, start_position(), depth(), type);
898 if (!is_at_start()) {
899 #if SIMDJSON_DEVELOPMENT_CHECKS
903 if (*json != start_char) {
return incorrect_type_error(incorrect_type_message); }
911 json = _json_iter->peek();
912 if (*json != start_char) {
return incorrect_type_error(incorrect_type_message); }
913 _json_iter->return_current_and_advance();
921 simdjson_inline
const uint8_t *value_iterator::peek_root_scalar(
const char *type) noexcept {
922 logger::log_value(*_json_iter, start_position(), depth(), type);
923 if (!is_at_start()) {
return peek_start(); }
926 return _json_iter->peek();
928 simdjson_inline
const uint8_t *value_iterator::peek_non_root_scalar(
const char *type) noexcept {
929 logger::log_value(*_json_iter, start_position(), depth(), type);
930 if (!is_at_start()) {
return peek_start(); }
932 assert_at_non_root_start();
933 return _json_iter->peek();
936 simdjson_inline
void value_iterator::advance_root_scalar(
const char *type) noexcept {
937 logger::log_value(*_json_iter, start_position(), depth(), type);
938 if (!is_at_start()) {
return; }
941 _json_iter->return_current_and_advance();
942 _json_iter->ascend_to(depth()-1);
944 simdjson_inline
void value_iterator::advance_non_root_scalar(
const char *type) noexcept {
945 logger::log_value(*_json_iter, start_position(), depth(), type);
946 if (!is_at_start()) {
return; }
948 assert_at_non_root_start();
949 _json_iter->return_current_and_advance();
950 _json_iter->ascend_to(depth()-1);
953 simdjson_inline
error_code value_iterator::incorrect_type_error(
const char *message)
const noexcept {
954 logger::log_error(*_json_iter, start_position(), depth(), message);
958 simdjson_inline
bool value_iterator::is_at_start() const noexcept {
959 return position() == start_position();
962 simdjson_inline
bool value_iterator::is_at_key() const noexcept {
966 return _depth == _json_iter->_depth && *_json_iter->peek() ==
'"';
969 simdjson_inline
bool value_iterator::is_at_iterator_start() const noexcept {
971 auto delta = position() - start_position();
972 return delta == 1 || delta == 2;
975 inline void value_iterator::assert_at_start() const noexcept {
976 SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
977 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
978 SIMDJSON_ASSUME( _depth > 0 );
981 inline void value_iterator::assert_at_container_start() const noexcept {
982 SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
983 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
984 SIMDJSON_ASSUME( _depth > 0 );
987 inline void value_iterator::assert_at_next() const noexcept {
988 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
989 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
990 SIMDJSON_ASSUME( _depth > 0 );
993 simdjson_inline
void value_iterator::move_at_start() noexcept {
994 _json_iter->_depth = _depth;
995 _json_iter->token.set_position(_start_position);
998 simdjson_inline
void value_iterator::move_at_container_start() noexcept {
999 _json_iter->_depth = _depth;
1000 _json_iter->token.set_position(_start_position + 1);
1003 simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
1004 if(error()) {
return error(); }
1005 move_at_container_start();
1006 return started_array();
1009 simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
1010 if(error()) {
return error(); }
1011 move_at_container_start();
1012 return started_object();
1015 inline void value_iterator::assert_at_child() const noexcept {
1016 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
1017 SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
1018 SIMDJSON_ASSUME( _depth > 0 );
1021 inline void value_iterator::assert_at_root() const noexcept {
1023 SIMDJSON_ASSUME( _depth == 1 );
1026 inline void value_iterator::assert_at_non_root_start() const noexcept {
1028 SIMDJSON_ASSUME( _depth > 1 );
1031 inline void value_iterator::assert_is_valid() const noexcept {
1032 SIMDJSON_ASSUME( _json_iter !=
nullptr );
1035 simdjson_inline
bool value_iterator::is_valid() const noexcept {
1036 return _json_iter !=
nullptr;
1039 simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
1040 switch (*peek_start()) {
1052 case '0':
case '1':
case '2':
case '3':
case '4':
1053 case '5':
case '6':
case '7':
case '8':
case '9':
1060 simdjson_inline token_position value_iterator::start_position() const noexcept {
1061 return _start_position;
1064 simdjson_inline token_position value_iterator::position() const noexcept {
1065 return _json_iter->position();
1068 simdjson_inline token_position value_iterator::end_position() const noexcept {
1069 return _json_iter->end_position();
1072 simdjson_inline token_position value_iterator::last_position() const noexcept {
1073 return _json_iter->last_position();
1076 simdjson_inline
error_code value_iterator::report_error(
error_code error,
const char *message) noexcept {
1077 return _json_iter->report_error(error, message);
1086 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value_iterator &&value) noexcept
1087 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(value)) {}
1088 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(
error_code error) noexcept
1089 : 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...
@ 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.
@ TRAILING_CONTENT
Unexpected trailing content in the JSON input.
@ INCOMPLETE_ARRAY_OR_OBJECT
The document ends early.
@ NUMBER_ERROR
Problem while parsing a number.
@ BIGINT_ERROR
The integer value exceeds 64 bits.
The result of a simdjson operation that could fail.