/* * _NumPyOS_ascii_strtod_plain: * * PyOS_ascii_strtod work-alike, with no enhanced features, * for forward compatibility with Python >= 2.7 */ static double NumPyOS_ascii_strtod_plain(const char *s, char** endptr) { double result; #if PY_VERSION_HEX >= 0x02070000 NPY_ALLOW_C_API_DEF NPY_ALLOW_C_API result = PyOS_string_to_double(s, endptr, NULL); if (PyErr_Occurred()) { if (endptr) { *endptr = (char*)s; } PyErr_Clear(); } NPY_DISABLE_C_API #else result = PyOS_ascii_strtod(s, endptr); #endif return result; }
static PyObject * strop_atof(PyObject *self, PyObject *args) { char *s, *end; double x; char buffer[256]; /* For errors */ WARN; if (!PyArg_ParseTuple(args, "s:atof", &s)) return NULL; while (*s && isspace(Py_CHARMASK(*s))) s++; if (s[0] == '\0') { PyErr_SetString(PyExc_ValueError, "empty string for atof()"); return NULL; } errno = 0; PyFPE_START_PROTECT("strop_atof", return 0) x = PyOS_ascii_strtod(s, &end); PyFPE_END_PROTECT(x) while (*end && isspace(Py_CHARMASK(*end))) end++; if (*end != '\0') { PyOS_snprintf(buffer, sizeof(buffer), "invalid literal for atof(): %.200s", s); PyErr_SetString(PyExc_ValueError, buffer); return NULL; } else if (errno != 0) { PyOS_snprintf(buffer, sizeof(buffer), "atof() literal too large: %.200s", s); PyErr_SetString(PyExc_ValueError, buffer); return NULL; } return PyFloat_FromDouble(x); }
static PyObject * complex_subtype_from_string(PyTypeObject *type, PyObject *v) { const char *s, *start; char *end; double x=0.0, y=0.0, z; int got_re=0, got_im=0, got_bracket=0, done=0; int digit_or_dot; int sw_error=0; int sign; char buffer[256]; /* For errors */ #ifdef Py_USING_UNICODE char s_buffer[256]; #endif Py_ssize_t len; if (PyString_Check(v)) { s = PyString_AS_STRING(v); len = PyString_GET_SIZE(v); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(v)) { if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) { PyErr_SetString(PyExc_ValueError, "complex() literal too large to convert"); return NULL; } if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), PyUnicode_GET_SIZE(v), s_buffer, NULL)) return NULL; s = s_buffer; len = strlen(s); } #endif else if (PyObject_AsCharBuffer(v, &s, &len)) { PyErr_SetString(PyExc_TypeError, "complex() arg is not a string"); return NULL; } /* position on first nonblank */ start = s; while (*s && isspace(Py_CHARMASK(*s))) s++; if (s[0] == '\0') { PyErr_SetString(PyExc_ValueError, "complex() arg is an empty string"); return NULL; } if (s[0] == '(') { /* Skip over possible bracket from repr(). */ got_bracket = 1; s++; while (*s && isspace(Py_CHARMASK(*s))) s++; } z = -1.0; sign = 1; do { switch (*s) { case '\0': if (s-start != len) { PyErr_SetString( PyExc_ValueError, "complex() arg contains a null byte"); return NULL; } if(!done) sw_error=1; break; case ')': if (!got_bracket || !(got_re || got_im)) { sw_error=1; break; } got_bracket=0; done=1; s++; while (*s && isspace(Py_CHARMASK(*s))) s++; if (*s) sw_error=1; break; case '-': sign = -1; /* Fallthrough */ case '+': if (done) sw_error=1; s++; if ( *s=='\0'||*s=='+'||*s=='-'||*s==')'|| isspace(Py_CHARMASK(*s)) ) sw_error=1; break; case 'J': case 'j': if (got_im || done) { sw_error = 1; break; } if (z<0.0) { y=sign; } else{ y=sign*z; } got_im=1; s++; if (*s!='+' && *s!='-' ) done=1; break; default: if (isspace(Py_CHARMASK(*s))) { while (*s && isspace(Py_CHARMASK(*s))) s++; if (*s && *s != ')') sw_error=1; else done = 1; break; } digit_or_dot = (*s=='.' || isdigit(Py_CHARMASK(*s))); if (done||!digit_or_dot) { sw_error=1; break; } errno = 0; PyFPE_START_PROTECT("strtod", return 0) z = PyOS_ascii_strtod(s, &end) ; PyFPE_END_PROTECT(z) if (errno != 0) { PyOS_snprintf(buffer, sizeof(buffer), "float() out of range: %.150s", s); PyErr_SetString( PyExc_ValueError, buffer); return NULL; } s=end; if (*s=='J' || *s=='j') { break; } if (got_re) { sw_error=1; break; } /* accept a real part */ x=sign*z; got_re=1; if (got_im) done=1; z = -1.0; sign = 1; break; } /* end of switch */ } while (s - start < len && !sw_error); if (sw_error || got_bracket) { PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string"); return NULL; } return complex_subtype_from_doubles(type, x, y); }
/* given a string convert to floating point and return it as a double. * this is to isolate possible unportabilities associated with declaring atof(). * it's worth it because atof() is often some 50% faster than sscanf ("%lf"); */ double atod (char *buf) { return (PyOS_ascii_strtod(buf, NULL)); }
/* * NumPyOS_ascii_strtod: * * Work around bugs in PyOS_ascii_strtod */ static double NumPyOS_ascii_strtod(const char *s, char** endptr) { struct lconv *locale_data = localeconv(); const char *decimal_point = locale_data->decimal_point; size_t decimal_point_len = strlen(decimal_point); char buffer[FLOAT_FORMATBUFLEN+1]; const char *p; char *q; size_t n; double result; while (NumPyOS_ascii_isspace(*s)) { ++s; } /* * ##1 * * Recognize POSIX inf/nan representations on all platforms. */ p = s; result = 1.0; if (*p == '-') { result = -1.0; ++p; } else if (*p == '+') { ++p; } if (NumPyOS_ascii_strncasecmp(p, "nan", 3) == 0) { p += 3; if (*p == '(') { ++p; while (NumPyOS_ascii_isalnum(*p) || *p == '_') { ++p; } if (*p == ')') { ++p; } } if (endptr != NULL) { *endptr = (char*)p; } return NPY_NAN; } else if (NumPyOS_ascii_strncasecmp(p, "inf", 3) == 0) { p += 3; if (NumPyOS_ascii_strncasecmp(p, "inity", 5) == 0) { p += 5; } if (endptr != NULL) { *endptr = (char*)p; } return result*NPY_INFINITY; } /* End of ##1 */ /* * ## 2 * * At least Python versions <= 2.5.2 and <= 2.6.1 * * Fails to do best-efforts parsing of strings of the form "1<DP>234" * where <DP> is the decimal point under the foreign locale. */ if (decimal_point[0] != '.' || decimal_point[1] != 0) { p = s; if (*p == '+' || *p == '-') { ++p; } while (*p >= '0' && *p <= '9') { ++p; } if (strncmp(p, decimal_point, decimal_point_len) == 0) { n = (size_t)(p - s); if (n > FLOAT_FORMATBUFLEN) { n = FLOAT_FORMATBUFLEN; } memcpy(buffer, s, n); buffer[n] = '\0'; result = PyOS_ascii_strtod(buffer, &q); if (endptr != NULL) { *endptr = (char*)(s + (q - buffer)); } return result; } } /* End of ##2 */ return PyOS_ascii_strtod(s, endptr); }
double PyOS_ascii_atof(const char *nptr) { return PyOS_ascii_strtod(nptr, NULL); }