Skip to content

Commit

Permalink
pythongh-125196: Add PyUnicodeWriter_Fill() function
Browse files Browse the repository at this point in the history
  • Loading branch information
vstinner committed Oct 9, 2024
1 parent f978fb4 commit cbc84c3
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 1 deletion.
9 changes: 9 additions & 0 deletions Doc/c-api/unicode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,15 @@ object.
On success, return ``0``.
On error, set an exception, leave the writer unchanged, and return ``-1``.
.. c:function:: int PyUnicodeWriter_Fill(PyUnicodeWriter *writer, Py_ssize_t len, Py_UCS4 ch)
Write *len* times the single Unicode character *ch* into *writer*.
*len* must not be negative.
On success, return ``0``.
On error, set an exception, leave the writer unchanged, and return ``-1``.
.. c:function:: int PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...)
Similar to :c:func:`PyUnicode_FromFormat`, but write the output directly into *writer*.
Expand Down
1 change: 1 addition & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ New Features
* :c:func:`PyUnicodeWriter_WriteStr`
* :c:func:`PyUnicodeWriter_WriteRepr`
* :c:func:`PyUnicodeWriter_WriteSubstring`
* :c:func:`PyUnicodeWriter_Fill`
* :c:func:`PyUnicodeWriter_Format`
* :c:func:`PyUnicodeWriter_DecodeUTF8Stateful`

Expand Down
4 changes: 4 additions & 0 deletions Include/cpython/unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,10 @@ PyAPI_FUNC(int) PyUnicodeWriter_WriteUCS4(
PyUnicodeWriter *writer,
Py_UCS4 *str,
Py_ssize_t size);
PyAPI_FUNC(int) PyUnicodeWriter_Fill(
PyUnicodeWriter *writer,
Py_ssize_t len,
Py_UCS4 ch);

PyAPI_FUNC(int) PyUnicodeWriter_WriteStr(
PyUnicodeWriter *writer,
Expand Down
16 changes: 15 additions & 1 deletion Lib/test/test_capi/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1744,8 +1744,11 @@ def test_basic(self):
# test PyUnicodeWriter_WriteRepr()
writer.write_repr("repr")

# test PyUnicodeWriter_Fill()
writer.fill(3, ".")

self.assertEqual(writer.finish(),
"var=long value 'repr'")
"var=long value 'repr'...")

def test_utf8(self):
writer = self.create_writer(0)
Expand Down Expand Up @@ -1867,6 +1870,17 @@ def test_substring_empty(self):
writer.write_substring("abc", 1, 1)
self.assertEqual(writer.finish(), '')

def test_fill(self):
writer = self.create_writer(0)
writer.fill(0, "#")
writer.write_char('(')
writer.fill(3, ".")
writer.write_char(')')
writer.fill(5, "-")
writer.write_char('.')
self.assertEqual(writer.finish(),
"(...)-----.")


@unittest.skipIf(ctypes is None, 'need ctypes')
class PyUnicodeWriterFormatTest(unittest.TestCase):
Expand Down
22 changes: 22 additions & 0 deletions Modules/_testcapi/unicode.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,27 @@ writer_finish(PyObject *self_raw, PyObject *Py_UNUSED(args))
}


static PyObject*
writer_fill(PyObject *self_raw, PyObject *args)
{
WriterObject *self = (WriterObject *)self_raw;
if (writer_check(self) < 0) {
return NULL;
}

Py_ssize_t len;
int ch;
if (!PyArg_ParseTuple(args, "nC", &len, &ch)) {
return NULL;
}

if (PyUnicodeWriter_Fill(self->writer, len, ch) < 0) {
return NULL;
}
Py_RETURN_NONE;
}


static PyMethodDef writer_methods[] = {
{"write_char", _PyCFunction_CAST(writer_write_char), METH_VARARGS},
{"write_utf8", _PyCFunction_CAST(writer_write_utf8), METH_VARARGS},
Expand All @@ -519,6 +540,7 @@ static PyMethodDef writer_methods[] = {
{"write_repr", _PyCFunction_CAST(writer_write_repr), METH_VARARGS},
{"write_substring", _PyCFunction_CAST(writer_write_substring), METH_VARARGS},
{"decodeutf8stateful", _PyCFunction_CAST(writer_decodeutf8stateful), METH_VARARGS},
{"fill", _PyCFunction_CAST(writer_fill), METH_VARARGS},
{"get_pointer", _PyCFunction_CAST(writer_get_pointer), METH_VARARGS},
{"finish", _PyCFunction_CAST(writer_finish), METH_NOARGS},
{NULL, NULL} /* sentinel */
Expand Down
27 changes: 27 additions & 0 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -13572,6 +13572,33 @@ PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
}

int
PyUnicodeWriter_Fill(PyUnicodeWriter *pub_writer, Py_ssize_t len, Py_UCS4 ch)
{
if (ch > MAX_UNICODE) {
PyErr_SetString(PyExc_ValueError,
"character must be in range(0x110000)");
return -1;
}
if (len < 0) {
PyErr_Format(PyExc_ValueError, "len must not be negative");
return -1;
}

if (len == 0) {
return 0;
}

_PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
if (_PyUnicodeWriter_Prepare(writer, len, ch) < 0) {
return -1;
}

_PyUnicode_FastFill(writer->buffer, writer->pos, len, ch);
writer->pos += len;
return 0;
}

int
_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, PyObject *str)
{
Expand Down

0 comments on commit cbc84c3

Please sign in to comment.