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);
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");
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; }
207SIMDJSON_PUSH_DISABLE_WARNINGS
208SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
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; }
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; }
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);
396SIMDJSON_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"); }
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();
424inline 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());
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");
503 if (error) {
return incorrect_type_error(
"Not a boolean"); }
506simdjson_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;
513simdjson_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);
516template <
typename string_type>
517simdjson_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; }
524simdjson_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());
527simdjson_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);
533simdjson_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"); }
538simdjson_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"); }
543simdjson_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"); }
548simdjson_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"); }
553simdjson_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"); }
558simdjson_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"); }
563simdjson_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"); }
568simdjson_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;
574simdjson_inline
bool value_iterator::is_negative() noexcept {
575 return numberparsing::is_negative(peek_non_root_scalar(
"numbersign"));
577simdjson_inline
bool value_iterator::is_root_negative() noexcept {
578 return numberparsing::is_negative(peek_root_scalar(
"numbersign"));
580simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
581 return numberparsing::is_integer(peek_non_root_scalar(
"integer"));
583simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
584 return numberparsing::get_number_type(peek_non_root_scalar(
"integer"));
586simdjson_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; }
593simdjson_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; }
609simdjson_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; }
630simdjson_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");
655simdjson_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);
658template <
typename string_type>
659simdjson_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; }
666simdjson_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());
669simdjson_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);
676simdjson_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");
692simdjson_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");
708simdjson_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");
725simdjson_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");
742simdjson_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");
762simdjson_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");
782simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(
bool check_trailing)
noexcept {
783 auto max_len = peek_root_length();
784 auto json = peek_root_scalar(
"bool");
788 bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json,
"true") &&
789 (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
790 bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json,
"false") &&
791 (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5])));
792 if(value_true ==
false && value_false ==
false) {
return incorrect_type_error(
"Not a boolean"); }
793 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
794 advance_root_scalar(
"bool");
798simdjson_inline simdjson_result<bool> value_iterator::is_root_null(
bool check_trailing)
noexcept {
799 auto max_len = peek_root_length();
800 auto json = peek_root_scalar(
"null");
801 bool result = (max_len >= 4 && !atomparsing::str4ncmp(json,
"null") &&
802 (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
804 if (check_trailing && !_json_iter->is_single_token()) {
return TRAILING_CONTENT; }
805 advance_root_scalar(
"null");
806 }
else if (json[0] ==
'n') {
807 return incorrect_type_error(
"Not a null but starts with n");
812simdjson_warn_unused simdjson_inline
error_code value_iterator::skip_child() noexcept {
813 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
814 SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
816 return _json_iter->skip_child(depth());
821 return { _json_iter, depth()+1, _json_iter->token.position() };
827SIMDJSON_PUSH_DISABLE_WARNINGS
828SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
829simdjson_inline
bool value_iterator::is_open()
const noexcept {
830 return _json_iter->depth() >= depth();
832SIMDJSON_POP_DISABLE_WARNINGS
834simdjson_inline
bool value_iterator::at_end() const noexcept {
835 return _json_iter->at_end();
838simdjson_inline
bool value_iterator::at_start() const noexcept {
839 return _json_iter->token.position() == start_position();
842simdjson_inline
bool value_iterator::at_first_field() const noexcept {
843 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
844 return _json_iter->token.position() == start_position() + 1;
847simdjson_inline
void value_iterator::abandon() noexcept {
848 _json_iter->abandon();
851simdjson_warn_unused simdjson_inline
depth_t value_iterator::depth() const noexcept {
854simdjson_warn_unused simdjson_inline
error_code value_iterator::error() const noexcept {
855 return _json_iter->error;
857simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
858 return _json_iter->string_buf_loc();
860simdjson_warn_unused simdjson_inline
const json_iterator &value_iterator::json_iter() const noexcept {
863simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
867simdjson_inline
const uint8_t *value_iterator::peek_start() const noexcept {
868 return _json_iter->peek(start_position());
870simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
871 return _json_iter->peek_length(start_position());
873simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
874 return _json_iter->peek_root_length(start_position());
877simdjson_inline
const uint8_t *value_iterator::peek_scalar(
const char *type)
noexcept {
878 logger::log_value(*_json_iter, start_position(), depth(), type);
880 if (!is_at_start()) {
return peek_start(); }
884 return _json_iter->peek();
887simdjson_inline
void value_iterator::advance_scalar(
const char *type)
noexcept {
888 logger::log_value(*_json_iter, start_position(), depth(), type);
890 if (!is_at_start()) {
return; }
894 _json_iter->return_current_and_advance();
895 _json_iter->ascend_to(depth()-1);
898simdjson_warn_unused simdjson_inline
error_code value_iterator::start_container(uint8_t start_char,
const char *incorrect_type_message,
const char *type)
noexcept {
899 logger::log_start_value(*_json_iter, start_position(), depth(), type);
902 if (!is_at_start()) {
903#if SIMDJSON_DEVELOPMENT_CHECKS
907 if (*json != start_char) {
return incorrect_type_error(incorrect_type_message); }
915 json = _json_iter->peek();
916 if (*json != start_char) {
return incorrect_type_error(incorrect_type_message); }
917 _json_iter->return_current_and_advance();
925simdjson_inline
const uint8_t *value_iterator::peek_root_scalar(
const char *type)
noexcept {
926 logger::log_value(*_json_iter, start_position(), depth(), type);
927 if (!is_at_start()) {
return peek_start(); }
930 return _json_iter->peek();
932simdjson_inline
const uint8_t *value_iterator::peek_non_root_scalar(
const char *type)
noexcept {
933 logger::log_value(*_json_iter, start_position(), depth(), type);
934 if (!is_at_start()) {
return peek_start(); }
936 assert_at_non_root_start();
937 return _json_iter->peek();
940simdjson_inline
void value_iterator::advance_root_scalar(
const char *type)
noexcept {
941 logger::log_value(*_json_iter, start_position(), depth(), type);
942 if (!is_at_start()) {
return; }
945 _json_iter->return_current_and_advance();
946 _json_iter->ascend_to(depth()-1);
948simdjson_inline
void value_iterator::advance_non_root_scalar(
const char *type)
noexcept {
949 logger::log_value(*_json_iter, start_position(), depth(), type);
950 if (!is_at_start()) {
return; }
952 assert_at_non_root_start();
953 _json_iter->return_current_and_advance();
954 _json_iter->ascend_to(depth()-1);
957simdjson_inline
error_code value_iterator::incorrect_type_error(
const char *message)
const noexcept {
958 logger::log_error(*_json_iter, start_position(), depth(), message);
962simdjson_inline
bool value_iterator::is_at_start() const noexcept {
963 return position() == start_position();
966simdjson_inline
bool value_iterator::is_at_key() const noexcept {
970 return _depth == _json_iter->_depth && *_json_iter->peek() ==
'"';
973simdjson_inline
bool value_iterator::is_at_iterator_start() const noexcept {
975 auto delta = position() - start_position();
976 return delta == 1 || delta == 2;
979inline void value_iterator::assert_at_start() const noexcept {
980 SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
981 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
982 SIMDJSON_ASSUME( _depth > 0 );
985inline void value_iterator::assert_at_container_start() const noexcept {
986 SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
987 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
988 SIMDJSON_ASSUME( _depth > 0 );
991inline void value_iterator::assert_at_next() const noexcept {
992 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
993 SIMDJSON_ASSUME( _json_iter->_depth == _depth );
994 SIMDJSON_ASSUME( _depth > 0 );
997simdjson_inline
void value_iterator::move_at_start() noexcept {
998 _json_iter->_depth = _depth;
999 _json_iter->token.set_position(_start_position);
1002simdjson_inline
void value_iterator::move_at_container_start() noexcept {
1003 _json_iter->_depth = _depth;
1004 _json_iter->token.set_position(_start_position + 1);
1007simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
1008 if(error()) {
return error(); }
1009 move_at_container_start();
1010 return started_array();
1013simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
1014 if(error()) {
return error(); }
1015 move_at_container_start();
1016 return started_object();
1019inline void value_iterator::assert_at_child() const noexcept {
1020 SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
1021 SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
1022 SIMDJSON_ASSUME( _depth > 0 );
1025inline void value_iterator::assert_at_root() const noexcept {
1027 SIMDJSON_ASSUME( _depth == 1 );
1030inline void value_iterator::assert_at_non_root_start() const noexcept {
1032 SIMDJSON_ASSUME( _depth > 1 );
1035inline void value_iterator::assert_is_valid() const noexcept {
1036 SIMDJSON_ASSUME( _json_iter !=
nullptr );
1039simdjson_inline
bool value_iterator::is_valid() const noexcept {
1040 return _json_iter !=
nullptr;
1043simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
1044 switch (*peek_start()) {
1056 case '0':
case '1':
case '2':
case '3':
case '4':
1057 case '5':
case '6':
case '7':
case '8':
case '9':
1060 return json_type::unknown;
1064simdjson_inline token_position value_iterator::start_position() const noexcept {
1065 return _start_position;
1068simdjson_inline token_position value_iterator::position() const noexcept {
1069 return _json_iter->position();
1072simdjson_inline token_position value_iterator::end_position() const noexcept {
1073 return _json_iter->end_position();
1076simdjson_inline token_position value_iterator::last_position() const noexcept {
1077 return _json_iter->last_position();
1080simdjson_inline
error_code value_iterator::report_error(
error_code error,
const char *message)
noexcept {
1081 return _json_iter->report_error(error, message);
1090simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value_iterator &&value) noexcept
1091 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(value)) {}
1092simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(
error_code error) noexcept
1093 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(error) {}
A forward-only JSON array.
A string escaped per JSON rules, terminated with quote (").
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.