5
5
6
6
namespace stage2 {
7
7
8
+ namespace {
9
+
8
10
struct number_writer {
9
11
parser &doc_parser;
10
12
@@ -439,6 +441,43 @@ struct structural_parser {
439
441
}
440
442
};
441
443
444
+ struct streaming_structural_parser : structural_parser {
445
+ really_inline streaming_structural_parser (size_t len, parser &_doc_parser)
446
+ : structural_parser(len, _doc_parser) {}
447
+
448
+ // override to add streaming
449
+ WARN_UNUSED really_inline error_code start (UNUSED size_t len) {
450
+ log_start ();
451
+ init (); // sets is_valid to false
452
+ // Capacity ain't no thang for streaming, so we don't check it.
453
+ // Advance to the first character as soon as possible
454
+ advance_char ();
455
+ // Push the root scope (there is always at least one scope)
456
+ if (start_document ()) {
457
+ return on_error (DEPTH_ERROR);
458
+ }
459
+ return SUCCESS;
460
+ }
461
+
462
+ // override to add streaming
463
+ WARN_UNUSED really_inline error_code finish () {
464
+ if ( structurals.past_end (doc_parser ().n_structural_indexes ) ) {
465
+ log_error (" IMPOSSIBLE: past the end of the JSON!" );
466
+ return on_error (TAPE_ERROR);
467
+ }
468
+ end_document (0 , 1 );
469
+ if (depth != 0 ) {
470
+ log_error (" Unclosed objects or arrays!" );
471
+ return on_error (TAPE_ERROR);
472
+ }
473
+ bool finished = structurals.at_end (doc_parser ().n_structural_indexes );
474
+ if (!finished) { log_value (" (and has more)" ); }
475
+ return on_success (finished ? SUCCESS : SUCCESS_AND_HAS_MORE);
476
+ }
477
+ }; // struct streaming_structural_parser
478
+
479
+ } // namespace {}
480
+
442
481
} // namespace stage2
443
482
444
483
/* ***********
@@ -458,6 +497,24 @@ WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, pa
458
497
return parser.finish ();
459
498
}
460
499
500
+ /* ***********
501
+ * The JSON is parsed to a tape, see the accompanying tape.md file
502
+ * for documentation.
503
+ ***********/
504
+ WARN_UNUSED error_code implementation::stage2 (const uint8_t *buf, size_t len, parser &doc_parser, size_t &next_json) const noexcept {
505
+ doc_parser.parsing_buf = buf;
506
+ doc_parser.next_structural = next_json;
507
+ stage2::streaming_structural_parser parser (len, doc_parser);
508
+ error_code result = parser.start (len);
509
+ if (result) { return result; }
510
+
511
+ if (parser.parse_root_value ()) {
512
+ return parser.error ();
513
+ }
514
+ next_json = doc_parser.next_structural ;
515
+ return parser.finish ();
516
+ }
517
+
461
518
WARN_UNUSED error_code implementation::parse (const uint8_t *buf, size_t len, parser &doc_parser) const noexcept {
462
519
error_code code = stage1 (buf, len, doc_parser, false );
463
520
if (!code) {
0 commit comments