diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index fcbbfe9..d26b7f4 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -292,7 +292,7 @@ report_parse_error(UC const *p, parse_error error) noexcept { template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t parse_number_string(UC const *p, UC const *pend, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { // Cyclomatic complexity https://en.wikipedia.org/wiki/Cyclomatic_complexity // Consider refactoring the 'parse_number_string' function. // FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN fix this. @@ -489,7 +489,7 @@ parse_number_string(UC const *p, UC const *pend, template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t parse_int_string(UC const *p, UC const *pend, T &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { from_chars_result_t answer; @@ -582,7 +582,9 @@ parse_int_string(UC const *p, UC const *pend, T &value, } } -#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN +#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN + value = T(i); +#else if (negative) { #ifdef FASTFLOAT_VISUAL_STUDIO #pragma warning(push) @@ -600,9 +602,7 @@ parse_int_string(UC const *p, UC const *pend, T &value, #pragma warning(pop) #endif } else { -#endif value = T(i); -#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN } #endif diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 1b4362d..667f819 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -33,29 +33,29 @@ namespace fast_float { -enum class chars_format : uint64_t; +enum class chars_format : uint8_t; #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN namespace detail { -constexpr chars_format basic_json_fmt = chars_format(1 << 5); -constexpr chars_format basic_fortran_fmt = chars_format(1 << 6); +constexpr chars_format basic_json_fmt = chars_format(1 << 4); +constexpr chars_format basic_fortran_fmt = chars_format(1 << 5); } // namespace detail #endif -enum class chars_format : uint64_t { +enum class chars_format : uint8_t { scientific = 1 << 0, - fixed = 1 << 2, + fixed = 1 << 1, general = fixed | scientific, - hex = 1 << 3, + hex = 1 << 2, #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN - no_infnan = 1 << 4, + no_infnan = 1 << 3, // RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6 json = uint64_t(detail::basic_json_fmt) | general | no_infnan, // Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed. json_or_infnan = uint64_t(detail::basic_json_fmt) | general, fortran = uint64_t(detail::basic_fortran_fmt) | general, - allow_leading_plus = 1 << 7, - skip_white_space = 1 << 8, + allow_leading_plus = 1 << 6, + skip_white_space = 1 << 7, #endif }; @@ -70,14 +70,18 @@ template struct parse_options_t { FASTFLOAT_CONSTEXPR20 explicit parse_options_t( chars_format fmt = chars_format::general, UC dot = UC('.'), int const b = 10) noexcept - : format(fmt), decimal_point(dot), base(b) {} + : format(fmt), decimal_point(dot), base(uint8_t(b)) { +#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN + assert(b >= 2 && b <= 36); +#endif + } /** Which number formats are accepted */ chars_format format; /** The character used as decimal point */ UC decimal_point; /** The base used for integers */ - uint32_t base; /* only allowed from 2 to 36 */ + uint8_t base; /* only allowed from 2 to 36 */ FASTFLOAT_ASSUME(base >= 2 && base <= 36); }; diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 677a146..3bc40a0 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -146,7 +146,7 @@ template struct from_chars_caller { template FASTFLOAT_CONSTEXPR20 static from_chars_result_t call(UC const *first, UC const *last, T &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { return from_chars_advanced(first, last, value, options); } }; @@ -156,7 +156,7 @@ template <> struct from_chars_caller { template FASTFLOAT_CONSTEXPR20 static from_chars_result_t call(UC const *first, UC const *last, std::float32_t &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { // if std::float32_t is defined, and we are in C++23 mode; macro set for // float32; set value to float due to equivalence between float and // float32_t @@ -173,7 +173,7 @@ template <> struct from_chars_caller { template FASTFLOAT_CONSTEXPR20 static from_chars_result_t call(UC const *first, UC const *last, std::float64_t &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { // if std::float64_t is defined, and we are in C++23 mode; macro set for // float64; set value as double due to equivalence between double and // float64_t @@ -301,7 +301,7 @@ from_chars_advanced(parsed_number_string_t const &pns, T &value) noexcept { template FASTFLOAT_CONSTEXPR20 from_chars_result_t from_chars_float_advanced(UC const *first, UC const *last, T &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { static_assert(is_supported_float_type::value, "only some floating-point types are supported"); @@ -365,7 +365,7 @@ from_chars(UC const *first, UC const *last, T &value, int const base) noexcept { template FASTFLOAT_CONSTEXPR20 from_chars_result_t from_chars_int_advanced(UC const *first, UC const *last, T &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { static_assert(is_supported_integer_type::value, "only integer types are supported"); @@ -378,20 +378,16 @@ from_chars_int_advanced(UC const *first, UC const *last, T &value, first++; } } -#else - // We are in parser code with external loop that checks bounds. - FASTFLOAT_ASSUME(first < last); -#endif - if ( -#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN - first == last || -#endif - options.base < 2 || options.base > 36) { + if (first == last || options.base < 2 || options.base > 36) { from_chars_result_t answer; answer.ec = std::errc::invalid_argument; answer.ptr = first; return answer; } +#else + // We are in parser code with external loop that checks bounds. + FASTFLOAT_ASSUME(first < last); +#endif return parse_int_string(first, last, value, options); } @@ -404,7 +400,7 @@ template <> struct from_chars_advanced_caller<1> { template FASTFLOAT_CONSTEXPR20 static from_chars_result_t call(UC const *first, UC const *last, T &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { return from_chars_float_advanced(first, last, value, options); } }; @@ -413,7 +409,7 @@ template <> struct from_chars_advanced_caller<2> { template FASTFLOAT_CONSTEXPR20 static from_chars_result_t call(UC const *first, UC const *last, T &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { return from_chars_int_advanced(first, last, value, options); } }; @@ -421,7 +417,7 @@ template <> struct from_chars_advanced_caller<2> { template FASTFLOAT_CONSTEXPR20 from_chars_result_t from_chars_advanced(UC const *first, UC const *last, T &value, - parse_options_t const &options) noexcept { + parse_options_t const options) noexcept { return from_chars_advanced_caller< size_t(is_supported_float_type::value) + 2 * size_t(is_supported_integer_type::value)>::call(first, last, value,