blob: f0a45f622fd77ca083033550f3fc159ea714c5c8 [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;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000059 if (PyObject_GetBuffer(base, &(mview->view), PyBUF_FULL) < 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{
72 PyObject *obj;
Neal Norwitzfaa54a32007-08-19 04:23:20 +000073 if (!PyArg_UnpackTuple(args, "memoryview", 1, 1, &obj)) return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000074
Guido van Rossum5dde61d2007-09-25 22:10:05 +000075 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000076}
77
78
79static void
Guido van Rossum5dde61d2007-09-25 22:10:05 +000080_strided_copy_nd(char *dest, char *src, int nd, Py_ssize_t *shape,
Neal Norwitz61ec0d32007-10-26 06:44:10 +000081 Py_ssize_t *strides, Py_ssize_t itemsize, char fort)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000082{
83 int k;
84 Py_ssize_t outstride;
85
86 if (nd==0) {
87 memcpy(dest, src, itemsize);
88 }
89 else if (nd == 1) {
90 for (k = 0; k<shape[0]; k++) {
91 memcpy(dest, src, itemsize);
92 dest += itemsize;
93 src += strides[0];
94 }
95 }
96 else {
97 if (fort == 'F') {
Guido van Rossum5dde61d2007-09-25 22:10:05 +000098 /* Copy first dimension first,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000099 second dimension second, etc...
100 Set up the recursive loop backwards so that final
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000101 dimension is actually copied last.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000102 */
103 outstride = itemsize;
104 for (k=1; k<nd-1;k++) {
105 outstride *= shape[k];
106 }
107 for (k=0; k<shape[nd-1]; k++) {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000108 _strided_copy_nd(dest, src, nd-1, shape,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000109 strides, itemsize, fort);
110 dest += outstride;
111 src += strides[nd-1];
112 }
113 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000114
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000115 else {
116 /* Copy last dimension first,
117 second-to-last dimension second, etc.
118 Set up the recursion so that the
119 first dimension is copied last
120 */
121 outstride = itemsize;
122 for (k=1; k < nd; k++) {
123 outstride *= shape[k];
124 }
125 for (k=0; k<shape[0]; k++) {
126 _strided_copy_nd(dest, src, nd-1, shape+1,
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000127 strides+1, itemsize,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000128 fort);
129 dest += outstride;
130 src += strides[0];
131 }
132 }
133 }
134 return;
135}
136
137void _add_one_to_index_F(int nd, Py_ssize_t *index, Py_ssize_t *shape);
138void _add_one_to_index_C(int nd, Py_ssize_t *index, Py_ssize_t *shape);
139
140static int
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000141_indirect_copy_nd(char *dest, Py_buffer *view, char fort)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000142{
143 Py_ssize_t *indices;
144 int k;
145 Py_ssize_t elements;
146 char *ptr;
147 void (*func)(int, Py_ssize_t *, Py_ssize_t *);
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000148
149
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000150 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000151 indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view->ndim);
152 if (indices == NULL) {
153 PyErr_NoMemory();
154 return -1;
155 }
156 for (k=0; k<view->ndim;k++) {
157 indices[k] = 0;
158 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000159
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000160 elements = 1;
161 for (k=0; k<view->ndim; k++) {
162 elements *= view->shape[k];
163 }
164 if (fort == 'F') {
165 func = _add_one_to_index_F;
166 }
167 else {
168 func = _add_one_to_index_C;
169 }
170 while (elements--) {
171 func(view->ndim, indices, view->shape);
172 ptr = PyBuffer_GetPointer(view, indices);
173 memcpy(dest, ptr, view->itemsize);
174 dest += view->itemsize;
175 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000176
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000177 PyMem_Free(indices);
178 return 0;
179}
180
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000181/*
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000182 Get a the data from an object as a contiguous chunk of memory (in
183 either 'C' or 'F'ortran order) even if it means copying it into a
184 separate memory area.
185
186 Returns a new reference to a Memory view object. If no copy is needed,
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000187 the memory view object points to the original memory and holds a
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000188 lock on the original. If a copy is needed, then the memory view object
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000189 points to a brand-new Bytes object (and holds a memory lock on it).
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000190
191 buffertype
192
193 PyBUF_READ buffer only needs to be read-only
Sean Reifscheider54cf12b2007-09-17 17:55:36 +0000194 PyBUF_WRITE buffer needs to be writable (give error if not contiguous)
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000195 PyBUF_SHADOW buffer needs to be writable so shadow it with
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000196 a contiguous buffer if it is not. The view will point to
197 the shadow buffer which can be written to and then
198 will be copied back into the other buffer when the memory
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000199 view is de-allocated. While the shadow buffer is
200 being used, it will have an exclusive write lock on
201 the original buffer.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000202 */
203
204PyObject *
205PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
206{
207 PyMemoryViewObject *mem;
208 PyObject *bytes;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000209 Py_buffer *view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000210 int flags;
211 char *dest;
212
213 if (!PyObject_CheckBuffer(obj)) {
214 PyErr_SetString(PyExc_TypeError,
215 "object does not have the buffer interface");
216 return NULL;
217 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000218
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000219 mem = PyObject_New(PyMemoryViewObject, &PyMemoryView_Type);
220 if (mem == NULL) return NULL;
221
222 view = &PyMemoryView(mem);
223 flags = PyBUF_FULL_RO;
224 switch(buffertype) {
225 case PyBUF_WRITE:
226 flags = PyBUF_FULL;
227 break;
228 case PyBUF_SHADOW:
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000229 flags = PyBUF_FULL_XLCK;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000230 break;
231 }
232
233 if (PyObject_GetBuffer(obj, view, flags) != 0) {
234 PyObject_DEL(mem);
235 return NULL;
236 }
237
238 if (PyBuffer_IsContiguous(view, fort)) {
239 /* no copy needed */
240 Py_INCREF(obj);
241 mem->base = obj;
242 return (PyObject *)mem;
243 }
244 /* otherwise a copy is needed */
245 if (buffertype == PyBUF_WRITE) {
246 PyObject_DEL(mem);
247 PyErr_SetString(PyExc_BufferError,
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000248 "writable contiguous buffer requested "
249 "for a non-contiguousobject.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000250 return NULL;
251 }
252 bytes = PyBytes_FromStringAndSize(NULL, view->len);
253 if (bytes == NULL) {
254 PyObject_ReleaseBuffer(obj, view);
255 return NULL;
256 }
257 dest = PyBytes_AS_STRING(bytes);
258 /* different copying strategy depending on whether
259 or not any pointer de-referencing is needed
260 */
261 /* strided or in-direct copy */
262 if (view->suboffsets==NULL) {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000263 _strided_copy_nd(dest, view->buf, view->ndim, view->shape,
264 view->strides, view->itemsize, fort);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000265 }
266 else {
267 if (_indirect_copy_nd(dest, view, fort) < 0) {
268 Py_DECREF(bytes);
269 PyObject_ReleaseBuffer(obj, view);
270 return NULL;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000271 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000272 }
273 if (buffertype == PyBUF_SHADOW) {
274 /* return a shadowed memory-view object */
275 view->buf = dest;
276 mem->base = PyTuple_Pack(2, obj, bytes);
277 Py_DECREF(bytes);
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000278 if (mem->base == NULL) {
279 PyObject_ReleaseBuffer(obj, view);
280 return NULL;
281 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000282 }
283 else {
284 PyObject_ReleaseBuffer(obj, view);
285 /* steal the reference */
286 mem->base = bytes;
287 }
288 return (PyObject *)mem;
289}
290
291
292static PyObject *
293memory_format_get(PyMemoryViewObject *self)
294{
295 return PyUnicode_FromString(self->view.format);
296}
297
298static PyObject *
299memory_itemsize_get(PyMemoryViewObject *self)
300{
Neal Norwitz61ec0d32007-10-26 06:44:10 +0000301 return PyInt_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000302}
303
304static PyObject *
305_IntTupleFromSsizet(int len, Py_ssize_t *vals)
306{
307 int i;
308 PyObject *o;
309 PyObject *intTuple;
310
311 if (vals == NULL) {
312 Py_INCREF(Py_None);
313 return Py_None;
314 }
315 intTuple = PyTuple_New(len);
316 if (!intTuple) return NULL;
317 for(i=0; i<len; i++) {
318 o = PyInt_FromSsize_t(vals[i]);
319 if (!o) {
320 Py_DECREF(intTuple);
321 return NULL;
322 }
323 PyTuple_SET_ITEM(intTuple, i, o);
324 }
325 return intTuple;
326}
327
328static PyObject *
329memory_shape_get(PyMemoryViewObject *self)
330{
331 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
332}
333
334static PyObject *
335memory_strides_get(PyMemoryViewObject *self)
336{
337 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
338}
339
340static PyObject *
341memory_suboffsets_get(PyMemoryViewObject *self)
342{
343 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
344}
345
346static PyObject *
347memory_size_get(PyMemoryViewObject *self)
348{
349 return PyInt_FromSsize_t(self->view.len);
350}
351
352static PyObject *
353memory_readonly_get(PyMemoryViewObject *self)
354{
Neal Norwitz666bb412007-08-19 18:38:46 +0000355 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000356}
357
358static PyObject *
359memory_ndim_get(PyMemoryViewObject *self)
360{
361 return PyInt_FromLong(self->view.ndim);
362}
363
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000364static PyGetSetDef memory_getsetlist[] ={
Neal Norwitz666bb412007-08-19 18:38:46 +0000365 {"format", (getter)memory_format_get, NULL, NULL},
366 {"itemsize", (getter)memory_itemsize_get, NULL, NULL},
367 {"shape", (getter)memory_shape_get, NULL, NULL},
368 {"strides", (getter)memory_strides_get, NULL, NULL},
369 {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL},
370 {"size", (getter)memory_size_get, NULL, NULL},
371 {"readonly", (getter)memory_readonly_get, NULL, NULL},
372 {"ndim", (getter)memory_ndim_get, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000373 {NULL, NULL, NULL, NULL},
374};
375
376
377static PyObject *
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000378memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000379{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000380 return PyBytes_FromObject((PyObject *)mem);
381}
382
383static PyObject *
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000384memory_tolist(PyMemoryViewObject *mem, PyObject *noargs)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000385{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000386 /* This should construct a (nested) list of unpacked objects
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000387 possibly using the struct module.
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000388 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000389 Py_INCREF(Py_NotImplemented);
390 return Py_NotImplemented;
391}
392
393
394
395static PyMethodDef memory_methods[] = {
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000396 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL},
397 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000398 {NULL, NULL} /* sentinel */
399};
400
401
402static void
403memory_dealloc(PyMemoryViewObject *self)
404{
Neal Norwitz666bb412007-08-19 18:38:46 +0000405 if (self->base != NULL) {
406 if (PyTuple_Check(self->base)) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000407 /* Special case when first element is generic object
408 with buffer interface and the second element is a
409 contiguous "shadow" that must be copied back into
410 the data areay of the first tuple element before
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000411 releasing the buffer on the first element.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000412 */
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000413
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000414 PyObject_CopyData(PyTuple_GET_ITEM(self->base,0),
415 PyTuple_GET_ITEM(self->base,1));
416
417 /* The view member should have readonly == -1 in
418 this instance indicating that the memory can
419 be "locked" and was locked and will be unlocked
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000420 again after this call.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000421 */
422 PyObject_ReleaseBuffer(PyTuple_GET_ITEM(self->base,0),
423 &(self->view));
Neal Norwitz666bb412007-08-19 18:38:46 +0000424 }
425 else {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000426 PyObject_ReleaseBuffer(self->base, &(self->view));
Neal Norwitz666bb412007-08-19 18:38:46 +0000427 }
428 Py_CLEAR(self->base);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000429 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000430 PyObject_DEL(self);
431}
432
433static PyObject *
434memory_repr(PyMemoryViewObject *self)
435{
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000436 return PyUnicode_FromFormat("<memory at %p>", self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000437}
438
439
440static PyObject *
441memory_str(PyMemoryViewObject *self)
442{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000443 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000444 PyObject *res;
445
446 if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
447 return NULL;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000448
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000449 res = PyBytes_FromStringAndSize(NULL, view.len);
450 PyBuffer_ToContiguous(PyBytes_AS_STRING(res), &view, view.len, 'C');
451 PyObject_ReleaseBuffer((PyObject *)self, &view);
452 return res;
453}
454
455/* Sequence methods */
456
457static Py_ssize_t
458memory_length(PyMemoryViewObject *self)
459{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000460 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000461
462 if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
463 return -1;
464 PyObject_ReleaseBuffer((PyObject *)self, &view);
465 return view.len;
466}
467
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000468/*
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000469 mem[obj] returns a bytes object holding the data for one element if
470 obj fully indexes the memory view or another memory-view object
471 if it does not.
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000472
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000473 0-d memory-view objects can be referenced using ... or () but
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000474 not with anything else.
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000475 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000476static PyObject *
477memory_subscript(PyMemoryViewObject *self, PyObject *key)
478{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000479 Py_buffer *view;
480 view = &(self->view);
481
482 if (view->ndim == 0) {
483 if (key == Py_Ellipsis ||
484 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
485 Py_INCREF(self);
486 return (PyObject *)self;
487 }
488 else {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000489 PyErr_SetString(PyExc_IndexError,
490 "invalid indexing of 0-dim memory");
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000491 return NULL;
492 }
493 }
494 if (PyIndex_Check(key)) {
495 Py_ssize_t result;
496 result = PyNumber_AsSsize_t(key, NULL);
497 if (result == -1 && PyErr_Occurred())
498 return NULL;
499 if (view->ndim == 1) {
500 /* Return a bytes object */
501 char *ptr;
502 ptr = (char *)view->buf;
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000503 if (result < 0) {
504 result += view->shape[0];
505 }
506 if ((result < 0) || (result > view->shape[0])) {
507 PyErr_SetString(PyExc_IndexError,
508 "index out of bounds");
509 return NULL;
510 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000511 if (view->strides == NULL)
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000512 ptr += view->itemsize * result;
513 else
514 ptr += view->strides[0] * result;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000515 if (view->suboffsets != NULL &&
516 view->suboffsets[0] >= 0)
517 {
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000518 ptr = *((char **)ptr) + view->suboffsets[0];
519 }
520 return PyBytes_FromStringAndSize(ptr, view->itemsize);
521 }
522 else {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000523 /* Return a new memory-view object */
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000524 Py_buffer newview;
Neal Norwitzb35f1282007-10-07 19:26:50 +0000525 memset(&newview, 0, sizeof(newview));
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000526 /* XXX: This needs to be fixed so it
527 actually returns a sub-view
528 */
Neal Norwitzb35f1282007-10-07 19:26:50 +0000529 return PyMemoryView_FromMemory(&newview);
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000530 }
531 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000532
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000533 /* Need to support getting a sliced view */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000534 Py_INCREF(Py_NotImplemented);
535 return Py_NotImplemented;
536}
537
Travis E. Oliphantfe9bed02007-10-12 23:27:53 +0000538
539/* Need to support assigning memory if we can */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000540static int
541memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
542{
543 return 0;
544}
545
546/* As mapping */
547static PyMappingMethods memory_as_mapping = {
548 (lenfunc)memory_length, /*mp_length*/
549 (binaryfunc)memory_subscript, /*mp_subscript*/
550 (objobjargproc)memory_ass_sub, /*mp_ass_subscript*/
551};
552
553
554/* Buffer methods */
555
556static PyBufferProcs memory_as_buffer = {
557 (getbufferproc)memory_getbuf, /* bf_getbuffer */
558 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
559};
560
561
562PyTypeObject PyMemoryView_Type = {
563 PyVarObject_HEAD_INIT(&PyType_Type, 0)
564 "memoryview",
565 sizeof(PyMemoryViewObject),
566 0,
567 (destructor)memory_dealloc, /* tp_dealloc */
568 0, /* tp_print */
569 0, /* tp_getattr */
570 0, /* tp_setattr */
571 0, /* tp_compare */
572 (reprfunc)memory_repr, /* tp_repr */
573 0, /* tp_as_number */
574 0, /* tp_as_sequence */
575 &memory_as_mapping, /* tp_as_mapping */
576 0, /* tp_hash */
577 0, /* tp_call */
578 (reprfunc)memory_str, /* tp_str */
579 PyObject_GenericGetAttr, /* tp_getattro */
580 0, /* tp_setattro */
581 &memory_as_buffer, /* tp_as_buffer */
582 Py_TPFLAGS_DEFAULT, /* tp_flags */
583 memory_doc, /* tp_doc */
584 0, /* tp_traverse */
585 0, /* tp_clear */
586 0, /* tp_richcompare */
587 0, /* tp_weaklistoffset */
588 0, /* tp_iter */
589 0, /* tp_iternext */
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000590 memory_methods, /* tp_methods */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000591 0, /* tp_members */
592 memory_getsetlist, /* tp_getset */
593 0, /* tp_base */
594 0, /* tp_dict */
595 0, /* tp_descr_get */
596 0, /* tp_descr_set */
597 0, /* tp_dictoffset */
598 0, /* tp_init */
599 0, /* tp_alloc */
600 memory_new, /* tp_new */
601};