diff --git a/src/generic/stage2/numberparsing.h b/src/generic/stage2/numberparsing.h index dac56ce6..632d7dc5 100644 --- a/src/generic/stage2/numberparsing.h +++ b/src/generic/stage2/numberparsing.h @@ -396,7 +396,9 @@ simdjson_really_inline error_code write_float(const uint8_t *const src, bool neg // we could extend our code by using a 128-bit integer instead // of a 64-bit integer. However, this is uncommon in practice. // digit count is off by 1 because of the decimal (assuming there was one). - if (simdjson_unlikely(digit_count-1 >= 19 && significant_digits(start_digits, digit_count) >= 19)) { + // + // 9999999999999999999 < 2**64 so we can accomodate 19 digits. + if (simdjson_unlikely(digit_count-1 > 19 && significant_digits(start_digits, digit_count) > 19)) { // Ok, chances are good that we had an overflow! // this is almost never going to get called!!! // we start anew, going slowly!!! @@ -715,16 +717,16 @@ SIMDJSON_UNUSED simdjson_really_inline simdjson_result parse_double(cons while (parse_digit(*p, i)) { p++; } exponent = -(p - start_decimal_digits); - // Overflow check. 19 digits (minus the decimal) may be overflow. - overflow = p-src-1 >= 19; + // Overflow check. More than 19 digits (minus the decimal) may be overflow. + overflow = p-src-1 > 19; if (simdjson_unlikely(overflow && leading_zero)) { // Skip leading 0.00000 and see if it still overflows const uint8_t *start_digits = src + 2; while (*start_digits == '0') { start_digits++; } - overflow = start_digits-src >= 19; + overflow = start_digits-src > 19; } } else { - overflow = p-src >= 19; + overflow = p-src > 19; } // diff --git a/tests/basictests.cpp b/tests/basictests.cpp index bfc0120e..f56a06fc 100644 --- a/tests/basictests.cpp +++ b/tests/basictests.cpp @@ -52,6 +52,44 @@ namespace number_tests { return true; } + bool nines() { + std::cout << __func__ << std::endl; + simdjson::dom::parser parser; + std::vector> testing = { + {"9999999999999999999.0",9999999999999999999.0}, + {"9999999999999999999",9999999999999999999.}, + {"999999999999999999.9",999999999999999999.9}, + {"99999999999999999.99",99999999999999999.99}, + {"9999999999999999.999",9999999999999999.999}, + {"999999999999999.9999",999999999999999.9999}, + {"99999999999999.99999",99999999999999.99999}, + {"9999999999999.999999",9999999999999.999999}, + {"999999999999.9999999",999999999999.9999999}, + {"99999999999.99999999",99999999999.99999999}, + {"9999999999.999999999",9999999999.999999999}, + {"999999999.9999999999",999999999.9999999999}, + {"99999999.99999999999",99999999.99999999999}, + {"9999999.999999999999",9999999.999999999999}, + {"999999.9999999999999",999999.9999999999999}, + {"99999.99999999999999",99999.99999999999999}, + {"9999.999999999999999",9999.999999999999999}, + {"999.9999999999999999",999.9999999999999999}, + {"99.99999999999999999",99.99999999999999999}, + {"9.999999999999999999",9.999999999999999999}, + {"0.9999999999999999999",0.9999999999999999999}, + {"0.09999999999999999999",0.09999999999999999999}, + }; + for (std::pair p : testing) { + double actual; + ASSERT_SUCCESS(parser.parse(p.first).get(actual)); + if (actual != p.second) { + std::cerr << "JSON '" << p.first << "' parsed to " << actual << " instead of " << p.first << std::endl; + return false; + } + } + return true; + } + bool powers_of_two() { std::cout << __func__ << std::endl; char buf[1024]; @@ -182,7 +220,8 @@ namespace number_tests { bool run() { return small_integers() && powers_of_two() && - powers_of_ten(); + powers_of_ten() && + nines(); } }