@@ -1805,9 +1805,10 @@ ALWAYS_INLINE(static) bool json_parse_any(JSON_ParserState *state, JSON_ParserCo
18051805 state -> current_nesting -- ;
18061806 state -> in_array -- ;
18071807
1808- json_frame_stack_pop (state -> frames );
18091808 json_push_value (state , config , json_decode_array (state , config , count ));
1809+ json_frame_stack_pop (state -> frames );
18101810 frame = json_frame_stack_peek (state -> frames );
1811+
18111812 json_value_completed (frame );
18121813
18131814 switch (frame -> phase ) {
@@ -2315,28 +2316,37 @@ static VALUE json_parse_any_resumable_safe(VALUE _args)
23152316 return (VALUE )json_parse_any (args -> state , args -> config , true);
23162317}
23172318
2319+ static JSON_ResumableParser * ResumableParser_acquire (VALUE self )
2320+ {
2321+ JSON_ResumableParser * parser = cResumableParser_get (self );
2322+ // self may have moved, so we need to update all pointers
2323+ // Investigate: We might be better off keeping JSON_ParserState on the stack
2324+ // and only persist what we need.
2325+ parser -> state .value_stack_handle = & self ;
2326+ parser -> state .frame_stack_handle = & self ;
2327+ parser -> state .value_stack = & parser -> value_stack ;
2328+ parser -> state .frames = & parser -> frames ;
2329+
2330+ return parser ;
2331+ }
2332+
23182333// TODO: doc
23192334static VALUE cResumableParser_parse (VALUE self )
23202335{
2321- JSON_ResumableParser * parser = cResumableParser_get (self );
2336+ JSON_ResumableParser * parser = ResumableParser_acquire (self );
23222337 if (!parser -> buffer ) {
23232338 return Qfalse ;
23242339 }
23252340 VALUE Vsource = parser -> buffer ; // Prevent compaction
23262341
23272342 // TODO: prevent reentrancy
23282343
2329- // self may have moved, so we need to update all pointers
2330- // We might be better off keeping JSON_ParserState on the stack
2331- // and only persist what we need.
2332- parser -> state .value_stack_handle = & self ;
2333- parser -> state .frame_stack_handle = & self ;
2334- parser -> state .value_stack = & parser -> value_stack ;
2335- parser -> state .frames = & parser -> frames ;
2336-
23372344 json_frame * frame = json_frame_stack_peek (& parser -> frames );
23382345
23392346 if (frame -> phase == JSON_PHASE_DONE ) {
2347+ JSON_ASSERT (parser -> value_stack .head == 1 );
2348+ JSON_ASSERT (parser -> frames .head == 1 );
2349+
23402350 frame -> phase = JSON_PHASE_VALUE ;
23412351 rvalue_stack_pop (parser -> state .value_stack , 1 );
23422352 }
@@ -2362,7 +2372,7 @@ static VALUE cResumableParser_parse(VALUE self)
23622372// TODO: doc
23632373static VALUE cResumableParser_value (VALUE self )
23642374{
2365- JSON_ResumableParser * parser = cResumableParser_get (self );
2375+ JSON_ResumableParser * parser = ResumableParser_acquire (self );
23662376 json_frame * frame = json_frame_stack_peek (& parser -> frames );
23672377
23682378 if (frame -> phase == JSON_PHASE_DONE ) {
@@ -2372,6 +2382,73 @@ static VALUE cResumableParser_value(VALUE self)
23722382 }
23732383}
23742384
2385+ // TODO: doc
2386+ static VALUE cResumableParser_partial_value (VALUE self )
2387+ {
2388+ JSON_ResumableParser * original_parser = ResumableParser_acquire (self );
2389+ JSON_ResumableParser parser = * original_parser ;
2390+
2391+ if (parser .value_stack .head == 0 ) {
2392+ return Qnil ;
2393+ }
2394+
2395+ json_frame * frame = json_frame_stack_peek (parser .state .frames );
2396+ long missing_object_value = 0 ;
2397+ if (frame -> type == JSON_FRAME_OBJECT && (frame -> phase == JSON_PHASE_VALUE || frame -> phase == JSON_PHASE_OBJECT_COLON )) {
2398+ missing_object_value = 1 ;
2399+ }
2400+
2401+ // Copy the value stack as we need to mutate it.
2402+ long capa = parser .value_stack .head ;
2403+ parser .value_stack .capa = (capa + missing_object_value );
2404+ VALUE tmpbuf , * value_stack_buffer = ALLOCV_N (VALUE , tmpbuf , capa + missing_object_value );
2405+ MEMCPY (value_stack_buffer , parser .value_stack .ptr , VALUE , parser .value_stack .capa );
2406+ parser .value_stack .ptr = value_stack_buffer ;
2407+
2408+ JSON_ParserState * state = & parser .state ;
2409+ JSON_ParserConfig * config = & parser .config ;
2410+
2411+ if (missing_object_value ) {
2412+ rvalue_stack_push (state -> value_stack , Qnil , NULL , & state -> value_stack );
2413+ }
2414+
2415+ VALUE partial_result = Qundef ;
2416+
2417+ while (UNDEF_P (partial_result )) {
2418+ frame = json_frame_stack_peek (state -> frames );
2419+
2420+ switch (frame -> type ) {
2421+ case JSON_FRAME_ROOT : {
2422+ partial_result = * rvalue_stack_peek (state -> value_stack , 1 );
2423+ break ;
2424+ }
2425+
2426+ case JSON_FRAME_ARRAY : {
2427+ long count = json_frame_entry_count (frame , state -> value_stack );
2428+ json_push_value (state , config , json_decode_array (state , config , count ));
2429+ json_frame_stack_pop (state -> frames );
2430+
2431+ break ;
2432+ }
2433+
2434+ case JSON_FRAME_OBJECT : {
2435+ long count = json_frame_entry_count (frame , state -> value_stack );
2436+ json_push_value (state , config , json_decode_object (state , config , count ));
2437+ json_frame_stack_pop (state -> frames );
2438+ break ;
2439+ }
2440+
2441+ default : {
2442+ JSON_UNREACHABLE_RETURN (Qundef );
2443+ break ;
2444+ }
2445+ }
2446+ }
2447+
2448+ ALLOCV_END (tmpbuf );
2449+ return partial_result ;
2450+ }
2451+
23752452// TODO: doc
23762453static VALUE cResumableParser_rest (VALUE self )
23772454{
@@ -2419,6 +2496,7 @@ void Init_parser(void)
24192496 rb_define_method (cResumableParser , "<<" , cResumableParser_feed , 1 );
24202497 rb_define_method (cResumableParser , "parse" , cResumableParser_parse , 0 );
24212498 rb_define_method (cResumableParser , "value" , cResumableParser_value , 0 );
2499+ rb_define_method (cResumableParser , "partial_value" , cResumableParser_partial_value , 0 );
24222500 rb_define_method (cResumableParser , "rest" , cResumableParser_rest , 0 );
24232501
24242502 rb_global_variable (& CNaN );
0 commit comments