mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Issue #26765: Moved common code and docstrings for bytes and bytearray methods
to bytes_methods.c.
This commit is contained in:
parent
045e635100
commit
dd40fc3e57
7 changed files with 519 additions and 777 deletions
|
@ -21,6 +21,15 @@ 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_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 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);
|
||||||
|
|
||||||
/* The maketrans() static method. */
|
/* The maketrans() static method. */
|
||||||
extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to);
|
extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to);
|
||||||
|
|
||||||
|
@ -37,7 +46,19 @@ extern const char _Py_upper__doc__[];
|
||||||
extern const char _Py_title__doc__[];
|
extern const char _Py_title__doc__[];
|
||||||
extern const char _Py_capitalize__doc__[];
|
extern const char _Py_capitalize__doc__[];
|
||||||
extern const char _Py_swapcase__doc__[];
|
extern const char _Py_swapcase__doc__[];
|
||||||
|
extern const char _Py_count__doc__[];
|
||||||
|
extern const char _Py_find__doc__[];
|
||||||
|
extern const char _Py_index__doc__[];
|
||||||
|
extern const char _Py_rfind__doc__[];
|
||||||
|
extern const char _Py_rindex__doc__[];
|
||||||
|
extern const char _Py_startswith__doc__[];
|
||||||
|
extern const char _Py_endswith__doc__[];
|
||||||
extern const char _Py_maketrans__doc__[];
|
extern const char _Py_maketrans__doc__[];
|
||||||
|
extern const char _Py_expandtabs__doc__[];
|
||||||
|
extern const char _Py_ljust__doc__[];
|
||||||
|
extern const char _Py_rjust__doc__[];
|
||||||
|
extern const char _Py_center__doc__[];
|
||||||
|
extern const char _Py_zfill__doc__[];
|
||||||
|
|
||||||
/* this is needed because some docs are shared from the .o, not static */
|
/* this is needed because some docs are shared from the .o, not static */
|
||||||
#define PyDoc_STRVAR_shared(name,str) const char name[] = PyDoc_STR(str)
|
#define PyDoc_STRVAR_shared(name,str) const char name[] = PyDoc_STR(str)
|
||||||
|
|
|
@ -1097,147 +1097,16 @@ bytearray_dealloc(PyByteArrayObject *self)
|
||||||
#include "stringlib/transmogrify.h"
|
#include "stringlib/transmogrify.h"
|
||||||
|
|
||||||
|
|
||||||
/* The following Py_LOCAL_INLINE and Py_LOCAL functions
|
|
||||||
were copied from the old char* style string object. */
|
|
||||||
|
|
||||||
/* helper macro to fixup start/end slice values */
|
|
||||||
#define ADJUST_INDICES(start, end, len) \
|
|
||||||
if (end > len) \
|
|
||||||
end = len; \
|
|
||||||
else if (end < 0) { \
|
|
||||||
end += len; \
|
|
||||||
if (end < 0) \
|
|
||||||
end = 0; \
|
|
||||||
} \
|
|
||||||
if (start < 0) { \
|
|
||||||
start += len; \
|
|
||||||
if (start < 0) \
|
|
||||||
start = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_LOCAL_INLINE(Py_ssize_t)
|
|
||||||
bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
|
|
||||||
{
|
|
||||||
PyObject *subobj;
|
|
||||||
char byte;
|
|
||||||
Py_buffer subbuf;
|
|
||||||
const char *sub;
|
|
||||||
Py_ssize_t len, sub_len;
|
|
||||||
Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
|
|
||||||
Py_ssize_t res;
|
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds_byte("find/rfind/index/rindex",
|
|
||||||
args, &subobj, &byte, &start, &end))
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
if (subobj) {
|
|
||||||
if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
sub = subbuf.buf;
|
|
||||||
sub_len = subbuf.len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sub = &byte;
|
|
||||||
sub_len = 1;
|
|
||||||
}
|
|
||||||
len = PyByteArray_GET_SIZE(self);
|
|
||||||
|
|
||||||
ADJUST_INDICES(start, end, len);
|
|
||||||
if (end - start < sub_len)
|
|
||||||
res = -1;
|
|
||||||
else if (sub_len == 1) {
|
|
||||||
if (dir > 0)
|
|
||||||
res = stringlib_find_char(
|
|
||||||
PyByteArray_AS_STRING(self) + start, end - start,
|
|
||||||
*sub);
|
|
||||||
else
|
|
||||||
res = stringlib_rfind_char(
|
|
||||||
PyByteArray_AS_STRING(self) + start, end - start,
|
|
||||||
*sub);
|
|
||||||
if (res >= 0)
|
|
||||||
res += start;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (dir > 0)
|
|
||||||
res = stringlib_find_slice(
|
|
||||||
PyByteArray_AS_STRING(self), len,
|
|
||||||
sub, sub_len, start, end);
|
|
||||||
else
|
|
||||||
res = stringlib_rfind_slice(
|
|
||||||
PyByteArray_AS_STRING(self), len,
|
|
||||||
sub, sub_len, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subobj)
|
|
||||||
PyBuffer_Release(&subbuf);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytearray_find(PyByteArrayObject *self, PyObject *args)
|
bytearray_find(PyByteArrayObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t result = bytearray_find_internal(self, args, +1);
|
return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
||||||
if (result == -2)
|
|
||||||
return NULL;
|
|
||||||
return PyLong_FromSsize_t(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytearray_count(PyByteArrayObject *self, PyObject *args)
|
bytearray_count(PyByteArrayObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *sub_obj;
|
return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
||||||
const char *str = PyByteArray_AS_STRING(self), *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 (!stringlib_parse_args_finds_byte("count", args, &sub_obj, &byte,
|
|
||||||
&start, &end))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (sub_obj) {
|
|
||||||
if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
sub = vsub.buf;
|
|
||||||
sub_len = vsub.len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sub = &byte;
|
|
||||||
sub_len = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ADJUST_INDICES(start, end, PyByteArray_GET_SIZE(self));
|
|
||||||
|
|
||||||
count_obj = PyLong_FromSsize_t(
|
|
||||||
stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (sub_obj)
|
|
||||||
PyBuffer_Release(&vsub);
|
|
||||||
|
|
||||||
return count_obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
@ -1269,216 +1138,40 @@ bytearray_copy_impl(PyByteArrayObject *self)
|
||||||
PyByteArray_GET_SIZE(self));
|
PyByteArray_GET_SIZE(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(index__doc__,
|
|
||||||
"B.index(sub[, start[, end]]) -> int\n\
|
|
||||||
\n\
|
|
||||||
Like B.find() but raise ValueError when the subsection is not found.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytearray_index(PyByteArrayObject *self, PyObject *args)
|
bytearray_index(PyByteArrayObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t result = bytearray_find_internal(self, args, +1);
|
return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
||||||
if (result == -2)
|
|
||||||
return NULL;
|
|
||||||
if (result == -1) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"subsection not found");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return PyLong_FromSsize_t(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytearray_rfind(PyByteArrayObject *self, PyObject *args)
|
bytearray_rfind(PyByteArrayObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t result = bytearray_find_internal(self, args, -1);
|
return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
||||||
if (result == -2)
|
|
||||||
return NULL;
|
|
||||||
return PyLong_FromSsize_t(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(rindex__doc__,
|
|
||||||
"B.rindex(sub[, start[, end]]) -> int\n\
|
|
||||||
\n\
|
|
||||||
Like B.rfind() but raise ValueError when the subsection is not found.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytearray_rindex(PyByteArrayObject *self, PyObject *args)
|
bytearray_rindex(PyByteArrayObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t result = bytearray_find_internal(self, args, -1);
|
return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
||||||
if (result == -2)
|
|
||||||
return NULL;
|
|
||||||
if (result == -1) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"subsection not found");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return PyLong_FromSsize_t(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bytearray_contains(PyObject *self, PyObject *arg)
|
bytearray_contains(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);
|
return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg);
|
||||||
if (ival == -1 && PyErr_Occurred()) {
|
|
||||||
Py_buffer varg;
|
|
||||||
Py_ssize_t pos;
|
|
||||||
PyErr_Clear();
|
|
||||||
if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
|
|
||||||
return -1;
|
|
||||||
pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
|
|
||||||
varg.buf, varg.len, 0);
|
|
||||||
PyBuffer_Release(&varg);
|
|
||||||
return pos >= 0;
|
|
||||||
}
|
|
||||||
if (ival < 0 || ival >= 256) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return memchr(PyByteArray_AS_STRING(self), (int) ival, Py_SIZE(self)) != NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Matches the end (direction >= 0) or start (direction < 0) of self
|
|
||||||
* against substr, using the start and end arguments. Returns
|
|
||||||
* -1 on error, 0 if not found and 1 if found.
|
|
||||||
*/
|
|
||||||
Py_LOCAL(int)
|
|
||||||
_bytearray_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start,
|
|
||||||
Py_ssize_t end, int direction)
|
|
||||||
{
|
|
||||||
Py_ssize_t len = PyByteArray_GET_SIZE(self);
|
|
||||||
const char* str;
|
|
||||||
Py_buffer vsubstr;
|
|
||||||
int rv = 0;
|
|
||||||
|
|
||||||
str = PyByteArray_AS_STRING(self);
|
|
||||||
|
|
||||||
if (PyObject_GetBuffer(substr, &vsubstr, PyBUF_SIMPLE) != 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ADJUST_INDICES(start, end, len);
|
|
||||||
|
|
||||||
if (direction < 0) {
|
|
||||||
/* startswith */
|
|
||||||
if (start+vsubstr.len > len) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* endswith */
|
|
||||||
if (end-start < vsubstr.len || start > len) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end-vsubstr.len > start)
|
|
||||||
start = end - vsubstr.len;
|
|
||||||
}
|
|
||||||
if (end-start >= vsubstr.len)
|
|
||||||
rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);
|
|
||||||
|
|
||||||
done:
|
|
||||||
PyBuffer_Release(&vsubstr);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytearray_startswith(PyByteArrayObject *self, PyObject *args)
|
bytearray_startswith(PyByteArrayObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t start = 0;
|
return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
||||||
Py_ssize_t end = PY_SSIZE_T_MAX;
|
|
||||||
PyObject *subobj;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
|
|
||||||
return NULL;
|
|
||||||
if (PyTuple_Check(subobj)) {
|
|
||||||
Py_ssize_t i;
|
|
||||||
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
|
|
||||||
result = _bytearray_tailmatch(self,
|
|
||||||
PyTuple_GET_ITEM(subobj, i),
|
|
||||||
start, end, -1);
|
|
||||||
if (result == -1)
|
|
||||||
return NULL;
|
|
||||||
else if (result) {
|
|
||||||
Py_RETURN_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Py_RETURN_FALSE;
|
|
||||||
}
|
|
||||||
result = _bytearray_tailmatch(self, subobj, start, end, -1);
|
|
||||||
if (result == -1) {
|
|
||||||
if (PyErr_ExceptionMatches(PyExc_TypeError))
|
|
||||||
PyErr_Format(PyExc_TypeError, "startswith first arg must be bytes "
|
|
||||||
"or a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return PyBool_FromLong(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytearray_endswith(PyByteArrayObject *self, PyObject *args)
|
bytearray_endswith(PyByteArrayObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t start = 0;
|
return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
||||||
Py_ssize_t end = PY_SSIZE_T_MAX;
|
|
||||||
PyObject *subobj;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))
|
|
||||||
return NULL;
|
|
||||||
if (PyTuple_Check(subobj)) {
|
|
||||||
Py_ssize_t i;
|
|
||||||
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
|
|
||||||
result = _bytearray_tailmatch(self,
|
|
||||||
PyTuple_GET_ITEM(subobj, i),
|
|
||||||
start, end, +1);
|
|
||||||
if (result == -1)
|
|
||||||
return NULL;
|
|
||||||
else if (result) {
|
|
||||||
Py_RETURN_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Py_RETURN_FALSE;
|
|
||||||
}
|
|
||||||
result = _bytearray_tailmatch(self, subobj, start, end, +1);
|
|
||||||
if (result == -1) {
|
|
||||||
if (PyErr_ExceptionMatches(PyExc_TypeError))
|
|
||||||
PyErr_Format(PyExc_TypeError, "endswith first arg must be bytes or "
|
|
||||||
"a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return PyBool_FromLong(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1544,7 +1237,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
|
||||||
result = PyByteArray_FromStringAndSize((char *)NULL, inlen);
|
result = PyByteArray_FromStringAndSize((char *)NULL, inlen);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
output_start = output = PyByteArray_AsString(result);
|
output_start = output = PyByteArray_AS_STRING(result);
|
||||||
input = PyByteArray_AS_STRING(input_obj);
|
input = PyByteArray_AS_STRING(input_obj);
|
||||||
|
|
||||||
if (vdel.len == 0 && table_chars != NULL) {
|
if (vdel.len == 0 && table_chars != NULL) {
|
||||||
|
@ -2919,19 +2612,22 @@ bytearray_methods[] = {
|
||||||
BYTEARRAY_APPEND_METHODDEF
|
BYTEARRAY_APPEND_METHODDEF
|
||||||
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
|
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
|
||||||
_Py_capitalize__doc__},
|
_Py_capitalize__doc__},
|
||||||
{"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},
|
{"center", (PyCFunction)stringlib_center, METH_VARARGS, _Py_center__doc__},
|
||||||
BYTEARRAY_CLEAR_METHODDEF
|
BYTEARRAY_CLEAR_METHODDEF
|
||||||
BYTEARRAY_COPY_METHODDEF
|
BYTEARRAY_COPY_METHODDEF
|
||||||
{"count", (PyCFunction)bytearray_count, METH_VARARGS, count__doc__},
|
{"count", (PyCFunction)bytearray_count, METH_VARARGS,
|
||||||
|
_Py_count__doc__},
|
||||||
BYTEARRAY_DECODE_METHODDEF
|
BYTEARRAY_DECODE_METHODDEF
|
||||||
{"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS, endswith__doc__},
|
{"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS,
|
||||||
|
_Py_endswith__doc__},
|
||||||
{"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
|
{"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
|
||||||
expandtabs__doc__},
|
_Py_expandtabs__doc__},
|
||||||
BYTEARRAY_EXTEND_METHODDEF
|
BYTEARRAY_EXTEND_METHODDEF
|
||||||
{"find", (PyCFunction)bytearray_find, METH_VARARGS, find__doc__},
|
{"find", (PyCFunction)bytearray_find, METH_VARARGS,
|
||||||
|
_Py_find__doc__},
|
||||||
BYTEARRAY_FROMHEX_METHODDEF
|
BYTEARRAY_FROMHEX_METHODDEF
|
||||||
{"hex", (PyCFunction)bytearray_hex, METH_NOARGS, hex__doc__},
|
{"hex", (PyCFunction)bytearray_hex, METH_NOARGS, hex__doc__},
|
||||||
{"index", (PyCFunction)bytearray_index, METH_VARARGS, index__doc__},
|
{"index", (PyCFunction)bytearray_index, METH_VARARGS, _Py_index__doc__},
|
||||||
BYTEARRAY_INSERT_METHODDEF
|
BYTEARRAY_INSERT_METHODDEF
|
||||||
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
|
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
|
||||||
_Py_isalnum__doc__},
|
_Py_isalnum__doc__},
|
||||||
|
@ -2948,7 +2644,7 @@ bytearray_methods[] = {
|
||||||
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
|
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
|
||||||
_Py_isupper__doc__},
|
_Py_isupper__doc__},
|
||||||
BYTEARRAY_JOIN_METHODDEF
|
BYTEARRAY_JOIN_METHODDEF
|
||||||
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, _Py_ljust__doc__},
|
||||||
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
||||||
BYTEARRAY_LSTRIP_METHODDEF
|
BYTEARRAY_LSTRIP_METHODDEF
|
||||||
BYTEARRAY_MAKETRANS_METHODDEF
|
BYTEARRAY_MAKETRANS_METHODDEF
|
||||||
|
@ -2957,23 +2653,23 @@ bytearray_methods[] = {
|
||||||
BYTEARRAY_REMOVE_METHODDEF
|
BYTEARRAY_REMOVE_METHODDEF
|
||||||
BYTEARRAY_REPLACE_METHODDEF
|
BYTEARRAY_REPLACE_METHODDEF
|
||||||
BYTEARRAY_REVERSE_METHODDEF
|
BYTEARRAY_REVERSE_METHODDEF
|
||||||
{"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, rfind__doc__},
|
{"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__},
|
||||||
{"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, rindex__doc__},
|
{"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__},
|
||||||
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__},
|
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, _Py_rjust__doc__},
|
||||||
BYTEARRAY_RPARTITION_METHODDEF
|
BYTEARRAY_RPARTITION_METHODDEF
|
||||||
BYTEARRAY_RSPLIT_METHODDEF
|
BYTEARRAY_RSPLIT_METHODDEF
|
||||||
BYTEARRAY_RSTRIP_METHODDEF
|
BYTEARRAY_RSTRIP_METHODDEF
|
||||||
BYTEARRAY_SPLIT_METHODDEF
|
BYTEARRAY_SPLIT_METHODDEF
|
||||||
BYTEARRAY_SPLITLINES_METHODDEF
|
BYTEARRAY_SPLITLINES_METHODDEF
|
||||||
{"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS ,
|
{"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS ,
|
||||||
startswith__doc__},
|
_Py_startswith__doc__},
|
||||||
BYTEARRAY_STRIP_METHODDEF
|
BYTEARRAY_STRIP_METHODDEF
|
||||||
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
|
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
|
||||||
_Py_swapcase__doc__},
|
_Py_swapcase__doc__},
|
||||||
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
|
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
|
||||||
BYTEARRAY_TRANSLATE_METHODDEF
|
BYTEARRAY_TRANSLATE_METHODDEF
|
||||||
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
|
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
|
||||||
{"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__},
|
{"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, _Py_zfill__doc__},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -387,3 +387,427 @@ _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FASTSEARCH fastsearch
|
||||||
|
#define STRINGLIB(F) stringlib_##F
|
||||||
|
#define STRINGLIB_CHAR char
|
||||||
|
#define STRINGLIB_SIZEOF_CHAR 1
|
||||||
|
|
||||||
|
#include "stringlib/fastsearch.h"
|
||||||
|
#include "stringlib/count.h"
|
||||||
|
#include "stringlib/find.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wraps stringlib_parse_args_finds() and additionally checks whether the
|
||||||
|
first argument is an integer in range(0, 256).
|
||||||
|
|
||||||
|
If this is the case, writes the integer value to the byte parameter
|
||||||
|
and sets subobj to NULL. Otherwise, sets the first argument to subobj
|
||||||
|
and doesn't touch byte. The other parameters are similar to those of
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
PyObject *tmp_subobj;
|
||||||
|
Py_ssize_t ival;
|
||||||
|
PyObject *err;
|
||||||
|
|
||||||
|
if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj,
|
||||||
|
start, end))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!PyNumber_Check(tmp_subobj)) {
|
||||||
|
*subobj = tmp_subobj;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ival = PyNumber_AsSsize_t(tmp_subobj, PyExc_OverflowError);
|
||||||
|
if (ival == -1) {
|
||||||
|
err = PyErr_Occurred();
|
||||||
|
if (err && !PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
|
||||||
|
PyErr_Clear();
|
||||||
|
*subobj = tmp_subobj;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ival < 0 || ival > 255) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*subobj = NULL;
|
||||||
|
*byte = (char)ival;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* helper macro to fixup start/end slice values */
|
||||||
|
#define ADJUST_INDICES(start, end, len) \
|
||||||
|
if (end > len) \
|
||||||
|
end = len; \
|
||||||
|
else if (end < 0) { \
|
||||||
|
end += len; \
|
||||||
|
if (end < 0) \
|
||||||
|
end = 0; \
|
||||||
|
} \
|
||||||
|
if (start < 0) { \
|
||||||
|
start += len; \
|
||||||
|
if (start < 0) \
|
||||||
|
start = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_LOCAL_INLINE(Py_ssize_t)
|
||||||
|
find_internal(const char *str, Py_ssize_t len,
|
||||||
|
const char *function_name, PyObject *args, 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))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if (subobj) {
|
||||||
|
if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
sub = subbuf.buf;
|
||||||
|
sub_len = subbuf.len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sub = &byte;
|
||||||
|
sub_len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADJUST_INDICES(start, end, len);
|
||||||
|
if (end - start < sub_len)
|
||||||
|
res = -1;
|
||||||
|
else if (sub_len == 1) {
|
||||||
|
if (dir > 0)
|
||||||
|
res = stringlib_find_char(
|
||||||
|
str + start, end - start,
|
||||||
|
*sub);
|
||||||
|
else
|
||||||
|
res = stringlib_rfind_char(
|
||||||
|
str + start, end - start,
|
||||||
|
*sub);
|
||||||
|
if (res >= 0)
|
||||||
|
res += start;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dir > 0)
|
||||||
|
res = stringlib_find_slice(
|
||||||
|
str, len,
|
||||||
|
sub, sub_len, start, end);
|
||||||
|
else
|
||||||
|
res = stringlib_rfind_slice(
|
||||||
|
str, len,
|
||||||
|
sub, sub_len, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subobj)
|
||||||
|
PyBuffer_Release(&subbuf);
|
||||||
|
|
||||||
|
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_ssize_t result = find_internal(str, len, "find", args, +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\
|
||||||
|
Like B.find() but raise ValueError when the subsection is not found.");
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args)
|
||||||
|
{
|
||||||
|
Py_ssize_t result = find_internal(str, len, "index", args, +1);
|
||||||
|
if (result == -2)
|
||||||
|
return NULL;
|
||||||
|
if (result == -1) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"subsection not found");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
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_ssize_t result = find_internal(str, len, "rfind", args, -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\
|
||||||
|
Like B.rfind() but raise ValueError when the subsection is not found.");
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args)
|
||||||
|
{
|
||||||
|
Py_ssize_t result = find_internal(str, len, "rindex", args, -1);
|
||||||
|
if (result == -2)
|
||||||
|
return NULL;
|
||||||
|
if (result == -1) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"subsection not found");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (sub_obj) {
|
||||||
|
if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sub = vsub.buf;
|
||||||
|
sub_len = vsub.len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sub = &byte;
|
||||||
|
sub_len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADJUST_INDICES(start, end, len);
|
||||||
|
|
||||||
|
count_obj = PyLong_FromSsize_t(
|
||||||
|
stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sub_obj)
|
||||||
|
PyBuffer_Release(&vsub);
|
||||||
|
|
||||||
|
return count_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg)
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
Py_buffer varg;
|
||||||
|
Py_ssize_t pos;
|
||||||
|
PyErr_Clear();
|
||||||
|
if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
|
||||||
|
return -1;
|
||||||
|
pos = stringlib_find(str, len,
|
||||||
|
varg.buf, varg.len, 0);
|
||||||
|
PyBuffer_Release(&varg);
|
||||||
|
return pos >= 0;
|
||||||
|
}
|
||||||
|
if (ival < 0 || ival >= 256) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return memchr(str, (int) ival, len) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Matches the end (direction >= 0) or start (direction < 0) of the buffer
|
||||||
|
* against substr, using the start and end arguments. Returns
|
||||||
|
* -1 on error, 0 if not found and 1 if found.
|
||||||
|
*/
|
||||||
|
Py_LOCAL(int)
|
||||||
|
tailmatch(const char *str, Py_ssize_t len, PyObject *substr,
|
||||||
|
Py_ssize_t start, Py_ssize_t end, int direction)
|
||||||
|
{
|
||||||
|
Py_buffer sub_view = {NULL, NULL};
|
||||||
|
const char *sub;
|
||||||
|
Py_ssize_t slen;
|
||||||
|
|
||||||
|
if (PyBytes_Check(substr)) {
|
||||||
|
sub = PyBytes_AS_STRING(substr);
|
||||||
|
slen = PyBytes_GET_SIZE(substr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0)
|
||||||
|
return -1;
|
||||||
|
sub = sub_view.buf;
|
||||||
|
slen = sub_view.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADJUST_INDICES(start, end, len);
|
||||||
|
|
||||||
|
if (direction < 0) {
|
||||||
|
/* startswith */
|
||||||
|
if (start + slen > len)
|
||||||
|
goto notfound;
|
||||||
|
} else {
|
||||||
|
/* endswith */
|
||||||
|
if (end - start < slen || start > len)
|
||||||
|
goto notfound;
|
||||||
|
|
||||||
|
if (end - slen > start)
|
||||||
|
start = end - slen;
|
||||||
|
}
|
||||||
|
if (end - start < slen)
|
||||||
|
goto notfound;
|
||||||
|
if (memcmp(str + start, sub, slen) != 0)
|
||||||
|
goto notfound;
|
||||||
|
|
||||||
|
PyBuffer_Release(&sub_view);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
notfound:
|
||||||
|
PyBuffer_Release(&sub_view);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_LOCAL(PyObject *)
|
||||||
|
_Py_bytes_tailmatch(const char *str, Py_ssize_t len,
|
||||||
|
const char *function_name, PyObject *args,
|
||||||
|
int direction)
|
||||||
|
{
|
||||||
|
Py_ssize_t start = 0;
|
||||||
|
Py_ssize_t end = PY_SSIZE_T_MAX;
|
||||||
|
PyObject *subobj;
|
||||||
|
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)
|
||||||
|
return NULL;
|
||||||
|
else if (result) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
result = tailmatch(str, len, subobj, start, end, direction);
|
||||||
|
if (result == -1) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return _Py_bytes_tailmatch(str, len, "endswith", args, +1);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR_shared(_Py_expandtabs__doc__,
|
||||||
|
"B.expandtabs(tabsize=8) -> copy of B\n\
|
||||||
|
\n\
|
||||||
|
Return a copy of B where all tab characters are expanded using spaces.\n\
|
||||||
|
If tabsize is not given, a tab size of 8 characters is assumed.");
|
||||||
|
|
||||||
|
PyDoc_STRVAR_shared(_Py_ljust__doc__,
|
||||||
|
"B.ljust(width[, fillchar]) -> copy of B\n"
|
||||||
|
"\n"
|
||||||
|
"Return B left justified in a string of length width. Padding is\n"
|
||||||
|
"done using the specified fill character (default is a space).");
|
||||||
|
|
||||||
|
PyDoc_STRVAR_shared(_Py_rjust__doc__,
|
||||||
|
"B.rjust(width[, fillchar]) -> copy of B\n"
|
||||||
|
"\n"
|
||||||
|
"Return B right justified in a string of length width. Padding is\n"
|
||||||
|
"done using the specified fill character (default is a space)");
|
||||||
|
|
||||||
|
PyDoc_STRVAR_shared(_Py_center__doc__,
|
||||||
|
"B.center(width[, fillchar]) -> copy of B\n"
|
||||||
|
"\n"
|
||||||
|
"Return B centered in a string of length width. Padding is\n"
|
||||||
|
"done using the specified fill character (default is a space).");
|
||||||
|
|
||||||
|
PyDoc_STRVAR_shared(_Py_zfill__doc__,
|
||||||
|
"B.zfill(width) -> copy of B\n"
|
||||||
|
"\n"
|
||||||
|
"Pad a numeric string B with zeros on the left, to fill a field\n"
|
||||||
|
"of the specified width. B is never truncated.");
|
||||||
|
|
||||||
|
|
|
@ -486,11 +486,11 @@ formatlong(PyObject *v, int flags, int prec, int type)
|
||||||
static int
|
static int
|
||||||
byte_converter(PyObject *arg, char *p)
|
byte_converter(PyObject *arg, char *p)
|
||||||
{
|
{
|
||||||
if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) {
|
if (PyBytes_Check(arg) && PyBytes_GET_SIZE(arg) == 1) {
|
||||||
*p = PyBytes_AS_STRING(arg)[0];
|
*p = PyBytes_AS_STRING(arg)[0];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1) {
|
else if (PyByteArray_Check(arg) && PyByteArray_GET_SIZE(arg) == 1) {
|
||||||
*p = PyByteArray_AS_STRING(arg)[0];
|
*p = PyByteArray_AS_STRING(arg)[0];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1488,24 +1488,7 @@ bytes_repeat(PyBytesObject *a, Py_ssize_t n)
|
||||||
static int
|
static int
|
||||||
bytes_contains(PyObject *self, PyObject *arg)
|
bytes_contains(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);
|
return _Py_bytes_contains(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), arg);
|
||||||
if (ival == -1 && PyErr_Occurred()) {
|
|
||||||
Py_buffer varg;
|
|
||||||
Py_ssize_t pos;
|
|
||||||
PyErr_Clear();
|
|
||||||
if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
|
|
||||||
return -1;
|
|
||||||
pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
|
|
||||||
varg.buf, varg.len, 0);
|
|
||||||
PyBuffer_Release(&varg);
|
|
||||||
return pos >= 0;
|
|
||||||
}
|
|
||||||
if (ival < 0 || ival >= 256) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return memchr(PyBytes_AS_STRING(self), (int) ival, Py_SIZE(self)) != NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1890,157 +1873,30 @@ _PyBytes_Join(PyObject *sep, PyObject *x)
|
||||||
return bytes_join((PyBytesObject*)sep, x);
|
return bytes_join((PyBytesObject*)sep, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* helper macro to fixup start/end slice values */
|
|
||||||
#define ADJUST_INDICES(start, end, len) \
|
|
||||||
if (end > len) \
|
|
||||||
end = len; \
|
|
||||||
else if (end < 0) { \
|
|
||||||
end += len; \
|
|
||||||
if (end < 0) \
|
|
||||||
end = 0; \
|
|
||||||
} \
|
|
||||||
if (start < 0) { \
|
|
||||||
start += len; \
|
|
||||||
if (start < 0) \
|
|
||||||
start = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_LOCAL_INLINE(Py_ssize_t)
|
|
||||||
bytes_find_internal(PyBytesObject *self, PyObject *args, int dir)
|
|
||||||
{
|
|
||||||
PyObject *subobj;
|
|
||||||
char byte;
|
|
||||||
Py_buffer subbuf;
|
|
||||||
const char *sub;
|
|
||||||
Py_ssize_t len, sub_len;
|
|
||||||
Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
|
|
||||||
Py_ssize_t res;
|
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds_byte("find/rfind/index/rindex",
|
|
||||||
args, &subobj, &byte, &start, &end))
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
if (subobj) {
|
|
||||||
if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
sub = subbuf.buf;
|
|
||||||
sub_len = subbuf.len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sub = &byte;
|
|
||||||
sub_len = 1;
|
|
||||||
}
|
|
||||||
len = PyBytes_GET_SIZE(self);
|
|
||||||
|
|
||||||
ADJUST_INDICES(start, end, len);
|
|
||||||
if (end - start < sub_len)
|
|
||||||
res = -1;
|
|
||||||
else if (sub_len == 1) {
|
|
||||||
if (dir > 0)
|
|
||||||
res = stringlib_find_char(
|
|
||||||
PyBytes_AS_STRING(self) + start, end - start,
|
|
||||||
*sub);
|
|
||||||
else
|
|
||||||
res = stringlib_rfind_char(
|
|
||||||
PyBytes_AS_STRING(self) + start, end - start,
|
|
||||||
*sub);
|
|
||||||
if (res >= 0)
|
|
||||||
res += start;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (dir > 0)
|
|
||||||
res = stringlib_find_slice(
|
|
||||||
PyBytes_AS_STRING(self), len,
|
|
||||||
sub, sub_len, start, end);
|
|
||||||
else
|
|
||||||
res = stringlib_rfind_slice(
|
|
||||||
PyBytes_AS_STRING(self), len,
|
|
||||||
sub, sub_len, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subobj)
|
|
||||||
PyBuffer_Release(&subbuf);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(find__doc__,
|
|
||||||
"B.find(sub[, start[, end]]) -> int\n\
|
|
||||||
\n\
|
|
||||||
Return the lowest index in B where substring 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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytes_find(PyBytesObject *self, PyObject *args)
|
bytes_find(PyBytesObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t result = bytes_find_internal(self, args, +1);
|
return _Py_bytes_find(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
|
||||||
if (result == -2)
|
|
||||||
return NULL;
|
|
||||||
return PyLong_FromSsize_t(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(index__doc__,
|
|
||||||
"B.index(sub[, start[, end]]) -> int\n\
|
|
||||||
\n\
|
|
||||||
Like B.find() but raise ValueError when the substring is not found.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytes_index(PyBytesObject *self, PyObject *args)
|
bytes_index(PyBytesObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t result = bytes_find_internal(self, args, +1);
|
return _Py_bytes_index(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
|
||||||
if (result == -2)
|
|
||||||
return NULL;
|
|
||||||
if (result == -1) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"substring not found");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return PyLong_FromSsize_t(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(rfind__doc__,
|
|
||||||
"B.rfind(sub[, start[, end]]) -> int\n\
|
|
||||||
\n\
|
|
||||||
Return the highest index in B where substring 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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytes_rfind(PyBytesObject *self, PyObject *args)
|
bytes_rfind(PyBytesObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t result = bytes_find_internal(self, args, -1);
|
return _Py_bytes_rfind(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
|
||||||
if (result == -2)
|
|
||||||
return NULL;
|
|
||||||
return PyLong_FromSsize_t(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(rindex__doc__,
|
|
||||||
"B.rindex(sub[, start[, end]]) -> int\n\
|
|
||||||
\n\
|
|
||||||
Like B.rfind() but raise ValueError when the substring is not found.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytes_rindex(PyBytesObject *self, PyObject *args)
|
bytes_rindex(PyBytesObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t result = bytes_find_internal(self, args, -1);
|
return _Py_bytes_rindex(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
|
||||||
if (result == -2)
|
|
||||||
return NULL;
|
|
||||||
if (result == -1) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"substring not found");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return PyLong_FromSsize_t(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2179,51 +2035,10 @@ bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(count__doc__,
|
|
||||||
"B.count(sub[, start[, end]]) -> int\n\
|
|
||||||
\n\
|
|
||||||
Return the number of non-overlapping occurrences of substring sub in\n\
|
|
||||||
string B[start:end]. Optional arguments start and end are interpreted\n\
|
|
||||||
as in slice notation.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytes_count(PyBytesObject *self, PyObject *args)
|
bytes_count(PyBytesObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *sub_obj;
|
return _Py_bytes_count(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
|
||||||
const char *str = PyBytes_AS_STRING(self), *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 (!stringlib_parse_args_finds_byte("count", args, &sub_obj, &byte,
|
|
||||||
&start, &end))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (sub_obj) {
|
|
||||||
if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
sub = vsub.buf;
|
|
||||||
sub_len = vsub.len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sub = &byte;
|
|
||||||
sub_len = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ADJUST_INDICES(start, end, PyBytes_GET_SIZE(self));
|
|
||||||
|
|
||||||
count_obj = PyLong_FromSsize_t(
|
|
||||||
stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (sub_obj)
|
|
||||||
PyBuffer_Release(&vsub);
|
|
||||||
|
|
||||||
return count_obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2307,7 +2122,7 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
|
||||||
PyBuffer_Release(&table_view);
|
PyBuffer_Release(&table_view);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
output_start = output = PyBytes_AsString(result);
|
output_start = output = PyBytes_AS_STRING(result);
|
||||||
input = PyBytes_AS_STRING(input_obj);
|
input = PyBytes_AS_STRING(input_obj);
|
||||||
|
|
||||||
if (dellen == 0 && table_chars != NULL) {
|
if (dellen == 0 && table_chars != NULL) {
|
||||||
|
@ -2914,145 +2729,17 @@ bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new,
|
||||||
|
|
||||||
/** End DALKE **/
|
/** End DALKE **/
|
||||||
|
|
||||||
/* Matches the end (direction >= 0) or start (direction < 0) of self
|
|
||||||
* against substr, using the start and end arguments. Returns
|
|
||||||
* -1 on error, 0 if not found and 1 if found.
|
|
||||||
*/
|
|
||||||
Py_LOCAL(int)
|
|
||||||
_bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
|
|
||||||
Py_ssize_t end, int direction)
|
|
||||||
{
|
|
||||||
Py_ssize_t len = PyBytes_GET_SIZE(self);
|
|
||||||
Py_ssize_t slen;
|
|
||||||
Py_buffer sub_view = {NULL, NULL};
|
|
||||||
const char* sub;
|
|
||||||
const char* str;
|
|
||||||
|
|
||||||
if (PyBytes_Check(substr)) {
|
|
||||||
sub = PyBytes_AS_STRING(substr);
|
|
||||||
slen = PyBytes_GET_SIZE(substr);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0)
|
|
||||||
return -1;
|
|
||||||
sub = sub_view.buf;
|
|
||||||
slen = sub_view.len;
|
|
||||||
}
|
|
||||||
str = PyBytes_AS_STRING(self);
|
|
||||||
|
|
||||||
ADJUST_INDICES(start, end, len);
|
|
||||||
|
|
||||||
if (direction < 0) {
|
|
||||||
/* startswith */
|
|
||||||
if (start+slen > len)
|
|
||||||
goto notfound;
|
|
||||||
} else {
|
|
||||||
/* endswith */
|
|
||||||
if (end-start < slen || start > len)
|
|
||||||
goto notfound;
|
|
||||||
|
|
||||||
if (end-slen > start)
|
|
||||||
start = end - slen;
|
|
||||||
}
|
|
||||||
if (end-start < slen)
|
|
||||||
goto notfound;
|
|
||||||
if (memcmp(str+start, sub, slen) != 0)
|
|
||||||
goto notfound;
|
|
||||||
|
|
||||||
PyBuffer_Release(&sub_view);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
notfound:
|
|
||||||
PyBuffer_Release(&sub_view);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytes_startswith(PyBytesObject *self, PyObject *args)
|
bytes_startswith(PyBytesObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t start = 0;
|
return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
|
||||||
Py_ssize_t end = PY_SSIZE_T_MAX;
|
|
||||||
PyObject *subobj;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
|
|
||||||
return NULL;
|
|
||||||
if (PyTuple_Check(subobj)) {
|
|
||||||
Py_ssize_t i;
|
|
||||||
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
|
|
||||||
result = _bytes_tailmatch(self,
|
|
||||||
PyTuple_GET_ITEM(subobj, i),
|
|
||||||
start, end, -1);
|
|
||||||
if (result == -1)
|
|
||||||
return NULL;
|
|
||||||
else if (result) {
|
|
||||||
Py_RETURN_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Py_RETURN_FALSE;
|
|
||||||
}
|
|
||||||
result = _bytes_tailmatch(self, subobj, start, end, -1);
|
|
||||||
if (result == -1) {
|
|
||||||
if (PyErr_ExceptionMatches(PyExc_TypeError))
|
|
||||||
PyErr_Format(PyExc_TypeError, "startswith first arg must be bytes "
|
|
||||||
"or a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return PyBool_FromLong(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(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.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytes_endswith(PyBytesObject *self, PyObject *args)
|
bytes_endswith(PyBytesObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t start = 0;
|
return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
|
||||||
Py_ssize_t end = PY_SSIZE_T_MAX;
|
|
||||||
PyObject *subobj;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))
|
|
||||||
return NULL;
|
|
||||||
if (PyTuple_Check(subobj)) {
|
|
||||||
Py_ssize_t i;
|
|
||||||
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
|
|
||||||
result = _bytes_tailmatch(self,
|
|
||||||
PyTuple_GET_ITEM(subobj, i),
|
|
||||||
start, end, +1);
|
|
||||||
if (result == -1)
|
|
||||||
return NULL;
|
|
||||||
else if (result) {
|
|
||||||
Py_RETURN_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Py_RETURN_FALSE;
|
|
||||||
}
|
|
||||||
result = _bytes_tailmatch(self, subobj, start, end, +1);
|
|
||||||
if (result == -1) {
|
|
||||||
if (PyErr_ExceptionMatches(PyExc_TypeError))
|
|
||||||
PyErr_Format(PyExc_TypeError, "endswith first arg must be bytes or "
|
|
||||||
"a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return PyBool_FromLong(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3224,17 +2911,20 @@ bytes_methods[] = {
|
||||||
{"__getnewargs__", (PyCFunction)bytes_getnewargs, METH_NOARGS},
|
{"__getnewargs__", (PyCFunction)bytes_getnewargs, METH_NOARGS},
|
||||||
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
|
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
|
||||||
_Py_capitalize__doc__},
|
_Py_capitalize__doc__},
|
||||||
{"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},
|
{"center", (PyCFunction)stringlib_center, METH_VARARGS,
|
||||||
{"count", (PyCFunction)bytes_count, METH_VARARGS, count__doc__},
|
_Py_center__doc__},
|
||||||
|
{"count", (PyCFunction)bytes_count, METH_VARARGS,
|
||||||
|
_Py_count__doc__},
|
||||||
BYTES_DECODE_METHODDEF
|
BYTES_DECODE_METHODDEF
|
||||||
{"endswith", (PyCFunction)bytes_endswith, METH_VARARGS,
|
{"endswith", (PyCFunction)bytes_endswith, METH_VARARGS,
|
||||||
endswith__doc__},
|
_Py_endswith__doc__},
|
||||||
{"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
|
{"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
|
||||||
expandtabs__doc__},
|
_Py_expandtabs__doc__},
|
||||||
{"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__},
|
{"find", (PyCFunction)bytes_find, METH_VARARGS,
|
||||||
|
_Py_find__doc__},
|
||||||
BYTES_FROMHEX_METHODDEF
|
BYTES_FROMHEX_METHODDEF
|
||||||
{"hex", (PyCFunction)bytes_hex, METH_NOARGS, hex__doc__},
|
{"hex", (PyCFunction)bytes_hex, METH_NOARGS, hex__doc__},
|
||||||
{"index", (PyCFunction)bytes_index, METH_VARARGS, index__doc__},
|
{"index", (PyCFunction)bytes_index, METH_VARARGS, _Py_index__doc__},
|
||||||
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
|
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
|
||||||
_Py_isalnum__doc__},
|
_Py_isalnum__doc__},
|
||||||
{"isalpha", (PyCFunction)stringlib_isalpha, METH_NOARGS,
|
{"isalpha", (PyCFunction)stringlib_isalpha, METH_NOARGS,
|
||||||
|
@ -3250,29 +2940,29 @@ bytes_methods[] = {
|
||||||
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
|
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
|
||||||
_Py_isupper__doc__},
|
_Py_isupper__doc__},
|
||||||
BYTES_JOIN_METHODDEF
|
BYTES_JOIN_METHODDEF
|
||||||
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, _Py_ljust__doc__},
|
||||||
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
||||||
BYTES_LSTRIP_METHODDEF
|
BYTES_LSTRIP_METHODDEF
|
||||||
BYTES_MAKETRANS_METHODDEF
|
BYTES_MAKETRANS_METHODDEF
|
||||||
BYTES_PARTITION_METHODDEF
|
BYTES_PARTITION_METHODDEF
|
||||||
BYTES_REPLACE_METHODDEF
|
BYTES_REPLACE_METHODDEF
|
||||||
{"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, rfind__doc__},
|
{"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, _Py_rfind__doc__},
|
||||||
{"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, rindex__doc__},
|
{"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, _Py_rindex__doc__},
|
||||||
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__},
|
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, _Py_rjust__doc__},
|
||||||
BYTES_RPARTITION_METHODDEF
|
BYTES_RPARTITION_METHODDEF
|
||||||
BYTES_RSPLIT_METHODDEF
|
BYTES_RSPLIT_METHODDEF
|
||||||
BYTES_RSTRIP_METHODDEF
|
BYTES_RSTRIP_METHODDEF
|
||||||
BYTES_SPLIT_METHODDEF
|
BYTES_SPLIT_METHODDEF
|
||||||
BYTES_SPLITLINES_METHODDEF
|
BYTES_SPLITLINES_METHODDEF
|
||||||
{"startswith", (PyCFunction)bytes_startswith, METH_VARARGS,
|
{"startswith", (PyCFunction)bytes_startswith, METH_VARARGS,
|
||||||
startswith__doc__},
|
_Py_startswith__doc__},
|
||||||
BYTES_STRIP_METHODDEF
|
BYTES_STRIP_METHODDEF
|
||||||
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
|
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
|
||||||
_Py_swapcase__doc__},
|
_Py_swapcase__doc__},
|
||||||
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
|
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
|
||||||
BYTES_TRANSLATE_METHODDEF
|
BYTES_TRANSLATE_METHODDEF
|
||||||
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
|
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
|
||||||
{"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__},
|
{"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, _Py_zfill__doc__},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -117,76 +117,3 @@ STRINGLIB(parse_args_finds)(const char * function_name, PyObject *args,
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef FORMAT_BUFFER_SIZE
|
#undef FORMAT_BUFFER_SIZE
|
||||||
|
|
||||||
#if STRINGLIB_IS_UNICODE
|
|
||||||
|
|
||||||
/*
|
|
||||||
Wraps stringlib_parse_args_finds() and additionally ensures that the
|
|
||||||
first argument is a unicode object.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Py_LOCAL_INLINE(int)
|
|
||||||
STRINGLIB(parse_args_finds_unicode)(const char * function_name, PyObject *args,
|
|
||||||
PyObject **substring,
|
|
||||||
Py_ssize_t *start, Py_ssize_t *end)
|
|
||||||
{
|
|
||||||
if(STRINGLIB(parse_args_finds)(function_name, args, substring,
|
|
||||||
start, end)) {
|
|
||||||
if (ensure_unicode(*substring) < 0)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* !STRINGLIB_IS_UNICODE */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Wraps stringlib_parse_args_finds() and additionally checks whether the
|
|
||||||
first argument is an integer in range(0, 256).
|
|
||||||
|
|
||||||
If this is the case, writes the integer value to the byte parameter
|
|
||||||
and sets subobj to NULL. Otherwise, sets the first argument to subobj
|
|
||||||
and doesn't touch byte. The other parameters are similar to those of
|
|
||||||
stringlib_parse_args_finds().
|
|
||||||
*/
|
|
||||||
|
|
||||||
Py_LOCAL_INLINE(int)
|
|
||||||
STRINGLIB(parse_args_finds_byte)(const char *function_name, PyObject *args,
|
|
||||||
PyObject **subobj, char *byte,
|
|
||||||
Py_ssize_t *start, Py_ssize_t *end)
|
|
||||||
{
|
|
||||||
PyObject *tmp_subobj;
|
|
||||||
Py_ssize_t ival;
|
|
||||||
PyObject *err;
|
|
||||||
|
|
||||||
if(!STRINGLIB(parse_args_finds)(function_name, args, &tmp_subobj,
|
|
||||||
start, end))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!PyNumber_Check(tmp_subobj)) {
|
|
||||||
*subobj = tmp_subobj;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ival = PyNumber_AsSsize_t(tmp_subobj, PyExc_OverflowError);
|
|
||||||
if (ival == -1) {
|
|
||||||
err = PyErr_Occurred();
|
|
||||||
if (err && !PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
|
|
||||||
PyErr_Clear();
|
|
||||||
*subobj = tmp_subobj;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ival < 0 || ival > 255) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*subobj = NULL;
|
|
||||||
*byte = (char)ival;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* STRINGLIB_IS_UNICODE */
|
|
||||||
|
|
|
@ -4,12 +4,6 @@
|
||||||
/* the more complicated methods. parts of these should be pulled out into the
|
/* the more complicated methods. parts of these should be pulled out into the
|
||||||
shared code in bytes_methods.c to cut down on duplicate code bloat. */
|
shared code in bytes_methods.c to cut down on duplicate code bloat. */
|
||||||
|
|
||||||
PyDoc_STRVAR(expandtabs__doc__,
|
|
||||||
"B.expandtabs(tabsize=8) -> copy of B\n\
|
|
||||||
\n\
|
|
||||||
Return a copy of B where all tab characters are expanded using spaces.\n\
|
|
||||||
If tabsize is not given, a tab size of 8 characters is assumed.");
|
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
stringlib_expandtabs(PyObject *self, PyObject *args, PyObject *kwds)
|
stringlib_expandtabs(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
|
@ -120,12 +114,6 @@ pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(ljust__doc__,
|
|
||||||
"B.ljust(width[, fillchar]) -> copy of B\n"
|
|
||||||
"\n"
|
|
||||||
"Return B left justified in a string of length width. Padding is\n"
|
|
||||||
"done using the specified fill character (default is a space).");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
stringlib_ljust(PyObject *self, PyObject *args)
|
stringlib_ljust(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -150,12 +138,6 @@ stringlib_ljust(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(rjust__doc__,
|
|
||||||
"B.rjust(width[, fillchar]) -> copy of B\n"
|
|
||||||
"\n"
|
|
||||||
"Return B right justified in a string of length width. Padding is\n"
|
|
||||||
"done using the specified fill character (default is a space)");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
stringlib_rjust(PyObject *self, PyObject *args)
|
stringlib_rjust(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -180,12 +162,6 @@ stringlib_rjust(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(center__doc__,
|
|
||||||
"B.center(width[, fillchar]) -> copy of B\n"
|
|
||||||
"\n"
|
|
||||||
"Return B centered in a string of length width. Padding is\n"
|
|
||||||
"done using the specified fill character (default is a space).");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
stringlib_center(PyObject *self, PyObject *args)
|
stringlib_center(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -213,12 +189,6 @@ stringlib_center(PyObject *self, PyObject *args)
|
||||||
return pad(self, left, marg - left, fillchar);
|
return pad(self, left, marg - left, fillchar);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(zfill__doc__,
|
|
||||||
"B.zfill(width) -> copy of B\n"
|
|
||||||
"\n"
|
|
||||||
"Pad a numeric string B with zeros on the left, to fill a field\n"
|
|
||||||
"of the specified width. B is never truncated.");
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
stringlib_zfill(PyObject *self, PyObject *args)
|
stringlib_zfill(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11244,6 +11244,25 @@ PyUnicode_AppendAndDel(PyObject **pleft, PyObject *right)
|
||||||
Py_XDECREF(right);
|
Py_XDECREF(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wraps stringlib_parse_args_finds() and additionally ensures that the
|
||||||
|
first argument is a unicode object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Py_LOCAL_INLINE(int)
|
||||||
|
parse_args_finds_unicode(const char * function_name, PyObject *args,
|
||||||
|
PyObject **substring,
|
||||||
|
Py_ssize_t *start, Py_ssize_t *end)
|
||||||
|
{
|
||||||
|
if(stringlib_parse_args_finds(function_name, args, substring,
|
||||||
|
start, end)) {
|
||||||
|
if (ensure_unicode(*substring) < 0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(count__doc__,
|
PyDoc_STRVAR(count__doc__,
|
||||||
"S.count(sub[, start[, end]]) -> int\n\
|
"S.count(sub[, start[, end]]) -> int\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -11262,8 +11281,7 @@ unicode_count(PyObject *self, PyObject *args)
|
||||||
void *buf1, *buf2;
|
void *buf1, *buf2;
|
||||||
Py_ssize_t len1, len2, iresult;
|
Py_ssize_t len1, len2, iresult;
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds_unicode("count", args, &substring,
|
if (!parse_args_finds_unicode("count", args, &substring, &start, &end))
|
||||||
&start, &end))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
kind1 = PyUnicode_KIND(self);
|
kind1 = PyUnicode_KIND(self);
|
||||||
|
@ -11445,8 +11463,7 @@ unicode_find(PyObject *self, PyObject *args)
|
||||||
Py_ssize_t end = 0;
|
Py_ssize_t end = 0;
|
||||||
Py_ssize_t result;
|
Py_ssize_t result;
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds_unicode("find", args, &substring,
|
if (!parse_args_finds_unicode("find", args, &substring, &start, &end))
|
||||||
&start, &end))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (PyUnicode_READY(self) == -1)
|
if (PyUnicode_READY(self) == -1)
|
||||||
|
@ -11525,8 +11542,7 @@ unicode_index(PyObject *self, PyObject *args)
|
||||||
Py_ssize_t start = 0;
|
Py_ssize_t start = 0;
|
||||||
Py_ssize_t end = 0;
|
Py_ssize_t end = 0;
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds_unicode("index", args, &substring,
|
if (!parse_args_finds_unicode("index", args, &substring, &start, &end))
|
||||||
&start, &end))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (PyUnicode_READY(self) == -1)
|
if (PyUnicode_READY(self) == -1)
|
||||||
|
@ -12555,8 +12571,7 @@ unicode_rfind(PyObject *self, PyObject *args)
|
||||||
Py_ssize_t end = 0;
|
Py_ssize_t end = 0;
|
||||||
Py_ssize_t result;
|
Py_ssize_t result;
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds_unicode("rfind", args, &substring,
|
if (!parse_args_finds_unicode("rfind", args, &substring, &start, &end))
|
||||||
&start, &end))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (PyUnicode_READY(self) == -1)
|
if (PyUnicode_READY(self) == -1)
|
||||||
|
@ -12584,8 +12599,7 @@ unicode_rindex(PyObject *self, PyObject *args)
|
||||||
Py_ssize_t end = 0;
|
Py_ssize_t end = 0;
|
||||||
Py_ssize_t result;
|
Py_ssize_t result;
|
||||||
|
|
||||||
if (!stringlib_parse_args_finds_unicode("rindex", args, &substring,
|
if (!parse_args_finds_unicode("rindex", args, &substring, &start, &end))
|
||||||
&start, &end))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (PyUnicode_READY(self) == -1)
|
if (PyUnicode_READY(self) == -1)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue