Kaydet (Commit) 1f932619 authored tarafından Serhiy Storchaka's avatar Serhiy Storchaka

Issue #27818: Speed up parsing width and precision in format() strings for

numbers.  Patch by Stefan Behnel.
üst 8631da64
...@@ -48,16 +48,17 @@ invalid_comma_type(Py_UCS4 presentation_type) ...@@ -48,16 +48,17 @@ invalid_comma_type(Py_UCS4 presentation_type)
returns -1 on error. returns -1 on error.
*/ */
static int static int
get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end, get_integer(PyObject *str, Py_ssize_t *ppos, Py_ssize_t end,
Py_ssize_t *result) Py_ssize_t *result)
{ {
Py_ssize_t accumulator, digitval; Py_ssize_t accumulator, digitval, pos = *ppos;
int numdigits; int numdigits;
int kind = PyUnicode_KIND(str);
void *data = PyUnicode_DATA(str);
accumulator = numdigits = 0; accumulator = numdigits = 0;
for (;;(*pos)++, numdigits++) { for (; pos < end; pos++, numdigits++) {
if (*pos >= end) digitval = Py_UNICODE_TODECIMAL(PyUnicode_READ(kind, data, pos));
break;
digitval = Py_UNICODE_TODECIMAL(PyUnicode_READ_CHAR(str, *pos));
if (digitval < 0) if (digitval < 0)
break; break;
/* /*
...@@ -69,10 +70,12 @@ get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end, ...@@ -69,10 +70,12 @@ get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end,
if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) { if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
"Too many decimal digits in format string"); "Too many decimal digits in format string");
*ppos = pos;
return -1; return -1;
} }
accumulator = accumulator * 10 + digitval; accumulator = accumulator * 10 + digitval;
} }
*ppos = pos;
*result = accumulator; *result = accumulator;
return numdigits; return numdigits;
} }
...@@ -150,9 +153,11 @@ parse_internal_render_format_spec(PyObject *format_spec, ...@@ -150,9 +153,11 @@ parse_internal_render_format_spec(PyObject *format_spec,
char default_align) char default_align)
{ {
Py_ssize_t pos = start; Py_ssize_t pos = start;
int kind = PyUnicode_KIND(format_spec);
void *data = PyUnicode_DATA(format_spec);
/* end-pos is used throughout this code to specify the length of /* end-pos is used throughout this code to specify the length of
the input string */ the input string */
#define READ_spec(index) PyUnicode_READ_CHAR(format_spec, index) #define READ_spec(index) PyUnicode_READ(kind, data, index)
Py_ssize_t consumed; Py_ssize_t consumed;
int align_specified = 0; int align_specified = 0;
...@@ -402,13 +407,15 @@ parse_number(PyObject *s, Py_ssize_t pos, Py_ssize_t end, ...@@ -402,13 +407,15 @@ parse_number(PyObject *s, Py_ssize_t pos, Py_ssize_t end,
Py_ssize_t *n_remainder, int *has_decimal) Py_ssize_t *n_remainder, int *has_decimal)
{ {
Py_ssize_t remainder; Py_ssize_t remainder;
int kind = PyUnicode_KIND(s);
void *data = PyUnicode_DATA(s);
while (pos<end && Py_ISDIGIT(PyUnicode_READ_CHAR(s, pos))) while (pos<end && Py_ISDIGIT(PyUnicode_READ(kind, data, pos)))
++pos; ++pos;
remainder = pos; remainder = pos;
/* Does remainder start with a decimal point? */ /* Does remainder start with a decimal point? */
*has_decimal = pos<end && PyUnicode_READ_CHAR(s, remainder) == '.'; *has_decimal = pos<end && PyUnicode_READ(kind, data, remainder) == '.';
/* Skip the decimal point. */ /* Skip the decimal point. */
if (*has_decimal) if (*has_decimal)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment