Skip to content

Commit 988c62b

Browse files
committed
Encapsulate significant_digits()
1 parent eb3e640 commit 988c62b

File tree

1 file changed

+31
-30
lines changed

1 file changed

+31
-30
lines changed

src/generic/stage2/numberparsing.h

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ namespace numberparsing {
88

99
#ifdef JSON_TEST_NUMBERS
1010
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
11-
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), writer.append_s64((VALUE)))
12-
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), writer.append_u64((VALUE)))
13-
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), writer.append_double((VALUE)))
11+
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
12+
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), (WRITER).append_u64((VALUE)))
13+
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), (WRITER).append_double((VALUE)))
1414
#else
1515
#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
16-
#define WRITE_INTEGER(VALUE, SRC, WRITER) writer.append_s64((VALUE))
17-
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) writer.append_u64((VALUE))
18-
#define WRITE_DOUBLE(VALUE, SRC, WRITER) writer.append_double((VALUE))
16+
#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
17+
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
18+
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
1919
#endif
2020

2121
// Attempts to compute i * 10^(power) exactly; and if "negative" is
@@ -250,7 +250,7 @@ template<typename W>
250250
error_code slow_float_parsing(SIMDJSON_UNUSED const uint8_t * src, W writer) {
251251
double d;
252252
if (parse_float_strtod(src, &d)) {
253-
WRITE_DOUBLE(d, src, writer);
253+
writer.append_double(d);
254254
return SUCCESS;
255255
}
256256
return INVALID_NUMBER(src);
@@ -345,35 +345,36 @@ simdjson_really_inline error_code parse_exponent(SIMDJSON_UNUSED const uint8_t *
345345
return SUCCESS;
346346
}
347347

348+
simdjson_really_inline int significant_digits(const uint8_t * start_digits, int digit_count) {
349+
// It is possible that the integer had an overflow.
350+
// We have to handle the case where we have 0.0000somenumber.
351+
const uint8_t *start = start_digits;
352+
while ((*start == '0') || (*start == '.')) {
353+
start++;
354+
}
355+
// we over-decrement by one when there is a '.'
356+
return digit_count - int(start - start_digits);
357+
}
358+
348359
template<typename W>
349360
simdjson_really_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, int digit_count, int64_t exponent, W &writer) {
350361
// If we frequently had to deal with long strings of digits,
351362
// we could extend our code by using a 128-bit integer instead
352363
// of a 64-bit integer. However, this is uncommon in practice.
353364
// digit count is off by 1 because of the decimal (assuming there was one).
354-
if (simdjson_unlikely((digit_count-1 >= 19))) { // this is uncommon
355-
// It is possible that the integer had an overflow.
356-
// We have to handle the case where we have 0.0000somenumber.
357-
const uint8_t *start = start_digits;
358-
while ((*start == '0') || (*start == '.')) {
359-
start++;
360-
}
361-
// we over-decrement by one when there is a '.'
362-
digit_count -= int(start - start_digits);
363-
if (digit_count >= 19) {
364-
// Ok, chances are good that we had an overflow!
365-
// this is almost never going to get called!!!
366-
// we start anew, going slowly!!!
367-
// This will happen in the following examples:
368-
// 10000000000000000000000000000000000000000000e+308
369-
// 3.1415926535897932384626433832795028841971693993751
370-
//
371-
error_code error = slow_float_parsing(src, writer);
372-
// The number was already written, but we made a copy of the writer
373-
// when we passed it to the parse_large_integer() function, so
374-
writer.skip_double();
375-
return error;
376-
}
365+
if (simdjson_unlikely(digit_count-1 >= 19 && significant_digits(start_digits, digit_count) >= 19)) {
366+
// Ok, chances are good that we had an overflow!
367+
// this is almost never going to get called!!!
368+
// we start anew, going slowly!!!
369+
// This will happen in the following examples:
370+
// 10000000000000000000000000000000000000000000e+308
371+
// 3.1415926535897932384626433832795028841971693993751
372+
//
373+
error_code error = slow_float_parsing(src, writer);
374+
// The number was already written, but we made a copy of the writer
375+
// when we passed it to the parse_large_integer() function, so
376+
writer.skip_double();
377+
return error;
377378
}
378379
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
379380
// way we've tried: https://github.com/simdjson/simdjson/pull/990#discussion_r448497331

0 commit comments

Comments
 (0)