NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
parse_number.h
Go to the documentation of this file.
1#ifndef FASTFLOAT_PARSE_NUMBER_H
2#define FASTFLOAT_PARSE_NUMBER_H
3
4#include "ascii_number.h"
5#include "decimal_to_binary.h"
6#include "digit_comparison.h"
7
8#include <cmath>
9#include <cstring>
10#include <limits>
11#include <system_error>
12
13namespace fast_float {
14
15
16namespace detail {
22template <typename T>
23from_chars_result parse_infnan(const char *first, const char *last, T &value) noexcept {
24 from_chars_result answer;
25 answer.ptr = first;
26 answer.ec = std::errc(); // be optimistic
27 bool minusSign = false;
28 if (*first == '-') { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here
29 minusSign = true;
30 ++first;
31 }
32 if (last - first >= 3) {
33 if (fastfloat_strncasecmp(first, "nan", 3)) {
34 answer.ptr = (first += 3);
35 value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN();
36 // 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).
37 if(first != last && *first == '(') {
38 for(const char* ptr = first + 1; ptr != last; ++ptr) {
39 if (*ptr == ')') {
40 answer.ptr = ptr + 1; // valid nan(n-char-seq-opt)
41 break;
42 }
43 else if(!(('a' <= *ptr && *ptr <= 'z') || ('A' <= *ptr && *ptr <= 'Z') || ('0' <= *ptr && *ptr <= '9') || *ptr == '_'))
44 break; // forbidden char, not nan(n-char-seq-opt)
45 }
46 }
47 return answer;
48 }
49 if (fastfloat_strncasecmp(first, "inf", 3)) {
50 if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, "inity", 5)) {
51 answer.ptr = first + 8;
52 } else {
53 answer.ptr = first + 3;
54 }
55 value = minusSign ? -std::numeric_limits<T>::infinity() : std::numeric_limits<T>::infinity();
56 return answer;
57 }
58 }
59 answer.ec = std::errc::invalid_argument;
60 return answer;
61}
62
63} // namespace detail
64
65template<typename T>
66from_chars_result from_chars(const char *first, const char *last,
67 T &value, chars_format fmt /*= chars_format::general*/) noexcept {
68 return from_chars_advanced(first, last, value, parse_options{fmt});
69}
70
71template<typename T>
72from_chars_result from_chars_advanced(const char *first, const char *last,
73 T &value, parse_options options) noexcept {
74
75 static_assert (std::is_same<T, double>::value || std::is_same<T, float>::value, "only float and double are supported");
76
77
78 from_chars_result answer;
79 if (first == last) {
80 answer.ec = std::errc::invalid_argument;
81 answer.ptr = first;
82 return answer;
83 }
84 parsed_number_string pns = parse_number_string(first, last, options);
85 if (!pns.valid) {
86 return detail::parse_infnan(first, last, value);
87 }
88 answer.ec = std::errc(); // be optimistic
89 answer.ptr = pns.lastmatch;
90 // Next is Clinger's fast path.
92 value = T(pns.mantissa);
93 if (pns.exponent < 0) { value = value / binary_format<T>::exact_power_of_ten(-pns.exponent); }
94 else { value = value * binary_format<T>::exact_power_of_ten(pns.exponent); }
95 if (pns.negative) { value = -value; }
96 return answer;
97 }
98 adjusted_mantissa am = compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
99 if(pns.too_many_digits && am.power2 >= 0) {
100 if(am != compute_float<binary_format<T>>(pns.exponent, pns.mantissa + 1)) {
101 am = compute_error<binary_format<T>>(pns.exponent, pns.mantissa);
102 }
103 }
104 // If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa) and we have an invalid power (am.power2 < 0),
105 // then we need to go the long way around again. This is very uncommon.
106 if(am.power2 < 0) { am = digit_comp<T>(pns, am); }
107 to_float(pns.negative, am, value);
108 return answer;
109}
110
111} // namespace fast_float
112
113#endif
CONSTDATA date::last_spec last
Definition: date.h:1989
from_chars_result parse_infnan(const char *first, const char *last, T &value) noexcept
Definition: parse_number.h:23
from_chars_result from_chars(const char *first, const char *last, T &value, chars_format fmt=chars_format::general) noexcept
Definition: parse_number.h:66
fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &value)
Definition: float_common.h:377
fastfloat_really_inline parsed_number_string parse_number_string(const char *p, const char *pend, parse_options options) noexcept
Definition: ascii_number.h:88
from_chars_result from_chars_advanced(const char *first, const char *last, T &value, parse_options options) noexcept
Definition: parse_number.h:72
fastfloat_really_inline adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept
bool fastfloat_strncasecmp(const char *input1, const char *input2, size_t length)
Definition: float_common.h:94
static constexpr T exact_power_of_ten(int64_t power)