mirror of
https://github.com/python/cpython
synced 2026-09-29 12:10:30 +03:00
Issue #22896: Avoid to use PyObject_AsCharBuffer(), PyObject_AsReadBuffer()
and PyObject_AsWriteBuffer().
This commit is contained in:
commit
3dd3e26680
18 changed files with 422 additions and 397 deletions
|
|
@ -250,27 +250,7 @@ PyObject_AsCharBuffer(PyObject *obj,
|
|||
const char **buffer,
|
||||
Py_ssize_t *buffer_len)
|
||||
{
|
||||
PyBufferProcs *pb;
|
||||
Py_buffer view;
|
||||
|
||||
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
|
||||
null_error();
|
||||
return -1;
|
||||
}
|
||||
pb = obj->ob_type->tp_as_buffer;
|
||||
if (pb == NULL || pb->bf_getbuffer == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"expected a bytes-like object");
|
||||
return -1;
|
||||
}
|
||||
if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
|
||||
|
||||
*buffer = view.buf;
|
||||
*buffer_len = view.len;
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(obj, &view);
|
||||
Py_XDECREF(view.obj);
|
||||
return 0;
|
||||
return PyObject_AsReadBuffer(obj, (const void **)buffer, buffer_len);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -294,28 +274,18 @@ int PyObject_AsReadBuffer(PyObject *obj,
|
|||
const void **buffer,
|
||||
Py_ssize_t *buffer_len)
|
||||
{
|
||||
PyBufferProcs *pb;
|
||||
Py_buffer view;
|
||||
|
||||
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
|
||||
null_error();
|
||||
return -1;
|
||||
}
|
||||
pb = obj->ob_type->tp_as_buffer;
|
||||
if (pb == NULL ||
|
||||
pb->bf_getbuffer == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"expected a bytes-like object");
|
||||
if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
|
||||
|
||||
*buffer = view.buf;
|
||||
*buffer_len = view.len;
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(obj, &view);
|
||||
Py_XDECREF(view.obj);
|
||||
PyBuffer_Release(&view);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -341,9 +311,7 @@ int PyObject_AsWriteBuffer(PyObject *obj,
|
|||
|
||||
*buffer = view.buf;
|
||||
*buffer_len = view.len;
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(obj, &view);
|
||||
Py_XDECREF(view.obj);
|
||||
PyBuffer_Release(&view);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -352,13 +320,15 @@ int PyObject_AsWriteBuffer(PyObject *obj,
|
|||
int
|
||||
PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
|
||||
{
|
||||
if (!PyObject_CheckBuffer(obj)) {
|
||||
PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
|
||||
|
||||
if (pb == NULL || pb->bf_getbuffer == NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"a bytes-like object is required, not '%.100s'",
|
||||
Py_TYPE(obj)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
|
||||
return (*pb->bf_getbuffer)(obj, view, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -676,10 +646,14 @@ void
|
|||
PyBuffer_Release(Py_buffer *view)
|
||||
{
|
||||
PyObject *obj = view->obj;
|
||||
if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)
|
||||
Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);
|
||||
Py_XDECREF(obj);
|
||||
PyBufferProcs *pb;
|
||||
if (obj == NULL)
|
||||
return;
|
||||
pb = Py_TYPE(obj)->tp_as_buffer;
|
||||
if (pb && pb->bf_releasebuffer)
|
||||
pb->bf_releasebuffer(obj, view);
|
||||
view->obj = NULL;
|
||||
Py_DECREF(obj);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
|
@ -1288,8 +1262,7 @@ PyNumber_Long(PyObject *o)
|
|||
{
|
||||
PyNumberMethods *m;
|
||||
PyObject *trunc_func;
|
||||
const char *buffer;
|
||||
Py_ssize_t buffer_len;
|
||||
Py_buffer view;
|
||||
_Py_IDENTIFIER(__trunc__);
|
||||
|
||||
if (o == NULL)
|
||||
|
|
@ -1327,21 +1300,22 @@ PyNumber_Long(PyObject *o)
|
|||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
|
||||
if (PyBytes_Check(o))
|
||||
if (PyUnicode_Check(o))
|
||||
/* The below check is done in PyLong_FromUnicode(). */
|
||||
return PyLong_FromUnicodeObject(o, 10);
|
||||
|
||||
if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == 0) {
|
||||
/* need to do extra error checking that PyLong_FromString()
|
||||
* doesn't do. In particular int('9\x005') must raise an
|
||||
* exception, not truncate at the null.
|
||||
*/
|
||||
return _PyLong_FromBytes(PyBytes_AS_STRING(o),
|
||||
PyBytes_GET_SIZE(o), 10);
|
||||
if (PyUnicode_Check(o))
|
||||
/* The above check is done in PyLong_FromUnicode(). */
|
||||
return PyLong_FromUnicodeObject(o, 10);
|
||||
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
|
||||
return _PyLong_FromBytes(buffer, buffer_len, 10);
|
||||
PyObject *result = _PyLong_FromBytes(view.buf, view.len, 10);
|
||||
PyBuffer_Release(&view);
|
||||
return result;
|
||||
}
|
||||
|
||||
return type_error("int() argument must be a string or a "
|
||||
"number, not '%.200s'", o);
|
||||
return type_error("int() argument must be a string, a bytes-like object "
|
||||
"or a number, not '%.200s'", o);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
|
|
|||
|
|
@ -80,24 +80,6 @@ bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view)
|
|||
obj->ob_exports--;
|
||||
}
|
||||
|
||||
static Py_ssize_t
|
||||
_getbuffer(PyObject *obj, Py_buffer *view)
|
||||
{
|
||||
PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer;
|
||||
|
||||
if (buffer == NULL || buffer->bf_getbuffer == NULL)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"a bytes-like object is required, not '%.100s'",
|
||||
Py_TYPE(obj)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
|
||||
return -1;
|
||||
return view->len;
|
||||
}
|
||||
|
||||
static int
|
||||
_canresize(PyByteArrayObject *self)
|
||||
{
|
||||
|
|
@ -268,8 +250,8 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
|
|||
|
||||
va.len = -1;
|
||||
vb.len = -1;
|
||||
if (_getbuffer(a, &va) < 0 ||
|
||||
_getbuffer(b, &vb) < 0) {
|
||||
if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
|
||||
PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
|
||||
Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
|
||||
goto done;
|
||||
|
|
@ -335,7 +317,7 @@ bytearray_iconcat(PyByteArrayObject *self, PyObject *other)
|
|||
Py_ssize_t size;
|
||||
Py_buffer vo;
|
||||
|
||||
if (_getbuffer(other, &vo) < 0) {
|
||||
if (PyObject_GetBuffer(other, &vo, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
|
||||
Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name);
|
||||
return NULL;
|
||||
|
|
@ -595,14 +577,14 @@ bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
|
|||
needed = 0;
|
||||
}
|
||||
else {
|
||||
if (_getbuffer(values, &vbytes) < 0) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"can't set bytearray slice from %.100s",
|
||||
Py_TYPE(values)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
needed = vbytes.len;
|
||||
bytes = vbytes.buf;
|
||||
if (PyObject_GetBuffer(values, &vbytes, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"can't set bytearray slice from %.100s",
|
||||
Py_TYPE(values)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
needed = vbytes.len;
|
||||
bytes = vbytes.buf;
|
||||
}
|
||||
|
||||
if (lo < 0)
|
||||
|
|
@ -1047,18 +1029,18 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op)
|
|||
Py_RETURN_NOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
self_size = _getbuffer(self, &self_bytes);
|
||||
if (self_size < 0) {
|
||||
if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_Clear();
|
||||
Py_RETURN_NOTIMPLEMENTED;
|
||||
}
|
||||
self_size = self_bytes.len;
|
||||
|
||||
other_size = _getbuffer(other, &other_bytes);
|
||||
if (other_size < 0) {
|
||||
if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_Clear();
|
||||
PyBuffer_Release(&self_bytes);
|
||||
Py_RETURN_NOTIMPLEMENTED;
|
||||
}
|
||||
other_size = other_bytes.len;
|
||||
|
||||
if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
|
||||
/* Shortcut: if the lengths differ, the objects differ */
|
||||
|
|
@ -1170,7 +1152,7 @@ bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
|
|||
return -2;
|
||||
|
||||
if (subobj) {
|
||||
if (_getbuffer(subobj, &subbuf) < 0)
|
||||
if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
|
||||
return -2;
|
||||
|
||||
sub = subbuf.buf;
|
||||
|
|
@ -1238,7 +1220,7 @@ bytearray_count(PyByteArrayObject *self, PyObject *args)
|
|||
return NULL;
|
||||
|
||||
if (sub_obj) {
|
||||
if (_getbuffer(sub_obj, &vsub) < 0)
|
||||
if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
|
||||
sub = vsub.buf;
|
||||
|
|
@ -1397,7 +1379,7 @@ bytearray_contains(PyObject *self, PyObject *arg)
|
|||
Py_buffer varg;
|
||||
Py_ssize_t pos;
|
||||
PyErr_Clear();
|
||||
if (_getbuffer(arg, &varg) < 0)
|
||||
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);
|
||||
|
|
@ -1428,7 +1410,7 @@ _bytearray_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start
|
|||
|
||||
str = PyByteArray_AS_STRING(self);
|
||||
|
||||
if (_getbuffer(substr, &vsubstr) < 0)
|
||||
if (PyObject_GetBuffer(substr, &vsubstr, PyBUF_SIMPLE) != 0)
|
||||
return -1;
|
||||
|
||||
ADJUST_INDICES(start, end, len);
|
||||
|
|
@ -1621,7 +1603,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_rig
|
|||
if (table == Py_None) {
|
||||
table_chars = NULL;
|
||||
table = NULL;
|
||||
} else if (_getbuffer(table, &vtable) < 0) {
|
||||
} else if (PyObject_GetBuffer(table, &vtable, PyBUF_SIMPLE) != 0) {
|
||||
return NULL;
|
||||
} else {
|
||||
if (vtable.len != 256) {
|
||||
|
|
@ -1634,7 +1616,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_rig
|
|||
}
|
||||
|
||||
if (deletechars != NULL) {
|
||||
if (_getbuffer(deletechars, &vdel) < 0) {
|
||||
if (PyObject_GetBuffer(deletechars, &vdel, PyBUF_SIMPLE) != 0) {
|
||||
if (table != NULL)
|
||||
PyBuffer_Release(&vtable);
|
||||
return NULL;
|
||||
|
|
@ -1699,8 +1681,8 @@ done:
|
|||
@staticmethod
|
||||
bytearray.maketrans
|
||||
|
||||
frm: object
|
||||
to: object
|
||||
frm: Py_buffer
|
||||
to: Py_buffer
|
||||
/
|
||||
|
||||
Return a translation table useable for the bytes or bytearray translate method.
|
||||
|
|
@ -1726,28 +1708,35 @@ PyDoc_STRVAR(bytearray_maketrans__doc__,
|
|||
{"maketrans", (PyCFunction)bytearray_maketrans, METH_VARARGS|METH_STATIC, bytearray_maketrans__doc__},
|
||||
|
||||
static PyObject *
|
||||
bytearray_maketrans_impl(PyObject *frm, PyObject *to);
|
||||
bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to);
|
||||
|
||||
static PyObject *
|
||||
bytearray_maketrans(void *null, PyObject *args)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyObject *frm;
|
||||
PyObject *to;
|
||||
Py_buffer frm = {NULL, NULL};
|
||||
Py_buffer to = {NULL, NULL};
|
||||
|
||||
if (!PyArg_UnpackTuple(args, "maketrans",
|
||||
2, 2,
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"y*y*:maketrans",
|
||||
&frm, &to))
|
||||
goto exit;
|
||||
return_value = bytearray_maketrans_impl(frm, to);
|
||||
return_value = bytearray_maketrans_impl(&frm, &to);
|
||||
|
||||
exit:
|
||||
/* Cleanup for frm */
|
||||
if (frm.obj)
|
||||
PyBuffer_Release(&frm);
|
||||
/* Cleanup for to */
|
||||
if (to.obj)
|
||||
PyBuffer_Release(&to);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
bytearray_maketrans_impl(PyObject *frm, PyObject *to)
|
||||
/*[clinic end generated code: output=307752019d9b25b5 input=ea9bdc6b328c15e2]*/
|
||||
bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to)
|
||||
/*[clinic end generated code: output=d332622814c26f4b input=5925a81d2fbbf151]*/
|
||||
{
|
||||
return _Py_bytes_maketrans(frm, to);
|
||||
}
|
||||
|
|
@ -2243,8 +2232,8 @@ replace(PyByteArrayObject *self,
|
|||
/*[clinic input]
|
||||
bytearray.replace
|
||||
|
||||
old: object
|
||||
new: object
|
||||
old: Py_buffer
|
||||
new: Py_buffer
|
||||
count: Py_ssize_t = -1
|
||||
Maximum number of occurrences to replace.
|
||||
-1 (the default value) means replace all occurrences.
|
||||
|
|
@ -2273,47 +2262,40 @@ PyDoc_STRVAR(bytearray_replace__doc__,
|
|||
{"replace", (PyCFunction)bytearray_replace, METH_VARARGS, bytearray_replace__doc__},
|
||||
|
||||
static PyObject *
|
||||
bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count);
|
||||
bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count);
|
||||
|
||||
static PyObject *
|
||||
bytearray_replace(PyByteArrayObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyObject *old;
|
||||
PyObject *new;
|
||||
Py_buffer old = {NULL, NULL};
|
||||
Py_buffer new = {NULL, NULL};
|
||||
Py_ssize_t count = -1;
|
||||
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"OO|n:replace",
|
||||
"y*y*|n:replace",
|
||||
&old, &new, &count))
|
||||
goto exit;
|
||||
return_value = bytearray_replace_impl(self, old, new, count);
|
||||
return_value = bytearray_replace_impl(self, &old, &new, count);
|
||||
|
||||
exit:
|
||||
/* Cleanup for old */
|
||||
if (old.obj)
|
||||
PyBuffer_Release(&old);
|
||||
/* Cleanup for new */
|
||||
if (new.obj)
|
||||
PyBuffer_Release(&new);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count)
|
||||
/*[clinic end generated code: output=4d2e3c9130da0f96 input=9aaaa123608dfc1f]*/
|
||||
bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count)
|
||||
/*[clinic end generated code: output=9997fbbd5bac4883 input=aa379d988637c7fb]*/
|
||||
{
|
||||
PyObject *res;
|
||||
Py_buffer vold, vnew;
|
||||
|
||||
if (_getbuffer(old, &vold) < 0)
|
||||
return NULL;
|
||||
if (_getbuffer(new, &vnew) < 0) {
|
||||
PyBuffer_Release(&vold);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = (PyObject *)replace((PyByteArrayObject *) self,
|
||||
vold.buf, vold.len,
|
||||
vnew.buf, vnew.len, count);
|
||||
|
||||
PyBuffer_Release(&vold);
|
||||
PyBuffer_Release(&vnew);
|
||||
return res;
|
||||
return (PyObject *)replace((PyByteArrayObject *) self,
|
||||
old->buf, old->len,
|
||||
new->buf, new->len, count);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
|
|
@ -2383,7 +2365,7 @@ bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit
|
|||
if (sep == Py_None)
|
||||
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
|
||||
|
||||
if (_getbuffer(sep, &vsub) < 0)
|
||||
if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
sub = vsub.buf;
|
||||
n = vsub.len;
|
||||
|
|
@ -2566,7 +2548,7 @@ bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxspli
|
|||
if (sep == Py_None)
|
||||
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
|
||||
|
||||
if (_getbuffer(sep, &vsub) < 0)
|
||||
if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
sub = vsub.buf;
|
||||
n = vsub.len;
|
||||
|
|
@ -3088,7 +3070,7 @@ bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes)
|
|||
byteslen = 6;
|
||||
}
|
||||
else {
|
||||
if (_getbuffer(bytes, &vbytes) < 0)
|
||||
if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
bytesptr = (char *) vbytes.buf;
|
||||
byteslen = vbytes.len;
|
||||
|
|
@ -3159,7 +3141,7 @@ bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes)
|
|||
byteslen = 6;
|
||||
}
|
||||
else {
|
||||
if (_getbuffer(bytes, &vbytes) < 0)
|
||||
if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
bytesptr = (char *) vbytes.buf;
|
||||
byteslen = vbytes.len;
|
||||
|
|
@ -3227,7 +3209,7 @@ bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes)
|
|||
byteslen = 6;
|
||||
}
|
||||
else {
|
||||
if (_getbuffer(bytes, &vbytes) < 0)
|
||||
if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
bytesptr = (char *) vbytes.buf;
|
||||
byteslen = vbytes.len;
|
||||
|
|
|
|||
|
|
@ -363,59 +363,27 @@ for use in the bytes or bytearray translate method where each byte\n\
|
|||
in frm is mapped to the byte at the same position in to.\n\
|
||||
The bytes objects frm and to must be of the same length.");
|
||||
|
||||
static Py_ssize_t
|
||||
_getbuffer(PyObject *obj, Py_buffer *view)
|
||||
{
|
||||
PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer;
|
||||
|
||||
if (buffer == NULL || buffer->bf_getbuffer == NULL)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"a bytes-like object is required, not '%.100s'",
|
||||
Py_TYPE(obj)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
|
||||
return -1;
|
||||
return view->len;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
_Py_bytes_maketrans(PyObject *frm, PyObject *to)
|
||||
_Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
|
||||
{
|
||||
PyObject *res = NULL;
|
||||
Py_buffer bfrm, bto;
|
||||
Py_ssize_t i;
|
||||
char *p;
|
||||
|
||||
bfrm.len = -1;
|
||||
bto.len = -1;
|
||||
|
||||
if (_getbuffer(frm, &bfrm) < 0)
|
||||
return NULL;
|
||||
if (_getbuffer(to, &bto) < 0)
|
||||
goto done;
|
||||
if (bfrm.len != bto.len) {
|
||||
if (frm->len != to->len) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"maketrans arguments must have same length");
|
||||
goto done;
|
||||
return NULL;
|
||||
}
|
||||
res = PyBytes_FromStringAndSize(NULL, 256);
|
||||
if (!res) {
|
||||
goto done;
|
||||
}
|
||||
if (!res)
|
||||
return NULL;
|
||||
p = PyBytes_AS_STRING(res);
|
||||
for (i = 0; i < 256; i++)
|
||||
p[i] = (char) i;
|
||||
for (i = 0; i < bfrm.len; i++) {
|
||||
p[((unsigned char *)bfrm.buf)[i]] = ((char *)bto.buf)[i];
|
||||
for (i = 0; i < frm->len; i++) {
|
||||
p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i];
|
||||
}
|
||||
|
||||
done:
|
||||
if (bfrm.len != -1)
|
||||
PyBuffer_Release(&bfrm);
|
||||
if (bto.len != -1)
|
||||
PyBuffer_Release(&bto);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,33 +12,6 @@ class bytes "PyBytesObject*" "&PyBytes_Type"
|
|||
[clinic start generated code]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1a1d9102afc1b00c]*/
|
||||
|
||||
static Py_ssize_t
|
||||
_getbuffer(PyObject *obj, Py_buffer *view)
|
||||
{
|
||||
PyBufferProcs *bufferprocs;
|
||||
if (PyBytes_CheckExact(obj)) {
|
||||
/* Fast path, e.g. for .join() of many bytes objects */
|
||||
Py_INCREF(obj);
|
||||
view->obj = obj;
|
||||
view->buf = PyBytes_AS_STRING(obj);
|
||||
view->len = PyBytes_GET_SIZE(obj);
|
||||
return view->len;
|
||||
}
|
||||
|
||||
bufferprocs = Py_TYPE(obj)->tp_as_buffer;
|
||||
if (bufferprocs == NULL || bufferprocs->bf_getbuffer == NULL)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"a bytes-like object is required, not '%.100s'",
|
||||
Py_TYPE(obj)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bufferprocs->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
|
||||
return -1;
|
||||
return view->len;
|
||||
}
|
||||
|
||||
#ifdef COUNT_ALLOCS
|
||||
Py_ssize_t null_strings, one_strings;
|
||||
#endif
|
||||
|
|
@ -1349,8 +1322,8 @@ bytes_concat(PyObject *a, PyObject *b)
|
|||
|
||||
va.len = -1;
|
||||
vb.len = -1;
|
||||
if (_getbuffer(a, &va) < 0 ||
|
||||
_getbuffer(b, &vb) < 0) {
|
||||
if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
|
||||
PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
|
||||
Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
|
||||
goto done;
|
||||
|
|
@ -1448,7 +1421,7 @@ bytes_contains(PyObject *self, PyObject *arg)
|
|||
Py_buffer varg;
|
||||
Py_ssize_t pos;
|
||||
PyErr_Clear();
|
||||
if (_getbuffer(arg, &varg) < 0)
|
||||
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);
|
||||
|
|
@ -1737,7 +1710,7 @@ bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
|
|||
maxsplit = PY_SSIZE_T_MAX;
|
||||
if (sep == Py_None)
|
||||
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
|
||||
if (_getbuffer(sep, &vsub) < 0)
|
||||
if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
sub = vsub.buf;
|
||||
n = vsub.len;
|
||||
|
|
@ -1751,7 +1724,7 @@ bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
|
|||
bytes.partition
|
||||
|
||||
self: self(type="PyBytesObject *")
|
||||
sep: object
|
||||
sep: Py_buffer
|
||||
/
|
||||
|
||||
Partition the bytes into three parts using the given separator.
|
||||
|
|
@ -1778,26 +1751,39 @@ PyDoc_STRVAR(bytes_partition__doc__,
|
|||
"object and two empty bytes objects.");
|
||||
|
||||
#define BYTES_PARTITION_METHODDEF \
|
||||
{"partition", (PyCFunction)bytes_partition, METH_O, bytes_partition__doc__},
|
||||
{"partition", (PyCFunction)bytes_partition, METH_VARARGS, bytes_partition__doc__},
|
||||
|
||||
static PyObject *
|
||||
bytes_partition(PyBytesObject *self, PyObject *sep)
|
||||
/*[clinic end generated code: output=b41e119c873c08bc input=6c5b9dcc5a9fd62e]*/
|
||||
bytes_partition_impl(PyBytesObject *self, Py_buffer *sep);
|
||||
|
||||
static PyObject *
|
||||
bytes_partition(PyBytesObject *self, PyObject *args)
|
||||
{
|
||||
const char *sep_chars;
|
||||
Py_ssize_t sep_len;
|
||||
PyObject *return_value = NULL;
|
||||
Py_buffer sep = {NULL, NULL};
|
||||
|
||||
if (PyBytes_Check(sep)) {
|
||||
sep_chars = PyBytes_AS_STRING(sep);
|
||||
sep_len = PyBytes_GET_SIZE(sep);
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len))
|
||||
return NULL;
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"y*:partition",
|
||||
&sep))
|
||||
goto exit;
|
||||
return_value = bytes_partition_impl(self, &sep);
|
||||
|
||||
exit:
|
||||
/* Cleanup for sep */
|
||||
if (sep.obj)
|
||||
PyBuffer_Release(&sep);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
bytes_partition_impl(PyBytesObject *self, Py_buffer *sep)
|
||||
/*[clinic end generated code: output=3006727cfbf83aa4 input=bc855dc63ca949de]*/
|
||||
{
|
||||
return stringlib_partition(
|
||||
(PyObject*) self,
|
||||
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
|
||||
sep, sep_chars, sep_len
|
||||
sep->obj, (const char *)sep->buf, sep->len
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1805,7 +1791,7 @@ bytes_partition(PyBytesObject *self, PyObject *sep)
|
|||
bytes.rpartition
|
||||
|
||||
self: self(type="PyBytesObject *")
|
||||
sep: object
|
||||
sep: Py_buffer
|
||||
/
|
||||
|
||||
Partition the bytes into three parts using the given separator.
|
||||
|
|
@ -1832,26 +1818,39 @@ PyDoc_STRVAR(bytes_rpartition__doc__,
|
|||
"objects and the original bytes object.");
|
||||
|
||||
#define BYTES_RPARTITION_METHODDEF \
|
||||
{"rpartition", (PyCFunction)bytes_rpartition, METH_O, bytes_rpartition__doc__},
|
||||
{"rpartition", (PyCFunction)bytes_rpartition, METH_VARARGS, bytes_rpartition__doc__},
|
||||
|
||||
static PyObject *
|
||||
bytes_rpartition(PyBytesObject *self, PyObject *sep)
|
||||
/*[clinic end generated code: output=3a620803657196ee input=79bc2932e78e5ce0]*/
|
||||
bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep);
|
||||
|
||||
static PyObject *
|
||||
bytes_rpartition(PyBytesObject *self, PyObject *args)
|
||||
{
|
||||
const char *sep_chars;
|
||||
Py_ssize_t sep_len;
|
||||
PyObject *return_value = NULL;
|
||||
Py_buffer sep = {NULL, NULL};
|
||||
|
||||
if (PyBytes_Check(sep)) {
|
||||
sep_chars = PyBytes_AS_STRING(sep);
|
||||
sep_len = PyBytes_GET_SIZE(sep);
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len))
|
||||
return NULL;
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"y*:rpartition",
|
||||
&sep))
|
||||
goto exit;
|
||||
return_value = bytes_rpartition_impl(self, &sep);
|
||||
|
||||
exit:
|
||||
/* Cleanup for sep */
|
||||
if (sep.obj)
|
||||
PyBuffer_Release(&sep);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep)
|
||||
/*[clinic end generated code: output=57b169dc47fa90e8 input=6588fff262a9170e]*/
|
||||
{
|
||||
return stringlib_rpartition(
|
||||
(PyObject*) self,
|
||||
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
|
||||
sep, sep_chars, sep_len
|
||||
sep->obj, (const char *)sep->buf, sep->len
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1916,7 +1915,7 @@ bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
|
|||
maxsplit = PY_SSIZE_T_MAX;
|
||||
if (sep == Py_None)
|
||||
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
|
||||
if (_getbuffer(sep, &vsub) < 0)
|
||||
if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
sub = vsub.buf;
|
||||
n = vsub.len;
|
||||
|
|
@ -2003,7 +2002,7 @@ bytes_find_internal(PyBytesObject *self, PyObject *args, int dir)
|
|||
return -2;
|
||||
|
||||
if (subobj) {
|
||||
if (_getbuffer(subobj, &subbuf) < 0)
|
||||
if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
|
||||
return -2;
|
||||
|
||||
sub = subbuf.buf;
|
||||
|
|
@ -2118,7 +2117,7 @@ do_xstrip(PyBytesObject *self, int striptype, PyObject *sepobj)
|
|||
Py_ssize_t seplen;
|
||||
Py_ssize_t i, j;
|
||||
|
||||
if (_getbuffer(sepobj, &vsep) < 0)
|
||||
if (PyObject_GetBuffer(sepobj, &vsep, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
sep = vsep.buf;
|
||||
seplen = vsep.len;
|
||||
|
|
@ -2360,7 +2359,7 @@ bytes_count(PyBytesObject *self, PyObject *args)
|
|||
return NULL;
|
||||
|
||||
if (sub_obj) {
|
||||
if (_getbuffer(sub_obj, &vsub) < 0)
|
||||
if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
|
||||
sub = vsub.buf;
|
||||
|
|
@ -2450,6 +2449,8 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
|
|||
/*[clinic end generated code: output=f0f29a57f41df5d8 input=d8fa5519d7cc4be7]*/
|
||||
{
|
||||
char *input, *output;
|
||||
Py_buffer table_view = {NULL, NULL};
|
||||
Py_buffer del_table_view = {NULL, NULL};
|
||||
const char *table_chars;
|
||||
Py_ssize_t i, c, changed = 0;
|
||||
PyObject *input_obj = (PyObject*)self;
|
||||
|
|
@ -2466,12 +2467,17 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
|
|||
table_chars = NULL;
|
||||
tablen = 256;
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(table, &table_chars, &tablen))
|
||||
return NULL;
|
||||
else {
|
||||
if (PyObject_GetBuffer(table, &table_view, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
table_chars = table_view.buf;
|
||||
tablen = table_view.len;
|
||||
}
|
||||
|
||||
if (tablen != 256) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"translation table must be 256 characters long");
|
||||
PyBuffer_Release(&table_view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -2480,8 +2486,14 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
|
|||
del_table_chars = PyBytes_AS_STRING(deletechars);
|
||||
dellen = PyBytes_GET_SIZE(deletechars);
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(deletechars, &del_table_chars, &dellen))
|
||||
return NULL;
|
||||
else {
|
||||
if (PyObject_GetBuffer(deletechars, &del_table_view, PyBUF_SIMPLE) != 0) {
|
||||
PyBuffer_Release(&table_view);
|
||||
return NULL;
|
||||
}
|
||||
del_table_chars = del_table_view.buf;
|
||||
dellen = del_table_view.len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
del_table_chars = NULL;
|
||||
|
|
@ -2490,8 +2502,11 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
|
|||
|
||||
inlen = PyBytes_GET_SIZE(input_obj);
|
||||
result = PyBytes_FromStringAndSize((char *)NULL, inlen);
|
||||
if (result == NULL)
|
||||
if (result == NULL) {
|
||||
PyBuffer_Release(&del_table_view);
|
||||
PyBuffer_Release(&table_view);
|
||||
return NULL;
|
||||
}
|
||||
output_start = output = PyBytes_AsString(result);
|
||||
input = PyBytes_AS_STRING(input_obj);
|
||||
|
||||
|
|
@ -2502,11 +2517,14 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
|
|||
if (Py_CHARMASK((*output++ = table_chars[c])) != c)
|
||||
changed = 1;
|
||||
}
|
||||
if (changed || !PyBytes_CheckExact(input_obj))
|
||||
return result;
|
||||
Py_DECREF(result);
|
||||
Py_INCREF(input_obj);
|
||||
return input_obj;
|
||||
if (!changed && PyBytes_CheckExact(input_obj)) {
|
||||
Py_INCREF(input_obj);
|
||||
Py_DECREF(result);
|
||||
result = input_obj;
|
||||
}
|
||||
PyBuffer_Release(&del_table_view);
|
||||
PyBuffer_Release(&table_view);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (table_chars == NULL) {
|
||||
|
|
@ -2516,9 +2534,11 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
|
|||
for (i = 0; i < 256; i++)
|
||||
trans_table[i] = Py_CHARMASK(table_chars[i]);
|
||||
}
|
||||
PyBuffer_Release(&table_view);
|
||||
|
||||
for (i = 0; i < dellen; i++)
|
||||
trans_table[(int) Py_CHARMASK(del_table_chars[i])] = -1;
|
||||
PyBuffer_Release(&del_table_view);
|
||||
|
||||
for (i = inlen; --i >= 0; ) {
|
||||
c = Py_CHARMASK(*input++);
|
||||
|
|
@ -2544,8 +2564,8 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
|
|||
@staticmethod
|
||||
bytes.maketrans
|
||||
|
||||
frm: object
|
||||
to: object
|
||||
frm: Py_buffer
|
||||
to: Py_buffer
|
||||
/
|
||||
|
||||
Return a translation table useable for the bytes or bytearray translate method.
|
||||
|
|
@ -2571,28 +2591,35 @@ PyDoc_STRVAR(bytes_maketrans__doc__,
|
|||
{"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC, bytes_maketrans__doc__},
|
||||
|
||||
static PyObject *
|
||||
bytes_maketrans_impl(PyObject *frm, PyObject *to);
|
||||
bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to);
|
||||
|
||||
static PyObject *
|
||||
bytes_maketrans(void *null, PyObject *args)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyObject *frm;
|
||||
PyObject *to;
|
||||
Py_buffer frm = {NULL, NULL};
|
||||
Py_buffer to = {NULL, NULL};
|
||||
|
||||
if (!PyArg_UnpackTuple(args, "maketrans",
|
||||
2, 2,
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"y*y*:maketrans",
|
||||
&frm, &to))
|
||||
goto exit;
|
||||
return_value = bytes_maketrans_impl(frm, to);
|
||||
return_value = bytes_maketrans_impl(&frm, &to);
|
||||
|
||||
exit:
|
||||
/* Cleanup for frm */
|
||||
if (frm.obj)
|
||||
PyBuffer_Release(&frm);
|
||||
/* Cleanup for to */
|
||||
if (to.obj)
|
||||
PyBuffer_Release(&to);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
bytes_maketrans_impl(PyObject *frm, PyObject *to)
|
||||
/*[clinic end generated code: output=89a3c3556975e466 input=d204f680f85da382]*/
|
||||
bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to)
|
||||
/*[clinic end generated code: output=7df47390c476ac60 input=de7a8fc5632bb8f1]*/
|
||||
{
|
||||
return _Py_bytes_maketrans(frm, to);
|
||||
}
|
||||
|
|
@ -3093,8 +3120,8 @@ replace(PyBytesObject *self,
|
|||
/*[clinic input]
|
||||
bytes.replace
|
||||
|
||||
old: object
|
||||
new: object
|
||||
old: Py_buffer
|
||||
new: Py_buffer
|
||||
count: Py_ssize_t = -1
|
||||
Maximum number of occurrences to replace.
|
||||
-1 (the default value) means replace all occurrences.
|
||||
|
|
@ -3123,50 +3150,40 @@ PyDoc_STRVAR(bytes_replace__doc__,
|
|||
{"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__},
|
||||
|
||||
static PyObject *
|
||||
bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count);
|
||||
bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count);
|
||||
|
||||
static PyObject *
|
||||
bytes_replace(PyBytesObject*self, PyObject *args)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyObject *old;
|
||||
PyObject *new;
|
||||
Py_buffer old = {NULL, NULL};
|
||||
Py_buffer new = {NULL, NULL};
|
||||
Py_ssize_t count = -1;
|
||||
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"OO|n:replace",
|
||||
"y*y*|n:replace",
|
||||
&old, &new, &count))
|
||||
goto exit;
|
||||
return_value = bytes_replace_impl(self, old, new, count);
|
||||
return_value = bytes_replace_impl(self, &old, &new, count);
|
||||
|
||||
exit:
|
||||
/* Cleanup for old */
|
||||
if (old.obj)
|
||||
PyBuffer_Release(&old);
|
||||
/* Cleanup for new */
|
||||
if (new.obj)
|
||||
PyBuffer_Release(&new);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count)
|
||||
/*[clinic end generated code: output=14ce72f4f9cb91cf input=d3ac254ea50f4ac1]*/
|
||||
bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count)
|
||||
/*[clinic end generated code: output=f07bd9ecf29ee8d8 input=b2fbbf0bf04de8e5]*/
|
||||
{
|
||||
const char *old_s, *new_s;
|
||||
Py_ssize_t old_len, new_len;
|
||||
|
||||
if (PyBytes_Check(old)) {
|
||||
old_s = PyBytes_AS_STRING(old);
|
||||
old_len = PyBytes_GET_SIZE(old);
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(old, &old_s, &old_len))
|
||||
return NULL;
|
||||
|
||||
if (PyBytes_Check(new)) {
|
||||
new_s = PyBytes_AS_STRING(new);
|
||||
new_len = PyBytes_GET_SIZE(new);
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(new, &new_s, &new_len))
|
||||
return NULL;
|
||||
|
||||
return (PyObject *)replace((PyBytesObject *) self,
|
||||
old_s, old_len,
|
||||
new_s, new_len, count);
|
||||
(const char *)old->buf, old->len,
|
||||
(const char *)new->buf, new->len, count);
|
||||
}
|
||||
|
||||
/** End DALKE **/
|
||||
|
|
@ -3181,6 +3198,7 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
|
|||
{
|
||||
Py_ssize_t len = PyBytes_GET_SIZE(self);
|
||||
Py_ssize_t slen;
|
||||
Py_buffer sub_view = {NULL, NULL};
|
||||
const char* sub;
|
||||
const char* str;
|
||||
|
||||
|
|
@ -3188,8 +3206,12 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
|
|||
sub = PyBytes_AS_STRING(substr);
|
||||
slen = PyBytes_GET_SIZE(substr);
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(substr, &sub, &slen))
|
||||
return -1;
|
||||
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);
|
||||
|
|
@ -3197,17 +3219,25 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
|
|||
if (direction < 0) {
|
||||
/* startswith */
|
||||
if (start+slen > len)
|
||||
return 0;
|
||||
goto notfound;
|
||||
} else {
|
||||
/* endswith */
|
||||
if (end-start < slen || start > len)
|
||||
return 0;
|
||||
goto notfound;
|
||||
|
||||
if (end-slen > start)
|
||||
start = end - slen;
|
||||
}
|
||||
if (end-start >= slen)
|
||||
return ! memcmp(str+start, sub, 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;
|
||||
}
|
||||
|
||||
|
|
@ -3978,7 +4008,7 @@ PyBytes_Concat(PyObject **pv, PyObject *w)
|
|||
Py_buffer wb;
|
||||
|
||||
wb.len = -1;
|
||||
if (_getbuffer(w, &wb) < 0) {
|
||||
if (PyObject_GetBuffer(w, &wb, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
|
||||
Py_TYPE(w)->tp_name, Py_TYPE(*pv)->tp_name);
|
||||
Py_CLEAR(*pv);
|
||||
|
|
|
|||
|
|
@ -767,6 +767,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
|
|||
int got_bracket=0;
|
||||
PyObject *s_buffer = NULL;
|
||||
Py_ssize_t len;
|
||||
Py_buffer view = {NULL, NULL};
|
||||
|
||||
if (PyUnicode_Check(v)) {
|
||||
s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v);
|
||||
|
|
@ -776,7 +777,11 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
|
|||
if (s == NULL)
|
||||
goto error;
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(v, &s, &len)) {
|
||||
else if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) == 0) {
|
||||
s = (const char *)view.buf;
|
||||
len = view.len;
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"complex() argument must be a string or a number, not '%.200s'",
|
||||
Py_TYPE(v)->tp_name);
|
||||
|
|
@ -890,6 +895,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
|
|||
if (s-start != len)
|
||||
goto parse_error;
|
||||
|
||||
PyBuffer_Release(&view);
|
||||
Py_XDECREF(s_buffer);
|
||||
return complex_subtype_from_doubles(type, x, y);
|
||||
|
||||
|
|
@ -897,6 +903,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
|
|||
PyErr_SetString(PyExc_ValueError,
|
||||
"complex() arg is a malformed string");
|
||||
error:
|
||||
PyBuffer_Release(&view);
|
||||
Py_XDECREF(s_buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1922,8 +1922,6 @@ static int
|
|||
UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyUnicodeErrorObject *ude;
|
||||
const char *data;
|
||||
Py_ssize_t size;
|
||||
|
||||
if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
|
||||
return -1;
|
||||
|
|
@ -1944,21 +1942,27 @@ UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!PyBytes_Check(ude->object)) {
|
||||
if (PyObject_AsReadBuffer(ude->object, (const void **)&data, &size)) {
|
||||
ude->encoding = ude->object = ude->reason = NULL;
|
||||
return -1;
|
||||
}
|
||||
ude->object = PyBytes_FromStringAndSize(data, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(ude->object);
|
||||
}
|
||||
|
||||
Py_INCREF(ude->encoding);
|
||||
Py_INCREF(ude->object);
|
||||
Py_INCREF(ude->reason);
|
||||
|
||||
if (!PyBytes_Check(ude->object)) {
|
||||
Py_buffer view;
|
||||
if (PyObject_GetBuffer(ude->object, &view, PyBUF_SIMPLE) != 0)
|
||||
goto error;
|
||||
Py_CLEAR(ude->object);
|
||||
ude->object = PyBytes_FromStringAndSize(view.buf, view.len);
|
||||
PyBuffer_Release(&view);
|
||||
if (!ude->object)
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
Py_CLEAR(ude->encoding);
|
||||
Py_CLEAR(ude->object);
|
||||
Py_CLEAR(ude->reason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ PyFloat_FromString(PyObject *v)
|
|||
double x;
|
||||
PyObject *s_buffer = NULL;
|
||||
Py_ssize_t len;
|
||||
Py_buffer view = {NULL, NULL};
|
||||
PyObject *result = NULL;
|
||||
|
||||
if (PyUnicode_Check(v)) {
|
||||
|
|
@ -143,7 +144,11 @@ PyFloat_FromString(PyObject *v)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (PyObject_AsCharBuffer(v, &s, &len)) {
|
||||
else if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) == 0) {
|
||||
s = (const char *)view.buf;
|
||||
len = view.len;
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"float() argument must be a string or a number, not '%.200s'",
|
||||
Py_TYPE(v)->tp_name);
|
||||
|
|
@ -170,6 +175,7 @@ PyFloat_FromString(PyObject *v)
|
|||
else
|
||||
result = PyFloat_FromDouble(x);
|
||||
|
||||
PyBuffer_Release(&view);
|
||||
Py_XDECREF(s_buffer);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,14 @@ STRINGLIB(bytes_join)(PyObject *sep, PyObject *iterable)
|
|||
for (i = 0, nbufs = 0; i < seqlen; i++) {
|
||||
Py_ssize_t itemlen;
|
||||
item = PySequence_Fast_GET_ITEM(seq, i);
|
||||
if (_getbuffer(item, &buffers[i]) < 0) {
|
||||
if (PyBytes_CheckExact(item)) {
|
||||
/* Fast path. */
|
||||
Py_INCREF(item);
|
||||
buffers[i].obj = item;
|
||||
buffers[i].buf = PyBytes_AS_STRING(item);
|
||||
buffers[i].len = PyBytes_GET_SIZE(item);
|
||||
}
|
||||
else if (PyObject_GetBuffer(item, &buffers[i], PyBUF_SIMPLE) != 0) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"sequence item %zd: expected a bytes-like object, "
|
||||
"%.80s found",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue