Skip to content

Commit 1feb88f

Browse files
committed
pythongh-125196: Add PyUnicodeWriter_Fill() function
1 parent f978fb4 commit 1feb88f

File tree

6 files changed

+72
-1
lines changed

6 files changed

+72
-1
lines changed

Doc/c-api/unicode.rst

+9
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,15 @@ object.
16631663
On success, return ``0``.
16641664
On error, set an exception, leave the writer unchanged, and return ``-1``.
16651665
1666+
.. c:function:: int PyUnicodeWriter_Fill(PyUnicodeWriter *writer, Py_ssize_t len, Py_UCS4 ch)
1667+
1668+
Write *len* times the single Unicode character *ch* into *writer*.
1669+
1670+
*len* must not be negative.
1671+
1672+
On success, return ``0``.
1673+
On error, set an exception, leave the writer unchanged, and return ``-1``.
1674+
16661675
.. c:function:: int PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...)
16671676
16681677
Similar to :c:func:`PyUnicode_FromFormat`, but write the output directly into *writer*.

Doc/whatsnew/3.14.rst

+1
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ New Features
639639
* :c:func:`PyUnicodeWriter_WriteStr`
640640
* :c:func:`PyUnicodeWriter_WriteRepr`
641641
* :c:func:`PyUnicodeWriter_WriteSubstring`
642+
* :c:func:`PyUnicodeWriter_Fill`
642643
* :c:func:`PyUnicodeWriter_Format`
643644
* :c:func:`PyUnicodeWriter_DecodeUTF8Stateful`
644645

Include/cpython/unicodeobject.h

+4
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,10 @@ PyAPI_FUNC(int) PyUnicodeWriter_WriteUCS4(
467467
PyUnicodeWriter *writer,
468468
Py_UCS4 *str,
469469
Py_ssize_t size);
470+
PyAPI_FUNC(int) PyUnicodeWriter_Fill(
471+
PyUnicodeWriter *writer,
472+
Py_ssize_t len,
473+
Py_UCS4 ch);
470474

471475
PyAPI_FUNC(int) PyUnicodeWriter_WriteStr(
472476
PyUnicodeWriter *writer,

Lib/test/test_capi/test_unicode.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -1744,8 +1744,11 @@ def test_basic(self):
17441744
# test PyUnicodeWriter_WriteRepr()
17451745
writer.write_repr("repr")
17461746

1747+
# test PyUnicodeWriter_Fill()
1748+
writer.fill(3, ".")
1749+
17471750
self.assertEqual(writer.finish(),
1748-
"var=long value 'repr'")
1751+
"var=long value 'repr'...")
17491752

17501753
def test_utf8(self):
17511754
writer = self.create_writer(0)
@@ -1867,6 +1870,17 @@ def test_substring_empty(self):
18671870
writer.write_substring("abc", 1, 1)
18681871
self.assertEqual(writer.finish(), '')
18691872

1873+
def test_fill(self):
1874+
writer = self.create_writer(0)
1875+
writer.fill(0, "#")
1876+
writer.write_char('(')
1877+
writer.fill(3, ".")
1878+
writer.write_char(')')
1879+
writer.fill(5, "-")
1880+
writer.write_char('.')
1881+
self.assertEqual(writer.finish(),
1882+
"(...)-----.")
1883+
18701884

18711885
@unittest.skipIf(ctypes is None, 'need ctypes')
18721886
class PyUnicodeWriterFormatTest(unittest.TestCase):

Modules/_testcapi/unicode.c

+22
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,27 @@ writer_finish(PyObject *self_raw, PyObject *Py_UNUSED(args))
510510
}
511511

512512

513+
static PyObject*
514+
writer_fill(PyObject *self_raw, PyObject *args)
515+
{
516+
WriterObject *self = (WriterObject *)self_raw;
517+
if (writer_check(self) < 0) {
518+
return NULL;
519+
}
520+
521+
Py_ssize_t len;
522+
int ch;
523+
if (!PyArg_ParseTuple(args, "nC", &len, &ch)) {
524+
return NULL;
525+
}
526+
527+
if (PyUnicodeWriter_Fill(self->writer, len, ch) < 0) {
528+
return NULL;
529+
}
530+
Py_RETURN_NONE;
531+
}
532+
533+
513534
static PyMethodDef writer_methods[] = {
514535
{"write_char", _PyCFunction_CAST(writer_write_char), METH_VARARGS},
515536
{"write_utf8", _PyCFunction_CAST(writer_write_utf8), METH_VARARGS},
@@ -519,6 +540,7 @@ static PyMethodDef writer_methods[] = {
519540
{"write_repr", _PyCFunction_CAST(writer_write_repr), METH_VARARGS},
520541
{"write_substring", _PyCFunction_CAST(writer_write_substring), METH_VARARGS},
521542
{"decodeutf8stateful", _PyCFunction_CAST(writer_decodeutf8stateful), METH_VARARGS},
543+
{"fill", _PyCFunction_CAST(writer_fill), METH_VARARGS},
522544
{"get_pointer", _PyCFunction_CAST(writer_get_pointer), METH_VARARGS},
523545
{"finish", _PyCFunction_CAST(writer_finish), METH_NOARGS},
524546
{NULL, NULL} /* sentinel */

Objects/unicodeobject.c

+21
Original file line numberDiff line numberDiff line change
@@ -13572,6 +13572,27 @@ PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
1357213572
return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
1357313573
}
1357413574

13575+
int
13576+
PyUnicodeWriter_Fill(PyUnicodeWriter *pub_writer, Py_ssize_t len, Py_UCS4 ch)
13577+
{
13578+
if (ch > MAX_UNICODE) {
13579+
PyErr_SetString(PyExc_ValueError,
13580+
"character must be in range(0x110000)");
13581+
return -1;
13582+
}
13583+
13584+
_PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
13585+
if (_PyUnicodeWriter_Prepare(writer, len, ch) < 0) {
13586+
return -1;
13587+
}
13588+
13589+
if (len > 0) {
13590+
_PyUnicode_FastFill(writer->buffer, writer->pos, len, ch);
13591+
writer->pos += len;
13592+
}
13593+
return 0;
13594+
}
13595+
1357513596
int
1357613597
_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, PyObject *str)
1357713598
{

0 commit comments

Comments
 (0)