Issue #22896: Avoid to use PyObject_AsCharBuffer(), PyObject_AsReadBuffer()

and PyObject_AsWriteBuffer().
This commit is contained in:
Serhiy Storchaka 2015-02-03 01:21:08 +02:00
parent b0ef78535a
commit 4fdb68491e
17 changed files with 327 additions and 335 deletions

View file

@ -250,28 +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 bytes, bytearray "
"or buffer compatible 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
@ -295,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 an object with a buffer interface");
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;
}
@ -342,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;
}
@ -353,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,
"'%.100s' does not support the buffer interface",
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
@ -652,10 +621,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 *
@ -1249,8 +1222,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)
@ -1288,21 +1260,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 *

View file

@ -74,24 +74,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,
"Type %.100s doesn't support the buffer API",
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)
{
@ -262,8 +244,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;
@ -304,7 +286,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;
@ -562,14 +544,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)
@ -1012,18 +994,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 */
@ -1135,7 +1117,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;
@ -1203,7 +1185,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;
@ -1318,7 +1300,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);
@ -1349,7 +1331,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);
@ -1493,7 +1475,7 @@ bytearray_translate(PyByteArrayObject *self, PyObject *args)
if (tableobj == Py_None) {
table = NULL;
tableobj = NULL;
} else if (_getbuffer(tableobj, &vtable) < 0) {
} else if (PyObject_GetBuffer(tableobj, &vtable, PyBUF_SIMPLE) != 0) {
return NULL;
} else {
if (vtable.len != 256) {
@ -1506,7 +1488,7 @@ bytearray_translate(PyByteArrayObject *self, PyObject *args)
}
if (delobj != NULL) {
if (_getbuffer(delobj, &vdel) < 0) {
if (PyObject_GetBuffer(delobj, &vdel, PyBUF_SIMPLE) != 0) {
if (tableobj != NULL)
PyBuffer_Release(&vtable);
return NULL;
@ -2070,26 +2052,20 @@ given, only the first count occurrences are replaced.");
static PyObject *
bytearray_replace(PyByteArrayObject *self, PyObject *args)
{
PyObject *res;
Py_buffer old = {NULL, NULL};
Py_buffer new = {NULL, NULL};
Py_ssize_t count = -1;
PyObject *from, *to, *res;
Py_buffer vfrom, vto;
if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
if (!PyArg_ParseTuple(args, "y*y*|n:replace", &old, &new, &count))
return NULL;
if (_getbuffer(from, &vfrom) < 0)
return NULL;
if (_getbuffer(to, &vto) < 0) {
PyBuffer_Release(&vfrom);
return NULL;
}
res = (PyObject *)replace((PyByteArrayObject *) self,
vfrom.buf, vfrom.len,
vto.buf, vto.len, count);
(const char *)old.buf, old.len,
(const char *)new.buf, new.len, count);
PyBuffer_Release(&vfrom);
PyBuffer_Release(&vto);
PyBuffer_Release(&old);
PyBuffer_Release(&new);
return res;
}
@ -2120,7 +2096,7 @@ bytearray_split(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
if (subobj == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
if (_getbuffer(subobj, &vsub) < 0)
if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
@ -2215,7 +2191,7 @@ bytearray_rsplit(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
if (subobj == Py_None)
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
if (_getbuffer(subobj, &vsub) < 0)
if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
@ -2503,7 +2479,7 @@ bytearray_strip(PyByteArrayObject *self, PyObject *args)
argsize = 6;
}
else {
if (_getbuffer(arg, &varg) < 0)
if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return NULL;
argptr = (char *) varg.buf;
argsize = varg.len;
@ -2540,7 +2516,7 @@ bytearray_lstrip(PyByteArrayObject *self, PyObject *args)
argsize = 6;
}
else {
if (_getbuffer(arg, &varg) < 0)
if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return NULL;
argptr = (char *) varg.buf;
argsize = varg.len;
@ -2574,7 +2550,7 @@ bytearray_rstrip(PyByteArrayObject *self, PyObject *args)
argsize = 6;
}
else {
if (_getbuffer(arg, &varg) < 0)
if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return NULL;
argptr = (char *) varg.buf;
argsize = varg.len;

View file

@ -363,41 +363,20 @@ 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,
"Type %.100s doesn't support the buffer API",
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 *args)
{
PyObject *frm, *to, *res = NULL;
Py_buffer bfrm, bto;
PyObject *res = NULL;
Py_buffer bfrm = {NULL, NULL};
Py_buffer bto = {NULL, NULL};
Py_ssize_t i;
char *p;
bfrm.len = -1;
bto.len = -1;
if (!PyArg_ParseTuple(args, "OO:maketrans", &frm, &to))
if (!PyArg_ParseTuple(args, "y*y*:maketrans", &bfrm, &bto))
return NULL;
if (_getbuffer(frm, &bfrm) < 0)
return NULL;
if (_getbuffer(to, &bto) < 0)
goto done;
if (bfrm.len != bto.len) {
PyErr_Format(PyExc_ValueError,
"maketrans arguments must have same length");
@ -415,9 +394,9 @@ _Py_bytes_maketrans(PyObject *args)
}
done:
if (bfrm.len != -1)
if (bfrm.obj != NULL)
PyBuffer_Release(&bfrm);
if (bto.len != -1)
if (bfrm.obj != NULL)
PyBuffer_Release(&bto);
return res;
}

View file

@ -7,33 +7,6 @@
#include "bytes_methods.h"
#include <stddef.h>
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,
"Type %.100s doesn't support the buffer API",
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
@ -695,8 +668,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;
@ -794,7 +767,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);
@ -1048,7 +1021,7 @@ bytes_split(PyBytesObject *self, PyObject *args, PyObject *kwds)
maxsplit = PY_SSIZE_T_MAX;
if (subobj == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
if (_getbuffer(subobj, &vsub) < 0)
if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
@ -1068,21 +1041,19 @@ found, returns B and two empty bytes objects.");
static PyObject *
bytes_partition(PyBytesObject *self, PyObject *sep_obj)
{
const char *sep;
Py_ssize_t sep_len;
Py_buffer sep = {NULL, NULL};
PyObject *res;
if (PyBytes_Check(sep_obj)) {
sep = PyBytes_AS_STRING(sep_obj);
sep_len = PyBytes_GET_SIZE(sep_obj);
}
else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
if (PyObject_GetBuffer(sep_obj, &sep, PyBUF_SIMPLE) != 0)
return NULL;
return stringlib_partition(
res = stringlib_partition(
(PyObject*) self,
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
sep_obj, sep, sep_len
sep_obj, sep.buf, sep.len
);
PyBuffer_Release(&sep);
return res;
}
PyDoc_STRVAR(rpartition__doc__,
@ -1096,21 +1067,19 @@ bytes objects and B.");
static PyObject *
bytes_rpartition(PyBytesObject *self, PyObject *sep_obj)
{
const char *sep;
Py_ssize_t sep_len;
Py_buffer sep = {NULL, NULL};
PyObject *res;
if (PyBytes_Check(sep_obj)) {
sep = PyBytes_AS_STRING(sep_obj);
sep_len = PyBytes_GET_SIZE(sep_obj);
}
else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
if (PyObject_GetBuffer(sep_obj, &sep, PyBUF_SIMPLE) != 0)
return NULL;
return stringlib_rpartition(
res = stringlib_rpartition(
(PyObject*) self,
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
sep_obj, sep, sep_len
sep_obj, sep.buf, sep.len
);
PyBuffer_Release(&sep);
return res;
}
PyDoc_STRVAR(rsplit__doc__,
@ -1140,7 +1109,7 @@ bytes_rsplit(PyBytesObject *self, PyObject *args, PyObject *kwds)
maxsplit = PY_SSIZE_T_MAX;
if (subobj == Py_None)
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
if (_getbuffer(subobj, &vsub) < 0)
if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
@ -1202,7 +1171,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;
@ -1317,7 +1286,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;
@ -1462,7 +1431,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;
@ -1498,6 +1467,8 @@ static PyObject *
bytes_translate(PyBytesObject *self, PyObject *args)
{
char *input, *output;
Py_buffer table_view = {NULL, NULL};
Py_buffer del_table_view = {NULL, NULL};
const char *table;
Py_ssize_t i, c, changed = 0;
PyObject *input_obj = (PyObject*)self;
@ -1519,12 +1490,17 @@ bytes_translate(PyBytesObject *self, PyObject *args)
table = NULL;
tablen = 256;
}
else if (PyObject_AsCharBuffer(tableobj, &table, &tablen))
return NULL;
else {
if (PyObject_GetBuffer(tableobj, &table_view, PyBUF_SIMPLE) != 0)
return NULL;
table = 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;
}
@ -1533,8 +1509,14 @@ bytes_translate(PyBytesObject *self, PyObject *args)
del_table = PyBytes_AS_STRING(delobj);
dellen = PyBytes_GET_SIZE(delobj);
}
else if (PyObject_AsCharBuffer(delobj, &del_table, &dellen))
return NULL;
else {
if (PyObject_GetBuffer(delobj, &del_table_view, PyBUF_SIMPLE) != 0) {
PyBuffer_Release(&table_view);
return NULL;
}
del_table = del_table_view.buf;
dellen = del_table_view.len;
}
}
else {
del_table = NULL;
@ -1543,8 +1525,11 @@ bytes_translate(PyBytesObject *self, PyObject *args)
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);
@ -1555,11 +1540,14 @@ bytes_translate(PyBytesObject *self, PyObject *args)
if (Py_CHARMASK((*output++ = table[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 == NULL) {
@ -1569,9 +1557,11 @@ bytes_translate(PyBytesObject *self, PyObject *args)
for (i = 0; i < 256; i++)
trans_table[i] = Py_CHARMASK(table[i]);
}
PyBuffer_Release(&table_view);
for (i = 0; i < dellen; i++)
trans_table[(int) Py_CHARMASK(del_table[i])] = -1;
PyBuffer_Release(&del_table_view);
for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++);
@ -2100,31 +2090,21 @@ given, only first count occurances are replaced.");
static PyObject *
bytes_replace(PyBytesObject *self, PyObject *args)
{
PyObject *res;
Py_buffer old = {NULL, NULL};
Py_buffer new = {NULL, NULL};
Py_ssize_t count = -1;
PyObject *from, *to;
const char *from_s, *to_s;
Py_ssize_t from_len, to_len;
if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
if (!PyArg_ParseTuple(args, "y*y*|n:replace", &old, &new, &count))
return NULL;
if (PyBytes_Check(from)) {
from_s = PyBytes_AS_STRING(from);
from_len = PyBytes_GET_SIZE(from);
}
else if (PyObject_AsCharBuffer(from, &from_s, &from_len))
return NULL;
res = (PyObject *)replace((PyBytesObject *) self,
(const char *)old.buf, old.len,
(const char *)new.buf, new.len, count);
if (PyBytes_Check(to)) {
to_s = PyBytes_AS_STRING(to);
to_len = PyBytes_GET_SIZE(to);
}
else if (PyObject_AsCharBuffer(to, &to_s, &to_len))
return NULL;
return (PyObject *)replace((PyBytesObject *) self,
from_s, from_len,
to_s, to_len, count);
PyBuffer_Release(&old);
PyBuffer_Release(&new);
return res;
}
/** End DALKE **/
@ -2139,6 +2119,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;
@ -2146,8 +2127,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);
@ -2155,17 +2140,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;
}

View file

@ -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;
}

View file

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

View file

@ -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;
}

View file

@ -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",