diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2014-05-01 12:36:20 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2014-05-01 12:36:20 (GMT) |
commit | 161d695fb0455ce52530d4f43a9eac4c738f64bb (patch) | |
tree | f9624b632bd3d242af8b4f6147a817a04b9b7260 /Objects/bytesobject.c | |
parent | 991fd2888cd5ea88b1463a697c9890071231fe75 (diff) | |
download | cpython-161d695fb0455ce52530d4f43a9eac4c738f64bb.zip cpython-161d695fb0455ce52530d4f43a9eac4c738f64bb.tar.gz cpython-161d695fb0455ce52530d4f43a9eac4c738f64bb.tar.bz2 |
Issue #21377: PyBytes_Concat() now tries to concatenate in-place when the first argument has a reference count of 1.
Patch by Nikolaus Rath.
Diffstat (limited to 'Objects/bytesobject.c')
-rw-r--r-- | Objects/bytesobject.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index b93b9ef..b8bfd24 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2781,7 +2781,6 @@ PyTypeObject PyBytes_Type = { void PyBytes_Concat(PyObject **pv, PyObject *w) { - PyObject *v; assert(pv != NULL); if (*pv == NULL) return; @@ -2789,9 +2788,45 @@ PyBytes_Concat(PyObject **pv, PyObject *w) Py_CLEAR(*pv); return; } - v = bytes_concat(*pv, w); - Py_DECREF(*pv); - *pv = v; + + if (Py_REFCNT(*pv) == 1 && PyBytes_CheckExact(*pv)) { + /* 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 |