summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-05-03 20:33:40 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-05-03 20:33:40 (GMT)
commit725bfd8489e444aedd8dfd686a27ffc308657155 (patch)
tree99d4e0cc2953794a67a5cff491e1897723a119ff /Modules
parent75930f85df76472686a8c4eb587a2a70562f61fe (diff)
downloadcpython-725bfd8489e444aedd8dfd686a27ffc308657155.zip
cpython-725bfd8489e444aedd8dfd686a27ffc308657155.tar.gz
cpython-725bfd8489e444aedd8dfd686a27ffc308657155.tar.bz2
Issue #5914: Add new C-API function PyOS_string_to_double, to complement
PyOS_double_to_string, and deprecate PyOS_ascii_strtod and PyOS_ascii_atof.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_pickle.c14
-rw-r--r--Modules/_testcapimodule.c49
2 files changed, 56 insertions, 7 deletions
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 754d132..8adc136 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -2971,20 +2971,20 @@ load_float(UnpicklerObject *self)
return bad_readline();
errno = 0;
- d = PyOS_ascii_strtod(s, &endptr);
-
- if ((errno == ERANGE && !(fabs(d) <= 1.0)) ||
- (endptr[0] != '\n') || (endptr[1] != '\0')) {
+ d = PyOS_string_to_double(s, &endptr, PyExc_OverflowError);
+ if (d == -1.0 && PyErr_Occurred())
+ return -1;
+ if ((endptr[0] != '\n') || (endptr[1] != '\0')) {
PyErr_SetString(PyExc_ValueError, "could not convert string to float");
return -1;
}
-
- if ((value = PyFloat_FromDouble(d)) == NULL)
+ value = PyFloat_FromDouble(d);
+ if (value == NULL)
return -1;
PDATA_PUSH(self->stack, value, -1);
return 0;
-}
+ }
static int
load_binfloat(UnpicklerObject *self)
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 4ba4898..1cbb825 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -1045,6 +1045,54 @@ test_with_docstring(PyObject *self)
Py_RETURN_NONE;
}
+/* Test PyOS_string_to_double. */
+static PyObject *
+test_string_to_double(PyObject *self) {
+ double result;
+ char *msg;
+
+#define CHECK_STRING(STR, expected) \
+ result = PyOS_string_to_double(STR, NULL, NULL); \
+ if (result == -1.0 && PyErr_Occurred()) \
+ return NULL; \
+ if (result != expected) { \
+ msg = "conversion of " STR " to float failed"; \
+ goto fail; \
+ }
+
+#define CHECK_INVALID(STR) \
+ result = PyOS_string_to_double(STR, NULL, NULL); \
+ if (result == -1.0 && PyErr_Occurred()) { \
+ if (PyErr_ExceptionMatches(PyExc_ValueError)) \
+ PyErr_Clear(); \
+ else \
+ return NULL; \
+ } \
+ else { \
+ msg = "conversion of " STR " didn't raise ValueError"; \
+ goto fail; \
+ }
+
+ CHECK_STRING("0.1", 0.1);
+ CHECK_STRING("1.234", 1.234);
+ CHECK_STRING("-1.35", -1.35);
+ CHECK_STRING(".1e01", 1.0);
+ CHECK_STRING("2.e-2", 0.02);
+
+ CHECK_INVALID(" 0.1");
+ CHECK_INVALID("\t\n-3");
+ CHECK_INVALID(".123 ");
+ CHECK_INVALID("3\n");
+ CHECK_INVALID("123abc");
+
+ Py_RETURN_NONE;
+ fail:
+ return raiseTestError("test_string_to_double", msg);
+#undef CHECK_STRING
+#undef CHECK_INVALID
+}
+
+
#ifdef HAVE_GETTIMEOFDAY
/* Profiling of integer performance */
static void print_delta(int test, struct timeval *s, struct timeval *e)
@@ -1223,6 +1271,7 @@ static PyMethodDef TestMethods[] = {
{"test_empty_argparse", (PyCFunction)test_empty_argparse,METH_NOARGS},
{"test_null_strings", (PyCFunction)test_null_strings, METH_NOARGS},
{"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS},
+ {"test_string_to_double", (PyCFunction)test_string_to_double, METH_NOARGS},
{"test_with_docstring", (PyCFunction)test_with_docstring, METH_NOARGS,
PyDoc_STR("This is a pretty normal docstring.")},