mirror of https://github.com/python/cpython
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:
parent
49fc1414b5
commit
deb921f851
|
@ -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_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 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_find(const char *str, Py_ssize_t len, PyObject *sub,
|
||||||
extern PyObject *_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args);
|
Py_ssize_t start, Py_ssize_t end);
|
||||||
extern PyObject *_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args);
|
extern PyObject *_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *sub,
|
||||||
extern PyObject *_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args);
|
Py_ssize_t start, Py_ssize_t end);
|
||||||
extern PyObject *_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args);
|
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 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,
|
extern PyObject *_Py_bytes_startswith(const char *str, Py_ssize_t len,
|
||||||
PyObject *subobj, Py_ssize_t start,
|
PyObject *subobj, Py_ssize_t start,
|
||||||
|
|
|
@ -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`
|
|
@ -1121,16 +1121,44 @@ bytearray_dealloc(PyByteArrayObject *self)
|
||||||
#include "stringlib/transmogrify.h"
|
#include "stringlib/transmogrify.h"
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
/*[clinic input]
|
||||||
bytearray_find(PyByteArrayObject *self, PyObject *args)
|
@text_signature "($self, sub[, start[, end]], /)"
|
||||||
{
|
bytearray.find
|
||||||
return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
|
||||||
}
|
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 *
|
static PyObject *
|
||||||
bytearray_count(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_count(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_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),
|
||||||
|
sub, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
@ -1162,22 +1190,55 @@ bytearray_copy_impl(PyByteArrayObject *self)
|
||||||
PyByteArray_GET_SIZE(self));
|
PyByteArray_GET_SIZE(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
/*[clinic input]
|
||||||
bytearray_index(PyByteArrayObject *self, PyObject *args)
|
bytearray.index = bytearray.find
|
||||||
{
|
|
||||||
return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
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 *
|
static PyObject *
|
||||||
bytearray_rfind(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_rfind(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 *
|
static PyObject *
|
||||||
bytearray_rindex(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_rindex(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_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),
|
||||||
|
sub, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -2236,17 +2297,15 @@ bytearray_methods[] = {
|
||||||
STRINGLIB_CENTER_METHODDEF
|
STRINGLIB_CENTER_METHODDEF
|
||||||
BYTEARRAY_CLEAR_METHODDEF
|
BYTEARRAY_CLEAR_METHODDEF
|
||||||
BYTEARRAY_COPY_METHODDEF
|
BYTEARRAY_COPY_METHODDEF
|
||||||
{"count", (PyCFunction)bytearray_count, METH_VARARGS,
|
BYTEARRAY_COUNT_METHODDEF
|
||||||
_Py_count__doc__},
|
|
||||||
BYTEARRAY_DECODE_METHODDEF
|
BYTEARRAY_DECODE_METHODDEF
|
||||||
BYTEARRAY_ENDSWITH_METHODDEF
|
BYTEARRAY_ENDSWITH_METHODDEF
|
||||||
STRINGLIB_EXPANDTABS_METHODDEF
|
STRINGLIB_EXPANDTABS_METHODDEF
|
||||||
BYTEARRAY_EXTEND_METHODDEF
|
BYTEARRAY_EXTEND_METHODDEF
|
||||||
{"find", (PyCFunction)bytearray_find, METH_VARARGS,
|
BYTEARRAY_FIND_METHODDEF
|
||||||
_Py_find__doc__},
|
|
||||||
BYTEARRAY_FROMHEX_METHODDEF
|
BYTEARRAY_FROMHEX_METHODDEF
|
||||||
BYTEARRAY_HEX_METHODDEF
|
BYTEARRAY_HEX_METHODDEF
|
||||||
{"index", (PyCFunction)bytearray_index, METH_VARARGS, _Py_index__doc__},
|
BYTEARRAY_INDEX_METHODDEF
|
||||||
BYTEARRAY_INSERT_METHODDEF
|
BYTEARRAY_INSERT_METHODDEF
|
||||||
{"isalnum", stringlib_isalnum, METH_NOARGS,
|
{"isalnum", stringlib_isalnum, METH_NOARGS,
|
||||||
_Py_isalnum__doc__},
|
_Py_isalnum__doc__},
|
||||||
|
@ -2276,8 +2335,8 @@ bytearray_methods[] = {
|
||||||
BYTEARRAY_REMOVEPREFIX_METHODDEF
|
BYTEARRAY_REMOVEPREFIX_METHODDEF
|
||||||
BYTEARRAY_REMOVESUFFIX_METHODDEF
|
BYTEARRAY_REMOVESUFFIX_METHODDEF
|
||||||
BYTEARRAY_REVERSE_METHODDEF
|
BYTEARRAY_REVERSE_METHODDEF
|
||||||
{"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__},
|
BYTEARRAY_RFIND_METHODDEF
|
||||||
{"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__},
|
BYTEARRAY_RINDEX_METHODDEF
|
||||||
STRINGLIB_RJUST_METHODDEF
|
STRINGLIB_RJUST_METHODDEF
|
||||||
BYTEARRAY_RPARTITION_METHODDEF
|
BYTEARRAY_RPARTITION_METHODDEF
|
||||||
BYTEARRAY_RSPLIT_METHODDEF
|
BYTEARRAY_RSPLIT_METHODDEF
|
||||||
|
|
|
@ -453,31 +453,21 @@ stringlib_parse_args_finds().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Py_LOCAL_INLINE(int)
|
Py_LOCAL_INLINE(int)
|
||||||
parse_args_finds_byte(const char *function_name, PyObject *args,
|
parse_args_finds_byte(const char *function_name, PyObject **subobj, char *byte)
|
||||||
PyObject **subobj, char *byte,
|
|
||||||
Py_ssize_t *start, Py_ssize_t *end)
|
|
||||||
{
|
{
|
||||||
PyObject *tmp_subobj;
|
if (PyObject_CheckBuffer(*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;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_PyIndex_Check(tmp_subobj)) {
|
if (!_PyIndex_Check(*subobj)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"argument should be integer or bytes-like object, "
|
"argument should be integer or bytes-like object, "
|
||||||
"not '%.200s'",
|
"not '%.200s'",
|
||||||
Py_TYPE(tmp_subobj)->tp_name);
|
Py_TYPE(*subobj)->tp_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ival = PyNumber_AsSsize_t(tmp_subobj, NULL);
|
Py_ssize_t ival = PyNumber_AsSsize_t(*subobj, NULL);
|
||||||
if (ival == -1 && PyErr_Occurred()) {
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -508,19 +498,19 @@ parse_args_finds_byte(const char *function_name, PyObject *args,
|
||||||
|
|
||||||
Py_LOCAL_INLINE(Py_ssize_t)
|
Py_LOCAL_INLINE(Py_ssize_t)
|
||||||
find_internal(const char *str, Py_ssize_t len,
|
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;
|
char byte;
|
||||||
Py_buffer subbuf;
|
Py_buffer subbuf;
|
||||||
const char *sub;
|
const char *sub;
|
||||||
Py_ssize_t sub_len;
|
Py_ssize_t sub_len;
|
||||||
Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
|
|
||||||
Py_ssize_t res;
|
Py_ssize_t res;
|
||||||
|
|
||||||
if (!parse_args_finds_byte(function_name, args,
|
if (!parse_args_finds_byte(function_name, &subobj, &byte)) {
|
||||||
&subobj, &byte, &start, &end))
|
|
||||||
return -2;
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
if (subobj) {
|
if (subobj) {
|
||||||
if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
|
if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
|
||||||
|
@ -566,37 +556,21 @@ find_internal(const char *str, Py_ssize_t len,
|
||||||
return res;
|
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 *
|
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)
|
if (result == -2)
|
||||||
return NULL;
|
return NULL;
|
||||||
return PyLong_FromSsize_t(result);
|
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 *
|
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)
|
if (result == -2)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
|
@ -607,37 +581,21 @@ _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args)
|
||||||
return PyLong_FromSsize_t(result);
|
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 *
|
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)
|
if (result == -2)
|
||||||
return NULL;
|
return NULL;
|
||||||
return PyLong_FromSsize_t(result);
|
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 *
|
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)
|
if (result == -2)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
|
@ -648,28 +606,20 @@ _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args)
|
||||||
return PyLong_FromSsize_t(result);
|
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 *
|
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;
|
const char *sub;
|
||||||
Py_ssize_t sub_len;
|
Py_ssize_t sub_len;
|
||||||
char byte;
|
char byte;
|
||||||
Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
|
|
||||||
|
|
||||||
Py_buffer vsub;
|
Py_buffer vsub;
|
||||||
PyObject *count_obj;
|
PyObject *count_obj;
|
||||||
|
|
||||||
if (!parse_args_finds_byte("count", args,
|
if (!parse_args_finds_byte("count", &sub_obj, &byte)) {
|
||||||
&sub_obj, &byte, &start, &end))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (sub_obj) {
|
if (sub_obj) {
|
||||||
if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
|
if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
|
||||||
|
|
|
@ -1863,30 +1863,80 @@ _PyBytes_Join(PyObject *sep, PyObject *x)
|
||||||
return bytes_join((PyBytesObject*)sep, 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 *
|
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 *
|
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 *
|
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 *
|
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 *
|
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,
|
{"capitalize", stringlib_capitalize, METH_NOARGS,
|
||||||
_Py_capitalize__doc__},
|
_Py_capitalize__doc__},
|
||||||
STRINGLIB_CENTER_METHODDEF
|
STRINGLIB_CENTER_METHODDEF
|
||||||
{"count", (PyCFunction)bytes_count, METH_VARARGS,
|
BYTES_COUNT_METHODDEF
|
||||||
_Py_count__doc__},
|
|
||||||
BYTES_DECODE_METHODDEF
|
BYTES_DECODE_METHODDEF
|
||||||
BYTES_ENDSWITH_METHODDEF
|
BYTES_ENDSWITH_METHODDEF
|
||||||
STRINGLIB_EXPANDTABS_METHODDEF
|
STRINGLIB_EXPANDTABS_METHODDEF
|
||||||
{"find", (PyCFunction)bytes_find, METH_VARARGS,
|
BYTES_FIND_METHODDEF
|
||||||
_Py_find__doc__},
|
|
||||||
BYTES_FROMHEX_METHODDEF
|
BYTES_FROMHEX_METHODDEF
|
||||||
BYTES_HEX_METHODDEF
|
BYTES_HEX_METHODDEF
|
||||||
{"index", (PyCFunction)bytes_index, METH_VARARGS, _Py_index__doc__},
|
BYTES_INDEX_METHODDEF
|
||||||
{"isalnum", stringlib_isalnum, METH_NOARGS,
|
{"isalnum", stringlib_isalnum, METH_NOARGS,
|
||||||
_Py_isalnum__doc__},
|
_Py_isalnum__doc__},
|
||||||
{"isalpha", stringlib_isalpha, METH_NOARGS,
|
{"isalpha", stringlib_isalpha, METH_NOARGS,
|
||||||
|
@ -2559,8 +2616,8 @@ bytes_methods[] = {
|
||||||
BYTES_REPLACE_METHODDEF
|
BYTES_REPLACE_METHODDEF
|
||||||
BYTES_REMOVEPREFIX_METHODDEF
|
BYTES_REMOVEPREFIX_METHODDEF
|
||||||
BYTES_REMOVESUFFIX_METHODDEF
|
BYTES_REMOVESUFFIX_METHODDEF
|
||||||
{"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, _Py_rfind__doc__},
|
BYTES_RFIND_METHODDEF
|
||||||
{"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, _Py_rindex__doc__},
|
BYTES_RINDEX_METHODDEF
|
||||||
STRINGLIB_RJUST_METHODDEF
|
STRINGLIB_RJUST_METHODDEF
|
||||||
BYTES_RPARTITION_METHODDEF
|
BYTES_RPARTITION_METHODDEF
|
||||||
BYTES_RSPLIT_METHODDEF
|
BYTES_RSPLIT_METHODDEF
|
||||||
|
|
|
@ -101,6 +101,106 @@ exit:
|
||||||
return return_value;
|
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__,
|
PyDoc_STRVAR(bytearray_clear__doc__,
|
||||||
"clear($self, /)\n"
|
"clear($self, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -137,6 +237,159 @@ bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
return bytearray_copy_impl(self);
|
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__,
|
PyDoc_STRVAR(bytearray_startswith__doc__,
|
||||||
"startswith($self, prefix[, start[, end]], /)\n"
|
"startswith($self, prefix[, start[, end]], /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -1363,4 +1616,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
return bytearray_sizeof_impl(self);
|
return bytearray_sizeof_impl(self);
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=0147908e97ebe882 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=5f861b02e3fa278b input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -294,6 +294,210 @@ PyDoc_STRVAR(bytes_join__doc__,
|
||||||
#define BYTES_JOIN_METHODDEF \
|
#define BYTES_JOIN_METHODDEF \
|
||||||
{"join", (PyCFunction)bytes_join, METH_O, bytes_join__doc__},
|
{"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__,
|
PyDoc_STRVAR(bytes_strip__doc__,
|
||||||
"strip($self, bytes=None, /)\n"
|
"strip($self, bytes=None, /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -396,6 +600,55 @@ exit:
|
||||||
return return_value;
|
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__,
|
PyDoc_STRVAR(bytes_translate__doc__,
|
||||||
"translate($self, table, /, delete=b\'\')\n"
|
"translate($self, table, /, delete=b\'\')\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -1131,4 +1384,4 @@ skip_optional_pos:
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=f2b10ccd2e3155c3 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=d6801c6001e57f91 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -70,50 +70,3 @@ STRINGLIB(contains_obj)(PyObject* str, PyObject* sub)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* STRINGLIB_WANT_CONTAINS_OBJ */
|
#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
|
|
||||||
|
|
Loading…
Reference in New Issue