blob: 79d7db1b0221b5df9fa5b2797967afe384abb6a0 [file] [log] [blame]
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001
2/* Memoryview object implementation */
3
4#include "Python.h"
5
6static int
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +00007memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00008{
Guido van Rossum5dde61d2007-09-25 22:10:05 +00009 if (view != NULL)
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +000010 *view = self->view;
Guido van Rossumbe801ac2007-10-08 03:32:34 +000011 if (self->base == NULL)
12 return 0;
Guido van Rossum5dde61d2007-09-25 22:10:05 +000013 return self->base->ob_type->tp_as_buffer->bf_getbuffer(self->base, NULL,
14 PyBUF_FULL);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000015}
16
17static void
Guido van Rossum5dde61d2007-09-25 22:10:05 +000018memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000019{
Guido van Rossumbe801ac2007-10-08 03:32:34 +000020 if (self->base != NULL)
21 PyObject_ReleaseBuffer(self->base, NULL);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000022}
23
24PyDoc_STRVAR(memory_doc,
25"memoryview(object)\n\
26\n\
27Create a new memoryview object which references the given object.");
28
29PyObject *
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +000030PyMemoryView_FromMemory(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000031{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +000032 PyMemoryViewObject *mview;
33
34 mview = (PyMemoryViewObject *)PyObject_New(PyMemoryViewObject,
35 &PyMemoryView_Type);
36 if (mview == NULL) return NULL;
37 mview->base = NULL;
38 mview->view = *info;
39 return (PyObject *)mview;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000040}
41
42PyObject *
43PyMemoryView_FromObject(PyObject *base)
44{
45 PyMemoryViewObject *mview;
46
47 if (!PyObject_CheckBuffer(base)) {
Guido van Rossum5dde61d2007-09-25 22:10:05 +000048 PyErr_SetString(PyExc_TypeError,
49 "cannot make memory view because object does "
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000050 "not have the buffer interface");
Guido van Rossum5dde61d2007-09-25 22:10:05 +000051 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000052 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +000053
54 mview = (PyMemoryViewObject *)PyObject_New(PyMemoryViewObject,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000055 &PyMemoryView_Type);
56 if (mview == NULL) return NULL;
Guido van Rossum5dde61d2007-09-25 22:10:05 +000057
Neal Norwitz666bb412007-08-19 18:38:46 +000058 mview->base = NULL;
Antoine Pitrou2f89aa62008-08-02 21:02:48 +000059 if (PyObject_GetBuffer(base, &(mview->view), PyBUF_FULL_RO) < 0) {
Neal Norwitz666bb412007-08-19 18:38:46 +000060 Py_DECREF(mview);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000061 return NULL;
62 }
63
64 mview->base = base;
65 Py_INCREF(base);
66 return (PyObject *)mview;
67}
68
69static PyObject *
70memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
71{
Christian Heimes7b6fc8e2007-11-08 02:28:11 +000072 PyObject *obj;
73 static char *kwlist[] = {"object", 0};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000074
Christian Heimes7b6fc8e2007-11-08 02:28:11 +000075 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
76 &obj)) {
77 return NULL;
78 }
79
80 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000081}
82
83
84static void
Guido van Rossum5dde61d2007-09-25 22:10:05 +000085_strided_copy_nd(char *dest, char *src, int nd, Py_ssize_t *shape,
Neal Norwitz61ec0d32007-10-26 06:44:10 +000086 Py_ssize_t *strides, Py_ssize_t itemsize, char fort)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000087{
88 int k;
89 Py_ssize_t outstride;
90
91 if (nd==0) {
92 memcpy(dest, src, itemsize);
93 }
94 else if (nd == 1) {
95 for (k = 0; k<shape[0]; k++) {
96 memcpy(dest, src, itemsize);
97 dest += itemsize;
98 src += strides[0];
99 }
100 }
101 else {
102 if (fort == 'F') {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000103 /* Copy first dimension first,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000104 second dimension second, etc...
105 Set up the recursive loop backwards so that final
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000106 dimension is actually copied last.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000107 */
108 outstride = itemsize;
109 for (k=1; k<nd-1;k++) {
110 outstride *= shape[k];
111 }
112 for (k=0; k<shape[nd-1]; k++) {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000113 _strided_copy_nd(dest, src, nd-1, shape,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000114 strides, itemsize, fort);
115 dest += outstride;
116 src += strides[nd-1];
117 }
118 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000119
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000120 else {
121 /* Copy last dimension first,
122 second-to-last dimension second, etc.
123 Set up the recursion so that the
124 first dimension is copied last
125 */
126 outstride = itemsize;
127 for (k=1; k < nd; k++) {
128 outstride *= shape[k];
129 }
130 for (k=0; k<shape[0]; k++) {
131 _strided_copy_nd(dest, src, nd-1, shape+1,
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000132 strides+1, itemsize,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000133 fort);
134 dest += outstride;
135 src += strides[0];
136 }
137 }
138 }
139 return;
140}
141
142void _add_one_to_index_F(int nd, Py_ssize_t *index, Py_ssize_t *shape);
143void _add_one_to_index_C(int nd, Py_ssize_t *index, Py_ssize_t *shape);
144
145static int
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000146_indirect_copy_nd(char *dest, Py_buffer *view, char fort)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000147{
148 Py_ssize_t *indices;
149 int k;
150 Py_ssize_t elements;
151 char *ptr;
152 void (*func)(int, Py_ssize_t *, Py_ssize_t *);
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000153
Amaury Forgeot d'Arc9c74b142008-06-18 00:47:36 +0000154 if (view->ndim > PY_SSIZE_T_MAX / sizeof(Py_ssize_t)) {
155 PyErr_NoMemory();
156 return -1;
157 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000158
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000159 indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view->ndim);
160 if (indices == NULL) {
161 PyErr_NoMemory();
162 return -1;
163 }
164 for (k=0; k<view->ndim;k++) {
165 indices[k] = 0;
166 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000167
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000168 elements = 1;
169 for (k=0; k<view->ndim; k++) {
170 elements *= view->shape[k];
171 }
172 if (fort == 'F') {
173 func = _add_one_to_index_F;
174 }
175 else {
176 func = _add_one_to_index_C;
177 }
178 while (elements--) {
179 func(view->ndim, indices, view->shape);
180 ptr = PyBuffer_GetPointer(view, indices);
181 memcpy(dest, ptr, view->itemsize);
182 dest += view->itemsize;
183 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000184
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000185 PyMem_Free(indices);
186 return 0;
187}
188
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000189/*
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000190 Get a the data from an object as a contiguous chunk of memory (in
191 either 'C' or 'F'ortran order) even if it means copying it into a
192 separate memory area.
193
194 Returns a new reference to a Memory view object. If no copy is needed,
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000195 the memory view object points to the original memory and holds a
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000196 lock on the original. If a copy is needed, then the memory view object
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000197 points to a brand-new Bytes object (and holds a memory lock on it).
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000198
199 buffertype
200
201 PyBUF_READ buffer only needs to be read-only
Sean Reifscheider54cf12b2007-09-17 17:55:36 +0000202 PyBUF_WRITE buffer needs to be writable (give error if not contiguous)
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000203 PyBUF_SHADOW buffer needs to be writable so shadow it with
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000204 a contiguous buffer if it is not. The view will point to
205 the shadow buffer which can be written to and then
206 will be copied back into the other buffer when the memory
Antoine Pitrou2f89aa62008-08-02 21:02:48 +0000207 view is de-allocated. While the shadow buffer is
208 being used, it will have an exclusive write lock on
209 the original buffer.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000210 */
211
212PyObject *
213PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
214{
215 PyMemoryViewObject *mem;
216 PyObject *bytes;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000217 Py_buffer *view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000218 int flags;
219 char *dest;
220
221 if (!PyObject_CheckBuffer(obj)) {
222 PyErr_SetString(PyExc_TypeError,
223 "object does not have the buffer interface");
224 return NULL;
225 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000226
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000227 mem = PyObject_New(PyMemoryViewObject, &PyMemoryView_Type);
228 if (mem == NULL) return NULL;
229
230 view = &PyMemoryView(mem);
231 flags = PyBUF_FULL_RO;
232 switch(buffertype) {
233 case PyBUF_WRITE:
234 flags = PyBUF_FULL;
235 break;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000236 }
237
238 if (PyObject_GetBuffer(obj, view, flags) != 0) {
239 PyObject_DEL(mem);
240 return NULL;
241 }
242
243 if (PyBuffer_IsContiguous(view, fort)) {
244 /* no copy needed */
245 Py_INCREF(obj);
246 mem->base = obj;
247 return (PyObject *)mem;
248 }
249 /* otherwise a copy is needed */
250 if (buffertype == PyBUF_WRITE) {
251 PyObject_DEL(mem);
252 PyErr_SetString(PyExc_BufferError,
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000253 "writable contiguous buffer requested "
254 "for a non-contiguousobject.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000255 return NULL;
256 }
Christian Heimes9c4756e2008-05-26 13:22:05 +0000257 bytes = PyByteArray_FromStringAndSize(NULL, view->len);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000258 if (bytes == NULL) {
259 PyObject_ReleaseBuffer(obj, view);
260 return NULL;
261 }
Christian Heimes9c4756e2008-05-26 13:22:05 +0000262 dest = PyByteArray_AS_STRING(bytes);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000263 /* different copying strategy depending on whether
264 or not any pointer de-referencing is needed
265 */
266 /* strided or in-direct copy */
267 if (view->suboffsets==NULL) {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000268 _strided_copy_nd(dest, view->buf, view->ndim, view->shape,
269 view->strides, view->itemsize, fort);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000270 }
271 else {
272 if (_indirect_copy_nd(dest, view, fort) < 0) {
273 Py_DECREF(bytes);
274 PyObject_ReleaseBuffer(obj, view);
275 return NULL;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000276 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000277 }
278 if (buffertype == PyBUF_SHADOW) {
279 /* return a shadowed memory-view object */
280 view->buf = dest;
281 mem->base = PyTuple_Pack(2, obj, bytes);
282 Py_DECREF(bytes);
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000283 if (mem->base == NULL) {
284 PyObject_ReleaseBuffer(obj, view);
285 return NULL;
286 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000287 }
288 else {
289 PyObject_ReleaseBuffer(obj, view);
290 /* steal the reference */
291 mem->base = bytes;
292 }
293 return (PyObject *)mem;
294}
295
296
297static PyObject *
298memory_format_get(PyMemoryViewObject *self)
299{
300 return PyUnicode_FromString(self->view.format);
301}
302
303static PyObject *
304memory_itemsize_get(PyMemoryViewObject *self)
305{
Christian Heimes217cfd12007-12-02 14:31:20 +0000306 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000307}
308
309static PyObject *
310_IntTupleFromSsizet(int len, Py_ssize_t *vals)
311{
312 int i;
313 PyObject *o;
314 PyObject *intTuple;
315
316 if (vals == NULL) {
317 Py_INCREF(Py_None);
318 return Py_None;
319 }
320 intTuple = PyTuple_New(len);
321 if (!intTuple) return NULL;
322 for(i=0; i<len; i++) {
Christian Heimes217cfd12007-12-02 14:31:20 +0000323 o = PyLong_FromSsize_t(vals[i]);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000324 if (!o) {
325 Py_DECREF(intTuple);
326 return NULL;
327 }
328 PyTuple_SET_ITEM(intTuple, i, o);
329 }
330 return intTuple;
331}
332
333static PyObject *
334memory_shape_get(PyMemoryViewObject *self)
335{
336 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
337}
338
339static PyObject *
340memory_strides_get(PyMemoryViewObject *self)
341{
342 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
343}
344
345static PyObject *
346memory_suboffsets_get(PyMemoryViewObject *self)
347{
348 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
349}
350
351static PyObject *
352memory_size_get(PyMemoryViewObject *self)
353{
Christian Heimes217cfd12007-12-02 14:31:20 +0000354 return PyLong_FromSsize_t(self->view.len);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000355}
356
357static PyObject *
358memory_readonly_get(PyMemoryViewObject *self)
359{
Neal Norwitz666bb412007-08-19 18:38:46 +0000360 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000361}
362
363static PyObject *
364memory_ndim_get(PyMemoryViewObject *self)
365{
Christian Heimes217cfd12007-12-02 14:31:20 +0000366 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000367}
368
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000369static PyGetSetDef memory_getsetlist[] ={
Neal Norwitz666bb412007-08-19 18:38:46 +0000370 {"format", (getter)memory_format_get, NULL, NULL},
371 {"itemsize", (getter)memory_itemsize_get, NULL, NULL},
372 {"shape", (getter)memory_shape_get, NULL, NULL},
373 {"strides", (getter)memory_strides_get, NULL, NULL},
374 {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL},
375 {"size", (getter)memory_size_get, NULL, NULL},
376 {"readonly", (getter)memory_readonly_get, NULL, NULL},
377 {"ndim", (getter)memory_ndim_get, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000378 {NULL, NULL, NULL, NULL},
379};
380
381
382static PyObject *
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000383memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000384{
Christian Heimes9c4756e2008-05-26 13:22:05 +0000385 return PyByteArray_FromObject((PyObject *)mem);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000386}
387
388static PyObject *
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000389memory_tolist(PyMemoryViewObject *mem, PyObject *noargs)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000390{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000391 /* This should construct a (nested) list of unpacked objects
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000392 possibly using the struct module.
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000393 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000394 Py_INCREF(Py_NotImplemented);
395 return Py_NotImplemented;
396}
397
398
399
400static PyMethodDef memory_methods[] = {
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000401 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL},
402 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000403 {NULL, NULL} /* sentinel */
404};
405
406
407static void
408memory_dealloc(PyMemoryViewObject *self)
409{
Neal Norwitz666bb412007-08-19 18:38:46 +0000410 if (self->base != NULL) {
411 if (PyTuple_Check(self->base)) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000412 /* Special case when first element is generic object
413 with buffer interface and the second element is a
414 contiguous "shadow" that must be copied back into
415 the data areay of the first tuple element before
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000416 releasing the buffer on the first element.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000417 */
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000418
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000419 PyObject_CopyData(PyTuple_GET_ITEM(self->base,0),
420 PyTuple_GET_ITEM(self->base,1));
421
422 /* The view member should have readonly == -1 in
423 this instance indicating that the memory can
424 be "locked" and was locked and will be unlocked
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000425 again after this call.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000426 */
427 PyObject_ReleaseBuffer(PyTuple_GET_ITEM(self->base,0),
428 &(self->view));
Neal Norwitz666bb412007-08-19 18:38:46 +0000429 }
430 else {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000431 PyObject_ReleaseBuffer(self->base, &(self->view));
Neal Norwitz666bb412007-08-19 18:38:46 +0000432 }
433 Py_CLEAR(self->base);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000434 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000435 PyObject_DEL(self);
436}
437
438static PyObject *
439memory_repr(PyMemoryViewObject *self)
440{
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000441 return PyUnicode_FromFormat("<memory at %p>", self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000442}
443
444
445static PyObject *
446memory_str(PyMemoryViewObject *self)
447{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000448 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000449 PyObject *res;
450
451 if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
452 return NULL;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000453
Christian Heimes9c4756e2008-05-26 13:22:05 +0000454 res = PyByteArray_FromStringAndSize(NULL, view.len);
455 PyBuffer_ToContiguous(PyByteArray_AS_STRING(res), &view, view.len, 'C');
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000456 PyObject_ReleaseBuffer((PyObject *)self, &view);
457 return res;
458}
459
460/* Sequence methods */
461
462static Py_ssize_t
463memory_length(PyMemoryViewObject *self)
464{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000465 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000466
467 if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
468 return -1;
469 PyObject_ReleaseBuffer((PyObject *)self, &view);
470 return view.len;
471}
472
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000473/*
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000474 mem[obj] returns a bytes object holding the data for one element if
475 obj fully indexes the memory view or another memory-view object
476 if it does not.
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000477
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000478 0-d memory-view objects can be referenced using ... or () but
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000479 not with anything else.
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000480 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000481static PyObject *
482memory_subscript(PyMemoryViewObject *self, PyObject *key)
483{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000484 Py_buffer *view;
485 view = &(self->view);
486
487 if (view->ndim == 0) {
488 if (key == Py_Ellipsis ||
489 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
490 Py_INCREF(self);
491 return (PyObject *)self;
492 }
493 else {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000494 PyErr_SetString(PyExc_IndexError,
495 "invalid indexing of 0-dim memory");
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000496 return NULL;
497 }
498 }
499 if (PyIndex_Check(key)) {
500 Py_ssize_t result;
501 result = PyNumber_AsSsize_t(key, NULL);
502 if (result == -1 && PyErr_Occurred())
503 return NULL;
504 if (view->ndim == 1) {
505 /* Return a bytes object */
506 char *ptr;
507 ptr = (char *)view->buf;
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000508 if (result < 0) {
509 result += view->shape[0];
510 }
511 if ((result < 0) || (result > view->shape[0])) {
512 PyErr_SetString(PyExc_IndexError,
513 "index out of bounds");
514 return NULL;
515 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000516 if (view->strides == NULL)
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000517 ptr += view->itemsize * result;
518 else
519 ptr += view->strides[0] * result;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000520 if (view->suboffsets != NULL &&
521 view->suboffsets[0] >= 0)
522 {
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000523 ptr = *((char **)ptr) + view->suboffsets[0];
524 }
Christian Heimes9c4756e2008-05-26 13:22:05 +0000525 return PyByteArray_FromStringAndSize(ptr, view->itemsize);
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000526 }
527 else {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000528 /* Return a new memory-view object */
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000529 Py_buffer newview;
Neal Norwitzb35f1282007-10-07 19:26:50 +0000530 memset(&newview, 0, sizeof(newview));
Antoine Pitrou2f89aa62008-08-02 21:02:48 +0000531 /* XXX: This needs to be fixed so it
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000532 actually returns a sub-view
533 */
Neal Norwitzb35f1282007-10-07 19:26:50 +0000534 return PyMemoryView_FromMemory(&newview);
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000535 }
536 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000537
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000538 /* Need to support getting a sliced view */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000539 Py_INCREF(Py_NotImplemented);
540 return Py_NotImplemented;
541}
542
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000543
544/* Need to support assigning memory if we can */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000545static int
546memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
547{
548 return 0;
549}
550
551/* As mapping */
552static PyMappingMethods memory_as_mapping = {
553 (lenfunc)memory_length, /*mp_length*/
554 (binaryfunc)memory_subscript, /*mp_subscript*/
555 (objobjargproc)memory_ass_sub, /*mp_ass_subscript*/
556};
557
558
559/* Buffer methods */
560
561static PyBufferProcs memory_as_buffer = {
562 (getbufferproc)memory_getbuf, /* bf_getbuffer */
563 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
564};
565
566
567PyTypeObject PyMemoryView_Type = {
568 PyVarObject_HEAD_INIT(&PyType_Type, 0)
569 "memoryview",
570 sizeof(PyMemoryViewObject),
571 0,
572 (destructor)memory_dealloc, /* tp_dealloc */
573 0, /* tp_print */
574 0, /* tp_getattr */
575 0, /* tp_setattr */
576 0, /* tp_compare */
577 (reprfunc)memory_repr, /* tp_repr */
578 0, /* tp_as_number */
579 0, /* tp_as_sequence */
580 &memory_as_mapping, /* tp_as_mapping */
581 0, /* tp_hash */
582 0, /* tp_call */
583 (reprfunc)memory_str, /* tp_str */
584 PyObject_GenericGetAttr, /* tp_getattro */
585 0, /* tp_setattro */
586 &memory_as_buffer, /* tp_as_buffer */
587 Py_TPFLAGS_DEFAULT, /* tp_flags */
588 memory_doc, /* tp_doc */
589 0, /* tp_traverse */
590 0, /* tp_clear */
591 0, /* tp_richcompare */
592 0, /* tp_weaklistoffset */
593 0, /* tp_iter */
594 0, /* tp_iternext */
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000595 memory_methods, /* tp_methods */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000596 0, /* tp_members */
597 memory_getsetlist, /* tp_getset */
598 0, /* tp_base */
599 0, /* tp_dict */
600 0, /* tp_descr_get */
601 0, /* tp_descr_set */
602 0, /* tp_dictoffset */
603 0, /* tp_init */
604 0, /* tp_alloc */
605 memory_new, /* tp_new */
606};