@@ -1022,24 +1022,28 @@ static inline VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig
10221022 return Qfalse ;
10231023}
10241024
1025+ static inline int json_parse_digits (JSON_ParserState * state , uint64_t * accumulator )
1026+ {
1027+ const char * start = state -> cursor ;
1028+ while ((state -> cursor < state -> end ) && rb_isdigit (* state -> cursor )) {
1029+ * accumulator = * accumulator * 10 + (* state -> cursor - '0' );
1030+ state -> cursor ++ ;
1031+ }
1032+ return (int )(state -> cursor - start );
1033+ }
1034+
10251035static inline VALUE json_parse_number (JSON_ParserState * state , JSON_ParserConfig * config , bool negative , const char * start )
10261036{
10271037 bool integer = true;
1038+ const char first_digit = * state -> cursor ;
10281039
10291040 // Variables for Ryu optimization - extract digits during parsing
1030- uint64_t mantissa = 0 ;
1031- int mantissa_digits = 0 ;
10321041 int32_t exponent = 0 ;
10331042 int decimal_point_pos = -1 ;
1034-
1035- const char first_digit = * state -> cursor ;
1043+ uint64_t mantissa = 0 ;
10361044
10371045 // Parse integer part and extract mantissa digits
1038- while ((state -> cursor < state -> end ) && rb_isdigit (* state -> cursor )) {
1039- mantissa = mantissa * 10 + (* state -> cursor - '0' );
1040- mantissa_digits ++ ;
1041- state -> cursor ++ ;
1042- }
1046+ int mantissa_digits = json_parse_digits (state , & mantissa );
10431047
10441048 if (RB_UNLIKELY (first_digit == '0' && mantissa_digits > 1 || negative && mantissa_digits == 0 )) {
10451049 raise_parse_error_at ("invalid number: %s" , state , start );
@@ -1051,19 +1055,16 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
10511055 decimal_point_pos = mantissa_digits ; // Remember position of decimal point
10521056 state -> cursor ++ ;
10531057
1054- if (state -> cursor == state -> end || !rb_isdigit (* state -> cursor )) {
1055- raise_parse_error_at ("invalid number: %s" , state , start );
1056- }
1058+ int fractional_digits = json_parse_digits (state , & mantissa );
1059+ mantissa_digits += fractional_digits ;
10571060
1058- while ((state -> cursor < state -> end ) && rb_isdigit (* state -> cursor )) {
1059- mantissa = mantissa * 10 + (* state -> cursor - '0' );
1060- mantissa_digits ++ ;
1061- state -> cursor ++ ;
1061+ if (RB_UNLIKELY (!fractional_digits )) {
1062+ raise_parse_error_at ("invalid number: %s" , state , start );
10621063 }
10631064 }
10641065
10651066 // Parse exponent
1066- if ((state -> cursor < state -> end ) && ((* state -> cursor == 'e' ) || ( * state -> cursor == 'E ' ))) {
1067+ if ((state -> cursor < state -> end ) && ((rb_tolower ( * state -> cursor ) == 'e ' ))) {
10671068 integer = false;
10681069 state -> cursor ++ ;
10691070
@@ -1073,18 +1074,14 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
10731074 state -> cursor ++ ;
10741075 }
10751076
1076- if (state -> cursor == state -> end || !rb_isdigit (* state -> cursor )) {
1077- raise_parse_error_at ("invalid number: %s" , state , start );
1078- }
1077+ uint64_t abs_exponent = 0 ;
1078+ int exponent_digits = json_parse_digits (state , & abs_exponent );
10791079
1080- while ((state -> cursor < state -> end ) && rb_isdigit (* state -> cursor )) {
1081- exponent = exponent * 10 + (* state -> cursor - '0' );
1082- state -> cursor ++ ;
1080+ if (RB_UNLIKELY (!exponent_digits )) {
1081+ raise_parse_error_at ("invalid number: %s" , state , start );
10831082 }
10841083
1085- if (negative_exponent ) {
1086- exponent = - exponent ;
1087- }
1084+ exponent = negative_exponent ? - ((int32_t )abs_exponent ) : ((int32_t )abs_exponent );
10881085 }
10891086
10901087 if (integer ) {
0 commit comments