mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-02-08 18:56:45 +08:00
Clean up
This commit is contained in:
parent
653790b5f3
commit
89fc24007a
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "float_common.h"
|
#include "float_common.h"
|
||||||
|
|
||||||
#if FASTFLOAT_SSE2
|
#ifdef FASTFLOAT_SSE2
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ namespace fast_float {
|
|||||||
// able to optimize it well.
|
// able to optimize it well.
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
fastfloat_really_inline constexpr bool is_integer(CharT c) noexcept {
|
fastfloat_really_inline constexpr bool is_integer(CharT c) noexcept {
|
||||||
return c >= static_cast<CharT>('0') && c <= static_cast<CharT>('9');
|
return c >= CharT('0') && c <= CharT('9');
|
||||||
}
|
}
|
||||||
|
|
||||||
fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
|
fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
|
||||||
@ -42,9 +42,10 @@ uint64_t fast_read_u64(const char* chars) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://quick-bench.com/q/fk6Y07KDGu8XZ9iUtQD8QJTc3Hg
|
// https://quick-bench.com/q/fk6Y07KDGu8XZ9iUtQD8QJTc3Hg
|
||||||
|
// todo: add support for char32_t
|
||||||
fastfloat_really_inline
|
fastfloat_really_inline
|
||||||
uint64_t fast_read_u64(const char16_t* chars) {
|
uint64_t fast_read_u64(const char16_t* chars) {
|
||||||
#if FASTFLOAT_SSE2
|
#ifdef FASTFLOAT_SSE2
|
||||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||||
static const char16_t masks[] = {0xff, 0xff, 0xff, 0xff};
|
static const char16_t masks[] = {0xff, 0xff, 0xff, 0xff};
|
||||||
const __m128i m_masks = _mm_loadu_si128(reinterpret_cast<const __m128i*>(masks));
|
const __m128i m_masks = _mm_loadu_si128(reinterpret_cast<const __m128i*>(masks));
|
||||||
@ -65,6 +66,7 @@ FASTFLOAT_SIMD_RESTORE_WARNINGS
|
|||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
bytes[i] = (unsigned char)chars[i];
|
bytes[i] = (unsigned char)chars[i];
|
||||||
|
|
||||||
|
// bit-cast
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
::memcpy(&val, bytes, sizeof(uint64_t));
|
::memcpy(&val, bytes, sizeof(uint64_t));
|
||||||
return val;
|
return val;
|
||||||
@ -77,7 +79,7 @@ uint64_t read_u64(const CharT *chars) {
|
|||||||
if (cpp20_and_in_constexpr()) {
|
if (cpp20_and_in_constexpr()) {
|
||||||
uint64_t val = 0;
|
uint64_t val = 0;
|
||||||
for(int i = 0; i < 8; ++i) {
|
for(int i = 0; i < 8; ++i) {
|
||||||
val |= uint64_t(*chars) << (i*8);
|
val |= uint64_t(char(*chars)) << (i*8);
|
||||||
++chars;
|
++chars;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@ -121,7 +123,7 @@ uint32_t parse_eight_digits_unrolled(uint64_t val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// http://0x80.pl/articles/simd-parsing-int-sequences.html
|
// http://0x80.pl/articles/simd-parsing-int-sequences.html
|
||||||
#if FASTFLOAT_SSE2
|
#ifdef FASTFLOAT_SSE2
|
||||||
fastfloat_really_inline
|
fastfloat_really_inline
|
||||||
uint32_t parse_eight_digits_unrolled_c16(const __m128i val) {
|
uint32_t parse_eight_digits_unrolled_c16(const __m128i val) {
|
||||||
// x - '0'
|
// x - '0'
|
||||||
@ -152,13 +154,15 @@ 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call this if you know chars are only digits
|
||||||
|
//todo: add support for char32_t
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||||
uint32_t parse_eight_digits_unrolled(const char16_t* chars) noexcept {
|
uint32_t parse_eight_digits_unrolled(const char16_t* chars) noexcept {
|
||||||
if (cpp20_and_in_constexpr() || !has_simd()) {
|
if (cpp20_and_in_constexpr() || !has_simd()) {
|
||||||
return parse_eight_digits_unrolled(read_u64(chars));
|
return parse_eight_digits_unrolled(read_u64(chars));
|
||||||
}
|
}
|
||||||
#if !FASTFLOAT_HAS_SIMD
|
#ifndef FASTFLOAT_HAS_SIMD
|
||||||
return 0; // never reaches here, satisfy compiler
|
return 0; // never reaches here, remove warning
|
||||||
#else
|
#else
|
||||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||||
return parse_eight_digits_unrolled_c16(_mm_loadu_si128(reinterpret_cast<const __m128i*>(chars)));
|
return parse_eight_digits_unrolled_c16(_mm_loadu_si128(reinterpret_cast<const __m128i*>(chars)));
|
||||||
@ -173,7 +177,9 @@ bool parse_if_eight_digits_unrolled(const char* chars, std::uint64_t& i) noexcep
|
|||||||
return all;
|
return all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call this if you don't know whether chars are only digits
|
||||||
// http://0x80.pl/articles/simd-parsing-int-sequences.html
|
// http://0x80.pl/articles/simd-parsing-int-sequences.html
|
||||||
|
//todo: add support for char32_t
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||||
bool parse_if_eight_digits_unrolled(const char16_t* chars, std::uint64_t& i) noexcept {
|
bool parse_if_eight_digits_unrolled(const char16_t* chars, std::uint64_t& i) noexcept {
|
||||||
if (cpp20_and_in_constexpr() || !has_simd()) {
|
if (cpp20_and_in_constexpr() || !has_simd()) {
|
||||||
@ -184,17 +190,16 @@ bool parse_if_eight_digits_unrolled(const char16_t* chars, std::uint64_t& i) noe
|
|||||||
i = i * 100000000 + parse_eight_digits_unrolled(read_u64(chars));
|
i = i * 100000000 + parse_eight_digits_unrolled(read_u64(chars));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#if !FASTFLOAT_HAS_SIMD
|
#ifndef FASTFLOAT_HAS_SIMD
|
||||||
return false; // never reaches here, satisfy compiler
|
return false; // never reaches here, remove warning
|
||||||
#else
|
#else
|
||||||
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||||
const __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i*>(chars));
|
const __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i*>(chars));
|
||||||
// (x - '0') <= 9
|
// (x - '0') <= 9
|
||||||
const __m128i t0 = _mm_sub_epi16(data, _mm_set1_epi16(80));
|
const __m128i t0 = _mm_sub_epi16(data, _mm_set1_epi16(80));
|
||||||
const __m128i t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-119));
|
const __m128i t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-119));
|
||||||
const bool is_digits = _mm_movemask_epi8(t1) == 0;
|
|
||||||
|
|
||||||
if (is_digits) {
|
if (_mm_movemask_epi8(t1) == 0) {
|
||||||
i = i * 100000000 + parse_eight_digits_unrolled_c16(data);
|
i = i * 100000000 + parse_eight_digits_unrolled_c16(data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -227,16 +232,16 @@ fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
|||||||
parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pend, parse_options options) noexcept {
|
parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pend, parse_options options) noexcept {
|
||||||
const chars_format fmt = options.format;
|
const chars_format fmt = options.format;
|
||||||
const parse_rules rules = options.rules;
|
const parse_rules rules = options.rules;
|
||||||
const CharT decimal_point = static_cast<CharT>(options.decimal_point);
|
const CharT decimal_point = CharT(options.decimal_point);
|
||||||
|
|
||||||
parsed_number_string<CharT> answer;
|
parsed_number_string<CharT> answer;
|
||||||
answer.valid = false;
|
answer.valid = false;
|
||||||
answer.too_many_digits = false;
|
answer.too_many_digits = false;
|
||||||
answer.negative = (*p == static_cast<CharT>('-'));
|
answer.negative = (*p == CharT('-'));
|
||||||
#if FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
#if FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
||||||
if ((*p == static_cast<CharT>('-')) || (*p == static_cast<CharT>('+'))) {
|
if ((*p == CharT('-')) || (*p == CharT('+'))) {
|
||||||
#else
|
#else
|
||||||
if (*p == static_cast<CharT>('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
if (*p == CharT('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||||
#endif
|
#endif
|
||||||
++p;
|
++p;
|
||||||
if (p == pend) {
|
if (p == pend) {
|
||||||
@ -254,7 +259,7 @@ parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pen
|
|||||||
// a multiplication by 10 is cheaper than an arbitrary integer
|
// a multiplication by 10 is cheaper than an arbitrary integer
|
||||||
// multiplication
|
// multiplication
|
||||||
i = 10 * i +
|
i = 10 * i +
|
||||||
uint64_t(*p - static_cast<CharT>('0')); // might overflow, we will handle the overflow later
|
uint64_t(*p - CharT('0')); // might overflow, we will handle the overflow later
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
const CharT *const end_of_integer_part = p;
|
const CharT *const end_of_integer_part = p;
|
||||||
@ -271,7 +276,7 @@ parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pen
|
|||||||
p += 8;
|
p += 8;
|
||||||
}
|
}
|
||||||
while ((p != pend) && is_integer(*p)) {
|
while ((p != pend) && is_integer(*p)) {
|
||||||
i = i * 10 + uint64_t(*p - static_cast<CharT>('0')); // in rare cases, this will overflow, but that's ok
|
i = i * 10 + uint64_t(*p - CharT('0')); // in rare cases, this will overflow, but that's ok
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
exponent = before - p;
|
exponent = before - p;
|
||||||
@ -283,14 +288,14 @@ parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pen
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
int64_t exp_number = 0; // explicit exponential part
|
int64_t exp_number = 0; // explicit exponential part
|
||||||
if ((fmt & chars_format::scientific) && (p != pend) && ((static_cast<CharT>('e') == *p) || (static_cast<CharT>('E') == *p))) {
|
if ((fmt & chars_format::scientific) && (p != pend) && ((CharT('e') == *p) || (CharT('E') == *p))) {
|
||||||
const CharT * location_of_e = p;
|
const CharT * location_of_e = p;
|
||||||
++p;
|
++p;
|
||||||
bool neg_exp = false;
|
bool neg_exp = false;
|
||||||
if ((p != pend) && (static_cast<CharT>('-') == *p)) {
|
if ((p != pend) && (CharT('-') == *p)) {
|
||||||
neg_exp = true;
|
neg_exp = true;
|
||||||
++p;
|
++p;
|
||||||
} else if ((p != pend) && (static_cast<CharT>('+') == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
|
} else if ((p != pend) && (CharT('+') == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if ((p == pend) || !is_integer(*p)) {
|
if ((p == pend) || !is_integer(*p)) {
|
||||||
@ -302,7 +307,7 @@ parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pen
|
|||||||
p = location_of_e;
|
p = location_of_e;
|
||||||
} else {
|
} else {
|
||||||
while ((p != pend) && is_integer(*p)) {
|
while ((p != pend) && is_integer(*p)) {
|
||||||
uint8_t digit = uint8_t(*p - static_cast<CharT>('0'));
|
uint8_t digit = uint8_t(*p - CharT('0'));
|
||||||
if (exp_number < 0x10000000) {
|
if (exp_number < 0x10000000) {
|
||||||
exp_number = 10 * exp_number + digit;
|
exp_number = 10 * exp_number + digit;
|
||||||
}
|
}
|
||||||
@ -317,7 +322,7 @@ parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pen
|
|||||||
}
|
}
|
||||||
|
|
||||||
// disallow leading zeros before the decimal point
|
// disallow leading zeros before the decimal point
|
||||||
if (rules == parse_rules::json_rules && start_digits[0] == static_cast<CharT>('0') && digit_count >= 2 && is_integer(start_digits[1]))
|
if (rules == parse_rules::json_rules && start_digits[0] == CharT('0') && digit_count >= 2 && is_integer(start_digits[1]))
|
||||||
return answer;
|
return answer;
|
||||||
|
|
||||||
answer.lastmatch = p;
|
answer.lastmatch = p;
|
||||||
@ -335,12 +340,13 @@ parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pen
|
|||||||
// We need to be mindful of the case where we only have zeroes...
|
// We need to be mindful of the case where we only have zeroes...
|
||||||
// E.g., 0.000000000...000.
|
// E.g., 0.000000000...000.
|
||||||
const CharT *start = start_digits;
|
const CharT *start = start_digits;
|
||||||
while ((start != pend) && (*start == static_cast<CharT>('0') || *start == decimal_point)) {
|
while ((start != pend) && (*start == CharT('0') || *start == decimal_point)) {
|
||||||
if(*start == static_cast<CharT>('0')) { digit_count --; }
|
if(*start == CharT('0')) { digit_count --; }
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// exponent/mantissa must be truncated later
|
// exponent/mantissa must be truncated later
|
||||||
|
// this is unlikely, so don't inline truncation code with the rest of parse_number_string()
|
||||||
answer.too_many_digits = digit_count > 19;
|
answer.too_many_digits = digit_count > 19;
|
||||||
}
|
}
|
||||||
answer.exponent = exponent;
|
answer.exponent = exponent;
|
||||||
@ -350,7 +356,7 @@ parsed_number_string<CharT> parse_number_string(const CharT *p, const CharT *pen
|
|||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||||
void truncate_exponent_mantissa(parsed_number_string<CharT>& ps)
|
void parse_truncated_number_string(parsed_number_string<CharT>& ps)
|
||||||
{
|
{
|
||||||
// Let us start again, this time, avoiding overflows.
|
// Let us start again, this time, avoiding overflows.
|
||||||
// We don't need to check if is_integer, since we use the
|
// We don't need to check if is_integer, since we use the
|
||||||
@ -361,7 +367,7 @@ void truncate_exponent_mantissa(parsed_number_string<CharT>& ps)
|
|||||||
const CharT* const int_end = p + ps.integer.len();
|
const CharT* const int_end = p + ps.integer.len();
|
||||||
const uint64_t minimal_nineteen_digit_integer{1000000000000000000};
|
const uint64_t minimal_nineteen_digit_integer{1000000000000000000};
|
||||||
while ((i < minimal_nineteen_digit_integer) && (p != int_end)) {
|
while ((i < minimal_nineteen_digit_integer) && (p != int_end)) {
|
||||||
i = i * 10 + uint64_t(*p - static_cast<CharT>('0'));
|
i = i * 10 + uint64_t(*p - CharT('0'));
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (i >= minimal_nineteen_digit_integer) { // We have a big integers
|
if (i >= minimal_nineteen_digit_integer) { // We have a big integers
|
||||||
@ -371,7 +377,7 @@ void truncate_exponent_mantissa(parsed_number_string<CharT>& ps)
|
|||||||
p = ps.fraction.ptr;
|
p = ps.fraction.ptr;
|
||||||
const CharT* const frac_end = p + ps.fraction.len();
|
const CharT* const frac_end = p + ps.fraction.len();
|
||||||
while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) {
|
while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) {
|
||||||
i = i * 10 + uint64_t(*p - static_cast<CharT>('0'));
|
i = i * 10 + uint64_t(*p - CharT('0'));
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
exponent = ps.fraction.ptr - p + ps.exp_number;
|
exponent = ps.fraction.ptr - p + ps.exp_number;
|
||||||
|
|||||||
@ -158,16 +158,18 @@ void round_down(adjusted_mantissa& am, int32_t shift) noexcept {
|
|||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||||
void skip_zeros(const CharT*& first, const CharT* last) noexcept {
|
void skip_zeros(const CharT*& first, const CharT* last) noexcept {
|
||||||
uint64_t val;
|
if (std::is_same<CharT, char>::value || has_simd()) {
|
||||||
while (!cpp20_and_in_constexpr() && std::distance(first, last) >= 8) {
|
uint64_t val;
|
||||||
val = fast_read_u64(first);
|
while (!cpp20_and_in_constexpr() && std::distance(first, last) >= 8) {
|
||||||
if (val != 0x3030303030303030) {
|
val = fast_read_u64(first);
|
||||||
break;
|
if (val != 0x3030303030303030) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
first += 8;
|
||||||
}
|
}
|
||||||
first += 8;
|
|
||||||
}
|
}
|
||||||
while (first != last) {
|
while (first != last) {
|
||||||
if (*first != static_cast<CharT>('0')) {
|
if (*first != CharT('0')) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
first++;
|
first++;
|
||||||
@ -179,17 +181,19 @@ void skip_zeros(const CharT*& first, const CharT* last) noexcept {
|
|||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||||
bool is_truncated(const CharT* first, const CharT* last) noexcept {
|
bool is_truncated(const CharT* first, const CharT* last) noexcept {
|
||||||
// do 8-bit optimizations, can just compare to 8 literal 0s.
|
if (std::is_same<CharT, char>::value || has_simd()) {
|
||||||
uint64_t val;
|
// do 8-bit optimizations, can just compare to 8 literal 0s.
|
||||||
while (!cpp20_and_in_constexpr() && std::distance(first, last) >= 8) {
|
uint64_t val;
|
||||||
val = fast_read_u64(first);
|
while (!cpp20_and_in_constexpr() && std::distance(first, last) >= 8) {
|
||||||
if (val != 0x3030303030303030) {
|
val = fast_read_u64(first);
|
||||||
return true;
|
if (val != 0x3030303030303030) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
first += 8;
|
||||||
}
|
}
|
||||||
first += 8;
|
|
||||||
}
|
}
|
||||||
while (first != last) {
|
while (first != last) {
|
||||||
if (*first != static_cast<CharT>('0')) {
|
if (*first != CharT('0')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
first++;
|
first++;
|
||||||
@ -215,7 +219,7 @@ void parse_eight_digits(const CharT*& p, limb& value, size_t& counter, size_t& c
|
|||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14
|
||||||
void parse_one_digit(const CharT*& p, limb& value, size_t& counter, size_t& count) noexcept {
|
void parse_one_digit(const CharT*& p, limb& value, size_t& counter, size_t& count) noexcept {
|
||||||
value = value * 10 + limb(*p - static_cast<CharT>('0'));
|
value = value * 10 + limb(*p - CharT('0'));
|
||||||
p++;
|
p++;
|
||||||
counter++;
|
counter++;
|
||||||
count++;
|
count++;
|
||||||
|
|||||||
@ -78,11 +78,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FASTFLOAT_SSE2
|
#ifdef FASTFLOAT_SSE2
|
||||||
#define FASTFLOAT_HAS_SIMD (1)
|
#define FASTFLOAT_HAS_SIMD (1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
|
// disable -Wcast-align=strict (GCC only)
|
||||||
#define FASTFLOAT_SIMD_DISABLE_WARNINGS \
|
#define FASTFLOAT_SIMD_DISABLE_WARNINGS \
|
||||||
_Pragma("GCC diagnostic push") \
|
_Pragma("GCC diagnostic push") \
|
||||||
_Pragma("GCC diagnostic ignored \"-Wcast-align\"")
|
_Pragma("GCC diagnostic ignored \"-Wcast-align\"")
|
||||||
@ -141,7 +142,7 @@ inline FASTFLOAT_CONSTEXPR14 bool
|
|||||||
fastfloat_strncasecmp(const CharT *input1, const char *input2, size_t length) {
|
fastfloat_strncasecmp(const CharT *input1, const char *input2, size_t length) {
|
||||||
char running_diff{0};
|
char running_diff{0};
|
||||||
for (size_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++) {
|
||||||
running_diff |= (static_cast<char>(input1[i]) ^ input2[i]);
|
running_diff |= (char(input1[i]) ^ input2[i]);
|
||||||
}
|
}
|
||||||
return (running_diff == 0) || (running_diff == 32);
|
return (running_diff == 0) || (running_diff == 32);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,12 +26,12 @@ parse_infnan(const CharT *first, const CharT *last, T &value) noexcept {
|
|||||||
answer.ptr = first;
|
answer.ptr = first;
|
||||||
answer.ec = std::errc(); // be optimistic
|
answer.ec = std::errc(); // be optimistic
|
||||||
bool minusSign = false;
|
bool minusSign = false;
|
||||||
if (*first == static_cast<CharT>('-')) { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here
|
if (*first == CharT('-')) { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here
|
||||||
minusSign = true;
|
minusSign = true;
|
||||||
++first;
|
++first;
|
||||||
}
|
}
|
||||||
#if FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
#if FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
|
||||||
if (*first == static_cast<CharT>('+')) {
|
if (*first == CharT('+')) {
|
||||||
++first;
|
++first;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -40,15 +40,15 @@ parse_infnan(const CharT *first, const CharT *last, T &value) noexcept {
|
|||||||
answer.ptr = (first += 3);
|
answer.ptr = (first += 3);
|
||||||
value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN();
|
value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN();
|
||||||
// Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan).
|
// Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan).
|
||||||
if(first != last && *first == static_cast<CharT>('(')) {
|
if(first != last && *first == CharT('(')) {
|
||||||
for(const CharT* ptr = first + 1; ptr != last; ++ptr) {
|
for(const CharT* ptr = first + 1; ptr != last; ++ptr) {
|
||||||
if (*ptr == static_cast<CharT>(')')) {
|
if (*ptr == CharT(')')) {
|
||||||
answer.ptr = ptr + 1; // valid nan(n-char-seq-opt)
|
answer.ptr = ptr + 1; // valid nan(n-char-seq-opt)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(!((static_cast<CharT>('a') <= *ptr && *ptr <= static_cast<CharT>('z')) ||
|
else if(!((CharT('a') <= *ptr && *ptr <= CharT('z')) ||
|
||||||
(static_cast<CharT>('A') <= *ptr && *ptr <= static_cast<CharT>('Z')) ||
|
(CharT('A') <= *ptr && *ptr <= CharT('Z')) ||
|
||||||
(static_cast<CharT>('0') <= *ptr && *ptr <= static_cast<CharT>('9')) || *ptr == static_cast<CharT>('_')))
|
(CharT('0') <= *ptr && *ptr <= CharT('9')) || *ptr == CharT('_')))
|
||||||
break; // forbidden char, not nan(n-char-seq-opt)
|
break; // forbidden char, not nan(n-char-seq-opt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,7 +159,7 @@ from_chars_result<CharT> from_chars_preparsed(parsed_number_string<CharT> pns, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pns.too_many_digits)
|
if (pns.too_many_digits)
|
||||||
truncate_exponent_mantissa(pns);
|
parse_truncated_number_string(pns);
|
||||||
|
|
||||||
answer.ec = std::errc(); // be optimistic
|
answer.ec = std::errc(); // be optimistic
|
||||||
answer.ptr = pns.lastmatch;
|
answer.ptr = pns.lastmatch;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user