@@ -767,6 +767,32 @@ static VALUE json_string_unescape(JSON_ParserState *state, const char *string, c
767767
768768#define MAX_FAST_INTEGER_SIZE 18
769769
770+ #if defined(__BYTE_ORDER__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
771+ // From: https://lemire.me/blog/2022/01/21/swar-explained-parsing-eight-digits/
772+ // Additional References:
773+ // https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
774+ // http://0x80.pl/notesen/2014-10-12-parsing-decimal-numbers-part-1-swar.html
775+ static inline uint32_t parse_eight_digits_unrolled (const char * p ) {
776+ uint64_t val ;
777+ memcpy (& val , p , sizeof (uint64_t ));
778+ const uint64_t mask = 0x000000FF000000FF ;
779+ const uint64_t mul1 = 0x000F424000000064 ; // 100 + (1000000ULL << 32)
780+ const uint64_t mul2 = 0x0000271000000001 ; // 1 + (10000ULL << 32)
781+ val -= 0x3030303030303030 ;
782+ val = (val * 10 ) + (val >> 8 ); // val = (val * 2561) >> 8;
783+ val = (((val & mask ) * mul1 ) + (((val >> 16 ) & mask ) * mul2 )) >> 32 ;
784+ return (uint32_t ) val ;
785+ }
786+
787+ // From: https://github.com/simdjson/simdjson/blob/32b301893c13d058095a07d9868edaaa42ee07aa/include/simdjson/generic/numberparsing.h#L333
788+ // Branchless version of: http://0x80.pl/articles/swar-digits-validate.html
789+ static inline int has_eight_consecutive_digits (const char * p ) {
790+ uint64_t val ;
791+ memcpy (& val , p , sizeof (uint64_t ));
792+ return (((val & 0xF0F0F0F0F0F0F0F0 ) | (((val + 0x0606060606060606 ) & 0xF0F0F0F0F0F0F0F0 ) >> 4 )) == 0x3333333333333333 );
793+ }
794+ #endif
795+
770796static VALUE json_decode_large_integer (const char * start , long len )
771797{
772798 VALUE buffer_v ;
@@ -1105,6 +1131,19 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
11051131 }
11061132 }
11071133
1134+ #if defined(__BYTE_ORDER__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
1135+ while (state -> cursor + 8 <= state -> end ) {
1136+ if (has_eight_consecutive_digits (state -> cursor )) {
1137+ uint64_t val = (uint64_t ) parse_eight_digits_unrolled (state -> cursor );
1138+ mantissa = mantissa * 100000000 + val ;
1139+ mantissa_digits += 8 ;
1140+ state -> cursor += 8 ;
1141+ continue ;
1142+ }
1143+ break ;
1144+ }
1145+ #endif
1146+
11081147 // Parse integer part and extract mantissa digits
11091148 while ((state -> cursor < state -> end ) && rb_isdigit (* state -> cursor )) {
11101149 mantissa = mantissa * 10 + (* state -> cursor - '0' );
@@ -1128,6 +1167,18 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
11281167 raise_parse_error_at ("invalid number: %s" , state , start );
11291168 }
11301169
1170+ #if defined(__BYTE_ORDER__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
1171+ while (state -> cursor + 8 <= state -> end ) {
1172+ if (has_eight_consecutive_digits (state -> cursor )) {
1173+ uint64_t val = (uint64_t ) parse_eight_digits_unrolled (state -> cursor );
1174+ mantissa = mantissa * 100000000 + val ;
1175+ mantissa_digits += 8 ;
1176+ state -> cursor += 8 ;
1177+ continue ;
1178+ }
1179+ break ;
1180+ }
1181+ #endif
11311182 while ((state -> cursor < state -> end ) && rb_isdigit (* state -> cursor )) {
11321183 mantissa = mantissa * 10 + (* state -> cursor - '0' );
11331184 mantissa_digits ++ ;
0 commit comments