Add a new PyUnicode_Fill() function

It is faster than the unicode_fill() function which was implemented in
formatter_unicode.c.
This commit is contained in:
Victor Stinner 2012-01-04 00:33:50 +01:00
parent 332503db07
commit 3fe553160c
4 changed files with 76 additions and 18 deletions

View File

@ -564,6 +564,21 @@ APIs:
.. versionadded:: 3.3 .. versionadded:: 3.3
.. c:function:: int PyUnicode_Fill(PyObject *unicode, Py_ssize_t start, \
Py_ssize_t length, Py_UCS4 fill_char)
Fill a string with a character: write *fill_char* into
``unicode[start:start+length]``.
Fail if *fill_char* is bigger than the string maximum character, or if the
string has more than 1 reference.
Return the number of written character, or return ``-1`` and raise an
exception on error.
.. versionadded:: 3.3
.. c:function:: int PyUnicode_WriteChar(PyObject *unicode, Py_ssize_t index, \ .. c:function:: int PyUnicode_WriteChar(PyObject *unicode, Py_ssize_t index, \
Py_UCS4 character) Py_UCS4 character)

View File

@ -623,11 +623,11 @@ PyAPI_FUNC(PyObject*) _PyUnicode_Copy(
#endif #endif
/* Copy character from one unicode object into another, this function performs /* Copy character from one unicode object into another, this function performs
character conversion when necessary and falls back to memcpy if possible. character conversion when necessary and falls back to memcpy() if possible.
Fail if to is too small (smaller than how_many or smaller than Fail if to is too small (smaller than *how_many* or smaller than
len(from)-from_start), or if kind(from[from_start:from_start+how_many]) > len(from)-from_start), or if kind(from[from_start:from_start+how_many]) >
kind(to), or if to has more than 1 reference. kind(to), or if *to* has more than 1 reference.
Return the number of written character, or return -1 and raise an exception Return the number of written character, or return -1 and raise an exception
on error. on error.
@ -650,6 +650,23 @@ PyAPI_FUNC(Py_ssize_t) PyUnicode_CopyCharacters(
); );
#endif #endif
/* Fill a string with a character: write fill_char into
unicode[start:start+length].
Fail if fill_char is bigger than the string maximum character, or if the
string has more than 1 reference.
Return the number of written character, or return -1 and raise an exception
on error. */
#ifndef Py_LIMITED_API
PyAPI_FUNC(Py_ssize_t) PyUnicode_Fill(
PyObject *unicode,
Py_ssize_t start,
Py_ssize_t length,
Py_UCS4 fill_char
);
#endif
/* Create a Unicode Object from the Py_UNICODE buffer u of the given /* Create a Unicode Object from the Py_UNICODE buffer u of the given
size. size.

View File

@ -9818,6 +9818,41 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
} \ } \
} while (0) } while (0)
Py_ssize_t
PyUnicode_Fill(PyObject *unicode, Py_ssize_t start, Py_ssize_t length,
Py_UCS4 fill_char)
{
Py_ssize_t maxlen;
enum PyUnicode_Kind kind;
void *data;
if (!PyUnicode_Check(unicode)) {
PyErr_BadInternalCall();
return -1;
}
if (PyUnicode_READY(unicode) == -1)
return -1;
if (unicode_check_modifiable(unicode))
return -1;
if (fill_char > PyUnicode_MAX_CHAR_VALUE(unicode)) {
PyErr_SetString(PyExc_ValueError,
"fill character is bigger than "
"the string maximum character");
return -1;
}
maxlen = PyUnicode_GET_LENGTH(unicode) - start;
length = Py_MIN(maxlen, length);
if (length <= 0)
return 0;
kind = PyUnicode_KIND(unicode);
data = PyUnicode_DATA(unicode);
FILL(kind, data, fill_char, start, length);
return length;
}
static PyObject * static PyObject *
pad(PyObject *self, pad(PyObject *self,
Py_ssize_t left, Py_ssize_t left,

View File

@ -317,15 +317,6 @@ calc_padding(Py_ssize_t nchars, Py_ssize_t width, Py_UCS4 align,
*n_rpadding = *n_total - nchars - *n_lpadding; *n_rpadding = *n_total - nchars - *n_lpadding;
} }
static void
unicode_fill(PyObject *str, Py_ssize_t start, Py_ssize_t end, Py_UCS4 ch)
{
int kind = PyUnicode_KIND(str);
void *data = PyUnicode_DATA(str);
while (start < end)
PyUnicode_WRITE(kind, data, start++, ch);
}
/* Do the padding, and return a pointer to where the caller-supplied /* Do the padding, and return a pointer to where the caller-supplied
content goes. */ content goes. */
static Py_ssize_t static Py_ssize_t
@ -335,12 +326,12 @@ fill_padding(PyObject *s, Py_ssize_t start, Py_ssize_t nchars,
{ {
/* Pad on left. */ /* Pad on left. */
if (n_lpadding) if (n_lpadding)
unicode_fill(s, start, start + n_lpadding, fill_char); PyUnicode_Fill(s, start, start + n_lpadding, fill_char);
/* Pad on right. */ /* Pad on right. */
if (n_rpadding) if (n_rpadding)
unicode_fill(s, start + nchars + n_lpadding, PyUnicode_Fill(s, start + nchars + n_lpadding,
start + nchars + n_lpadding + n_rpadding, fill_char); start + nchars + n_lpadding + n_rpadding, fill_char);
/* Pointer to the user content. */ /* Pointer to the user content. */
return start + n_lpadding; return start + n_lpadding;
@ -557,7 +548,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
#endif #endif
if (spec->n_lpadding) { if (spec->n_lpadding) {
unicode_fill(out, pos, pos + spec->n_lpadding, fill_char); PyUnicode_Fill(out, pos, pos + spec->n_lpadding, fill_char);
pos += spec->n_lpadding; pos += spec->n_lpadding;
} }
if (spec->n_sign == 1) { if (spec->n_sign == 1) {
@ -581,7 +572,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
pos += spec->n_prefix; pos += spec->n_prefix;
} }
if (spec->n_spadding) { if (spec->n_spadding) {
unicode_fill(out, pos, pos + spec->n_spadding, fill_char); PyUnicode_Fill(out, pos, pos + spec->n_spadding, fill_char);
pos += spec->n_spadding; pos += spec->n_spadding;
} }
@ -640,7 +631,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
} }
if (spec->n_rpadding) { if (spec->n_rpadding) {
unicode_fill(out, pos, pos + spec->n_rpadding, fill_char); PyUnicode_Fill(out, pos, pos + spec->n_rpadding, fill_char);
pos += spec->n_rpadding; pos += spec->n_rpadding;
} }
return 0; return 0;