diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-05-20 22:05:25 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-05-20 22:05:25 (GMT) |
commit | bd16edd305ba8067615e703a2cfeeb33907f40b8 (patch) | |
tree | 6c167711c3e67a713c0bfc27eeef1e530816bdd9 /Python/pystrtod.c | |
parent | 4db6ff683d1b1d6e6c6bef875a88c9121c68137d (diff) | |
download | cpython-bd16edd305ba8067615e703a2cfeeb33907f40b8.zip cpython-bd16edd305ba8067615e703a2cfeeb33907f40b8.tar.gz cpython-bd16edd305ba8067615e703a2cfeeb33907f40b8.tar.bz2 |
Refactor to remove duplicated nan/inf parsing code in
pystrtod.c, floatobject.c and dtoa.c.
Diffstat (limited to 'Python/pystrtod.c')
-rw-r--r-- | Python/pystrtod.c | 99 |
1 files changed, 60 insertions, 39 deletions
diff --git a/Python/pystrtod.c b/Python/pystrtod.c index d36f931..95c0ff6 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -3,6 +3,57 @@ #include <Python.h> #include <locale.h> +/* _Py_parse_inf_or_nan: Attempt to parse a string of the form "nan", "inf" or + "infinity", with an optional leading sign of "+" or "-". On success, + return the NaN or Infinity as a double and set *endptr to point just beyond + the successfully parsed portion of the string. On failure, return -1.0 and + set *endptr to point to the start of the string. */ + +static int +case_insensitive_match(const char *s, const char *t) +{ + while(*t && Py_TOLOWER(*s) == *t) { + s++; + t++; + } + return *t ? 0 : 1; +} + +double +_Py_parse_inf_or_nan(const char *p, char **endptr) +{ + double retval; + const char *s; + int negate = 0; + + s = p; + if (*s == '-') { + negate = 1; + s++; + } + else if (*s == '+') { + s++; + } + if (case_insensitive_match(s, "inf")) { + s += 3; + if (case_insensitive_match(s, "inity")) + s += 5; + retval = negate ? -Py_HUGE_VAL : Py_HUGE_VAL; + } +#ifdef Py_NAN + else if (case_insensitive_match(s, "nan")) { + s += 3; + retval = negate ? -Py_NAN : Py_NAN; + } +#endif + else { + s = p; + retval = -1.0; + } + *endptr = (char *)s; + return retval; +} + /** * PyOS_ascii_strtod: * @nptr: the string to convert to a numeric value. @@ -49,6 +100,10 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) result = _Py_dg_strtod(nptr, endptr); _Py_SET_53BIT_PRECISION_END; + if (*endptr == nptr) + /* string might represent and inf or nan */ + result = _Py_parse_inf_or_nan(nptr, endptr); + return result; } @@ -63,19 +118,6 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) correctly rounded results. */ -/* Case-insensitive string match used for nan and inf detection; t should be - lower-case. Returns 1 for a successful match, 0 otherwise. */ - -static int -case_insensitive_match(const char *s, const char *t) -{ - while(*t && Py_TOLOWER(*s) == *t) { - s++; - t++; - } - return *t ? 0 : 1; -} - double _PyOS_ascii_strtod(const char *nptr, char **endptr) { @@ -101,6 +143,11 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) decimal_point_pos = NULL; + /* Parse infinities and nans */ + val = _Py_parse_inf_or_nan(nptr, endptr); + if (*endptr != nptr) + return val; + /* Set errno to zero, so that we can distinguish zero results and underflows */ errno = 0; @@ -118,31 +165,6 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) p++; } - /* Parse infinities and nans */ - if (*p == 'i' || *p == 'I') { - if (case_insensitive_match(p+1, "nf")) { - val = Py_HUGE_VAL; - if (case_insensitive_match(p+3, "inity")) - fail_pos = (char *)p+8; - else - fail_pos = (char *)p+3; - goto got_val; - } - else - goto invalid_string; - } -#ifdef Py_NAN - if (*p == 'n' || *p == 'N') { - if (case_insensitive_match(p+1, "an")) { - val = Py_NAN; - fail_pos = (char *)p+3; - goto got_val; - } - else - goto invalid_string; - } -#endif - /* Some platform strtods accept hex floats; Python shouldn't (at the moment), so we check explicitly for strings starting with '0x'. */ if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) @@ -231,7 +253,6 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) if (fail_pos == digits_pos) goto invalid_string; - got_val: if (negate && fail_pos != nptr) val = -val; *endptr = fail_pos; |