11#include "ruby.h"
2- #include "../fbuffer/fbuffer.h"
2+ #include "ruby/encoding.h"
3+
4+ /* shims */
5+ /* This is the fallback definition from Ruby 3.4 */
6+
7+ #ifndef RBIMPL_STDBOOL_H
8+ #if defined(__cplusplus )
9+ # if defined(HAVE_STDBOOL_H ) && (__cplusplus >= 201103L )
10+ # include <cstdbool>
11+ # endif
12+ #elif defined(HAVE_STDBOOL_H )
13+ # include <stdbool.h>
14+ #elif !defined(HAVE__BOOL )
15+ typedef unsigned char _Bool ;
16+ # define bool _Bool
17+ # define true ((_Bool)+1)
18+ # define false ((_Bool)+0)
19+ # define __bool_true_false_are_defined
20+ #endif
21+ #endif
22+
23+ #ifndef RB_UNLIKELY
24+ #define RB_UNLIKELY (expr ) expr
25+ #endif
26+
27+ #ifndef RB_LIKELY
28+ #define RB_LIKELY (expr ) expr
29+ #endif
330
431static VALUE mJSON , eNestingError , Encoding_UTF_8 ;
532static VALUE CNaN , CInfinity , CMinusInfinity ;
@@ -401,7 +428,6 @@ typedef struct JSON_ParserStateStruct {
401428 VALUE stack_handle ;
402429 const char * cursor ;
403430 const char * end ;
404- FBuffer fbuffer ;
405431 rvalue_stack * stack ;
406432 rvalue_cache name_cache ;
407433 int in_array ;
@@ -690,26 +716,44 @@ static inline VALUE fast_decode_integer(const char *p, const char *pe)
690716 return LL2NUM (memo );
691717}
692718
693- static VALUE
719+ static VALUE json_decode_large_integer (const char * start , long len )
720+ {
721+ VALUE buffer_v ;
722+ char * buffer = RB_ALLOCV_N (char , buffer_v , len + 1 );
723+ MEMCPY (buffer , start , char , len );
724+ buffer [len ] = '\0' ;
725+ VALUE number = rb_cstr2inum (buffer , 10 );
726+ RB_ALLOCV_END (buffer_v );
727+ return number ;
728+ }
729+
730+ static inline VALUE
694731json_decode_integer (JSON_ParserState * state , const char * start , const char * end )
695732{
696733 long len = end - start ;
697734 if (RB_LIKELY (len < MAX_FAST_INTEGER_SIZE )) {
698735 return fast_decode_integer (start , end );
699736 }
700-
701- fbuffer_clear (& state -> fbuffer );
702- fbuffer_append (& state -> fbuffer , start , len );
703- fbuffer_append_char (& state -> fbuffer , '\0' );
704- return rb_cstr2inum (FBUFFER_PTR (& state -> fbuffer ), 10 );
737+ return json_decode_large_integer (start , len );
705738}
706739
740+ static VALUE json_decode_large_float (const char * start , long len )
741+ {
742+ VALUE buffer_v ;
743+ char * buffer = RB_ALLOCV_N (char , buffer_v , len + 1 );
744+ MEMCPY (buffer , start , char , len );
745+ buffer [len ] = '\0' ;
746+ VALUE number = DBL2NUM (rb_cstr_to_dbl (buffer , 1 ));
747+ RB_ALLOCV_END (buffer_v );
748+ return number ;
749+ }
750+
707751static VALUE json_decode_float (JSON_ParserState * state , const char * start , const char * end )
708752{
709753 VALUE mod = Qnil ;
710754 ID method_id = 0 ;
711755 JSON_ParserConfig * config = state -> config ;
712- if (config -> decimal_class ) {
756+ if (RB_UNLIKELY ( config -> decimal_class ) ) {
713757 // TODO: we should move this to the constructor
714758 if (rb_respond_to (config -> decimal_class , i_try_convert )) {
715759 mod = config -> decimal_class ;
@@ -739,15 +783,17 @@ static VALUE json_decode_float(JSON_ParserState *state, const char *start, const
739783 }
740784
741785 long len = end - start ;
742- fbuffer_clear (& state -> fbuffer );
743- fbuffer_append (& state -> fbuffer , start , len );
744- fbuffer_append_char (& state -> fbuffer , '\0' );
745786
746- if (method_id ) {
747- VALUE text = rb_str_new2 ( FBUFFER_PTR ( & state -> fbuffer ) );
787+ if (RB_UNLIKELY ( method_id ) ) {
788+ VALUE text = rb_str_new ( start , len );
748789 return rb_funcallv (mod , method_id , 1 , & text );
790+ } else if (RB_LIKELY (len < 64 )) {
791+ char buffer [64 ];
792+ MEMCPY (buffer , start , char , len );
793+ buffer [len ] = '\0' ;
794+ return DBL2NUM (rb_cstr_to_dbl (buffer , 1 ));
749795 } else {
750- return DBL2NUM ( rb_cstr_to_dbl ( FBUFFER_PTR ( & state -> fbuffer ), 1 ) );
796+ return json_decode_large_float ( start , len );
751797 }
752798}
753799
@@ -1283,14 +1329,6 @@ static VALUE cParserConfig_initialize(VALUE self, VALUE opts)
12831329 return self ;
12841330}
12851331
1286- static VALUE cParser_parse_safe (VALUE vstate )
1287- {
1288- JSON_ParserState * state = (JSON_ParserState * )vstate ;
1289- VALUE result = json_parse_any (state );
1290- json_ensure_eof (state );
1291- return result ;
1292- }
1293-
12941332static VALUE cParser_parse (JSON_ParserConfig * config , VALUE Vsource )
12951333{
12961334 Vsource = convert_encoding (StringValue (Vsource ));
@@ -1311,17 +1349,13 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
13111349 };
13121350 JSON_ParserState * state = & _state ;
13131351
1314- char stack_buffer [FBUFFER_STACK_SIZE ];
1315- fbuffer_stack_init (& state -> fbuffer , FBUFFER_INITIAL_LENGTH_DEFAULT , stack_buffer , FBUFFER_STACK_SIZE );
1316-
1317- int interupted ;
1318- VALUE result = rb_protect (cParser_parse_safe , (VALUE )state , & interupted );
1352+ VALUE result = json_parse_any (state );
13191353
1354+ // This may be skipped in case of exception, but
1355+ // it won't cause a leak.
13201356 rvalue_stack_eagerly_release (state -> stack_handle );
1321- fbuffer_free (& state -> fbuffer );
1322- if (interupted ) {
1323- rb_jump_tag (interupted );
1324- }
1357+
1358+ json_ensure_eof (state );
13251359
13261360 return result ;
13271361}
0 commit comments