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>
This commit is contained in:
Erlend E. Aasland 2024-04-12 09:40:55 +02:00 committed by GitHub
parent 49fc1414b5
commit deb921f851
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 709 additions and 170 deletions

View file

@ -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)