Skip to content

Commit 6bc46f5

Browse files
committed
Refactor json_decode_integer to not decode the number twice
1 parent a2726cb commit 6bc46f5

File tree

1 file changed

+21
-31
lines changed

1 file changed

+21
-31
lines changed

ext/json/ext/parser/parser.c

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ typedef unsigned char _Bool;
2121
#endif
2222
#endif
2323

24+
#if SIZEOF_UINT64_T == SIZEOF_LONG_LONG
25+
# define INT64T2NUM(x) LL2NUM(x)
26+
# define UINT64T2NUM(x) ULL2NUM(x)
27+
#elif SIZEOF_UINT64_T == SIZEOF_LONG
28+
# define INT64T2NUM(x) LONG2NUM(x)
29+
# define UINT64T2NUM(x) ULONG2NUM(x)
30+
#else
31+
# error No uint64_t conversion
32+
#endif
33+
2434
#include "../simd/simd.h"
2535

2636
#ifndef RB_UNLIKELY
@@ -756,26 +766,6 @@ static VALUE json_string_unescape(JSON_ParserState *state, const char *string, c
756766
}
757767

758768
#define MAX_FAST_INTEGER_SIZE 18
759-
static inline VALUE fast_decode_integer(const char *p, const char *pe)
760-
{
761-
bool negative = false;
762-
if (*p == '-') {
763-
negative = true;
764-
p++;
765-
}
766-
767-
long long memo = 0;
768-
while (p < pe) {
769-
memo *= 10;
770-
memo += *p - '0';
771-
p++;
772-
}
773-
774-
if (negative) {
775-
memo = -memo;
776-
}
777-
return LL2NUM(memo);
778-
}
779769

780770
static VALUE json_decode_large_integer(const char *start, long len)
781771
{
@@ -789,13 +779,16 @@ static VALUE json_decode_large_integer(const char *start, long len)
789779
}
790780

791781
static inline VALUE
792-
json_decode_integer(const char *start, const char *end)
782+
json_decode_integer(uint64_t mantissa, int mantissa_digits, bool negative, const char *start, const char *end)
793783
{
794-
long len = end - start;
795-
if (RB_LIKELY(len < MAX_FAST_INTEGER_SIZE)) {
796-
return fast_decode_integer(start, end);
784+
if (RB_LIKELY(mantissa_digits < MAX_FAST_INTEGER_SIZE)) {
785+
if (negative) {
786+
return INT64T2NUM(-((int64_t)mantissa));
787+
}
788+
return UINT64T2NUM(mantissa);
797789
}
798-
return json_decode_large_integer(start, len);
790+
791+
return json_decode_large_integer(start, end - start);
799792
}
800793

801794
static VALUE json_decode_large_float(const char *start, long len)
@@ -1119,12 +1112,9 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
11191112
state->cursor++;
11201113
}
11211114

1122-
long integer_length = state->cursor - start;
1123-
if (negative) integer_length--; // Don't count the sign
1124-
1125-
if (RB_UNLIKELY(start[0] == '0' && integer_length > 1)) {
1115+
if (RB_UNLIKELY(start[0] == '0' && mantissa_digits > 1)) {
11261116
raise_parse_error_at("invalid number: %s", state, start);
1127-
} else if (RB_UNLIKELY(integer_length > 1 && negative && start[1] == '0')) {
1117+
} else if (RB_UNLIKELY(mantissa_digits > 1 && negative && start[1] == '0')) {
11281118
raise_parse_error_at("invalid number: %s", state, start);
11291119
}
11301120

@@ -1171,7 +1161,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
11711161
}
11721162

11731163
if (integer) {
1174-
return json_push_value(state, config, json_decode_integer(start, state->cursor));
1164+
return json_push_value(state, config, json_decode_integer(mantissa, mantissa_digits, negative, start, state->cursor));
11751165
}
11761166

11771167
// Adjust exponent based on decimal point position

0 commit comments

Comments
 (0)