@@ -219,3 +219,153 @@ called with a non-bytes parameter.
219219 reallocation fails, the original bytes object at *\* bytes * is deallocated,
220220 *\* bytes * is set to ``NULL ``, :exc: `MemoryError ` is set, and ``-1 `` is
221221 returned.
222+
223+ PyBytesWriter
224+ -------------
225+
226+ The :c:type: `PyBytesWriter ` API can be used to create a Python :class: `bytes `
227+ object.
228+
229+ .. versionadded :: next
230+
231+ .. c :type :: PyBytesWriter
232+
233+ A bytes writer instance.
234+
235+ The API is **not thread safe **: a writer should only be used by a single
236+ thread at the same time.
237+
238+ The instance must be destroyed by :c:func: `PyBytesWriter_Finish ` on
239+ success, or :c:func: `PyBytesWriter_Discard ` on error.
240+
241+
242+ Create, Finish, Discard
243+ ^^^^^^^^^^^^^^^^^^^^^^^
244+
245+ .. c :function :: PyBytesWriter* PyBytesWriter_Create (Py_ssize_t size)
246+
247+ Create a :c:type:`PyBytesWriter` to write *size* bytes.
248+
249+ If *size* is greater than zero, allocate *size* bytes, and set the
250+ writer size to *size*. The caller is responsible to write *size*
251+ bytes using :c:func:`PyBytesWriter_GetData`.
252+
253+ On error, set an exception and return NULL.
254+
255+ *size* must be positive or zero.
256+
257+ .. c:function:: PyObject* PyBytesWriter_Finish(PyBytesWriter *writer)
258+
259+ Finish a :c:type: `PyBytesWriter ` created by
260+ :c:func: `PyBytesWriter_Create `.
261+
262+ On success, return a Python :class: `bytes ` object.
263+ On error, set an exception and return ``NULL ``.
264+
265+ The writer instance is invalid after the call in any case.
266+ No API can be called on the writer after :c:func: `PyBytesWriter_Finish `.
267+
268+ .. c :function :: PyObject* PyBytesWriter_FinishWithSize (PyBytesWriter *writer, Py_ssize_t size)
269+
270+ Similar to :c:func: `PyBytesWriter_Finish `, but resize the writer
271+ to *size * bytes before creating the :class: `bytes ` object.
272+
273+ .. c :function :: PyObject* PyBytesWriter_FinishWithPointer (PyBytesWriter *writer, void *buf)
274+
275+ Similar to :c:func: `PyBytesWriter_Finish `, but resize the writer
276+ using *buf * pointer before creating the :class: `bytes ` object.
277+
278+ Set an exception and return ``NULL `` if *buf * pointer is outside the
279+ internal buffer bounds.
280+
281+ Function pseudo-code::
282+
283+ Py_ssize_t size = (char*)buf - (char*)PyBytesWriter_GetData(writer);
284+ return PyBytesWriter_FinishWithSize(writer, size);
285+
286+ .. c :function :: void PyBytesWriter_Discard (PyBytesWriter *writer)
287+
288+ Discard a :c:type: `PyBytesWriter ` created by :c:func: `PyBytesWriter_Create `.
289+
290+ Do nothing if *writer * is ``NULL ``.
291+
292+ The writer instance is invalid after the call.
293+ No API can be called on the writer after :c:func: `PyBytesWriter_Discard `.
294+
295+ High-level API
296+ ^^^^^^^^^^^^^^
297+
298+ .. c :function :: int PyBytesWriter_WriteBytes (PyBytesWriter *writer, const void *bytes, Py_ssize_t size)
299+
300+ Grow the *writer * internal buffer by *size * bytes,
301+ write *size * bytes of *bytes * at the *writer * end,
302+ and add *size * to the *writer * size.
303+
304+ If *size * is equal to ``-1 ``, call ``strlen(bytes) `` to get the
305+ string length.
306+
307+ On success, return ``0 ``.
308+ On error, set an exception and return ``-1 ``.
309+
310+
311+ Getters
312+ ^^^^^^^
313+
314+ .. c :function :: Py_ssize_t PyBytesWriter_GetSize (PyBytesWriter *writer)
315+
316+ Get the writer size.
317+
318+ .. c :function :: void * PyBytesWriter_GetData (PyBytesWriter *writer)
319+
320+ Get the writer data: start of the internal buffer.
321+
322+ The pointer is valid until :c:func: `PyBytesWriter_Finish ` or
323+ :c:func: `PyBytesWriter_Discard ` is called on *writer *.
324+
325+
326+ Low-level API
327+ ^^^^^^^^^^^^^
328+
329+ .. c :function :: int PyBytesWriter_Resize (PyBytesWriter *writer, Py_ssize_t size)
330+
331+ Resize the writer to *size * bytes. It can be used to enlarge or to
332+ shrink the writer.
333+
334+ Newly allocated bytes are left uninitialized.
335+
336+ On success, return ``0 ``.
337+ On error, set an exception and return ``-1 ``.
338+
339+ *size * must be positive or zero.
340+
341+ .. c :function :: int PyBytesWriter_Grow (PyBytesWriter *writer, Py_ssize_t grow)
342+
343+ Resize the writer by adding *grow * bytes to the current writer size.
344+
345+ Newly allocated bytes are left uninitialized.
346+
347+ On success, return ``0 ``.
348+ On error, set an exception and return ``-1 ``.
349+
350+ *size * can be negative to shrink the writer.
351+
352+ .. c :function :: void * PyBytesWriter_GrowAndUpdatePointer (PyBytesWriter *writer, Py_ssize_t size, void *buf)
353+
354+ Similar to :c:func: `PyBytesWriter_Grow `, but update also the *buf *
355+ pointer.
356+
357+ The *buf * pointer is moved if the internal buffer is moved in memory.
358+ The *buf * relative position within the internal buffer is left
359+ unchanged.
360+
361+ On error, set an exception and return ``NULL ``.
362+
363+ *buf * must not be ``NULL ``.
364+
365+ Function pseudo-code::
366+
367+ Py_ssize_t pos = (char*)buf - (char*)PyBytesWriter_GetData(writer);
368+ if (PyBytesWriter_Grow(writer, size) < 0) {
369+ return NULL;
370+ }
371+ return (char*)PyBytesWriter_GetData(writer) + pos;
0 commit comments