1 #ifndef SIMDJSON_PARSEDJSON_ITERATOR_INL_H
2 #define SIMDJSON_PARSEDJSON_ITERATOR_INL_H
4 #include "simdjson/dom/base.h"
5 #include "simdjson/dom/parsedjson_iterator.h"
6 #include "simdjson/internal/jsonformatutils.h"
8 #include "simdjson/dom/parser-inl.h"
9 #include "simdjson/internal/tape_ref-inl.h"
16 #ifndef SIMDJSON_DISABLE_DEPRECATED_API
21 SIMDJSON_PUSH_DISABLE_WARNINGS
22 SIMDJSON_DISABLE_DEPRECATED_WARNING
25 simdjson_warn_unused
bool dom::parser::Iterator::is_ok()
const {
26 return location < tape_length;
30 size_t dom::parser::Iterator::get_tape_location()
const {
35 size_t dom::parser::Iterator::get_tape_length()
const {
41 size_t dom::parser::Iterator::get_depth()
const {
47 uint8_t dom::parser::Iterator::get_scope_type()
const {
48 return depth_index[depth].scope_type;
51 bool dom::parser::Iterator::move_forward() {
52 if (location + 1 >= tape_length) {
56 if ((current_type ==
'[') || (current_type ==
'{')) {
59 assert(depth < max_depth);
60 depth_index[depth].start_of_scope = location;
61 depth_index[depth].scope_type = current_type;
62 }
else if ((current_type ==
']') || (current_type ==
'}')) {
65 }
else if (is_number()) {
71 current_val = doc.tape[location];
72 current_type = uint8_t(current_val >> 56);
76 void dom::parser::Iterator::move_to_value() {
79 current_val = doc.tape[location];
80 current_type = uint8_t(current_val >> 56);
83 bool dom::parser::Iterator::move_to_key(
const char *key) {
86 const bool right_key = (strcmp(get_string(), key) == 0);
97 bool dom::parser::Iterator::move_to_key_insensitive(
101 const bool right_key = (simdjson_strcasecmp(get_string(), key) == 0);
112 bool dom::parser::Iterator::move_to_key(
const char *key,
116 bool right_key = ((get_string_length() == length) &&
117 (memcmp(get_string(), key, length) == 0));
128 bool dom::parser::Iterator::move_to_index(uint32_t index) {
131 for (; i < index; i++) {
144 bool dom::parser::Iterator::prev() {
145 size_t target_location = location;
147 size_t npos = location;
148 if (target_location == npos) {
155 if ((current_type ==
'[') || (current_type ==
'{')) {
157 npos = uint32_t(current_val);
159 npos = npos + ((current_type ==
'd' || current_type ==
'l') ? 2 : 1);
161 }
while (npos < target_location);
163 current_val = doc.tape[location];
164 current_type = uint8_t(current_val >> 56);
168 bool dom::parser::Iterator::up() {
176 current_val = doc.tape[location];
177 current_type = uint8_t(current_val >> 56);
181 bool dom::parser::Iterator::down() {
182 if (location + 1 >= tape_length) {
185 if ((current_type ==
'[') || (current_type ==
'{')) {
186 size_t npos = uint32_t(current_val);
187 if (npos == location + 2) {
191 assert(depth < max_depth);
192 location = location + 1;
193 depth_index[depth].start_of_scope = location;
194 depth_index[depth].scope_type = current_type;
195 current_val = doc.tape[location];
196 current_type = uint8_t(current_val >> 56);
202 void dom::parser::Iterator::to_start_scope() {
203 location = depth_index[depth].start_of_scope;
204 current_val = doc.tape[location];
205 current_type = uint8_t(current_val >> 56);
208 inline void dom::parser::Iterator::rewind() {
214 bool dom::parser::Iterator::next() {
216 if ((current_type ==
'[') || (current_type ==
'{')) {
218 npos = uint32_t(current_val);
220 npos = location + (is_number() ? 2 : 1);
222 uint64_t next_val = doc.tape[npos];
223 uint8_t next_type = uint8_t(next_val >> 56);
224 if ((next_type ==
']') || (next_type ==
'}')) {
228 current_val = next_val;
229 current_type = next_type;
232 dom::parser::Iterator::Iterator(
const dom::parser &pj) noexcept(
false)
235 #if SIMDJSON_EXCEPTIONS
236 if (!pj.valid) {
throw simdjson_error(pj.error); }
238 if (!pj.valid) {
return; }
241 max_depth = pj.max_depth();
242 depth_index =
new scopeindex_t[max_depth + 1];
243 depth_index[0].start_of_scope = location;
244 current_val = doc.tape[location++];
245 current_type = uint8_t(current_val >> 56);
246 depth_index[0].scope_type = current_type;
247 tape_length = size_t(current_val & internal::JSON_VALUE_MASK);
248 if (location < tape_length) {
251 current_val = doc.tape[location];
252 current_type = uint8_t(current_val >> 56);
254 assert(depth < max_depth);
255 depth_index[depth].start_of_scope = location;
256 depth_index[depth].scope_type = current_type;
259 dom::parser::Iterator::Iterator(
260 const dom::parser::Iterator &o) noexcept
264 location(o.location),
265 tape_length(o.tape_length),
266 current_type(o.current_type),
267 current_val(o.current_val)
269 depth_index =
new scopeindex_t[max_depth+1];
270 std::memcpy(depth_index, o.depth_index, (depth + 1) *
sizeof(depth_index[0]));
273 dom::parser::Iterator::~Iterator() noexcept {
274 if (depth_index) {
delete[] depth_index; }
277 bool dom::parser::Iterator::print(std::ostream &os,
bool escape_strings)
const {
281 switch (current_type) {
284 if (escape_strings) {
285 os << internal::escape_json_string(std::string_view(get_string(), get_string_length()));
289 std::copy(get_string(), get_string() + get_string_length(), std::ostream_iterator<char>(os));
297 os << get_unsigned_integer();
315 os << char(current_type);
323 bool dom::parser::Iterator::move_to(
const char *pointer,
325 char *new_pointer =
nullptr;
326 if (pointer[0] ==
'#') {
328 new_pointer =
new char[length];
329 uint32_t new_length = 0;
330 for (uint32_t i = 1; i < length; i++) {
331 if (pointer[i] ==
'%' && pointer[i + 1] ==
'x') {
336 std::stoi(std::string(&pointer[i + 2], 2),
nullptr, 16);
337 if (fragment ==
'\\' || fragment ==
'"' || (fragment <= 0x1F)) {
339 new_pointer[new_length] =
'\\';
342 new_pointer[new_length] = char(fragment);
345 }
catch (std::invalid_argument &) {
346 delete[] new_pointer;
351 new_pointer[new_length] = pointer[i];
356 pointer = new_pointer;
360 size_t depth_s = depth;
361 size_t location_s = location;
362 uint8_t current_type_s = current_type;
363 uint64_t current_val_s = current_val;
367 bool found = relative_move_to(pointer, length);
368 delete[] new_pointer;
374 location = location_s;
375 current_type = current_type_s;
376 current_val = current_val_s;
382 inline bool dom::parser::Iterator::move_to(
const std::string &pointer) {
383 return move_to(pointer.c_str(), uint32_t(pointer.length()));
386 inline int64_t dom::parser::Iterator::get_integer()
const {
387 if (location + 1 >= tape_length) {
390 return static_cast<int64_t
>(doc.tape[location + 1]);
393 inline uint64_t dom::parser::Iterator::get_unsigned_integer()
const {
394 if (location + 1 >= tape_length) {
397 return doc.tape[location + 1];
400 inline const char * dom::parser::Iterator::get_string()
const {
401 return reinterpret_cast<const char *
>(
402 doc.string_buf.get() + (current_val & internal::JSON_VALUE_MASK) +
sizeof(uint32_t));
405 inline uint32_t dom::parser::Iterator::get_string_length()
const {
408 reinterpret_cast<const char *
>(doc.string_buf.get() +
409 (current_val & internal::JSON_VALUE_MASK)),
414 inline double dom::parser::Iterator::get_double()
const {
415 if (location + 1 >= tape_length) {
416 return std::numeric_limits<double>::quiet_NaN();
420 std::memcpy(&answer, &doc.tape[location + 1],
sizeof(answer));
424 bool dom::parser::Iterator::relative_move_to(
const char *pointer,
431 if (pointer[0] !=
'/') {
437 std::string key_or_index;
441 if (is_array() && pointer[1] ==
'-') {
453 for (; offset < length; offset++) {
454 if (pointer[offset] ==
'/') {
458 if (is_array() && (pointer[offset] <
'0' || pointer[offset] >
'9')) {
463 if (pointer[offset] ==
'~') {
465 if (pointer[offset + 1] ==
'1') {
471 if (pointer[offset + 1] ==
'0') {
477 if (pointer[offset] ==
'\\') {
478 if (pointer[offset + 1] ==
'\\' || pointer[offset + 1] ==
'"' ||
479 (pointer[offset + 1] <= 0x1F)) {
480 key_or_index += pointer[offset + 1];
486 if (pointer[offset] ==
'\"') {
492 key_or_index += pointer[offset];
497 if (move_to_key(key_or_index.c_str(), uint32_t(key_or_index.length()))) {
498 found = relative_move_to(pointer + offset, length - offset);
500 }
else if (is_array()) {
501 if (key_or_index ==
"-") {
507 if ((current_type ==
'[') || (current_type ==
'{')) {
509 npos = uint32_t(current_val);
512 location + ((current_type ==
'd' || current_type ==
'l') ? 2 : 1);
515 current_val = doc.tape[npos];
516 current_type = uint8_t(current_val >> 56);
521 if (key_or_index[0] ==
'0' && key_or_index.length() > 1) {
525 if (key_or_index.length() == 0) {
529 uint32_t index = std::stoi(key_or_index);
530 if (move_to_index(index)) {
531 found = relative_move_to(pointer + offset, length - offset);
539 SIMDJSON_POP_DISABLE_WARNINGS
The top level simdjson namespace, containing everything the library provides.