Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 37 additions & 20 deletions peps/pep-0782.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Create, Finish, Discard
Create a :c:type:`PyBytesWriter` to write *size* bytes.

If *size* is greater than zero, allocate *size* bytes for the
returned buffer.
returned buffer, and set the writer size to *size*.
Comment thread
vstinner marked this conversation as resolved.
Outdated

On error, set an exception and return NULL.

Expand All @@ -107,14 +107,14 @@ Create, Finish, Discard
Similar to :c:func:`PyBytesWriter_Finish`, but resize the writer
using *buf* pointer before creating the :class:`bytes` object.

Pseudo-code::
Set an exception and return ``NULL`` if *buf* pointer is outside the
internal buffer bounds.

Function pseudo-code::

Py_ssize_t size = (char*)buf - (char*)PyBytesWriter_GetData(writer);
return PyBytesWriter_FinishWithSize(writer, size);

Set an exception and return ``NULL`` if *buf* pointer is outside the
internal buffer bounds.

.. c:function:: void PyBytesWriter_Discard(PyBytesWriter *writer)

Discard a :c:type:`PyBytesWriter` created by :c:func:`PyBytesWriter_Create`.
Expand All @@ -128,7 +128,8 @@ High-level API

.. c:function:: int PyBytesWriter_WriteBytes(PyBytesWriter *writer, const void *bytes, Py_ssize_t size)

Write *size* bytes of *bytes* into the *writer*.
Write *size* bytes of *bytes* at the *writer* end,
and add *size* to the writer size.
Comment thread
vstinner marked this conversation as resolved.
Outdated

If *size* is equal to ``-1``, call ``strlen(bytes)`` to get the
string length.
Expand All @@ -138,8 +139,8 @@ High-level API

.. c:function:: int PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...)

Similar to ``PyBytes_FromFormat()``, but write the output directly
into the writer.
Similar to ``PyBytes_FromFormat()``, but write the output directly at
the writer end. Then add the written size to the writer size.

On success, return ``0``.
On error, set an exception and return ``-1``.
Expand All @@ -153,7 +154,7 @@ Getters

.. c:function:: void* PyBytesWriter_GetData(PyBytesWriter *writer)

Get the writer data.
Get the writer data: start of the internal buffer.

The pointer is valid until :c:func:`PyBytesWriter_Finish` or
:c:func:`PyBytesWriter_Discard` is called on *writer*.
Expand Down Expand Up @@ -182,16 +183,21 @@ Low-level API
On success, return ``0``.
On error, set an exception and return ``-1``.

*size* must be positive or zero.
*size* can be negative to shrink the writer.

.. c:function:: void* PyBytesWriter_GrowAndUpdatePointer(PyBytesWriter *writer, Py_ssize_t size, void *buf)

Similar to :c:func:`PyBytesWriter_Grow`, but update also the *buf*
pointer.

The *buf* pointer is moved if the internal buffer is moved in memory.
The *buf* position inside the internal buffer is left unchanged.
Comment thread
vstinner marked this conversation as resolved.
Outdated

On error, set an exception and return ``NULL``.

Pseudo-code::
*buf* must not be ``NULL``.

Function pseudo-code::

Py_ssize_t pos = (char*)buf - (char*)PyBytesWriter_GetData(writer);
if (PyBytesWriter_Grow(writer, size) < 0) {
Expand All @@ -207,6 +213,10 @@ Overallocation
overallocate the internal buffer to reduce the number of ``realloc()``
calls and so reduce memory copies.

:c:func:`PyBytesWriter_Finish` trims overallocations: it shrinks the
internal buffer to the exact size when creating the final :class:`bytes`
object.


Thread safety
-------------
Expand Down Expand Up @@ -315,17 +325,20 @@ Reference Implementation

`Pull request gh-131681 <https://github.com/python/cpython/pull/131681>`__.

The implementation allocates internally a :class:`bytes` object, so
:c:func:`PyBytesWriter_Finish` just returns the object without having
to copy memory.
Notes on the CPython reference implementation which are not part of the
Specification:

* The implementation allocates internally a :class:`bytes` object, so
:c:func:`PyBytesWriter_Finish` just returns the object without having
to copy memory.

For strings up to 256 bytes, a small internal raw buffer of bytes is
used. It avoids having to resize a :class:`bytes` object which is
inefficient. At the end, :c:func:`PyBytesWriter_Finish` creates the
:class:`bytes` object from this small buffer.
* For strings up to 256 bytes, a small internal raw buffer of bytes is
used. It avoids having to resize a :class:`bytes` object which is
inefficient. At the end, :c:func:`PyBytesWriter_Finish` creates the
:class:`bytes` object from this small buffer.

A free list is used to reduce the cost of allocating a
:c:type:`PyBytesWriter` on the heap memory.
* A free list is used to reduce the cost of allocating a
:c:type:`PyBytesWriter` on the heap memory.


Backwards Compatibility
Expand All @@ -334,6 +347,10 @@ Backwards Compatibility
There is no impact on the backward compatibility, only new APIs are
added.

``PyBytes_FromStringAndSize(NULL, size)`` and ``_PyBytes_Resize()`` APIs
are soft deprecated. No new warnings is emitted when these functions are
used and they are not planned for removal.


Prior Discussions
=================
Expand Down