summaryrefslogtreecommitdiffstats
path: root/Modules/_json.c
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2011-04-25 17:16:06 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2011-04-25 17:16:06 (GMT)
commitf645451d78f046c4df47ed420f7c38948f81eeb0 (patch)
treee57a93733e0f831237fc2c7e6f247efc7d94654a /Modules/_json.c
parent54afa5504cfbe192f5466ff9edc291b10736dfdd (diff)
downloadcpython-f645451d78f046c4df47ed420f7c38948f81eeb0.zip
cpython-f645451d78f046c4df47ed420f7c38948f81eeb0.tar.gz
cpython-f645451d78f046c4df47ed420f7c38948f81eeb0.tar.bz2
Issue #11856: Speed up parsing of JSON numbers.
Diffstat (limited to 'Modules/_json.c')
-rw-r--r--Modules/_json.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/Modules/_json.c b/Modules/_json.c
index 6c1a194..9177094 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -842,7 +842,8 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_
Py_ssize_t idx = start;
int is_float = 0;
PyObject *rval;
- PyObject *numstr;
+ PyObject *numstr = NULL;
+ PyObject *custom_func;
/* read a sign if it's there, make sure it's not the end of the string */
if (str[idx] == '-') {
@@ -895,22 +896,37 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_
}
}
- /* copy the section we determined to be a number */
- numstr = PyUnicode_FromUnicode(&str[start], idx - start);
- if (numstr == NULL)
- return NULL;
- if (is_float) {
- /* parse as a float using a fast path if available, otherwise call user defined method */
- if (s->parse_float != (PyObject *)&PyFloat_Type) {
- rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL);
- }
- else {
- rval = PyFloat_FromString(numstr);
- }
+ if (is_float && s->parse_float != (PyObject *)&PyFloat_Type)
+ custom_func = s->parse_float;
+ else if (!is_float && s->parse_int != (PyObject *) &PyLong_Type)
+ custom_func = s->parse_int;
+ else
+ custom_func = NULL;
+
+ if (custom_func) {
+ /* copy the section we determined to be a number */
+ numstr = PyUnicode_FromUnicode(&str[start], idx - start);
+ if (numstr == NULL)
+ return NULL;
+ rval = PyObject_CallFunctionObjArgs(custom_func, numstr, NULL);
}
else {
- /* no fast path for unicode -> int, just call */
- rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL);
+ Py_ssize_t i, n;
+ char *buf;
+ /* Straight conversion to ASCII, to avoid costly conversion of
+ decimal unicode digits (which cannot appear here) */
+ n = idx - start;
+ numstr = PyBytes_FromStringAndSize(NULL, n);
+ if (numstr == NULL)
+ return NULL;
+ buf = PyBytes_AS_STRING(numstr);
+ for (i = 0; i < n; i++) {
+ buf[i] = (char) str[i + start];
+ }
+ if (is_float)
+ rval = PyFloat_FromString(numstr);
+ else
+ rval = PyLong_FromString(buf, NULL, 10);
}
Py_DECREF(numstr);
*next_idx_ptr = idx;