Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-125196: Add PyUnicodeWriter_Fill() function #125201

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add :c:func:`PyUnicodeWriter_Fill` function. Patch by Victor Stinner.
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 (len < 0) {
PyErr_Format(PyExc_ValueError, "len must not be negative");
return -1;
}
if (ch > MAX_UNICODE) {
PyErr_SetString(PyExc_ValueError,
"character must be in range(0x110000)");
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
Loading