From 2c789a9db9b6fba42722fb0c179d654a387950d1 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 2 Apr 2024 21:06:08 +0200 Subject: [PATCH 01/21] Adapt byte*.startswith --- Objects/bytearrayobject.c | 20 ++++++++++++--- Objects/bytes_methods.c | 8 ------ Objects/bytesobject.c | 20 ++++++++++++--- Objects/clinic/bytearrayobject.c.h | 41 +++++++++++++++++++++++++++++- Objects/clinic/bytesobject.c.h | 41 +++++++++++++++++++++++++++++- 5 files changed, 114 insertions(+), 16 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 5e3b3affbc76c5..48a6eb018befec 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1186,8 +1186,23 @@ bytearray_contains(PyObject *self, PyObject *arg) return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg); } +/*[clinic input] +@text_signature "($self, prefix[, start[, end]], /)" +bytearray.startswith + + *args: object + / + +Return True if B starts with the specified prefix, False otherwise. + +With optional start, test B beginning at that position. +With optional end, stop comparing B at that position. +prefix can also be a tuple of bytes to try. +[clinic start generated code]*/ + static PyObject * -bytearray_startswith(PyByteArrayObject *self, PyObject *args) +bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=cfec6eb4d8d465b2 input=53a7036eaff0525e]*/ { return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } @@ -2249,8 +2264,7 @@ bytearray_methods[] = { BYTEARRAY_RSTRIP_METHODDEF BYTEARRAY_SPLIT_METHODDEF BYTEARRAY_SPLITLINES_METHODDEF - {"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS , - _Py_startswith__doc__}, + BYTEARRAY_STARTSWITH_METHODDEF BYTEARRAY_STRIP_METHODDEF {"swapcase", stringlib_swapcase, METH_NOARGS, _Py_swapcase__doc__}, diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index c1bc6383df30ce..a18a2aaa332688 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -807,14 +807,6 @@ _Py_bytes_tailmatch(const char *str, Py_ssize_t len, return PyBool_FromLong(result); } -PyDoc_STRVAR_shared(_Py_startswith__doc__, -"B.startswith(prefix[, start[, end]]) -> bool\n\ -\n\ -Return True if B starts with the specified prefix, False otherwise.\n\ -With optional start, test B beginning at that position.\n\ -With optional end, stop comparing B at that position.\n\ -prefix can also be a tuple of bytes to try."); - PyObject * _Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) { diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 256e01f54f0782..5836ad9a628829 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2285,8 +2285,23 @@ bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix) return PyBytes_FromStringAndSize(self_start, self_len); } +/*[clinic input] +@text_signature "($self, prefix[, start[, end]], /)" +bytes.startswith + + *args: object + / + +Return True if B starts with the specified prefix, False otherwise. + +With optional start, test B beginning at that position. +With optional end, stop comparing B at that position. +prefix can also be a tuple of bytes to try. +[clinic start generated code]*/ + static PyObject * -bytes_startswith(PyBytesObject *self, PyObject *args) +bytes_startswith_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=172340dafc2f3c97 input=87559404108dcdfc]*/ { return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } @@ -2532,8 +2547,7 @@ bytes_methods[] = { BYTES_RSTRIP_METHODDEF BYTES_SPLIT_METHODDEF BYTES_SPLITLINES_METHODDEF - {"startswith", (PyCFunction)bytes_startswith, METH_VARARGS, - _Py_startswith__doc__}, + BYTES_STARTSWITH_METHODDEF BYTES_STRIP_METHODDEF {"swapcase", stringlib_swapcase, METH_NOARGS, _Py_swapcase__doc__}, diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index d95245067e2608..5ede27b998136d 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -137,6 +137,45 @@ bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) return bytearray_copy_impl(self); } +PyDoc_STRVAR(bytearray_startswith__doc__, +"startswith($self, prefix[, start[, end]], /)\n" +"--\n" +"\n" +"Return True if B starts with the specified prefix, False otherwise.\n" +"\n" +"With optional start, test B beginning at that position.\n" +"With optional end, stop comparing B at that position.\n" +"prefix can also be a tuple of bytes to try."); + +#define BYTEARRAY_STARTSWITH_METHODDEF \ + {"startswith", _PyCFunction_CAST(bytearray_startswith), METH_FASTCALL, bytearray_startswith__doc__}, + +static PyObject * +bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_startswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("startswith", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_startswith_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytearray_removeprefix__doc__, "removeprefix($self, prefix, /)\n" "--\n" @@ -1261,4 +1300,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=0797a5e03cda2a16 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=01c78d65700f652d input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 1e45be3e7aefb3..e4b7211382035d 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -652,6 +652,45 @@ bytes_removesuffix(PyBytesObject *self, PyObject *arg) return return_value; } +PyDoc_STRVAR(bytes_startswith__doc__, +"startswith($self, prefix[, start[, end]], /)\n" +"--\n" +"\n" +"Return True if B starts with the specified prefix, False otherwise.\n" +"\n" +"With optional start, test B beginning at that position.\n" +"With optional end, stop comparing B at that position.\n" +"prefix can also be a tuple of bytes to try."); + +#define BYTES_STARTSWITH_METHODDEF \ + {"startswith", _PyCFunction_CAST(bytes_startswith), METH_FASTCALL, bytes_startswith__doc__}, + +static PyObject * +bytes_startswith_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_startswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("startswith", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_startswith_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytes_decode__doc__, "decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" @@ -1029,4 +1068,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=8a49dbbd78914a6f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9148bed58e358e53 input=a9049054013a1b77]*/ From 132080c20e9cfadc64f2b650e93c33e7cb9862bf Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 2 Apr 2024 21:30:28 +0200 Subject: [PATCH 02/21] Adapt byte*.endswith --- Objects/bytearrayobject.c | 17 ++++++++++--- Objects/bytes_methods.c | 8 ------ Objects/bytesobject.c | 17 ++++++++++--- Objects/clinic/bytearrayobject.c.h | 41 +++++++++++++++++++++++++++++- Objects/clinic/bytesobject.c.h | 41 +++++++++++++++++++++++++++++- 5 files changed, 108 insertions(+), 16 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 48a6eb018befec..dc173d58cbf7b5 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1207,8 +1207,20 @@ bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args) return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, prefix[, start[, end]], /)" +bytearray.endswith = bytearray.startswith + +Return True if B ends with the specified prefix, False otherwise. + +With optional start, test B beginning at that position. +With optional end, stop comparing B at that position. +prefix can also be a tuple of bytes to try. +[clinic start generated code]*/ + static PyObject * -bytearray_endswith(PyByteArrayObject *self, PyObject *args) +bytearray_endswith_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=2d9b7e94ef2b142a input=2a2ba6955504ae08]*/ { return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } @@ -2218,8 +2230,7 @@ bytearray_methods[] = { {"count", (PyCFunction)bytearray_count, METH_VARARGS, _Py_count__doc__}, BYTEARRAY_DECODE_METHODDEF - {"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS, - _Py_endswith__doc__}, + BYTEARRAY_ENDSWITH_METHODDEF STRINGLIB_EXPANDTABS_METHODDEF BYTEARRAY_EXTEND_METHODDEF {"find", (PyCFunction)bytearray_find, METH_VARARGS, diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index a18a2aaa332688..4a778ef4a82b22 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -813,14 +813,6 @@ _Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) return _Py_bytes_tailmatch(str, len, "startswith", args, -1); } -PyDoc_STRVAR_shared(_Py_endswith__doc__, -"B.endswith(suffix[, start[, end]]) -> bool\n\ -\n\ -Return True if B ends with the specified suffix, False otherwise.\n\ -With optional start, test B beginning at that position.\n\ -With optional end, stop comparing B at that position.\n\ -suffix can also be a tuple of bytes to try."); - PyObject * _Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args) { diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 5836ad9a628829..b105995e6168fa 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2306,8 +2306,20 @@ bytes_startswith_impl(PyBytesObject *self, PyObject *args) return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, prefix[, start[, end]], /)" +bytes.endswith = bytes.startswith + +Return True if B ends with the specified prefix, False otherwise. + +With optional start, test B beginning at that position. +With optional end, stop comparing B at that position. +prefix can also be a tuple of bytes to try. +[clinic start generated code]*/ + static PyObject * -bytes_endswith(PyBytesObject *self, PyObject *args) +bytes_endswith_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=b462e732a996e3eb input=3f7fc635440e2ab5]*/ { return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } @@ -2506,8 +2518,7 @@ bytes_methods[] = { {"count", (PyCFunction)bytes_count, METH_VARARGS, _Py_count__doc__}, BYTES_DECODE_METHODDEF - {"endswith", (PyCFunction)bytes_endswith, METH_VARARGS, - _Py_endswith__doc__}, + BYTES_ENDSWITH_METHODDEF STRINGLIB_EXPANDTABS_METHODDEF {"find", (PyCFunction)bytes_find, METH_VARARGS, _Py_find__doc__}, diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 5ede27b998136d..addef9c995c51a 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -176,6 +176,45 @@ bytearray_startswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t return return_value; } +PyDoc_STRVAR(bytearray_endswith__doc__, +"endswith($self, prefix[, start[, end]], /)\n" +"--\n" +"\n" +"Return True if B ends with the specified prefix, False otherwise.\n" +"\n" +"With optional start, test B beginning at that position.\n" +"With optional end, stop comparing B at that position.\n" +"prefix can also be a tuple of bytes to try."); + +#define BYTEARRAY_ENDSWITH_METHODDEF \ + {"endswith", _PyCFunction_CAST(bytearray_endswith), METH_FASTCALL, bytearray_endswith__doc__}, + +static PyObject * +bytearray_endswith_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_endswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("endswith", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_endswith_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytearray_removeprefix__doc__, "removeprefix($self, prefix, /)\n" "--\n" @@ -1300,4 +1339,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=01c78d65700f652d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0074ca263a60fd85 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index e4b7211382035d..054ffb572ab780 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -691,6 +691,45 @@ bytes_startswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) return return_value; } +PyDoc_STRVAR(bytes_endswith__doc__, +"endswith($self, prefix[, start[, end]], /)\n" +"--\n" +"\n" +"Return True if B ends with the specified prefix, False otherwise.\n" +"\n" +"With optional start, test B beginning at that position.\n" +"With optional end, stop comparing B at that position.\n" +"prefix can also be a tuple of bytes to try."); + +#define BYTES_ENDSWITH_METHODDEF \ + {"endswith", _PyCFunction_CAST(bytes_endswith), METH_FASTCALL, bytes_endswith__doc__}, + +static PyObject * +bytes_endswith_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_endswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("endswith", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_endswith_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytes_decode__doc__, "decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" @@ -1068,4 +1107,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=9148bed58e358e53 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ec9b14dc1196888d input=a9049054013a1b77]*/ From b7f04d7d9cd3d0a83556eb2117142a06774bc08d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 2 Apr 2024 21:49:17 +0200 Subject: [PATCH 03/21] Optimise --- Include/internal/pycore_bytes_methods.h | 8 ++- Objects/bytearrayobject.c | 27 ++++++--- Objects/bytes_methods.c | 35 +++++------ Objects/bytesobject.c | 35 +++++------ Objects/clinic/bytearrayobject.c.h | 74 ++++++++++++++++------- Objects/clinic/bytesobject.c.h | 78 ++++++++++++++++--------- 6 files changed, 162 insertions(+), 95 deletions(-) diff --git a/Include/internal/pycore_bytes_methods.h b/Include/internal/pycore_bytes_methods.h index 11e8ab20e91367..b9c0a4e2b2f77d 100644 --- a/Include/internal/pycore_bytes_methods.h +++ b/Include/internal/pycore_bytes_methods.h @@ -32,8 +32,12 @@ extern PyObject *_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args extern PyObject *_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args); extern PyObject *_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args); extern int _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg); -extern PyObject *_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args); -extern PyObject *_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args); +extern PyObject *_Py_bytes_startswith(const char *str, Py_ssize_t len, + PyObject *subobj, Py_ssize_t start, + Py_ssize_t end); +extern PyObject *_Py_bytes_endswith(const char *str, Py_ssize_t len, + PyObject *subobj, Py_ssize_t start, + Py_ssize_t end); /* The maketrans() static method. */ extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to); diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index dc173d58cbf7b5..8d6e91998288fe 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1190,10 +1190,15 @@ bytearray_contains(PyObject *self, PyObject *arg) @text_signature "($self, prefix[, start[, end]], /)" bytearray.startswith - *args: object + prefix as subobj: object + A byte string or a tuple of byte strings to try. + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the byte string. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the byte string. / -Return True if B starts with the specified prefix, False otherwise. +Return True if the byte string starts with the specified prefix, False otherwise. With optional start, test B beginning at that position. With optional end, stop comparing B at that position. @@ -1201,17 +1206,19 @@ prefix can also be a tuple of bytes to try. [clinic start generated code]*/ static PyObject * -bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=cfec6eb4d8d465b2 input=53a7036eaff0525e]*/ +bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=a3d9b6d44d3662a6 input=596f48473d404176]*/ { - return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + subobj, start, end); } /*[clinic input] @text_signature "($self, prefix[, start[, end]], /)" bytearray.endswith = bytearray.startswith -Return True if B ends with the specified prefix, False otherwise. +Return True if the byte string ends with the specified prefix, False otherwise. With optional start, test B beginning at that position. With optional end, stop comparing B at that position. @@ -1219,10 +1226,12 @@ prefix can also be a tuple of bytes to try. [clinic start generated code]*/ static PyObject * -bytearray_endswith_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=2d9b7e94ef2b142a input=2a2ba6955504ae08]*/ +bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=e75ea8c227954caa input=96d3f21baa53c7b2]*/ { - return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + subobj, start, end); } /*[clinic input] diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index 4a778ef4a82b22..21b6668171bf61 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -771,50 +771,47 @@ tailmatch(const char *str, Py_ssize_t len, PyObject *substr, static PyObject * _Py_bytes_tailmatch(const char *str, Py_ssize_t len, - const char *function_name, PyObject *args, + const char *function_name, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end, int direction) { - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - PyObject *subobj = NULL; - int result; - - if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end)) - return NULL; if (PyTuple_Check(subobj)) { Py_ssize_t i; for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { - result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i), - start, end, direction); - if (result == -1) + PyObject *item = PyTuple_GET_ITEM(subobj, i); + int result = tailmatch(str, len, item, start, end, direction); + if (result < 0) { return NULL; + } else if (result) { Py_RETURN_TRUE; } } Py_RETURN_FALSE; } - result = tailmatch(str, len, subobj, start, end, direction); + int result = tailmatch(str, len, subobj, start, end, direction); if (result == -1) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) + if (PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Format(PyExc_TypeError, "%s first arg must be bytes or a tuple of bytes, " "not %s", function_name, Py_TYPE(subobj)->tp_name); + } return NULL; } - else - return PyBool_FromLong(result); + return PyBool_FromLong(result); } PyObject * -_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) { - return _Py_bytes_tailmatch(str, len, "startswith", args, -1); + return _Py_bytes_tailmatch(str, len, "startswith", subobj, start, end, -1); } PyObject * -_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) { - return _Py_bytes_tailmatch(str, len, "endswith", args, +1); + return _Py_bytes_tailmatch(str, len, "endswith", subobj, start, end, +1); } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index b105995e6168fa..141d01e795787b 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2289,39 +2289,40 @@ bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix) @text_signature "($self, prefix[, start[, end]], /)" bytes.startswith - *args: object + prefix as subobj: object + A byte string or a tuple of byte strings to try. + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the byte string. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the byte string. / -Return True if B starts with the specified prefix, False otherwise. - -With optional start, test B beginning at that position. -With optional end, stop comparing B at that position. -prefix can also be a tuple of bytes to try. +Return True if the byte string starts with the specified prefix, False otherwise. [clinic start generated code]*/ static PyObject * -bytes_startswith_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=172340dafc2f3c97 input=87559404108dcdfc]*/ +bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=b1e8da1cbd528e8c input=86b5f991fc8ac0dc]*/ { - return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + subobj, start, end); } /*[clinic input] @text_signature "($self, prefix[, start[, end]], /)" bytes.endswith = bytes.startswith -Return True if B ends with the specified prefix, False otherwise. - -With optional start, test B beginning at that position. -With optional end, stop comparing B at that position. -prefix can also be a tuple of bytes to try. +Return True if the byte string ends with the specified prefix, False otherwise. [clinic start generated code]*/ static PyObject * -bytes_endswith_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=b462e732a996e3eb input=3f7fc635440e2ab5]*/ +bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, + Py_ssize_t end) +/*[clinic end generated code: output=038b633111f3629d input=38d3f36990facc7b]*/ { - return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + subobj, start, end); } diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index addef9c995c51a..a161a1a485666b 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -141,7 +141,14 @@ PyDoc_STRVAR(bytearray_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if B starts with the specified prefix, False otherwise.\n" +"Return True if the byte string starts with the specified prefix, False otherwise.\n" +"\n" +" prefix\n" +" A byte string or a tuple of byte strings to try.\n" +" start\n" +" Optional start position. Default: start of the byte string.\n" +" end\n" +" Optional stop position. Default: end of the byte string.\n" "\n" "With optional start, test B beginning at that position.\n" "With optional end, stop comparing B at that position.\n" @@ -151,28 +158,37 @@ PyDoc_STRVAR(bytearray_startswith__doc__, {"startswith", _PyCFunction_CAST(bytearray_startswith), METH_FASTCALL, bytearray_startswith__doc__}, static PyObject * -bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args); +bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytearray_startswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *subobj; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("startswith", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("startswith", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + subobj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytearray_startswith_impl(self, __clinic_args); +skip_optional: + return_value = bytearray_startswith_impl(self, subobj, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -180,7 +196,14 @@ PyDoc_STRVAR(bytearray_endswith__doc__, "endswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if B ends with the specified prefix, False otherwise.\n" +"Return True if the byte string ends with the specified prefix, False otherwise.\n" +"\n" +" prefix\n" +" A byte string or a tuple of byte strings to try.\n" +" start\n" +" Optional start position. Default: start of the byte string.\n" +" end\n" +" Optional stop position. Default: end of the byte string.\n" "\n" "With optional start, test B beginning at that position.\n" "With optional end, stop comparing B at that position.\n" @@ -190,28 +213,37 @@ PyDoc_STRVAR(bytearray_endswith__doc__, {"endswith", _PyCFunction_CAST(bytearray_endswith), METH_FASTCALL, bytearray_endswith__doc__}, static PyObject * -bytearray_endswith_impl(PyByteArrayObject *self, PyObject *args); +bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytearray_endswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *subobj; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("endswith", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("endswith", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + subobj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytearray_endswith_impl(self, __clinic_args); +skip_optional: + return_value = bytearray_endswith_impl(self, subobj, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -1339,4 +1371,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=0074ca263a60fd85 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8ef9bb3a7401c0f6 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 054ffb572ab780..ed31ec7a2876ed 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -656,38 +656,50 @@ PyDoc_STRVAR(bytes_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if B starts with the specified prefix, False otherwise.\n" +"Return True if the byte string starts with the specified prefix, False otherwise.\n" "\n" -"With optional start, test B beginning at that position.\n" -"With optional end, stop comparing B at that position.\n" -"prefix can also be a tuple of bytes to try."); +" prefix\n" +" A byte string or a tuple of byte strings to try.\n" +" start\n" +" Optional start position. Default: start of the byte string.\n" +" end\n" +" Optional stop position. Default: end of the byte string."); #define BYTES_STARTSWITH_METHODDEF \ {"startswith", _PyCFunction_CAST(bytes_startswith), METH_FASTCALL, bytes_startswith__doc__}, static PyObject * -bytes_startswith_impl(PyBytesObject *self, PyObject *args); +bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytes_startswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *subobj; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("startswith", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("startswith", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + subobj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; } - return_value = bytes_startswith_impl(self, __clinic_args); + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; + } +skip_optional: + return_value = bytes_startswith_impl(self, subobj, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -695,38 +707,50 @@ PyDoc_STRVAR(bytes_endswith__doc__, "endswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if B ends with the specified prefix, False otherwise.\n" +"Return True if the byte string ends with the specified prefix, False otherwise.\n" "\n" -"With optional start, test B beginning at that position.\n" -"With optional end, stop comparing B at that position.\n" -"prefix can also be a tuple of bytes to try."); +" prefix\n" +" A byte string or a tuple of byte strings to try.\n" +" start\n" +" Optional start position. Default: start of the byte string.\n" +" end\n" +" Optional stop position. Default: end of the byte string."); #define BYTES_ENDSWITH_METHODDEF \ {"endswith", _PyCFunction_CAST(bytes_endswith), METH_FASTCALL, bytes_endswith__doc__}, static PyObject * -bytes_endswith_impl(PyBytesObject *self, PyObject *args); +bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, + Py_ssize_t end); static PyObject * bytes_endswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *subobj; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("endswith", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("endswith", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + subobj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; } - return_value = bytes_endswith_impl(self, __clinic_args); + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; + } +skip_optional: + return_value = bytes_endswith_impl(self, subobj, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -1107,4 +1131,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=ec9b14dc1196888d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4c2cdae78ce05ce5 input=a9049054013a1b77]*/ From 57c9afcc2eaebc8b2751413e14fd3478b425c7e8 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 09:49:20 +0200 Subject: [PATCH 04/21] Add NEWS --- .../2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst new file mode 100644 index 00000000000000..17374d0d5c575b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst @@ -0,0 +1,6 @@ +Improve the performance of the following :class:`bytes` and +:class:`bytearray` methods by adapting them to the :c:macro:`METH_FASTCALL` +calling convention: + +* :meth:`!endswith` +* :meth:`!startswith` From 1b89eb9c8c7669fc1daeb22842ce9bebcdaccc09 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 09:54:26 +0200 Subject: [PATCH 05/21] Adjust docstring --- Objects/bytearrayobject.c | 6 +----- Objects/clinic/bytearrayobject.c.h | 8 ++------ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 8d6e91998288fe..5b07f23fdb76c0 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1219,16 +1219,12 @@ bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, bytearray.endswith = bytearray.startswith Return True if the byte string ends with the specified prefix, False otherwise. - -With optional start, test B beginning at that position. -With optional end, stop comparing B at that position. -prefix can also be a tuple of bytes to try. [clinic start generated code]*/ static PyObject * bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=e75ea8c227954caa input=96d3f21baa53c7b2]*/ +/*[clinic end generated code: output=e75ea8c227954caa input=6b8a65e1d0071201]*/ { return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index a161a1a485666b..aa923ab23609ed 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -203,11 +203,7 @@ PyDoc_STRVAR(bytearray_endswith__doc__, " start\n" " Optional start position. Default: start of the byte string.\n" " end\n" -" Optional stop position. Default: end of the byte string.\n" -"\n" -"With optional start, test B beginning at that position.\n" -"With optional end, stop comparing B at that position.\n" -"prefix can also be a tuple of bytes to try."); +" Optional stop position. Default: end of the byte string."); #define BYTEARRAY_ENDSWITH_METHODDEF \ {"endswith", _PyCFunction_CAST(bytearray_endswith), METH_FASTCALL, bytearray_endswith__doc__}, @@ -1371,4 +1367,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=8ef9bb3a7401c0f6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=11cc701b1df6250e input=a9049054013a1b77]*/ From fabe7618c5b762687093d1984a211ce25639e131 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 09:57:21 +0200 Subject: [PATCH 06/21] Docstring: Use 'bytes' or 'bytearray' instead of 'byte string' --- Objects/bytearrayobject.c | 10 +++++----- Objects/bytesobject.c | 10 +++++----- Objects/clinic/bytearrayobject.c.h | 16 ++++++++-------- Objects/clinic/bytesobject.c.h | 16 ++++++++-------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 5b07f23fdb76c0..329bea92472994 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1191,14 +1191,14 @@ bytearray_contains(PyObject *self, PyObject *arg) bytearray.startswith prefix as subobj: object - A byte string or a tuple of byte strings to try. + A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None - Optional start position. Default: start of the byte string. + Optional start position. Default: start of the bytearray. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None - Optional stop position. Default: end of the byte string. + Optional stop position. Default: end of the bytearray. / -Return True if the byte string starts with the specified prefix, False otherwise. +Return True if the bytearray starts with the specified prefix, False otherwise. With optional start, test B beginning at that position. With optional end, stop comparing B at that position. @@ -1208,7 +1208,7 @@ prefix can also be a tuple of bytes to try. static PyObject * bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=a3d9b6d44d3662a6 input=596f48473d404176]*/ +/*[clinic end generated code: output=a3d9b6d44d3662a6 input=1bb77e6e964116b5]*/ { return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 141d01e795787b..0a62f40f0a6571 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2290,20 +2290,20 @@ bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix) bytes.startswith prefix as subobj: object - A byte string or a tuple of byte strings to try. + A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None - Optional start position. Default: start of the byte string. + Optional start position. Default: start of the bytes. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None - Optional stop position. Default: end of the byte string. + Optional stop position. Default: end of the bytes. / -Return True if the byte string starts with the specified prefix, False otherwise. +Return True if the bytes starts with the specified prefix, False otherwise. [clinic start generated code]*/ static PyObject * bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=b1e8da1cbd528e8c input=86b5f991fc8ac0dc]*/ +/*[clinic end generated code: output=b1e8da1cbd528e8c input=917d9cf26c33b96a]*/ { return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index aa923ab23609ed..eceffcbb47154a 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -141,14 +141,14 @@ PyDoc_STRVAR(bytearray_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string starts with the specified prefix, False otherwise.\n" +"Return True if the bytearray starts with the specified prefix, False otherwise.\n" "\n" " prefix\n" -" A byte string or a tuple of byte strings to try.\n" +" A bytes or a tuple of bytes to try.\n" " start\n" -" Optional start position. Default: start of the byte string.\n" +" Optional start position. Default: start of the bytearray.\n" " end\n" -" Optional stop position. Default: end of the byte string.\n" +" Optional stop position. Default: end of the bytearray.\n" "\n" "With optional start, test B beginning at that position.\n" "With optional end, stop comparing B at that position.\n" @@ -199,11 +199,11 @@ PyDoc_STRVAR(bytearray_endswith__doc__, "Return True if the byte string ends with the specified prefix, False otherwise.\n" "\n" " prefix\n" -" A byte string or a tuple of byte strings to try.\n" +" A bytes or a tuple of bytes to try.\n" " start\n" -" Optional start position. Default: start of the byte string.\n" +" Optional start position. Default: start of the bytearray.\n" " end\n" -" Optional stop position. Default: end of the byte string."); +" Optional stop position. Default: end of the bytearray."); #define BYTEARRAY_ENDSWITH_METHODDEF \ {"endswith", _PyCFunction_CAST(bytearray_endswith), METH_FASTCALL, bytearray_endswith__doc__}, @@ -1367,4 +1367,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=11cc701b1df6250e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d1ec3d7be5d1093c input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index ed31ec7a2876ed..4571d5d9314172 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -656,14 +656,14 @@ PyDoc_STRVAR(bytes_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string starts with the specified prefix, False otherwise.\n" +"Return True if the bytes starts with the specified prefix, False otherwise.\n" "\n" " prefix\n" -" A byte string or a tuple of byte strings to try.\n" +" A bytes or a tuple of bytes to try.\n" " start\n" -" Optional start position. Default: start of the byte string.\n" +" Optional start position. Default: start of the bytes.\n" " end\n" -" Optional stop position. Default: end of the byte string."); +" Optional stop position. Default: end of the bytes."); #define BYTES_STARTSWITH_METHODDEF \ {"startswith", _PyCFunction_CAST(bytes_startswith), METH_FASTCALL, bytes_startswith__doc__}, @@ -710,11 +710,11 @@ PyDoc_STRVAR(bytes_endswith__doc__, "Return True if the byte string ends with the specified prefix, False otherwise.\n" "\n" " prefix\n" -" A byte string or a tuple of byte strings to try.\n" +" A bytes or a tuple of bytes to try.\n" " start\n" -" Optional start position. Default: start of the byte string.\n" +" Optional start position. Default: start of the bytes.\n" " end\n" -" Optional stop position. Default: end of the byte string."); +" Optional stop position. Default: end of the bytes."); #define BYTES_ENDSWITH_METHODDEF \ {"endswith", _PyCFunction_CAST(bytes_endswith), METH_FASTCALL, bytes_endswith__doc__}, @@ -1131,4 +1131,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=4c2cdae78ce05ce5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5d319f11a99fbc02 input=a9049054013a1b77]*/ From e9b59cc5ddcb06d331682943cc3b67974d7907ea Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 09:58:30 +0200 Subject: [PATCH 07/21] Docstring: Remove unneeded body from bytearray.startswith; the param section will fill in the needed info --- Objects/bytearrayobject.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 329bea92472994..c82c8edee35fc6 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1199,10 +1199,6 @@ bytearray.startswith / Return True if the bytearray starts with the specified prefix, False otherwise. - -With optional start, test B beginning at that position. -With optional end, stop comparing B at that position. -prefix can also be a tuple of bytes to try. [clinic start generated code]*/ static PyObject * From 655a6a88fed9035838e9fe389766024f22568c29 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 10:08:37 +0200 Subject: [PATCH 08/21] Regen clinic --- Objects/bytearrayobject.c | 2 +- Objects/clinic/bytearrayobject.c.h | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index c82c8edee35fc6..6055852fd44ef0 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1204,7 +1204,7 @@ Return True if the bytearray starts with the specified prefix, False otherwise. static PyObject * bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=a3d9b6d44d3662a6 input=1bb77e6e964116b5]*/ +/*[clinic end generated code: output=a3d9b6d44d3662a6 input=5815c1138cf1ba28]*/ { return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index eceffcbb47154a..5ae2964fed944a 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -148,11 +148,7 @@ PyDoc_STRVAR(bytearray_startswith__doc__, " start\n" " Optional start position. Default: start of the bytearray.\n" " end\n" -" Optional stop position. Default: end of the bytearray.\n" -"\n" -"With optional start, test B beginning at that position.\n" -"With optional end, stop comparing B at that position.\n" -"prefix can also be a tuple of bytes to try."); +" Optional stop position. Default: end of the bytearray."); #define BYTEARRAY_STARTSWITH_METHODDEF \ {"startswith", _PyCFunction_CAST(bytearray_startswith), METH_FASTCALL, bytearray_startswith__doc__}, @@ -1367,4 +1363,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=d1ec3d7be5d1093c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=353628ec8834ad01 input=a9049054013a1b77]*/ From e1a5acc94029a6fd994ad8bf4c249f29bf85c097 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 11:27:20 +0200 Subject: [PATCH 09/21] Adapt byte*.{*find,*index,count} --- Objects/bytearrayobject.c | 79 ++++++++++-- Objects/bytes_methods.c | 43 ------- Objects/bytesobject.c | 77 ++++++++++-- Objects/clinic/bytearrayobject.c.h | 191 ++++++++++++++++++++++++++++- Objects/clinic/bytesobject.c.h | 191 ++++++++++++++++++++++++++++- 5 files changed, 512 insertions(+), 69 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 6055852fd44ef0..64c63119bcbd8a 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1121,14 +1121,38 @@ bytearray_dealloc(PyByteArrayObject *self) #include "stringlib/transmogrify.h" +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytearray.find + + *args: object + / + +Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. + +Optional arguments 'start' and 'end' are interpreted as in slice notation. +Return -1 on failure. +[clinic start generated code]*/ + static PyObject * -bytearray_find(PyByteArrayObject *self, PyObject *args) +bytearray_find_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=a77f2d2cf96f4301 input=0515d0b1cdb6bf57]*/ { return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytearray.count = bytearray.find + +Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end]. + +Optional arguments start and end are interpreted as in slice notation. +[clinic start generated code]*/ + static PyObject * -bytearray_count(PyByteArrayObject *self, PyObject *args) +bytearray_count_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=ef57bde4b8b86a0f input=a6f76f638a7a450c]*/ { return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } @@ -1162,20 +1186,53 @@ bytearray_copy_impl(PyByteArrayObject *self) PyByteArray_GET_SIZE(self)); } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytearray.index = bytearray.find + +Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. + +Optional arguments start and end are interpreted as in slice notation. +Raise ValueError if the subsection is not found. +[clinic start generated code]*/ + static PyObject * -bytearray_index(PyByteArrayObject *self, PyObject *args) +bytearray_index_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=b712bd29955506e6 input=34f93d0642e75797]*/ { return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytearray.rfind = bytearray.find + +Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. + +Optional arguments 'start' and 'end' are interpreted as in slice notation. +Return -1 on failure. +[clinic start generated code]*/ + static PyObject * -bytearray_rfind(PyByteArrayObject *self, PyObject *args) +bytearray_rfind_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=c3ae3b3474c46566 input=a40d7bfe9d71c21c]*/ { return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytearray.rindex = bytearray.find + +Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. + +Optional arguments start and end are interpreted as in slice notation. +Raise ValueError if the subsection is not found. +[clinic start generated code]*/ + static PyObject * -bytearray_rindex(PyByteArrayObject *self, PyObject *args) +bytearray_rindex_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=7801cbd97f9ca19e input=78f9e77317d145fb]*/ { return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } @@ -2228,17 +2285,15 @@ bytearray_methods[] = { STRINGLIB_CENTER_METHODDEF BYTEARRAY_CLEAR_METHODDEF BYTEARRAY_COPY_METHODDEF - {"count", (PyCFunction)bytearray_count, METH_VARARGS, - _Py_count__doc__}, + BYTEARRAY_COUNT_METHODDEF BYTEARRAY_DECODE_METHODDEF BYTEARRAY_ENDSWITH_METHODDEF STRINGLIB_EXPANDTABS_METHODDEF BYTEARRAY_EXTEND_METHODDEF - {"find", (PyCFunction)bytearray_find, METH_VARARGS, - _Py_find__doc__}, + BYTEARRAY_FIND_METHODDEF BYTEARRAY_FROMHEX_METHODDEF BYTEARRAY_HEX_METHODDEF - {"index", (PyCFunction)bytearray_index, METH_VARARGS, _Py_index__doc__}, + BYTEARRAY_INDEX_METHODDEF BYTEARRAY_INSERT_METHODDEF {"isalnum", stringlib_isalnum, METH_NOARGS, _Py_isalnum__doc__}, @@ -2268,8 +2323,8 @@ bytearray_methods[] = { BYTEARRAY_REMOVEPREFIX_METHODDEF BYTEARRAY_REMOVESUFFIX_METHODDEF BYTEARRAY_REVERSE_METHODDEF - {"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__}, - {"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__}, + BYTEARRAY_RFIND_METHODDEF + BYTEARRAY_RINDEX_METHODDEF STRINGLIB_RJUST_METHODDEF BYTEARRAY_RPARTITION_METHODDEF BYTEARRAY_RSPLIT_METHODDEF diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index 21b6668171bf61..7333e4ee016ca1 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -566,15 +566,6 @@ find_internal(const char *str, Py_ssize_t len, return res; } -PyDoc_STRVAR_shared(_Py_find__doc__, -"B.find(sub[, start[, end]]) -> int\n\ -\n\ -Return the lowest index in B where subsection sub is found,\n\ -such that sub is contained within B[start,end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Return -1 on failure."); - PyObject * _Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args) { @@ -584,15 +575,6 @@ _Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args) return PyLong_FromSsize_t(result); } -PyDoc_STRVAR_shared(_Py_index__doc__, -"B.index(sub[, start[, end]]) -> int\n\ -\n\ -Return the lowest index in B where subsection sub is found,\n\ -such that sub is contained within B[start,end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Raises ValueError when the subsection is not found."); - PyObject * _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args) { @@ -607,15 +589,6 @@ _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args) return PyLong_FromSsize_t(result); } -PyDoc_STRVAR_shared(_Py_rfind__doc__, -"B.rfind(sub[, start[, end]]) -> int\n\ -\n\ -Return the highest index in B where subsection sub is found,\n\ -such that sub is contained within B[start,end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Return -1 on failure."); - PyObject * _Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args) { @@ -625,15 +598,6 @@ _Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args) return PyLong_FromSsize_t(result); } -PyDoc_STRVAR_shared(_Py_rindex__doc__, -"B.rindex(sub[, start[, end]]) -> int\n\ -\n\ -Return the highest index in B where subsection sub is found,\n\ -such that sub is contained within B[start,end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Raise ValueError when the subsection is not found."); - PyObject * _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args) { @@ -648,13 +612,6 @@ _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args) return PyLong_FromSsize_t(result); } -PyDoc_STRVAR_shared(_Py_count__doc__, -"B.count(sub[, start[, end]]) -> int\n\ -\n\ -Return the number of non-overlapping occurrences of subsection sub in\n\ -bytes B[start:end]. Optional arguments start and end are interpreted\n\ -as in slice notation."); - PyObject * _Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args) { diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 0a62f40f0a6571..2156f864f4a5fb 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1863,28 +1863,73 @@ _PyBytes_Join(PyObject *sep, PyObject *x) return bytes_join((PyBytesObject*)sep, x); } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytes.find + + *args: object + / + +Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. + +Optional arguments 'start' and 'end' are interpreted as in slice notation. +Return -1 on failure. +[clinic start generated code]*/ + static PyObject * -bytes_find(PyBytesObject *self, PyObject *args) +bytes_find_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=62e7a26240c8a4a2 input=f0bde0cb478d2b8c]*/ { return _Py_bytes_find(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytes.index = bytes.find + +Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. + +Optional arguments start and end are interpreted as in slice notation. +Raise ValueError if the subsection is not found. +[clinic start generated code]*/ + static PyObject * -bytes_index(PyBytesObject *self, PyObject *args) +bytes_index_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=866d781b6589b72f input=ffba1569b1c9af9b]*/ { return _Py_bytes_index(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytes.rfind = bytes.find + +Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. + +Optional arguments 'start' and 'end' are interpreted as in slice notation. +Return -1 on failure. +[clinic start generated code]*/ static PyObject * -bytes_rfind(PyBytesObject *self, PyObject *args) +bytes_rfind_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=ae774c87c9c7a5af input=e42f537ca09ece2b]*/ { return _Py_bytes_rfind(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytes.rindex = bytes.find + +Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. + +Optional arguments start and end are interpreted as in slice notation. +Raise ValueError if the subsection is not found. +[clinic start generated code]*/ static PyObject * -bytes_rindex(PyBytesObject *self, PyObject *args) +bytes_rindex_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=6758f68eb1883d20 input=b7b56bf94364b8da]*/ { return _Py_bytes_rindex(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } @@ -2023,8 +2068,18 @@ bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes) } +/*[clinic input] +@text_signature "($self, sub[, start[, end]], /)" +bytes.count = bytes.find + +Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end]. + +Optional arguments start and end are interpreted as in slice notation. +[clinic start generated code]*/ + static PyObject * -bytes_count(PyBytesObject *self, PyObject *args) +bytes_count_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=5d8c9f60259d3064 input=2a32925161376240]*/ { return _Py_bytes_count(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } @@ -2516,16 +2571,14 @@ bytes_methods[] = { {"capitalize", stringlib_capitalize, METH_NOARGS, _Py_capitalize__doc__}, STRINGLIB_CENTER_METHODDEF - {"count", (PyCFunction)bytes_count, METH_VARARGS, - _Py_count__doc__}, + BYTES_COUNT_METHODDEF BYTES_DECODE_METHODDEF BYTES_ENDSWITH_METHODDEF STRINGLIB_EXPANDTABS_METHODDEF - {"find", (PyCFunction)bytes_find, METH_VARARGS, - _Py_find__doc__}, + BYTES_FIND_METHODDEF BYTES_FROMHEX_METHODDEF BYTES_HEX_METHODDEF - {"index", (PyCFunction)bytes_index, METH_VARARGS, _Py_index__doc__}, + BYTES_INDEX_METHODDEF {"isalnum", stringlib_isalnum, METH_NOARGS, _Py_isalnum__doc__}, {"isalpha", stringlib_isalpha, METH_NOARGS, @@ -2551,8 +2604,8 @@ bytes_methods[] = { BYTES_REPLACE_METHODDEF BYTES_REMOVEPREFIX_METHODDEF BYTES_REMOVESUFFIX_METHODDEF - {"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, _Py_rfind__doc__}, - {"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, _Py_rindex__doc__}, + BYTES_RFIND_METHODDEF + BYTES_RINDEX_METHODDEF STRINGLIB_RJUST_METHODDEF BYTES_RPARTITION_METHODDEF BYTES_RSPLIT_METHODDEF diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 5ae2964fed944a..92060de1743e6d 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -101,6 +101,81 @@ bytearray___init__(PyObject *self, PyObject *args, PyObject *kwargs) return return_value; } +PyDoc_STRVAR(bytearray_find__doc__, +"find($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"\n" +"Optional arguments \'start\' and \'end\' are interpreted as in slice notation.\n" +"Return -1 on failure."); + +#define BYTEARRAY_FIND_METHODDEF \ + {"find", _PyCFunction_CAST(bytearray_find), METH_FASTCALL, bytearray_find__doc__}, + +static PyObject * +bytearray_find_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_find(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("find", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_find_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(bytearray_count__doc__, +"count($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the number of non-overlapping occurrences of subsection \'sub\' in bytes B[start:end].\n" +"\n" +"Optional arguments start and end are interpreted as in slice notation."); + +#define BYTEARRAY_COUNT_METHODDEF \ + {"count", _PyCFunction_CAST(bytearray_count), METH_FASTCALL, bytearray_count__doc__}, + +static PyObject * +bytearray_count_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_count(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("count", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_count_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytearray_clear__doc__, "clear($self, /)\n" "--\n" @@ -137,6 +212,120 @@ bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) return bytearray_copy_impl(self); } +PyDoc_STRVAR(bytearray_index__doc__, +"index($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"\n" +"Optional arguments start and end are interpreted as in slice notation.\n" +"Raise ValueError if the subsection is not found."); + +#define BYTEARRAY_INDEX_METHODDEF \ + {"index", _PyCFunction_CAST(bytearray_index), METH_FASTCALL, bytearray_index__doc__}, + +static PyObject * +bytearray_index_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_index(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("index", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_index_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(bytearray_rfind__doc__, +"rfind($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"\n" +"Optional arguments \'start\' and \'end\' are interpreted as in slice notation.\n" +"Return -1 on failure."); + +#define BYTEARRAY_RFIND_METHODDEF \ + {"rfind", _PyCFunction_CAST(bytearray_rfind), METH_FASTCALL, bytearray_rfind__doc__}, + +static PyObject * +bytearray_rfind_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_rfind(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("rfind", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_rfind_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(bytearray_rindex__doc__, +"rindex($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"\n" +"Optional arguments start and end are interpreted as in slice notation.\n" +"Raise ValueError if the subsection is not found."); + +#define BYTEARRAY_RINDEX_METHODDEF \ + {"rindex", _PyCFunction_CAST(bytearray_rindex), METH_FASTCALL, bytearray_rindex__doc__}, + +static PyObject * +bytearray_rindex_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_rindex(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("rindex", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_rindex_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytearray_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" @@ -1363,4 +1552,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=353628ec8834ad01 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e30a6e2fcaba605c input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 4571d5d9314172..112353a533d5d4 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -294,6 +294,158 @@ PyDoc_STRVAR(bytes_join__doc__, #define BYTES_JOIN_METHODDEF \ {"join", (PyCFunction)bytes_join, METH_O, bytes_join__doc__}, +PyDoc_STRVAR(bytes_find__doc__, +"find($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"\n" +"Optional arguments \'start\' and \'end\' are interpreted as in slice notation.\n" +"Return -1 on failure."); + +#define BYTES_FIND_METHODDEF \ + {"find", _PyCFunction_CAST(bytes_find), METH_FASTCALL, bytes_find__doc__}, + +static PyObject * +bytes_find_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_find(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("find", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_find_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(bytes_index__doc__, +"index($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"\n" +"Optional arguments start and end are interpreted as in slice notation.\n" +"Raise ValueError if the subsection is not found."); + +#define BYTES_INDEX_METHODDEF \ + {"index", _PyCFunction_CAST(bytes_index), METH_FASTCALL, bytes_index__doc__}, + +static PyObject * +bytes_index_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_index(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("index", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_index_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(bytes_rfind__doc__, +"rfind($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"\n" +"Optional arguments \'start\' and \'end\' are interpreted as in slice notation.\n" +"Return -1 on failure."); + +#define BYTES_RFIND_METHODDEF \ + {"rfind", _PyCFunction_CAST(bytes_rfind), METH_FASTCALL, bytes_rfind__doc__}, + +static PyObject * +bytes_rfind_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_rfind(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("rfind", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_rfind_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(bytes_rindex__doc__, +"rindex($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"\n" +"Optional arguments start and end are interpreted as in slice notation.\n" +"Raise ValueError if the subsection is not found."); + +#define BYTES_RINDEX_METHODDEF \ + {"rindex", _PyCFunction_CAST(bytes_rindex), METH_FASTCALL, bytes_rindex__doc__}, + +static PyObject * +bytes_rindex_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_rindex(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("rindex", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_rindex_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytes_strip__doc__, "strip($self, bytes=None, /)\n" "--\n" @@ -396,6 +548,43 @@ bytes_rstrip(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) return return_value; } +PyDoc_STRVAR(bytes_count__doc__, +"count($self, sub[, start[, end]], /)\n" +"--\n" +"\n" +"Return the number of non-overlapping occurrences of subsection \'sub\' in bytes B[start:end].\n" +"\n" +"Optional arguments start and end are interpreted as in slice notation."); + +#define BYTES_COUNT_METHODDEF \ + {"count", _PyCFunction_CAST(bytes_count), METH_FASTCALL, bytes_count__doc__}, + +static PyObject * +bytes_count_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_count(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("count", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_count_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytes_translate__doc__, "translate($self, table, /, delete=b\'\')\n" "--\n" @@ -1131,4 +1320,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=5d319f11a99fbc02 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f5b0691b15de261f input=a9049054013a1b77]*/ From 2c54b79ab333a05fe0c6e297e54b505a05ffc268 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 11:55:44 +0200 Subject: [PATCH 10/21] Address Inada-san's review: endswith's first param is named 'suffix' --- Objects/bytearrayobject.c | 16 ++++++++++++---- Objects/bytesobject.c | 16 ++++++++++++---- Objects/clinic/bytearrayobject.c.h | 8 ++++---- Objects/clinic/bytesobject.c.h | 8 ++++---- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 6055852fd44ef0..e9763dfe338fe2 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1211,16 +1211,24 @@ bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, } /*[clinic input] -@text_signature "($self, prefix[, start[, end]], /)" -bytearray.endswith = bytearray.startswith +@text_signature "($self, suffix[, start[, end]], /)" +bytearray.endswith + + suffix as subobj: object + A bytes or a tuple of bytes to try. + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the bytearray. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the bytearray. + / -Return True if the byte string ends with the specified prefix, False otherwise. +Return True if the byte string ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=e75ea8c227954caa input=6b8a65e1d0071201]*/ +/*[clinic end generated code: output=e75ea8c227954caa input=3b63c2dc878407c2]*/ { return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 0a62f40f0a6571..33e3fc3da41e16 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2310,16 +2310,24 @@ bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, } /*[clinic input] -@text_signature "($self, prefix[, start[, end]], /)" -bytes.endswith = bytes.startswith +@text_signature "($self, suffix[, start[, end]], /)" +bytes.endswith + + suffix as subobj: object + A bytes or a tuple of bytes to try. + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the bytes. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the bytes. + / -Return True if the byte string ends with the specified prefix, False otherwise. +Return True if the byte string ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=038b633111f3629d input=38d3f36990facc7b]*/ +/*[clinic end generated code: output=038b633111f3629d input=66b64eccac830889]*/ { return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 5ae2964fed944a..b4743ad8cad947 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -189,12 +189,12 @@ bytearray_startswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t } PyDoc_STRVAR(bytearray_endswith__doc__, -"endswith($self, prefix[, start[, end]], /)\n" +"endswith($self, suffix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string ends with the specified prefix, False otherwise.\n" +"Return True if the byte string ends with the specified suffix, False otherwise.\n" "\n" -" prefix\n" +" suffix\n" " A bytes or a tuple of bytes to try.\n" " start\n" " Optional start position. Default: start of the bytearray.\n" @@ -1363,4 +1363,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=353628ec8834ad01 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4264a5341cb44fef input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 4571d5d9314172..944b882e01472d 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -704,12 +704,12 @@ bytes_startswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) } PyDoc_STRVAR(bytes_endswith__doc__, -"endswith($self, prefix[, start[, end]], /)\n" +"endswith($self, suffix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string ends with the specified prefix, False otherwise.\n" +"Return True if the byte string ends with the specified suffix, False otherwise.\n" "\n" -" prefix\n" +" suffix\n" " A bytes or a tuple of bytes to try.\n" " start\n" " Optional start position. Default: start of the bytes.\n" @@ -1131,4 +1131,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=5d319f11a99fbc02 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=48f0667452337301 input=a9049054013a1b77]*/ From a6981f3778acb65d86849adff5bcd22712d783b5 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 12:20:17 +0200 Subject: [PATCH 11/21] WIP --- Include/internal/pycore_bytes_methods.h | 15 ++- Objects/bytearrayobject.c | 52 ++++---- Objects/bytes_methods.c | 59 ++++----- Objects/bytesobject.c | 52 ++++---- Objects/clinic/bytearrayobject.c.h | 166 ++++++++++++++++-------- Objects/clinic/bytesobject.c.h | 166 ++++++++++++++++-------- 6 files changed, 326 insertions(+), 184 deletions(-) diff --git a/Include/internal/pycore_bytes_methods.h b/Include/internal/pycore_bytes_methods.h index b9c0a4e2b2f77d..059dc2599bbd77 100644 --- a/Include/internal/pycore_bytes_methods.h +++ b/Include/internal/pycore_bytes_methods.h @@ -26,11 +26,16 @@ extern void _Py_bytes_title(char *result, const char *s, Py_ssize_t len); extern void _Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len); extern void _Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len); -extern PyObject *_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args); -extern PyObject *_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args); -extern PyObject *_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args); -extern PyObject *_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args); -extern PyObject *_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args); +extern PyObject *_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); +extern PyObject *_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); +extern PyObject *_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); +extern PyObject *_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); +extern PyObject *_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); extern int _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg); extern PyObject *_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *subobj, Py_ssize_t start, diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 3e4ef419de95fa..76cfb1082761a4 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1125,20 +1125,25 @@ bytearray_dealloc(PyByteArrayObject *self) @text_signature "($self, sub[, start[, end]], /)" bytearray.find - *args: object + sub: object + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the bytes. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the bytes. / Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. -Optional arguments 'start' and 'end' are interpreted as in slice notation. Return -1 on failure. [clinic start generated code]*/ static PyObject * -bytearray_find_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=a77f2d2cf96f4301 input=0515d0b1cdb6bf57]*/ +bytearray_find_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end) +/*[clinic end generated code: output=413e1cab2ae87da0 input=27dce3d6f4f24c31]*/ { - return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + sub, start, end); } /*[clinic input] @@ -1146,15 +1151,15 @@ bytearray_find_impl(PyByteArrayObject *self, PyObject *args) bytearray.count = bytearray.find Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end]. - -Optional arguments start and end are interpreted as in slice notation. [clinic start generated code]*/ static PyObject * -bytearray_count_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=ef57bde4b8b86a0f input=a6f76f638a7a450c]*/ +bytearray_count_impl(PyByteArrayObject *self, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=a21ee2692e4f1233 input=f4582e0f6bc42fd7]*/ { - return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + sub, start, end); } /*[clinic input] @@ -1192,15 +1197,16 @@ bytearray.index = bytearray.find Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. -Optional arguments start and end are interpreted as in slice notation. Raise ValueError if the subsection is not found. [clinic start generated code]*/ static PyObject * -bytearray_index_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=b712bd29955506e6 input=34f93d0642e75797]*/ +bytearray_index_impl(PyByteArrayObject *self, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=067a1e78efc672a7 input=5dab02095748cc92]*/ { - return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + sub, start, end); } /*[clinic input] @@ -1209,15 +1215,16 @@ bytearray.rfind = bytearray.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. -Optional arguments 'start' and 'end' are interpreted as in slice notation. Return -1 on failure. [clinic start generated code]*/ static PyObject * -bytearray_rfind_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=c3ae3b3474c46566 input=a40d7bfe9d71c21c]*/ +bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=51bf886f932b283c input=0c059ef74263f94b]*/ { - return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + sub, start, end); } /*[clinic input] @@ -1226,15 +1233,16 @@ bytearray.rindex = bytearray.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. -Optional arguments start and end are interpreted as in slice notation. Raise ValueError if the subsection is not found. [clinic start generated code]*/ static PyObject * -bytearray_rindex_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=7801cbd97f9ca19e input=78f9e77317d145fb]*/ +bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=38e1cf66bafb08b9 input=b1e0254a85220795]*/ { - return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + sub, start, end); } static int diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index 7333e4ee016ca1..981aa57164385e 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -453,31 +453,21 @@ stringlib_parse_args_finds(). */ Py_LOCAL_INLINE(int) -parse_args_finds_byte(const char *function_name, PyObject *args, - PyObject **subobj, char *byte, - Py_ssize_t *start, Py_ssize_t *end) +parse_args_finds_byte(const char *function_name, PyObject **subobj, char *byte) { - PyObject *tmp_subobj; - Py_ssize_t ival; - - if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj, - start, end)) - return 0; - - if (PyObject_CheckBuffer(tmp_subobj)) { - *subobj = tmp_subobj; + if (PyObject_CheckBuffer(*subobj)) { return 1; } - if (!_PyIndex_Check(tmp_subobj)) { + if (!_PyIndex_Check(*subobj)) { PyErr_Format(PyExc_TypeError, "argument should be integer or bytes-like object, " "not '%.200s'", - Py_TYPE(tmp_subobj)->tp_name); + Py_TYPE(*subobj)->tp_name); return 0; } - ival = PyNumber_AsSsize_t(tmp_subobj, NULL); + Py_ssize_t ival = PyNumber_AsSsize_t(*subobj, NULL); if (ival == -1 && PyErr_Occurred()) { return 0; } @@ -508,19 +498,19 @@ parse_args_finds_byte(const char *function_name, PyObject *args, Py_LOCAL_INLINE(Py_ssize_t) find_internal(const char *str, Py_ssize_t len, - const char *function_name, PyObject *args, int dir) + const char *function_name, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end, + int dir) { - PyObject *subobj; char byte; Py_buffer subbuf; const char *sub; Py_ssize_t sub_len; - Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; Py_ssize_t res; - if (!parse_args_finds_byte(function_name, args, - &subobj, &byte, &start, &end)) + if (!parse_args_finds_byte(function_name, &subobj, &byte)) { return -2; + } if (subobj) { if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) @@ -567,18 +557,20 @@ find_internal(const char *str, Py_ssize_t len, } PyObject * -_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) { - Py_ssize_t result = find_internal(str, len, "find", args, +1); + Py_ssize_t result = find_internal(str, len, "find", sub, start, end, +1); if (result == -2) return NULL; return PyLong_FromSsize_t(result); } PyObject * -_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) { - Py_ssize_t result = find_internal(str, len, "index", args, +1); + Py_ssize_t result = find_internal(str, len, "index", sub, start, end, +1); if (result == -2) return NULL; if (result == -1) { @@ -590,18 +582,20 @@ _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args) } PyObject * -_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) { - Py_ssize_t result = find_internal(str, len, "rfind", args, -1); + Py_ssize_t result = find_internal(str, len, "rfind", sub, start, end, -1); if (result == -2) return NULL; return PyLong_FromSsize_t(result); } PyObject * -_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) { - Py_ssize_t result = find_internal(str, len, "rindex", args, -1); + Py_ssize_t result = find_internal(str, len, "rindex", sub, start, end, -1); if (result == -2) return NULL; if (result == -1) { @@ -613,20 +607,19 @@ _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args) } PyObject * -_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *sub_obj, + Py_ssize_t start, Py_ssize_t end) { - PyObject *sub_obj; const char *sub; Py_ssize_t sub_len; char byte; - Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; Py_buffer vsub; PyObject *count_obj; - if (!parse_args_finds_byte("count", args, - &sub_obj, &byte, &start, &end)) + if (!parse_args_finds_byte("count", &sub_obj, &byte)) { return NULL; + } if (sub_obj) { if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 6fd1dd314b9d6b..fff3cf5ae3a1e7 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1867,20 +1867,25 @@ _PyBytes_Join(PyObject *sep, PyObject *x) @text_signature "($self, sub[, start[, end]], /)" bytes.find - *args: object + sub: object + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the bytes. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the bytes. / Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. -Optional arguments 'start' and 'end' are interpreted as in slice notation. Return -1 on failure. [clinic start generated code]*/ static PyObject * -bytes_find_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=62e7a26240c8a4a2 input=f0bde0cb478d2b8c]*/ +bytes_find_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end) +/*[clinic end generated code: output=d5961a1c77b472a1 input=3171e62a8ae7f240]*/ { - return _Py_bytes_find(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_find(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + sub, start, end); } /*[clinic input] @@ -1889,15 +1894,16 @@ bytes.index = bytes.find Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. -Optional arguments start and end are interpreted as in slice notation. Raise ValueError if the subsection is not found. [clinic start generated code]*/ static PyObject * -bytes_index_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=866d781b6589b72f input=ffba1569b1c9af9b]*/ +bytes_index_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end) +/*[clinic end generated code: output=0da25cc74683ba42 input=712ec82ceee77c06]*/ { - return _Py_bytes_index(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_index(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + sub, start, end); } /*[clinic input] @@ -1906,15 +1912,16 @@ bytes.rfind = bytes.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. -Optional arguments 'start' and 'end' are interpreted as in slice notation. Return -1 on failure. [clinic start generated code]*/ static PyObject * -bytes_rfind_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=ae774c87c9c7a5af input=e42f537ca09ece2b]*/ +bytes_rfind_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end) +/*[clinic end generated code: output=51b60fa4ad011c09 input=19e2e378ffb1cad1]*/ { - return _Py_bytes_rfind(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_rfind(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + sub, start, end); } /*[clinic input] @@ -1923,15 +1930,16 @@ bytes.rindex = bytes.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. -Optional arguments start and end are interpreted as in slice notation. Raise ValueError if the subsection is not found. [clinic start generated code]*/ static PyObject * -bytes_rindex_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=6758f68eb1883d20 input=b7b56bf94364b8da]*/ +bytes_rindex_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end) +/*[clinic end generated code: output=42bf674e0a0aabf6 input=3a398f4797c1ab93]*/ { - return _Py_bytes_rindex(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_rindex(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + sub, start, end); } @@ -2073,15 +2081,15 @@ bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes) bytes.count = bytes.find Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end]. - -Optional arguments start and end are interpreted as in slice notation. [clinic start generated code]*/ static PyObject * -bytes_count_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=5d8c9f60259d3064 input=2a32925161376240]*/ +bytes_count_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end) +/*[clinic end generated code: output=9848140b9be17d0f input=e620ca81fb49f0de]*/ { - return _Py_bytes_count(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_count(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + sub, start, end); } diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 9cc638c3829964..a496cfd959f62e 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -107,35 +107,48 @@ PyDoc_STRVAR(bytearray_find__doc__, "\n" "Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" "\n" -"Optional arguments \'start\' and \'end\' are interpreted as in slice notation.\n" +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes.\n" +"\n" "Return -1 on failure."); #define BYTEARRAY_FIND_METHODDEF \ {"find", _PyCFunction_CAST(bytearray_find), METH_FASTCALL, bytearray_find__doc__}, static PyObject * -bytearray_find_impl(PyByteArrayObject *self, PyObject *args); +bytearray_find_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end); static PyObject * bytearray_find(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("find", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("find", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; } - return_value = bytearray_find_impl(self, __clinic_args); + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; + } +skip_optional: + return_value = bytearray_find_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -145,34 +158,46 @@ PyDoc_STRVAR(bytearray_count__doc__, "\n" "Return the number of non-overlapping occurrences of subsection \'sub\' in bytes B[start:end].\n" "\n" -"Optional arguments start and end are interpreted as in slice notation."); +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes."); #define BYTEARRAY_COUNT_METHODDEF \ {"count", _PyCFunction_CAST(bytearray_count), METH_FASTCALL, bytearray_count__doc__}, static PyObject * -bytearray_count_impl(PyByteArrayObject *self, PyObject *args); +bytearray_count_impl(PyByteArrayObject *self, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytearray_count(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("count", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("count", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytearray_count_impl(self, __clinic_args); +skip_optional: + return_value = bytearray_count_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -218,35 +243,48 @@ PyDoc_STRVAR(bytearray_index__doc__, "\n" "Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" "\n" -"Optional arguments start and end are interpreted as in slice notation.\n" +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes.\n" +"\n" "Raise ValueError if the subsection is not found."); #define BYTEARRAY_INDEX_METHODDEF \ {"index", _PyCFunction_CAST(bytearray_index), METH_FASTCALL, bytearray_index__doc__}, static PyObject * -bytearray_index_impl(PyByteArrayObject *self, PyObject *args); +bytearray_index_impl(PyByteArrayObject *self, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytearray_index(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("index", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("index", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytearray_index_impl(self, __clinic_args); +skip_optional: + return_value = bytearray_index_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -256,35 +294,48 @@ PyDoc_STRVAR(bytearray_rfind__doc__, "\n" "Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" "\n" -"Optional arguments \'start\' and \'end\' are interpreted as in slice notation.\n" +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes.\n" +"\n" "Return -1 on failure."); #define BYTEARRAY_RFIND_METHODDEF \ {"rfind", _PyCFunction_CAST(bytearray_rfind), METH_FASTCALL, bytearray_rfind__doc__}, static PyObject * -bytearray_rfind_impl(PyByteArrayObject *self, PyObject *args); +bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytearray_rfind(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("rfind", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("rfind", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; } - return_value = bytearray_rfind_impl(self, __clinic_args); + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; + } +skip_optional: + return_value = bytearray_rfind_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -294,35 +345,48 @@ PyDoc_STRVAR(bytearray_rindex__doc__, "\n" "Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" "\n" -"Optional arguments start and end are interpreted as in slice notation.\n" +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes.\n" +"\n" "Raise ValueError if the subsection is not found."); #define BYTEARRAY_RINDEX_METHODDEF \ {"rindex", _PyCFunction_CAST(bytearray_rindex), METH_FASTCALL, bytearray_rindex__doc__}, static PyObject * -bytearray_rindex_impl(PyByteArrayObject *self, PyObject *args); +bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytearray_rindex(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("rindex", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("rindex", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; } - return_value = bytearray_rindex_impl(self, __clinic_args); + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; + } +skip_optional: + return_value = bytearray_rindex_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -1552,4 +1616,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=c9b74241c4448dcb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c38e639d46457765 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index b1d1d787f05524..0d60b54e6ee07f 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -300,35 +300,48 @@ PyDoc_STRVAR(bytes_find__doc__, "\n" "Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" "\n" -"Optional arguments \'start\' and \'end\' are interpreted as in slice notation.\n" +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes.\n" +"\n" "Return -1 on failure."); #define BYTES_FIND_METHODDEF \ {"find", _PyCFunction_CAST(bytes_find), METH_FASTCALL, bytes_find__doc__}, static PyObject * -bytes_find_impl(PyBytesObject *self, PyObject *args); +bytes_find_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end); static PyObject * bytes_find(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("find", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("find", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytes_find_impl(self, __clinic_args); +skip_optional: + return_value = bytes_find_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -338,35 +351,48 @@ PyDoc_STRVAR(bytes_index__doc__, "\n" "Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" "\n" -"Optional arguments start and end are interpreted as in slice notation.\n" +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes.\n" +"\n" "Raise ValueError if the subsection is not found."); #define BYTES_INDEX_METHODDEF \ {"index", _PyCFunction_CAST(bytes_index), METH_FASTCALL, bytes_index__doc__}, static PyObject * -bytes_index_impl(PyBytesObject *self, PyObject *args); +bytes_index_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end); static PyObject * bytes_index(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("index", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("index", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytes_index_impl(self, __clinic_args); +skip_optional: + return_value = bytes_index_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -376,35 +402,48 @@ PyDoc_STRVAR(bytes_rfind__doc__, "\n" "Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" "\n" -"Optional arguments \'start\' and \'end\' are interpreted as in slice notation.\n" +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes.\n" +"\n" "Return -1 on failure."); #define BYTES_RFIND_METHODDEF \ {"rfind", _PyCFunction_CAST(bytes_rfind), METH_FASTCALL, bytes_rfind__doc__}, static PyObject * -bytes_rfind_impl(PyBytesObject *self, PyObject *args); +bytes_rfind_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end); static PyObject * bytes_rfind(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("rfind", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("rfind", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytes_rfind_impl(self, __clinic_args); +skip_optional: + return_value = bytes_rfind_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -414,35 +453,48 @@ PyDoc_STRVAR(bytes_rindex__doc__, "\n" "Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" "\n" -"Optional arguments start and end are interpreted as in slice notation.\n" +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes.\n" +"\n" "Raise ValueError if the subsection is not found."); #define BYTES_RINDEX_METHODDEF \ {"rindex", _PyCFunction_CAST(bytes_rindex), METH_FASTCALL, bytes_rindex__doc__}, static PyObject * -bytes_rindex_impl(PyBytesObject *self, PyObject *args); +bytes_rindex_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end); static PyObject * bytes_rindex(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("rindex", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("rindex", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytes_rindex_impl(self, __clinic_args); +skip_optional: + return_value = bytes_rindex_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -554,34 +606,46 @@ PyDoc_STRVAR(bytes_count__doc__, "\n" "Return the number of non-overlapping occurrences of subsection \'sub\' in bytes B[start:end].\n" "\n" -"Optional arguments start and end are interpreted as in slice notation."); +" start\n" +" Optional start position. Default: start of the bytes.\n" +" end\n" +" Optional stop position. Default: end of the bytes."); #define BYTES_COUNT_METHODDEF \ {"count", _PyCFunction_CAST(bytes_count), METH_FASTCALL, bytes_count__doc__}, static PyObject * -bytes_count_impl(PyBytesObject *self, PyObject *args); +bytes_count_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, + Py_ssize_t end); static PyObject * bytes_count(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *sub; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("count", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("count", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + sub = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytes_count_impl(self, __clinic_args); +skip_optional: + return_value = bytes_count_impl(self, sub, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -1320,4 +1384,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=bdf8d4778dfd3c63 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=35e40c2444afd1ee input=a9049054013a1b77]*/ From 2443309e1baf0eceb5e52b2d7c172dc72dfed739 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 12:23:50 +0200 Subject: [PATCH 12/21] Address Inada-san's review: indent clinic input and consistently use 'the bytes' and 'the bytearray' in docstring --- Objects/bytearrayobject.c | 10 +++++----- Objects/bytesobject.c | 10 +++++----- Objects/clinic/bytearrayobject.c.h | 4 ++-- Objects/clinic/bytesobject.c.h | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index e9763dfe338fe2..8639496727536a 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1193,9 +1193,9 @@ bytearray.startswith prefix as subobj: object A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None - Optional start position. Default: start of the bytearray. + Optional start position. Default: start of the bytearray. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None - Optional stop position. Default: end of the bytearray. + Optional stop position. Default: end of the bytearray. / Return True if the bytearray starts with the specified prefix, False otherwise. @@ -1204,7 +1204,7 @@ Return True if the bytearray starts with the specified prefix, False otherwise. static PyObject * bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=a3d9b6d44d3662a6 input=5815c1138cf1ba28]*/ +/*[clinic end generated code: output=a3d9b6d44d3662a6 input=76385e0b376b45c1]*/ { return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); @@ -1222,13 +1222,13 @@ bytearray.endswith Optional stop position. Default: end of the bytearray. / -Return True if the byte string ends with the specified suffix, False otherwise. +Return True if the bytearray ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=e75ea8c227954caa input=3b63c2dc878407c2]*/ +/*[clinic end generated code: output=e75ea8c227954caa input=9b8baa879aa3d74b]*/ { return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 33e3fc3da41e16..d7b0c6b7b01aa9 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2292,9 +2292,9 @@ bytes.startswith prefix as subobj: object A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None - Optional start position. Default: start of the bytes. + Optional start position. Default: start of the bytes. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None - Optional stop position. Default: end of the bytes. + Optional stop position. Default: end of the bytes. / Return True if the bytes starts with the specified prefix, False otherwise. @@ -2303,7 +2303,7 @@ Return True if the bytes starts with the specified prefix, False otherwise. static PyObject * bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=b1e8da1cbd528e8c input=917d9cf26c33b96a]*/ +/*[clinic end generated code: output=b1e8da1cbd528e8c input=8a4165df8adfa6c9]*/ { return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), subobj, start, end); @@ -2321,13 +2321,13 @@ bytes.endswith Optional stop position. Default: end of the bytes. / -Return True if the byte string ends with the specified suffix, False otherwise. +Return True if the bytes ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=038b633111f3629d input=66b64eccac830889]*/ +/*[clinic end generated code: output=038b633111f3629d input=b5c3407a2a5c9aac]*/ { return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index b4743ad8cad947..dabc2b16c94fce 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -192,7 +192,7 @@ PyDoc_STRVAR(bytearray_endswith__doc__, "endswith($self, suffix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string ends with the specified suffix, False otherwise.\n" +"Return True if the bytearray ends with the specified suffix, False otherwise.\n" "\n" " suffix\n" " A bytes or a tuple of bytes to try.\n" @@ -1363,4 +1363,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=4264a5341cb44fef input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0147908e97ebe882 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 944b882e01472d..05e182778aece1 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -707,7 +707,7 @@ PyDoc_STRVAR(bytes_endswith__doc__, "endswith($self, suffix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string ends with the specified suffix, False otherwise.\n" +"Return True if the bytes ends with the specified suffix, False otherwise.\n" "\n" " suffix\n" " A bytes or a tuple of bytes to try.\n" @@ -1131,4 +1131,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=48f0667452337301 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f2b10ccd2e3155c3 input=a9049054013a1b77]*/ From 3e9e733c16a40189e84b5b0cfae80368d2691530 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 13:17:47 +0200 Subject: [PATCH 13/21] Amend NEWS entry --- .../2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst index 17374d0d5c575b..5aa86a0c39a376 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst @@ -2,5 +2,10 @@ Improve the performance of the following :class:`bytes` and :class:`bytearray` methods by adapting them to the :c:macro:`METH_FASTCALL` calling convention: +* :meth:`!count` * :meth:`!endswith` +* :meth:`!find` +* :meth:`!index` +* :meth:`!rfind` +* :meth:`!rindex` * :meth:`!startswith` From 096a23285d22eebf179e7fb0eaf030eafa504875 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 18:04:10 +0200 Subject: [PATCH 14/21] Remove now unused STRINGLIB_parse_args_finds --- Objects/stringlib/find.h | 47 ---------------------------------------- 1 file changed, 47 deletions(-) diff --git a/Objects/stringlib/find.h b/Objects/stringlib/find.h index 509b9297396be8..c385718a5b2692 100644 --- a/Objects/stringlib/find.h +++ b/Objects/stringlib/find.h @@ -70,50 +70,3 @@ STRINGLIB(contains_obj)(PyObject* str, PyObject* sub) } #endif /* STRINGLIB_WANT_CONTAINS_OBJ */ - -/* -This function is a helper for the "find" family (find, rfind, index, -rindex) and for count, startswith and endswith, because they all have -the same behaviour for the arguments. - -It does not touch the variables received until it knows everything -is ok. -*/ - -#define FORMAT_BUFFER_SIZE 50 - -Py_LOCAL_INLINE(int) -STRINGLIB(parse_args_finds)(const char * function_name, PyObject *args, - PyObject **subobj, - Py_ssize_t *start, Py_ssize_t *end) -{ - PyObject *tmp_subobj; - Py_ssize_t tmp_start = 0; - Py_ssize_t tmp_end = PY_SSIZE_T_MAX; - PyObject *obj_start=Py_None, *obj_end=Py_None; - char format[FORMAT_BUFFER_SIZE] = "O|OO:"; - size_t len = strlen(format); - - strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1); - format[FORMAT_BUFFER_SIZE - 1] = '\0'; - - if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end)) - return 0; - - /* To support None in "start" and "end" arguments, meaning - the same as if they were not passed. - */ - if (obj_start != Py_None) - if (!_PyEval_SliceIndex(obj_start, &tmp_start)) - return 0; - if (obj_end != Py_None) - if (!_PyEval_SliceIndex(obj_end, &tmp_end)) - return 0; - - *start = tmp_start; - *end = tmp_end; - *subobj = tmp_subobj; - return 1; -} - -#undef FORMAT_BUFFER_SIZE From f937faa2b4b459227cc30c4b929e2f2b3ab8aec9 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 10 Apr 2024 10:15:48 +0200 Subject: [PATCH 15/21] Remove now unneeded @text_signature's --- Objects/bytearrayobject.c | 12 ++++-------- Objects/bytesobject.c | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 123bea21e0db54..802cc475f19536 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1147,7 +1147,6 @@ bytearray_find_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, } /*[clinic input] -@text_signature "($self, sub[, start[, end]], /)" bytearray.count = bytearray.find Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end]. @@ -1156,7 +1155,7 @@ Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[ static PyObject * bytearray_count_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=a21ee2692e4f1233 input=f4582e0f6bc42fd7]*/ +/*[clinic end generated code: output=a21ee2692e4f1233 input=4deb529db38deda8]*/ { return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), sub, start, end); @@ -1192,7 +1191,6 @@ bytearray_copy_impl(PyByteArrayObject *self) } /*[clinic input] -@text_signature "($self, sub[, start[, end]], /)" bytearray.index = bytearray.find Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. @@ -1203,14 +1201,13 @@ Raise ValueError if the subsection is not found. static PyObject * bytearray_index_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=067a1e78efc672a7 input=5dab02095748cc92]*/ +/*[clinic end generated code: output=067a1e78efc672a7 input=78239d5ea77ce955]*/ { return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), sub, start, end); } /*[clinic input] -@text_signature "($self, sub[, start[, end]], /)" bytearray.rfind = bytearray.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. @@ -1221,14 +1218,13 @@ Return -1 on failure. static PyObject * bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=51bf886f932b283c input=0c059ef74263f94b]*/ +/*[clinic end generated code: output=51bf886f932b283c input=235e5579a8e22f17]*/ { return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), sub, start, end); } /*[clinic input] -@text_signature "($self, sub[, start[, end]], /)" bytearray.rindex = bytearray.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. @@ -1239,7 +1235,7 @@ Raise ValueError if the subsection is not found. static PyObject * bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=38e1cf66bafb08b9 input=b1e0254a85220795]*/ +/*[clinic end generated code: output=38e1cf66bafb08b9 input=dcf4f35717461bff]*/ { return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), sub, start, end); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 690ba7a0d74af1..cd799a926ae63c 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1889,7 +1889,6 @@ bytes_find_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, } /*[clinic input] -@text_signature "($self, sub[, start[, end]], /)" bytes.index = bytes.find Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. @@ -1900,14 +1899,13 @@ Raise ValueError if the subsection is not found. static PyObject * bytes_index_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=0da25cc74683ba42 input=712ec82ceee77c06]*/ +/*[clinic end generated code: output=0da25cc74683ba42 input=aa34ad71ba0bafe3]*/ { return _Py_bytes_index(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), sub, start, end); } /*[clinic input] -@text_signature "($self, sub[, start[, end]], /)" bytes.rfind = bytes.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. @@ -1918,14 +1916,13 @@ Return -1 on failure. static PyObject * bytes_rfind_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=51b60fa4ad011c09 input=19e2e378ffb1cad1]*/ +/*[clinic end generated code: output=51b60fa4ad011c09 input=864c3e7f3010b33c]*/ { return _Py_bytes_rfind(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), sub, start, end); } /*[clinic input] -@text_signature "($self, sub[, start[, end]], /)" bytes.rindex = bytes.find Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. @@ -1936,7 +1933,7 @@ Raise ValueError if the subsection is not found. static PyObject * bytes_rindex_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=42bf674e0a0aabf6 input=3a398f4797c1ab93]*/ +/*[clinic end generated code: output=42bf674e0a0aabf6 input=21051fc5cfeacf2c]*/ { return _Py_bytes_rindex(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), sub, start, end); @@ -2077,7 +2074,6 @@ bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes) /*[clinic input] -@text_signature "($self, sub[, start[, end]], /)" bytes.count = bytes.find Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end]. @@ -2086,7 +2082,7 @@ Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[ static PyObject * bytes_count_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=9848140b9be17d0f input=e620ca81fb49f0de]*/ +/*[clinic end generated code: output=9848140b9be17d0f input=b6e4a5ed515e1e59]*/ { return _Py_bytes_count(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), sub, start, end); From d6715241d43c202524caa4f94ad9a5e04685c141 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 12 Apr 2024 09:01:53 +0200 Subject: [PATCH 16/21] Apply suggestions from code review Co-authored-by: Inada Naoki --- Objects/bytearrayobject.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 802cc475f19536..8336161383a3b4 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1132,7 +1132,7 @@ bytearray.find Optional stop position. Default: end of the bytes. / -Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. +Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end]. Return -1 on failure. [clinic start generated code]*/ @@ -1193,7 +1193,7 @@ bytearray_copy_impl(PyByteArrayObject *self) /*[clinic input] bytearray.index = bytearray.find -Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. +Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end]. Raise ValueError if the subsection is not found. [clinic start generated code]*/ @@ -1227,7 +1227,7 @@ bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub, /*[clinic input] bytearray.rindex = bytearray.find -Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. +Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end]. Raise ValueError if the subsection is not found. [clinic start generated code]*/ From c83c5d1e34a1e4f4f3caca37bdd67045fab46453 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 12 Apr 2024 09:03:14 +0200 Subject: [PATCH 17/21] Regen clinic --- Objects/bytearrayobject.c | 6 +++--- Objects/clinic/bytearrayobject.c.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 8336161383a3b4..269865a8a836dd 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1140,7 +1140,7 @@ Return -1 on failure. static PyObject * bytearray_find_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=413e1cab2ae87da0 input=27dce3d6f4f24c31]*/ +/*[clinic end generated code: output=413e1cab2ae87da0 input=793dfad803e2952f]*/ { return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), sub, start, end); @@ -1201,7 +1201,7 @@ Raise ValueError if the subsection is not found. static PyObject * bytearray_index_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=067a1e78efc672a7 input=78239d5ea77ce955]*/ +/*[clinic end generated code: output=067a1e78efc672a7 input=8cbaf6836dbd2a9a]*/ { return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), sub, start, end); @@ -1235,7 +1235,7 @@ Raise ValueError if the subsection is not found. static PyObject * bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=38e1cf66bafb08b9 input=dcf4f35717461bff]*/ +/*[clinic end generated code: output=38e1cf66bafb08b9 input=81cf49d0af4d5bd0]*/ { return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), sub, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index c1b970d15716f8..59be9a295dc629 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -105,7 +105,7 @@ PyDoc_STRVAR(bytearray_find__doc__, "find($self, sub[, start[, end]], /)\n" "--\n" "\n" -"Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start:end].\n" "\n" " start\n" " Optional start position. Default: start of the bytes.\n" @@ -241,7 +241,7 @@ PyDoc_STRVAR(bytearray_index__doc__, "index($self, sub[, start[, end]], /)\n" "--\n" "\n" -"Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"Return the lowest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start:end].\n" "\n" " start\n" " Optional start position. Default: start of the bytes.\n" @@ -343,7 +343,7 @@ PyDoc_STRVAR(bytearray_rindex__doc__, "rindex($self, sub[, start[, end]], /)\n" "--\n" "\n" -"Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start:end].\n" "\n" " start\n" " Optional start position. Default: start of the bytes.\n" @@ -1616,4 +1616,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=5a5c9cdc24858a0a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=77ba9ddf79f9b124 input=a9049054013a1b77]*/ From 747ecf93f6ca1b9c7cb725de0cd0cc8358f51cb1 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 12 Apr 2024 09:04:21 +0200 Subject: [PATCH 18/21] Update Objects/bytearrayobject.c Co-authored-by: Inada Naoki --- Objects/bytearrayobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 269865a8a836dd..6f41fff19fb909 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1210,7 +1210,7 @@ bytearray_index_impl(PyByteArrayObject *self, PyObject *sub, /*[clinic input] bytearray.rfind = bytearray.find -Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start,end]. +Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end]. Return -1 on failure. [clinic start generated code]*/ From 0ad3919466e47227d3c0e0ad312c64c544f55fdc Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 12 Apr 2024 09:05:24 +0200 Subject: [PATCH 19/21] Again --- Objects/bytearrayobject.c | 2 +- Objects/clinic/bytearrayobject.c.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 6f41fff19fb909..80679f93cd4c13 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1218,7 +1218,7 @@ Return -1 on failure. static PyObject * bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=51bf886f932b283c input=235e5579a8e22f17]*/ +/*[clinic end generated code: output=51bf886f932b283c input=eaa107468a158423]*/ { return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), sub, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 59be9a295dc629..c748c53e1c0a75 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -292,7 +292,7 @@ PyDoc_STRVAR(bytearray_rfind__doc__, "rfind($self, sub[, start[, end]], /)\n" "--\n" "\n" -"Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start,end].\n" +"Return the highest index in B where subsection \'sub\' is found, such that \'sub\' is contained within B[start:end].\n" "\n" " start\n" " Optional start position. Default: start of the bytes.\n" @@ -1616,4 +1616,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=77ba9ddf79f9b124 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5f861b02e3fa278b input=a9049054013a1b77]*/ From f0cdf7049bafd3079bf224867081b72bcf47f6f2 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 12 Apr 2024 09:09:58 +0200 Subject: [PATCH 20/21] NEWS From 9bb65d2c4635ff9c9b20012965a5f996179e95be Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 12 Apr 2024 09:11:51 +0200 Subject: [PATCH 21/21] Correct NEWS entry --- Misc/NEWS.d/3.13.0a6.rst | 5 ----- .../2024-04-12-09-09-11.gh-issue-117431.lxFEeJ.rst | 9 +++++++++ 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-12-09-09-11.gh-issue-117431.lxFEeJ.rst diff --git a/Misc/NEWS.d/3.13.0a6.rst b/Misc/NEWS.d/3.13.0a6.rst index 72b204b64c08bc..06807b396ed5da 100644 --- a/Misc/NEWS.d/3.13.0a6.rst +++ b/Misc/NEWS.d/3.13.0a6.rst @@ -55,12 +55,7 @@ Improve the performance of the following :class:`bytes` and :class:`bytearray` methods by adapting them to the :c:macro:`METH_FASTCALL` calling convention: -* :meth:`!count` * :meth:`!endswith` -* :meth:`!find` -* :meth:`!index` -* :meth:`!rfind` -* :meth:`!rindex` * :meth:`!startswith` .. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-12-09-09-11.gh-issue-117431.lxFEeJ.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-12-09-09-11.gh-issue-117431.lxFEeJ.rst new file mode 100644 index 00000000000000..0d94389aba124a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-12-09-09-11.gh-issue-117431.lxFEeJ.rst @@ -0,0 +1,9 @@ +Improve the performance of the following :class:`bytes` and +:class:`bytearray` methods by adapting them to the :c:macro:`METH_FASTCALL` +calling convention: + +* :meth:`!count` +* :meth:`!find` +* :meth:`!index` +* :meth:`!rfind` +* :meth:`!rindex`