mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-02-16 23:29:54 +08:00
address issues raised by @mayawarrier
This commit is contained in:
parent
545c184596
commit
5223d7a460
@ -27,13 +27,13 @@ fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
|
|||||||
| (val & 0x000000000000FF00) << 40
|
| (val & 0x000000000000FF00) << 40
|
||||||
| (val & 0x00000000000000FF) << 56;
|
| (val & 0x00000000000000FF) << 56;
|
||||||
}
|
}
|
||||||
template <typename UC>
|
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||||
uint64_t read_u64(UC const * chars) {
|
uint64_t read_u64(const char *chars) {
|
||||||
if (cpp20_and_in_constexpr() || sizeof(UC) > 1) {
|
if (cpp20_and_in_constexpr()) {
|
||||||
uint64_t val{};
|
uint64_t val = 0;
|
||||||
for(int i = 0; i < 8; ++i) {
|
for(int i = 0; i < 8; ++i) {
|
||||||
val |= uint64_t(char(*chars)) << (i * 8);
|
val |= uint64_t(*chars) << (i*8);
|
||||||
++chars;
|
++chars;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@ -75,9 +75,9 @@ uint32_t parse_eight_digits_unrolled(uint64_t val) {
|
|||||||
val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
|
val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
|
||||||
return uint32_t(val);
|
return uint32_t(val);
|
||||||
}
|
}
|
||||||
template <typename UC>
|
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
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));
|
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));
|
0x8080808080808080));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename UC>
|
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
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));
|
return is_made_of_eight_digits_fast(read_u64(chars));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +101,8 @@ struct parsed_number_string_t {
|
|||||||
bool valid{false};
|
bool valid{false};
|
||||||
bool too_many_digits{false};
|
bool too_many_digits{false};
|
||||||
// contains the range of the significant digits
|
// contains the range of the significant digits
|
||||||
span<UC> integer{}; // non-nullable
|
span<const UC> integer{}; // non-nullable
|
||||||
span<UC> fraction{}; // nullable
|
span<const UC> fraction{}; // nullable
|
||||||
};
|
};
|
||||||
using byte_span = span<char>;
|
using byte_span = span<char>;
|
||||||
using parsed_number_string = parsed_number_string_t<char>;
|
using parsed_number_string = parsed_number_string_t<char>;
|
||||||
@ -145,16 +144,18 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
|||||||
}
|
}
|
||||||
UC const * const end_of_integer_part = p;
|
UC const * const end_of_integer_part = p;
|
||||||
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
|
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
|
||||||
answer.integer = span<UC>(start_digits, size_t(digit_count));
|
answer.integer = span<const UC>(start_digits, size_t(digit_count));
|
||||||
int64_t exponent = 0;
|
int64_t exponent = 0;
|
||||||
if ((p != pend) && (*p == decimal_point)) {
|
if ((p != pend) && (*p == decimal_point)) {
|
||||||
++p;
|
++p;
|
||||||
UC const * before = p;
|
UC const * before = p;
|
||||||
// can occur at most twice without overflowing, but let it occur more, since
|
// can occur at most twice without overflowing, but let it occur more, since
|
||||||
// for integers with many digits, digit parsing is the primary bottleneck.
|
// for integers with many digits, digit parsing is the primary bottleneck.
|
||||||
while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) {
|
if (std::is_same<UC,char>::value) {
|
||||||
i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok
|
while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast((const char *&)p)) {
|
||||||
p += 8;
|
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)) {
|
while ((p != pend) && is_integer(*p)) {
|
||||||
uint8_t digit = uint8_t(*p - UC('0'));
|
uint8_t digit = uint8_t(*p - UC('0'));
|
||||||
@ -162,7 +163,7 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
|||||||
i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
|
i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
|
||||||
}
|
}
|
||||||
exponent = before - p;
|
exponent = before - p;
|
||||||
answer.fraction = span<UC>(before, size_t(p - before));
|
answer.fraction = span<const UC>(before, size_t(p - before));
|
||||||
digit_count -= exponent;
|
digit_count -= exponent;
|
||||||
}
|
}
|
||||||
// we must have encountered at least one integer!
|
// we must have encountered at least one integer!
|
||||||
|
|||||||
@ -197,13 +197,12 @@ bool is_truncated(UC const * first, UC const * last) noexcept {
|
|||||||
}
|
}
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||||
bool is_truncated(span<UC> s) noexcept {
|
bool is_truncated(span<const UC> s) noexcept {
|
||||||
return is_truncated(s.ptr, s.ptr + s.len());
|
return is_truncated(s.ptr, s.ptr + s.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename UC>
|
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
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);
|
value = value * 100000000 + parse_eight_digits_unrolled(p);
|
||||||
p += 8;
|
p += 8;
|
||||||
counter += 8;
|
counter += 8;
|
||||||
@ -255,8 +254,10 @@ void parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_
|
|||||||
skip_zeros(p, pend);
|
skip_zeros(p, pend);
|
||||||
// process all digits, in increments of step per loop
|
// process all digits, in increments of step per loop
|
||||||
while (p != pend) {
|
while (p != pend) {
|
||||||
while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
|
if (std::is_same<UC,char>::value) {
|
||||||
parse_eight_digits(p, value, counter, digits);
|
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) {
|
while (counter < step && p != pend && digits < max_digits) {
|
||||||
parse_one_digit(p, value, counter, digits);
|
parse_one_digit(p, value, counter, digits);
|
||||||
@ -288,8 +289,10 @@ void parse_mantissa(bigint& result, parsed_number_string_t<UC>& num, size_t max_
|
|||||||
}
|
}
|
||||||
// process all digits, in increments of step per loop
|
// process all digits, in increments of step per loop
|
||||||
while (p != pend) {
|
while (p != pend) {
|
||||||
while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) {
|
if (std::is_same<UC,char>::value) {
|
||||||
parse_eight_digits(p, value, counter, digits);
|
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) {
|
while (counter < step && p != pend && digits < max_digits) {
|
||||||
parse_one_digit(p, value, counter, digits);
|
parse_one_digit(p, value, counter, digits);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user