summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend@python.org>2024-04-12 07:40:55 (GMT)
committerGitHub <noreply@github.com>2024-04-12 07:40:55 (GMT)
commitdeb921f85173a194afb4386553d85c3f99767ca1 (patch)
treec5f32d62bf1ad727f25f6e8b084876c32d8a96e2
parent49fc1414b52b31f6ad0408775d160ec0559c33bb (diff)
downloadcpython-deb921f85173a194afb4386553d85c3f99767ca1.zip
cpython-deb921f85173a194afb4386553d85c3f99767ca1.tar.gz
cpython-deb921f85173a194afb4386553d85c3f99767ca1.tar.bz2
gh-117431: Adapt bytes and bytearray .find() and friends to Argument Clinic (#117502)
This change gives a significant speedup, as the METH_FASTCALL calling convention is now used. The following bytes and bytearray methods are adapted: - count() - find() - index() - rfind() - rindex() Co-authored-by: Inada Naoki <songofacandy@gmail.com>
-rw-r--r--Include/internal/pycore_bytes_methods.h15
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-04-12-09-09-11.gh-issue-117431.lxFEeJ.rst9
-rw-r--r--Objects/bytearrayobject.c93
-rw-r--r--Objects/bytes_methods.c102
-rw-r--r--Objects/bytesobject.c91
-rw-r--r--Objects/clinic/bytearrayobject.c.h255
-rw-r--r--Objects/clinic/bytesobject.c.h255
-rw-r--r--Objects/stringlib/find.h47
8 files changed, 703 insertions, 164 deletions
diff --git a/Include/internal/pycore_bytes_methods.h b/Include/internal/pycore_bytes_methods.h
index b9c0a4e..059dc25 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/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 0000000..0d94389
--- /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`
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 8639496..80679f9 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -1121,16 +1121,44 @@ bytearray_dealloc(PyByteArrayObject *self)
#include "stringlib/transmogrify.h"
+/*[clinic input]
+@text_signature "($self, sub[, start[, end]], /)"
+bytearray.find
+
+ 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].
+
+Return -1 on failure.
+[clinic start generated code]*/
+
static PyObject *
-bytearray_find(PyByteArrayObject *self, PyObject *args)
+bytearray_find_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start,
+ Py_ssize_t end)
+/*[clinic end generated code: output=413e1cab2ae87da0 input=793dfad803e2952f]*/
{
- 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]
+bytearray.count = bytearray.find
+
+Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end].
+[clinic start generated code]*/
+
static PyObject *
-bytearray_count(PyByteArrayObject *self, PyObject *args)
+bytearray_count_impl(PyByteArrayObject *self, PyObject *sub,
+ Py_ssize_t start, Py_ssize_t end)
+/*[clinic end generated code: output=a21ee2692e4f1233 input=4deb529db38deda8]*/
{
- 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]
@@ -1162,22 +1190,55 @@ bytearray_copy_impl(PyByteArrayObject *self)
PyByteArray_GET_SIZE(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].
+
+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 *sub,
+ Py_ssize_t start, Py_ssize_t end)
+/*[clinic end generated code: output=067a1e78efc672a7 input=8cbaf6836dbd2a9a]*/
{
- 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]
+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 -1 on failure.
+[clinic start generated code]*/
+
static PyObject *
-bytearray_rfind(PyByteArrayObject *self, PyObject *args)
+bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub,
+ Py_ssize_t start, Py_ssize_t end)
+/*[clinic end generated code: output=51bf886f932b283c input=eaa107468a158423]*/
{
- 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]
+bytearray.rindex = bytearray.find
+
+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]*/
+
static PyObject *
-bytearray_rindex(PyByteArrayObject *self, PyObject *args)
+bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub,
+ Py_ssize_t start, Py_ssize_t end)
+/*[clinic end generated code: output=38e1cf66bafb08b9 input=81cf49d0af4d5bd0]*/
{
- 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
@@ -2236,17 +2297,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__},
@@ -2276,8 +2335,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 21b6668..981aa57 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)
@@ -566,37 +556,21 @@ 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)
+_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);
}
-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)
+_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) {
@@ -607,37 +581,21 @@ _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)
+_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);
}
-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)
+_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) {
@@ -648,28 +606,20 @@ _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)
+_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 d576dd9..cd799a9 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1863,30 +1863,80 @@ _PyBytes_Join(PyObject *sep, PyObject *x)
return bytes_join((PyBytesObject*)sep, x);
}
+/*[clinic input]
+@text_signature "($self, sub[, start[, end]], /)"
+bytes.find
+
+ 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].
+
+Return -1 on failure.
+[clinic start generated code]*/
+
static PyObject *
-bytes_find(PyBytesObject *self, PyObject *args)
+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]
+bytes.index = bytes.find
+
+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]*/
+
static PyObject *
-bytes_index(PyBytesObject *self, PyObject *args)
+bytes_index_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start,
+ Py_ssize_t end)
+/*[clinic end generated code: output=0da25cc74683ba42 input=aa34ad71ba0bafe3]*/
{
- 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]
+bytes.rfind = bytes.find
+
+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]*/
static PyObject *
-bytes_rfind(PyBytesObject *self, PyObject *args)
+bytes_rfind_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start,
+ Py_ssize_t end)
+/*[clinic end generated code: output=51b60fa4ad011c09 input=864c3e7f3010b33c]*/
{
- 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]
+bytes.rindex = bytes.find
+
+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]*/
static PyObject *
-bytes_rindex(PyBytesObject *self, PyObject *args)
+bytes_rindex_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start,
+ Py_ssize_t end)
+/*[clinic end generated code: output=42bf674e0a0aabf6 input=21051fc5cfeacf2c]*/
{
- 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);
}
@@ -2023,10 +2073,19 @@ bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes)
}
+/*[clinic input]
+bytes.count = bytes.find
+
+Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end].
+[clinic start generated code]*/
+
static PyObject *
-bytes_count(PyBytesObject *self, PyObject *args)
+bytes_count_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start,
+ Py_ssize_t end)
+/*[clinic end generated code: output=9848140b9be17d0f input=b6e4a5ed515e1e59]*/
{
- 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);
}
@@ -2524,16 +2583,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,
@@ -2559,8 +2616,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 dabc2b1..c748c53 100644
--- a/Objects/clinic/bytearrayobject.c.h
+++ b/Objects/clinic/bytearrayobject.c.h
@@ -101,6 +101,106 @@ exit:
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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("find", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytearray_find_impl(self, sub, start, end);
+
+exit:
+ 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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("count", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytearray_count_impl(self, sub, start, end);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(bytearray_clear__doc__,
"clear($self, /)\n"
"--\n"
@@ -137,6 +237,159 @@ 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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("index", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytearray_index_impl(self, sub, start, end);
+
+exit:
+ 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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("rfind", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytearray_rfind_impl(self, sub, start, end);
+
+exit:
+ 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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("rindex", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytearray_rindex_impl(self, sub, start, end);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(bytearray_startswith__doc__,
"startswith($self, prefix[, start[, end]], /)\n"
"--\n"
@@ -1363,4 +1616,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl(self);
}
-/*[clinic end generated code: output=0147908e97ebe882 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5f861b02e3fa278b input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h
index 05e1827..0b4b375 100644
--- a/Objects/clinic/bytesobject.c.h
+++ b/Objects/clinic/bytesobject.c.h
@@ -294,6 +294,210 @@ 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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("find", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytes_find_impl(self, sub, start, end);
+
+exit:
+ 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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("index", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytes_index_impl(self, sub, start, end);
+
+exit:
+ 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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("rfind", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytes_rfind_impl(self, sub, start, end);
+
+exit:
+ 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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("rindex", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytes_rindex_impl(self, sub, start, end);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(bytes_strip__doc__,
"strip($self, bytes=None, /)\n"
"--\n"
@@ -396,6 +600,55 @@ exit:
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"
+" 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 *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 *sub;
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+
+ if (!_PyArg_CheckPositional("count", nargs, 1, 3)) {
+ goto exit;
+ }
+ sub = args[0];
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[1], &start)) {
+ goto exit;
+ }
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!_PyEval_SliceIndex(args[2], &end)) {
+ goto exit;
+ }
+skip_optional:
+ return_value = bytes_count_impl(self, sub, start, end);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(bytes_translate__doc__,
"translate($self, table, /, delete=b\'\')\n"
"--\n"
@@ -1131,4 +1384,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=f2b10ccd2e3155c3 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=d6801c6001e57f91 input=a9049054013a1b77]*/
diff --git a/Objects/stringlib/find.h b/Objects/stringlib/find.h
index 509b929..c385718 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