@@ -22,48 +22,43 @@ namespace {
22
22
template <typename T>
23
23
from_chars_result parse_infnan (const char *first, const char *last, T &value) noexcept {
24
24
from_chars_result answer;
25
+ answer.ptr = first;
25
26
answer.ec = std::errc (); // be optimistic
27
+ bool minusSign = false ;
28
+ if (*first == ' -' ) { // assume first < last, so dereference without checks
29
+ minusSign = true ;
30
+ ++first;
31
+ } else if ( *first == ' +' ) { // C++17 20.19.3.7 explicitly forbids '+' here, but anyway
32
+ ++first;
33
+ }
26
34
if (last - first >= 3 ) {
27
35
if (fastfloat_strncasecmp (first, " nan" , 3 )) {
28
- answer.ptr = first + 3 ;
29
- value = std::numeric_limits<T>::quiet_NaN ();
36
+ answer.ptr = (first += 3 );
37
+ value = minusSign ? -std::numeric_limits<T>::quiet_NaN () : std::numeric_limits<T>::quiet_NaN ();
38
+ // 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).
39
+ if (first != last && *first == ' (' ) {
40
+ for (const char * ptr = first + 1 ; ptr != last; ++ptr) {
41
+ if (*ptr == ' )' ) {
42
+ answer.ptr = ptr + 1 ; // valid nan(n-char-seq-opt)
43
+ break ;
44
+ }
45
+ else if (!((' a' <= *ptr && *ptr <= ' z' ) || (' A' <= *ptr && *ptr <= ' Z' ) || (' 0' <= *ptr && *ptr <= ' 9' ) || *ptr == ' _' ))
46
+ break ; // forbidden char, not nan(n-char-seq-opt)
47
+ }
48
+ }
30
49
return answer;
31
50
}
32
51
if (fastfloat_strncasecmp (first, " inf" , 3 )) {
33
- if ((last - first >= 8 ) && fastfloat_strncasecmp (first, " infinity " , 8 )) {
52
+ if ((last - first >= 8 ) && fastfloat_strncasecmp (first + 3 , " inity " , 5 )) {
34
53
answer.ptr = first + 8 ;
35
54
} else {
36
55
answer.ptr = first + 3 ;
37
56
}
38
- value = std::numeric_limits<T>::infinity ();
57
+ value = minusSign ? -std::numeric_limits<T>:: infinity () : std::numeric_limits<T>::infinity ();
39
58
return answer;
40
59
}
41
- if (last - first >= 4 ) {
42
- if (fastfloat_strncasecmp (first, " +nan" , 4 ) || fastfloat_strncasecmp (first, " -nan" , 4 )) {
43
- answer.ptr = first + 4 ;
44
- value = std::numeric_limits<T>::quiet_NaN ();
45
- if (first[0 ] == ' -' ) {
46
- value = -value;
47
- }
48
- return answer;
49
- }
50
-
51
- if (fastfloat_strncasecmp (first, " +inf" , 4 ) || fastfloat_strncasecmp (first, " -inf" , 4 )) {
52
- if ((last - first >= 9 ) && fastfloat_strncasecmp (first + 1 , " infinity" , 8 )) {
53
- answer.ptr = first + 9 ;
54
- } else {
55
- answer.ptr = first + 4 ;
56
- }
57
- value = std::numeric_limits<T>::infinity ();
58
- if (first[0 ] == ' -' ) {
59
- value = -value;
60
- }
61
- return answer;
62
- }
63
- }
64
60
}
65
61
answer.ec = std::errc::invalid_argument;
66
- answer.ptr = first;
67
62
return answer;
68
63
}
69
64
0 commit comments