@@ -22,48 +22,43 @@ namespace {
2222template <typename T>
2323from_chars_result parse_infnan (const char *first, const char *last, T &value) noexcept {
2424 from_chars_result answer;
25+ answer.ptr = first;
2526 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+ }
2634 if (last - first >= 3 ) {
2735 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+ }
3049 return answer;
3150 }
3251 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 )) {
3453 answer.ptr = first + 8 ;
3554 } else {
3655 answer.ptr = first + 3 ;
3756 }
38- value = std::numeric_limits<T>::infinity ();
57+ value = minusSign ? -std::numeric_limits<T>:: infinity () : std::numeric_limits<T>::infinity ();
3958 return answer;
4059 }
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- }
6460 }
6561 answer.ec = std::errc::invalid_argument;
66- answer.ptr = first;
6762 return answer;
6863}
6964
0 commit comments