summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorPieter Eendebak <pieter.eendebak@gmail.com>2022-03-28 08:43:45 (GMT)
committerGitHub <noreply@github.com>2022-03-28 08:43:45 (GMT)
commit850687df47b03e98c1433e6e70e71a8921eb4454 (patch)
treeac852f75711ba9aa84959895dbf6778f2cceb7bb /Modules
parent86384cf83f96fcaec03e2ad6516e2e24f20d3b92 (diff)
downloadcpython-850687df47b03e98c1433e6e70e71a8921eb4454.zip
cpython-850687df47b03e98c1433e6e70e71a8921eb4454.tar.gz
cpython-850687df47b03e98c1433e6e70e71a8921eb4454.tar.bz2
bpo-47070: Add _PyBytes_Repeat() (GH-31999)
Use it where appropriate: the repeat functions of `array.array`, `bytes`, `bytearray`, and `str`.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/arraymodule.c49
1 files changed, 18 insertions, 31 deletions
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 18991f8..a04e6a4 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -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;