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}
};