blob: 46a8416712689c99589e926df66bccf568cbe6e2 [file] [log] [blame]
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001/* Memoryview object implementation */
2
3#include "Python.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00005
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00006
Stefan Krah9a2d99e2012-02-25 12:24:21 +01007/****************************************************************************/
8/* ManagedBuffer Object */
9/****************************************************************************/
10
11/*
12 ManagedBuffer Object:
13 ---------------------
14
15 The purpose of this object is to facilitate the handling of chained
16 memoryviews that have the same underlying exporting object. PEP-3118
17 allows the underlying object to change while a view is exported. This
18 could lead to unexpected results when constructing a new memoryview
19 from an existing memoryview.
20
21 Rather than repeatedly redirecting buffer requests to the original base
22 object, all chained memoryviews use a single buffer snapshot. This
23 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
24
25 Ownership rules:
26 ----------------
27
28 The master buffer inside a managed buffer is filled in by the original
29 base object. shape, strides, suboffsets and format are read-only for
30 all consumers.
31
32 A memoryview's buffer is a private copy of the exporter's buffer. shape,
33 strides and suboffsets belong to the memoryview and are thus writable.
34
35 If a memoryview itself exports several buffers via memory_getbuf(), all
36 buffer copies share shape, strides and suboffsets. In this case, the
37 arrays are NOT writable.
38
39 Reference count assumptions:
40 ----------------------------
41
42 The 'obj' member of a Py_buffer must either be NULL or refer to the
43 exporting base object. In the Python codebase, all getbufferprocs
44 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
45
46 PyBuffer_Release() decrements view.obj (if non-NULL), so the
47 releasebufferprocs must NOT decrement view.obj.
48*/
49
50
51#define XSTRINGIZE(v) #v
52#define STRINGIZE(v) XSTRINGIZE(v)
53
54#define CHECK_MBUF_RELEASED(mbuf) \
55 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
56 PyErr_SetString(PyExc_ValueError, \
57 "operation forbidden on released memoryview object"); \
58 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000059 }
60
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000061
Stefan Krah9a2d99e2012-02-25 12:24:21 +010062Py_LOCAL_INLINE(_PyManagedBufferObject *)
63mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000064{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010065 _PyManagedBufferObject *mbuf;
66
67 mbuf = (_PyManagedBufferObject *)
68 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
69 if (mbuf == NULL)
70 return NULL;
71 mbuf->flags = 0;
72 mbuf->exports = 0;
73 mbuf->master.obj = NULL;
74 _PyObject_GC_TRACK(mbuf);
75
76 return mbuf;
77}
78
79static PyObject *
80_PyManagedBuffer_FromObject(PyObject *base)
81{
82 _PyManagedBufferObject *mbuf;
83
84 mbuf = mbuf_alloc();
85 if (mbuf == NULL)
86 return NULL;
87
88 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +010089 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +010090 Py_DECREF(mbuf);
91 return NULL;
92 }
93
Stefan Krah9a2d99e2012-02-25 12:24:21 +010094 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +000095}
96
97static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +010098mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +000099{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100100 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
101 return;
102
103 /* NOTE: at this point self->exports can still be > 0 if this function
104 is called from mbuf_clear() to break up a reference cycle. */
105 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
106
107 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
108 _PyObject_GC_UNTRACK(self);
109 PyBuffer_Release(&self->master);
110}
111
112static void
113mbuf_dealloc(_PyManagedBufferObject *self)
114{
115 assert(self->exports == 0);
116 mbuf_release(self);
117 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
118 PyMem_Free(self->master.format);
119 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000120}
121
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000122static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100123mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000124{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100125 Py_VISIT(self->master.obj);
126 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000127}
128
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100129static int
130mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000131{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100132 assert(self->exports >= 0);
133 mbuf_release(self);
134 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000135}
136
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100137PyTypeObject _PyManagedBuffer_Type = {
138 PyVarObject_HEAD_INIT(&PyType_Type, 0)
139 "managedbuffer",
140 sizeof(_PyManagedBufferObject),
141 0,
142 (destructor)mbuf_dealloc, /* tp_dealloc */
143 0, /* tp_print */
144 0, /* tp_getattr */
145 0, /* tp_setattr */
146 0, /* tp_reserved */
147 0, /* tp_repr */
148 0, /* tp_as_number */
149 0, /* tp_as_sequence */
150 0, /* tp_as_mapping */
151 0, /* tp_hash */
152 0, /* tp_call */
153 0, /* tp_str */
154 PyObject_GenericGetAttr, /* tp_getattro */
155 0, /* tp_setattro */
156 0, /* tp_as_buffer */
157 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
158 0, /* tp_doc */
159 (traverseproc)mbuf_traverse, /* tp_traverse */
160 (inquiry)mbuf_clear /* tp_clear */
161};
162
163
164/****************************************************************************/
165/* MemoryView Object */
166/****************************************************************************/
167
168/* In the process of breaking reference cycles mbuf_release() can be
169 called before memory_release(). */
170#define BASE_INACCESSIBLE(mv) \
171 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
172 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
173
174#define CHECK_RELEASED(mv) \
175 if (BASE_INACCESSIBLE(mv)) { \
176 PyErr_SetString(PyExc_ValueError, \
177 "operation forbidden on released memoryview object"); \
178 return NULL; \
179 }
180
181#define CHECK_RELEASED_INT(mv) \
182 if (BASE_INACCESSIBLE(mv)) { \
183 PyErr_SetString(PyExc_ValueError, \
184 "operation forbidden on released memoryview object"); \
185 return -1; \
186 }
187
188#define CHECK_LIST_OR_TUPLE(v) \
189 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
190 PyErr_SetString(PyExc_TypeError, \
191 #v " must be a list or a tuple"); \
192 return NULL; \
193 }
194
195#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
196
197/* Check for the presence of suboffsets in the first dimension. */
198#define HAVE_PTR(suboffsets) (suboffsets && suboffsets[0] >= 0)
199/* Adjust ptr if suboffsets are present. */
200#define ADJUST_PTR(ptr, suboffsets) \
201 (HAVE_PTR(suboffsets) ? *((char**)ptr) + suboffsets[0] : ptr)
202
203/* Memoryview buffer properties */
204#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
205#define MV_F_CONTIGUOUS(flags) \
206 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
207#define MV_ANY_CONTIGUOUS(flags) \
208 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
209
210/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
211#define MV_CONTIGUOUS_NDIM1(view) \
212 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
213
214/* getbuffer() requests */
215#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
216#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
217#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
218#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
219#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
220#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
221#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
222#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
223
224
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000225PyDoc_STRVAR(memory_doc,
226"memoryview(object)\n\
227\n\
228Create a new memoryview object which references the given object.");
229
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100230
231/**************************************************************************/
232/* Copy memoryview buffers */
233/**************************************************************************/
234
235/* The functions in this section take a source and a destination buffer
236 with the same logical structure: format, itemsize, ndim and shape
237 are identical, with ndim > 0.
238
239 NOTE: All buffers are assumed to have PyBUF_FULL information, which
240 is the case for memoryviews! */
241
242
243/* Assumptions: ndim >= 1. The macro tests for a corner case that should
244 perhaps be explicitly forbidden in the PEP. */
245#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
246 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
247
248Py_LOCAL_INLINE(int)
249last_dim_is_contiguous(Py_buffer *dest, Py_buffer *src)
250{
251 assert(dest->ndim > 0 && src->ndim > 0);
252 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
253 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
254 dest->strides[dest->ndim-1] == dest->itemsize &&
255 src->strides[src->ndim-1] == src->itemsize);
256}
257
258/* Check that the logical structure of the destination and source buffers
259 is identical. */
260static int
261cmp_structure(Py_buffer *dest, Py_buffer *src)
262{
263 const char *dfmt, *sfmt;
264 int i;
265
266 assert(dest->format && src->format);
267 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
268 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
269
270 if (strcmp(dfmt, sfmt) != 0 ||
271 dest->itemsize != src->itemsize ||
272 dest->ndim != src->ndim) {
273 goto value_error;
274 }
275
276 for (i = 0; i < dest->ndim; i++) {
277 if (dest->shape[i] != src->shape[i])
278 goto value_error;
279 if (dest->shape[i] == 0)
280 break;
281 }
282
283 return 0;
284
285value_error:
286 PyErr_SetString(PyExc_ValueError,
287 "ndarray assignment: lvalue and rvalue have different structures");
288 return -1;
289}
290
291/* Base case for recursive multi-dimensional copying. Contiguous arrays are
292 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
293 sizeof(mem) == shape[0] * itemsize. */
294static void
295copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
296 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
297 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
298 char *mem)
299{
300 if (mem == NULL) { /* contiguous */
301 Py_ssize_t size = shape[0] * itemsize;
302 if (dptr + size < sptr || sptr + size < dptr)
303 memcpy(dptr, sptr, size); /* no overlapping */
304 else
305 memmove(dptr, sptr, size);
306 }
307 else {
308 char *p;
309 Py_ssize_t i;
310 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
311 char *xsptr = ADJUST_PTR(sptr, ssuboffsets);
312 memcpy(p, xsptr, itemsize);
313 }
314 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
315 char *xdptr = ADJUST_PTR(dptr, dsuboffsets);
316 memcpy(xdptr, p, itemsize);
317 }
318 }
319
320}
321
322/* Recursively copy a source buffer to a destination buffer. The two buffers
323 have the same ndim, shape and itemsize. */
324static void
325copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
326 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
327 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
328 char *mem)
329{
330 Py_ssize_t i;
331
332 assert(ndim >= 1);
333
334 if (ndim == 1) {
335 copy_base(shape, itemsize,
336 dptr, dstrides, dsuboffsets,
337 sptr, sstrides, ssuboffsets,
338 mem);
339 return;
340 }
341
342 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
343 char *xdptr = ADJUST_PTR(dptr, dsuboffsets);
344 char *xsptr = ADJUST_PTR(sptr, ssuboffsets);
345
346 copy_rec(shape+1, ndim-1, itemsize,
347 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
348 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
349 mem);
350 }
351}
352
353/* Faster copying of one-dimensional arrays. */
354static int
355copy_single(Py_buffer *dest, Py_buffer *src)
356{
357 char *mem = NULL;
358
359 assert(dest->ndim == 1);
360
361 if (cmp_structure(dest, src) < 0)
362 return -1;
363
364 if (!last_dim_is_contiguous(dest, src)) {
365 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
366 if (mem == NULL) {
367 PyErr_NoMemory();
368 return -1;
369 }
370 }
371
372 copy_base(dest->shape, dest->itemsize,
373 dest->buf, dest->strides, dest->suboffsets,
374 src->buf, src->strides, src->suboffsets,
375 mem);
376
377 if (mem)
378 PyMem_Free(mem);
379
380 return 0;
381}
382
383/* Recursively copy src to dest. Both buffers must have the same basic
384 structure. Copying is atomic, the function never fails with a partial
385 copy. */
386static int
387copy_buffer(Py_buffer *dest, Py_buffer *src)
388{
389 char *mem = NULL;
390
391 assert(dest->ndim > 0);
392
393 if (cmp_structure(dest, src) < 0)
394 return -1;
395
396 if (!last_dim_is_contiguous(dest, src)) {
397 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
398 if (mem == NULL) {
399 PyErr_NoMemory();
400 return -1;
401 }
402 }
403
404 copy_rec(dest->shape, dest->ndim, dest->itemsize,
405 dest->buf, dest->strides, dest->suboffsets,
406 src->buf, src->strides, src->suboffsets,
407 mem);
408
409 if (mem)
410 PyMem_Free(mem);
411
412 return 0;
413}
414
415/* Initialize strides for a C-contiguous array. */
416Py_LOCAL_INLINE(void)
417init_strides_from_shape(Py_buffer *view)
418{
419 Py_ssize_t i;
420
421 assert(view->ndim > 0);
422
423 view->strides[view->ndim-1] = view->itemsize;
424 for (i = view->ndim-2; i >= 0; i--)
425 view->strides[i] = view->strides[i+1] * view->shape[i+1];
426}
427
428/* Initialize strides for a Fortran-contiguous array. */
429Py_LOCAL_INLINE(void)
430init_fortran_strides_from_shape(Py_buffer *view)
431{
432 Py_ssize_t i;
433
434 assert(view->ndim > 0);
435
436 view->strides[0] = view->itemsize;
437 for (i = 1; i < view->ndim; i++)
438 view->strides[i] = view->strides[i-1] * view->shape[i-1];
439}
440
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200441/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
442 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100443 len(mem) == src->len. */
444static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200445buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100446{
447 Py_buffer dest;
448 Py_ssize_t *strides;
449 int ret;
450
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200451 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100452 assert(src->shape != NULL);
453 assert(src->strides != NULL);
454
455 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
456 if (strides == NULL) {
457 PyErr_NoMemory();
458 return -1;
459 }
460
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200461 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100462 dest = *src;
463 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200464 /* shape is constant and shared: the logical representation of the
465 array is unaltered. */
466
467 /* The physical representation determined by strides (and possibly
468 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100469 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200470 if (order == 'C' || order == 'A') {
471 init_strides_from_shape(&dest);
472 }
473 else {
474 init_fortran_strides_from_shape(&dest);
475 }
476
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100477 dest.suboffsets = NULL;
478
479 ret = copy_buffer(&dest, src);
480
481 PyMem_Free(strides);
482 return ret;
483}
484
485
486/****************************************************************************/
487/* Constructors */
488/****************************************************************************/
489
490/* Initialize values that are shared with the managed buffer. */
491Py_LOCAL_INLINE(void)
492init_shared_values(Py_buffer *dest, const Py_buffer *src)
493{
494 dest->obj = src->obj;
495 dest->buf = src->buf;
496 dest->len = src->len;
497 dest->itemsize = src->itemsize;
498 dest->readonly = src->readonly;
499 dest->format = src->format ? src->format : "B";
500 dest->internal = src->internal;
501}
502
503/* Copy shape and strides. Reconstruct missing values. */
504static void
505init_shape_strides(Py_buffer *dest, const Py_buffer *src)
506{
507 Py_ssize_t i;
508
509 if (src->ndim == 0) {
510 dest->shape = NULL;
511 dest->strides = NULL;
512 return;
513 }
514 if (src->ndim == 1) {
515 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
516 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
517 return;
518 }
519
520 for (i = 0; i < src->ndim; i++)
521 dest->shape[i] = src->shape[i];
522 if (src->strides) {
523 for (i = 0; i < src->ndim; i++)
524 dest->strides[i] = src->strides[i];
525 }
526 else {
527 init_strides_from_shape(dest);
528 }
529}
530
531Py_LOCAL_INLINE(void)
532init_suboffsets(Py_buffer *dest, const Py_buffer *src)
533{
534 Py_ssize_t i;
535
536 if (src->suboffsets == NULL) {
537 dest->suboffsets = NULL;
538 return;
539 }
540 for (i = 0; i < src->ndim; i++)
541 dest->suboffsets[i] = src->suboffsets[i];
542}
543
544/* len = product(shape) * itemsize */
545Py_LOCAL_INLINE(void)
546init_len(Py_buffer *view)
547{
548 Py_ssize_t i, len;
549
550 len = 1;
551 for (i = 0; i < view->ndim; i++)
552 len *= view->shape[i];
553 len *= view->itemsize;
554
555 view->len = len;
556}
557
558/* Initialize memoryview buffer properties. */
559static void
560init_flags(PyMemoryViewObject *mv)
561{
562 const Py_buffer *view = &mv->view;
563 int flags = 0;
564
565 switch (view->ndim) {
566 case 0:
567 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
568 _Py_MEMORYVIEW_FORTRAN);
569 break;
570 case 1:
571 if (MV_CONTIGUOUS_NDIM1(view))
572 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
573 break;
574 default:
575 if (PyBuffer_IsContiguous(view, 'C'))
576 flags |= _Py_MEMORYVIEW_C;
577 if (PyBuffer_IsContiguous(view, 'F'))
578 flags |= _Py_MEMORYVIEW_FORTRAN;
579 break;
580 }
581
582 if (view->suboffsets) {
583 flags |= _Py_MEMORYVIEW_PIL;
584 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
585 }
586
587 mv->flags = flags;
588}
589
590/* Allocate a new memoryview and perform basic initialization. New memoryviews
591 are exclusively created through the mbuf_add functions. */
592Py_LOCAL_INLINE(PyMemoryViewObject *)
593memory_alloc(int ndim)
594{
595 PyMemoryViewObject *mv;
596
597 mv = (PyMemoryViewObject *)
598 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
599 if (mv == NULL)
600 return NULL;
601
602 mv->mbuf = NULL;
603 mv->hash = -1;
604 mv->flags = 0;
605 mv->exports = 0;
606 mv->view.ndim = ndim;
607 mv->view.shape = mv->ob_array;
608 mv->view.strides = mv->ob_array + ndim;
609 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100610 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100611
612 _PyObject_GC_TRACK(mv);
613 return mv;
614}
615
616/*
617 Return a new memoryview that is registered with mbuf. If src is NULL,
618 use mbuf->master as the underlying buffer. Otherwise, use src.
619
620 The new memoryview has full buffer information: shape and strides
621 are always present, suboffsets as needed. Arrays are copied to
622 the memoryview's ob_array field.
623 */
624static PyObject *
625mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
626{
627 PyMemoryViewObject *mv;
628 Py_buffer *dest;
629
630 if (src == NULL)
631 src = &mbuf->master;
632
633 if (src->ndim > PyBUF_MAX_NDIM) {
634 PyErr_SetString(PyExc_ValueError,
635 "memoryview: number of dimensions must not exceed "
636 STRINGIZE(PyBUF_MAX_NDIM));
637 return NULL;
638 }
639
640 mv = memory_alloc(src->ndim);
641 if (mv == NULL)
642 return NULL;
643
644 dest = &mv->view;
645 init_shared_values(dest, src);
646 init_shape_strides(dest, src);
647 init_suboffsets(dest, src);
648 init_flags(mv);
649
650 mv->mbuf = mbuf;
651 Py_INCREF(mbuf);
652 mbuf->exports++;
653
654 return (PyObject *)mv;
655}
656
657/* Register an incomplete view: shape, strides, suboffsets and flags still
658 need to be initialized. Use 'ndim' instead of src->ndim to determine the
659 size of the memoryview's ob_array.
660
661 Assumption: ndim <= PyBUF_MAX_NDIM. */
662static PyObject *
663mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
664 int ndim)
665{
666 PyMemoryViewObject *mv;
667 Py_buffer *dest;
668
669 if (src == NULL)
670 src = &mbuf->master;
671
672 assert(ndim <= PyBUF_MAX_NDIM);
673
674 mv = memory_alloc(ndim);
675 if (mv == NULL)
676 return NULL;
677
678 dest = &mv->view;
679 init_shared_values(dest, src);
680
681 mv->mbuf = mbuf;
682 Py_INCREF(mbuf);
683 mbuf->exports++;
684
685 return (PyObject *)mv;
686}
687
688/* Expose a raw memory area as a view of contiguous bytes. flags can be
689 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
690 The memoryview has complete buffer information. */
691PyObject *
692PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
693{
694 _PyManagedBufferObject *mbuf;
695 PyObject *mv;
696 int readonly;
697
698 assert(mem != NULL);
699 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
700
701 mbuf = mbuf_alloc();
702 if (mbuf == NULL)
703 return NULL;
704
705 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
706 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
707 PyBUF_FULL_RO);
708
709 mv = mbuf_add_view(mbuf, NULL);
710 Py_DECREF(mbuf);
711
712 return mv;
713}
714
715/* Create a memoryview from a given Py_buffer. For simple byte views,
716 PyMemoryView_FromMemory() should be used instead.
717 This function is the only entry point that can create a master buffer
718 without full information. Because of this fact init_shape_strides()
719 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000720PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000721PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000722{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100723 _PyManagedBufferObject *mbuf;
724 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000725
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000726 if (info->buf == NULL) {
727 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100728 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000729 return NULL;
730 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100731
732 mbuf = mbuf_alloc();
733 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000734 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100735
736 /* info->obj is either NULL or a borrowed reference. This reference
737 should not be decremented in PyBuffer_Release(). */
738 mbuf->master = *info;
739 mbuf->master.obj = NULL;
740
741 mv = mbuf_add_view(mbuf, NULL);
742 Py_DECREF(mbuf);
743
744 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000745}
746
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100747/* Create a memoryview from an object that implements the buffer protocol.
748 If the object is a memoryview, the new memoryview must be registered
749 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000750PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100751PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000752{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100753 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000754
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100755 if (PyMemoryView_Check(v)) {
756 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
757 CHECK_RELEASED(mv);
758 return mbuf_add_view(mv->mbuf, &mv->view);
759 }
760 else if (PyObject_CheckBuffer(v)) {
761 PyObject *ret;
762 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
763 if (mbuf == NULL)
764 return NULL;
765 ret = mbuf_add_view(mbuf, NULL);
766 Py_DECREF(mbuf);
767 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000768 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000769
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100770 PyErr_Format(PyExc_TypeError,
771 "memoryview: %.200s object does not have the buffer interface",
772 Py_TYPE(v)->tp_name);
773 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000774}
775
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100776/* Copy the format string from a base object that might vanish. */
777static int
778mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
779{
780 if (fmt != NULL) {
781 char *cp = PyMem_Malloc(strlen(fmt)+1);
782 if (cp == NULL) {
783 PyErr_NoMemory();
784 return -1;
785 }
786 mbuf->master.format = strcpy(cp, fmt);
787 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
788 }
789
790 return 0;
791}
792
793/*
794 Return a memoryview that is based on a contiguous copy of src.
795 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
796
797 Ownership rules:
798 1) As usual, the returned memoryview has a private copy
799 of src->shape, src->strides and src->suboffsets.
800 2) src->format is copied to the master buffer and released
801 in mbuf_dealloc(). The releasebufferproc of the bytes
802 object is NULL, so it does not matter that mbuf_release()
803 passes the altered format pointer to PyBuffer_Release().
804*/
805static PyObject *
806memory_from_contiguous_copy(Py_buffer *src, char order)
807{
808 _PyManagedBufferObject *mbuf;
809 PyMemoryViewObject *mv;
810 PyObject *bytes;
811 Py_buffer *dest;
812 int i;
813
814 assert(src->ndim > 0);
815 assert(src->shape != NULL);
816
817 bytes = PyBytes_FromStringAndSize(NULL, src->len);
818 if (bytes == NULL)
819 return NULL;
820
821 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
822 Py_DECREF(bytes);
823 if (mbuf == NULL)
824 return NULL;
825
826 if (mbuf_copy_format(mbuf, src->format) < 0) {
827 Py_DECREF(mbuf);
828 return NULL;
829 }
830
831 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
832 Py_DECREF(mbuf);
833 if (mv == NULL)
834 return NULL;
835
836 dest = &mv->view;
837
838 /* shared values are initialized correctly except for itemsize */
839 dest->itemsize = src->itemsize;
840
841 /* shape and strides */
842 for (i = 0; i < src->ndim; i++) {
843 dest->shape[i] = src->shape[i];
844 }
845 if (order == 'C' || order == 'A') {
846 init_strides_from_shape(dest);
847 }
848 else {
849 init_fortran_strides_from_shape(dest);
850 }
851 /* suboffsets */
852 dest->suboffsets = NULL;
853
854 /* flags */
855 init_flags(mv);
856
857 if (copy_buffer(dest, src) < 0) {
858 Py_DECREF(mv);
859 return NULL;
860 }
861
862 return (PyObject *)mv;
863}
864
865/*
866 Return a new memoryview object based on a contiguous exporter with
867 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
868 The logical structure of the input and output buffers is the same
869 (i.e. tolist(input) == tolist(output)), but the physical layout in
870 memory can be explicitly chosen.
871
872 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
873 otherwise it may be writable or read-only.
874
875 If the exporter is already contiguous with the desired target order,
876 the memoryview will be directly based on the exporter.
877
878 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
879 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
880 'F'ortran order otherwise.
881*/
882PyObject *
883PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
884{
885 PyMemoryViewObject *mv;
886 PyObject *ret;
887 Py_buffer *view;
888
889 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
890 assert(order == 'C' || order == 'F' || order == 'A');
891
892 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
893 if (mv == NULL)
894 return NULL;
895
896 view = &mv->view;
897 if (buffertype == PyBUF_WRITE && view->readonly) {
898 PyErr_SetString(PyExc_BufferError,
899 "underlying buffer is not writable");
900 Py_DECREF(mv);
901 return NULL;
902 }
903
904 if (PyBuffer_IsContiguous(view, order))
905 return (PyObject *)mv;
906
907 if (buffertype == PyBUF_WRITE) {
908 PyErr_SetString(PyExc_BufferError,
909 "writable contiguous buffer requested "
910 "for a non-contiguous object.");
911 Py_DECREF(mv);
912 return NULL;
913 }
914
915 ret = memory_from_contiguous_copy(view, order);
916 Py_DECREF(mv);
917 return ret;
918}
919
920
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000921static PyObject *
922memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
923{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000924 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100925 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000926
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000927 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
928 &obj)) {
929 return NULL;
930 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000931
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000932 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000933}
934
935
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100936/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200937/* Previously in abstract.c */
938/****************************************************************************/
939
940typedef struct {
941 Py_buffer view;
942 Py_ssize_t array[1];
943} Py_buffer_full;
944
945int
946PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
947{
948 Py_buffer_full *fb = NULL;
949 int ret;
950
951 assert(order == 'C' || order == 'F' || order == 'A');
952
953 if (len != src->len) {
954 PyErr_SetString(PyExc_ValueError,
955 "PyBuffer_ToContiguous: len != view->len");
956 return -1;
957 }
958
959 if (PyBuffer_IsContiguous(src, order)) {
960 memcpy((char *)buf, src->buf, len);
961 return 0;
962 }
963
964 /* buffer_to_contiguous() assumes PyBUF_FULL */
965 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
966 if (fb == NULL) {
967 PyErr_NoMemory();
968 return -1;
969 }
970 fb->view.ndim = src->ndim;
971 fb->view.shape = fb->array;
972 fb->view.strides = fb->array + src->ndim;
973 fb->view.suboffsets = fb->array + 2 * src->ndim;
974
975 init_shared_values(&fb->view, src);
976 init_shape_strides(&fb->view, src);
977 init_suboffsets(&fb->view, src);
978
979 src = &fb->view;
980
981 ret = buffer_to_contiguous(buf, src, order);
982 PyMem_Free(fb);
983 return ret;
984}
985
986
987/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100988/* Release/GC management */
989/****************************************************************************/
990
991/* Inform the managed buffer that this particular memoryview will not access
992 the underlying buffer again. If no other memoryviews are registered with
993 the managed buffer, the underlying buffer is released instantly and
994 marked as inaccessible for both the memoryview and the managed buffer.
995
996 This function fails if the memoryview itself has exported buffers. */
997static int
998_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000999{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001000 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1001 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001002
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001003 if (self->exports == 0) {
1004 self->flags |= _Py_MEMORYVIEW_RELEASED;
1005 assert(self->mbuf->exports > 0);
1006 if (--self->mbuf->exports == 0)
1007 mbuf_release(self->mbuf);
1008 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001009 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001010 if (self->exports > 0) {
1011 PyErr_Format(PyExc_BufferError,
1012 "memoryview has %zd exported buffer%s", self->exports,
1013 self->exports==1 ? "" : "s");
1014 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001015 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001016
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001017 Py_FatalError("_memory_release(): negative export count");
1018 return -1;
1019}
1020
1021static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001022memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001023{
1024 if (_memory_release(self) < 0)
1025 return NULL;
1026 Py_RETURN_NONE;
1027}
1028
1029static void
1030memory_dealloc(PyMemoryViewObject *self)
1031{
1032 assert(self->exports == 0);
1033 _PyObject_GC_UNTRACK(self);
1034 (void)_memory_release(self);
1035 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001036 if (self->weakreflist != NULL)
1037 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001038 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001039}
1040
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001041static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001042memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001043{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001044 Py_VISIT(self->mbuf);
1045 return 0;
1046}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001047
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001048static int
1049memory_clear(PyMemoryViewObject *self)
1050{
1051 (void)_memory_release(self);
1052 Py_CLEAR(self->mbuf);
1053 return 0;
1054}
1055
1056static PyObject *
1057memory_enter(PyObject *self, PyObject *args)
1058{
1059 CHECK_RELEASED(self);
1060 Py_INCREF(self);
1061 return self;
1062}
1063
1064static PyObject *
1065memory_exit(PyObject *self, PyObject *args)
1066{
Stefan Krahe4c07992012-07-28 14:10:02 +02001067 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001068}
1069
1070
1071/****************************************************************************/
1072/* Casting format and shape */
1073/****************************************************************************/
1074
1075#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1076
1077Py_LOCAL_INLINE(Py_ssize_t)
1078get_native_fmtchar(char *result, const char *fmt)
1079{
1080 Py_ssize_t size = -1;
1081
1082 if (fmt[0] == '@') fmt++;
1083
1084 switch (fmt[0]) {
1085 case 'c': case 'b': case 'B': size = sizeof(char); break;
1086 case 'h': case 'H': size = sizeof(short); break;
1087 case 'i': case 'I': size = sizeof(int); break;
1088 case 'l': case 'L': size = sizeof(long); break;
1089 #ifdef HAVE_LONG_LONG
1090 case 'q': case 'Q': size = sizeof(PY_LONG_LONG); break;
1091 #endif
1092 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1093 case 'f': size = sizeof(float); break;
1094 case 'd': size = sizeof(double); break;
1095 #ifdef HAVE_C99_BOOL
1096 case '?': size = sizeof(_Bool); break;
1097 #else
1098 case '?': size = sizeof(char); break;
1099 #endif
1100 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001101 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001102
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001103 if (size > 0 && fmt[1] == '\0') {
1104 *result = fmt[0];
1105 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001106 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001107
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001108 return -1;
1109}
1110
1111/* Cast a memoryview's data type to 'format'. The input array must be
1112 C-contiguous. At least one of input-format, output-format must have
1113 byte size. The output array is 1-D, with the same byte length as the
1114 input array. Thus, view->len must be a multiple of the new itemsize. */
1115static int
1116cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1117{
1118 Py_buffer *view = &mv->view;
1119 PyObject *asciifmt;
1120 char srcchar, destchar;
1121 Py_ssize_t itemsize;
1122 int ret = -1;
1123
1124 assert(view->ndim >= 1);
1125 assert(Py_SIZE(mv) == 3*view->ndim);
1126 assert(view->shape == mv->ob_array);
1127 assert(view->strides == mv->ob_array + view->ndim);
1128 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1129
1130 if (get_native_fmtchar(&srcchar, view->format) < 0) {
1131 PyErr_SetString(PyExc_ValueError,
1132 "memoryview: source format must be a native single character "
1133 "format prefixed with an optional '@'");
1134 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001135 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001136
1137 asciifmt = PyUnicode_AsASCIIString(format);
1138 if (asciifmt == NULL)
1139 return ret;
1140
1141 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1142 if (itemsize < 0) {
1143 PyErr_SetString(PyExc_ValueError,
1144 "memoryview: destination format must be a native single "
1145 "character format prefixed with an optional '@'");
1146 goto out;
1147 }
1148
1149 if (!IS_BYTE_FORMAT(srcchar) && !IS_BYTE_FORMAT(destchar)) {
1150 PyErr_SetString(PyExc_TypeError,
1151 "memoryview: cannot cast between two non-byte formats");
1152 goto out;
1153 }
1154 if (view->len % itemsize) {
1155 PyErr_SetString(PyExc_TypeError,
1156 "memoryview: length is not a multiple of itemsize");
1157 goto out;
1158 }
1159
1160 strncpy(mv->format, PyBytes_AS_STRING(asciifmt),
1161 _Py_MEMORYVIEW_MAX_FORMAT);
1162 mv->format[_Py_MEMORYVIEW_MAX_FORMAT-1] = '\0';
1163 view->format = mv->format;
1164 view->itemsize = itemsize;
1165
1166 view->ndim = 1;
1167 view->shape[0] = view->len / view->itemsize;
1168 view->strides[0] = view->itemsize;
1169 view->suboffsets = NULL;
1170
1171 init_flags(mv);
1172
1173 ret = 0;
1174
1175out:
1176 Py_DECREF(asciifmt);
1177 return ret;
1178}
1179
1180/* The memoryview must have space for 3*len(seq) elements. */
1181static Py_ssize_t
1182copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1183 Py_ssize_t itemsize)
1184{
1185 Py_ssize_t x, i;
1186 Py_ssize_t len = itemsize;
1187
1188 for (i = 0; i < ndim; i++) {
1189 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1190 if (!PyLong_Check(tmp)) {
1191 PyErr_SetString(PyExc_TypeError,
1192 "memoryview.cast(): elements of shape must be integers");
1193 return -1;
1194 }
1195 x = PyLong_AsSsize_t(tmp);
1196 if (x == -1 && PyErr_Occurred()) {
1197 return -1;
1198 }
1199 if (x <= 0) {
1200 /* In general elements of shape may be 0, but not for casting. */
1201 PyErr_Format(PyExc_ValueError,
1202 "memoryview.cast(): elements of shape must be integers > 0");
1203 return -1;
1204 }
1205 if (x > PY_SSIZE_T_MAX / len) {
1206 PyErr_Format(PyExc_ValueError,
1207 "memoryview.cast(): product(shape) > SSIZE_MAX");
1208 return -1;
1209 }
1210 len *= x;
1211 shape[i] = x;
1212 }
1213
1214 return len;
1215}
1216
1217/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1218 If the result array does not have exactly the same byte length as the
1219 input array, raise ValueError. */
1220static int
1221cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1222{
1223 Py_buffer *view = &mv->view;
1224 Py_ssize_t len;
1225
1226 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1227 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1228 assert(view->shape == mv->ob_array);
1229 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1230 assert(view->suboffsets == NULL);
1231
1232 view->ndim = ndim;
1233 if (view->ndim == 0) {
1234 view->shape = NULL;
1235 view->strides = NULL;
1236 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001237 }
1238 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001239 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1240 if (len < 0)
1241 return -1;
1242 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001243 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001244
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001245 if (view->len != len) {
1246 PyErr_SetString(PyExc_TypeError,
1247 "memoryview: product(shape) * itemsize != buffer size");
1248 return -1;
1249 }
1250
1251 init_flags(mv);
1252
1253 return 0;
1254}
1255
1256static int
1257zero_in_shape(PyMemoryViewObject *mv)
1258{
1259 Py_buffer *view = &mv->view;
1260 Py_ssize_t i;
1261
1262 for (i = 0; i < view->ndim; i++)
1263 if (view->shape[i] == 0)
1264 return 1;
1265
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001266 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001267}
1268
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001269/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001270 Cast a copy of 'self' to a different view. The input view must
1271 be C-contiguous. The function always casts the input view to a
1272 1-D output according to 'format'. At least one of input-format,
1273 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001274
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001275 If 'shape' is given, the 1-D view from the previous step will
1276 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001277
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001278 All casts must result in views that will have the exact byte
1279 size of the original input. Otherwise, an error is raised.
1280*/
1281static PyObject *
1282memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001283{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001284 static char *kwlist[] = {"format", "shape", NULL};
1285 PyMemoryViewObject *mv = NULL;
1286 PyObject *shape = NULL;
1287 PyObject *format;
1288 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001289
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001290 CHECK_RELEASED(self);
1291
1292 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1293 &format, &shape)) {
1294 return NULL;
1295 }
1296 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001297 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001298 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001299 return NULL;
1300 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001301 if (!MV_C_CONTIGUOUS(self->flags)) {
1302 PyErr_SetString(PyExc_TypeError,
1303 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001304 return NULL;
1305 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001306 if (zero_in_shape(self)) {
1307 PyErr_SetString(PyExc_TypeError,
1308 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001309 return NULL;
1310 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001311 if (shape) {
1312 CHECK_LIST_OR_TUPLE(shape)
1313 ndim = PySequence_Fast_GET_SIZE(shape);
1314 if (ndim > PyBUF_MAX_NDIM) {
1315 PyErr_SetString(PyExc_ValueError,
1316 "memoryview: number of dimensions must not exceed "
1317 STRINGIZE(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001318 return NULL;
1319 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001320 if (self->view.ndim != 1 && ndim != 1) {
1321 PyErr_SetString(PyExc_TypeError,
1322 "memoryview: cast must be 1D -> ND or ND -> 1D");
1323 return NULL;
1324 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001325 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001326
1327 mv = (PyMemoryViewObject *)
1328 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1329 if (mv == NULL)
1330 return NULL;
1331
1332 if (cast_to_1D(mv, format) < 0)
1333 goto error;
1334 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1335 goto error;
1336
1337 return (PyObject *)mv;
1338
1339error:
1340 Py_DECREF(mv);
1341 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001342}
1343
1344
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001345/**************************************************************************/
1346/* getbuffer */
1347/**************************************************************************/
1348
1349static int
1350memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1351{
1352 Py_buffer *base = &self->view;
1353 int baseflags = self->flags;
1354
1355 CHECK_RELEASED_INT(self);
1356
1357 /* start with complete information */
1358 *view = *base;
1359 view->obj = NULL;
1360
1361 if (REQ_WRITABLE(flags) && base->readonly) {
1362 PyErr_SetString(PyExc_BufferError,
1363 "memoryview: underlying buffer is not writable");
1364 return -1;
1365 }
1366 if (!REQ_FORMAT(flags)) {
1367 /* NULL indicates that the buffer's data type has been cast to 'B'.
1368 view->itemsize is the _previous_ itemsize. If shape is present,
1369 the equality product(shape) * itemsize = len still holds at this
1370 point. The equality calcsize(format) = itemsize does _not_ hold
1371 from here on! */
1372 view->format = NULL;
1373 }
1374
1375 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1376 PyErr_SetString(PyExc_BufferError,
1377 "memoryview: underlying buffer is not C-contiguous");
1378 return -1;
1379 }
1380 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1381 PyErr_SetString(PyExc_BufferError,
1382 "memoryview: underlying buffer is not Fortran contiguous");
1383 return -1;
1384 }
1385 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1386 PyErr_SetString(PyExc_BufferError,
1387 "memoryview: underlying buffer is not contiguous");
1388 return -1;
1389 }
1390 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1391 PyErr_SetString(PyExc_BufferError,
1392 "memoryview: underlying buffer requires suboffsets");
1393 return -1;
1394 }
1395 if (!REQ_STRIDES(flags)) {
1396 if (!MV_C_CONTIGUOUS(baseflags)) {
1397 PyErr_SetString(PyExc_BufferError,
1398 "memoryview: underlying buffer is not C-contiguous");
1399 return -1;
1400 }
1401 view->strides = NULL;
1402 }
1403 if (!REQ_SHAPE(flags)) {
1404 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1405 so base->buf = ndbuf->data. */
1406 if (view->format != NULL) {
1407 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1408 not make sense. */
1409 PyErr_Format(PyExc_BufferError,
1410 "ndarray: cannot cast to unsigned bytes if the format flag "
1411 "is present");
1412 return -1;
1413 }
1414 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1415 do _not_ hold from here on! */
1416 view->ndim = 1;
1417 view->shape = NULL;
1418 }
1419
1420
1421 view->obj = (PyObject *)self;
1422 Py_INCREF(view->obj);
1423 self->exports++;
1424
1425 return 0;
1426}
1427
1428static void
1429memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1430{
1431 self->exports--;
1432 return;
1433 /* PyBuffer_Release() decrements view->obj after this function returns. */
1434}
1435
1436/* Buffer methods */
1437static PyBufferProcs memory_as_buffer = {
1438 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1439 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1440};
1441
1442
1443/****************************************************************************/
1444/* Optimized pack/unpack for all native format specifiers */
1445/****************************************************************************/
1446
1447/*
1448 Fix exceptions:
1449 1) Include format string in the error message.
1450 2) OverflowError -> ValueError.
1451 3) The error message from PyNumber_Index() is not ideal.
1452*/
1453static int
1454type_error_int(const char *fmt)
1455{
1456 PyErr_Format(PyExc_TypeError,
1457 "memoryview: invalid type for format '%s'", fmt);
1458 return -1;
1459}
1460
1461static int
1462value_error_int(const char *fmt)
1463{
1464 PyErr_Format(PyExc_ValueError,
1465 "memoryview: invalid value for format '%s'", fmt);
1466 return -1;
1467}
1468
1469static int
1470fix_error_int(const char *fmt)
1471{
1472 assert(PyErr_Occurred());
1473 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1474 PyErr_Clear();
1475 return type_error_int(fmt);
1476 }
1477 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1478 PyErr_ExceptionMatches(PyExc_ValueError)) {
1479 PyErr_Clear();
1480 return value_error_int(fmt);
1481 }
1482
1483 return -1;
1484}
1485
1486/* Accept integer objects or objects with an __index__() method. */
1487static long
1488pylong_as_ld(PyObject *item)
1489{
1490 PyObject *tmp;
1491 long ld;
1492
1493 tmp = PyNumber_Index(item);
1494 if (tmp == NULL)
1495 return -1;
1496
1497 ld = PyLong_AsLong(tmp);
1498 Py_DECREF(tmp);
1499 return ld;
1500}
1501
1502static unsigned long
1503pylong_as_lu(PyObject *item)
1504{
1505 PyObject *tmp;
1506 unsigned long lu;
1507
1508 tmp = PyNumber_Index(item);
1509 if (tmp == NULL)
1510 return (unsigned long)-1;
1511
1512 lu = PyLong_AsUnsignedLong(tmp);
1513 Py_DECREF(tmp);
1514 return lu;
1515}
1516
1517#ifdef HAVE_LONG_LONG
1518static PY_LONG_LONG
1519pylong_as_lld(PyObject *item)
1520{
1521 PyObject *tmp;
1522 PY_LONG_LONG lld;
1523
1524 tmp = PyNumber_Index(item);
1525 if (tmp == NULL)
1526 return -1;
1527
1528 lld = PyLong_AsLongLong(tmp);
1529 Py_DECREF(tmp);
1530 return lld;
1531}
1532
1533static unsigned PY_LONG_LONG
1534pylong_as_llu(PyObject *item)
1535{
1536 PyObject *tmp;
1537 unsigned PY_LONG_LONG llu;
1538
1539 tmp = PyNumber_Index(item);
1540 if (tmp == NULL)
1541 return (unsigned PY_LONG_LONG)-1;
1542
1543 llu = PyLong_AsUnsignedLongLong(tmp);
1544 Py_DECREF(tmp);
1545 return llu;
1546}
1547#endif
1548
1549static Py_ssize_t
1550pylong_as_zd(PyObject *item)
1551{
1552 PyObject *tmp;
1553 Py_ssize_t zd;
1554
1555 tmp = PyNumber_Index(item);
1556 if (tmp == NULL)
1557 return -1;
1558
1559 zd = PyLong_AsSsize_t(tmp);
1560 Py_DECREF(tmp);
1561 return zd;
1562}
1563
1564static size_t
1565pylong_as_zu(PyObject *item)
1566{
1567 PyObject *tmp;
1568 size_t zu;
1569
1570 tmp = PyNumber_Index(item);
1571 if (tmp == NULL)
1572 return (size_t)-1;
1573
1574 zu = PyLong_AsSize_t(tmp);
1575 Py_DECREF(tmp);
1576 return zu;
1577}
1578
1579/* Timings with the ndarray from _testbuffer.c indicate that using the
1580 struct module is around 15x slower than the two functions below. */
1581
1582#define UNPACK_SINGLE(dest, ptr, type) \
1583 do { \
1584 type x; \
1585 memcpy((char *)&x, ptr, sizeof x); \
1586 dest = x; \
1587 } while (0)
1588
1589/* Unpack a single item. 'fmt' can be any native format character in struct
1590 module syntax. This function is very sensitive to small changes. With this
1591 layout gcc automatically generates a fast jump table. */
1592Py_LOCAL_INLINE(PyObject *)
1593unpack_single(const char *ptr, const char *fmt)
1594{
1595 unsigned PY_LONG_LONG llu;
1596 unsigned long lu;
1597 size_t zu;
1598 PY_LONG_LONG lld;
1599 long ld;
1600 Py_ssize_t zd;
1601 double d;
1602 unsigned char uc;
1603 void *p;
1604
1605 switch (fmt[0]) {
1606
1607 /* signed integers and fast path for 'B' */
1608 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1609 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1610 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1611 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1612 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1613
1614 /* boolean */
1615 #ifdef HAVE_C99_BOOL
1616 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
1617 #else
1618 case '?': UNPACK_SINGLE(ld, ptr, char); goto convert_bool;
1619 #endif
1620
1621 /* unsigned integers */
1622 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1623 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1624 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1625
1626 /* native 64-bit */
1627 #ifdef HAVE_LONG_LONG
1628 case 'q': UNPACK_SINGLE(lld, ptr, PY_LONG_LONG); goto convert_lld;
1629 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned PY_LONG_LONG); goto convert_llu;
1630 #endif
1631
1632 /* ssize_t and size_t */
1633 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1634 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1635
1636 /* floats */
1637 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1638 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1639
1640 /* bytes object */
1641 case 'c': goto convert_bytes;
1642
1643 /* pointer */
1644 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1645
1646 /* default */
1647 default: goto err_format;
1648 }
1649
1650convert_uc:
1651 /* PyLong_FromUnsignedLong() is slower */
1652 return PyLong_FromLong(uc);
1653convert_ld:
1654 return PyLong_FromLong(ld);
1655convert_lu:
1656 return PyLong_FromUnsignedLong(lu);
1657convert_lld:
1658 return PyLong_FromLongLong(lld);
1659convert_llu:
1660 return PyLong_FromUnsignedLongLong(llu);
1661convert_zd:
1662 return PyLong_FromSsize_t(zd);
1663convert_zu:
1664 return PyLong_FromSize_t(zu);
1665convert_double:
1666 return PyFloat_FromDouble(d);
1667convert_bool:
1668 return PyBool_FromLong(ld);
1669convert_bytes:
1670 return PyBytes_FromStringAndSize(ptr, 1);
1671convert_pointer:
1672 return PyLong_FromVoidPtr(p);
1673err_format:
1674 PyErr_Format(PyExc_NotImplementedError,
1675 "memoryview: format %s not supported", fmt);
1676 return NULL;
1677}
1678
1679#define PACK_SINGLE(ptr, src, type) \
1680 do { \
1681 type x; \
1682 x = (type)src; \
1683 memcpy(ptr, (char *)&x, sizeof x); \
1684 } while (0)
1685
1686/* Pack a single item. 'fmt' can be any native format character in
1687 struct module syntax. */
1688static int
1689pack_single(char *ptr, PyObject *item, const char *fmt)
1690{
1691 unsigned PY_LONG_LONG llu;
1692 unsigned long lu;
1693 size_t zu;
1694 PY_LONG_LONG lld;
1695 long ld;
1696 Py_ssize_t zd;
1697 double d;
1698 void *p;
1699
1700 switch (fmt[0]) {
1701 /* signed integers */
1702 case 'b': case 'h': case 'i': case 'l':
1703 ld = pylong_as_ld(item);
1704 if (ld == -1 && PyErr_Occurred())
1705 goto err_occurred;
1706 switch (fmt[0]) {
1707 case 'b':
1708 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1709 *((signed char *)ptr) = (signed char)ld; break;
1710 case 'h':
1711 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1712 PACK_SINGLE(ptr, ld, short); break;
1713 case 'i':
1714 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1715 PACK_SINGLE(ptr, ld, int); break;
1716 default: /* 'l' */
1717 PACK_SINGLE(ptr, ld, long); break;
1718 }
1719 break;
1720
1721 /* unsigned integers */
1722 case 'B': case 'H': case 'I': case 'L':
1723 lu = pylong_as_lu(item);
1724 if (lu == (unsigned long)-1 && PyErr_Occurred())
1725 goto err_occurred;
1726 switch (fmt[0]) {
1727 case 'B':
1728 if (lu > UCHAR_MAX) goto err_range;
1729 *((unsigned char *)ptr) = (unsigned char)lu; break;
1730 case 'H':
1731 if (lu > USHRT_MAX) goto err_range;
1732 PACK_SINGLE(ptr, lu, unsigned short); break;
1733 case 'I':
1734 if (lu > UINT_MAX) goto err_range;
1735 PACK_SINGLE(ptr, lu, unsigned int); break;
1736 default: /* 'L' */
1737 PACK_SINGLE(ptr, lu, unsigned long); break;
1738 }
1739 break;
1740
1741 /* native 64-bit */
1742 #ifdef HAVE_LONG_LONG
1743 case 'q':
1744 lld = pylong_as_lld(item);
1745 if (lld == -1 && PyErr_Occurred())
1746 goto err_occurred;
1747 PACK_SINGLE(ptr, lld, PY_LONG_LONG);
1748 break;
1749 case 'Q':
1750 llu = pylong_as_llu(item);
1751 if (llu == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
1752 goto err_occurred;
1753 PACK_SINGLE(ptr, llu, unsigned PY_LONG_LONG);
1754 break;
1755 #endif
1756
1757 /* ssize_t and size_t */
1758 case 'n':
1759 zd = pylong_as_zd(item);
1760 if (zd == -1 && PyErr_Occurred())
1761 goto err_occurred;
1762 PACK_SINGLE(ptr, zd, Py_ssize_t);
1763 break;
1764 case 'N':
1765 zu = pylong_as_zu(item);
1766 if (zu == (size_t)-1 && PyErr_Occurred())
1767 goto err_occurred;
1768 PACK_SINGLE(ptr, zu, size_t);
1769 break;
1770
1771 /* floats */
1772 case 'f': case 'd':
1773 d = PyFloat_AsDouble(item);
1774 if (d == -1.0 && PyErr_Occurred())
1775 goto err_occurred;
1776 if (fmt[0] == 'f') {
1777 PACK_SINGLE(ptr, d, float);
1778 }
1779 else {
1780 PACK_SINGLE(ptr, d, double);
1781 }
1782 break;
1783
1784 /* bool */
1785 case '?':
1786 ld = PyObject_IsTrue(item);
1787 if (ld < 0)
1788 return -1; /* preserve original error */
1789 #ifdef HAVE_C99_BOOL
1790 PACK_SINGLE(ptr, ld, _Bool);
1791 #else
1792 PACK_SINGLE(ptr, ld, char);
1793 #endif
1794 break;
1795
1796 /* bytes object */
1797 case 'c':
1798 if (!PyBytes_Check(item))
1799 return type_error_int(fmt);
1800 if (PyBytes_GET_SIZE(item) != 1)
1801 return value_error_int(fmt);
1802 *ptr = PyBytes_AS_STRING(item)[0];
1803 break;
1804
1805 /* pointer */
1806 case 'P':
1807 p = PyLong_AsVoidPtr(item);
1808 if (p == NULL && PyErr_Occurred())
1809 goto err_occurred;
1810 PACK_SINGLE(ptr, p, void *);
1811 break;
1812
1813 /* default */
1814 default: goto err_format;
1815 }
1816
1817 return 0;
1818
1819err_occurred:
1820 return fix_error_int(fmt);
1821err_range:
1822 return value_error_int(fmt);
1823err_format:
1824 PyErr_Format(PyExc_NotImplementedError,
1825 "memoryview: format %s not supported", fmt);
1826 return -1;
1827}
1828
1829
1830/****************************************************************************/
1831/* Representations */
1832/****************************************************************************/
1833
1834/* allow explicit form of native format */
1835Py_LOCAL_INLINE(const char *)
1836adjust_fmt(const Py_buffer *view)
1837{
1838 const char *fmt;
1839
1840 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
1841 if (fmt[0] && fmt[1] == '\0')
1842 return fmt;
1843
1844 PyErr_Format(PyExc_NotImplementedError,
1845 "memoryview: unsupported format %s", view->format);
1846 return NULL;
1847}
1848
1849/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
1850static PyObject *
1851tolist_base(const char *ptr, const Py_ssize_t *shape,
1852 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
1853 const char *fmt)
1854{
1855 PyObject *lst, *item;
1856 Py_ssize_t i;
1857
1858 lst = PyList_New(shape[0]);
1859 if (lst == NULL)
1860 return NULL;
1861
1862 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
1863 const char *xptr = ADJUST_PTR(ptr, suboffsets);
1864 item = unpack_single(xptr, fmt);
1865 if (item == NULL) {
1866 Py_DECREF(lst);
1867 return NULL;
1868 }
1869 PyList_SET_ITEM(lst, i, item);
1870 }
1871
1872 return lst;
1873}
1874
1875/* Unpack a multi-dimensional array into a nested list.
1876 Assumption: ndim >= 1. */
1877static PyObject *
1878tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
1879 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
1880 const char *fmt)
1881{
1882 PyObject *lst, *item;
1883 Py_ssize_t i;
1884
1885 assert(ndim >= 1);
1886 assert(shape != NULL);
1887 assert(strides != NULL);
1888
1889 if (ndim == 1)
1890 return tolist_base(ptr, shape, strides, suboffsets, fmt);
1891
1892 lst = PyList_New(shape[0]);
1893 if (lst == NULL)
1894 return NULL;
1895
1896 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
1897 const char *xptr = ADJUST_PTR(ptr, suboffsets);
1898 item = tolist_rec(xptr, ndim-1, shape+1,
1899 strides+1, suboffsets ? suboffsets+1 : NULL,
1900 fmt);
1901 if (item == NULL) {
1902 Py_DECREF(lst);
1903 return NULL;
1904 }
1905 PyList_SET_ITEM(lst, i, item);
1906 }
1907
1908 return lst;
1909}
1910
1911/* Return a list representation of the memoryview. Currently only buffers
1912 with native format strings are supported. */
1913static PyObject *
1914memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
1915{
1916 const Py_buffer *view = &(mv->view);
1917 const char *fmt;
1918
1919 CHECK_RELEASED(mv);
1920
1921 fmt = adjust_fmt(view);
1922 if (fmt == NULL)
1923 return NULL;
1924 if (view->ndim == 0) {
1925 return unpack_single(view->buf, fmt);
1926 }
1927 else if (view->ndim == 1) {
1928 return tolist_base(view->buf, view->shape,
1929 view->strides, view->suboffsets,
1930 fmt);
1931 }
1932 else {
1933 return tolist_rec(view->buf, view->ndim, view->shape,
1934 view->strides, view->suboffsets,
1935 fmt);
1936 }
1937}
1938
1939static PyObject *
1940memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
1941{
1942 Py_buffer *src = VIEW_ADDR(self);
1943 PyObject *bytes = NULL;
1944
1945 CHECK_RELEASED(self);
1946
1947 if (MV_C_CONTIGUOUS(self->flags)) {
1948 return PyBytes_FromStringAndSize(src->buf, src->len);
1949 }
1950
1951 bytes = PyBytes_FromStringAndSize(NULL, src->len);
1952 if (bytes == NULL)
1953 return NULL;
1954
Stefan Krah7d12d9d2012-07-28 12:25:55 +02001955 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001956 Py_DECREF(bytes);
1957 return NULL;
1958 }
1959
1960 return bytes;
1961}
1962
1963static PyObject *
1964memory_repr(PyMemoryViewObject *self)
1965{
1966 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1967 return PyUnicode_FromFormat("<released memory at %p>", self);
1968 else
1969 return PyUnicode_FromFormat("<memory at %p>", self);
1970}
1971
1972
1973/**************************************************************************/
1974/* Indexing and slicing */
1975/**************************************************************************/
1976
1977/* Get the pointer to the item at index. */
1978static char *
1979ptr_from_index(Py_buffer *view, Py_ssize_t index)
1980{
1981 char *ptr;
1982 Py_ssize_t nitems; /* items in the first dimension */
1983
1984 assert(view->shape);
1985 assert(view->strides);
1986
1987 nitems = view->shape[0];
1988 if (index < 0) {
1989 index += nitems;
1990 }
1991 if (index < 0 || index >= nitems) {
1992 PyErr_SetString(PyExc_IndexError, "index out of bounds");
1993 return NULL;
1994 }
1995
1996 ptr = (char *)view->buf;
1997 ptr += view->strides[0] * index;
1998
1999 ptr = ADJUST_PTR(ptr, view->suboffsets);
2000
2001 return ptr;
2002}
2003
2004/* Return the item at index. In a one-dimensional view, this is an object
2005 with the type specified by view->format. Otherwise, the item is a sub-view.
2006 The function is used in memory_subscript() and memory_as_sequence. */
2007static PyObject *
2008memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2009{
2010 Py_buffer *view = &(self->view);
2011 const char *fmt;
2012
2013 CHECK_RELEASED(self);
2014
2015 fmt = adjust_fmt(view);
2016 if (fmt == NULL)
2017 return NULL;
2018
2019 if (view->ndim == 0) {
2020 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2021 return NULL;
2022 }
2023 if (view->ndim == 1) {
2024 char *ptr = ptr_from_index(view, index);
2025 if (ptr == NULL)
2026 return NULL;
2027 return unpack_single(ptr, fmt);
2028 }
2029
2030 PyErr_SetString(PyExc_NotImplementedError,
2031 "multi-dimensional sub-views are not implemented");
2032 return NULL;
2033}
2034
2035Py_LOCAL_INLINE(int)
2036init_slice(Py_buffer *base, PyObject *key, int dim)
2037{
2038 Py_ssize_t start, stop, step, slicelength;
2039
2040 if (PySlice_GetIndicesEx(key, base->shape[dim],
2041 &start, &stop, &step, &slicelength) < 0) {
2042 return -1;
2043 }
2044
2045
2046 if (base->suboffsets == NULL || dim == 0) {
2047 adjust_buf:
2048 base->buf = (char *)base->buf + base->strides[dim] * start;
2049 }
2050 else {
2051 Py_ssize_t n = dim-1;
2052 while (n >= 0 && base->suboffsets[n] < 0)
2053 n--;
2054 if (n < 0)
2055 goto adjust_buf; /* all suboffsets are negative */
2056 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2057 }
2058 base->shape[dim] = slicelength;
2059 base->strides[dim] = base->strides[dim] * step;
2060
2061 return 0;
2062}
2063
2064static int
2065is_multislice(PyObject *key)
2066{
2067 Py_ssize_t size, i;
2068
2069 if (!PyTuple_Check(key))
2070 return 0;
2071 size = PyTuple_GET_SIZE(key);
2072 if (size == 0)
2073 return 0;
2074
2075 for (i = 0; i < size; i++) {
2076 PyObject *x = PyTuple_GET_ITEM(key, i);
2077 if (!PySlice_Check(x))
2078 return 0;
2079 }
2080 return 1;
2081}
2082
2083/* mv[obj] returns an object holding the data for one element if obj
2084 fully indexes the memoryview or another memoryview object if it
2085 does not.
2086
2087 0-d memoryview objects can be referenced using mv[...] or mv[()]
2088 but not with anything else. */
2089static PyObject *
2090memory_subscript(PyMemoryViewObject *self, PyObject *key)
2091{
2092 Py_buffer *view;
2093 view = &(self->view);
2094
2095 CHECK_RELEASED(self);
2096
2097 if (view->ndim == 0) {
2098 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2099 const char *fmt = adjust_fmt(view);
2100 if (fmt == NULL)
2101 return NULL;
2102 return unpack_single(view->buf, fmt);
2103 }
2104 else if (key == Py_Ellipsis) {
2105 Py_INCREF(self);
2106 return (PyObject *)self;
2107 }
2108 else {
2109 PyErr_SetString(PyExc_TypeError,
2110 "invalid indexing of 0-dim memory");
2111 return NULL;
2112 }
2113 }
2114
2115 if (PyIndex_Check(key)) {
2116 Py_ssize_t index;
2117 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2118 if (index == -1 && PyErr_Occurred())
2119 return NULL;
2120 return memory_item(self, index);
2121 }
2122 else if (PySlice_Check(key)) {
2123 PyMemoryViewObject *sliced;
2124
2125 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2126 if (sliced == NULL)
2127 return NULL;
2128
2129 if (init_slice(&sliced->view, key, 0) < 0) {
2130 Py_DECREF(sliced);
2131 return NULL;
2132 }
2133 init_len(&sliced->view);
2134 init_flags(sliced);
2135
2136 return (PyObject *)sliced;
2137 }
2138 else if (is_multislice(key)) {
2139 PyErr_SetString(PyExc_NotImplementedError,
2140 "multi-dimensional slicing is not implemented");
2141 return NULL;
2142 }
2143
2144 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2145 return NULL;
2146}
2147
2148static int
2149memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2150{
2151 Py_buffer *view = &(self->view);
2152 Py_buffer src;
2153 const char *fmt;
2154 char *ptr;
2155
2156 CHECK_RELEASED_INT(self);
2157
2158 fmt = adjust_fmt(view);
2159 if (fmt == NULL)
2160 return -1;
2161
2162 if (view->readonly) {
2163 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2164 return -1;
2165 }
2166 if (value == NULL) {
2167 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2168 return -1;
2169 }
2170 if (view->ndim == 0) {
2171 if (key == Py_Ellipsis ||
2172 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2173 ptr = (char *)view->buf;
2174 return pack_single(ptr, value, fmt);
2175 }
2176 else {
2177 PyErr_SetString(PyExc_TypeError,
2178 "invalid indexing of 0-dim memory");
2179 return -1;
2180 }
2181 }
2182 if (view->ndim != 1) {
2183 PyErr_SetString(PyExc_NotImplementedError,
2184 "memoryview assignments are currently restricted to ndim = 1");
2185 return -1;
2186 }
2187
2188 if (PyIndex_Check(key)) {
2189 Py_ssize_t index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2190 if (index == -1 && PyErr_Occurred())
2191 return -1;
2192 ptr = ptr_from_index(view, index);
2193 if (ptr == NULL)
2194 return -1;
2195 return pack_single(ptr, value, fmt);
2196 }
2197 /* one-dimensional: fast path */
2198 if (PySlice_Check(key) && view->ndim == 1) {
2199 Py_buffer dest; /* sliced view */
2200 Py_ssize_t arrays[3];
2201 int ret = -1;
2202
2203 /* rvalue must be an exporter */
2204 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2205 return ret;
2206
2207 dest = *view;
2208 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2209 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2210 if (view->suboffsets) {
2211 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2212 }
2213
2214 if (init_slice(&dest, key, 0) < 0)
2215 goto end_block;
2216 dest.len = dest.shape[0] * dest.itemsize;
2217
2218 ret = copy_single(&dest, &src);
2219
2220 end_block:
2221 PyBuffer_Release(&src);
2222 return ret;
2223 }
2224 else if (PySlice_Check(key) || is_multislice(key)) {
2225 /* Call memory_subscript() to produce a sliced lvalue, then copy
2226 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2227 PyErr_SetString(PyExc_NotImplementedError,
2228 "memoryview slice assignments are currently restricted "
2229 "to ndim = 1");
2230 return -1;
2231 }
2232
2233 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2234 return -1;
2235}
2236
2237static Py_ssize_t
2238memory_length(PyMemoryViewObject *self)
2239{
2240 CHECK_RELEASED_INT(self);
2241 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2242}
2243
2244/* As mapping */
2245static PyMappingMethods memory_as_mapping = {
2246 (lenfunc)memory_length, /* mp_length */
2247 (binaryfunc)memory_subscript, /* mp_subscript */
2248 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2249};
2250
2251/* As sequence */
2252static PySequenceMethods memory_as_sequence = {
2253 0, /* sq_length */
2254 0, /* sq_concat */
2255 0, /* sq_repeat */
2256 (ssizeargfunc)memory_item, /* sq_item */
2257};
2258
2259
2260/**************************************************************************/
2261/* Comparisons */
2262/**************************************************************************/
2263
2264#define CMP_SINGLE(p, q, type) \
2265 do { \
2266 type x; \
2267 type y; \
2268 memcpy((char *)&x, p, sizeof x); \
2269 memcpy((char *)&y, q, sizeof y); \
2270 equal = (x == y); \
2271 } while (0)
2272
2273Py_LOCAL_INLINE(int)
2274unpack_cmp(const char *p, const char *q, const char *fmt)
2275{
2276 int equal;
2277
2278 switch (fmt[0]) {
2279
2280 /* signed integers and fast path for 'B' */
2281 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2282 case 'b': return *((signed char *)p) == *((signed char *)q);
2283 case 'h': CMP_SINGLE(p, q, short); return equal;
2284 case 'i': CMP_SINGLE(p, q, int); return equal;
2285 case 'l': CMP_SINGLE(p, q, long); return equal;
2286
2287 /* boolean */
2288 #ifdef HAVE_C99_BOOL
2289 case '?': CMP_SINGLE(p, q, _Bool); return equal;
2290 #else
2291 case '?': CMP_SINGLE(p, q, char); return equal;
2292 #endif
2293
2294 /* unsigned integers */
2295 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2296 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2297 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2298
2299 /* native 64-bit */
2300 #ifdef HAVE_LONG_LONG
2301 case 'q': CMP_SINGLE(p, q, PY_LONG_LONG); return equal;
2302 case 'Q': CMP_SINGLE(p, q, unsigned PY_LONG_LONG); return equal;
2303 #endif
2304
2305 /* ssize_t and size_t */
2306 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2307 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2308
2309 /* floats */
2310 /* XXX DBL_EPSILON? */
2311 case 'f': CMP_SINGLE(p, q, float); return equal;
2312 case 'd': CMP_SINGLE(p, q, double); return equal;
2313
2314 /* bytes object */
2315 case 'c': return *p == *q;
2316
2317 /* pointer */
2318 case 'P': CMP_SINGLE(p, q, void *); return equal;
2319
2320 /* Py_NotImplemented */
2321 default: return -1;
2322 }
2323}
2324
2325/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2326static int
2327cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2328 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2329 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
2330 const char *fmt)
2331{
2332 Py_ssize_t i;
2333 int equal;
2334
2335 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
2336 const char *xp = ADJUST_PTR(p, psuboffsets);
2337 const char *xq = ADJUST_PTR(q, qsuboffsets);
2338 equal = unpack_cmp(xp, xq, fmt);
2339 if (equal <= 0)
2340 return equal;
2341 }
2342
2343 return 1;
2344}
2345
2346/* Recursively compare two multi-dimensional arrays that have the same
2347 logical structure. Assumption: ndim >= 1. */
2348static int
2349cmp_rec(const char *p, const char *q,
2350 Py_ssize_t ndim, const Py_ssize_t *shape,
2351 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2352 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
2353 const char *fmt)
2354{
2355 Py_ssize_t i;
2356 int equal;
2357
2358 assert(ndim >= 1);
2359 assert(shape != NULL);
2360 assert(pstrides != NULL);
2361 assert(qstrides != NULL);
2362
2363 if (ndim == 1) {
2364 return cmp_base(p, q, shape,
2365 pstrides, psuboffsets,
2366 qstrides, qsuboffsets,
2367 fmt);
2368 }
2369
2370 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
2371 const char *xp = ADJUST_PTR(p, psuboffsets);
2372 const char *xq = ADJUST_PTR(q, qsuboffsets);
2373 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2374 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2375 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
2376 fmt);
2377 if (equal <= 0)
2378 return equal;
2379 }
2380
2381 return 1;
2382}
2383
2384static PyObject *
2385memory_richcompare(PyObject *v, PyObject *w, int op)
2386{
2387 PyObject *res;
2388 Py_buffer wbuf, *vv, *ww = NULL;
2389 const char *vfmt, *wfmt;
2390 int equal = -1; /* Py_NotImplemented */
2391
2392 if (op != Py_EQ && op != Py_NE)
2393 goto result; /* Py_NotImplemented */
2394
2395 assert(PyMemoryView_Check(v));
2396 if (BASE_INACCESSIBLE(v)) {
2397 equal = (v == w);
2398 goto result;
2399 }
2400 vv = VIEW_ADDR(v);
2401
2402 if (PyMemoryView_Check(w)) {
2403 if (BASE_INACCESSIBLE(w)) {
2404 equal = (v == w);
2405 goto result;
2406 }
2407 ww = VIEW_ADDR(w);
2408 }
2409 else {
2410 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2411 PyErr_Clear();
2412 goto result; /* Py_NotImplemented */
2413 }
2414 ww = &wbuf;
2415 }
2416
2417 vfmt = adjust_fmt(vv);
2418 wfmt = adjust_fmt(ww);
2419 if (vfmt == NULL || wfmt == NULL) {
2420 PyErr_Clear();
2421 goto result; /* Py_NotImplemented */
2422 }
2423
2424 if (cmp_structure(vv, ww) < 0) {
2425 PyErr_Clear();
2426 equal = 0;
2427 goto result;
2428 }
2429
2430 if (vv->ndim == 0) {
2431 equal = unpack_cmp(vv->buf, ww->buf, vfmt);
2432 }
2433 else if (vv->ndim == 1) {
2434 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2435 vv->strides, vv->suboffsets,
2436 ww->strides, ww->suboffsets,
2437 vfmt);
2438 }
2439 else {
2440 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2441 vv->strides, vv->suboffsets,
2442 ww->strides, ww->suboffsets,
2443 vfmt);
2444 }
2445
2446result:
2447 if (equal < 0)
2448 res = Py_NotImplemented;
2449 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2450 res = Py_True;
2451 else
2452 res = Py_False;
2453
2454 if (ww == &wbuf)
2455 PyBuffer_Release(ww);
2456 Py_INCREF(res);
2457 return res;
2458}
2459
2460/**************************************************************************/
2461/* Hash */
2462/**************************************************************************/
2463
2464static Py_hash_t
2465memory_hash(PyMemoryViewObject *self)
2466{
2467 if (self->hash == -1) {
2468 Py_buffer *view = &self->view;
2469 char *mem = view->buf;
2470
2471 CHECK_RELEASED_INT(self);
2472
2473 if (!view->readonly) {
2474 PyErr_SetString(PyExc_ValueError,
2475 "cannot hash writable memoryview object");
2476 return -1;
2477 }
2478 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2479 /* Keep the original error message */
2480 return -1;
2481 }
2482
2483 if (!MV_C_CONTIGUOUS(self->flags)) {
2484 mem = PyMem_Malloc(view->len);
2485 if (mem == NULL) {
2486 PyErr_NoMemory();
2487 return -1;
2488 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002489 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002490 PyMem_Free(mem);
2491 return -1;
2492 }
2493 }
2494
2495 /* Can't fail */
2496 self->hash = _Py_HashBytes((unsigned char *)mem, view->len);
2497
2498 if (mem != view->buf)
2499 PyMem_Free(mem);
2500 }
2501
2502 return self->hash;
2503}
2504
2505
2506/**************************************************************************/
2507/* getters */
2508/**************************************************************************/
2509
2510static PyObject *
2511_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2512{
2513 int i;
2514 PyObject *o;
2515 PyObject *intTuple;
2516
2517 if (vals == NULL)
2518 return PyTuple_New(0);
2519
2520 intTuple = PyTuple_New(len);
2521 if (!intTuple)
2522 return NULL;
2523 for (i=0; i<len; i++) {
2524 o = PyLong_FromSsize_t(vals[i]);
2525 if (!o) {
2526 Py_DECREF(intTuple);
2527 return NULL;
2528 }
2529 PyTuple_SET_ITEM(intTuple, i, o);
2530 }
2531 return intTuple;
2532}
2533
2534static PyObject *
2535memory_obj_get(PyMemoryViewObject *self)
2536{
2537 Py_buffer *view = &self->view;
2538
2539 CHECK_RELEASED(self);
2540 if (view->obj == NULL) {
2541 Py_RETURN_NONE;
2542 }
2543 Py_INCREF(view->obj);
2544 return view->obj;
2545}
2546
2547static PyObject *
2548memory_nbytes_get(PyMemoryViewObject *self)
2549{
2550 CHECK_RELEASED(self);
2551 return PyLong_FromSsize_t(self->view.len);
2552}
2553
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002554static PyObject *
2555memory_format_get(PyMemoryViewObject *self)
2556{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002557 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002558 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002559}
2560
2561static PyObject *
2562memory_itemsize_get(PyMemoryViewObject *self)
2563{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002564 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002565 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002566}
2567
2568static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002569memory_shape_get(PyMemoryViewObject *self)
2570{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002571 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002572 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002573}
2574
2575static PyObject *
2576memory_strides_get(PyMemoryViewObject *self)
2577{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002578 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002579 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002580}
2581
2582static PyObject *
2583memory_suboffsets_get(PyMemoryViewObject *self)
2584{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002585 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002586 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002587}
2588
2589static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002590memory_readonly_get(PyMemoryViewObject *self)
2591{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002592 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002593 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002594}
2595
2596static PyObject *
2597memory_ndim_get(PyMemoryViewObject *self)
2598{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002599 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002600 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002601}
2602
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002603static PyObject *
2604memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2605{
2606 CHECK_RELEASED(self);
2607 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
2608}
2609
2610static PyObject *
2611memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2612{
2613 CHECK_RELEASED(self);
2614 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
2615}
2616
2617static PyObject *
2618memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2619{
2620 CHECK_RELEASED(self);
2621 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
2622}
2623
2624static PyGetSetDef memory_getsetlist[] = {
2625 {"obj", (getter)memory_obj_get, NULL, NULL},
2626 {"nbytes", (getter)memory_nbytes_get, NULL, NULL},
2627 {"readonly", (getter)memory_readonly_get, NULL, NULL},
2628 {"itemsize", (getter)memory_itemsize_get, NULL, NULL},
2629 {"format", (getter)memory_format_get, NULL, NULL},
2630 {"ndim", (getter)memory_ndim_get, NULL, NULL},
2631 {"shape", (getter)memory_shape_get, NULL, NULL},
2632 {"strides", (getter)memory_strides_get, NULL, NULL},
2633 {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL},
2634 {"c_contiguous", (getter)memory_c_contiguous, NULL, NULL},
2635 {"f_contiguous", (getter)memory_f_contiguous, NULL, NULL},
2636 {"contiguous", (getter)memory_contiguous, NULL, NULL},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002637 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002638};
2639
2640
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002641static PyMethodDef memory_methods[] = {
Stefan Krahe4c07992012-07-28 14:10:02 +02002642 {"release", (PyCFunction)memory_release, METH_NOARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002643 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL},
2644 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL},
2645 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, NULL},
Stefan Krahe4c07992012-07-28 14:10:02 +02002646 {"__enter__", memory_enter, METH_NOARGS, NULL},
2647 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002648 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002649};
2650
2651
2652PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002653 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002654 "memoryview", /* tp_name */
2655 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
2656 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002657 (destructor)memory_dealloc, /* tp_dealloc */
2658 0, /* tp_print */
2659 0, /* tp_getattr */
2660 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00002661 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002662 (reprfunc)memory_repr, /* tp_repr */
2663 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00002664 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002665 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01002666 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002667 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00002668 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002669 PyObject_GenericGetAttr, /* tp_getattro */
2670 0, /* tp_setattro */
2671 &memory_as_buffer, /* tp_as_buffer */
2672 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2673 memory_doc, /* tp_doc */
2674 (traverseproc)memory_traverse, /* tp_traverse */
2675 (inquiry)memory_clear, /* tp_clear */
2676 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01002677 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002678 0, /* tp_iter */
2679 0, /* tp_iternext */
2680 memory_methods, /* tp_methods */
2681 0, /* tp_members */
2682 memory_getsetlist, /* tp_getset */
2683 0, /* tp_base */
2684 0, /* tp_dict */
2685 0, /* tp_descr_get */
2686 0, /* tp_descr_set */
2687 0, /* tp_dictoffset */
2688 0, /* tp_init */
2689 0, /* tp_alloc */
2690 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002691};