Issue #26765: Moved common code and docstrings for bytes and bytearray methods

to bytes_methods.c.
This commit is contained in:
Serhiy Storchaka 2016-05-04 22:23:26 +03:00
parent 045e635100
commit dd40fc3e57
7 changed files with 519 additions and 777 deletions

View File

@ -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_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. */
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_capitalize__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_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 */
#define PyDoc_STRVAR_shared(name,str) const char name[] = PyDoc_STR(str)

View File

@ -1097,147 +1097,16 @@ bytearray_dealloc(PyByteArrayObject *self)
#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 *
bytearray_find(PyByteArrayObject *self, PyObject *args)
{
Py_ssize_t result = bytearray_find_internal(self, args, +1);
if (result == -2)
return NULL;
return PyLong_FromSsize_t(result);
return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
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 *
bytearray_count(PyByteArrayObject *self, PyObject *args)
{
PyObject *sub_obj;
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;
return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
/*[clinic input]
@ -1269,216 +1138,40 @@ bytearray_copy_impl(PyByteArrayObject *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 *
bytearray_index(PyByteArrayObject *self, PyObject *args)
{
Py_ssize_t result = bytearray_find_internal(self, args, +1);
if (result == -2)
return NULL;
if (result == -1) {
PyErr_SetString(PyExc_ValueError,
"subsection not found");
return NULL;
return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
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 *
bytearray_rfind(PyByteArrayObject *self, PyObject *args)
{
Py_ssize_t result = bytearray_find_internal(self, args, -1);
if (result == -2)
return NULL;
return PyLong_FromSsize_t(result);
return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
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 *
bytearray_rindex(PyByteArrayObject *self, PyObject *args)
{
Py_ssize_t result = bytearray_find_internal(self, args, -1);
if (result == -2)
return NULL;
if (result == -1) {
PyErr_SetString(PyExc_ValueError,
"subsection not found");
return NULL;
return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
return PyLong_FromSsize_t(result);
}
static int
bytearray_contains(PyObject *self, 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(PyByteArray_AS_STRING(self), Py_SIZE(self),
varg.buf, varg.len, 0);
PyBuffer_Release(&varg);
return pos >= 0;
return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg);
}
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 *
bytearray_startswith(PyByteArrayObject *self, PyObject *args)
{
Py_ssize_t start = 0;
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;
return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
}
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 *
bytearray_endswith(PyByteArrayObject *self, PyObject *args)
{
Py_ssize_t start = 0;
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);
return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
@ -1544,7 +1237,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
result = PyByteArray_FromStringAndSize((char *)NULL, inlen);
if (result == NULL)
goto done;
output_start = output = PyByteArray_AsString(result);
output_start = output = PyByteArray_AS_STRING(result);
input = PyByteArray_AS_STRING(input_obj);
if (vdel.len == 0 && table_chars != NULL) {
@ -2919,19 +2612,22 @@ bytearray_methods[] = {
BYTEARRAY_APPEND_METHODDEF
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
_Py_capitalize__doc__},
{"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},
{"center", (PyCFunction)stringlib_center, METH_VARARGS, _Py_center__doc__},
BYTEARRAY_CLEAR_METHODDEF
BYTEARRAY_COPY_METHODDEF
{"count", (PyCFunction)bytearray_count, METH_VARARGS, count__doc__},
{"count", (PyCFunction)bytearray_count, METH_VARARGS,
_Py_count__doc__},
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__doc__},
_Py_expandtabs__doc__},
BYTEARRAY_EXTEND_METHODDEF
{"find", (PyCFunction)bytearray_find, METH_VARARGS, find__doc__},
{"find", (PyCFunction)bytearray_find, METH_VARARGS,
_Py_find__doc__},
BYTEARRAY_FROMHEX_METHODDEF
{"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
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
_Py_isalnum__doc__},
@ -2948,7 +2644,7 @@ bytearray_methods[] = {
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
_Py_isupper__doc__},
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__},
BYTEARRAY_LSTRIP_METHODDEF
BYTEARRAY_MAKETRANS_METHODDEF
@ -2957,23 +2653,23 @@ bytearray_methods[] = {
BYTEARRAY_REMOVE_METHODDEF
BYTEARRAY_REPLACE_METHODDEF
BYTEARRAY_REVERSE_METHODDEF
{"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, rfind__doc__},
{"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, rindex__doc__},
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__},
{"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__},
{"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__},
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, _Py_rjust__doc__},
BYTEARRAY_RPARTITION_METHODDEF
BYTEARRAY_RSPLIT_METHODDEF
BYTEARRAY_RSTRIP_METHODDEF
BYTEARRAY_SPLIT_METHODDEF
BYTEARRAY_SPLITLINES_METHODDEF
{"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS ,
startswith__doc__},
_Py_startswith__doc__},
BYTEARRAY_STRIP_METHODDEF
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
_Py_swapcase__doc__},
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
BYTEARRAY_TRANSLATE_METHODDEF
{"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}
};

View File

@ -387,3 +387,427 @@ _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
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.");

View File

@ -486,11 +486,11 @@ formatlong(PyObject *v, int flags, int prec, int type)
static int
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];
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];
return 1;
}
@ -1488,24 +1488,7 @@ bytes_repeat(PyBytesObject *a, Py_ssize_t n)
static int
bytes_contains(PyObject *self, 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(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;
return _Py_bytes_contains(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), arg);
}
static PyObject *
@ -1890,157 +1873,30 @@ _PyBytes_Join(PyObject *sep, PyObject *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 *
bytes_find(PyBytesObject *self, PyObject *args)
{
Py_ssize_t result = bytes_find_internal(self, args, +1);
if (result == -2)
return NULL;
return PyLong_FromSsize_t(result);
return _Py_bytes_find(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
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 *
bytes_index(PyBytesObject *self, PyObject *args)
{
Py_ssize_t result = bytes_find_internal(self, args, +1);
if (result == -2)
return NULL;
if (result == -1) {
PyErr_SetString(PyExc_ValueError,
"substring not found");
return NULL;
}
return PyLong_FromSsize_t(result);
return _Py_bytes_index(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
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 *
bytes_rfind(PyBytesObject *self, PyObject *args)
{
Py_ssize_t result = bytes_find_internal(self, args, -1);
if (result == -2)
return NULL;
return PyLong_FromSsize_t(result);
return _Py_bytes_rfind(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
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 *
bytes_rindex(PyBytesObject *self, PyObject *args)
{
Py_ssize_t result = bytes_find_internal(self, args, -1);
if (result == -2)
return NULL;
if (result == -1) {
PyErr_SetString(PyExc_ValueError,
"substring not found");
return NULL;
}
return PyLong_FromSsize_t(result);
return _Py_bytes_rindex(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
@ -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 *
bytes_count(PyBytesObject *self, PyObject *args)
{
PyObject *sub_obj;
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;
return _Py_bytes_count(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
@ -2307,7 +2122,7 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
PyBuffer_Release(&table_view);
return NULL;
}
output_start = output = PyBytes_AsString(result);
output_start = output = PyBytes_AS_STRING(result);
input = PyBytes_AS_STRING(input_obj);
if (dellen == 0 && table_chars != NULL) {
@ -2914,145 +2729,17 @@ bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new,
/** 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 *
bytes_startswith(PyBytesObject *self, PyObject *args)
{
Py_ssize_t start = 0;
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;
return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
}
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 *
bytes_endswith(PyBytesObject *self, PyObject *args)
{
Py_ssize_t start = 0;
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);
return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
@ -3224,17 +2911,20 @@ bytes_methods[] = {
{"__getnewargs__", (PyCFunction)bytes_getnewargs, METH_NOARGS},
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
_Py_capitalize__doc__},
{"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},
{"count", (PyCFunction)bytes_count, METH_VARARGS, count__doc__},
{"center", (PyCFunction)stringlib_center, METH_VARARGS,
_Py_center__doc__},
{"count", (PyCFunction)bytes_count, METH_VARARGS,
_Py_count__doc__},
BYTES_DECODE_METHODDEF
{"endswith", (PyCFunction)bytes_endswith, METH_VARARGS,
endswith__doc__},
_Py_endswith__doc__},
{"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
expandtabs__doc__},
{"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__},
_Py_expandtabs__doc__},
{"find", (PyCFunction)bytes_find, METH_VARARGS,
_Py_find__doc__},
BYTES_FROMHEX_METHODDEF
{"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,
_Py_isalnum__doc__},
{"isalpha", (PyCFunction)stringlib_isalpha, METH_NOARGS,
@ -3250,29 +2940,29 @@ bytes_methods[] = {
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
_Py_isupper__doc__},
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__},
BYTES_LSTRIP_METHODDEF
BYTES_MAKETRANS_METHODDEF
BYTES_PARTITION_METHODDEF
BYTES_REPLACE_METHODDEF
{"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, rfind__doc__},
{"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, rindex__doc__},
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__},
{"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, _Py_rfind__doc__},
{"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, _Py_rindex__doc__},
{"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, _Py_rjust__doc__},
BYTES_RPARTITION_METHODDEF
BYTES_RSPLIT_METHODDEF
BYTES_RSTRIP_METHODDEF
BYTES_SPLIT_METHODDEF
BYTES_SPLITLINES_METHODDEF
{"startswith", (PyCFunction)bytes_startswith, METH_VARARGS,
startswith__doc__},
_Py_startswith__doc__},
BYTES_STRIP_METHODDEF
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
_Py_swapcase__doc__},
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
BYTES_TRANSLATE_METHODDEF
{"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 */
};

View File

@ -117,76 +117,3 @@ STRINGLIB(parse_args_finds)(const char * function_name, PyObject *args,
}
#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 */

View File

@ -4,12 +4,6 @@
/* 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. */
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*
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;
}
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 *
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 *
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 *
stringlib_center(PyObject *self, PyObject *args)
{
@ -213,12 +189,6 @@ stringlib_center(PyObject *self, PyObject *args)
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 *
stringlib_zfill(PyObject *self, PyObject *args)
{

View File

@ -11244,6 +11244,25 @@ PyUnicode_AppendAndDel(PyObject **pleft, PyObject *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__,
"S.count(sub[, start[, end]]) -> int\n\
\n\
@ -11262,8 +11281,7 @@ unicode_count(PyObject *self, PyObject *args)
void *buf1, *buf2;
Py_ssize_t len1, len2, iresult;
if (!stringlib_parse_args_finds_unicode("count", args, &substring,
&start, &end))
if (!parse_args_finds_unicode("count", args, &substring, &start, &end))
return NULL;
kind1 = PyUnicode_KIND(self);
@ -11445,8 +11463,7 @@ unicode_find(PyObject *self, PyObject *args)
Py_ssize_t end = 0;
Py_ssize_t result;
if (!stringlib_parse_args_finds_unicode("find", args, &substring,
&start, &end))
if (!parse_args_finds_unicode("find", args, &substring, &start, &end))
return NULL;
if (PyUnicode_READY(self) == -1)
@ -11525,8 +11542,7 @@ unicode_index(PyObject *self, PyObject *args)
Py_ssize_t start = 0;
Py_ssize_t end = 0;
if (!stringlib_parse_args_finds_unicode("index", args, &substring,
&start, &end))
if (!parse_args_finds_unicode("index", args, &substring, &start, &end))
return NULL;
if (PyUnicode_READY(self) == -1)
@ -12555,8 +12571,7 @@ unicode_rfind(PyObject *self, PyObject *args)
Py_ssize_t end = 0;
Py_ssize_t result;
if (!stringlib_parse_args_finds_unicode("rfind", args, &substring,
&start, &end))
if (!parse_args_finds_unicode("rfind", args, &substring, &start, &end))
return NULL;
if (PyUnicode_READY(self) == -1)
@ -12584,8 +12599,7 @@ unicode_rindex(PyObject *self, PyObject *args)
Py_ssize_t end = 0;
Py_ssize_t result;
if (!stringlib_parse_args_finds_unicode("rindex", args, &substring,
&start, &end))
if (!parse_args_finds_unicode("rindex", args, &substring, &start, &end))
return NULL;
if (PyUnicode_READY(self) == -1)