diff -r e8b3083bb148 Include/abstract.h --- a/Include/abstract.h Sat Nov 22 22:14:41 2014 -0800 +++ b/Include/abstract.h Mon Nov 24 21:16:44 2014 +0200 @@ -526,6 +526,12 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx success */ + PyAPI_FUNC(int) _PyBuffer_Converter(PyObject *obj, Py_buffer *view); + + /* Converter for simple read-only buffers for PyArg_Parse* functions. + Returns 0 and raises an error on failure and returns 1 on success. + */ + PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices); diff -r e8b3083bb148 Include/bytes_methods.h --- a/Include/bytes_methods.h Sat Nov 22 22:14:41 2014 -0800 +++ b/Include/bytes_methods.h Mon Nov 24 21:16:44 2014 +0200 @@ -22,7 +22,7 @@ extern void _Py_bytes_capitalize(char *r 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 e8b3083bb148 Modules/_codecsmodule.c --- a/Modules/_codecsmodule.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Modules/_codecsmodule.c Mon Nov 24 21:16:44 2014 +0200 @@ -288,8 +288,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)) @@ -302,11 +300,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; } } @@ -731,8 +734,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", @@ -745,6 +746,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; @@ -759,9 +761,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; } } diff -r e8b3083bb148 Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Modules/_ctypes/_ctypes.c Mon Nov 24 21:16:44 2014 +0200 @@ -463,8 +463,7 @@ KeepRef(CDataObject *target, Py_ssize_t static PyObject * CDataType_from_buffer(PyObject *type, PyObject *args) { - void *buffer; - Py_ssize_t buffer_len; + Py_buffer view; Py_ssize_t offset = 0; PyObject *obj, *result; StgDictObject *dict = PyType_stgdict(type); @@ -473,29 +472,36 @@ CDataType_from_buffer(PyObject *type, Py if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset)) return NULL; - if (-1 == PyObject_AsWriteBuffer(obj, &buffer, &buffer_len)) + if (PyObject_GetBuffer(obj, &view, PyBUF_WRITABLE) != 0) { + PyErr_SetString(PyExc_TypeError, + "expected a writable bytes-like object"); return NULL; + } if (offset < 0) { PyErr_SetString(PyExc_ValueError, "offset cannot be negative"); + PyBuffer_Release(&view); return NULL; } - if (dict->size > buffer_len - offset) { + if (dict->size > view.len - offset) { PyErr_Format(PyExc_ValueError, "Buffer size too small (%zd instead of at least %zd bytes)", - buffer_len, dict->size + offset); + view.len, dict->size + offset); + PyBuffer_Release(&view); return NULL; } - result = PyCData_AtAddress(type, (char *)buffer + offset); - if (result == NULL) + result = PyCData_AtAddress(type, (char *)view.buf + offset); + if (result == NULL) { + PyBuffer_Release(&view); return NULL; + } Py_INCREF(obj); - if (-1 == KeepRef((CDataObject *)result, -1, obj)) { - return NULL; - } + if (-1 == KeepRef((CDataObject *)result, -1, obj)) + result = NULL; + PyBuffer_Release(&view); return result; } @@ -508,8 +514,7 @@ GenericPyCData_new(PyTypeObject *type, P static PyObject * CDataType_from_buffer_copy(PyObject *type, PyObject *args) { - const void *buffer; - Py_ssize_t buffer_len; + Py_buffer view; Py_ssize_t offset = 0; PyObject *obj, *result; StgDictObject *dict = PyType_stgdict(type); @@ -518,27 +523,30 @@ CDataType_from_buffer_copy(PyObject *typ if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset)) return NULL; - if (-1 == PyObject_AsReadBuffer(obj, (const void**)&buffer, &buffer_len)) + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0) return NULL; if (offset < 0) { PyErr_SetString(PyExc_ValueError, "offset cannot be negative"); + PyBuffer_Release(&view); return NULL; } - if (dict->size > buffer_len - offset) { + if (dict->size > view.len - offset) { PyErr_Format(PyExc_ValueError, "Buffer size too small (%zd instead of at least %zd bytes)", - buffer_len, dict->size + offset); + view.len, dict->size + offset); + PyBuffer_Release(&view); 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 *)view.buf + offset, dict->size); + } + PyBuffer_Release(&view); return result; } diff -r e8b3083bb148 Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Modules/_io/bytesio.c Mon Nov 24 21:16:44 2014 +0200 @@ -555,15 +555,19 @@ PyDoc_STRVAR(readinto_doc, static PyObject * bytesio_readinto(bytesio *self, PyObject *buffer) { - void *raw_buffer; + Py_buffer view; Py_ssize_t len, n; CHECK_CLOSED(self, NULL); - if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1) + if (PyObject_GetBuffer(buffer, &view, PyBUF_WRITABLE) != 0) { + PyErr_SetString(PyExc_TypeError, + "expected a writable bytes-like object"); return NULL; + } /* adjust invalid sizes */ + len = view.len; n = self->string_size - self->pos; if (len > n) { len = n; @@ -571,7 +575,7 @@ bytesio_readinto(bytesio *self, PyObject len = 0; } - memcpy(raw_buffer, self->buf + self->pos, len); + memcpy(view.buf, self->buf + self->pos, len); assert(self->pos + len < PY_SSIZE_T_MAX); assert(len >= 0); self->pos += len; diff -r e8b3083bb148 Modules/_sqlite/connection.c --- a/Modules/_sqlite/connection.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Modules/_sqlite/connection.c Mon Nov 24 21:16:44 2014 +0200 @@ -522,19 +522,20 @@ static int 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 e8b3083bb148 Modules/_sqlite/statement.c --- a/Modules/_sqlite/statement.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Modules/_sqlite/statement.c Mon Nov 24 21:16:44 2014 +0200 @@ -94,7 +94,6 @@ int pysqlite_statement_create(pysqlite_S 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,23 @@ int pysqlite_statement_bind_parameter(py } 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"); + PyBuffer_Release(&view); 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 e8b3083bb148 Modules/_struct.c --- a/Modules/_struct.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Modules/_struct.c Mon Nov 24 21:16:44 2014 +0200 @@ -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,40 @@ s_pack_into(PyObject *self, PyObject *ar } /* Extract a writable memory buffer from the first argument */ - if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0), - (void**)&buffer, &buffer_len) == -1 ) { + if (PyObject_GetBuffer(PyTuple_GET_ITEM(args, 0), &buffer, PyBUF_WRITABLE) != 0) { + PyErr_SetString(PyExc_TypeError, + "expected a writable bytes-like object"); 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, buffer.buf + offset) != 0) { + PyBuffer_Release(&buffer); return NULL; } + PyBuffer_Release(&buffer); Py_RETURN_NONE; } diff -r e8b3083bb148 Objects/abstract.c --- a/Objects/abstract.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Objects/abstract.c Mon Nov 24 21:16:44 2014 +0200 @@ -250,27 +250,7 @@ PyObject_AsCharBuffer(PyObject *obj, const char **buffer, Py_ssize_t *buffer_len) { - PyBufferProcs *pb; - Py_buffer view; - - if (obj == NULL || buffer == NULL || buffer_len == NULL) { - null_error(); - return -1; - } - pb = obj->ob_type->tp_as_buffer; - if (pb == NULL || pb->bf_getbuffer == NULL) { - PyErr_SetString(PyExc_TypeError, - "expected a bytes-like object"); - return -1; - } - if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1; - - *buffer = view.buf; - *buffer_len = view.len; - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(obj, &view); - Py_XDECREF(view.obj); - return 0; + return PyObject_AsReadBuffer(obj, (const void **)buffer, buffer_len); } int @@ -294,28 +274,18 @@ int PyObject_AsReadBuffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len) { - PyBufferProcs *pb; Py_buffer view; if (obj == NULL || buffer == NULL || buffer_len == NULL) { null_error(); return -1; } - pb = obj->ob_type->tp_as_buffer; - if (pb == NULL || - pb->bf_getbuffer == NULL) { - PyErr_SetString(PyExc_TypeError, - "expected a bytes-like object"); + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0) return -1; - } - - if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1; *buffer = view.buf; *buffer_len = view.len; - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(obj, &view); - Py_XDECREF(view.obj); + PyBuffer_Release(&view); return 0; } @@ -341,9 +311,7 @@ int PyObject_AsWriteBuffer(PyObject *obj *buffer = view.buf; *buffer_len = view.len; - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(obj, &view); - Py_XDECREF(view.obj); + PyBuffer_Release(&view); return 0; } @@ -352,13 +320,29 @@ int PyObject_AsWriteBuffer(PyObject *obj int PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { - if (!PyObject_CheckBuffer(obj)) { + PyBufferProcs *pb = obj->ob_type->tp_as_buffer; + + if (pb == NULL || pb->bf_getbuffer == NULL) { PyErr_Format(PyExc_TypeError, "a bytes-like object is required, not '%.100s'", Py_TYPE(obj)->tp_name); return -1; } - return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags); + return (*pb->bf_getbuffer)(obj, view, flags); +} + +int +_PyBuffer_Converter(PyObject *obj, Py_buffer *view) +{ + 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 1; + } + return PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == 0; } static int @@ -651,10 +635,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 * @@ -1262,8 +1250,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) @@ -1301,21 +1288,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); - - 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 e8b3083bb148 Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Objects/bytearrayobject.c Mon Nov 24 21:16:44 2014 +0200 @@ -79,24 +79,6 @@ bytearray_releasebuffer(PyByteArrayObjec 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) { @@ -267,8 +249,8 @@ PyByteArray_Concat(PyObject *a, PyObject va.len = -1; vb.len = -1; - if (_getbuffer(a, &va) < 0 || - _getbuffer(b, &vb) < 0) { + if (!_PyBuffer_Converter(a, &va) || + !_PyBuffer_Converter(b, &vb)) { PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); goto done; @@ -309,7 +291,7 @@ bytearray_iconcat(PyByteArrayObject *sel Py_ssize_t size; Py_buffer vo; - if (_getbuffer(other, &vo) < 0) { + if (!_PyBuffer_Converter(other, &vo)) { PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name); return NULL; @@ -569,7 +551,7 @@ bytearray_setslice(PyByteArrayObject *se needed = 0; } else { - if (_getbuffer(values, &vbytes) < 0) { + if (!_PyBuffer_Converter(values, &vbytes)) { PyErr_Format(PyExc_TypeError, "can't set bytearray slice from %.100s", Py_TYPE(values)->tp_name); @@ -1021,18 +1003,18 @@ bytearray_richcompare(PyObject *self, Py Py_RETURN_NOTIMPLEMENTED; } - self_size = _getbuffer(self, &self_bytes); - if (self_size < 0) { + if (!_PyBuffer_Converter(self, &self_bytes)) { PyErr_Clear(); Py_RETURN_NOTIMPLEMENTED; } - - other_size = _getbuffer(other, &other_bytes); - if (other_size < 0) { + self_size = self_bytes.len; + + if (!_PyBuffer_Converter(other, &other_bytes)) { 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 */ @@ -1144,7 +1126,7 @@ bytearray_find_internal(PyByteArrayObjec return -2; if (subobj) { - if (_getbuffer(subobj, &subbuf) < 0) + if (!_PyBuffer_Converter(subobj, &subbuf)) return -2; sub = subbuf.buf; @@ -1212,7 +1194,7 @@ bytearray_count(PyByteArrayObject *self, return NULL; if (sub_obj) { - if (_getbuffer(sub_obj, &vsub) < 0) + if (!_PyBuffer_Converter(sub_obj, &vsub)) return NULL; sub = vsub.buf; @@ -1371,7 +1353,7 @@ bytearray_contains(PyObject *self, PyObj Py_buffer varg; Py_ssize_t pos; PyErr_Clear(); - if (_getbuffer(arg, &varg) < 0) + if (!_PyBuffer_Converter(arg, &varg)) return -1; pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self), varg.buf, varg.len, 0); @@ -1402,7 +1384,7 @@ Py_LOCAL(int) str = PyByteArray_AS_STRING(self); - if (_getbuffer(substr, &vsubstr) < 0) + if (!_PyBuffer_Converter(substr, &vsubstr)) return -1; ADJUST_INDICES(start, end, len); @@ -1595,7 +1577,7 @@ bytearray_translate_impl(PyByteArrayObje if (table == Py_None) { table_chars = NULL; table = NULL; - } else if (_getbuffer(table, &vtable) < 0) { + } else if (!_PyBuffer_Converter(table, &vtable)) { return NULL; } else { if (vtable.len != 256) { @@ -1608,7 +1590,7 @@ bytearray_translate_impl(PyByteArrayObje } if (deletechars != NULL) { - if (_getbuffer(deletechars, &vdel) < 0) { + if (!_PyBuffer_Converter(deletechars, &vdel)) { if (table != NULL) PyBuffer_Release(&vtable); return NULL; @@ -1673,8 +1655,8 @@ done: @staticmethod bytearray.maketrans - frm: object - to: object + frm: simple_buffer + to: simple_buffer / Return a translation table useable for the bytes or bytearray translate method. @@ -1700,28 +1682,35 @@ PyDoc_STRVAR(bytearray_maketrans__doc__, {"maketrans", (PyCFunction)bytearray_maketrans, METH_VARARGS|METH_STATIC, bytearray_maketrans__doc__}, static PyObject * -bytearray_maketrans_impl(PyObject *frm, PyObject *to); +bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to); static PyObject * bytearray_maketrans(void *null, PyObject *args) { PyObject *return_value = NULL; - PyObject *frm; - PyObject *to; - - if (!PyArg_UnpackTuple(args, "maketrans", - 2, 2, - &frm, &to)) + Py_buffer frm = {NULL, NULL}; + Py_buffer to = {NULL, NULL}; + + if (!PyArg_ParseTuple(args, + "O&O&:maketrans", + _PyBuffer_Converter, &frm, _PyBuffer_Converter, &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=62c9eab786b2f6d6 input=b5535e6dba0a5d1d]*/ { return _Py_bytes_maketrans(frm, to); } @@ -2217,8 +2206,8 @@ replace(PyByteArrayObject *self, /*[clinic input] bytearray.replace - old: object - new: object + old: simple_buffer + new: simple_buffer count: Py_ssize_t = -1 Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences. @@ -2247,47 +2236,40 @@ PyDoc_STRVAR(bytearray_replace__doc__, {"replace", (PyCFunction)bytearray_replace, METH_VARARGS, bytearray_replace__doc__}, static PyObject * -bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count); +bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * bytearray_replace(PyByteArrayObject *self, PyObject *args) { PyObject *return_value = NULL; - PyObject *old; - PyObject *new; + Py_buffer old = {NULL, NULL}; + Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; if (!PyArg_ParseTuple(args, - "OO|n:replace", - &old, &new, &count)) + "O&O&|n:replace", + _PyBuffer_Converter, &old, _PyBuffer_Converter, &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=8e33a818a0719edf input=0a13c0be405c4fe5]*/ { - 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] @@ -2357,7 +2339,7 @@ bytearray_split_impl(PyByteArrayObject * if (sep == Py_None) return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) + if (!_PyBuffer_Converter(sep, &vsub)) return NULL; sub = vsub.buf; n = vsub.len; @@ -2540,7 +2522,7 @@ bytearray_rsplit_impl(PyByteArrayObject if (sep == Py_None) return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) + if (!_PyBuffer_Converter(sep, &vsub)) return NULL; sub = vsub.buf; n = vsub.len; @@ -3062,7 +3044,7 @@ bytearray_strip_impl(PyByteArrayObject * byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) + if (!_PyBuffer_Converter(bytes, &vbytes)) return NULL; bytesptr = (char *) vbytes.buf; byteslen = vbytes.len; @@ -3133,7 +3115,7 @@ bytearray_lstrip_impl(PyByteArrayObject byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) + if (!_PyBuffer_Converter(bytes, &vbytes)) return NULL; bytesptr = (char *) vbytes.buf; byteslen = vbytes.len; @@ -3201,7 +3183,7 @@ bytearray_rstrip_impl(PyByteArrayObject byteslen = 6; } else { - if (_getbuffer(bytes, &vbytes) < 0) + if (!_PyBuffer_Converter(bytes, &vbytes)) return NULL; bytesptr = (char *) vbytes.buf; byteslen = vbytes.len; diff -r e8b3083bb148 Objects/bytes_methods.c --- a/Objects/bytes_methods.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Objects/bytes_methods.c Mon Nov 24 21:16:44 2014 +0200 @@ -363,59 +363,27 @@ for use in the bytes or bytearray transl 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 e8b3083bb148 Objects/bytesobject.c --- a/Objects/bytesobject.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Objects/bytesobject.c Mon Nov 24 21:16:44 2014 +0200 @@ -12,33 +12,6 @@ class bytes "PyBytesObject*" "&PyBytes_T [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 @@ -721,8 +694,8 @@ bytes_concat(PyObject *a, PyObject *b) va.len = -1; vb.len = -1; - if (_getbuffer(a, &va) < 0 || - _getbuffer(b, &vb) < 0) { + if (!_PyBuffer_Converter(a, &va) || + !_PyBuffer_Converter(b, &vb)) { PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); goto done; @@ -820,7 +793,7 @@ bytes_contains(PyObject *self, PyObject Py_buffer varg; Py_ssize_t pos; PyErr_Clear(); - if (_getbuffer(arg, &varg) < 0) + if (!_PyBuffer_Converter(arg, &varg)) return -1; pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self), varg.buf, varg.len, 0); @@ -1109,7 +1082,7 @@ bytes_split_impl(PyBytesObject*self, PyO maxsplit = PY_SSIZE_T_MAX; if (sep == Py_None) return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) + if (!_PyBuffer_Converter(sep, &vsub)) return NULL; sub = vsub.buf; n = vsub.len; @@ -1123,7 +1096,7 @@ bytes_split_impl(PyBytesObject*self, PyO bytes.partition self: self(type="PyBytesObject *") - sep: object + sep: simple_buffer / Partition the bytes into three parts using the given separator. @@ -1150,26 +1123,39 @@ PyDoc_STRVAR(bytes_partition__doc__, "object and two empty bytes objects."); #define BYTES_PARTITION_METHODDEF \ - {"partition", (PyCFunction)bytes_partition, METH_O, bytes_partition__doc__}, + {"partition", (PyCFunction)bytes_partition, METH_VARARGS, bytes_partition__doc__}, static PyObject * -bytes_partition(PyBytesObject *self, PyObject *sep) -/*[clinic end generated code: output=b41e119c873c08bc input=6c5b9dcc5a9fd62e]*/ +bytes_partition_impl(PyBytesObject *self, Py_buffer *sep); + +static PyObject * +bytes_partition(PyBytesObject *self, PyObject *args) { - const char *sep_chars; - Py_ssize_t sep_len; - - 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, + "O&:partition", + _PyBuffer_Converter, &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=24ba7aef4ec69f08 input=3413f1c03d0e09ce]*/ +{ 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 ); } @@ -1177,7 +1163,7 @@ bytes_partition(PyBytesObject *self, PyO bytes.rpartition self: self(type="PyBytesObject *") - sep: object + sep: simple_buffer / Partition the bytes into three parts using the given separator. @@ -1204,26 +1190,39 @@ PyDoc_STRVAR(bytes_rpartition__doc__, "objects and the original bytes object."); #define BYTES_RPARTITION_METHODDEF \ - {"rpartition", (PyCFunction)bytes_rpartition, METH_O, bytes_rpartition__doc__}, + {"rpartition", (PyCFunction)bytes_rpartition, METH_VARARGS, bytes_rpartition__doc__}, static PyObject * -bytes_rpartition(PyBytesObject *self, PyObject *sep) -/*[clinic end generated code: output=3a620803657196ee input=79bc2932e78e5ce0]*/ +bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep); + +static PyObject * +bytes_rpartition(PyBytesObject *self, PyObject *args) { - const char *sep_chars; - Py_ssize_t sep_len; - - 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, + "O&:rpartition", + _PyBuffer_Converter, &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=30199c7f214768ba input=3d184a198def65b2]*/ +{ 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 ); } @@ -1288,7 +1287,7 @@ bytes_rsplit_impl(PyBytesObject*self, Py maxsplit = PY_SSIZE_T_MAX; if (sep == Py_None) return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); - if (_getbuffer(sep, &vsub) < 0) + if (!_PyBuffer_Converter(sep, &vsub)) return NULL; sub = vsub.buf; n = vsub.len; @@ -1375,7 +1374,7 @@ bytes_find_internal(PyBytesObject *self, return -2; if (subobj) { - if (_getbuffer(subobj, &subbuf) < 0) + if (!_PyBuffer_Converter(subobj, &subbuf)) return -2; sub = subbuf.buf; @@ -1490,7 +1489,7 @@ do_xstrip(PyBytesObject *self, int strip Py_ssize_t seplen; Py_ssize_t i, j; - if (_getbuffer(sepobj, &vsep) < 0) + if (!_PyBuffer_Converter(sepobj, &vsep)) return NULL; sep = vsep.buf; seplen = vsep.len; @@ -1732,7 +1731,7 @@ bytes_count(PyBytesObject *self, PyObjec return NULL; if (sub_obj) { - if (_getbuffer(sub_obj, &vsub) < 0) + if (!_PyBuffer_Converter(sub_obj, &vsub)) return NULL; sub = vsub.buf; @@ -1822,6 +1821,8 @@ bytes_translate_impl(PyBytesObject *self /*[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; @@ -1838,8 +1839,12 @@ bytes_translate_impl(PyBytesObject *self 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, @@ -1852,8 +1857,12 @@ bytes_translate_impl(PyBytesObject *self 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) + return NULL; + del_table_chars = del_table_view.buf; + dellen = del_table_view.len; + } } else { del_table_chars = NULL; @@ -1862,8 +1871,11 @@ bytes_translate_impl(PyBytesObject *self 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); @@ -1874,10 +1886,13 @@ bytes_translate_impl(PyBytesObject *self 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); + 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 input_obj; } @@ -1888,9 +1903,11 @@ bytes_translate_impl(PyBytesObject *self 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++); @@ -1916,8 +1933,8 @@ bytes_translate_impl(PyBytesObject *self @staticmethod bytes.maketrans - frm: object - to: object + frm: simple_buffer + to: simple_buffer / Return a translation table useable for the bytes or bytearray translate method. @@ -1943,28 +1960,35 @@ PyDoc_STRVAR(bytes_maketrans__doc__, {"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC, bytes_maketrans__doc__}, static PyObject * -bytes_maketrans_impl(PyObject *frm, PyObject *to); +bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to); static PyObject * bytes_maketrans(void *null, PyObject *args) { PyObject *return_value = NULL; - PyObject *frm; - PyObject *to; - - if (!PyArg_UnpackTuple(args, "maketrans", - 2, 2, - &frm, &to)) + Py_buffer frm = {NULL, NULL}; + Py_buffer to = {NULL, NULL}; + + if (!PyArg_ParseTuple(args, + "O&O&:maketrans", + _PyBuffer_Converter, &frm, _PyBuffer_Converter, &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=dd17a345ab364b99 input=5500fa496416ea0c]*/ { return _Py_bytes_maketrans(frm, to); } @@ -2465,8 +2489,8 @@ replace(PyBytesObject *self, /*[clinic input] bytes.replace - old: object - new: object + old: simple_buffer + new: simple_buffer count: Py_ssize_t = -1 Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences. @@ -2495,50 +2519,40 @@ PyDoc_STRVAR(bytes_replace__doc__, {"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__}, static PyObject * -bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count); +bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * bytes_replace(PyBytesObject*self, PyObject *args) { PyObject *return_value = NULL; - PyObject *old; - PyObject *new; + Py_buffer old = {NULL, NULL}; + Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; if (!PyArg_ParseTuple(args, - "OO|n:replace", - &old, &new, &count)) + "O&O&|n:replace", + _PyBuffer_Converter, &old, _PyBuffer_Converter, &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=3b581e617710f2c6 input=74b37be7c347f7e5]*/ { - 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 **/ @@ -2553,6 +2567,7 @@ Py_LOCAL(int) { Py_ssize_t len = PyBytes_GET_SIZE(self); Py_ssize_t slen; + Py_buffer sub_view = {NULL, NULL}; const char* sub; const char* str; @@ -2560,8 +2575,12 @@ Py_LOCAL(int) 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); @@ -2569,17 +2588,25 @@ Py_LOCAL(int) 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; } @@ -3335,7 +3362,7 @@ PyBytes_Concat(PyObject **pv, PyObject * Py_buffer wb; wb.len = -1; - if (_getbuffer(w, &wb) < 0) { + if (!_PyBuffer_Converter(w, &wb)) { 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 e8b3083bb148 Objects/complexobject.c --- a/Objects/complexobject.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Objects/complexobject.c Mon Nov 24 21:16:44 2014 +0200 @@ -767,6 +767,7 @@ complex_subtype_from_string(PyTypeObject 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 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,8 @@ complex_subtype_from_string(PyTypeObject if (s-start != len) goto parse_error; + if (view.obj) + PyBuffer_Release(&view); Py_XDECREF(s_buffer); return complex_subtype_from_doubles(type, x, y); @@ -897,6 +904,8 @@ complex_subtype_from_string(PyTypeObject PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string"); error: + if (view.obj) + PyBuffer_Release(&view); Py_XDECREF(s_buffer); return NULL; } diff -r e8b3083bb148 Objects/exceptions.c --- a/Objects/exceptions.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Objects/exceptions.c Mon Nov 24 21:16:44 2014 +0200 @@ -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,29 @@ UnicodeDecodeError_init(PyObject *self, 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)) { + Py_buffer view; + if (PyObject_GetBuffer(ude->object, &view, PyBUF_SIMPLE) != 0) { ude->encoding = ude->object = ude->reason = NULL; return -1; } - ude->object = PyBytes_FromStringAndSize(data, size); + Py_DECREF(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 e8b3083bb148 Objects/floatobject.c --- a/Objects/floatobject.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Objects/floatobject.c Mon Nov 24 21:16:44 2014 +0200 @@ -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,8 @@ PyFloat_FromString(PyObject *v) else result = PyFloat_FromDouble(x); + if (view.obj) + PyBuffer_Release(&view); Py_XDECREF(s_buffer); return result; } diff -r e8b3083bb148 Objects/stringlib/join.h --- a/Objects/stringlib/join.h Sat Nov 22 22:14:41 2014 -0800 +++ b/Objects/stringlib/join.h Mon Nov 24 21:16:44 2014 +0200 @@ -58,7 +58,7 @@ STRINGLIB(bytes_join)(PyObject *sep, PyO 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 (!_PyBuffer_Converter(item, &buffers[i])) { PyErr_Format(PyExc_TypeError, "sequence item %zd: expected bytes, bytearray, " "or an object with the buffer interface, %.80s found", diff -r e8b3083bb148 Python/bltinmodule.c --- a/Python/bltinmodule.c Sat Nov 22 22:14:41 2014 -0800 +++ b/Python/bltinmodule.c Mon Nov 24 21:16:44 2014 +0200 @@ -723,10 +723,10 @@ builtin_chr_impl(PyModuleDef *module, in } -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,17 +735,18 @@ source_as_string(PyObject *cmd, char *fu 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"); return NULL; @@ -827,7 +828,8 @@ static PyObject * 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 +900,13 @@ builtin_compile_impl(PyModuleDef *module 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); + if (view.obj) + PyBuffer_Release(&view); goto finally; error: @@ -1042,7 +1046,8 @@ builtin_eval_impl(PyModuleDef *module, P /*[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 @@ builtin_eval_impl(PyModuleDef *module, P } 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,8 @@ builtin_eval_impl(PyModuleDef *module, P (void)PyEval_MergeCompilerFlags(&cf); result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); + if (view.obj) + PyBuffer_Release(&view); Py_XDECREF(tmp); return result; } @@ -1204,11 +1211,12 @@ builtin_exec_impl(PyModuleDef *module, P 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 +1224,8 @@ builtin_exec_impl(PyModuleDef *module, P locals, &cf); else v = PyRun_String(str, Py_file_input, globals, locals); + if (view.obj) + PyBuffer_Release(&view); } if (v == NULL) return NULL; diff -r e8b3083bb148 Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py Sat Nov 22 22:14:41 2014 -0800 +++ b/Tools/clinic/clinic.py Mon Nov 24 21:16:44 2014 +0200 @@ -2660,6 +2660,16 @@ class Py_buffer_converter(CConverter): name = ensure_legal_c_identifier(self.name) return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"]) +class simple_buffer_converter(CConverter): + type = 'Py_buffer' + converter = '_PyBuffer_Converter' + impl_by_reference = True + c_default = "{NULL, NULL}" + + def cleanup(self): + name = self.name + return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"]) + def correct_name_for_self(f): if f.kind in (CALLABLE, METHOD_INIT):