Issue #21377: PyBytes_Concat() now tries to concatenate in-place when the first argument has a reference count of 1.

Patch by Nikolaus Rath.
This commit is contained in:
Antoine Pitrou 2014-05-01 14:36:20 +02:00
parent 991fd2888c
commit 161d695fb0
2 changed files with 42 additions and 4 deletions

View File

@ -10,6 +10,9 @@ Release date: TBA
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #21377: PyBytes_Concat() now tries to concatenate in-place when the
first argument has a reference count of 1. Patch by Nikolaus Rath.
- Issue #20355: -W command line options now have higher priority than the - Issue #20355: -W command line options now have higher priority than the
PYTHONWARNINGS environment variable. Patch by Arfrever. PYTHONWARNINGS environment variable. Patch by Arfrever.

View File

@ -2781,7 +2781,6 @@ PyTypeObject PyBytes_Type = {
void void
PyBytes_Concat(PyObject **pv, PyObject *w) PyBytes_Concat(PyObject **pv, PyObject *w)
{ {
PyObject *v;
assert(pv != NULL); assert(pv != NULL);
if (*pv == NULL) if (*pv == NULL)
return; return;
@ -2789,9 +2788,45 @@ PyBytes_Concat(PyObject **pv, PyObject *w)
Py_CLEAR(*pv); Py_CLEAR(*pv);
return; return;
} }
v = bytes_concat(*pv, w);
Py_DECREF(*pv); if (Py_REFCNT(*pv) == 1 && PyBytes_CheckExact(*pv)) {
*pv = v; /* Only one reference, so we can resize in place */
size_t oldsize;
Py_buffer wb;
wb.len = -1;
if (_getbuffer(w, &wb) < 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(w)->tp_name, Py_TYPE(*pv)->tp_name);
Py_CLEAR(*pv);
return;
}
oldsize = PyBytes_GET_SIZE(*pv);
if (oldsize > PY_SSIZE_T_MAX - wb.len) {
PyErr_NoMemory();
goto error;
}
if (_PyBytes_Resize(pv, oldsize + wb.len) < 0)
goto error;
memcpy(PyBytes_AS_STRING(*pv) + oldsize, wb.buf, wb.len);
PyBuffer_Release(&wb);
return;
error:
PyBuffer_Release(&wb);
Py_CLEAR(*pv);
return;
}
else {
/* Multiple references, need to create new object */
PyObject *v;
v = bytes_concat(*pv, w);
Py_DECREF(*pv);
*pv = v;
}
} }
void void