From 5223d7a460276fe61f63807cf09a1e3a8bfcc3e6 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 26 Apr 2023 18:25:27 -0400 Subject: [PATCH] address issues raised by @mayawarrier --- include/fast_float/ascii_number.h | 33 ++++++++++++++------------- include/fast_float/digit_comparison.h | 17 ++++++++------ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index 0751969..98365e2 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -27,13 +27,13 @@ fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { | (val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56; } -template + fastfloat_really_inline FASTFLOAT_CONSTEXPR20 -uint64_t read_u64(UC const * chars) { - if (cpp20_and_in_constexpr() || sizeof(UC) > 1) { - uint64_t val{}; +uint64_t read_u64(const char *chars) { + if (cpp20_and_in_constexpr()) { + uint64_t val = 0; for(int i = 0; i < 8; ++i) { - val |= uint64_t(char(*chars)) << (i * 8); + val |= uint64_t(*chars) << (i*8); ++chars; } return val; @@ -75,9 +75,9 @@ uint32_t parse_eight_digits_unrolled(uint64_t val) { val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; return uint32_t(val); } -template + fastfloat_really_inline FASTFLOAT_CONSTEXPR20 -uint32_t parse_eight_digits_unrolled(UC const * chars) noexcept { +uint32_t parse_eight_digits_unrolled(const char *chars) noexcept { return parse_eight_digits_unrolled(read_u64(chars)); } @@ -87,9 +87,8 @@ fastfloat_really_inline constexpr bool is_made_of_eight_digits_fast(uint64_t val 0x8080808080808080)); } -template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 -bool is_made_of_eight_digits_fast(UC const * chars) noexcept { +bool is_made_of_eight_digits_fast(const char *chars) noexcept { return is_made_of_eight_digits_fast(read_u64(chars)); } @@ -102,8 +101,8 @@ struct parsed_number_string_t { bool valid{false}; bool too_many_digits{false}; // contains the range of the significant digits - span integer{}; // non-nullable - span fraction{}; // nullable + span integer{}; // non-nullable + span fraction{}; // nullable }; using byte_span = span; using parsed_number_string = parsed_number_string_t; @@ -145,16 +144,18 @@ parsed_number_string_t parse_number_string(UC const *p, UC const * pend, par } UC const * const end_of_integer_part = p; int64_t digit_count = int64_t(end_of_integer_part - start_digits); - answer.integer = span(start_digits, size_t(digit_count)); + answer.integer = span(start_digits, size_t(digit_count)); int64_t exponent = 0; if ((p != pend) && (*p == decimal_point)) { ++p; UC const * before = p; // can occur at most twice without overflowing, but let it occur more, since // for integers with many digits, digit parsing is the primary bottleneck. - while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) { - i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok - p += 8; + if (std::is_same::value) { + while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast((const char *&)p)) { + i = i * 100000000 + parse_eight_digits_unrolled((const char *&)p); // in rare cases, this will overflow, but that's ok + p += 8; + } } while ((p != pend) && is_integer(*p)) { uint8_t digit = uint8_t(*p - UC('0')); @@ -162,7 +163,7 @@ parsed_number_string_t parse_number_string(UC const *p, UC const * pend, par i = i * 10 + digit; // in rare cases, this will overflow, but that's ok } exponent = before - p; - answer.fraction = span(before, size_t(p - before)); + answer.fraction = span(before, size_t(p - before)); digit_count -= exponent; } // we must have encountered at least one integer! diff --git a/include/fast_float/digit_comparison.h b/include/fast_float/digit_comparison.h index c85be59..b2c8495 100644 --- a/include/fast_float/digit_comparison.h +++ b/include/fast_float/digit_comparison.h @@ -197,13 +197,12 @@ bool is_truncated(UC const * first, UC const * last) noexcept { } template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 -bool is_truncated(span s) noexcept { +bool is_truncated(span s) noexcept { return is_truncated(s.ptr, s.ptr + s.len()); } -template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 -void parse_eight_digits(UC const *& p, limb& value, size_t& counter, size_t& count) noexcept { +void parse_eight_digits(const char*& p, limb& value, size_t& counter, size_t& count) noexcept { value = value * 100000000 + parse_eight_digits_unrolled(p); p += 8; counter += 8; @@ -255,8 +254,10 @@ void parse_mantissa(bigint& result, parsed_number_string_t& num, size_t max_ skip_zeros(p, pend); // process all digits, in increments of step per loop while (p != pend) { - while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) { - parse_eight_digits(p, value, counter, digits); + if (std::is_same::value) { + while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) { + parse_eight_digits((const char *&)p, value, counter, digits); + } } while (counter < step && p != pend && digits < max_digits) { parse_one_digit(p, value, counter, digits); @@ -288,8 +289,10 @@ void parse_mantissa(bigint& result, parsed_number_string_t& num, size_t max_ } // process all digits, in increments of step per loop while (p != pend) { - while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) { - parse_eight_digits(p, value, counter, digits); + if (std::is_same::value) { + while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) { + parse_eight_digits((const char *&)p, value, counter, digits); + } } while (counter < step && p != pend && digits < max_digits) { parse_one_digit(p, value, counter, digits);