diff options
| author | Jean Boussier <jean.boussier@gmail.com> | 2025-11-01 09:42:24 +0100 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2025-11-01 08:52:35 +0000 |
| commit | a6bdf52bc9005f4c8709736588fca53787ad3d78 (patch) | |
| tree | df07260926ec6d447bf5b4866a8af22af5f80012 /ext/json | |
| parent | 6e2e7a335546275edf15a1617663d5a1c03c6188 (diff) | |
[ruby/json] parser.c: Extract json_parse_digits
https://github.com/ruby/json/commit/1bf405ecc6
Diffstat (limited to 'ext/json')
| -rw-r--r-- | ext/json/parser/parser.c | 49 |
1 files changed, 23 insertions, 26 deletions
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index 565f8e0203..d69cc28a92 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -1022,24 +1022,28 @@ static inline VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig return Qfalse; } +static inline int json_parse_digits(JSON_ParserState *state, uint64_t *accumulator) +{ + const char *start = state->cursor; + while ((state->cursor < state->end) && rb_isdigit(*state->cursor)) { + *accumulator = *accumulator * 10 + (*state->cursor - '0'); + state->cursor++; + } + return (int)(state->cursor - start); +} + static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig *config, bool negative, const char *start) { bool integer = true; + const char first_digit = *state->cursor; // Variables for Ryu optimization - extract digits during parsing - uint64_t mantissa = 0; - int mantissa_digits = 0; int32_t exponent = 0; int decimal_point_pos = -1; - - const char first_digit = *state->cursor; + uint64_t mantissa = 0; // Parse integer part and extract mantissa digits - while ((state->cursor < state->end) && rb_isdigit(*state->cursor)) { - mantissa = mantissa * 10 + (*state->cursor - '0'); - mantissa_digits++; - state->cursor++; - } + int mantissa_digits = json_parse_digits(state, &mantissa); if (RB_UNLIKELY(first_digit == '0' && mantissa_digits > 1 || negative && mantissa_digits == 0)) { raise_parse_error_at("invalid number: %s", state, start); @@ -1051,19 +1055,16 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig decimal_point_pos = mantissa_digits; // Remember position of decimal point state->cursor++; - if (state->cursor == state->end || !rb_isdigit(*state->cursor)) { - raise_parse_error_at("invalid number: %s", state, start); - } + int fractional_digits = json_parse_digits(state, &mantissa); + mantissa_digits += fractional_digits; - while ((state->cursor < state->end) && rb_isdigit(*state->cursor)) { - mantissa = mantissa * 10 + (*state->cursor - '0'); - mantissa_digits++; - state->cursor++; + if (RB_UNLIKELY(!fractional_digits)) { + raise_parse_error_at("invalid number: %s", state, start); } } // Parse exponent - if ((state->cursor < state->end) && ((*state->cursor == 'e') || (*state->cursor == 'E'))) { + if ((state->cursor < state->end) && ((rb_tolower(*state->cursor) == 'e'))) { integer = false; state->cursor++; @@ -1073,18 +1074,14 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig state->cursor++; } - if (state->cursor == state->end || !rb_isdigit(*state->cursor)) { - raise_parse_error_at("invalid number: %s", state, start); - } + uint64_t abs_exponent = 0; + int exponent_digits = json_parse_digits(state, &abs_exponent); - while ((state->cursor < state->end) && rb_isdigit(*state->cursor)) { - exponent = exponent * 10 + (*state->cursor - '0'); - state->cursor++; + if (RB_UNLIKELY(!exponent_digits)) { + raise_parse_error_at("invalid number: %s", state, start); } - if (negative_exponent) { - exponent = -exponent; - } + exponent = negative_exponent ? -((int32_t)abs_exponent) : ((int32_t)abs_exponent); } if (integer) { |
