]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-129813, PEP 782: Use PyBytesWriter in _PyBytes_FromList() (#138837)
authorVictor Stinner <vstinner@python.org>
Sat, 13 Sep 2025 17:23:57 +0000 (19:23 +0200)
committerGitHub <noreply@github.com>
Sat, 13 Sep 2025 17:23:57 +0000 (19:23 +0200)
Use the new public PyBytesWriter API in:

* _PyBytes_FromHex()
* _PyBytes_FromBuffer()
* _PyBytes_FromList()
* _PyBytes_FromTuple()
* _PyBytes_FromIterator()

Add _PyBytesWriter_ResizeAndUpdatePointer() and
_PyBytesWriter_GetAllocated() helper functions.

Objects/bytesobject.c

index 0bfdd727c7690386ed4866ce98820fc00adce6fb..7a59c76941254c89dbe7d56513f17fa1b304ff27 100644 (file)
@@ -36,6 +36,9 @@ class bytes "PyBytesObject *" "&PyBytes_Type"
 /* Forward declaration */
 Py_LOCAL_INLINE(Py_ssize_t) _PyBytesWriter_GetSize(_PyBytesWriter *writer,
                                                    char *str);
+static void* _PyBytesWriter_ResizeAndUpdatePointer(PyBytesWriter *writer,
+                                                   Py_ssize_t size, void *data);
+static Py_ssize_t _PyBytesWriter_GetAllocated(PyBytesWriter *writer);
 
 
 #define CHARACTERS _Py_SINGLETON(bytes_characters)
@@ -2531,17 +2534,13 @@ bytes_fromhex_impl(PyTypeObject *type, PyObject *string)
 PyObject*
 _PyBytes_FromHex(PyObject *string, int use_bytearray)
 {
-    char *buf;
     Py_ssize_t hexlen, invalid_char;
     unsigned int top, bot;
     const Py_UCS1 *str, *start, *end;
-    _PyBytesWriter writer;
+    PyBytesWriter *writer = NULL;
     Py_buffer view;
     view.obj = NULL;
 
-    _PyBytesWriter_Init(&writer);
-    writer.use_bytearray = use_bytearray;
-
     if (PyUnicode_Check(string)) {
         hexlen = PyUnicode_GET_LENGTH(string);
 
@@ -2577,10 +2576,16 @@ _PyBytes_FromHex(PyObject *string, int use_bytearray)
     }
 
     /* This overestimates if there are spaces */
-    buf = _PyBytesWriter_Alloc(&writer, hexlen / 2);
-    if (buf == NULL) {
+    if (use_bytearray) {
+        writer = _PyBytesWriter_CreateByteArray(hexlen / 2);
+    }
+    else {
+        writer = PyBytesWriter_Create(hexlen / 2);
+    }
+    if (writer == NULL) {
         goto release_buffer;
     }
+    char *buf = PyBytesWriter_GetData(writer);
 
     start = str;
     end = str + hexlen;
@@ -2619,7 +2624,7 @@ _PyBytes_FromHex(PyObject *string, int use_bytearray)
     if (view.obj != NULL) {
        PyBuffer_Release(&view);
     }
-    return _PyBytesWriter_Finish(&writer, buf);
+    return PyBytesWriter_FinishWithPointer(writer, buf);
 
   error:
     if (invalid_char == -1) {
@@ -2630,7 +2635,7 @@ _PyBytes_FromHex(PyObject *string, int use_bytearray)
                      "non-hexadecimal number found in "
                      "fromhex() arg at position %zd", invalid_char);
     }
-    _PyBytesWriter_Dealloc(&writer);
+    PyBytesWriter_Discard(writer);
 
   release_buffer:
     if (view.obj != NULL) {
@@ -2857,23 +2862,25 @@ bytes_new_impl(PyTypeObject *type, PyObject *x, const char *encoding,
 static PyObject*
 _PyBytes_FromBuffer(PyObject *x)
 {
-    PyObject *new;
     Py_buffer view;
-
     if (PyObject_GetBuffer(x, &view, PyBUF_FULL_RO) < 0)
         return NULL;
 
-    new = PyBytes_FromStringAndSize(NULL, view.len);
-    if (!new)
+    PyBytesWriter *writer = PyBytesWriter_Create(view.len);
+    if (writer == NULL) {
         goto fail;
-    if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval,
-                &view, view.len, 'C') < 0)
+    }
+
+    if (PyBuffer_ToContiguous(PyBytesWriter_GetData(writer),
+                              &view, view.len, 'C') < 0) {
         goto fail;
+    }
+
     PyBuffer_Release(&view);
-    return new;
+    return PyBytesWriter_Finish(writer);
 
 fail:
-    Py_XDECREF(new);
+    PyBytesWriter_Discard(writer);
     PyBuffer_Release(&view);
     return NULL;
 }
@@ -2881,23 +2888,18 @@ fail:
 static PyObject*
 _PyBytes_FromList(PyObject *x)
 {
-    Py_ssize_t i, size = PyList_GET_SIZE(x);
-    Py_ssize_t value;
-    char *str;
-    PyObject *item;
-    _PyBytesWriter writer;
-
-    _PyBytesWriter_Init(&writer);
-    str = _PyBytesWriter_Alloc(&writer, size);
-    if (str == NULL)
+    Py_ssize_t size = PyList_GET_SIZE(x);
+    PyBytesWriter *writer = PyBytesWriter_Create(size);
+    if (writer == NULL) {
         return NULL;
-    writer.overallocate = 1;
-    size = writer.allocated;
+    }
+    char *str = PyBytesWriter_GetData(writer);
+    size = _PyBytesWriter_GetAllocated(writer);
 
-    for (i = 0; i < PyList_GET_SIZE(x); i++) {
-        item = PyList_GET_ITEM(x, i);
+    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(x); i++) {
+        PyObject *item = PyList_GET_ITEM(x, i);
         Py_INCREF(item);
-        value = PyNumber_AsSsize_t(item, NULL);
+        Py_ssize_t value = PyNumber_AsSsize_t(item, NULL);
         Py_DECREF(item);
         if (value == -1 && PyErr_Occurred())
             goto error;
@@ -2909,33 +2911,33 @@ _PyBytes_FromList(PyObject *x)
         }
 
         if (i >= size) {
-            str = _PyBytesWriter_Resize(&writer, str, size+1);
-            if (str == NULL)
-                return NULL;
-            size = writer.allocated;
+            str = _PyBytesWriter_ResizeAndUpdatePointer(writer, size + 1, str);
+            if (str == NULL) {
+                goto error;
+            }
+            size = _PyBytesWriter_GetAllocated(writer);
         }
         *str++ = (char) value;
     }
-    return _PyBytesWriter_Finish(&writer, str);
+    return PyBytesWriter_FinishWithPointer(writer, str);
 
-  error:
-    _PyBytesWriter_Dealloc(&writer);
+error:
+    PyBytesWriter_Discard(writer);
     return NULL;
 }
 
 static PyObject*
 _PyBytes_FromTuple(PyObject *x)
 {
-    PyObject *bytes;
     Py_ssize_t i, size = PyTuple_GET_SIZE(x);
     Py_ssize_t value;
-    char *str;
     PyObject *item;
 
-    bytes = PyBytes_FromStringAndSize(NULL, size);
-    if (bytes == NULL)
+    PyBytesWriter *writer = PyBytesWriter_Create(size);
+    if (writer == NULL) {
         return NULL;
-    str = ((PyBytesObject *)bytes)->ob_sval;
+    }
+    char *str = PyBytesWriter_GetData(writer);
 
     for (i = 0; i < size; i++) {
         item = PyTuple_GET_ITEM(x, i);
@@ -2950,31 +2952,29 @@ _PyBytes_FromTuple(PyObject *x)
         }
         *str++ = (char) value;
     }
-    return bytes;
+    return PyBytesWriter_Finish(writer);
 
   error:
-    Py_DECREF(bytes);
+    PyBytesWriter_Discard(writer);
     return NULL;
 }
 
 static PyObject *
 _PyBytes_FromIterator(PyObject *it, PyObject *x)
 {
-    char *str;
     Py_ssize_t i, size;
-    _PyBytesWriter writer;
 
     /* For iterator version, create a bytes object and resize as needed */
     size = PyObject_LengthHint(x, 64);
     if (size == -1 && PyErr_Occurred())
         return NULL;
 
-    _PyBytesWriter_Init(&writer);
-    str = _PyBytesWriter_Alloc(&writer, size);
-    if (str == NULL)
+    PyBytesWriter *writer = PyBytesWriter_Create(size);
+    if (writer == NULL) {
         return NULL;
-    writer.overallocate = 1;
-    size = writer.allocated;
+    }
+    char *str = PyBytesWriter_GetData(writer);
+    size = _PyBytesWriter_GetAllocated(writer);
 
     /* Run the iterator to exhaustion */
     for (i = 0; ; i++) {
@@ -3004,18 +3004,18 @@ _PyBytes_FromIterator(PyObject *it, PyObject *x)
 
         /* Append the byte */
         if (i >= size) {
-            str = _PyBytesWriter_Resize(&writer, str, size+1);
-            if (str == NULL)
-                return NULL;
-            size = writer.allocated;
+            str = _PyBytesWriter_ResizeAndUpdatePointer(writer, size + 1, str);
+            if (str == NULL) {
+                goto error;
+            }
+            size = _PyBytesWriter_GetAllocated(writer);
         }
         *str++ = (char) value;
     }
-
-    return _PyBytesWriter_Finish(&writer, str);
+    return PyBytesWriter_FinishWithPointer(writer, str);
 
   error:
-    _PyBytesWriter_Dealloc(&writer);
+    PyBytesWriter_Discard(writer);
     return NULL;
 }
 
@@ -3983,6 +3983,13 @@ PyBytesWriter_GetSize(PyBytesWriter *writer)
 }
 
 
+static Py_ssize_t
+_PyBytesWriter_GetAllocated(PyBytesWriter *writer)
+{
+    return byteswriter_allocated(writer);
+}
+
+
 int
 PyBytesWriter_Resize(PyBytesWriter *writer, Py_ssize_t size)
 {
@@ -3998,6 +4005,18 @@ PyBytesWriter_Resize(PyBytesWriter *writer, Py_ssize_t size)
 }
 
 
+static void*
+_PyBytesWriter_ResizeAndUpdatePointer(PyBytesWriter *writer, Py_ssize_t size,
+                                      void *data)
+{
+    Py_ssize_t pos = (char*)data - byteswriter_data(writer);
+    if (PyBytesWriter_Resize(writer, size) < 0) {
+        return NULL;
+    }
+    return byteswriter_data(writer) + pos;
+}
+
+
 int
 PyBytesWriter_Grow(PyBytesWriter *writer, Py_ssize_t size)
 {