33#include <Python.h>
44#include <locale.h>
55
6+ /* _Py_parse_inf_or_nan: Attempt to parse a string of the form "nan", "inf" or
7+ "infinity", with an optional leading sign of "+" or "-". On success,
8+ return the NaN or Infinity as a double and set *endptr to point just beyond
9+ the successfully parsed portion of the string. On failure, return -1.0 and
10+ set *endptr to point to the start of the string. */
11+
12+ static int
13+ case_insensitive_match (const char * s , const char * t )
14+ {
15+ while (* t && Py_TOLOWER (* s ) == * t ) {
16+ s ++ ;
17+ t ++ ;
18+ }
19+ return * t ? 0 : 1 ;
20+ }
21+
22+ double
23+ _Py_parse_inf_or_nan (const char * p , char * * endptr )
24+ {
25+ double retval ;
26+ const char * s ;
27+ int negate = 0 ;
28+
29+ s = p ;
30+ if (* s == '-' ) {
31+ negate = 1 ;
32+ s ++ ;
33+ }
34+ else if (* s == '+' ) {
35+ s ++ ;
36+ }
37+ if (case_insensitive_match (s , "inf" )) {
38+ s += 3 ;
39+ if (case_insensitive_match (s , "inity" ))
40+ s += 5 ;
41+ retval = negate ? - Py_HUGE_VAL : Py_HUGE_VAL ;
42+ }
43+ #ifdef Py_NAN
44+ else if (case_insensitive_match (s , "nan ")) {
45+ s += 3 ;
46+ retval = negate ? - Py_NAN : Py_NAN ;
47+ }
48+ #endif
49+ else {
50+ s = p ;
51+ retval = -1.0 ;
52+ }
53+ * endptr = (char * )s ;
54+ return retval ;
55+ }
56+
657/**
758 * PyOS_ascii_strtod:
859 * @nptr: the string to convert to a numeric value.
@@ -49,6 +100,10 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr)
49100 result = _Py_dg_strtod (nptr , endptr );
50101 _Py_SET_53BIT_PRECISION_END ;
51102
103+ if (* endptr == nptr )
104+ /* string might represent and inf or nan */
105+ result = _Py_parse_inf_or_nan (nptr , endptr );
106+
52107 return result ;
53108
54109}
@@ -63,19 +118,6 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr)
63118 correctly rounded results.
64119*/
65120
66- /* Case-insensitive string match used for nan and inf detection; t should be
67- lower-case. Returns 1 for a successful match, 0 otherwise. */
68-
69- static int
70- case_insensitive_match (const char * s , const char * t )
71- {
72- while (* t && Py_TOLOWER (* s ) == * t ) {
73- s ++ ;
74- t ++ ;
75- }
76- return * t ? 0 : 1 ;
77- }
78-
79121double
80122_PyOS_ascii_strtod (const char * nptr , char * * endptr )
81123{
@@ -101,6 +143,11 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr)
101143
102144 decimal_point_pos = NULL ;
103145
146+ /* Parse infinities and nans */
147+ val = _Py_parse_inf_or_nan (nptr , endptr );
148+ if (* endptr != nptr )
149+ return val ;
150+
104151 /* Set errno to zero, so that we can distinguish zero results
105152 and underflows */
106153 errno = 0 ;
@@ -118,31 +165,6 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr)
118165 p ++ ;
119166 }
120167
121- /* Parse infinities and nans */
122- if (* p == 'i' || * p == 'I' ) {
123- if (case_insensitive_match (p + 1 , "nf" )) {
124- val = Py_HUGE_VAL ;
125- if (case_insensitive_match (p + 3 , "inity" ))
126- fail_pos = (char * )p + 8 ;
127- else
128- fail_pos = (char * )p + 3 ;
129- goto got_val ;
130- }
131- else
132- goto invalid_string ;
133- }
134- #ifdef Py_NAN
135- if (* p == 'n' || * p == 'N' ) {
136- if (case_insensitive_match (p + 1 , "an" )) {
137- val = Py_NAN ;
138- fail_pos = (char * )p + 3 ;
139- goto got_val ;
140- }
141- else
142- goto invalid_string ;
143- }
144- #endif
145-
146168 /* Some platform strtods accept hex floats; Python shouldn't (at the
147169 moment), so we check explicitly for strings starting with '0x'. */
148170 if (* p == '0' && (* (p + 1 ) == 'x' || * (p + 1 ) == 'X' ))
@@ -231,7 +253,6 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr)
231253 if (fail_pos == digits_pos )
232254 goto invalid_string ;
233255
234- got_val :
235256 if (negate && fail_pos != nptr )
236257 val = - val ;
237258 * endptr = fail_pos ;
0 commit comments