Skip to content

Commit 3fe5531

Browse files
author
Victor Stinner
committed
Add a new PyUnicode_Fill() function
It is faster than the unicode_fill() function which was implemented in formatter_unicode.c.
1 parent 332503d commit 3fe5531

4 files changed

Lines changed: 76 additions & 18 deletions

File tree

‎Doc/c-api/unicode.rst‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,21 @@ APIs:
564564
.. versionadded:: 3.3
565565
566566
567+
.. c:function:: int PyUnicode_Fill(PyObject *unicode, Py_ssize_t start, \
568+
Py_ssize_t length, Py_UCS4 fill_char)
569+
570+
Fill a string with a character: write *fill_char* into
571+
``unicode[start:start+length]``.
572+
573+
Fail if *fill_char* is bigger than the string maximum character, or if the
574+
string has more than 1 reference.
575+
576+
Return the number of written character, or return ``-1`` and raise an
577+
exception on error.
578+
579+
.. versionadded:: 3.3
580+
581+
567582
.. c:function:: int PyUnicode_WriteChar(PyObject *unicode, Py_ssize_t index, \
568583
Py_UCS4 character)
569584

‎Include/unicodeobject.h‎

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,11 +623,11 @@ PyAPI_FUNC(PyObject*) _PyUnicode_Copy(
623623
#endif
624624

625625
/* Copy character from one unicode object into another, this function performs
626-
character conversion when necessary and falls back to memcpy if possible.
626+
character conversion when necessary and falls back to memcpy() if possible.
627627
628-
Fail if to is too small (smaller than how_many or smaller than
628+
Fail if to is too small (smaller than *how_many* or smaller than
629629
len(from)-from_start), or if kind(from[from_start:from_start+how_many]) >
630-
kind(to), or if to has more than 1 reference.
630+
kind(to), or if *to* has more than 1 reference.
631631
632632
Return the number of written character, or return -1 and raise an exception
633633
on error.
@@ -650,6 +650,23 @@ PyAPI_FUNC(Py_ssize_t) PyUnicode_CopyCharacters(
650650
);
651651
#endif
652652

653+
/* Fill a string with a character: write fill_char into
654+
unicode[start:start+length].
655+
656+
Fail if fill_char is bigger than the string maximum character, or if the
657+
string has more than 1 reference.
658+
659+
Return the number of written character, or return -1 and raise an exception
660+
on error. */
661+
#ifndef Py_LIMITED_API
662+
PyAPI_FUNC(Py_ssize_t) PyUnicode_Fill(
663+
PyObject *unicode,
664+
Py_ssize_t start,
665+
Py_ssize_t length,
666+
Py_UCS4 fill_char
667+
);
668+
#endif
669+
653670
/* Create a Unicode Object from the Py_UNICODE buffer u of the given
654671
size.
655672

‎Objects/unicodeobject.c‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9818,6 +9818,41 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
98189818
} \
98199819
} while (0)
98209820

9821+
Py_ssize_t
9822+
PyUnicode_Fill(PyObject *unicode, Py_ssize_t start, Py_ssize_t length,
9823+
Py_UCS4 fill_char)
9824+
{
9825+
Py_ssize_t maxlen;
9826+
enum PyUnicode_Kind kind;
9827+
void *data;
9828+
9829+
if (!PyUnicode_Check(unicode)) {
9830+
PyErr_BadInternalCall();
9831+
return -1;
9832+
}
9833+
if (PyUnicode_READY(unicode) == -1)
9834+
return -1;
9835+
if (unicode_check_modifiable(unicode))
9836+
return -1;
9837+
9838+
if (fill_char > PyUnicode_MAX_CHAR_VALUE(unicode)) {
9839+
PyErr_SetString(PyExc_ValueError,
9840+
"fill character is bigger than "
9841+
"the string maximum character");
9842+
return -1;
9843+
}
9844+
9845+
maxlen = PyUnicode_GET_LENGTH(unicode) - start;
9846+
length = Py_MIN(maxlen, length);
9847+
if (length <= 0)
9848+
return 0;
9849+
9850+
kind = PyUnicode_KIND(unicode);
9851+
data = PyUnicode_DATA(unicode);
9852+
FILL(kind, data, fill_char, start, length);
9853+
return length;
9854+
}
9855+
98219856
static PyObject *
98229857
pad(PyObject *self,
98239858
Py_ssize_t left,

‎Python/formatter_unicode.c‎

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -317,15 +317,6 @@ calc_padding(Py_ssize_t nchars, Py_ssize_t width, Py_UCS4 align,
317317
*n_rpadding = *n_total - nchars - *n_lpadding;
318318
}
319319

320-
static void
321-
unicode_fill(PyObject *str, Py_ssize_t start, Py_ssize_t end, Py_UCS4 ch)
322-
{
323-
int kind = PyUnicode_KIND(str);
324-
void *data = PyUnicode_DATA(str);
325-
while (start < end)
326-
PyUnicode_WRITE(kind, data, start++, ch);
327-
}
328-
329320
/* Do the padding, and return a pointer to where the caller-supplied
330321
content goes. */
331322
static Py_ssize_t
@@ -335,12 +326,12 @@ fill_padding(PyObject *s, Py_ssize_t start, Py_ssize_t nchars,
335326
{
336327
/* Pad on left. */
337328
if (n_lpadding)
338-
unicode_fill(s, start, start + n_lpadding, fill_char);
329+
PyUnicode_Fill(s, start, start + n_lpadding, fill_char);
339330

340331
/* Pad on right. */
341332
if (n_rpadding)
342-
unicode_fill(s, start + nchars + n_lpadding,
343-
start + nchars + n_lpadding + n_rpadding, fill_char);
333+
PyUnicode_Fill(s, start + nchars + n_lpadding,
334+
start + nchars + n_lpadding + n_rpadding, fill_char);
344335

345336
/* Pointer to the user content. */
346337
return start + n_lpadding;
@@ -557,7 +548,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
557548
#endif
558549

559550
if (spec->n_lpadding) {
560-
unicode_fill(out, pos, pos + spec->n_lpadding, fill_char);
551+
PyUnicode_Fill(out, pos, pos + spec->n_lpadding, fill_char);
561552
pos += spec->n_lpadding;
562553
}
563554
if (spec->n_sign == 1) {
@@ -581,7 +572,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
581572
pos += spec->n_prefix;
582573
}
583574
if (spec->n_spadding) {
584-
unicode_fill(out, pos, pos + spec->n_spadding, fill_char);
575+
PyUnicode_Fill(out, pos, pos + spec->n_spadding, fill_char);
585576
pos += spec->n_spadding;
586577
}
587578

@@ -640,7 +631,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
640631
}
641632

642633
if (spec->n_rpadding) {
643-
unicode_fill(out, pos, pos + spec->n_rpadding, fill_char);
634+
PyUnicode_Fill(out, pos, pos + spec->n_rpadding, fill_char);
644635
pos += spec->n_rpadding;
645636
}
646637
return 0;

0 commit comments

Comments
 (0)