[Python-checkins] cpython: Issue #21377: PyBytes_Concat() now tries to concatenate in-place when the first

antoine.pitrou python-checkins at python.org
Thu May 1 14:36:29 CEST 2014


http://hg.python.org/cpython/rev/4ed1b6c7e2f3
changeset:   90530:4ed1b6c7e2f3
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Thu May 01 14:36:20 2014 +0200
summary:
  Issue #21377: PyBytes_Concat() now tries to concatenate in-place when the first argument has a reference count of 1.
Patch by Nikolaus Rath.

files:
  Misc/NEWS             |   3 ++
  Objects/bytesobject.c |  43 ++++++++++++++++++++++++++++--
  2 files changed, 42 insertions(+), 4 deletions(-)


diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 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
   PYTHONWARNINGS environment variable.  Patch by Arfrever.
 
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -2781,7 +2781,6 @@
 void
 PyBytes_Concat(PyObject **pv, PyObject *w)
 {
-    PyObject *v;
     assert(pv != NULL);
     if (*pv == NULL)
         return;
@@ -2789,9 +2788,45 @@
         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

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list