File indexing completed on 2025-04-19 08:19:38
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_CHARCONV_DETAIL_FASTFLOAT_PARSE_NUMBER_HPP
0009 #define BOOST_CHARCONV_DETAIL_FASTFLOAT_PARSE_NUMBER_HPP
0010
0011 #include <boost/charconv/detail/fast_float/ascii_number.hpp>
0012 #include <boost/charconv/detail/fast_float/decimal_to_binary.hpp>
0013 #include <boost/charconv/detail/fast_float/digit_comparison.hpp>
0014 #include <boost/charconv/detail/fast_float/float_common.hpp>
0015
0016 #include <cmath>
0017 #include <cstring>
0018 #include <limits>
0019 #include <system_error>
0020
0021 namespace boost { namespace charconv { namespace detail { namespace fast_float {
0022
0023
0024 namespace detail {
0025
0026
0027
0028
0029
0030
0031 #if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
0032 # pragma GCC diagnostic push
0033 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
0034 #endif
0035
0036 template <typename T, typename UC>
0037 from_chars_result_t<UC> BOOST_CHARCONV_FASTFLOAT_CONSTEXPR14
0038 parse_infnan(UC const * first, UC const * last, T &value) noexcept {
0039 from_chars_result_t<UC> answer{};
0040 answer.ptr = first;
0041 answer.ec = std::errc();
0042 bool minusSign = false;
0043 if (*first == UC('-')) {
0044 minusSign = true;
0045 ++first;
0046 }
0047 #ifdef BOOST_CHARCONV_FASTFLOAT_ALLOWS_LEADING_PLUS
0048 if (*first == UC('+')) {
0049 ++first;
0050 }
0051 #endif
0052 if (last - first >= 3) {
0053 if (fastfloat_strncasecmp(first, str_const_nan<UC>(), 3)) {
0054 answer.ptr = (first += 3);
0055 value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN();
0056
0057 if(first != last && *first == UC('(')) {
0058 for(UC const * ptr = first + 1; ptr != last; ++ptr) {
0059 if (*ptr == UC(')')) {
0060 answer.ptr = ptr + 1;
0061 break;
0062 }
0063 else if(!((UC('a') <= *ptr && *ptr <= UC('z')) || (UC('A') <= *ptr && *ptr <= UC('Z')) || (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_')))
0064 break;
0065 }
0066 }
0067 return answer;
0068 }
0069 if (fastfloat_strncasecmp(first, str_const_inf<UC>(), 3)) {
0070 if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) {
0071 answer.ptr = first + 8;
0072 } else {
0073 answer.ptr = first + 3;
0074 }
0075 value = minusSign ? -std::numeric_limits<T>::infinity() : std::numeric_limits<T>::infinity();
0076 return answer;
0077 }
0078 }
0079 answer.ec = std::errc::invalid_argument;
0080 return answer;
0081 }
0082
0083 #if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
0084 # pragma GCC diagnostic pop
0085 #endif
0086
0087
0088
0089
0090
0091
0092 BOOST_FORCEINLINE bool rounds_to_nearest() noexcept {
0093
0094 #if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
0095 return false;
0096 #endif
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 static volatile float fmin = std::numeric_limits<float>::min();
0114 float fmini = fmin;
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 #ifdef BOOST_CHARCONV_FASTFLOAT_VISUAL_STUDIO
0131 # pragma warning(push)
0132
0133
0134 #elif defined(__clang__)
0135 # pragma clang diagnostic push
0136 # pragma clang diagnostic ignored "-Wfloat-equal"
0137 #elif defined(__GNUC__)
0138 # pragma GCC diagnostic push
0139 # pragma GCC diagnostic ignored "-Wfloat-equal"
0140 #endif
0141 return (fmini + 1.0f == 1.0f - fmini);
0142 #ifdef BOOST_CHARCONV_FASTFLOAT_VISUAL_STUDIO
0143 # pragma warning(pop)
0144 #elif defined(__clang__)
0145 # pragma clang diagnostic pop
0146 #elif defined(__GNUC__)
0147 # pragma GCC diagnostic pop
0148 #endif
0149 }
0150
0151 }
0152
0153 template<typename T, typename UC>
0154 BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
0155 from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
0156 T &value, chars_format fmt ) noexcept {
0157 return from_chars_advanced(first, last, value, parse_options_t<UC>{fmt});
0158 }
0159
0160 template<typename T, typename UC>
0161 BOOST_CHARCONV_FASTFLOAT_CONSTEXPR20
0162 from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
0163 T &value, parse_options_t<UC> options) noexcept {
0164
0165 static_assert (std::is_same<T, double>::value || std::is_same<T, float>::value, "only float and double are supported");
0166 static_assert (std::is_same<UC, char>::value ||
0167 std::is_same<UC, wchar_t>::value ||
0168 std::is_same<UC, char16_t>::value ||
0169 std::is_same<UC, char32_t>::value , "only char, wchar_t, char16_t and char32_t are supported");
0170
0171 from_chars_result_t<UC> answer;
0172 #ifdef BOOST_CHARCONV_FASTFLOAT_SKIP_WHITE_SPACE
0173 while ((first != last) && fast_float::is_space(uint8_t(*first))) {
0174 first++;
0175 }
0176 #endif
0177 if (first == last) {
0178 answer.ec = std::errc::invalid_argument;
0179 answer.ptr = first;
0180 return answer;
0181 }
0182 parsed_number_string_t<UC> pns = parse_number_string<UC>(first, last, options);
0183 if (!pns.valid) {
0184 return detail::parse_infnan(first, last, value);
0185 }
0186 answer.ec = std::errc();
0187 answer.ptr = pns.lastmatch;
0188
0189
0190
0191
0192
0193 if (binary_format<T>::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format<T>::max_exponent_fast_path() && !pns.too_many_digits) {
0194
0195
0196
0197
0198
0199
0200
0201 if(!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
0202
0203
0204 if (pns.mantissa <=binary_format<T>::max_mantissa_fast_path()) {
0205 value = T(pns.mantissa);
0206 if (pns.exponent < 0) { value = value / binary_format<T>::exact_power_of_ten(-pns.exponent); }
0207 else { value = value * binary_format<T>::exact_power_of_ten(pns.exponent); }
0208 if (pns.negative) { value = -value; }
0209 return answer;
0210 }
0211 } else {
0212
0213
0214 if (pns.exponent >= 0 && pns.mantissa <=binary_format<T>::max_mantissa_fast_path(pns.exponent)) {
0215 #if defined(__clang__)
0216
0217 if(pns.mantissa == 0) {
0218 value = pns.negative ? -0. : 0.;
0219 return answer;
0220 }
0221 #endif
0222 value = T(pns.mantissa) * binary_format<T>::exact_power_of_ten(pns.exponent);
0223 if (pns.negative) { value = -value; }
0224 return answer;
0225 }
0226 }
0227 }
0228 adjusted_mantissa am = compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
0229 if(pns.too_many_digits && am.power2 >= 0) {
0230 if(am != compute_float<binary_format<T>>(pns.exponent, pns.mantissa + 1)) {
0231 am = compute_error<binary_format<T>>(pns.exponent, pns.mantissa);
0232 }
0233 }
0234
0235
0236 if(am.power2 < 0) { am = digit_comp<T>(pns, am); }
0237 to_float(pns.negative, am, value);
0238
0239 if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || am.power2 == binary_format<T>::infinite_power()) {
0240 answer.ec = std::errc::result_out_of_range;
0241 }
0242 return answer;
0243 }
0244
0245 }}}}
0246
0247 #endif