Issue #22896: Avoid to use PyObject_AsCharBuffer(), PyObject_AsReadBuffer()
and PyObject_AsWriteBuffer().
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 9ed3f92..7e3121a 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -250,28 +250,7 @@
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 @@
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 @@
*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_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 @@
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 @@
{
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 @@
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 *
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index d72abb7..f5eb321 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -74,24 +74,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c
index 4e8107b..9ff7ace 100644
--- a/Objects/bytes_methods.c
+++ b/Objects/bytes_methods.c
@@ -363,41 +363,20 @@
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 @@
}
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;
}
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index a3ccbcf..e56dbed 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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;
}
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 0128120..7f4cdd9 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -767,6 +767,7 @@
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 @@
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 @@
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 @@
PyErr_SetString(PyExc_ValueError,
"complex() arg is a malformed string");
error:
+ PyBuffer_Release(&view);
Py_XDECREF(s_buffer);
return NULL;
}
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 873fbc6..c76eca8 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -1922,8 +1922,6 @@
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 @@
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 *
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 05b7679..33e30ca 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -131,6 +131,7 @@
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 @@
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 @@
else
result = PyFloat_FromDouble(x);
+ PyBuffer_Release(&view);
Py_XDECREF(s_buffer);
return result;
}
diff --git a/Objects/stringlib/join.h b/Objects/stringlib/join.h
index 35eb984..cbf81be 100644
--- a/Objects/stringlib/join.h
+++ b/Objects/stringlib/join.h
@@ -58,7 +58,14 @@
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",