1#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
3#ifndef SIMDJSON_CONDITIONAL_INCLUDE
4#define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
5#include "simdjson/internal/dom_parser_implementation.h"
6#include "simdjson/generic/ondemand/base.h"
7#include "simdjson/generic/ondemand/json_iterator.h"
8#include "simdjson/generic/ondemand/parser.h"
9#include "simdjson/generic/ondemand/raw_json_string.h"
10#include "simdjson/generic/ondemand/logger-inl.h"
11#include "simdjson/generic/ondemand/parser-inl.h"
12#include "simdjson/generic/ondemand/token_iterator-inl.h"
16namespace SIMDJSON_IMPLEMENTATION {
19simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept
20 : token(std::forward<token_iterator>(other.token)),
22 _string_buf_loc{other._string_buf_loc},
26 _streaming{other._streaming}
27#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
28 , _allow_incomplete_json{other._allow_incomplete_json}
31 other.parser =
nullptr;
33simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other)
noexcept {
35 parser = other.parser;
36 _string_buf_loc = other._string_buf_loc;
38 _depth = other._depth;
40 _streaming = other._streaming;
41#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
42 _allow_incomplete_json = other._allow_incomplete_json;
44 other.parser =
nullptr;
48simdjson_inline json_iterator::json_iterator(
const uint8_t *buf, ondemand::parser *_parser) noexcept
49 : token(buf, &_parser->implementation->structural_indexes[0]),
51 _string_buf_loc{parser->string_buf.get()},
53 _root{parser->implementation->structural_indexes.get()},
57 logger::log_headers();
63#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
64simdjson_inline json_iterator::json_iterator(
const uint8_t *buf, ondemand::parser *_parser,
bool streaming) noexcept
65 : token(buf, &_parser->implementation->structural_indexes[0]),
67 _string_buf_loc{parser->string_buf.get()},
69 _root{parser->implementation->structural_indexes.get()},
70 _streaming{streaming},
71 _allow_incomplete_json{
true}
74 logger::log_headers();
81inline void json_iterator::rewind() noexcept {
82 token.set_position( root_position() );
83 logger::log_headers();
84 _string_buf_loc = parser->string_buf.get();
88inline bool json_iterator::balanced() const noexcept {
89 token_iterator ti(token);
91 ti.set_position( root_position() );
92 while(ti.peek() <= peek_last()) {
93 switch (*ti.return_current_and_advance())
112SIMDJSON_PUSH_DISABLE_WARNINGS
113SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
114simdjson_warn_unused simdjson_inline
error_code json_iterator::skip_child(
depth_t parent_depth)
noexcept {
115 if (depth() <= parent_depth) {
return SUCCESS; }
116 switch (*return_current_and_advance()) {
125 case '[':
case '{':
case ':':
126 logger::log_start_value(*
this,
"skip");
130 logger::log_value(*
this,
"skip");
134 logger::log_end_value(*
this,
"skip");
136 if (depth() <= parent_depth) {
return SUCCESS; }
137#if SIMDJSON_CHECK_EOF
144 if(!at_end() && *peek() ==
':') {
150 logger::log_value(*
this,
"key");
151 return_current_and_advance();
154 simdjson_fallthrough;
158 logger::log_value(*
this,
"skip");
160 if (depth() <= parent_depth) {
return SUCCESS; }
165 while (position() < end_position()) {
166 switch (*return_current_and_advance()) {
168 logger::log_start_value(*
this,
"skip");
177 logger::log_end_value(*
this,
"skip");
179 if (depth() <= parent_depth) {
return SUCCESS; }
182 logger::log_value(*
this,
"skip",
"");
190SIMDJSON_POP_DISABLE_WARNINGS
192simdjson_inline
bool json_iterator::at_root() const noexcept {
193 return position() == root_position();
196simdjson_inline
bool json_iterator::is_single_token() const noexcept {
197 return parser->implementation->n_structural_indexes == 1;
200simdjson_inline
bool json_iterator::streaming() const noexcept {
204#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
205simdjson_inline
bool json_iterator::allow_incomplete_json() const noexcept {
206 return _allow_incomplete_json;
209simdjson_inline
size_t json_iterator::remaining_input_length(
const uint8_t *json)
const noexcept {
210 const uint8_t *end = token.buf + parser->_document_len;
211 return json < end ? size_t(end - json) : 0;
215simdjson_inline token_position json_iterator::root_position() const noexcept {
219simdjson_inline
void json_iterator::assert_at_document_depth() const noexcept {
220 SIMDJSON_ASSUME( _depth == 1 );
223simdjson_inline
void json_iterator::assert_at_root() const noexcept {
224 SIMDJSON_ASSUME( _depth == 1 );
225#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
228 SIMDJSON_ASSUME( token.position() == _root );
232simdjson_inline
void json_iterator::assert_more_tokens(uint32_t required_tokens)
const noexcept {
233 assert_valid_position(token._position + required_tokens - 1);
236simdjson_inline
void json_iterator::assert_valid_position(token_position position)
const noexcept {
238#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
239 SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
240 SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
244simdjson_inline
bool json_iterator::at_end() const noexcept {
245 return position() == end_position();
247simdjson_inline token_position json_iterator::end_position() const noexcept {
248 uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
249 return &parser->implementation->structural_indexes[n_structural_indexes];
252inline std::string json_iterator::to_string() const noexcept {
253 if( !is_alive() ) {
return "dead json_iterator instance"; }
254 const char * current_structural =
reinterpret_cast<const char *
>(token.peek());
255 return std::string(
"json_iterator [ depth : ") + std::to_string(_depth)
256 + std::string(
", structural : '") + std::string(current_structural,1)
257 + std::string(
"', offset : ") + std::to_string(token.current_offset())
262inline simdjson_result<const char *> json_iterator::current_location() const noexcept {
265 return reinterpret_cast<const char *
>(token.peek(-1));
267 return reinterpret_cast<const char *
>(token.peek());
273 return reinterpret_cast<const char *
>(token.peek());
276simdjson_inline
bool json_iterator::is_alive() const noexcept {
280simdjson_inline
void json_iterator::abandon() noexcept {
285simdjson_inline
const uint8_t *json_iterator::return_current_and_advance() noexcept {
286#if SIMDJSON_CHECK_EOF
287 assert_more_tokens();
289 return token.return_current_and_advance();
292simdjson_inline
const uint8_t *json_iterator::unsafe_pointer() const noexcept {
297simdjson_inline
const uint8_t *json_iterator::peek(int32_t delta)
const noexcept {
298#if SIMDJSON_CHECK_EOF
299 assert_more_tokens(delta+1);
301 return token.peek(delta);
304simdjson_inline uint32_t json_iterator::peek_length(int32_t delta)
const noexcept {
305#if SIMDJSON_CHECK_EOF
306 assert_more_tokens(delta+1);
308 return token.peek_length(delta);
311simdjson_inline
const uint8_t *json_iterator::peek(token_position position)
const noexcept {
317 return token.peek(position);
320simdjson_inline uint32_t json_iterator::peek_length(token_position position)
const noexcept {
321#if SIMDJSON_CHECK_EOF
322 assert_valid_position(position);
324 return token.peek_length(position);
326simdjson_inline uint32_t json_iterator::peek_root_length(token_position position)
const noexcept {
327#if SIMDJSON_CHECK_EOF
328 assert_valid_position(position);
330 return token.peek_root_length(position);
333simdjson_inline token_position json_iterator::last_position() const noexcept {
337 uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
338 SIMDJSON_ASSUME(n_structural_indexes > 0);
339 return &parser->implementation->structural_indexes[n_structural_indexes - 1];
341simdjson_inline
const uint8_t *json_iterator::peek_last() const noexcept {
342 return token.peek(last_position());
345simdjson_inline
void json_iterator::ascend_to(
depth_t parent_depth)
noexcept {
346 SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
347 SIMDJSON_ASSUME(_depth == parent_depth + 1);
348 _depth = parent_depth;
351simdjson_inline
void json_iterator::descend_to(
depth_t child_depth)
noexcept {
352 SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
353 SIMDJSON_ASSUME(_depth == child_depth - 1);
354 _depth = child_depth;
357simdjson_inline
depth_t json_iterator::depth() const noexcept {
361simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept {
362 return _string_buf_loc;
365simdjson_warn_unused simdjson_inline
error_code json_iterator::report_error(
error_code _error,
const char *message)
noexcept {
367 logger::log_error(*
this, message);
372simdjson_inline token_position json_iterator::position() const noexcept {
373 return token.position();
376simdjson_inline simdjson_result<std::string_view> json_iterator::unescape(raw_json_string in,
bool allow_replacement)
noexcept {
377#if SIMDJSON_DEVELOPMENT_CHECKS
378 auto result = parser->unescape(in, _string_buf_loc, allow_replacement);
379#if !defined(SIMDJSON_VISUAL_STUDIO) && !defined(SIMDJSON_CLANG_VISUAL_STUDIO)
382 SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc));
386 return parser->unescape(in, _string_buf_loc, allow_replacement);
390simdjson_inline simdjson_result<std::string_view> json_iterator::unescape_wobbly(raw_json_string in)
noexcept {
391#if SIMDJSON_DEVELOPMENT_CHECKS
392 auto result = parser->unescape_wobbly(in, _string_buf_loc);
393#if !defined(SIMDJSON_VISUAL_STUDIO) && !defined(SIMDJSON_CLANG_VISUAL_STUDIO)
396 SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc));
400 return parser->unescape_wobbly(in, _string_buf_loc);
404simdjson_inline
void json_iterator::reenter_child(token_position position,
depth_t child_depth)
noexcept {
405 SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
406 SIMDJSON_ASSUME(_depth == child_depth - 1);
407#if SIMDJSON_DEVELOPMENT_CHECKS
408#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
409 SIMDJSON_ASSUME(
size_t(child_depth) < parser->max_depth());
410 SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
413 token.set_position(position);
414 _depth = child_depth;
417simdjson_warn_unused simdjson_inline
error_code json_iterator::consume_character(
char c)
noexcept {
419 return_current_and_advance();
425#if SIMDJSON_DEVELOPMENT_CHECKS
427simdjson_inline token_position json_iterator::start_position(
depth_t depth)
const noexcept {
428 SIMDJSON_ASSUME(
size_t(depth) < parser->max_depth());
429 return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
432simdjson_inline
void json_iterator::set_start_position(
depth_t depth, token_position position)
noexcept {
433 SIMDJSON_ASSUME(
size_t(depth) < parser->max_depth());
434 if(
size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
440simdjson_warn_unused simdjson_inline
error_code json_iterator::optional_error(
error_code _error,
const char *message)
noexcept {
442 logger::log_error(*
this, message);
447simdjson_warn_unused simdjson_inline
bool json_iterator::copy_to_buffer(
const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf,
size_t N)
noexcept {
450 if((N < max_len) || (N == 0)) {
return false; }
452 std::memcpy(tmpbuf, json, max_len);
454 std::memset(tmpbuf + max_len,
' ', N - max_len);
465simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &&value) noexcept
466 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>(value)) {}
467simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>::simdjson_result(
error_code error) noexcept
468 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>(error) {}
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.
const char * error_message(error_code error) noexcept
It is the convention throughout the code that the macro SIMDJSON_DEVELOPMENT_CHECKS determines whethe...
error_code
All possible errors returned by simdjson.
@ INCORRECT_TYPE
JSON element has a different type than user expected.
@ OUT_OF_BOUNDS
Attempted to access location outside of document.
@ TAPE_ERROR
Something went wrong, this is a generic error. Fatal/unrecoverable error.
@ NO_SUCH_FIELD
JSON field not found in object.
@ INCOMPLETE_ARRAY_OR_OBJECT
The document ends early. Fatal/unrecoverable error.
@ UNINITIALIZED
unknown error, or uninitialized document