diff options
author | Pieter Eendebak <pieter.eendebak@gmail.com> | 2022-03-28 10:43:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-28 04:43:45 -0400 |
commit | 850687df47b03e98c1433e6e70e71a8921eb4454 (patch) | |
tree | ac852f75711ba9aa84959895dbf6778f2cceb7bb /Modules/arraymodule.c | |
parent | 86384cf83f96fcaec03e2ad6516e2e24f20d3b92 (diff) | |
download | cpython-git-850687df47b03e98c1433e6e70e71a8921eb4454.tar.gz |
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/arraymodule.c')
-rw-r--r-- | Modules/arraymodule.c | 49 |
1 files changed, 18 insertions, 31 deletions
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 18991f8148..a04e6a4e07 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; |