|
4 | 4 | // "simdjson/stage2.h" (this simplifies amalgation) |
5 | 5 |
|
6 | 6 | namespace stage2 { |
| 7 | +namespace { // Make everything here private |
7 | 8 |
|
8 | 9 | #ifdef SIMDJSON_USE_COMPUTED_GOTO |
9 | 10 | #define INIT_ADDRESSES() { &&array_begin, &&array_continue, &&error, &&finish, &&object_begin, &&object_continue } |
@@ -81,10 +82,6 @@ struct structural_parser { |
81 | 82 | parser{_parser}, |
82 | 83 | depth{0} { |
83 | 84 | } |
84 | | - // For streaming: pick up after the previous document |
85 | | - really_inline structural_parser(dom_parser_implementation &_parser) |
86 | | - : structural_parser(_parser, _parser.next_structural_index) { |
87 | | - } |
88 | 85 |
|
89 | 86 | WARN_UNUSED really_inline bool start_scope(ret_address_t continue_state) { |
90 | 87 | parser.containing_scope[depth].tape_index = parser.current_loc; |
@@ -272,24 +269,6 @@ struct structural_parser { |
272 | 269 | } |
273 | 270 | } |
274 | 271 |
|
275 | | - // override to add streaming |
276 | | - WARN_UNUSED really_inline error_code finish() { |
277 | | - if ( structurals.past_end(parser.n_structural_indexes) ) { |
278 | | - log_error("IMPOSSIBLE: past the end of the JSON!"); |
279 | | - return parser.error = TAPE_ERROR; |
280 | | - } |
281 | | - end_document(); |
282 | | - if (depth != 0) { |
283 | | - log_error("Unclosed objects or arrays!"); |
284 | | - return parser.error = TAPE_ERROR; |
285 | | - } |
286 | | - if (parser.containing_scope[depth].tape_index != 0) { |
287 | | - log_error("IMPOSSIBLE: root scope tape index did not start at 0!"); |
288 | | - return parser.error = TAPE_ERROR; |
289 | | - } |
290 | | - return SUCCESS; |
291 | | - } |
292 | | - |
293 | 272 | template<bool STREAMING> |
294 | 273 | WARN_UNUSED really_inline error_code finish() { |
295 | 274 | // Check if we're at (or past) the end |
@@ -426,11 +405,12 @@ struct structural_parser { |
426 | 405 | #undef FAIL_IF |
427 | 406 | #define FAIL_IF(EXPR) { if (EXPR) { goto error; } } |
428 | 407 |
|
| 408 | +template<bool STREAMING> |
429 | 409 | WARN_UNUSED static error_code parse_structurals(dom_parser_implementation &dom_parser, dom::document &doc) noexcept { |
430 | 410 | dom_parser.doc = &doc; |
431 | 411 | static constexpr stage2::unified_machine_addresses addresses = INIT_ADDRESSES(); |
432 | | - stage2::structural_parser parser(dom_parser, 0); |
433 | | - error_code result = parser.start<false>(dom_parser.len, addresses.finish); |
| 412 | + stage2::structural_parser parser(dom_parser, STREAMING ? dom_parser.next_structural_index : 0); |
| 413 | + error_code result = parser.start<STREAMING>(dom_parser.len, addresses.finish); |
434 | 414 | if (result) { return result; } |
435 | 415 |
|
436 | 416 | // |
@@ -545,140 +525,27 @@ WARN_UNUSED static error_code parse_structurals(dom_parser_implementation &dom_p |
545 | 525 | } |
546 | 526 |
|
547 | 527 | finish: |
548 | | - return parser.finish<false>(); |
| 528 | + return parser.finish<STREAMING>(); |
549 | 529 |
|
550 | 530 | error: |
551 | 531 | return parser.error(); |
552 | 532 | } |
553 | 533 |
|
| 534 | +} // namespace {} |
554 | 535 | } // namespace stage2 |
555 | 536 |
|
556 | 537 | /************ |
557 | 538 | * The JSON is parsed to a tape, see the accompanying tape.md file |
558 | 539 | * for documentation. |
559 | 540 | ***********/ |
560 | 541 | WARN_UNUSED error_code dom_parser_implementation::stage2(dom::document &_doc) noexcept { |
561 | | - return stage2::parse_structurals(*this, _doc); |
| 542 | + return stage2::parse_structurals<false>(*this, _doc); |
562 | 543 | } |
563 | 544 |
|
564 | 545 | /************ |
565 | 546 | * The JSON is parsed to a tape, see the accompanying tape.md file |
566 | 547 | * for documentation. |
567 | 548 | ***********/ |
568 | 549 | WARN_UNUSED error_code dom_parser_implementation::stage2_next(dom::document &_doc) noexcept { |
569 | | - this->doc = &_doc; |
570 | | - static constexpr stage2::unified_machine_addresses addresses = INIT_ADDRESSES(); |
571 | | - stage2::structural_parser parser(*this, next_structural_index); |
572 | | - error_code result = parser.start<true>(len, addresses.finish); |
573 | | - if (result) { return result; } |
574 | | - // |
575 | | - // Read first value |
576 | | - // |
577 | | - switch (parser.structurals.current_char()) { |
578 | | - case '{': |
579 | | - FAIL_IF( parser.start_object(addresses.finish) ); |
580 | | - goto object_begin; |
581 | | - case '[': |
582 | | - FAIL_IF( parser.start_array(addresses.finish) ); |
583 | | - goto array_begin; |
584 | | - case '"': |
585 | | - FAIL_IF( parser.parse_string() ); |
586 | | - goto finish; |
587 | | - case 't': case 'f': case 'n': |
588 | | - FAIL_IF( parser.parse_single_atom() ); |
589 | | - goto finish; |
590 | | - case '0': case '1': case '2': case '3': case '4': |
591 | | - case '5': case '6': case '7': case '8': case '9': |
592 | | - FAIL_IF( |
593 | | - parser.structurals.with_space_terminated_copy([&](const uint8_t *copy, size_t idx) { |
594 | | - return parser.parse_number(©[idx], false); |
595 | | - }) |
596 | | - ); |
597 | | - goto finish; |
598 | | - case '-': |
599 | | - FAIL_IF( |
600 | | - parser.structurals.with_space_terminated_copy([&](const uint8_t *copy, size_t idx) { |
601 | | - return parser.parse_number(©[idx], true); |
602 | | - }) |
603 | | - ); |
604 | | - goto finish; |
605 | | - default: |
606 | | - parser.log_error("Document starts with a non-value character"); |
607 | | - goto error; |
608 | | - } |
609 | | - |
610 | | -// |
611 | | -// Object parser parsers |
612 | | -// |
613 | | -object_begin: |
614 | | - switch (parser.advance_char()) { |
615 | | - case '"': { |
616 | | - FAIL_IF( parser.parse_string(true) ); |
617 | | - goto object_key_parser; |
618 | | - } |
619 | | - case '}': |
620 | | - parser.end_object(); |
621 | | - goto scope_end; |
622 | | - default: |
623 | | - parser.log_error("Object does not start with a key"); |
624 | | - goto error; |
625 | | - } |
626 | | - |
627 | | -object_key_parser: |
628 | | - if (parser.advance_char() != ':' ) { parser.log_error("Missing colon after key in object"); goto error; } |
629 | | - parser.increment_count(); |
630 | | - parser.advance_char(); |
631 | | - GOTO( parser.parse_value(addresses, addresses.object_continue) ); |
632 | | - |
633 | | -object_continue: |
634 | | - switch (parser.advance_char()) { |
635 | | - case ',': |
636 | | - if (parser.advance_char() != '"' ) { parser.log_error("Key string missing at beginning of field in object"); goto error; } |
637 | | - FAIL_IF( parser.parse_string(true) ); |
638 | | - goto object_key_parser; |
639 | | - case '}': |
640 | | - parser.end_object(); |
641 | | - goto scope_end; |
642 | | - default: |
643 | | - parser.log_error("No comma between object fields"); |
644 | | - goto error; |
645 | | - } |
646 | | - |
647 | | -scope_end: |
648 | | - CONTINUE( parser.parser.ret_address[parser.depth] ); |
649 | | - |
650 | | -// |
651 | | -// Array parser parsers |
652 | | -// |
653 | | -array_begin: |
654 | | - if (parser.advance_char() == ']') { |
655 | | - parser.end_array(); |
656 | | - goto scope_end; |
657 | | - } |
658 | | - parser.increment_count(); |
659 | | - |
660 | | -main_array_switch: |
661 | | - /* we call update char on all paths in, so we can peek at parser.c on the |
662 | | - * on paths that can accept a close square brace (post-, and at start) */ |
663 | | - GOTO( parser.parse_value(addresses, addresses.array_continue) ); |
664 | | - |
665 | | -array_continue: |
666 | | - switch (parser.advance_char()) { |
667 | | - case ',': |
668 | | - parser.increment_count(); |
669 | | - parser.advance_char(); |
670 | | - goto main_array_switch; |
671 | | - case ']': |
672 | | - parser.end_array(); |
673 | | - goto scope_end; |
674 | | - default: |
675 | | - parser.log_error("Missing comma between array values"); |
676 | | - goto error; |
677 | | - } |
678 | | - |
679 | | -finish: |
680 | | - return parser.finish<true>(); |
681 | | - |
682 | | -error: |
683 | | - return parser.error(); |
| 550 | + return stage2::parse_structurals<true>(*this, _doc); |
684 | 551 | } |
0 commit comments