summaryrefslogtreecommitdiffstats
path: root/Objects
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 /Objects
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 'Objects')
-rw-r--r--Objects/bytearrayobject.c61
-rw-r--r--Objects/bytesobject.c46
-rw-r--r--Objects/unicodeobject.c12
3 files changed, 47 insertions, 72 deletions
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 74267cf..3849337 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -4,6 +4,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h"
+#include "pycore_bytesobject.h"
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_strhex.h" // _Py_strhex_with_sep()
#include "pycore_long.h" // _PyLong_FromUnsignedChar()
@@ -319,37 +320,16 @@ bytearray_iconcat(PyByteArrayObject *self, PyObject *other)
static PyObject *
bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count)
{
- PyByteArrayObject *result;
- Py_ssize_t mysize;
- Py_ssize_t size;
- const char *buf;
-
if (count < 0)
count = 0;
- mysize = Py_SIZE(self);
+ const Py_ssize_t mysize = Py_SIZE(self);
if (count > 0 && mysize > PY_SSIZE_T_MAX / count)
return PyErr_NoMemory();
- size = mysize * count;
- result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size);
- buf = PyByteArray_AS_STRING(self);
+ Py_ssize_t size = mysize * count;
+ PyByteArrayObject* result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size);
+ const char* buf = PyByteArray_AS_STRING(self);
if (result != NULL && size != 0) {
- if (mysize == 1)
- memset(result->ob_bytes, buf[0], size);
- else {
- Py_ssize_t i, j;
-
- i = 0;
- if (i < size) {
- memcpy(result->ob_bytes, buf, mysize);
- i = mysize;
- }
- // repeatedly double the number of bytes copied
- while (i < size) {
- j = Py_MIN(i, size - i);
- memcpy(result->ob_bytes + i, result->ob_bytes, j);
- i += j;
- }
- }
+ _PyBytes_Repeat(result->ob_bytes, size, buf, mysize);
}
return (PyObject *)result;
}
@@ -357,33 +337,22 @@ bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count)
static PyObject *
bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count)
{
- Py_ssize_t mysize;
- Py_ssize_t size;
- char *buf;
-
if (count < 0)
count = 0;
- mysize = Py_SIZE(self);
+ else if (count == 1) {
+ Py_INCREF(self);
+ return (PyObject*)self;
+ }
+
+ const Py_ssize_t mysize = Py_SIZE(self);
if (count > 0 && mysize > PY_SSIZE_T_MAX / count)
return PyErr_NoMemory();
- size = mysize * count;
+ const Py_ssize_t size = mysize * count;
if (PyByteArray_Resize((PyObject *)self, size) < 0)
return NULL;
- buf = PyByteArray_AS_STRING(self);
- if (mysize == 1)
- memset(buf, buf[0], size);
- else {
- Py_ssize_t i, j;
-
- i = mysize;
- // repeatedly double the number of bytes copied
- while (i < size) {
- j = Py_MIN(i, size - i);
- memcpy(buf + i, buf, j);
- i += j;
- }
- }
+ char* buf = PyByteArray_AS_STRING(self);
+ _PyBytes_Repeat(buf, size, buf, mysize);
Py_INCREF(self);
return (PyObject *)self;
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 56c941a..78c42c2 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -4,7 +4,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
-#include "pycore_bytesobject.h" // _PyBytes_Find()
+#include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_Repeat()
#include "pycore_bytes_methods.h" // _Py_bytes_startswith()
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_format.h" // F_LJUST
@@ -1421,8 +1421,6 @@ bytes_concat(PyObject *a, PyObject *b)
static PyObject *
bytes_repeat(PyBytesObject *a, Py_ssize_t n)
{
- Py_ssize_t i;
- Py_ssize_t j;
Py_ssize_t size;
PyBytesObject *op;
size_t nbytes;
@@ -1457,20 +1455,9 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS
op->ob_shash = -1;
_Py_COMP_DIAG_POP
op->ob_sval[size] = '\0';
- if (Py_SIZE(a) == 1 && n > 0) {
- memset(op->ob_sval, a->ob_sval[0] , n);
- return (PyObject *) op;
- }
- i = 0;
- if (i < size) {
- memcpy(op->ob_sval, a->ob_sval, Py_SIZE(a));
- i = Py_SIZE(a);
- }
- while (i < size) {
- j = (i <= size-i) ? i : size-i;
- memcpy(op->ob_sval+i, op->ob_sval, j);
- i += j;
- }
+
+ _PyBytes_Repeat(op->ob_sval, size, a->ob_sval, Py_SIZE(a));
+
return (PyObject *) op;
}
@@ -3528,3 +3515,28 @@ _PyBytesWriter_WriteBytes(_PyBytesWriter *writer, void *ptr,
return str;
}
+
+
+void
+_PyBytes_Repeat(char* dest, Py_ssize_t len_dest,
+ const char* src, Py_ssize_t len_src)
+{
+ if (len_dest == 0) {
+ return;
+ }
+ if (len_src == 1) {
+ memset(dest, src[0], len_dest);
+ }
+ else {
+ if (src != dest) {
+ memcpy(dest, src, len_src);
+ }
+ Py_ssize_t copied = len_src;
+ while (copied < len_dest) {
+ Py_ssize_t bytes_to_copy = Py_MIN(copied, len_dest - copied);
+ memcpy(dest + copied, dest, bytes_to_copy);
+ copied += bytes_to_copy;
+ }
+ }
+}
+
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index ce3ebce..72f9245 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -42,6 +42,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_atomic_funcs.h" // _Py_atomic_size_get()
+#include "pycore_bytesobject.h" // _PyBytes_Repeat()
#include "pycore_bytes_methods.h" // _Py_bytes_lower()
#include "pycore_format.h" // F_LJUST
#include "pycore_initconfig.h" // _PyStatus_OK()
@@ -12782,17 +12783,10 @@ unicode_repeat(PyObject *str, Py_ssize_t len)
}
}
else {
- /* number of characters copied this far */
- Py_ssize_t done = PyUnicode_GET_LENGTH(str);
Py_ssize_t char_size = PyUnicode_KIND(str);
char *to = (char *) PyUnicode_DATA(u);
- memcpy(to, PyUnicode_DATA(str),
- PyUnicode_GET_LENGTH(str) * char_size);
- while (done < nchars) {
- n = (done <= nchars-done) ? done : nchars-done;
- memcpy(to + (done * char_size), to, n * char_size);
- done += n;
- }
+ _PyBytes_Repeat(to, nchars * char_size, PyUnicode_DATA(str),
+ PyUnicode_GET_LENGTH(str) * char_size);
}
assert(_PyUnicode_CheckConsistency(u, 1));