Issue #11856: Speed up parsing of JSON numbers.

This commit is contained in:
Antoine Pitrou 2011-04-25 19:16:06 +02:00
parent 54afa5504c
commit f645451d78
2 changed files with 33 additions and 15 deletions

View File

@ -113,6 +113,8 @@ Core and Builtins
Library
-------
- Issue #11856: Speed up parsing of JSON numbers.
- Issue #11005: threading.RLock()._release_save() raises a RuntimeError if the
lock was not acquired.

View File

@ -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;