@@ -819,32 +819,24 @@ static VALUE json_decode_large_float(const char *start, long len)
819819/* Ruby JSON optimized float decoder using vendored Ryu algorithm
820820 * Accepts pre-extracted mantissa and exponent from first-pass validation
821821 */
822- static inline VALUE json_ryu_parse_float ( uint64_t m10 , int m10digits , int32_t e10 , bool signedM ,
822+ static inline VALUE json_decode_float ( JSON_ParserConfig * config , uint64_t m10 , int m10digits , int32_t e10 , bool signedM ,
823823 const char * start , const char * end )
824824{
825+ if (RB_UNLIKELY (config -> decimal_class )) {
826+ VALUE text = rb_str_new (start , end - start );
827+ return rb_funcallv (config -> decimal_class , config -> decimal_method_id , 1 , & text );
828+ }
829+
825830 // Fall back to rb_cstr_to_dbl for potential subnormals (rare edge case)
826831 // Ryu has rounding issues with subnormals around 1e-310 (< 2.225e-308)
827- if (m10digits + e10 < -307 ) {
828- // Use original string directly via shared helper
832+ if (RB_UNLIKELY (m10digits > 17 || m10digits + e10 < -307 )) {
829833 return json_decode_large_float (start , end - start );
830834 }
831835
832836 double result = ryu_s2d_from_parts (m10 , m10digits , e10 , signedM );
833837 return DBL2NUM (result );
834838}
835839
836- static VALUE json_decode_float (JSON_ParserConfig * config , const char * start , const char * end )
837- {
838- long len = end - start ;
839-
840- if (RB_UNLIKELY (config -> decimal_class )) {
841- VALUE text = rb_str_new (start , len );
842- return rb_funcallv (config -> decimal_class , config -> decimal_method_id , 1 , & text );
843- } else {
844- return json_decode_large_float (start , len );
845- }
846- }
847-
848840static inline VALUE json_decode_array (JSON_ParserState * state , JSON_ParserConfig * config , long count )
849841{
850842 VALUE array = rb_ary_new_from_values (count , rvalue_stack_peek (state -> stack , count ));
@@ -1123,9 +1115,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
11231115
11241116 // Parse integer part and extract mantissa digits
11251117 while ((state -> cursor < state -> end ) && rb_isdigit (* state -> cursor )) {
1126- if (m10digits < 17 ) { // Only keep first 17 significant digits
1127- m10 = m10 * 10 + (* state -> cursor - '0' );
1128- }
1118+ m10 = m10 * 10 + (* state -> cursor - '0' );
11291119 m10digits ++ ;
11301120 state -> cursor ++ ;
11311121 }
@@ -1150,9 +1140,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
11501140 }
11511141
11521142 while ((state -> cursor < state -> end ) && rb_isdigit (* state -> cursor )) {
1153- if (m10digits < 17 ) { // Only keep first 17 significant digits
1154- m10 = m10 * 10 + (* state -> cursor - '0' );
1155- }
1143+ m10 = m10 * 10 + (* state -> cursor - '0' );
11561144 m10digits ++ ;
11571145 state -> cursor ++ ;
11581146 }
@@ -1191,13 +1179,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
11911179 e10 -= (m10digits - decimal_point_pos );
11921180 }
11931181
1194- // Use optimized Ryu path if we have a valid mantissa
1195- if (m10digits > 0 && m10digits <= 17 && !config -> decimal_class ) {
1196- return json_push_value (state , config , json_ryu_parse_float (m10 , m10digits , e10 , signedM , start , state -> cursor ));
1197- }
1198-
1199- // Fallback to standard path for edge cases
1200- return json_push_value (state , config , json_decode_float (config , start , state -> cursor ));
1182+ return json_push_value (state , config , json_decode_float (config , m10 , m10digits , e10 , signedM , start , state -> cursor ));
12011183 }
12021184 case '"' : {
12031185 // %r{\A"[^"\\\t\n\x00]*(?:\\[bfnrtu\\/"][^"\\]*)*"}
0 commit comments