1 #ifndef SIMDJSON_INLINE_PARSEDJSON_ITERATOR_H
2 #define SIMDJSON_INLINE_PARSEDJSON_ITERATOR_H
4 #include "simdjson/dom/parsedjson_iterator.h"
5 #include "simdjson/portability.h"
8 #ifndef SIMDJSON_DISABLE_DEPRECATED_API
13 SIMDJSON_PUSH_DISABLE_WARNINGS
14 SIMDJSON_DISABLE_DEPRECATED_WARNING
17 simdjson_warn_unused
bool dom::parser::Iterator::is_ok()
const {
18 return location < tape_length;
22 size_t dom::parser::Iterator::get_tape_location()
const {
27 size_t dom::parser::Iterator::get_tape_length()
const {
33 size_t dom::parser::Iterator::get_depth()
const {
39 uint8_t dom::parser::Iterator::get_scope_type()
const {
40 return depth_index[depth].scope_type;
43 bool dom::parser::Iterator::move_forward() {
44 if (location + 1 >= tape_length) {
48 if ((current_type ==
'[') || (current_type ==
'{')) {
51 assert(depth < max_depth);
52 depth_index[depth].start_of_scope = location;
53 depth_index[depth].scope_type = current_type;
54 }
else if ((current_type ==
']') || (current_type ==
'}')) {
57 }
else if (is_number()) {
63 current_val = doc.tape[location];
64 current_type = uint8_t(current_val >> 56);
68 void dom::parser::Iterator::move_to_value() {
71 current_val = doc.tape[location];
72 current_type = uint8_t(current_val >> 56);
75 bool dom::parser::Iterator::move_to_key(
const char *key) {
78 const bool right_key = (strcmp(get_string(), key) == 0);
89 bool dom::parser::Iterator::move_to_key_insensitive(
93 const bool right_key = (simdjson_strcasecmp(get_string(), key) == 0);
104 bool dom::parser::Iterator::move_to_key(
const char *key,
108 bool right_key = ((get_string_length() == length) &&
109 (memcmp(get_string(), key, length) == 0));
120 bool dom::parser::Iterator::move_to_index(uint32_t index) {
123 for (; i < index; i++) {
136 bool dom::parser::Iterator::prev() {
137 size_t target_location = location;
139 size_t npos = location;
140 if (target_location == npos) {
147 if ((current_type ==
'[') || (current_type ==
'{')) {
149 npos = uint32_t(current_val);
151 npos = npos + ((current_type ==
'd' || current_type ==
'l') ? 2 : 1);
153 }
while (npos < target_location);
155 current_val = doc.tape[location];
156 current_type = uint8_t(current_val >> 56);
160 bool dom::parser::Iterator::up() {
168 current_val = doc.tape[location];
169 current_type = uint8_t(current_val >> 56);
173 bool dom::parser::Iterator::down() {
174 if (location + 1 >= tape_length) {
177 if ((current_type ==
'[') || (current_type ==
'{')) {
178 size_t npos = uint32_t(current_val);
179 if (npos == location + 2) {
183 assert(depth < max_depth);
184 location = location + 1;
185 depth_index[depth].start_of_scope = location;
186 depth_index[depth].scope_type = current_type;
187 current_val = doc.tape[location];
188 current_type = uint8_t(current_val >> 56);
194 void dom::parser::Iterator::to_start_scope() {
195 location = depth_index[depth].start_of_scope;
196 current_val = doc.tape[location];
197 current_type = uint8_t(current_val >> 56);
200 bool dom::parser::Iterator::next() {
202 if ((current_type ==
'[') || (current_type ==
'{')) {
204 npos = uint32_t(current_val);
206 npos = location + (is_number() ? 2 : 1);
208 uint64_t next_val = doc.tape[npos];
209 uint8_t next_type = uint8_t(next_val >> 56);
210 if ((next_type ==
']') || (next_type ==
'}')) {
214 current_val = next_val;
215 current_type = next_type;
218 dom::parser::Iterator::Iterator(
const dom::parser &pj) noexcept(
false)
221 #if SIMDJSON_EXCEPTIONS
222 if (!pj.valid) {
throw simdjson_error(pj.error); }
224 if (!pj.valid) {
return; }
227 max_depth = pj.max_depth();
228 depth_index =
new scopeindex_t[max_depth + 1];
229 depth_index[0].start_of_scope = location;
230 current_val = doc.tape[location++];
231 current_type = uint8_t(current_val >> 56);
232 depth_index[0].scope_type = current_type;
233 tape_length = size_t(current_val & internal::JSON_VALUE_MASK);
234 if (location < tape_length) {
237 current_val = doc.tape[location];
238 current_type = uint8_t(current_val >> 56);
240 assert(depth < max_depth);
241 depth_index[depth].start_of_scope = location;
242 depth_index[depth].scope_type = current_type;
245 dom::parser::Iterator::Iterator(
246 const dom::parser::Iterator &o) noexcept
250 location(o.location),
251 tape_length(o.tape_length),
252 current_type(o.current_type),
253 current_val(o.current_val)
255 depth_index =
new scopeindex_t[max_depth+1];
256 std::memcpy(depth_index, o.depth_index, (depth + 1) *
sizeof(depth_index[0]));
259 dom::parser::Iterator::~Iterator() noexcept {
260 if (depth_index) {
delete[] depth_index; }
263 bool dom::parser::Iterator::print(std::ostream &os,
bool escape_strings)
const {
267 switch (current_type) {
270 if (escape_strings) {
271 os << internal::escape_json_string(std::string_view(get_string(), get_string_length()));
275 std::copy(get_string(), get_string() + get_string_length(), std::ostream_iterator<char>(os));
283 os << get_unsigned_integer();
301 os << char(current_type);
309 bool dom::parser::Iterator::move_to(
const char *pointer,
311 char *new_pointer =
nullptr;
312 if (pointer[0] ==
'#') {
314 new_pointer =
new char[length];
315 uint32_t new_length = 0;
316 for (uint32_t i = 1; i < length; i++) {
317 if (pointer[i] ==
'%' && pointer[i + 1] ==
'x') {
322 std::stoi(std::string(&pointer[i + 2], 2),
nullptr, 16);
323 if (fragment ==
'\\' || fragment ==
'"' || (fragment <= 0x1F)) {
325 new_pointer[new_length] =
'\\';
328 new_pointer[new_length] = char(fragment);
331 }
catch (std::invalid_argument &) {
332 delete[] new_pointer;
337 new_pointer[new_length] = pointer[i];
342 pointer = new_pointer;
346 size_t depth_s = depth;
347 size_t location_s = location;
348 uint8_t current_type_s = current_type;
349 uint64_t current_val_s = current_val;
353 bool found = relative_move_to(pointer, length);
354 delete[] new_pointer;
360 location = location_s;
361 current_type = current_type_s;
362 current_val = current_val_s;
368 bool dom::parser::Iterator::relative_move_to(
const char *pointer,
375 if (pointer[0] !=
'/') {
381 std::string key_or_index;
385 if (is_array() && pointer[1] ==
'-') {
397 for (; offset < length; offset++) {
398 if (pointer[offset] ==
'/') {
402 if (is_array() && (pointer[offset] <
'0' || pointer[offset] >
'9')) {
407 if (pointer[offset] ==
'~') {
409 if (pointer[offset + 1] ==
'1') {
415 if (pointer[offset + 1] ==
'0') {
421 if (pointer[offset] ==
'\\') {
422 if (pointer[offset + 1] ==
'\\' || pointer[offset + 1] ==
'"' ||
423 (pointer[offset + 1] <= 0x1F)) {
424 key_or_index += pointer[offset + 1];
430 if (pointer[offset] ==
'\"') {
436 key_or_index += pointer[offset];
441 if (move_to_key(key_or_index.c_str(), uint32_t(key_or_index.length()))) {
442 found = relative_move_to(pointer + offset, length - offset);
444 }
else if (is_array()) {
445 if (key_or_index ==
"-") {
451 if ((current_type ==
'[') || (current_type ==
'{')) {
453 npos = uint32_t(current_val);
456 location + ((current_type ==
'd' || current_type ==
'l') ? 2 : 1);
459 current_val = doc.tape[npos];
460 current_type = uint8_t(current_val >> 56);
465 if (key_or_index[0] ==
'0' && key_or_index.length() > 1) {
469 if (key_or_index.length() == 0) {
473 uint32_t index = std::stoi(key_or_index);
474 if (move_to_index(index)) {
475 found = relative_move_to(pointer + offset, length - offset);
483 SIMDJSON_POP_DISABLE_WARNINGS
We want to support argument-dependent lookup (ADL).