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 {
18simdjson_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();
44 SIMDJSON_TRY(end_container());
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();
86simdjson_warn_unused simdjson_inline
error_code value_iterator::end_container() noexcept {
91 _json_iter->ascend_to(depth()-1);
99 switch (*_json_iter->return_current_and_advance()) {
101 logger::log_end_value(*_json_iter,
"object");
102 SIMDJSON_TRY( end_container() );
107 return report_error(
TAPE_ERROR,
"Missing comma between object fields");
123 if (at_first_field()) {
136 }
else if (!is_open()) {
137#if SIMDJSON_DEVELOPMENT_CHECKS
160 if ((error = skip_child() )) { abandon();
return error; }
161 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
162#if SIMDJSON_DEVELOPMENT_CHECKS
173 if ((error = field_key().get(actual_key) )) { abandon();
return error; };
176 if ((error = field_value() )) { abandon();
return error; }
186 logger::log_event(*
this,
"match", key, -2);
192 logger::log_event(*
this,
"no match", key, -2);
195 SIMDJSON_TRY( skip_child() );
199 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
206SIMDJSON_PUSH_DISABLE_WARNINGS
207SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
221 token_position search_start = _json_iter->position();
224 bool at_first = at_first_field();
247 }
else if (!is_open()) {
249#if SIMDJSON_DEVELOPMENT_CHECKS
255 SIMDJSON_TRY(reset_object().get(has_value));
275 if ((error = skip_child() )) { abandon();
return error; }
276 search_start = _json_iter->position();
277 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
278#if SIMDJSON_DEVELOPMENT_CHECKS
298 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
306 if ((error = field_key().get(actual_key) )) { abandon();
return error; };
309 if ((error = field_value() )) { abandon();
return error; }
320 logger::log_event(*
this,
"match", key, -2);
326 logger::log_event(*
this,
"no match", key, -2);
329 SIMDJSON_TRY( skip_child() );
333 if ((error = has_next_field().get(has_value) )) { abandon();
return error; }
339 if(at_first) {
return false; }
345 SIMDJSON_TRY(reset_object().get(has_value));
347 SIMDJSON_ASSUME(has_value);
348 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
356 error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
359 error = field_value(); SIMDJSON_ASSUME(!error);
370 logger::log_event(*
this,
"match", key, -2);
376 logger::log_event(*
this,
"no match", key, -2);
379 SIMDJSON_TRY( skip_child() );
383 if(_json_iter->position() == search_start) {
return false; }
387 error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
395SIMDJSON_POP_DISABLE_WARNINGS
400 const uint8_t *key = _json_iter->return_current_and_advance();
401 if (*(key++) !=
'"') {
return report_error(
TAPE_ERROR,
"Object key is not a string"); }
408 if (*_json_iter->return_current_and_advance() !=
':') {
return report_error(
TAPE_ERROR,
"Missing colon in object field"); }
409 _json_iter->descend_to(depth()+1);
414 SIMDJSON_TRY( start_container(
'[',
"Not an array",
"array") );
415 return started_array();
419 SIMDJSON_TRY( start_container(
'[',
"Not an array",
"array") );
420 return started_root_array();
423inline std::string value_iterator::to_string() const noexcept {
424 auto answer = std::string(
"value_iterator [ depth : ") + std::to_string(_depth) + std::string(
", ");
425 if(_json_iter !=
nullptr) { answer += _json_iter->to_string(); }
426 answer += std::string(
" ]");
431 assert_at_container_start();
432 if (*_json_iter->peek() ==
']') {
433 logger::log_value(*_json_iter,
"empty array");
434 _json_iter->return_current_and_advance();
435 SIMDJSON_TRY( end_container() );
438 _json_iter->descend_to(depth()+1);
439#if SIMDJSON_DEVELOPMENT_CHECKS
440 _json_iter->set_start_position(_depth, start_position());
450 if ( ! _json_iter->streaming() ) {
456 if (*_json_iter->peek_last() !=
']') {
457 _json_iter->abandon();
466 if ((*_json_iter->peek(_json_iter->end_position()) ==
']') && (!_json_iter->balanced())) {
467 _json_iter->abandon();
476 auto error = check_root_array();
477 if (error) {
return error; }
478 return started_array();
484 logger::log_event(*
this,
"has_next_element");
485 switch (*_json_iter->return_current_and_advance()) {
487 logger::log_end_value(*_json_iter,
"array");
488 SIMDJSON_TRY( end_container() );
491 _json_iter->descend_to(depth()+1);
494 return report_error(
TAPE_ERROR,
"Missing comma between array elements");
498simdjson_warn_unused simdjson_inline
simdjson_result<bool> value_iterator::parse_bool(
const uint8_t *json)
const noexcept {
499 auto not_true = atomparsing::str4ncmp(json,
"true");
500 auto not_false = atomparsing::str4ncmp(json,
"fals") | (json[4] ^
'e');
501 bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
502 if (error) {
return incorrect_type_error(
"Not a boolean"); }
505simdjson_warn_unused simdjson_inline
simdjson_result<bool> value_iterator::parse_null(
const uint8_t *json)
const noexcept {
506 bool is_null_string = !atomparsing::str4ncmp(json,
"null") && jsoncharutils::is_structural_or_whitespace(json[4]);
508 if(!is_null_string && json[0]==
'n') {
return incorrect_type_error(
"Not a null but starts with n"); }
509 return is_null_string;
512simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(
bool allow_replacement)
noexcept {
513 return get_raw_json_string().unescape(json_iter(), allow_replacement);
515template <
typename string_type>
516simdjson_warn_unused simdjson_inline
error_code value_iterator::get_string(string_type& receiver,
bool allow_replacement)
noexcept {
517 std::string_view content;
519 auto saved_string_buf_loc = _json_iter->string_buf_loc();
520 auto err = get_string(allow_replacement).get(content);
521 if (err) {
return err; }
524 _json_iter->string_buf_loc() = saved_string_buf_loc;
527simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
528 return get_raw_json_string().unescape_wobbly(json_iter());
530simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
531 auto json = peek_scalar(
"string");
532 if (*json !=
'"') {
return incorrect_type_error(
"Not a string"); }
533 advance_scalar(
"string");
534 return raw_json_string(json+1);
536simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
537 auto result = numberparsing::parse_unsigned(peek_non_root_scalar(
"uint64"));
538 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"uint64"); }
541simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
542 auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar(
"uint64"));
543 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"uint64"); }
546simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
547 auto result = numberparsing::parse_integer(peek_non_root_scalar(
"int64"));
548 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"int64"); }
551simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
552 auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar(
"int64"));
553 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"int64"); }
556simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
557 auto result = numberparsing::parse_double(peek_non_root_scalar(
"double"));
558 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"double"); }
561simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
562 auto result = numberparsing::parse_double_in_string(peek_non_root_scalar(
"double"));
563 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"double"); }
566simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
567 auto result = parse_bool(peek_non_root_scalar(
"bool"));
568 if(result.error() ==
SUCCESS) { advance_non_root_scalar(
"bool"); }
571simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
573 SIMDJSON_TRY(parse_null(peek_non_root_scalar(
"null")).get(is_null_value));
574 if(is_null_value) { advance_non_root_scalar(
"null"); }
575 return is_null_value;
577simdjson_inline
bool value_iterator::is_negative() noexcept {
578 return numberparsing::is_negative(peek_non_root_scalar(
"numbersign"));
580simdjson_inline
bool value_iterator::is_root_negative() noexcept {
581 return numberparsing::is_negative(peek_root_scalar(
"numbersign"));
583simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
584 return numberparsing::is_integer(peek_non_root_scalar(
"integer"));
586simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
587 return numberparsing::get_number_type(peek_non_root_scalar(
"integer"));
589simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
591 error_code error = numberparsing::parse_number(peek_non_root_scalar(
"number"), num);
592 if(error) {
return error; }
596simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(
bool check_trailing)
noexcept {
597 auto max_len = peek_root_length();
598 auto json = peek_root_scalar(
"is_root_integer");
599 uint8_t tmpbuf[20+1+1]{};
601 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
604 auto answer = numberparsing::is_integer(tmpbuf);
608 if(check_trailing && (answer.error() ==
SUCCESS) && (!_json_iter->is_single_token())) {
return TRAILING_CONTENT; }
612simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> value_iterator::get_root_number_type(
bool check_trailing)
noexcept {
613 auto max_len = peek_root_length();
614 auto json = peek_root_scalar(
"number");
618 uint8_t tmpbuf[1074+8+1+1];
619 tmpbuf[1074+8+1] =
'\0';
620 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
621 if(numberparsing::check_if_integer(json, max_len)) {
622 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
623 logger::log_error(*_json_iter, start_position(), depth(),
"Found big integer");
624 return number_type::big_integer;
626 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters and not a big integer");
629 auto answer = numberparsing::get_number_type(tmpbuf);
630 if (check_trailing && (answer.error() ==
SUCCESS) && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
633simdjson_inline simdjson_result<number> value_iterator::get_root_number(
bool check_trailing)
noexcept {
634 auto max_len = peek_root_length();
635 auto json = peek_root_scalar(
"number");
640 uint8_t tmpbuf[1074+8+1+1];
641 tmpbuf[1074+8+1] =
'\0';
642 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
643 if(numberparsing::check_if_integer(json, max_len)) {
644 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
645 logger::log_error(*_json_iter, start_position(), depth(),
"Found big integer");
648 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters and not a big integer");
652 error_code error = numberparsing::parse_number(tmpbuf, num);
653 if(error) {
return error; }
654 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
655 advance_root_scalar(
"number");
658simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(
bool check_trailing,
bool allow_replacement)
noexcept {
659 return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
661template <
typename string_type>
662simdjson_warn_unused simdjson_inline
error_code value_iterator::get_root_string(string_type& receiver,
bool check_trailing,
bool allow_replacement)
noexcept {
663 std::string_view content;
665 auto saved_string_buf_loc = _json_iter->string_buf_loc();
666 auto err = get_root_string(check_trailing, allow_replacement).get(content);
667 if (err) {
return err; }
670 _json_iter->string_buf_loc() = saved_string_buf_loc;
673simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(
bool check_trailing)
noexcept {
674 return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
676simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(
bool check_trailing)
noexcept {
677 auto json = peek_scalar(
"string");
678 if (*json !=
'"') {
return incorrect_type_error(
"Not a string"); }
679 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
680 advance_scalar(
"string");
681 return raw_json_string(json+1);
683simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(
bool check_trailing)
noexcept {
684 auto max_len = peek_root_length();
685 auto json = peek_root_scalar(
"uint64");
686 uint8_t tmpbuf[20+1+1]{};
688 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
689 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
692 auto result = numberparsing::parse_unsigned(tmpbuf);
693 if(result.error() ==
SUCCESS) {
694 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
695 advance_root_scalar(
"uint64");
699simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(
bool check_trailing)
noexcept {
700 auto max_len = peek_root_length();
701 auto json = peek_root_scalar(
"uint64");
702 uint8_t tmpbuf[20+1+1]{};
704 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
705 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
708 auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
709 if(result.error() ==
SUCCESS) {
710 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
711 advance_root_scalar(
"uint64");
715simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(
bool check_trailing)
noexcept {
716 auto max_len = peek_root_length();
717 auto json = peek_root_scalar(
"int64");
718 uint8_t tmpbuf[20+1+1];
720 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
721 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
725 auto result = numberparsing::parse_integer(tmpbuf);
726 if(result.error() ==
SUCCESS) {
727 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
728 advance_root_scalar(
"int64");
732simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(
bool check_trailing)
noexcept {
733 auto max_len = peek_root_length();
734 auto json = peek_root_scalar(
"int64");
735 uint8_t tmpbuf[20+1+1];
737 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
738 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 20 characters");
742 auto result = numberparsing::parse_integer_in_string(tmpbuf);
743 if(result.error() ==
SUCCESS) {
744 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
745 advance_root_scalar(
"int64");
749simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(
bool check_trailing)
noexcept {
750 auto max_len = peek_root_length();
751 auto json = peek_root_scalar(
"double");
755 uint8_t tmpbuf[1074+8+1+1];
756 tmpbuf[1074+8+1] =
'\0';
757 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
758 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters");
761 auto result = numberparsing::parse_double(tmpbuf);
762 if(result.error() ==
SUCCESS) {
763 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
764 advance_root_scalar(
"double");
769simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(
bool check_trailing)
noexcept {
770 auto max_len = peek_root_length();
771 auto json = peek_root_scalar(
"double");
775 uint8_t tmpbuf[1074+8+1+1];
776 tmpbuf[1074+8+1] =
'\0';
777 if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
778 logger::log_error(*_json_iter, start_position(), depth(),
"Root number more than 1082 characters");
781 auto result = numberparsing::parse_double_in_string(tmpbuf);
782 if(result.error() ==
SUCCESS) {
783 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
784 advance_root_scalar(
"double");
789simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(
bool check_trailing)
noexcept {
790 auto max_len = peek_root_length();
791 auto json = peek_root_scalar(
"bool");
795 bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json,
"true") &&
796 (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
797 bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json,
"false") &&
798 (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5])));
799 if(value_true ==
false && value_false ==
false) {
return incorrect_type_error(
"Not a boolean"); }
800 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
801 advance_root_scalar(
"bool");
805simdjson_inline simdjson_result<bool> value_iterator::is_root_null(
bool check_trailing)
noexcept {
806 auto max_len = peek_root_length();
807 auto json = peek_root_scalar(
"null");
808 bool result = (max_len >= 4 && !atomparsing::str4ncmp(json,
"null") &&
809 (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
811 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
812 advance_root_scalar(
"null");
813 }
else if (json[0] ==
'n') {
814 return incorrect_type_error(
"Not a null but starts with n");
819simdjson_warn_unused simdjson_inline
error_code value_iterator::skip_child() noexcept {
820 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
821 SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
823 return _json_iter->skip_child(depth());
828 return { _json_iter, depth()+1, _json_iter->token.position() };
834SIMDJSON_PUSH_DISABLE_WARNINGS
835SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
836simdjson_inline
bool value_iterator::is_open() const noexcept {
837 return _json_iter->depth() >= depth();
839SIMDJSON_POP_DISABLE_WARNINGS
841simdjson_inline
bool value_iterator::at_end() const noexcept {
842 return _json_iter->at_end();
845simdjson_inline
bool value_iterator::at_start() const noexcept {
846 return _json_iter->token.position() == start_position();
849simdjson_inline
bool value_iterator::at_first_field() const noexcept {
850 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
851 return _json_iter->token.position() == start_position() + 1;
854simdjson_inline
void value_iterator::abandon() noexcept {
855 _json_iter->abandon();
858simdjson_warn_unused simdjson_inline
depth_t value_iterator::depth() const noexcept {
861simdjson_warn_unused simdjson_inline
error_code value_iterator::error() const noexcept {
862 return _json_iter->error;
864simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
865 return _json_iter->string_buf_loc();
867simdjson_warn_unused simdjson_inline
const json_iterator &value_iterator::json_iter() const noexcept {
870simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
874simdjson_inline
const uint8_t *value_iterator::peek_start() const noexcept {
875 return _json_iter->peek(start_position());
877simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
878 return _json_iter->peek_length(start_position());
880simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
881 return _json_iter->peek_root_length(start_position());
884simdjson_inline
const uint8_t *value_iterator::peek_scalar(
const char *type)
noexcept {
885 logger::log_value(*_json_iter, start_position(), depth(), type);
887 if (!is_at_start()) {
return peek_start(); }
891 return _json_iter->peek();
894simdjson_inline
void value_iterator::advance_scalar(
const char *type)
noexcept {
895 logger::log_value(*_json_iter, start_position(), depth(), type);
897 if (!is_at_start()) {
return; }
901 _json_iter->return_current_and_advance();
902 _json_iter->ascend_to(depth()-1);
905simdjson_warn_unused simdjson_inline
error_code value_iterator::start_container(uint8_t start_char,
const char *incorrect_type_message,
const char *type)
noexcept {
906 logger::log_start_value(*_json_iter, start_position(), depth(), type);
909 if (!is_at_start()) {
910#if SIMDJSON_DEVELOPMENT_CHECKS
914 if (*json != start_char) {
return incorrect_type_error(incorrect_type_message); }
922 json = _json_iter->peek();
923 if (*json != start_char) {
return incorrect_type_error(incorrect_type_message); }
924 _json_iter->return_current_and_advance();
932simdjson_inline
const uint8_t *value_iterator::peek_root_scalar(
const char *type)
noexcept {
933 logger::log_value(*_json_iter, start_position(), depth(), type);
934 if (!is_at_start()) {
return peek_start(); }
937 return _json_iter->peek();
939simdjson_inline
const uint8_t *value_iterator::peek_non_root_scalar(
const char *type)
noexcept {
940 logger::log_value(*_json_iter, start_position(), depth(), type);
941 if (!is_at_start()) {
return peek_start(); }
943 assert_at_non_root_start();
944 return _json_iter->peek();
947simdjson_inline
void value_iterator::advance_root_scalar(
const char *type)
noexcept {
948 logger::log_value(*_json_iter, start_position(), depth(), type);
949 if (!is_at_start()) {
return; }
952 _json_iter->return_current_and_advance();
953 _json_iter->ascend_to(depth()-1);
955simdjson_inline
void value_iterator::advance_non_root_scalar(
const char *type)
noexcept {
956 logger::log_value(*_json_iter, start_position(), depth(), type);
957 if (!is_at_start()) {
return; }
959 assert_at_non_root_start();
960 _json_iter->return_current_and_advance();
961 _json_iter->ascend_to(depth()-1);
964simdjson_inline
error_code value_iterator::incorrect_type_error(
const char *message)
const noexcept {
965 logger::log_error(*_json_iter, start_position(), depth(), message);
969simdjson_inline
bool value_iterator::is_at_start() const noexcept {
970 return position() == start_position();
973simdjson_inline
bool value_iterator::is_at_key() const noexcept {
980 return _depth == _json_iter->_depth && *_json_iter->peek() ==
'"';
983simdjson_inline
bool value_iterator::is_at_iterator_start() const noexcept {
985 auto delta = position() - start_position();
986 return delta == 1 || delta == 2;
989inline void value_iterator::assert_at_start() const noexcept {
990 SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
991 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
992 SIMDJSON_ASSUME( _depth > 0 );
995inline void value_iterator::assert_at_container_start() const noexcept {
996 SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
997 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
998 SIMDJSON_ASSUME( _depth > 0 );
1001inline void value_iterator::assert_at_next() const noexcept {
1002 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
1003 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
1004 SIMDJSON_ASSUME( _depth > 0 );
1007simdjson_inline
void value_iterator::move_at_start() noexcept {
1008 _json_iter->_depth = _depth;
1009 _json_iter->token.set_position(_start_position);
1012simdjson_inline
void value_iterator::move_at_container_start() noexcept {
1013 _json_iter->_depth = _depth;
1014 _json_iter->token.set_position(_start_position + 1);
1017simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
1018 if(error()) {
return error(); }
1019 move_at_container_start();
1020 return started_array();
1023simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
1024 if(error()) {
return error(); }
1025 move_at_container_start();
1026 return started_object();
1029inline void value_iterator::assert_at_child() const noexcept {
1030 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
1031 SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
1032 SIMDJSON_ASSUME( _depth > 0 );
1035inline void value_iterator::assert_at_root() const noexcept {
1037 SIMDJSON_ASSUME( _depth == 1 );
1040inline void value_iterator::assert_at_non_root_start() const noexcept {
1042 SIMDJSON_ASSUME( _depth > 1 );
1045inline void value_iterator::assert_is_valid() const noexcept {
1046 SIMDJSON_ASSUME( _json_iter !=
nullptr );
1049simdjson_inline
bool value_iterator::is_valid() const noexcept {
1050 return _json_iter !=
nullptr;
1053simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
1054 switch (*peek_start()) {
1066 case '0':
case '1':
case '2':
case '3':
case '4':
1067 case '5':
case '6':
case '7':
case '8':
case '9':
1070 return json_type::unknown;
1074simdjson_inline token_position value_iterator::start_position() const noexcept {
1075 return _start_position;
1078simdjson_inline token_position value_iterator::position() const noexcept {
1079 return _json_iter->position();
1082simdjson_inline token_position value_iterator::end_position() const noexcept {
1083 return _json_iter->end_position();
1086simdjson_inline token_position value_iterator::last_position() const noexcept {
1087 return _json_iter->last_position();
1090simdjson_inline
error_code value_iterator::report_error(
error_code error,
const char *message)
noexcept {
1091 return _json_iter->report_error(error, message);
1100simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value_iterator &&value) noexcept
1101 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(value)) {}
1102simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(
error_code error) noexcept
1103 : 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 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.
@ 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.