@@ -219,3 +219,162 @@ 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+ .. c :function :: int PyBytesWriter_Format (PyBytesWriter *writer, const char *format, ...)
311+
312+ Similar to :c:func: `PyBytes_FromFormat `, but write the output directly at
313+ the writer end. Grow the writer internal buffer on demand. Then add the
314+ written size to the writer size.
315+
316+ On success, return ``0 ``.
317+ On error, set an exception and return ``-1 ``.
318+
319+
320+ Getters
321+ ^^^^^^^
322+
323+ .. c :function :: Py_ssize_t PyBytesWriter_GetSize (PyBytesWriter *writer)
324+
325+ Get the writer size.
326+
327+ .. c :function :: void * PyBytesWriter_GetData (PyBytesWriter *writer)
328+
329+ Get the writer data: start of the internal buffer.
330+
331+ The pointer is valid until :c:func: `PyBytesWriter_Finish ` or
332+ :c:func: `PyBytesWriter_Discard ` is called on *writer *.
333+
334+
335+ Low-level API
336+ ^^^^^^^^^^^^^
337+
338+ .. c :function :: int PyBytesWriter_Resize (PyBytesWriter *writer, Py_ssize_t size)
339+
340+ Resize the writer to *size * bytes. It can be used to enlarge or to
341+ shrink the writer.
342+
343+ Newly allocated bytes are left uninitialized.
344+
345+ On success, return ``0 ``.
346+ On error, set an exception and return ``-1 ``.
347+
348+ *size * must be positive or zero.
349+
350+ .. c :function :: int PyBytesWriter_Grow (PyBytesWriter *writer, Py_ssize_t grow)
351+
352+ Resize the writer by adding *grow * bytes to the current writer size.
353+
354+ Newly allocated bytes are left uninitialized.
355+
356+ On success, return ``0 ``.
357+ On error, set an exception and return ``-1 ``.
358+
359+ *size * can be negative to shrink the writer.
360+
361+ .. c :function :: void * PyBytesWriter_GrowAndUpdatePointer (PyBytesWriter *writer, Py_ssize_t size, void *buf)
362+
363+ Similar to :c:func: `PyBytesWriter_Grow `, but update also the *buf *
364+ pointer.
365+
366+ The *buf * pointer is moved if the internal buffer is moved in memory.
367+ The *buf * relative position within the internal buffer is left
368+ unchanged.
369+
370+ On error, set an exception and return ``NULL ``.
371+
372+ *buf * must not be ``NULL ``.
373+
374+ Function pseudo-code::
375+
376+ Py_ssize_t pos = (char*)buf - (char*)PyBytesWriter_GetData(writer);
377+ if (PyBytesWriter_Grow(writer, size) < 0) {
378+ return NULL;
379+ }
380+ return (char*)PyBytesWriter_GetData(writer) + pos;
0 commit comments