diff -r be505d22dde8 Modules/_testbuffer.c --- a/Modules/_testbuffer.c Thu Aug 30 00:30:14 2012 +0200 +++ b/Modules/_testbuffer.c Thu Aug 30 13:23:01 2012 -0400 @@ -5,7 +5,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" - +#include /* struct module */ PyObject *structmodule = NULL; @@ -2784,6 +2784,150 @@ }; +static int +congruent(Py_buffer *v1, Py_buffer *v2) +{ + return v1->len == v2->len && + v1->ndim == v2->ndim && + v1->readonly == v2->readonly && + v1->itemsize == v2->itemsize && + strcpy(v1->format, v2->format) == 0 && + memcpy(v1->shape, v2->shape, v1->ndim) == 0 && + memcpy(v1->strides, v2->strides, v1->ndim) == 0 && + memcpy(v1->suboffsets, v2->suboffsets, v1->ndim) == 0; +} + +static PyObject * +objview_bytes(PyObject *obj, Py_ssize_t *outer_suboffset) +{ + PyObject *view; + Py_buffer info; + + *outer_suboffset = offsetof(PyBytesObject, ob_sval); + if (PyObject_GetBuffer(obj, &info, PyBUF_FULL_RO) < 0) + return NULL; + assert(info.buf == *outer_suboffset + (char *)obj); + info.buf = (char *)obj; + view = PyMemoryView_FromBuffer(&info); + + return view; +} + +static PyObject * +objview_array(PyObject *obj, Py_ssize_t *outer_suboffset) +{ + typedef struct { + PyObject_VAR_HEAD + char *ob_item; + } arrayobject_head; + Py_ssize_t shape[2] = {1,}; + Py_ssize_t strides[2] = {sizeof(char*),}; + Py_ssize_t suboffsets[2] = {0, -1}; + PyObject *view; + Py_buffer info; + *outer_suboffset = offsetof(arrayobject_head, ob_item); + if (PyObject_GetBuffer(obj, &info, PyBUF_FULL_RO) < 0) + return NULL; + assert(info.buf == *(char **)(*outer_suboffset + (char *)obj)); + info.buf = (char *)obj; + info.ndim = 2; + shape[1] = info.len; + info.shape = shape; + strides[1] = info.itemsize; + info.strides = strides; + info.suboffsets = suboffsets; + view = PyMemoryView_FromBuffer(&info); + + return view; +} + +static PyObject * +objview_tuple(PyObject *tup, Py_ssize_t *outer_suboffset); + +static PyObject * +objview_any(PyObject *obj, Py_ssize_t *outer_suboffset) +{ + if (PyTuple_Check(obj)) + return objview_tuple(obj, outer_suboffset); + if (PyBytes_Check(obj)) + return objview_bytes(obj, outer_suboffset); + /* XXX need a more robust check */ + if (strcmp("array.array", Py_TYPE(obj)->tp_name) == 0) + return objview_array(obj, outer_suboffset); + PyErr_Format(PyExc_TypeError, "unsupported type"); + return NULL; +} + +static PyObject * +objview_tuple(PyObject *tup, Py_ssize_t *outer_suboffset) +{ + typedef struct { + PyObject_VAR_HEAD + char *ob_item; + } arrayobject_head; + PyObject *view; + PyObject *obj; + Py_buffer info; + PyMemoryViewObject *subview; + Py_ssize_t i, *sizes, suboffset0; + *outer_suboffset = offsetof(PyTupleObject, ob_item); + obj = PyTuple_GET_ITEM(tup, 0); + subview = (PyMemoryViewObject *)objview_any(obj, &suboffset0); + /* XXX add congruency check */ + if (subview == NULL) + return NULL; + Py_INCREF(tup); + info.obj = tup; + info.buf = &PyTuple_GET_ITEM(tup, 0); + assert(*outer_suboffset + (char *)tup == info.buf); + info.len = PyTuple_GET_SIZE(tup) * subview->view.len; + info.ndim = 1 + subview->view.ndim; + info.itemsize = subview->view.itemsize; + info.format = subview->view.format; + info.readonly = subview->view.readonly; + sizes = PyMem_Malloc(3 * info.ndim * sizeof(Py_ssize_t)); + if (sizes == NULL) { + PyErr_NoMemory(); + return NULL; + } + info.shape = sizes; + info.strides = sizes + info.ndim; + info.suboffsets = sizes + 2 * info.ndim; + info.shape[0] = PyTuple_GET_SIZE(tup); + for (i = 0; i < subview->view.ndim; ++i) + info.shape[1 + i] = subview->view.shape[i]; + info.strides[0] = sizeof(PyObject *); + for (i = 0; i < subview->view.ndim; ++i) + info.strides[1 + i] = subview->view.strides[i]; + info.suboffsets[0] = suboffset0; + if (subview->view.suboffsets == NULL) + for (i = 0; i < subview->view.ndim; ++i) + info.suboffsets[1 + i] = -1; + else + for (i = 0; i < subview->view.ndim; ++i) + info.suboffsets[1 + i] = subview->view.suboffsets[i]; + view = PyMemoryView_FromBuffer(&info); + /* PyMemoryView_FromBuffer ignores info.buf. Add it explicitely. */ + if (view != NULL) + ((PyMemoryViewObject *)view)->view.obj = info.obj; + PyMem_Free(sizes); + Py_DECREF(subview); + return view; +} + + +PyDoc_STRVAR(objview_doc, +"objview(obj)\n\ +\n\ +Return a memoryview with buf = obj"); + +static PyObject * +objview(PyObject *self, PyObject *obj) +{ + Py_ssize_t dummy; + return objview_any(obj, &dummy); +} + static struct PyMethodDef _testbuffer_functions[] = { {"slice_indices", slice_indices, METH_VARARGS, NULL}, {"get_pointer", get_pointer, METH_VARARGS, NULL}, @@ -2792,6 +2936,7 @@ {"py_buffer_to_contiguous", py_buffer_to_contiguous, METH_VARARGS, NULL}, {"is_contiguous", is_contiguous, METH_VARARGS, NULL}, {"cmp_contig", cmp_contig, METH_VARARGS, NULL}, + {"objview", objview, METH_O, objview_doc}, {NULL, NULL} };