diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 3769972..1b2594e 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -325,147 +325,22 @@ struct is_supported_char_type > { }; -template -inline FASTFLOAT_CONSTEXPR14 bool -fastfloat_strncasecmp3(UC const *actual_mixedcase, - UC const *expected_lowercase) { - uint64_t mask{0}; - FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { mask = 0x2020202020202020; } - else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { - mask = 0x0020002000200020; - } - else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { - mask = 0x0000002000000020; - } - else { - return false; - } - - uint64_t val1{0}, val2{0}; - if (cpp20_and_in_constexpr()) { - for (size_t i = 0; i < 3; i++) { - if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { - return false; - } - } - return true; - } else { - FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1 || sizeof(UC) == 2) { - ::memcpy(&val1, actual_mixedcase, 3 * sizeof(UC)); - ::memcpy(&val2, expected_lowercase, 3 * sizeof(UC)); - val1 |= mask; - val2 |= mask; - return val1 == val2; - } - else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { - ::memcpy(&val1, actual_mixedcase, 2 * sizeof(UC)); - ::memcpy(&val2, expected_lowercase, 2 * sizeof(UC)); - val1 |= mask; - if (val1 != val2) { - return false; - } - return (actual_mixedcase[2] | 32) == (expected_lowercase[2]); - } - else { - return false; - } - } -} - -template -inline FASTFLOAT_CONSTEXPR14 bool -fastfloat_strncasecmp5(UC const *actual_mixedcase, - UC const *expected_lowercase) { - uint64_t mask{0}; - uint64_t val1{0}, val2{0}; - if (cpp20_and_in_constexpr()) { - for (size_t i = 0; i < 5; i++) { - if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { - return false; - } - } - return true; - } else { - FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { - mask = 0x2020202020202020; - ::memcpy(&val1, actual_mixedcase, 5 * sizeof(UC)); - ::memcpy(&val2, expected_lowercase, 5 * sizeof(UC)); - val1 |= mask; - val2 |= mask; - return val1 == val2; - } - else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { - mask = 0x0020002000200020; - ::memcpy(&val1, actual_mixedcase, 4 * sizeof(UC)); - ::memcpy(&val2, expected_lowercase, 4 * sizeof(UC)); - val1 |= mask; - if (val1 != val2) { - return false; - } - return (actual_mixedcase[4] | 32) == (expected_lowercase[4]); - } - else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { - mask = 0x0000002000000020; - ::memcpy(&val1, actual_mixedcase, 2 * sizeof(UC)); - ::memcpy(&val2, expected_lowercase, 2 * sizeof(UC)); - val1 |= mask; - if (val1 != val2) { - return false; - } - ::memcpy(&val1, actual_mixedcase + 2, 2 * sizeof(UC)); - ::memcpy(&val2, expected_lowercase + 2, 2 * sizeof(UC)); - val1 |= mask; - if (val1 != val2) { - return false; - } - return (actual_mixedcase[4] | 32) == (expected_lowercase[4]); - } - else { - return false; - } - } -} - -// Compares two ASCII strings in a case insensitive manner. +// Compares two ASCII strings in a case insensitive manner. The expected +// string is lowercase ASCII, so OR-ing 0x20 into each actual character maps +// 'A'..'Z' onto 'a'..'z' and leaves everything else mismatched. The lengths +// used are tiny constants (3 and 5), so the compiler unrolls this loop; keep +// it small so that the (rarely executed) inf/nan path does not bloat the hot +// parser it is inlined into. template inline FASTFLOAT_CONSTEXPR14 bool fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase, size_t length) { - uint64_t mask{0}; - FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { mask = 0x2020202020202020; } - else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { - mask = 0x0020002000200020; - } - else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { - mask = 0x0000002000000020; - } - else { - return false; - } - - if (cpp20_and_in_constexpr()) { - for (size_t i = 0; i < length; i++) { - if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { - return false; - } + for (size_t i = 0; i < length; ++i) { + if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { + return false; } - return true; - } else { - uint64_t val1{0}, val2{0}; - size_t sz{8 / (sizeof(UC))}; - for (size_t i = 0; i < length; i += sz) { - val1 = val2 = 0; - sz = sz < (length - i) ? sz : length - i; - ::memcpy(&val1, actual_mixedcase + i, sz * sizeof(UC)); - ::memcpy(&val2, expected_lowercase + i, sz * sizeof(UC)); - val1 |= mask; - val2 |= mask; - if (val1 != val2) { - return false; - } - } - return true; } + return true; } #ifndef FLT_EVAL_METHOD diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 14d077b..febfdc7 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -35,7 +35,7 @@ from_chars_result_t ++first; } if (last - first >= 3) { - if (fastfloat_strncasecmp3(first, str_const_nan())) { + if (fastfloat_strncasecmp(first, str_const_nan(), 3)) { answer.ptr = (first += 3); value = minusSign ? -std::numeric_limits::quiet_NaN() : std::numeric_limits::quiet_NaN(); @@ -54,9 +54,9 @@ from_chars_result_t } return answer; } - if (fastfloat_strncasecmp3(first, str_const_inf())) { + if (fastfloat_strncasecmp(first, str_const_inf(), 3)) { if ((last - first >= 8) && - fastfloat_strncasecmp5(first + 3, str_const_inf() + 3)) { + fastfloat_strncasecmp(first + 3, str_const_inf() + 3, 5)) { answer.ptr = first + 8; } else { answer.ptr = first + 3;