Issue #25349: Add fast path for b'%c' % int

Optimize also %% formater.
This commit is contained in:
Victor Stinner 2015-10-09 22:50:36 +02:00
parent be75b8cf23
commit 0cdad1e2bc
2 changed files with 17 additions and 10 deletions

View File

@ -300,6 +300,8 @@ class FormatTest(unittest.TestCase):
testcommon(b"%c", 7, b"\x07") testcommon(b"%c", 7, b"\x07")
testcommon(b"%c", b"Z", b"Z") testcommon(b"%c", b"Z", b"Z")
testcommon(b"%c", bytearray(b"Z"), b"Z") testcommon(b"%c", bytearray(b"Z"), b"Z")
testcommon(b"%5c", 65, b" A")
testcommon(b"%-5c", 65, b"A ")
# %b will insert a series of bytes, either from a type that supports # %b will insert a series of bytes, either from a type that supports
# the Py_buffer protocol, or something that has a __bytes__ method # the Py_buffer protocol, or something that has a __bytes__ method
class FakeBytes(object): class FakeBytes(object):

View File

@ -808,9 +808,8 @@ _PyBytes_Format(PyObject *format, PyObject *args)
fill = ' '; fill = ' ';
switch (c) { switch (c) {
case '%': case '%':
pbuf = "%"; *res++ = '%';
len = 1; continue;
break;
case 'r': case 'r':
// %r is only for 2/3 code; 3 only code should use %a // %r is only for 2/3 code; 3 only code should use %a
@ -842,9 +841,9 @@ _PyBytes_Format(PyObject *format, PyObject *args)
case 'x': case 'x':
case 'X': case 'X':
if (PyLong_CheckExact(v) if (PyLong_CheckExact(v)
&& width == -1 && prec == -1 && width == -1 && prec == -1
&& !(flags & (F_SIGN | F_BLANK)) && !(flags & (F_SIGN | F_BLANK))
&& c != 'X') && c != 'X')
{ {
/* Fast path */ /* Fast path */
int alternate = flags & F_ALT; int alternate = flags & F_ALT;
@ -869,7 +868,7 @@ _PyBytes_Format(PyObject *format, PyObject *args)
} }
/* Fast path */ /* Fast path */
writer.min_size -= 2; /* size preallocated by "%d" */ writer.min_size -= 2; /* size preallocated for "%d" */
res = _PyLong_FormatBytesWriter(&writer, res, res = _PyLong_FormatBytesWriter(&writer, res,
v, base, alternate); v, base, alternate);
if (res == NULL) if (res == NULL)
@ -898,7 +897,7 @@ _PyBytes_Format(PyObject *format, PyObject *args)
&& !(flags & (F_SIGN | F_BLANK))) && !(flags & (F_SIGN | F_BLANK)))
{ {
/* Fast path */ /* Fast path */
writer.min_size -= 2; /* size preallocated by "%f" */ writer.min_size -= 2; /* size preallocated for "%f" */
res = formatfloat(v, flags, prec, c, NULL, &writer, res); res = formatfloat(v, flags, prec, c, NULL, &writer, res);
if (res == NULL) if (res == NULL)
goto error; goto error;
@ -919,6 +918,11 @@ _PyBytes_Format(PyObject *format, PyObject *args)
len = byte_converter(v, &onechar); len = byte_converter(v, &onechar);
if (!len) if (!len)
goto error; goto error;
if (width == -1) {
/* Fast path */
*res++ = onechar;
continue;
}
break; break;
default: default:
@ -949,8 +953,9 @@ _PyBytes_Format(PyObject *format, PyObject *args)
alloc = width; alloc = width;
if (sign != 0 && len == width) if (sign != 0 && len == width)
alloc++; alloc++;
if (alloc > 1) { /* 2: size preallocated for %s */
res = _PyBytesWriter_Prepare(&writer, res, alloc - 1); if (alloc > 2) {
res = _PyBytesWriter_Prepare(&writer, res, alloc - 2);
if (res == NULL) if (res == NULL)
goto error; goto error;
} }