mirror of https://github.com/python/cpython
Issue #22896: Avoid to use PyObject_AsCharBuffer(), PyObject_AsReadBuffer()
and PyObject_AsWriteBuffer().
This commit is contained in:
parent
b0ef78535a
commit
4fdb68491e
|
@ -10,7 +10,7 @@ class X(Structure):
|
|||
self._init_called = True
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_fom_buffer(self):
|
||||
def test_from_buffer(self):
|
||||
a = array.array("i", range(16))
|
||||
x = (c_int * 16).from_buffer(a)
|
||||
|
||||
|
@ -23,25 +23,37 @@ class Test(unittest.TestCase):
|
|||
a[0], a[-1] = 200, -200
|
||||
self.assertEqual(x[:], a.tolist())
|
||||
|
||||
self.assertIn(a, x._objects.values())
|
||||
self.assertRaises(BufferError, a.append, 100)
|
||||
self.assertRaises(BufferError, a.pop)
|
||||
|
||||
self.assertRaises(ValueError,
|
||||
c_int.from_buffer, a, -1)
|
||||
del x; del y; gc.collect(); gc.collect(); gc.collect()
|
||||
a.append(100)
|
||||
a.pop()
|
||||
x = (c_int * 16).from_buffer(a)
|
||||
|
||||
self.assertIn(a, [obj.obj if isinstance(obj, memoryview) else obj
|
||||
for obj in x._objects.values()])
|
||||
|
||||
expected = x[:]
|
||||
del a; gc.collect(); gc.collect(); gc.collect()
|
||||
self.assertEqual(x[:], expected)
|
||||
|
||||
self.assertRaises(TypeError,
|
||||
(c_char * 16).from_buffer, "a" * 16)
|
||||
with self.assertRaises(TypeError):
|
||||
(c_char * 16).from_buffer(b"a" * 16)
|
||||
with self.assertRaises(TypeError):
|
||||
(c_char * 16).from_buffer("a" * 16)
|
||||
|
||||
def test_fom_buffer_with_offset(self):
|
||||
def test_from_buffer_with_offset(self):
|
||||
a = array.array("i", range(16))
|
||||
x = (c_int * 15).from_buffer(a, sizeof(c_int))
|
||||
|
||||
self.assertEqual(x[:], a.tolist()[1:])
|
||||
self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a, sizeof(c_int)))
|
||||
self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 * sizeof(c_int)))
|
||||
with self.assertRaises(ValueError):
|
||||
c_int.from_buffer(a, -1)
|
||||
with self.assertRaises(ValueError):
|
||||
(c_int * 16).from_buffer(a, sizeof(c_int))
|
||||
with self.assertRaises(ValueError):
|
||||
(c_int * 1).from_buffer(a, 16 * sizeof(c_int))
|
||||
|
||||
def test_from_buffer_copy(self):
|
||||
a = array.array("i", range(16))
|
||||
|
@ -56,26 +68,30 @@ class Test(unittest.TestCase):
|
|||
a[0], a[-1] = 200, -200
|
||||
self.assertEqual(x[:], list(range(16)))
|
||||
|
||||
self.assertEqual(x._objects, None)
|
||||
a.append(100)
|
||||
self.assertEqual(x[:], list(range(16)))
|
||||
|
||||
self.assertRaises(ValueError,
|
||||
c_int.from_buffer, a, -1)
|
||||
self.assertEqual(x._objects, None)
|
||||
|
||||
del a; gc.collect(); gc.collect(); gc.collect()
|
||||
self.assertEqual(x[:], list(range(16)))
|
||||
|
||||
x = (c_char * 16).from_buffer_copy(b"a" * 16)
|
||||
self.assertEqual(x[:], b"a" * 16)
|
||||
with self.assertRaises(TypeError):
|
||||
(c_char * 16).from_buffer_copy("a" * 16)
|
||||
|
||||
def test_fom_buffer_copy_with_offset(self):
|
||||
def test_from_buffer_copy_with_offset(self):
|
||||
a = array.array("i", range(16))
|
||||
x = (c_int * 15).from_buffer_copy(a, sizeof(c_int))
|
||||
|
||||
self.assertEqual(x[:], a.tolist()[1:])
|
||||
self.assertRaises(ValueError,
|
||||
(c_int * 16).from_buffer_copy, a, sizeof(c_int))
|
||||
self.assertRaises(ValueError,
|
||||
(c_int * 1).from_buffer_copy, a, 16 * sizeof(c_int))
|
||||
with self.assertRaises(ValueError):
|
||||
c_int.from_buffer_copy(a, -1)
|
||||
with self.assertRaises(ValueError):
|
||||
(c_int * 16).from_buffer_copy(a, sizeof(c_int))
|
||||
with self.assertRaises(ValueError):
|
||||
(c_int * 1).from_buffer_copy(a, 16 * sizeof(c_int))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -11,6 +11,9 @@ Release date: TBA
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Issue #22896: Avoid using PyObject_AsCharBuffer(), PyObject_AsReadBuffer()
|
||||
and PyObject_AsWriteBuffer().
|
||||
|
||||
- Issue #21295: Revert some changes (issue #16795) to AST line numbers and
|
||||
column offsets that constituted a regression.
|
||||
|
||||
|
|
|
@ -284,8 +284,6 @@ unicode_internal_decode(PyObject *self,
|
|||
{
|
||||
PyObject *obj;
|
||||
const char *errors = NULL;
|
||||
const char *data;
|
||||
Py_ssize_t size;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode",
|
||||
&obj, &errors))
|
||||
|
@ -298,11 +296,16 @@ unicode_internal_decode(PyObject *self,
|
|||
return codec_tuple(obj, PyUnicode_GET_LENGTH(obj));
|
||||
}
|
||||
else {
|
||||
if (PyObject_AsReadBuffer(obj, (const void **)&data, &size))
|
||||
Py_buffer view;
|
||||
PyObject *result;
|
||||
if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
|
||||
return codec_tuple(_PyUnicode_DecodeUnicodeInternal(data, size, errors),
|
||||
size);
|
||||
result = codec_tuple(
|
||||
_PyUnicode_DecodeUnicodeInternal(view.buf, view.len, errors),
|
||||
view.len);
|
||||
PyBuffer_Release(&view);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -727,8 +730,6 @@ unicode_internal_encode(PyObject *self,
|
|||
{
|
||||
PyObject *obj;
|
||||
const char *errors = NULL;
|
||||
const char *data;
|
||||
Py_ssize_t len, size;
|
||||
|
||||
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
||||
"unicode_internal codec has been deprecated",
|
||||
|
@ -741,6 +742,7 @@ unicode_internal_encode(PyObject *self,
|
|||
|
||||
if (PyUnicode_Check(obj)) {
|
||||
Py_UNICODE *u;
|
||||
Py_ssize_t len, size;
|
||||
|
||||
if (PyUnicode_READY(obj) < 0)
|
||||
return NULL;
|
||||
|
@ -755,9 +757,13 @@ unicode_internal_encode(PyObject *self,
|
|||
PyUnicode_GET_LENGTH(obj));
|
||||
}
|
||||
else {
|
||||
if (PyObject_AsReadBuffer(obj, (const void **)&data, &size))
|
||||
Py_buffer view;
|
||||
PyObject *result;
|
||||
if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
|
||||
return NULL;
|
||||
return codec_tuple(PyBytes_FromStringAndSize(data, size), size);
|
||||
result = codec_tuple(PyBytes_FromStringAndSize(view.buf, view.len), view.len);
|
||||
PyBuffer_Release(&view);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -463,39 +463,45 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep);
|
|||
static PyObject *
|
||||
CDataType_from_buffer(PyObject *type, PyObject *args)
|
||||
{
|
||||
void *buffer;
|
||||
Py_ssize_t buffer_len;
|
||||
Py_buffer buffer;
|
||||
Py_ssize_t offset = 0;
|
||||
PyObject *obj, *result;
|
||||
PyObject *result, *mv;
|
||||
StgDictObject *dict = PyType_stgdict(type);
|
||||
assert (dict);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset))
|
||||
return NULL;
|
||||
|
||||
if (-1 == PyObject_AsWriteBuffer(obj, &buffer, &buffer_len))
|
||||
if (!PyArg_ParseTuple(args, "w*|n:from_buffer", &buffer, &offset))
|
||||
return NULL;
|
||||
|
||||
if (offset < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"offset cannot be negative");
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
if (dict->size > buffer_len - offset) {
|
||||
if (dict->size > buffer.len - offset) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Buffer size too small (%zd instead of at least %zd bytes)",
|
||||
buffer_len, dict->size + offset);
|
||||
buffer.len, dict->size + offset);
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = PyCData_AtAddress(type, (char *)buffer + offset);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(obj);
|
||||
if (-1 == KeepRef((CDataObject *)result, -1, obj)) {
|
||||
result = PyCData_AtAddress(type, (char *)buffer.buf + offset);
|
||||
if (result == NULL) {
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mv = PyMemoryView_FromBuffer(&buffer);
|
||||
if (mv == NULL) {
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
/* Hack the memoryview so that it will release the buffer. */
|
||||
((PyMemoryViewObject *)mv)->mbuf->master.obj = buffer.obj;
|
||||
((PyMemoryViewObject *)mv)->view.obj = buffer.obj;
|
||||
if (-1 == KeepRef((CDataObject *)result, -1, mv))
|
||||
result = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -508,37 +514,36 @@ GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
|
|||
static PyObject *
|
||||
CDataType_from_buffer_copy(PyObject *type, PyObject *args)
|
||||
{
|
||||
const void *buffer;
|
||||
Py_ssize_t buffer_len;
|
||||
Py_buffer buffer;
|
||||
Py_ssize_t offset = 0;
|
||||
PyObject *obj, *result;
|
||||
PyObject *result;
|
||||
StgDictObject *dict = PyType_stgdict(type);
|
||||
assert (dict);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset))
|
||||
return NULL;
|
||||
|
||||
if (-1 == PyObject_AsReadBuffer(obj, (const void**)&buffer, &buffer_len))
|
||||
if (!PyArg_ParseTuple(args, "y*|n:from_buffer", &buffer, &offset))
|
||||
return NULL;
|
||||
|
||||
if (offset < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"offset cannot be negative");
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dict->size > buffer_len - offset) {
|
||||
if (dict->size > buffer.len - offset) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Buffer size too small (%zd instead of at least %zd bytes)",
|
||||
buffer_len, dict->size + offset);
|
||||
buffer.len, dict->size + offset);
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
memcpy(((CDataObject *)result)->b_ptr,
|
||||
(char *)buffer+offset, dict->size);
|
||||
if (result != NULL) {
|
||||
memcpy(((CDataObject *)result)->b_ptr,
|
||||
(char *)buffer.buf + offset, dict->size);
|
||||
}
|
||||
PyBuffer_Release(&buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -437,17 +437,18 @@ PyDoc_STRVAR(readinto_doc,
|
|||
"is set not to block as has no data to read.");
|
||||
|
||||
static PyObject *
|
||||
bytesio_readinto(bytesio *self, PyObject *buffer)
|
||||
bytesio_readinto(bytesio *self, PyObject *arg)
|
||||
{
|
||||
void *raw_buffer;
|
||||
Py_buffer buffer;
|
||||
Py_ssize_t len, n;
|
||||
|
||||
CHECK_CLOSED(self);
|
||||
|
||||
if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1)
|
||||
if (!PyArg_Parse(arg, "w*", &buffer))
|
||||
return NULL;
|
||||
|
||||
/* adjust invalid sizes */
|
||||
len = buffer.len;
|
||||
n = self->string_size - self->pos;
|
||||
if (len > n) {
|
||||
len = n;
|
||||
|
@ -455,10 +456,11 @@ bytesio_readinto(bytesio *self, PyObject *buffer)
|
|||
len = 0;
|
||||
}
|
||||
|
||||
memcpy(raw_buffer, self->buf + self->pos, len);
|
||||
memcpy(buffer.buf, self->buf + self->pos, len);
|
||||
assert(self->pos + len < PY_SSIZE_T_MAX);
|
||||
assert(len >= 0);
|
||||
self->pos += len;
|
||||
PyBuffer_Release(&buffer);
|
||||
|
||||
return PyLong_FromSsize_t(len);
|
||||
}
|
||||
|
|
|
@ -522,19 +522,20 @@ _pysqlite_set_result(sqlite3_context* context, PyObject* py_val)
|
|||
return -1;
|
||||
sqlite3_result_text(context, str, -1, SQLITE_TRANSIENT);
|
||||
} else if (PyObject_CheckBuffer(py_val)) {
|
||||
const char* buffer;
|
||||
Py_ssize_t buflen;
|
||||
if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) {
|
||||
Py_buffer view;
|
||||
if (PyObject_GetBuffer(py_val, &view, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"could not convert BLOB to buffer");
|
||||
return -1;
|
||||
}
|
||||
if (buflen > INT_MAX) {
|
||||
if (view.len > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"BLOB longer than INT_MAX bytes");
|
||||
PyBuffer_Release(&view);
|
||||
return -1;
|
||||
}
|
||||
sqlite3_result_blob(context, buffer, (int)buflen, SQLITE_TRANSIENT);
|
||||
sqlite3_result_blob(context, view.buf, (int)view.len, SQLITE_TRANSIENT);
|
||||
PyBuffer_Release(&view);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,6 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con
|
|||
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
const char* buffer;
|
||||
char* string;
|
||||
Py_ssize_t buflen;
|
||||
parameter_type paramtype;
|
||||
|
@ -145,18 +144,22 @@ int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObjec
|
|||
}
|
||||
rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
|
||||
break;
|
||||
case TYPE_BUFFER:
|
||||
if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) != 0) {
|
||||
case TYPE_BUFFER: {
|
||||
Py_buffer view;
|
||||
if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
|
||||
return -1;
|
||||
}
|
||||
if (buflen > INT_MAX) {
|
||||
if (view.len > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"BLOB longer than INT_MAX bytes");
|
||||
PyBuffer_Release(&view);
|
||||
return -1;
|
||||
}
|
||||
rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT);
|
||||
rc = sqlite3_bind_blob(self->st, pos, view.buf, (int)view.len, SQLITE_TRANSIENT);
|
||||
PyBuffer_Release(&view);
|
||||
break;
|
||||
}
|
||||
case TYPE_UNKNOWN:
|
||||
rc = -1;
|
||||
}
|
||||
|
|
|
@ -1842,8 +1842,8 @@ static PyObject *
|
|||
s_pack_into(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyStructObject *soself;
|
||||
char *buffer;
|
||||
Py_ssize_t buffer_len, offset;
|
||||
Py_buffer buffer;
|
||||
Py_ssize_t offset;
|
||||
|
||||
/* Validate arguments. +1 is for the first arg as buffer. */
|
||||
soself = (PyStructObject *)self;
|
||||
|
@ -1868,34 +1868,37 @@ s_pack_into(PyObject *self, PyObject *args)
|
|||
}
|
||||
|
||||
/* Extract a writable memory buffer from the first argument */
|
||||
if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0),
|
||||
(void**)&buffer, &buffer_len) == -1 ) {
|
||||
if (!PyArg_Parse(PyTuple_GET_ITEM(args, 0), "w*", &buffer))
|
||||
return NULL;
|
||||
}
|
||||
assert( buffer_len >= 0 );
|
||||
assert(buffer.len >= 0);
|
||||
|
||||
/* Extract the offset from the first argument */
|
||||
offset = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 1), PyExc_IndexError);
|
||||
if (offset == -1 && PyErr_Occurred())
|
||||
if (offset == -1 && PyErr_Occurred()) {
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Support negative offsets. */
|
||||
if (offset < 0)
|
||||
offset += buffer_len;
|
||||
offset += buffer.len;
|
||||
|
||||
/* Check boundaries */
|
||||
if (offset < 0 || (buffer_len - offset) < soself->s_size) {
|
||||
if (offset < 0 || (buffer.len - offset) < soself->s_size) {
|
||||
PyErr_Format(StructError,
|
||||
"pack_into requires a buffer of at least %zd bytes",
|
||||
soself->s_size);
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Call the guts */
|
||||
if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) {
|
||||
if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset) != 0) {
|
||||
PyBuffer_Release(&buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyBuffer_Release(&buffer);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -559,10 +559,10 @@ PyDoc_STRVAR(chr_doc,
|
|||
Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.");
|
||||
|
||||
|
||||
static char *
|
||||
source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf)
|
||||
static const char *
|
||||
source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, Py_buffer *view)
|
||||
{
|
||||
char *str;
|
||||
const char *str;
|
||||
Py_ssize_t size;
|
||||
|
||||
if (PyUnicode_Check(cmd)) {
|
||||
|
@ -571,19 +571,21 @@ source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf)
|
|||
if (str == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else if (!PyObject_CheckReadBuffer(cmd)) {
|
||||
else if (PyObject_GetBuffer(cmd, view, PyBUF_SIMPLE) == 0) {
|
||||
str = (const char *)view->buf;
|
||||
size = view->len;
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s() arg 1 must be a %s object",
|
||||
funcname, what);
|
||||
return NULL;
|
||||
}
|
||||
else if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strlen(str) != size) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"source code string cannot contain null bytes");
|
||||
PyBuffer_Release(view);
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
|
@ -592,7 +594,8 @@ source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf)
|
|||
static PyObject *
|
||||
builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
char *str;
|
||||
Py_buffer view = {NULL, NULL};
|
||||
const char *str;
|
||||
PyObject *filename;
|
||||
char *startstr;
|
||||
int mode = -1;
|
||||
|
@ -678,11 +681,12 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
goto finally;
|
||||
}
|
||||
|
||||
str = source_as_string(cmd, "compile", "string, bytes or AST", &cf);
|
||||
str = source_as_string(cmd, "compile", "string, bytes or AST", &cf, &view);
|
||||
if (str == NULL)
|
||||
goto error;
|
||||
|
||||
result = Py_CompileStringObject(str, filename, start[mode], &cf, optimize);
|
||||
PyBuffer_Release(&view);
|
||||
goto finally;
|
||||
|
||||
error:
|
||||
|
@ -752,7 +756,8 @@ builtin_eval(PyObject *self, PyObject *args)
|
|||
{
|
||||
PyObject *cmd, *result, *tmp = NULL;
|
||||
PyObject *globals = Py_None, *locals = Py_None;
|
||||
char *str;
|
||||
Py_buffer view = {NULL, NULL};
|
||||
const char *str;
|
||||
PyCompilerFlags cf;
|
||||
|
||||
if (!PyArg_UnpackTuple(args, "eval", 1, 3, &cmd, &globals, &locals))
|
||||
|
@ -801,7 +806,7 @@ builtin_eval(PyObject *self, PyObject *args)
|
|||
}
|
||||
|
||||
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
|
||||
str = source_as_string(cmd, "eval", "string, bytes or code", &cf);
|
||||
str = source_as_string(cmd, "eval", "string, bytes or code", &cf, &view);
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -810,6 +815,7 @@ builtin_eval(PyObject *self, PyObject *args)
|
|||
|
||||
(void)PyEval_MergeCompilerFlags(&cf);
|
||||
result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);
|
||||
PyBuffer_Release(&view);
|
||||
Py_XDECREF(tmp);
|
||||
return result;
|
||||
}
|
||||
|
@ -876,11 +882,12 @@ builtin_exec(PyObject *self, PyObject *args)
|
|||
v = PyEval_EvalCode(prog, globals, locals);
|
||||
}
|
||||
else {
|
||||
char *str;
|
||||
Py_buffer view = {NULL, NULL};
|
||||
const char *str;
|
||||
PyCompilerFlags cf;
|
||||
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
|
||||
str = source_as_string(prog, "exec",
|
||||
"string, bytes or code", &cf);
|
||||
"string, bytes or code", &cf, &view);
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
if (PyEval_MergeCompilerFlags(&cf))
|
||||
|
@ -888,6 +895,7 @@ builtin_exec(PyObject *self, PyObject *args)
|
|||
locals, &cf);
|
||||
else
|
||||
v = PyRun_String(str, Py_file_input, globals, locals);
|
||||
PyBuffer_Release(&view);
|
||||
}
|
||||
if (v == NULL)
|
||||
return NULL;
|
||||
|
|
Loading…
Reference in New Issue