bpo-47070: Add _PyBytes_Repeat() (GH-31999)

Use it where appropriate: the repeat functions of `array.array`, `bytes`, `bytearray`, and `str`.
This commit is contained in:
Pieter Eendebak 2022-03-28 10:43:45 +02:00 committed by GitHub
parent 86384cf83f
commit 850687df47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 103 deletions

View file

@ -10,6 +10,7 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_bytesobject.h" // _PyBytes_Repeat
#include "structmember.h" // PyMemberDef
#include <stddef.h> // offsetof()
#include <stddef.h>
@ -910,34 +911,24 @@ static PyObject *
array_repeat(arrayobject *a, Py_ssize_t n)
{
array_state *state = find_array_state_by_type(Py_TYPE(a));
Py_ssize_t size;
arrayobject *np;
Py_ssize_t oldbytes, newbytes;
if (n < 0)
n = 0;
if ((Py_SIZE(a) != 0) && (n > PY_SSIZE_T_MAX / Py_SIZE(a))) {
const Py_ssize_t array_length = Py_SIZE(a);
if ((array_length != 0) && (n > PY_SSIZE_T_MAX / array_length)) {
return PyErr_NoMemory();
}
size = Py_SIZE(a) * n;
np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
Py_ssize_t size = array_length * n;
arrayobject* np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
if (np == NULL)
return NULL;
if (size == 0)
return (PyObject *)np;
oldbytes = Py_SIZE(a) * a->ob_descr->itemsize;
newbytes = oldbytes * n;
/* this follows the code in unicode_repeat */
if (oldbytes == 1) {
memset(np->ob_item, a->ob_item[0], newbytes);
} else {
Py_ssize_t done = oldbytes;
memcpy(np->ob_item, a->ob_item, oldbytes);
while (done < newbytes) {
Py_ssize_t ncopy = (done <= newbytes-done) ? done : newbytes-done;
memcpy(np->ob_item+done, np->ob_item, ncopy);
done += ncopy;
}
}
const Py_ssize_t oldbytes = array_length * a->ob_descr->itemsize;
const Py_ssize_t newbytes = oldbytes * n;
_PyBytes_Repeat(np->ob_item, newbytes, a->ob_item, oldbytes);
return (PyObject *)np;
}
@ -1075,27 +1066,23 @@ array_inplace_concat(arrayobject *self, PyObject *bb)
static PyObject *
array_inplace_repeat(arrayobject *self, Py_ssize_t n)
{
char *items, *p;
Py_ssize_t size, i;
const Py_ssize_t array_size = Py_SIZE(self);
if (Py_SIZE(self) > 0) {
if (array_size > 0 && n != 1 ) {
if (n < 0)
n = 0;
if ((self->ob_descr->itemsize != 0) &&
(Py_SIZE(self) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
(array_size > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) {
return PyErr_NoMemory();
}
size = Py_SIZE(self) * self->ob_descr->itemsize;
Py_ssize_t size = array_size * self->ob_descr->itemsize;
if (n > 0 && size > PY_SSIZE_T_MAX / n) {
return PyErr_NoMemory();
}
if (array_resize(self, n * Py_SIZE(self)) == -1)
if (array_resize(self, n * array_size) == -1)
return NULL;
items = p = self->ob_item;
for (i = 1; i < n; i++) {
p += size;
memcpy(p, items, size);
}
_PyBytes_Repeat(self->ob_item, n*size, self->ob_item, size);
}
Py_INCREF(self);
return (PyObject *)self;