changeset: 94475:2e684ce772de parent: 94473:651aa21433ba parent: 94474:1da9630e9b7f user: Serhiy Storchaka date: Tue Feb 03 01:25:42 2015 +0200 files: Include/bytes_methods.h Misc/NEWS Modules/_codecsmodule.c Modules/_io/bytesio.c Modules/_struct.c Objects/abstract.c Objects/bytearrayobject.c Objects/bytes_methods.c Objects/bytesobject.c Objects/complexobject.c Objects/exceptions.c Objects/floatobject.c Python/bltinmodule.c description: Issue #22896: Avoid to use PyObject_AsCharBuffer(), PyObject_AsReadBuffer() and PyObject_AsWriteBuffer(). diff -r 651aa21433ba -r 2e684ce772de Include/bytes_methods.h --- a/Include/bytes_methods.h Mon Feb 02 17:47:31 2015 -0500 +++ b/Include/bytes_methods.h Tue Feb 03 01:25:42 2015 +0200 @@ -22,7 +22,7 @@ extern void _Py_bytes_swapcase(char *result, char *s, Py_ssize_t len); /* The maketrans() static method. */ -extern PyObject* _Py_bytes_maketrans(PyObject *frm, PyObject *to); +extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to); /* Shared __doc__ strings. */ extern const char _Py_isspace__doc__[]; diff -r 651aa21433ba -r 2e684ce772de Lib/ctypes/test/test_frombuffer.py --- a/Lib/ctypes/test/test_frombuffer.py Mon Feb 02 17:47:31 2015 -0500 +++ b/Lib/ctypes/test/test_frombuffer.py Tue Feb 03 01:25:42 2015 +0200 @@ -10,7 +10,7 @@ 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 @@ 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 @@ 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() diff -r 651aa21433ba -r 2e684ce772de Misc/NEWS --- a/Misc/NEWS Mon Feb 02 17:47:31 2015 -0500 +++ b/Misc/NEWS Tue Feb 03 01:25:42 2015 +0200 @@ -10,6 +10,9 @@ 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. diff -r 651aa21433ba -r 2e684ce772de Modules/_codecsmodule.c --- a/Modules/_codecsmodule.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Modules/_codecsmodule.c Tue Feb 03 01:25:42 2015 +0200 @@ -288,8 +288,6 @@ { PyObject *obj; const char *errors = NULL; - const char *data; - Py_ssize_t size; if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode", &obj, &errors)) @@ -302,11 +300,16 @@ 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; } } @@ -731,8 +734,6 @@ { 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", @@ -745,6 +746,7 @@ if (PyUnicode_Check(obj)) { Py_UNICODE *u; + Py_ssize_t len, size; if (PyUnicode_READY(obj) < 0) return NULL; @@ -759,9 +761,13 @@ 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; } } diff -r 651aa21433ba -r 2e684ce772de Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Modules/_ctypes/_ctypes.c Tue Feb 03 01:25:42 2015 +0200 @@ -463,39 +463,45 @@ 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.buf + offset); + if (result == NULL) { + PyBuffer_Release(&buffer); return NULL; } - result = PyCData_AtAddress(type, (char *)buffer + offset); - if (result == NULL) + mv = PyMemoryView_FromBuffer(&buffer); + if (mv == NULL) { + PyBuffer_Release(&buffer); return NULL; - - Py_INCREF(obj); - if (-1 == KeepRef((CDataObject *)result, -1, obj)) { - 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 @@ 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; } diff -r 651aa21433ba -r 2e684ce772de Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Modules/_io/bytesio.c Tue Feb 03 01:25:42 2015 +0200 @@ -553,17 +553,18 @@ "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, NULL); - 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; @@ -571,10 +572,11 @@ 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); } diff -r 651aa21433ba -r 2e684ce772de Modules/_sqlite/connection.c --- a/Modules/_sqlite/connection.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Modules/_sqlite/connection.c Tue Feb 03 01:25:42 2015 +0200 @@ -522,19 +522,20 @@ 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; } diff -r 651aa21433ba -r 2e684ce772de Modules/_sqlite/statement.c --- a/Modules/_sqlite/statement.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Modules/_sqlite/statement.c Tue Feb 03 01:25:42 2015 +0200 @@ -94,7 +94,6 @@ 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 @@ } 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; } diff -r 651aa21433ba -r 2e684ce772de Modules/_struct.c --- a/Modules/_struct.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Modules/_struct.c Tue Feb 03 01:25:42 2015 +0200 @@ -1842,8 +1842,8 @@ 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 @@ } /* 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; } diff -r 651aa21433ba -r 2e684ce772de Objects/abstract.c --- a/Objects/abstract.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Objects/abstract.c Tue Feb 03 01:25:42 2015 +0200 @@ -250,27 +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 a bytes-like object"); - return -1; - } - if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1; - - *buffer = view.buf; - *buffer_len = view.len; - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(obj, &view); - Py_XDECREF(view.obj); - return 0; + return PyObject_AsReadBuffer(obj, (const void **)buffer, buffer_len); } int @@ -294,28 +274,18 @@ const void **buffer, Py_ssize_t *buffer_len) { - PyBufferProcs *pb; Py_buffer view; if (obj == NULL || buffer == NULL || buffer_len == NULL) { null_error(); return -1; } - pb = obj->ob_type->tp_as_buffer; - if (pb == NULL || - pb->bf_getbuffer == NULL) { - PyErr_SetString(PyExc_TypeError, - "expected a bytes-like object"); + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0) return -1; - } - - if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1; *buffer = view.buf; *buffer_len = view.len; - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(obj, &view); - Py_XDECREF(view.obj); + PyBuffer_Release(&view); return 0; } @@ -341,9 +311,7 @@ *buffer = view.buf; *buffer_len = view.len; - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(obj, &view); - Py_XDECREF(view.obj); + PyBuffer_Release(&view); return 0; } @@ -352,13 +320,15 @@ int PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { - if (!PyObject_CheckBuffer(obj)) { + PyBufferProcs *pb = obj->ob_type->tp_as_buffer; + + if (pb == NULL || pb->bf_getbuffer == NULL) { PyErr_Format(PyExc_TypeError, "a bytes-like object is required, not '%.100s'", Py_TYPE(obj)->tp_name); return -1; } - return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags); + return (*pb->bf_getbuffer)(obj, view, flags); } static int @@ -676,10 +646,14 @@ PyBuffer_Release(Py_buffer *view) { PyObject *obj = view->obj; - if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer) - Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view); - Py_XDECREF(obj); + PyBufferProcs *pb; + if (obj == NULL) + return; + pb = Py_TYPE(obj)->tp_as_buffer; + if (pb && pb->bf_releasebuffer) + pb->bf_releasebuffer(obj, view); view->obj = NULL; + Py_DECREF(obj); } PyObject * @@ -1288,8 +1262,7 @@ { PyNumberMethods *m; PyObject *trunc_func; - const char *buffer; - Py_ssize_t buffer_len; + Py_buffer view; _Py_IDENTIFIER(__trunc__); if (o == NULL) @@ -1327,21 +1300,22 @@ 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); - - return type_error("int() argument must be a string or a " - "number, not '%.200s'", o); + PyObject *result = _PyLong_FromBytes(view.buf, view.len, 10); + PyBuffer_Release(&view); + return result; + } + + return type_error("int() argument must be a string, a bytes-like object " + "or a number, not '%.200s'", o); } PyObject * diff -r 651aa21433ba -r 2e684ce772de Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Objects/bytearrayobject.c Tue Feb 03 01:25:42 2015 +0200 @@ -80,24 +80,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, - "a bytes-like object is required, not '%.100s'", - Py_TYPE(obj)->tp_name); - return -1; - } - - if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0) - return -1; - return view->len; -} - static int _canresize(PyByteArrayObject *self) { @@ -268,8 +250,8 @@ va.len = -1; vb.len = -1; - if (_getbuffer(a, &va) < 0 || - _getbuffer(b, &vb) < 0) { + if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 || + PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) { PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); goto done; @@ -335,7 +317,7 @@ Py_ssize_t size; Py_buffer vo; - if (_getbuffer(other, &vo) < 0) { + if (PyObject_GetBuffer(other, &vo, PyBUF_SIMPLE) != 0) { PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name); return NULL; @@ -595,14 +577,14 @@ needed = 0; } else { - if (_getbuffer(values, &vbytes) < 0) { - PyErr_Format(PyExc_TypeError, - "can't set bytearray slice from %.100s", - Py_TYPE(values)->tp_name); - return -1; - } - needed = vbytes.len; - bytes = vbytes.buf; + if (PyObject_GetBuffer(values, &vbytes, PyBUF_SIMPLE) != 0) { + PyErr_Format(PyExc_TypeError, + "can't set bytearray slice from %.100s", + Py_TYPE(values)->tp_name); + return -1; + } + needed = vbytes.len; + bytes = vbytes.buf; } if (lo < 0) @@ -1047,18 +1029,18 @@ 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; } - - other_size = _getbuffer(other, &other_bytes); - if (other_size < 0) { + self_size = self_bytes.len; + + if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) { PyErr_Clear(); PyBuffer_Release(&self_bytes); Py_RETURN_NOTIMPLEMENTED; } + other_size = other_bytes.len; if (self_size != other_size && (op == Py_EQ || op == Py_NE)) { /* Shortcut: if the lengths differ, the objects differ */ @@ -1170,7 +1152,7 @@ return -2; if (subobj) { - if (_getbuffer(subobj, &subbuf) < 0) + if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) return -2; sub = subbuf.buf; @@ -1238,7 +1220,7 @@ return NULL; if (sub_obj) { - if (_getbuffer(sub_obj, &vsub) < 0) + if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; @@ -1397,7 +1379,7 @@ Py_buffer varg; Py_ssize_t pos; PyErr_Clear(); - if (_getbuffer(arg, &varg) < 0) + if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) return -1; pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self), varg.buf, varg.len, 0); @@ -1428,7 +1410,7 @@ str = PyByteArray_AS_STRING(self); - if (_getbuffer(substr, &vsubstr) < 0) + if (PyObject_GetBuffer(substr, &vsubstr, PyBUF_SIMPLE) != 0) return -1; ADJUST_INDICES(start, end, len); @@ -1621,7 +1603,7 @@ if (table == Py_None) { table_chars = NULL; table = NULL; - } else if (_getbuffer(table, &vtable) < 0) { + } else if (PyObject_GetBuffer(table, &vtable, PyBUF_SIMPLE) != 0) { return NULL; } else { if (vtable.len != 256) { @@ -1634,7 +1616,7 @@ } if (deletechars != NULL) { - if (_getbuffer(deletechars, &vdel) < 0) { + if (PyObject_GetBuffer(deletechars, &vdel, PyBUF_SIMPLE) != 0) { if (table != NULL) PyBuffer_Release(&vtable); return NULL; @@ -1699,8 +1681,8 @@ @staticmethod bytearray.maketrans - frm: object - to: object + frm: Py_buffer + to: Py_buffer / Return a translation table useable for the bytes or bytearray translate method. @@ -1726,28 +1708,35 @@ {"maketrans", (PyCFunction)bytearray_maketrans, METH_VARARGS|METH_STATIC, bytearray_maketrans__doc__}, static PyObject * -bytearray_maketrans_impl(PyObject *frm, PyObject *to); +bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to); static PyObject * bytearray_maketrans(void *null, PyObject *args) { PyObject *return_value = NULL; - PyObject *frm; - PyObject *to; - - if (!PyArg_UnpackTuple(args, "maketrans", - 2, 2, + Py_buffer frm = {NULL, NULL}; + Py_buffer to = {NULL, NULL}; + + if (!PyArg_ParseTuple(args, + "y*y*:maketrans", &frm, &to)) goto exit; - return_value = bytearray_maketrans_impl(frm, to); + return_value = bytearray_maketrans_impl(&frm, &to); exit: + /* Cleanup for frm */ + if (frm.obj) + PyBuffer_Release(&frm); + /* Cleanup for to */ + if (to.obj) + PyBuffer_Release(&to); + return return_value; } static PyObject * -bytearray_maketrans_impl(PyObject *frm, PyObject *to) -/*[clinic end generated code: output=307752019d9b25b5 input=ea9bdc6b328c15e2]*/ +bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to) +/*[clinic end generated code: output=d332622814c26f4b input=5925a81d2fbbf151]*/ { return _Py_bytes_maketrans(frm, to); } @@ -2243,8 +2232,8 @@ /*[clinic input] bytearray.replace - old: object - new: object + old: Py_buffer + new: Py_buffer count: Py_ssize_t = -1 Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences. @@ -2273,47 +2262,40 @@ {"replace", (PyCFunction)bytearray_replace, METH_VARARGS, bytearray_replace__doc__}, static PyObject * -bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count); +bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * bytearray_replace(PyByteArrayObject *self, PyObject *args) { PyObject *return_value = NULL; - PyObject *old; - PyObject *new; + Py_buffer old = {NULL, NULL}; + Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; if (!PyArg_ParseTuple(args, - "OO|n:replace", + "y*y*|n:replace", &old, &new, &count)) goto exit; - return_value = bytearray_replace_impl(self, old, new, count); + return_value = bytearray_replace_impl(self, &old, &new, count); exit: + /* Cleanup for old */ + if (old.obj) + PyBuffer_Release(&old); + /* Cleanup for new */ + if (new.obj) + PyBuffer_Release(&new); + return return_value; } static PyObject * -bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count) -/*[clinic end generated code: output=4d2e3c9130da0f96 input=9aaaa123608dfc1f]*/ +bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) +/*[clinic end generated code: output=9997fbbd5bac4883 input=aa379d988637c7fb]*/ { - PyObject *res; - Py_buffer vold, vnew; - - if (_getbuffer(old, &vold) < 0) - return NULL; - if (_getbuffer(new, &vnew) < 0) { - PyBuffer_Release(&vold); - return NULL; - } - - res = (PyObject *)replace((PyByteArrayObject *) self, - vold.buf, vold.len, - vnew.buf, vnew.len, count); - - PyBuffer_Release(&vold); - PyBuffer_Release(&vnew); - return res; + return (PyObject *)replace((PyByteArrayObject *) self, + old->buf, old->len, + new->buf, new->len, count); } /*[clinic input] @@ -2383,7 +2365,7 @@ if (sep == Py_None) return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) + if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; n = vsub.len; @@ -2566,7 +2548,7 @@ if (sep == Py_None) return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) + if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; n = vsub.len; @@ -3088,7 +3070,7 @@ byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) + if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) return NULL; bytesptr = (char *) vbytes.buf; byteslen = vbytes.len; @@ -3159,7 +3141,7 @@ byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) + if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) return NULL; bytesptr = (char *) vbytes.buf; byteslen = vbytes.len; @@ -3227,7 +3209,7 @@ byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) + if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) return NULL; bytesptr = (char *) vbytes.buf; byteslen = vbytes.len; diff -r 651aa21433ba -r 2e684ce772de Objects/bytes_methods.c --- a/Objects/bytes_methods.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Objects/bytes_methods.c Tue Feb 03 01:25:42 2015 +0200 @@ -363,59 +363,27 @@ in frm is mapped to the byte at the same position in to.\n\ The bytes objects frm and to must be of the same length."); -static Py_ssize_t -_getbuffer(PyObject *obj, Py_buffer *view) -{ - PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer; - - if (buffer == NULL || buffer->bf_getbuffer == NULL) - { - PyErr_Format(PyExc_TypeError, - "a bytes-like object is required, not '%.100s'", - Py_TYPE(obj)->tp_name); - return -1; - } - - if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0) - return -1; - return view->len; -} - PyObject * -_Py_bytes_maketrans(PyObject *frm, PyObject *to) +_Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to) { PyObject *res = NULL; - Py_buffer bfrm, bto; Py_ssize_t i; char *p; - bfrm.len = -1; - bto.len = -1; - - if (_getbuffer(frm, &bfrm) < 0) - return NULL; - if (_getbuffer(to, &bto) < 0) - goto done; - if (bfrm.len != bto.len) { + if (frm->len != to->len) { PyErr_Format(PyExc_ValueError, "maketrans arguments must have same length"); - goto done; + return NULL; } res = PyBytes_FromStringAndSize(NULL, 256); - if (!res) { - goto done; - } + if (!res) + return NULL; p = PyBytes_AS_STRING(res); for (i = 0; i < 256; i++) p[i] = (char) i; - for (i = 0; i < bfrm.len; i++) { - p[((unsigned char *)bfrm.buf)[i]] = ((char *)bto.buf)[i]; + for (i = 0; i < frm->len; i++) { + p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i]; } -done: - if (bfrm.len != -1) - PyBuffer_Release(&bfrm); - if (bto.len != -1) - PyBuffer_Release(&bto); return res; } diff -r 651aa21433ba -r 2e684ce772de Objects/bytesobject.c --- a/Objects/bytesobject.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Objects/bytesobject.c Tue Feb 03 01:25:42 2015 +0200 @@ -12,33 +12,6 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=1a1d9102afc1b00c]*/ -static Py_ssize_t -_getbuffer(PyObject *obj, Py_buffer *view) -{ - PyBufferProcs *bufferprocs; - if (PyBytes_CheckExact(obj)) { - /* Fast path, e.g. for .join() of many bytes objects */ - Py_INCREF(obj); - view->obj = obj; - view->buf = PyBytes_AS_STRING(obj); - view->len = PyBytes_GET_SIZE(obj); - return view->len; - } - - bufferprocs = Py_TYPE(obj)->tp_as_buffer; - if (bufferprocs == NULL || bufferprocs->bf_getbuffer == NULL) - { - PyErr_Format(PyExc_TypeError, - "a bytes-like object is required, not '%.100s'", - Py_TYPE(obj)->tp_name); - return -1; - } - - if (bufferprocs->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0) - return -1; - return view->len; -} - #ifdef COUNT_ALLOCS Py_ssize_t null_strings, one_strings; #endif @@ -1349,8 +1322,8 @@ va.len = -1; vb.len = -1; - if (_getbuffer(a, &va) < 0 || - _getbuffer(b, &vb) < 0) { + if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 || + PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) { PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); goto done; @@ -1448,7 +1421,7 @@ Py_buffer varg; Py_ssize_t pos; PyErr_Clear(); - if (_getbuffer(arg, &varg) < 0) + if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) return -1; pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self), varg.buf, varg.len, 0); @@ -1737,7 +1710,7 @@ maxsplit = PY_SSIZE_T_MAX; if (sep == Py_None) return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) + if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; n = vsub.len; @@ -1751,7 +1724,7 @@ bytes.partition self: self(type="PyBytesObject *") - sep: object + sep: Py_buffer / Partition the bytes into three parts using the given separator. @@ -1778,26 +1751,39 @@ "object and two empty bytes objects."); #define BYTES_PARTITION_METHODDEF \ - {"partition", (PyCFunction)bytes_partition, METH_O, bytes_partition__doc__}, + {"partition", (PyCFunction)bytes_partition, METH_VARARGS, bytes_partition__doc__}, + +static PyObject * +bytes_partition_impl(PyBytesObject *self, Py_buffer *sep); static PyObject * -bytes_partition(PyBytesObject *self, PyObject *sep) -/*[clinic end generated code: output=b41e119c873c08bc input=6c5b9dcc5a9fd62e]*/ +bytes_partition(PyBytesObject *self, PyObject *args) { - const char *sep_chars; - Py_ssize_t sep_len; - - if (PyBytes_Check(sep)) { - sep_chars = PyBytes_AS_STRING(sep); - sep_len = PyBytes_GET_SIZE(sep); - } - else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len)) - return NULL; - + PyObject *return_value = NULL; + Py_buffer sep = {NULL, NULL}; + + if (!PyArg_ParseTuple(args, + "y*:partition", + &sep)) + goto exit; + return_value = bytes_partition_impl(self, &sep); + +exit: + /* Cleanup for sep */ + if (sep.obj) + PyBuffer_Release(&sep); + + return return_value; +} + +static PyObject * +bytes_partition_impl(PyBytesObject *self, Py_buffer *sep) +/*[clinic end generated code: output=3006727cfbf83aa4 input=bc855dc63ca949de]*/ +{ return stringlib_partition( (PyObject*) self, PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), - sep, sep_chars, sep_len + sep->obj, (const char *)sep->buf, sep->len ); } @@ -1805,7 +1791,7 @@ bytes.rpartition self: self(type="PyBytesObject *") - sep: object + sep: Py_buffer / Partition the bytes into three parts using the given separator. @@ -1832,26 +1818,39 @@ "objects and the original bytes object."); #define BYTES_RPARTITION_METHODDEF \ - {"rpartition", (PyCFunction)bytes_rpartition, METH_O, bytes_rpartition__doc__}, + {"rpartition", (PyCFunction)bytes_rpartition, METH_VARARGS, bytes_rpartition__doc__}, + +static PyObject * +bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep); static PyObject * -bytes_rpartition(PyBytesObject *self, PyObject *sep) -/*[clinic end generated code: output=3a620803657196ee input=79bc2932e78e5ce0]*/ +bytes_rpartition(PyBytesObject *self, PyObject *args) { - const char *sep_chars; - Py_ssize_t sep_len; - - if (PyBytes_Check(sep)) { - sep_chars = PyBytes_AS_STRING(sep); - sep_len = PyBytes_GET_SIZE(sep); - } - else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len)) - return NULL; - + PyObject *return_value = NULL; + Py_buffer sep = {NULL, NULL}; + + if (!PyArg_ParseTuple(args, + "y*:rpartition", + &sep)) + goto exit; + return_value = bytes_rpartition_impl(self, &sep); + +exit: + /* Cleanup for sep */ + if (sep.obj) + PyBuffer_Release(&sep); + + return return_value; +} + +static PyObject * +bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep) +/*[clinic end generated code: output=57b169dc47fa90e8 input=6588fff262a9170e]*/ +{ return stringlib_rpartition( (PyObject*) self, PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), - sep, sep_chars, sep_len + sep->obj, (const char *)sep->buf, sep->len ); } @@ -1916,7 +1915,7 @@ maxsplit = PY_SSIZE_T_MAX; if (sep == Py_None) return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) + if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; n = vsub.len; @@ -2003,7 +2002,7 @@ return -2; if (subobj) { - if (_getbuffer(subobj, &subbuf) < 0) + if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) return -2; sub = subbuf.buf; @@ -2118,7 +2117,7 @@ Py_ssize_t seplen; Py_ssize_t i, j; - if (_getbuffer(sepobj, &vsep) < 0) + if (PyObject_GetBuffer(sepobj, &vsep, PyBUF_SIMPLE) != 0) return NULL; sep = vsep.buf; seplen = vsep.len; @@ -2360,7 +2359,7 @@ return NULL; if (sub_obj) { - if (_getbuffer(sub_obj, &vsub) < 0) + if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) return NULL; sub = vsub.buf; @@ -2450,6 +2449,8 @@ /*[clinic end generated code: output=f0f29a57f41df5d8 input=d8fa5519d7cc4be7]*/ { char *input, *output; + Py_buffer table_view = {NULL, NULL}; + Py_buffer del_table_view = {NULL, NULL}; const char *table_chars; Py_ssize_t i, c, changed = 0; PyObject *input_obj = (PyObject*)self; @@ -2466,12 +2467,17 @@ table_chars = NULL; tablen = 256; } - else if (PyObject_AsCharBuffer(table, &table_chars, &tablen)) - return NULL; + else { + if (PyObject_GetBuffer(table, &table_view, PyBUF_SIMPLE) != 0) + return NULL; + table_chars = table_view.buf; + tablen = table_view.len; + } if (tablen != 256) { PyErr_SetString(PyExc_ValueError, "translation table must be 256 characters long"); + PyBuffer_Release(&table_view); return NULL; } @@ -2480,8 +2486,14 @@ del_table_chars = PyBytes_AS_STRING(deletechars); dellen = PyBytes_GET_SIZE(deletechars); } - else if (PyObject_AsCharBuffer(deletechars, &del_table_chars, &dellen)) - return NULL; + else { + if (PyObject_GetBuffer(deletechars, &del_table_view, PyBUF_SIMPLE) != 0) { + PyBuffer_Release(&table_view); + return NULL; + } + del_table_chars = del_table_view.buf; + dellen = del_table_view.len; + } } else { del_table_chars = NULL; @@ -2490,8 +2502,11 @@ inlen = PyBytes_GET_SIZE(input_obj); result = PyBytes_FromStringAndSize((char *)NULL, inlen); - if (result == NULL) + if (result == NULL) { + PyBuffer_Release(&del_table_view); + PyBuffer_Release(&table_view); return NULL; + } output_start = output = PyBytes_AsString(result); input = PyBytes_AS_STRING(input_obj); @@ -2502,11 +2517,14 @@ if (Py_CHARMASK((*output++ = table_chars[c])) != c) changed = 1; } - if (changed || !PyBytes_CheckExact(input_obj)) - return result; - Py_DECREF(result); - Py_INCREF(input_obj); - return input_obj; + if (!changed && PyBytes_CheckExact(input_obj)) { + Py_INCREF(input_obj); + Py_DECREF(result); + result = input_obj; + } + PyBuffer_Release(&del_table_view); + PyBuffer_Release(&table_view); + return result; } if (table_chars == NULL) { @@ -2516,9 +2534,11 @@ for (i = 0; i < 256; i++) trans_table[i] = Py_CHARMASK(table_chars[i]); } + PyBuffer_Release(&table_view); for (i = 0; i < dellen; i++) trans_table[(int) Py_CHARMASK(del_table_chars[i])] = -1; + PyBuffer_Release(&del_table_view); for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); @@ -2544,8 +2564,8 @@ @staticmethod bytes.maketrans - frm: object - to: object + frm: Py_buffer + to: Py_buffer / Return a translation table useable for the bytes or bytearray translate method. @@ -2571,28 +2591,35 @@ {"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC, bytes_maketrans__doc__}, static PyObject * -bytes_maketrans_impl(PyObject *frm, PyObject *to); +bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to); static PyObject * bytes_maketrans(void *null, PyObject *args) { PyObject *return_value = NULL; - PyObject *frm; - PyObject *to; - - if (!PyArg_UnpackTuple(args, "maketrans", - 2, 2, + Py_buffer frm = {NULL, NULL}; + Py_buffer to = {NULL, NULL}; + + if (!PyArg_ParseTuple(args, + "y*y*:maketrans", &frm, &to)) goto exit; - return_value = bytes_maketrans_impl(frm, to); + return_value = bytes_maketrans_impl(&frm, &to); exit: + /* Cleanup for frm */ + if (frm.obj) + PyBuffer_Release(&frm); + /* Cleanup for to */ + if (to.obj) + PyBuffer_Release(&to); + return return_value; } static PyObject * -bytes_maketrans_impl(PyObject *frm, PyObject *to) -/*[clinic end generated code: output=89a3c3556975e466 input=d204f680f85da382]*/ +bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to) +/*[clinic end generated code: output=7df47390c476ac60 input=de7a8fc5632bb8f1]*/ { return _Py_bytes_maketrans(frm, to); } @@ -3093,8 +3120,8 @@ /*[clinic input] bytes.replace - old: object - new: object + old: Py_buffer + new: Py_buffer count: Py_ssize_t = -1 Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences. @@ -3123,50 +3150,40 @@ {"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__}, static PyObject * -bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count); +bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * bytes_replace(PyBytesObject*self, PyObject *args) { PyObject *return_value = NULL; - PyObject *old; - PyObject *new; + Py_buffer old = {NULL, NULL}; + Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; if (!PyArg_ParseTuple(args, - "OO|n:replace", + "y*y*|n:replace", &old, &new, &count)) goto exit; - return_value = bytes_replace_impl(self, old, new, count); + return_value = bytes_replace_impl(self, &old, &new, count); exit: + /* Cleanup for old */ + if (old.obj) + PyBuffer_Release(&old); + /* Cleanup for new */ + if (new.obj) + PyBuffer_Release(&new); + return return_value; } static PyObject * -bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count) -/*[clinic end generated code: output=14ce72f4f9cb91cf input=d3ac254ea50f4ac1]*/ +bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) +/*[clinic end generated code: output=f07bd9ecf29ee8d8 input=b2fbbf0bf04de8e5]*/ { - const char *old_s, *new_s; - Py_ssize_t old_len, new_len; - - if (PyBytes_Check(old)) { - old_s = PyBytes_AS_STRING(old); - old_len = PyBytes_GET_SIZE(old); - } - else if (PyObject_AsCharBuffer(old, &old_s, &old_len)) - return NULL; - - if (PyBytes_Check(new)) { - new_s = PyBytes_AS_STRING(new); - new_len = PyBytes_GET_SIZE(new); - } - else if (PyObject_AsCharBuffer(new, &new_s, &new_len)) - return NULL; - return (PyObject *)replace((PyBytesObject *) self, - old_s, old_len, - new_s, new_len, count); + (const char *)old->buf, old->len, + (const char *)new->buf, new->len, count); } /** End DALKE **/ @@ -3181,6 +3198,7 @@ { Py_ssize_t len = PyBytes_GET_SIZE(self); Py_ssize_t slen; + Py_buffer sub_view = {NULL, NULL}; const char* sub; const char* str; @@ -3188,8 +3206,12 @@ sub = PyBytes_AS_STRING(substr); slen = PyBytes_GET_SIZE(substr); } - else if (PyObject_AsCharBuffer(substr, &sub, &slen)) - return -1; + else { + if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0) + return -1; + sub = sub_view.buf; + slen = sub_view.len; + } str = PyBytes_AS_STRING(self); ADJUST_INDICES(start, end, len); @@ -3197,17 +3219,25 @@ if (direction < 0) { /* startswith */ if (start+slen > len) - return 0; + goto notfound; } else { /* endswith */ if (end-start < slen || start > len) - return 0; + goto notfound; if (end-slen > start) start = end - slen; } - if (end-start >= slen) - return ! memcmp(str+start, sub, slen); + if (end-start < slen) + goto notfound; + if (memcmp(str+start, sub, slen) != 0) + goto notfound; + + PyBuffer_Release(&sub_view); + return 1; + +notfound: + PyBuffer_Release(&sub_view); return 0; } @@ -3978,7 +4008,7 @@ Py_buffer wb; wb.len = -1; - if (_getbuffer(w, &wb) < 0) { + if (PyObject_GetBuffer(w, &wb, PyBUF_SIMPLE) != 0) { PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", Py_TYPE(w)->tp_name, Py_TYPE(*pv)->tp_name); Py_CLEAR(*pv); diff -r 651aa21433ba -r 2e684ce772de Objects/complexobject.c --- a/Objects/complexobject.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Objects/complexobject.c Tue Feb 03 01:25:42 2015 +0200 @@ -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 -r 651aa21433ba -r 2e684ce772de Objects/exceptions.c --- a/Objects/exceptions.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Objects/exceptions.c Tue Feb 03 01:25:42 2015 +0200 @@ -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; } + Py_INCREF(ude->encoding); + Py_INCREF(ude->object); + Py_INCREF(ude->reason); + 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); + 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; } - else { - Py_INCREF(ude->object); - } - - Py_INCREF(ude->encoding); - Py_INCREF(ude->reason); - return 0; + +error: + Py_CLEAR(ude->encoding); + Py_CLEAR(ude->object); + Py_CLEAR(ude->reason); + return -1; } static PyObject * diff -r 651aa21433ba -r 2e684ce772de Objects/floatobject.c --- a/Objects/floatobject.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Objects/floatobject.c Tue Feb 03 01:25:42 2015 +0200 @@ -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 -r 651aa21433ba -r 2e684ce772de Objects/stringlib/join.h --- a/Objects/stringlib/join.h Mon Feb 02 17:47:31 2015 -0500 +++ b/Objects/stringlib/join.h Tue Feb 03 01:25:42 2015 +0200 @@ -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", diff -r 651aa21433ba -r 2e684ce772de Python/bltinmodule.c --- a/Python/bltinmodule.c Mon Feb 02 17:47:31 2015 -0500 +++ b/Python/bltinmodule.c Tue Feb 03 01:25:42 2015 +0200 @@ -723,10 +723,10 @@ } -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)) { @@ -735,19 +735,21 @@ 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_t)size) { + + if (strlen(str) != (size_t)size) { PyErr_SetString(PyExc_ValueError, "source code string cannot contain null bytes"); + PyBuffer_Release(view); return NULL; } return str; @@ -827,7 +829,8 @@ builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) /*[clinic end generated code: output=c72d197809d178fc input=c6212a9d21472f7e]*/ { - char *str; + Py_buffer view = {NULL, NULL}; + const char *str; int compile_mode = -1; int is_ast; PyCompilerFlags cf; @@ -898,11 +901,12 @@ goto finally; } - str = source_as_string(source, "compile", "string, bytes or AST", &cf); + str = source_as_string(source, "compile", "string, bytes or AST", &cf, &view); if (str == NULL) goto error; result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize); + PyBuffer_Release(&view); goto finally; error: @@ -1042,7 +1046,8 @@ /*[clinic end generated code: output=644fd59012538ce6 input=31e42c1d2125b50b]*/ { PyObject *result, *tmp = NULL; - char *str; + Py_buffer view = {NULL, NULL}; + const char *str; PyCompilerFlags cf; if (locals != Py_None && !PyMapping_Check(locals)) { @@ -1089,7 +1094,7 @@ } cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(source, "eval", "string, bytes or code", &cf); + str = source_as_string(source, "eval", "string, bytes or code", &cf, &view); if (str == NULL) return NULL; @@ -1098,6 +1103,7 @@ (void)PyEval_MergeCompilerFlags(&cf); result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); + PyBuffer_Release(&view); Py_XDECREF(tmp); return result; } @@ -1204,11 +1210,12 @@ v = PyEval_EvalCode(source, 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(source, "exec", - "string, bytes or code", &cf); + "string, bytes or code", &cf, &view); if (str == NULL) return NULL; if (PyEval_MergeCompilerFlags(&cf)) @@ -1216,6 +1223,7 @@ locals, &cf); else v = PyRun_String(str, Py_file_input, globals, locals); + PyBuffer_Release(&view); } if (v == NULL) return NULL;