blob: f2f7505f7f70917c135e2695aa17b59c34ea9eb1 [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,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000081 Py_ssize_t *strides, int itemsize, char fort)
82{
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
199 view is de-allocated.
200 */
201
202PyObject *
203PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
204{
205 PyMemoryViewObject *mem;
206 PyObject *bytes;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000207 Py_buffer *view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000208 int flags;
209 char *dest;
210
211 if (!PyObject_CheckBuffer(obj)) {
212 PyErr_SetString(PyExc_TypeError,
213 "object does not have the buffer interface");
214 return NULL;
215 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000216
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000217 mem = PyObject_New(PyMemoryViewObject, &PyMemoryView_Type);
218 if (mem == NULL) return NULL;
219
220 view = &PyMemoryView(mem);
221 flags = PyBUF_FULL_RO;
222 switch(buffertype) {
223 case PyBUF_WRITE:
224 flags = PyBUF_FULL;
225 break;
226 case PyBUF_SHADOW:
227 flags = PyBUF_FULL_LCK;
228 break;
229 }
230
231 if (PyObject_GetBuffer(obj, view, flags) != 0) {
232 PyObject_DEL(mem);
233 return NULL;
234 }
235
236 if (PyBuffer_IsContiguous(view, fort)) {
237 /* no copy needed */
238 Py_INCREF(obj);
239 mem->base = obj;
240 return (PyObject *)mem;
241 }
242 /* otherwise a copy is needed */
243 if (buffertype == PyBUF_WRITE) {
244 PyObject_DEL(mem);
245 PyErr_SetString(PyExc_BufferError,
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000246 "writable contiguous buffer requested "
247 "for a non-contiguousobject.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000248 return NULL;
249 }
250 bytes = PyBytes_FromStringAndSize(NULL, view->len);
251 if (bytes == NULL) {
252 PyObject_ReleaseBuffer(obj, view);
253 return NULL;
254 }
255 dest = PyBytes_AS_STRING(bytes);
256 /* different copying strategy depending on whether
257 or not any pointer de-referencing is needed
258 */
259 /* strided or in-direct copy */
260 if (view->suboffsets==NULL) {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000261 _strided_copy_nd(dest, view->buf, view->ndim, view->shape,
262 view->strides, view->itemsize, fort);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000263 }
264 else {
265 if (_indirect_copy_nd(dest, view, fort) < 0) {
266 Py_DECREF(bytes);
267 PyObject_ReleaseBuffer(obj, view);
268 return NULL;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000269 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000270 }
271 if (buffertype == PyBUF_SHADOW) {
272 /* return a shadowed memory-view object */
273 view->buf = dest;
274 mem->base = PyTuple_Pack(2, obj, bytes);
275 Py_DECREF(bytes);
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000276 if (mem->base == NULL) {
277 PyObject_ReleaseBuffer(obj, view);
278 return NULL;
279 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000280 }
281 else {
282 PyObject_ReleaseBuffer(obj, view);
283 /* steal the reference */
284 mem->base = bytes;
285 }
286 return (PyObject *)mem;
287}
288
289
290static PyObject *
291memory_format_get(PyMemoryViewObject *self)
292{
293 return PyUnicode_FromString(self->view.format);
294}
295
296static PyObject *
297memory_itemsize_get(PyMemoryViewObject *self)
298{
299 return PyInt_FromLong(self->view.itemsize);
300}
301
302static PyObject *
303_IntTupleFromSsizet(int len, Py_ssize_t *vals)
304{
305 int i;
306 PyObject *o;
307 PyObject *intTuple;
308
309 if (vals == NULL) {
310 Py_INCREF(Py_None);
311 return Py_None;
312 }
313 intTuple = PyTuple_New(len);
314 if (!intTuple) return NULL;
315 for(i=0; i<len; i++) {
316 o = PyInt_FromSsize_t(vals[i]);
317 if (!o) {
318 Py_DECREF(intTuple);
319 return NULL;
320 }
321 PyTuple_SET_ITEM(intTuple, i, o);
322 }
323 return intTuple;
324}
325
326static PyObject *
327memory_shape_get(PyMemoryViewObject *self)
328{
329 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
330}
331
332static PyObject *
333memory_strides_get(PyMemoryViewObject *self)
334{
335 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
336}
337
338static PyObject *
339memory_suboffsets_get(PyMemoryViewObject *self)
340{
341 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
342}
343
344static PyObject *
345memory_size_get(PyMemoryViewObject *self)
346{
347 return PyInt_FromSsize_t(self->view.len);
348}
349
350static PyObject *
351memory_readonly_get(PyMemoryViewObject *self)
352{
Neal Norwitz666bb412007-08-19 18:38:46 +0000353 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000354}
355
356static PyObject *
357memory_ndim_get(PyMemoryViewObject *self)
358{
359 return PyInt_FromLong(self->view.ndim);
360}
361
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000362static PyGetSetDef memory_getsetlist[] ={
Neal Norwitz666bb412007-08-19 18:38:46 +0000363 {"format", (getter)memory_format_get, NULL, NULL},
364 {"itemsize", (getter)memory_itemsize_get, NULL, NULL},
365 {"shape", (getter)memory_shape_get, NULL, NULL},
366 {"strides", (getter)memory_strides_get, NULL, NULL},
367 {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL},
368 {"size", (getter)memory_size_get, NULL, NULL},
369 {"readonly", (getter)memory_readonly_get, NULL, NULL},
370 {"ndim", (getter)memory_ndim_get, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000371 {NULL, NULL, NULL, NULL},
372};
373
374
375static PyObject *
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000376memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000377{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000378 return PyBytes_FromObject((PyObject *)mem);
379}
380
381static PyObject *
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000382memory_tolist(PyMemoryViewObject *mem, PyObject *noargs)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000383{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000384 /* This should construct a (nested) list of unpacked objects
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000385 possibly using the struct module.
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000386 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000387 Py_INCREF(Py_NotImplemented);
388 return Py_NotImplemented;
389}
390
391
392
393static PyMethodDef memory_methods[] = {
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000394 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL},
395 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000396 {NULL, NULL} /* sentinel */
397};
398
399
400static void
401memory_dealloc(PyMemoryViewObject *self)
402{
Neal Norwitz666bb412007-08-19 18:38:46 +0000403 if (self->base != NULL) {
404 if (PyTuple_Check(self->base)) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000405 /* Special case when first element is generic object
406 with buffer interface and the second element is a
407 contiguous "shadow" that must be copied back into
408 the data areay of the first tuple element before
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000409 releasing the buffer on the first element.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000410 */
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000411
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000412 PyObject_CopyData(PyTuple_GET_ITEM(self->base,0),
413 PyTuple_GET_ITEM(self->base,1));
414
415 /* The view member should have readonly == -1 in
416 this instance indicating that the memory can
417 be "locked" and was locked and will be unlocked
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000418 again after this call.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000419 */
420 PyObject_ReleaseBuffer(PyTuple_GET_ITEM(self->base,0),
421 &(self->view));
Neal Norwitz666bb412007-08-19 18:38:46 +0000422 }
423 else {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000424 PyObject_ReleaseBuffer(self->base, &(self->view));
Neal Norwitz666bb412007-08-19 18:38:46 +0000425 }
426 Py_CLEAR(self->base);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000427 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000428 PyObject_DEL(self);
429}
430
431static PyObject *
432memory_repr(PyMemoryViewObject *self)
433{
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000434 /* XXX(nnorwitz): the code should be different or remove condition. */
435 if (self->base == NULL)
436 return PyUnicode_FromFormat("<memory at %p>", self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000437 else
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000438 return PyUnicode_FromFormat("<memory at %p>", self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000439}
440
441
442static PyObject *
443memory_str(PyMemoryViewObject *self)
444{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000445 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000446 PyObject *res;
447
448 if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
449 return NULL;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000450
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000451 res = PyBytes_FromStringAndSize(NULL, view.len);
452 PyBuffer_ToContiguous(PyBytes_AS_STRING(res), &view, view.len, 'C');
453 PyObject_ReleaseBuffer((PyObject *)self, &view);
454 return res;
455}
456
457/* Sequence methods */
458
459static Py_ssize_t
460memory_length(PyMemoryViewObject *self)
461{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000462 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000463
464 if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
465 return -1;
466 PyObject_ReleaseBuffer((PyObject *)self, &view);
467 return view.len;
468}
469
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000470/*
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000471 mem[obj] returns a bytes object holding the data for one element if
472 obj fully indexes the memory view or another memory-view object
473 if it does not.
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000474
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000475 0-d memory-view objects can be referenced using ... or () but
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000476 not with anything else.
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000477 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000478static PyObject *
479memory_subscript(PyMemoryViewObject *self, PyObject *key)
480{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000481 Py_buffer *view;
482 view = &(self->view);
483
484 if (view->ndim == 0) {
485 if (key == Py_Ellipsis ||
486 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
487 Py_INCREF(self);
488 return (PyObject *)self;
489 }
490 else {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000491 PyErr_SetString(PyExc_IndexError,
492 "invalid indexing of 0-dim memory");
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000493 return NULL;
494 }
495 }
496 if (PyIndex_Check(key)) {
497 Py_ssize_t result;
498 result = PyNumber_AsSsize_t(key, NULL);
499 if (result == -1 && PyErr_Occurred())
500 return NULL;
501 if (view->ndim == 1) {
502 /* Return a bytes object */
503 char *ptr;
504 ptr = (char *)view->buf;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000505 if (view->strides == NULL)
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000506 ptr += view->itemsize * result;
507 else
508 ptr += view->strides[0] * result;
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000509 if (view->suboffsets != NULL &&
510 view->suboffsets[0] >= 0)
511 {
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000512 ptr = *((char **)ptr) + view->suboffsets[0];
513 }
514 return PyBytes_FromStringAndSize(ptr, view->itemsize);
515 }
516 else {
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000517 /* Return a new memory-view object */
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000518 Py_buffer newview;
Neal Norwitzb35f1282007-10-07 19:26:50 +0000519 memset(&newview, 0, sizeof(newview));
520 return PyMemoryView_FromMemory(&newview);
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000521 }
522 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000523
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000524 Py_INCREF(Py_NotImplemented);
525 return Py_NotImplemented;
526}
527
528static int
529memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
530{
531 return 0;
532}
533
534/* As mapping */
535static PyMappingMethods memory_as_mapping = {
536 (lenfunc)memory_length, /*mp_length*/
537 (binaryfunc)memory_subscript, /*mp_subscript*/
538 (objobjargproc)memory_ass_sub, /*mp_ass_subscript*/
539};
540
541
542/* Buffer methods */
543
544static PyBufferProcs memory_as_buffer = {
545 (getbufferproc)memory_getbuf, /* bf_getbuffer */
546 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
547};
548
549
550PyTypeObject PyMemoryView_Type = {
551 PyVarObject_HEAD_INIT(&PyType_Type, 0)
552 "memoryview",
553 sizeof(PyMemoryViewObject),
554 0,
555 (destructor)memory_dealloc, /* tp_dealloc */
556 0, /* tp_print */
557 0, /* tp_getattr */
558 0, /* tp_setattr */
559 0, /* tp_compare */
560 (reprfunc)memory_repr, /* tp_repr */
561 0, /* tp_as_number */
562 0, /* tp_as_sequence */
563 &memory_as_mapping, /* tp_as_mapping */
564 0, /* tp_hash */
565 0, /* tp_call */
566 (reprfunc)memory_str, /* tp_str */
567 PyObject_GenericGetAttr, /* tp_getattro */
568 0, /* tp_setattro */
569 &memory_as_buffer, /* tp_as_buffer */
570 Py_TPFLAGS_DEFAULT, /* tp_flags */
571 memory_doc, /* tp_doc */
572 0, /* tp_traverse */
573 0, /* tp_clear */
574 0, /* tp_richcompare */
575 0, /* tp_weaklistoffset */
576 0, /* tp_iter */
577 0, /* tp_iternext */
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000578 memory_methods, /* tp_methods */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000579 0, /* tp_members */
580 memory_getsetlist, /* tp_getset */
581 0, /* tp_base */
582 0, /* tp_dict */
583 0, /* tp_descr_get */
584 0, /* tp_descr_set */
585 0, /* tp_dictoffset */
586 0, /* tp_init */
587 0, /* tp_alloc */
588 memory_new, /* tp_new */
589};