blob: b6951ab88e0e031753bd86d69cf5f88731c35f04 [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
Stefan Krah9a2d99e2012-02-25 12:24:21 +010051#define CHECK_MBUF_RELEASED(mbuf) \
52 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
53 PyErr_SetString(PyExc_ValueError, \
54 "operation forbidden on released memoryview object"); \
55 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000056 }
57
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000058
Stefan Krah9a2d99e2012-02-25 12:24:21 +010059Py_LOCAL_INLINE(_PyManagedBufferObject *)
60mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000061{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010062 _PyManagedBufferObject *mbuf;
63
64 mbuf = (_PyManagedBufferObject *)
65 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
66 if (mbuf == NULL)
67 return NULL;
68 mbuf->flags = 0;
69 mbuf->exports = 0;
70 mbuf->master.obj = NULL;
71 _PyObject_GC_TRACK(mbuf);
72
73 return mbuf;
74}
75
76static PyObject *
77_PyManagedBuffer_FromObject(PyObject *base)
78{
79 _PyManagedBufferObject *mbuf;
80
81 mbuf = mbuf_alloc();
82 if (mbuf == NULL)
83 return NULL;
84
85 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +010086 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +010087 Py_DECREF(mbuf);
88 return NULL;
89 }
90
Stefan Krah9a2d99e2012-02-25 12:24:21 +010091 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +000092}
93
94static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +010095mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +000096{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010097 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
98 return;
99
100 /* NOTE: at this point self->exports can still be > 0 if this function
101 is called from mbuf_clear() to break up a reference cycle. */
102 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
103
104 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
105 _PyObject_GC_UNTRACK(self);
106 PyBuffer_Release(&self->master);
107}
108
109static void
110mbuf_dealloc(_PyManagedBufferObject *self)
111{
112 assert(self->exports == 0);
113 mbuf_release(self);
114 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
115 PyMem_Free(self->master.format);
116 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000117}
118
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000119static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100120mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000121{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100122 Py_VISIT(self->master.obj);
123 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000124}
125
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100126static int
127mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000128{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100129 assert(self->exports >= 0);
130 mbuf_release(self);
131 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000132}
133
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100134PyTypeObject _PyManagedBuffer_Type = {
135 PyVarObject_HEAD_INIT(&PyType_Type, 0)
136 "managedbuffer",
137 sizeof(_PyManagedBufferObject),
138 0,
139 (destructor)mbuf_dealloc, /* tp_dealloc */
140 0, /* tp_print */
141 0, /* tp_getattr */
142 0, /* tp_setattr */
143 0, /* tp_reserved */
144 0, /* tp_repr */
145 0, /* tp_as_number */
146 0, /* tp_as_sequence */
147 0, /* tp_as_mapping */
148 0, /* tp_hash */
149 0, /* tp_call */
150 0, /* tp_str */
151 PyObject_GenericGetAttr, /* tp_getattro */
152 0, /* tp_setattro */
153 0, /* tp_as_buffer */
154 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
155 0, /* tp_doc */
156 (traverseproc)mbuf_traverse, /* tp_traverse */
157 (inquiry)mbuf_clear /* tp_clear */
158};
159
160
161/****************************************************************************/
162/* MemoryView Object */
163/****************************************************************************/
164
165/* In the process of breaking reference cycles mbuf_release() can be
166 called before memory_release(). */
167#define BASE_INACCESSIBLE(mv) \
168 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
169 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
170
171#define CHECK_RELEASED(mv) \
172 if (BASE_INACCESSIBLE(mv)) { \
173 PyErr_SetString(PyExc_ValueError, \
174 "operation forbidden on released memoryview object"); \
175 return NULL; \
176 }
177
178#define CHECK_RELEASED_INT(mv) \
179 if (BASE_INACCESSIBLE(mv)) { \
180 PyErr_SetString(PyExc_ValueError, \
181 "operation forbidden on released memoryview object"); \
182 return -1; \
183 }
184
185#define CHECK_LIST_OR_TUPLE(v) \
186 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
187 PyErr_SetString(PyExc_TypeError, \
188 #v " must be a list or a tuple"); \
189 return NULL; \
190 }
191
192#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
193
194/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100195#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100196/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100197#define ADJUST_PTR(ptr, suboffsets, dim) \
198 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100199
200/* Memoryview buffer properties */
201#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
202#define MV_F_CONTIGUOUS(flags) \
203 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
204#define MV_ANY_CONTIGUOUS(flags) \
205 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
206
207/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
208#define MV_CONTIGUOUS_NDIM1(view) \
209 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
210
211/* getbuffer() requests */
212#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
213#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
214#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
215#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
216#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
217#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
218#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
219#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
220
221
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000222PyDoc_STRVAR(memory_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +0200223"memoryview($module, object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000224\n\
225Create a new memoryview object which references the given object.");
226
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100227
228/**************************************************************************/
229/* Copy memoryview buffers */
230/**************************************************************************/
231
232/* The functions in this section take a source and a destination buffer
233 with the same logical structure: format, itemsize, ndim and shape
234 are identical, with ndim > 0.
235
236 NOTE: All buffers are assumed to have PyBUF_FULL information, which
237 is the case for memoryviews! */
238
239
240/* Assumptions: ndim >= 1. The macro tests for a corner case that should
241 perhaps be explicitly forbidden in the PEP. */
242#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
243 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
244
245Py_LOCAL_INLINE(int)
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000246last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100247{
248 assert(dest->ndim > 0 && src->ndim > 0);
249 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
250 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
251 dest->strides[dest->ndim-1] == dest->itemsize &&
252 src->strides[src->ndim-1] == src->itemsize);
253}
254
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000255/* This is not a general function for determining format equivalence.
256 It is used in copy_single() and copy_buffer() to weed out non-matching
257 formats. Skipping the '@' character is specifically used in slice
258 assignments, where the lvalue is already known to have a single character
259 format. This is a performance hack that could be rewritten (if properly
260 benchmarked). */
261Py_LOCAL_INLINE(int)
262equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100263{
264 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100265
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 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000271 dest->itemsize != src->itemsize) {
272 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100273 }
274
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000275 return 1;
276}
277
278/* Two shapes are equivalent if they are either equal or identical up
279 to a zero element at the same position. For example, in NumPy arrays
280 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
281Py_LOCAL_INLINE(int)
282equiv_shape(const Py_buffer *dest, const Py_buffer *src)
283{
284 int i;
285
286 if (dest->ndim != src->ndim)
287 return 0;
288
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100289 for (i = 0; i < dest->ndim; i++) {
290 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000291 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100292 if (dest->shape[i] == 0)
293 break;
294 }
295
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000296 return 1;
297}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100298
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000299/* Check that the logical structure of the destination and source buffers
300 is identical. */
301static int
302equiv_structure(const Py_buffer *dest, const Py_buffer *src)
303{
304 if (!equiv_format(dest, src) ||
305 !equiv_shape(dest, src)) {
306 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100307 "memoryview assignment: lvalue and rvalue have different "
308 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000309 return 0;
310 }
311
312 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100313}
314
315/* Base case for recursive multi-dimensional copying. Contiguous arrays are
316 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
317 sizeof(mem) == shape[0] * itemsize. */
318static void
319copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
320 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
321 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
322 char *mem)
323{
324 if (mem == NULL) { /* contiguous */
325 Py_ssize_t size = shape[0] * itemsize;
326 if (dptr + size < sptr || sptr + size < dptr)
327 memcpy(dptr, sptr, size); /* no overlapping */
328 else
329 memmove(dptr, sptr, size);
330 }
331 else {
332 char *p;
333 Py_ssize_t i;
334 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100335 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100336 memcpy(p, xsptr, itemsize);
337 }
338 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100339 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100340 memcpy(xdptr, p, itemsize);
341 }
342 }
343
344}
345
346/* Recursively copy a source buffer to a destination buffer. The two buffers
347 have the same ndim, shape and itemsize. */
348static void
349copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
350 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
351 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
352 char *mem)
353{
354 Py_ssize_t i;
355
356 assert(ndim >= 1);
357
358 if (ndim == 1) {
359 copy_base(shape, itemsize,
360 dptr, dstrides, dsuboffsets,
361 sptr, sstrides, ssuboffsets,
362 mem);
363 return;
364 }
365
366 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100367 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
368 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100369
370 copy_rec(shape+1, ndim-1, itemsize,
371 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
372 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
373 mem);
374 }
375}
376
377/* Faster copying of one-dimensional arrays. */
378static int
379copy_single(Py_buffer *dest, Py_buffer *src)
380{
381 char *mem = NULL;
382
383 assert(dest->ndim == 1);
384
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000385 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100386 return -1;
387
388 if (!last_dim_is_contiguous(dest, src)) {
389 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
390 if (mem == NULL) {
391 PyErr_NoMemory();
392 return -1;
393 }
394 }
395
396 copy_base(dest->shape, dest->itemsize,
397 dest->buf, dest->strides, dest->suboffsets,
398 src->buf, src->strides, src->suboffsets,
399 mem);
400
401 if (mem)
402 PyMem_Free(mem);
403
404 return 0;
405}
406
407/* Recursively copy src to dest. Both buffers must have the same basic
408 structure. Copying is atomic, the function never fails with a partial
409 copy. */
410static int
411copy_buffer(Py_buffer *dest, Py_buffer *src)
412{
413 char *mem = NULL;
414
415 assert(dest->ndim > 0);
416
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000417 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100418 return -1;
419
420 if (!last_dim_is_contiguous(dest, src)) {
421 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
422 if (mem == NULL) {
423 PyErr_NoMemory();
424 return -1;
425 }
426 }
427
428 copy_rec(dest->shape, dest->ndim, dest->itemsize,
429 dest->buf, dest->strides, dest->suboffsets,
430 src->buf, src->strides, src->suboffsets,
431 mem);
432
433 if (mem)
434 PyMem_Free(mem);
435
436 return 0;
437}
438
439/* Initialize strides for a C-contiguous array. */
440Py_LOCAL_INLINE(void)
441init_strides_from_shape(Py_buffer *view)
442{
443 Py_ssize_t i;
444
445 assert(view->ndim > 0);
446
447 view->strides[view->ndim-1] = view->itemsize;
448 for (i = view->ndim-2; i >= 0; i--)
449 view->strides[i] = view->strides[i+1] * view->shape[i+1];
450}
451
452/* Initialize strides for a Fortran-contiguous array. */
453Py_LOCAL_INLINE(void)
454init_fortran_strides_from_shape(Py_buffer *view)
455{
456 Py_ssize_t i;
457
458 assert(view->ndim > 0);
459
460 view->strides[0] = view->itemsize;
461 for (i = 1; i < view->ndim; i++)
462 view->strides[i] = view->strides[i-1] * view->shape[i-1];
463}
464
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200465/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
466 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100467 len(mem) == src->len. */
468static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200469buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100470{
471 Py_buffer dest;
472 Py_ssize_t *strides;
473 int ret;
474
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200475 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100476 assert(src->shape != NULL);
477 assert(src->strides != NULL);
478
479 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
480 if (strides == NULL) {
481 PyErr_NoMemory();
482 return -1;
483 }
484
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200485 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100486 dest = *src;
487 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200488 /* shape is constant and shared: the logical representation of the
489 array is unaltered. */
490
491 /* The physical representation determined by strides (and possibly
492 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100493 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200494 if (order == 'C' || order == 'A') {
495 init_strides_from_shape(&dest);
496 }
497 else {
498 init_fortran_strides_from_shape(&dest);
499 }
500
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100501 dest.suboffsets = NULL;
502
503 ret = copy_buffer(&dest, src);
504
505 PyMem_Free(strides);
506 return ret;
507}
508
509
510/****************************************************************************/
511/* Constructors */
512/****************************************************************************/
513
514/* Initialize values that are shared with the managed buffer. */
515Py_LOCAL_INLINE(void)
516init_shared_values(Py_buffer *dest, const Py_buffer *src)
517{
518 dest->obj = src->obj;
519 dest->buf = src->buf;
520 dest->len = src->len;
521 dest->itemsize = src->itemsize;
522 dest->readonly = src->readonly;
523 dest->format = src->format ? src->format : "B";
524 dest->internal = src->internal;
525}
526
527/* Copy shape and strides. Reconstruct missing values. */
528static void
529init_shape_strides(Py_buffer *dest, const Py_buffer *src)
530{
531 Py_ssize_t i;
532
533 if (src->ndim == 0) {
534 dest->shape = NULL;
535 dest->strides = NULL;
536 return;
537 }
538 if (src->ndim == 1) {
539 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
540 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
541 return;
542 }
543
544 for (i = 0; i < src->ndim; i++)
545 dest->shape[i] = src->shape[i];
546 if (src->strides) {
547 for (i = 0; i < src->ndim; i++)
548 dest->strides[i] = src->strides[i];
549 }
550 else {
551 init_strides_from_shape(dest);
552 }
553}
554
555Py_LOCAL_INLINE(void)
556init_suboffsets(Py_buffer *dest, const Py_buffer *src)
557{
558 Py_ssize_t i;
559
560 if (src->suboffsets == NULL) {
561 dest->suboffsets = NULL;
562 return;
563 }
564 for (i = 0; i < src->ndim; i++)
565 dest->suboffsets[i] = src->suboffsets[i];
566}
567
568/* len = product(shape) * itemsize */
569Py_LOCAL_INLINE(void)
570init_len(Py_buffer *view)
571{
572 Py_ssize_t i, len;
573
574 len = 1;
575 for (i = 0; i < view->ndim; i++)
576 len *= view->shape[i];
577 len *= view->itemsize;
578
579 view->len = len;
580}
581
582/* Initialize memoryview buffer properties. */
583static void
584init_flags(PyMemoryViewObject *mv)
585{
586 const Py_buffer *view = &mv->view;
587 int flags = 0;
588
589 switch (view->ndim) {
590 case 0:
591 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
592 _Py_MEMORYVIEW_FORTRAN);
593 break;
594 case 1:
595 if (MV_CONTIGUOUS_NDIM1(view))
596 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
597 break;
598 default:
599 if (PyBuffer_IsContiguous(view, 'C'))
600 flags |= _Py_MEMORYVIEW_C;
601 if (PyBuffer_IsContiguous(view, 'F'))
602 flags |= _Py_MEMORYVIEW_FORTRAN;
603 break;
604 }
605
606 if (view->suboffsets) {
607 flags |= _Py_MEMORYVIEW_PIL;
608 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
609 }
610
611 mv->flags = flags;
612}
613
614/* Allocate a new memoryview and perform basic initialization. New memoryviews
615 are exclusively created through the mbuf_add functions. */
616Py_LOCAL_INLINE(PyMemoryViewObject *)
617memory_alloc(int ndim)
618{
619 PyMemoryViewObject *mv;
620
621 mv = (PyMemoryViewObject *)
622 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
623 if (mv == NULL)
624 return NULL;
625
626 mv->mbuf = NULL;
627 mv->hash = -1;
628 mv->flags = 0;
629 mv->exports = 0;
630 mv->view.ndim = ndim;
631 mv->view.shape = mv->ob_array;
632 mv->view.strides = mv->ob_array + ndim;
633 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100634 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100635
636 _PyObject_GC_TRACK(mv);
637 return mv;
638}
639
640/*
641 Return a new memoryview that is registered with mbuf. If src is NULL,
642 use mbuf->master as the underlying buffer. Otherwise, use src.
643
644 The new memoryview has full buffer information: shape and strides
645 are always present, suboffsets as needed. Arrays are copied to
646 the memoryview's ob_array field.
647 */
648static PyObject *
649mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
650{
651 PyMemoryViewObject *mv;
652 Py_buffer *dest;
653
654 if (src == NULL)
655 src = &mbuf->master;
656
657 if (src->ndim > PyBUF_MAX_NDIM) {
658 PyErr_SetString(PyExc_ValueError,
659 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200660 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100661 return NULL;
662 }
663
664 mv = memory_alloc(src->ndim);
665 if (mv == NULL)
666 return NULL;
667
668 dest = &mv->view;
669 init_shared_values(dest, src);
670 init_shape_strides(dest, src);
671 init_suboffsets(dest, src);
672 init_flags(mv);
673
674 mv->mbuf = mbuf;
675 Py_INCREF(mbuf);
676 mbuf->exports++;
677
678 return (PyObject *)mv;
679}
680
681/* Register an incomplete view: shape, strides, suboffsets and flags still
682 need to be initialized. Use 'ndim' instead of src->ndim to determine the
683 size of the memoryview's ob_array.
684
685 Assumption: ndim <= PyBUF_MAX_NDIM. */
686static PyObject *
687mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
688 int ndim)
689{
690 PyMemoryViewObject *mv;
691 Py_buffer *dest;
692
693 if (src == NULL)
694 src = &mbuf->master;
695
696 assert(ndim <= PyBUF_MAX_NDIM);
697
698 mv = memory_alloc(ndim);
699 if (mv == NULL)
700 return NULL;
701
702 dest = &mv->view;
703 init_shared_values(dest, src);
704
705 mv->mbuf = mbuf;
706 Py_INCREF(mbuf);
707 mbuf->exports++;
708
709 return (PyObject *)mv;
710}
711
712/* Expose a raw memory area as a view of contiguous bytes. flags can be
713 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
714 The memoryview has complete buffer information. */
715PyObject *
716PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
717{
718 _PyManagedBufferObject *mbuf;
719 PyObject *mv;
720 int readonly;
721
722 assert(mem != NULL);
723 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
724
725 mbuf = mbuf_alloc();
726 if (mbuf == NULL)
727 return NULL;
728
729 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
730 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
731 PyBUF_FULL_RO);
732
733 mv = mbuf_add_view(mbuf, NULL);
734 Py_DECREF(mbuf);
735
736 return mv;
737}
738
739/* Create a memoryview from a given Py_buffer. For simple byte views,
740 PyMemoryView_FromMemory() should be used instead.
741 This function is the only entry point that can create a master buffer
742 without full information. Because of this fact init_shape_strides()
743 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000744PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000745PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000746{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100747 _PyManagedBufferObject *mbuf;
748 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000749
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000750 if (info->buf == NULL) {
751 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100752 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000753 return NULL;
754 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100755
756 mbuf = mbuf_alloc();
757 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000758 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100759
760 /* info->obj is either NULL or a borrowed reference. This reference
761 should not be decremented in PyBuffer_Release(). */
762 mbuf->master = *info;
763 mbuf->master.obj = NULL;
764
765 mv = mbuf_add_view(mbuf, NULL);
766 Py_DECREF(mbuf);
767
768 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000769}
770
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100771/* Create a memoryview from an object that implements the buffer protocol.
772 If the object is a memoryview, the new memoryview must be registered
773 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000774PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100775PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000776{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100777 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000778
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100779 if (PyMemoryView_Check(v)) {
780 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
781 CHECK_RELEASED(mv);
782 return mbuf_add_view(mv->mbuf, &mv->view);
783 }
784 else if (PyObject_CheckBuffer(v)) {
785 PyObject *ret;
786 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
787 if (mbuf == NULL)
788 return NULL;
789 ret = mbuf_add_view(mbuf, NULL);
790 Py_DECREF(mbuf);
791 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000792 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000793
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100794 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400795 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100796 Py_TYPE(v)->tp_name);
797 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000798}
799
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100800/* Copy the format string from a base object that might vanish. */
801static int
802mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
803{
804 if (fmt != NULL) {
805 char *cp = PyMem_Malloc(strlen(fmt)+1);
806 if (cp == NULL) {
807 PyErr_NoMemory();
808 return -1;
809 }
810 mbuf->master.format = strcpy(cp, fmt);
811 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
812 }
813
814 return 0;
815}
816
817/*
818 Return a memoryview that is based on a contiguous copy of src.
819 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
820
821 Ownership rules:
822 1) As usual, the returned memoryview has a private copy
823 of src->shape, src->strides and src->suboffsets.
824 2) src->format is copied to the master buffer and released
825 in mbuf_dealloc(). The releasebufferproc of the bytes
826 object is NULL, so it does not matter that mbuf_release()
827 passes the altered format pointer to PyBuffer_Release().
828*/
829static PyObject *
830memory_from_contiguous_copy(Py_buffer *src, char order)
831{
832 _PyManagedBufferObject *mbuf;
833 PyMemoryViewObject *mv;
834 PyObject *bytes;
835 Py_buffer *dest;
836 int i;
837
838 assert(src->ndim > 0);
839 assert(src->shape != NULL);
840
841 bytes = PyBytes_FromStringAndSize(NULL, src->len);
842 if (bytes == NULL)
843 return NULL;
844
845 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
846 Py_DECREF(bytes);
847 if (mbuf == NULL)
848 return NULL;
849
850 if (mbuf_copy_format(mbuf, src->format) < 0) {
851 Py_DECREF(mbuf);
852 return NULL;
853 }
854
855 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
856 Py_DECREF(mbuf);
857 if (mv == NULL)
858 return NULL;
859
860 dest = &mv->view;
861
862 /* shared values are initialized correctly except for itemsize */
863 dest->itemsize = src->itemsize;
864
865 /* shape and strides */
866 for (i = 0; i < src->ndim; i++) {
867 dest->shape[i] = src->shape[i];
868 }
869 if (order == 'C' || order == 'A') {
870 init_strides_from_shape(dest);
871 }
872 else {
873 init_fortran_strides_from_shape(dest);
874 }
875 /* suboffsets */
876 dest->suboffsets = NULL;
877
878 /* flags */
879 init_flags(mv);
880
881 if (copy_buffer(dest, src) < 0) {
882 Py_DECREF(mv);
883 return NULL;
884 }
885
886 return (PyObject *)mv;
887}
888
889/*
890 Return a new memoryview object based on a contiguous exporter with
891 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
892 The logical structure of the input and output buffers is the same
893 (i.e. tolist(input) == tolist(output)), but the physical layout in
894 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200895
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100896 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
897 otherwise it may be writable or read-only.
898
899 If the exporter is already contiguous with the desired target order,
900 the memoryview will be directly based on the exporter.
901
902 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
903 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
904 'F'ortran order otherwise.
905*/
906PyObject *
907PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
908{
909 PyMemoryViewObject *mv;
910 PyObject *ret;
911 Py_buffer *view;
912
913 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
914 assert(order == 'C' || order == 'F' || order == 'A');
915
916 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
917 if (mv == NULL)
918 return NULL;
919
920 view = &mv->view;
921 if (buffertype == PyBUF_WRITE && view->readonly) {
922 PyErr_SetString(PyExc_BufferError,
923 "underlying buffer is not writable");
924 Py_DECREF(mv);
925 return NULL;
926 }
927
928 if (PyBuffer_IsContiguous(view, order))
929 return (PyObject *)mv;
930
931 if (buffertype == PyBUF_WRITE) {
932 PyErr_SetString(PyExc_BufferError,
933 "writable contiguous buffer requested "
934 "for a non-contiguous object.");
935 Py_DECREF(mv);
936 return NULL;
937 }
938
939 ret = memory_from_contiguous_copy(view, order);
940 Py_DECREF(mv);
941 return ret;
942}
943
944
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000945static PyObject *
946memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
947{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000948 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100949 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000950
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000951 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
952 &obj)) {
953 return NULL;
954 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000955
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000956 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000957}
958
959
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100960/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200961/* Previously in abstract.c */
962/****************************************************************************/
963
964typedef struct {
965 Py_buffer view;
966 Py_ssize_t array[1];
967} Py_buffer_full;
968
969int
970PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
971{
972 Py_buffer_full *fb = NULL;
973 int ret;
974
975 assert(order == 'C' || order == 'F' || order == 'A');
976
977 if (len != src->len) {
978 PyErr_SetString(PyExc_ValueError,
979 "PyBuffer_ToContiguous: len != view->len");
980 return -1;
981 }
982
983 if (PyBuffer_IsContiguous(src, order)) {
984 memcpy((char *)buf, src->buf, len);
985 return 0;
986 }
987
988 /* buffer_to_contiguous() assumes PyBUF_FULL */
989 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
990 if (fb == NULL) {
991 PyErr_NoMemory();
992 return -1;
993 }
994 fb->view.ndim = src->ndim;
995 fb->view.shape = fb->array;
996 fb->view.strides = fb->array + src->ndim;
997 fb->view.suboffsets = fb->array + 2 * src->ndim;
998
999 init_shared_values(&fb->view, src);
1000 init_shape_strides(&fb->view, src);
1001 init_suboffsets(&fb->view, src);
1002
1003 src = &fb->view;
1004
1005 ret = buffer_to_contiguous(buf, src, order);
1006 PyMem_Free(fb);
1007 return ret;
1008}
1009
1010
1011/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001012/* Release/GC management */
1013/****************************************************************************/
1014
1015/* Inform the managed buffer that this particular memoryview will not access
1016 the underlying buffer again. If no other memoryviews are registered with
1017 the managed buffer, the underlying buffer is released instantly and
1018 marked as inaccessible for both the memoryview and the managed buffer.
1019
1020 This function fails if the memoryview itself has exported buffers. */
1021static int
1022_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001023{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001024 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1025 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001026
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001027 if (self->exports == 0) {
1028 self->flags |= _Py_MEMORYVIEW_RELEASED;
1029 assert(self->mbuf->exports > 0);
1030 if (--self->mbuf->exports == 0)
1031 mbuf_release(self->mbuf);
1032 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001033 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001034 if (self->exports > 0) {
1035 PyErr_Format(PyExc_BufferError,
1036 "memoryview has %zd exported buffer%s", self->exports,
1037 self->exports==1 ? "" : "s");
1038 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001039 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001040
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001041 Py_FatalError("_memory_release(): negative export count");
1042 return -1;
1043}
1044
1045static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001046memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001047{
1048 if (_memory_release(self) < 0)
1049 return NULL;
1050 Py_RETURN_NONE;
1051}
1052
1053static void
1054memory_dealloc(PyMemoryViewObject *self)
1055{
1056 assert(self->exports == 0);
1057 _PyObject_GC_UNTRACK(self);
1058 (void)_memory_release(self);
1059 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001060 if (self->weakreflist != NULL)
1061 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001062 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001063}
1064
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001065static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001066memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001067{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001068 Py_VISIT(self->mbuf);
1069 return 0;
1070}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001071
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001072static int
1073memory_clear(PyMemoryViewObject *self)
1074{
1075 (void)_memory_release(self);
1076 Py_CLEAR(self->mbuf);
1077 return 0;
1078}
1079
1080static PyObject *
1081memory_enter(PyObject *self, PyObject *args)
1082{
1083 CHECK_RELEASED(self);
1084 Py_INCREF(self);
1085 return self;
1086}
1087
1088static PyObject *
1089memory_exit(PyObject *self, PyObject *args)
1090{
Stefan Krahe4c07992012-07-28 14:10:02 +02001091 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001092}
1093
1094
1095/****************************************************************************/
1096/* Casting format and shape */
1097/****************************************************************************/
1098
1099#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1100
1101Py_LOCAL_INLINE(Py_ssize_t)
1102get_native_fmtchar(char *result, const char *fmt)
1103{
1104 Py_ssize_t size = -1;
1105
1106 if (fmt[0] == '@') fmt++;
1107
1108 switch (fmt[0]) {
1109 case 'c': case 'b': case 'B': size = sizeof(char); break;
1110 case 'h': case 'H': size = sizeof(short); break;
1111 case 'i': case 'I': size = sizeof(int); break;
1112 case 'l': case 'L': size = sizeof(long); break;
1113 #ifdef HAVE_LONG_LONG
1114 case 'q': case 'Q': size = sizeof(PY_LONG_LONG); break;
1115 #endif
1116 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1117 case 'f': size = sizeof(float); break;
1118 case 'd': size = sizeof(double); break;
1119 #ifdef HAVE_C99_BOOL
1120 case '?': size = sizeof(_Bool); break;
1121 #else
1122 case '?': size = sizeof(char); break;
1123 #endif
1124 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001125 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001126
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001127 if (size > 0 && fmt[1] == '\0') {
1128 *result = fmt[0];
1129 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001130 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001131
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001132 return -1;
1133}
1134
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001135Py_LOCAL_INLINE(char *)
1136get_native_fmtstr(const char *fmt)
1137{
1138 int at = 0;
1139
1140 if (fmt[0] == '@') {
1141 at = 1;
1142 fmt++;
1143 }
1144 if (fmt[0] == '\0' || fmt[1] != '\0') {
1145 return NULL;
1146 }
1147
1148#define RETURN(s) do { return at ? "@" s : s; } while (0)
1149
1150 switch (fmt[0]) {
1151 case 'c': RETURN("c");
1152 case 'b': RETURN("b");
1153 case 'B': RETURN("B");
1154 case 'h': RETURN("h");
1155 case 'H': RETURN("H");
1156 case 'i': RETURN("i");
1157 case 'I': RETURN("I");
1158 case 'l': RETURN("l");
1159 case 'L': RETURN("L");
1160 #ifdef HAVE_LONG_LONG
1161 case 'q': RETURN("q");
1162 case 'Q': RETURN("Q");
1163 #endif
1164 case 'n': RETURN("n");
1165 case 'N': RETURN("N");
1166 case 'f': RETURN("f");
1167 case 'd': RETURN("d");
1168 #ifdef HAVE_C99_BOOL
1169 case '?': RETURN("?");
1170 #else
1171 case '?': RETURN("?");
1172 #endif
1173 case 'P': RETURN("P");
1174 }
1175
1176 return NULL;
1177}
1178
1179
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001180/* Cast a memoryview's data type to 'format'. The input array must be
1181 C-contiguous. At least one of input-format, output-format must have
1182 byte size. The output array is 1-D, with the same byte length as the
1183 input array. Thus, view->len must be a multiple of the new itemsize. */
1184static int
1185cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1186{
1187 Py_buffer *view = &mv->view;
1188 PyObject *asciifmt;
1189 char srcchar, destchar;
1190 Py_ssize_t itemsize;
1191 int ret = -1;
1192
1193 assert(view->ndim >= 1);
1194 assert(Py_SIZE(mv) == 3*view->ndim);
1195 assert(view->shape == mv->ob_array);
1196 assert(view->strides == mv->ob_array + view->ndim);
1197 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1198
1199 if (get_native_fmtchar(&srcchar, view->format) < 0) {
1200 PyErr_SetString(PyExc_ValueError,
1201 "memoryview: source format must be a native single character "
1202 "format prefixed with an optional '@'");
1203 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001204 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001205
1206 asciifmt = PyUnicode_AsASCIIString(format);
1207 if (asciifmt == NULL)
1208 return ret;
1209
1210 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1211 if (itemsize < 0) {
1212 PyErr_SetString(PyExc_ValueError,
1213 "memoryview: destination format must be a native single "
1214 "character format prefixed with an optional '@'");
1215 goto out;
1216 }
1217
1218 if (!IS_BYTE_FORMAT(srcchar) && !IS_BYTE_FORMAT(destchar)) {
1219 PyErr_SetString(PyExc_TypeError,
1220 "memoryview: cannot cast between two non-byte formats");
1221 goto out;
1222 }
1223 if (view->len % itemsize) {
1224 PyErr_SetString(PyExc_TypeError,
1225 "memoryview: length is not a multiple of itemsize");
1226 goto out;
1227 }
1228
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001229 view->format = get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
1230 if (view->format == NULL) {
1231 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1232 PyErr_SetString(PyExc_RuntimeError,
1233 "memoryview: internal error");
1234 goto out;
1235 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001236 view->itemsize = itemsize;
1237
1238 view->ndim = 1;
1239 view->shape[0] = view->len / view->itemsize;
1240 view->strides[0] = view->itemsize;
1241 view->suboffsets = NULL;
1242
1243 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001244
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001245 ret = 0;
1246
1247out:
1248 Py_DECREF(asciifmt);
1249 return ret;
1250}
1251
1252/* The memoryview must have space for 3*len(seq) elements. */
1253static Py_ssize_t
1254copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1255 Py_ssize_t itemsize)
1256{
1257 Py_ssize_t x, i;
1258 Py_ssize_t len = itemsize;
1259
1260 for (i = 0; i < ndim; i++) {
1261 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1262 if (!PyLong_Check(tmp)) {
1263 PyErr_SetString(PyExc_TypeError,
1264 "memoryview.cast(): elements of shape must be integers");
1265 return -1;
1266 }
1267 x = PyLong_AsSsize_t(tmp);
1268 if (x == -1 && PyErr_Occurred()) {
1269 return -1;
1270 }
1271 if (x <= 0) {
1272 /* In general elements of shape may be 0, but not for casting. */
1273 PyErr_Format(PyExc_ValueError,
1274 "memoryview.cast(): elements of shape must be integers > 0");
1275 return -1;
1276 }
1277 if (x > PY_SSIZE_T_MAX / len) {
1278 PyErr_Format(PyExc_ValueError,
1279 "memoryview.cast(): product(shape) > SSIZE_MAX");
1280 return -1;
1281 }
1282 len *= x;
1283 shape[i] = x;
1284 }
1285
1286 return len;
1287}
1288
1289/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1290 If the result array does not have exactly the same byte length as the
1291 input array, raise ValueError. */
1292static int
1293cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1294{
1295 Py_buffer *view = &mv->view;
1296 Py_ssize_t len;
1297
1298 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1299 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1300 assert(view->shape == mv->ob_array);
1301 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1302 assert(view->suboffsets == NULL);
1303
1304 view->ndim = ndim;
1305 if (view->ndim == 0) {
1306 view->shape = NULL;
1307 view->strides = NULL;
1308 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001309 }
1310 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001311 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1312 if (len < 0)
1313 return -1;
1314 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001315 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001316
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001317 if (view->len != len) {
1318 PyErr_SetString(PyExc_TypeError,
1319 "memoryview: product(shape) * itemsize != buffer size");
1320 return -1;
1321 }
1322
1323 init_flags(mv);
1324
1325 return 0;
1326}
1327
1328static int
1329zero_in_shape(PyMemoryViewObject *mv)
1330{
1331 Py_buffer *view = &mv->view;
1332 Py_ssize_t i;
1333
1334 for (i = 0; i < view->ndim; i++)
1335 if (view->shape[i] == 0)
1336 return 1;
1337
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001338 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001339}
1340
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001341/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001342 Cast a copy of 'self' to a different view. The input view must
1343 be C-contiguous. The function always casts the input view to a
1344 1-D output according to 'format'. At least one of input-format,
1345 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001346
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001347 If 'shape' is given, the 1-D view from the previous step will
1348 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001349
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001350 All casts must result in views that will have the exact byte
1351 size of the original input. Otherwise, an error is raised.
1352*/
1353static PyObject *
1354memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001355{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001356 static char *kwlist[] = {"format", "shape", NULL};
1357 PyMemoryViewObject *mv = NULL;
1358 PyObject *shape = NULL;
1359 PyObject *format;
1360 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001361
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001362 CHECK_RELEASED(self);
1363
1364 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1365 &format, &shape)) {
1366 return NULL;
1367 }
1368 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001369 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001370 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001371 return NULL;
1372 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001373 if (!MV_C_CONTIGUOUS(self->flags)) {
1374 PyErr_SetString(PyExc_TypeError,
1375 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001376 return NULL;
1377 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001378 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001379 PyErr_SetString(PyExc_TypeError,
1380 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001381 return NULL;
1382 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001383 if (shape) {
1384 CHECK_LIST_OR_TUPLE(shape)
1385 ndim = PySequence_Fast_GET_SIZE(shape);
1386 if (ndim > PyBUF_MAX_NDIM) {
1387 PyErr_SetString(PyExc_ValueError,
1388 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001389 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001390 return NULL;
1391 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001392 if (self->view.ndim != 1 && ndim != 1) {
1393 PyErr_SetString(PyExc_TypeError,
1394 "memoryview: cast must be 1D -> ND or ND -> 1D");
1395 return NULL;
1396 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001397 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001398
1399 mv = (PyMemoryViewObject *)
1400 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1401 if (mv == NULL)
1402 return NULL;
1403
1404 if (cast_to_1D(mv, format) < 0)
1405 goto error;
1406 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1407 goto error;
1408
1409 return (PyObject *)mv;
1410
1411error:
1412 Py_DECREF(mv);
1413 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001414}
1415
1416
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001417/**************************************************************************/
1418/* getbuffer */
1419/**************************************************************************/
1420
1421static int
1422memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1423{
1424 Py_buffer *base = &self->view;
1425 int baseflags = self->flags;
1426
1427 CHECK_RELEASED_INT(self);
1428
1429 /* start with complete information */
1430 *view = *base;
1431 view->obj = NULL;
1432
1433 if (REQ_WRITABLE(flags) && base->readonly) {
1434 PyErr_SetString(PyExc_BufferError,
1435 "memoryview: underlying buffer is not writable");
1436 return -1;
1437 }
1438 if (!REQ_FORMAT(flags)) {
1439 /* NULL indicates that the buffer's data type has been cast to 'B'.
1440 view->itemsize is the _previous_ itemsize. If shape is present,
1441 the equality product(shape) * itemsize = len still holds at this
1442 point. The equality calcsize(format) = itemsize does _not_ hold
1443 from here on! */
1444 view->format = NULL;
1445 }
1446
1447 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1448 PyErr_SetString(PyExc_BufferError,
1449 "memoryview: underlying buffer is not C-contiguous");
1450 return -1;
1451 }
1452 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1453 PyErr_SetString(PyExc_BufferError,
1454 "memoryview: underlying buffer is not Fortran contiguous");
1455 return -1;
1456 }
1457 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1458 PyErr_SetString(PyExc_BufferError,
1459 "memoryview: underlying buffer is not contiguous");
1460 return -1;
1461 }
1462 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1463 PyErr_SetString(PyExc_BufferError,
1464 "memoryview: underlying buffer requires suboffsets");
1465 return -1;
1466 }
1467 if (!REQ_STRIDES(flags)) {
1468 if (!MV_C_CONTIGUOUS(baseflags)) {
1469 PyErr_SetString(PyExc_BufferError,
1470 "memoryview: underlying buffer is not C-contiguous");
1471 return -1;
1472 }
1473 view->strides = NULL;
1474 }
1475 if (!REQ_SHAPE(flags)) {
1476 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1477 so base->buf = ndbuf->data. */
1478 if (view->format != NULL) {
1479 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1480 not make sense. */
1481 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001482 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001483 "is present");
1484 return -1;
1485 }
1486 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1487 do _not_ hold from here on! */
1488 view->ndim = 1;
1489 view->shape = NULL;
1490 }
1491
1492
1493 view->obj = (PyObject *)self;
1494 Py_INCREF(view->obj);
1495 self->exports++;
1496
1497 return 0;
1498}
1499
1500static void
1501memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1502{
1503 self->exports--;
1504 return;
1505 /* PyBuffer_Release() decrements view->obj after this function returns. */
1506}
1507
1508/* Buffer methods */
1509static PyBufferProcs memory_as_buffer = {
1510 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1511 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1512};
1513
1514
1515/****************************************************************************/
1516/* Optimized pack/unpack for all native format specifiers */
1517/****************************************************************************/
1518
1519/*
1520 Fix exceptions:
1521 1) Include format string in the error message.
1522 2) OverflowError -> ValueError.
1523 3) The error message from PyNumber_Index() is not ideal.
1524*/
1525static int
1526type_error_int(const char *fmt)
1527{
1528 PyErr_Format(PyExc_TypeError,
1529 "memoryview: invalid type for format '%s'", fmt);
1530 return -1;
1531}
1532
1533static int
1534value_error_int(const char *fmt)
1535{
1536 PyErr_Format(PyExc_ValueError,
1537 "memoryview: invalid value for format '%s'", fmt);
1538 return -1;
1539}
1540
1541static int
1542fix_error_int(const char *fmt)
1543{
1544 assert(PyErr_Occurred());
1545 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1546 PyErr_Clear();
1547 return type_error_int(fmt);
1548 }
1549 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1550 PyErr_ExceptionMatches(PyExc_ValueError)) {
1551 PyErr_Clear();
1552 return value_error_int(fmt);
1553 }
1554
1555 return -1;
1556}
1557
1558/* Accept integer objects or objects with an __index__() method. */
1559static long
1560pylong_as_ld(PyObject *item)
1561{
1562 PyObject *tmp;
1563 long ld;
1564
1565 tmp = PyNumber_Index(item);
1566 if (tmp == NULL)
1567 return -1;
1568
1569 ld = PyLong_AsLong(tmp);
1570 Py_DECREF(tmp);
1571 return ld;
1572}
1573
1574static unsigned long
1575pylong_as_lu(PyObject *item)
1576{
1577 PyObject *tmp;
1578 unsigned long lu;
1579
1580 tmp = PyNumber_Index(item);
1581 if (tmp == NULL)
1582 return (unsigned long)-1;
1583
1584 lu = PyLong_AsUnsignedLong(tmp);
1585 Py_DECREF(tmp);
1586 return lu;
1587}
1588
1589#ifdef HAVE_LONG_LONG
1590static PY_LONG_LONG
1591pylong_as_lld(PyObject *item)
1592{
1593 PyObject *tmp;
1594 PY_LONG_LONG lld;
1595
1596 tmp = PyNumber_Index(item);
1597 if (tmp == NULL)
1598 return -1;
1599
1600 lld = PyLong_AsLongLong(tmp);
1601 Py_DECREF(tmp);
1602 return lld;
1603}
1604
1605static unsigned PY_LONG_LONG
1606pylong_as_llu(PyObject *item)
1607{
1608 PyObject *tmp;
1609 unsigned PY_LONG_LONG llu;
1610
1611 tmp = PyNumber_Index(item);
1612 if (tmp == NULL)
1613 return (unsigned PY_LONG_LONG)-1;
1614
1615 llu = PyLong_AsUnsignedLongLong(tmp);
1616 Py_DECREF(tmp);
1617 return llu;
1618}
1619#endif
1620
1621static Py_ssize_t
1622pylong_as_zd(PyObject *item)
1623{
1624 PyObject *tmp;
1625 Py_ssize_t zd;
1626
1627 tmp = PyNumber_Index(item);
1628 if (tmp == NULL)
1629 return -1;
1630
1631 zd = PyLong_AsSsize_t(tmp);
1632 Py_DECREF(tmp);
1633 return zd;
1634}
1635
1636static size_t
1637pylong_as_zu(PyObject *item)
1638{
1639 PyObject *tmp;
1640 size_t zu;
1641
1642 tmp = PyNumber_Index(item);
1643 if (tmp == NULL)
1644 return (size_t)-1;
1645
1646 zu = PyLong_AsSize_t(tmp);
1647 Py_DECREF(tmp);
1648 return zu;
1649}
1650
1651/* Timings with the ndarray from _testbuffer.c indicate that using the
1652 struct module is around 15x slower than the two functions below. */
1653
1654#define UNPACK_SINGLE(dest, ptr, type) \
1655 do { \
1656 type x; \
1657 memcpy((char *)&x, ptr, sizeof x); \
1658 dest = x; \
1659 } while (0)
1660
1661/* Unpack a single item. 'fmt' can be any native format character in struct
1662 module syntax. This function is very sensitive to small changes. With this
1663 layout gcc automatically generates a fast jump table. */
1664Py_LOCAL_INLINE(PyObject *)
1665unpack_single(const char *ptr, const char *fmt)
1666{
1667 unsigned PY_LONG_LONG llu;
1668 unsigned long lu;
1669 size_t zu;
1670 PY_LONG_LONG lld;
1671 long ld;
1672 Py_ssize_t zd;
1673 double d;
1674 unsigned char uc;
1675 void *p;
1676
1677 switch (fmt[0]) {
1678
1679 /* signed integers and fast path for 'B' */
1680 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1681 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1682 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1683 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1684 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1685
1686 /* boolean */
1687 #ifdef HAVE_C99_BOOL
1688 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
1689 #else
1690 case '?': UNPACK_SINGLE(ld, ptr, char); goto convert_bool;
1691 #endif
1692
1693 /* unsigned integers */
1694 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1695 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1696 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1697
1698 /* native 64-bit */
1699 #ifdef HAVE_LONG_LONG
1700 case 'q': UNPACK_SINGLE(lld, ptr, PY_LONG_LONG); goto convert_lld;
1701 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned PY_LONG_LONG); goto convert_llu;
1702 #endif
1703
1704 /* ssize_t and size_t */
1705 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1706 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1707
1708 /* floats */
1709 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1710 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1711
1712 /* bytes object */
1713 case 'c': goto convert_bytes;
1714
1715 /* pointer */
1716 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1717
1718 /* default */
1719 default: goto err_format;
1720 }
1721
1722convert_uc:
1723 /* PyLong_FromUnsignedLong() is slower */
1724 return PyLong_FromLong(uc);
1725convert_ld:
1726 return PyLong_FromLong(ld);
1727convert_lu:
1728 return PyLong_FromUnsignedLong(lu);
1729convert_lld:
1730 return PyLong_FromLongLong(lld);
1731convert_llu:
1732 return PyLong_FromUnsignedLongLong(llu);
1733convert_zd:
1734 return PyLong_FromSsize_t(zd);
1735convert_zu:
1736 return PyLong_FromSize_t(zu);
1737convert_double:
1738 return PyFloat_FromDouble(d);
1739convert_bool:
1740 return PyBool_FromLong(ld);
1741convert_bytes:
1742 return PyBytes_FromStringAndSize(ptr, 1);
1743convert_pointer:
1744 return PyLong_FromVoidPtr(p);
1745err_format:
1746 PyErr_Format(PyExc_NotImplementedError,
1747 "memoryview: format %s not supported", fmt);
1748 return NULL;
1749}
1750
1751#define PACK_SINGLE(ptr, src, type) \
1752 do { \
1753 type x; \
1754 x = (type)src; \
1755 memcpy(ptr, (char *)&x, sizeof x); \
1756 } while (0)
1757
1758/* Pack a single item. 'fmt' can be any native format character in
1759 struct module syntax. */
1760static int
1761pack_single(char *ptr, PyObject *item, const char *fmt)
1762{
1763 unsigned PY_LONG_LONG llu;
1764 unsigned long lu;
1765 size_t zu;
1766 PY_LONG_LONG lld;
1767 long ld;
1768 Py_ssize_t zd;
1769 double d;
1770 void *p;
1771
1772 switch (fmt[0]) {
1773 /* signed integers */
1774 case 'b': case 'h': case 'i': case 'l':
1775 ld = pylong_as_ld(item);
1776 if (ld == -1 && PyErr_Occurred())
1777 goto err_occurred;
1778 switch (fmt[0]) {
1779 case 'b':
1780 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1781 *((signed char *)ptr) = (signed char)ld; break;
1782 case 'h':
1783 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1784 PACK_SINGLE(ptr, ld, short); break;
1785 case 'i':
1786 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1787 PACK_SINGLE(ptr, ld, int); break;
1788 default: /* 'l' */
1789 PACK_SINGLE(ptr, ld, long); break;
1790 }
1791 break;
1792
1793 /* unsigned integers */
1794 case 'B': case 'H': case 'I': case 'L':
1795 lu = pylong_as_lu(item);
1796 if (lu == (unsigned long)-1 && PyErr_Occurred())
1797 goto err_occurred;
1798 switch (fmt[0]) {
1799 case 'B':
1800 if (lu > UCHAR_MAX) goto err_range;
1801 *((unsigned char *)ptr) = (unsigned char)lu; break;
1802 case 'H':
1803 if (lu > USHRT_MAX) goto err_range;
1804 PACK_SINGLE(ptr, lu, unsigned short); break;
1805 case 'I':
1806 if (lu > UINT_MAX) goto err_range;
1807 PACK_SINGLE(ptr, lu, unsigned int); break;
1808 default: /* 'L' */
1809 PACK_SINGLE(ptr, lu, unsigned long); break;
1810 }
1811 break;
1812
1813 /* native 64-bit */
1814 #ifdef HAVE_LONG_LONG
1815 case 'q':
1816 lld = pylong_as_lld(item);
1817 if (lld == -1 && PyErr_Occurred())
1818 goto err_occurred;
1819 PACK_SINGLE(ptr, lld, PY_LONG_LONG);
1820 break;
1821 case 'Q':
1822 llu = pylong_as_llu(item);
1823 if (llu == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
1824 goto err_occurred;
1825 PACK_SINGLE(ptr, llu, unsigned PY_LONG_LONG);
1826 break;
1827 #endif
1828
1829 /* ssize_t and size_t */
1830 case 'n':
1831 zd = pylong_as_zd(item);
1832 if (zd == -1 && PyErr_Occurred())
1833 goto err_occurred;
1834 PACK_SINGLE(ptr, zd, Py_ssize_t);
1835 break;
1836 case 'N':
1837 zu = pylong_as_zu(item);
1838 if (zu == (size_t)-1 && PyErr_Occurred())
1839 goto err_occurred;
1840 PACK_SINGLE(ptr, zu, size_t);
1841 break;
1842
1843 /* floats */
1844 case 'f': case 'd':
1845 d = PyFloat_AsDouble(item);
1846 if (d == -1.0 && PyErr_Occurred())
1847 goto err_occurred;
1848 if (fmt[0] == 'f') {
1849 PACK_SINGLE(ptr, d, float);
1850 }
1851 else {
1852 PACK_SINGLE(ptr, d, double);
1853 }
1854 break;
1855
1856 /* bool */
1857 case '?':
1858 ld = PyObject_IsTrue(item);
1859 if (ld < 0)
1860 return -1; /* preserve original error */
1861 #ifdef HAVE_C99_BOOL
1862 PACK_SINGLE(ptr, ld, _Bool);
1863 #else
1864 PACK_SINGLE(ptr, ld, char);
1865 #endif
1866 break;
1867
1868 /* bytes object */
1869 case 'c':
1870 if (!PyBytes_Check(item))
1871 return type_error_int(fmt);
1872 if (PyBytes_GET_SIZE(item) != 1)
1873 return value_error_int(fmt);
1874 *ptr = PyBytes_AS_STRING(item)[0];
1875 break;
1876
1877 /* pointer */
1878 case 'P':
1879 p = PyLong_AsVoidPtr(item);
1880 if (p == NULL && PyErr_Occurred())
1881 goto err_occurred;
1882 PACK_SINGLE(ptr, p, void *);
1883 break;
1884
1885 /* default */
1886 default: goto err_format;
1887 }
1888
1889 return 0;
1890
1891err_occurred:
1892 return fix_error_int(fmt);
1893err_range:
1894 return value_error_int(fmt);
1895err_format:
1896 PyErr_Format(PyExc_NotImplementedError,
1897 "memoryview: format %s not supported", fmt);
1898 return -1;
1899}
1900
1901
1902/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001903/* unpack using the struct module */
1904/****************************************************************************/
1905
1906/* For reasonable performance it is necessary to cache all objects required
1907 for unpacking. An unpacker can handle the format passed to unpack_from().
1908 Invariant: All pointer fields of the struct should either be NULL or valid
1909 pointers. */
1910struct unpacker {
1911 PyObject *unpack_from; /* Struct.unpack_from(format) */
1912 PyObject *mview; /* cached memoryview */
1913 char *item; /* buffer for mview */
1914 Py_ssize_t itemsize; /* len(item) */
1915};
1916
1917static struct unpacker *
1918unpacker_new(void)
1919{
1920 struct unpacker *x = PyMem_Malloc(sizeof *x);
1921
1922 if (x == NULL) {
1923 PyErr_NoMemory();
1924 return NULL;
1925 }
1926
1927 x->unpack_from = NULL;
1928 x->mview = NULL;
1929 x->item = NULL;
1930 x->itemsize = 0;
1931
1932 return x;
1933}
1934
1935static void
1936unpacker_free(struct unpacker *x)
1937{
1938 if (x) {
1939 Py_XDECREF(x->unpack_from);
1940 Py_XDECREF(x->mview);
1941 PyMem_Free(x->item);
1942 PyMem_Free(x);
1943 }
1944}
1945
1946/* Return a new unpacker for the given format. */
1947static struct unpacker *
1948struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1949{
1950 PyObject *structmodule; /* XXX cache these two */
1951 PyObject *Struct = NULL; /* XXX in globals? */
1952 PyObject *structobj = NULL;
1953 PyObject *format = NULL;
1954 struct unpacker *x = NULL;
1955
1956 structmodule = PyImport_ImportModule("struct");
1957 if (structmodule == NULL)
1958 return NULL;
1959
1960 Struct = PyObject_GetAttrString(structmodule, "Struct");
1961 Py_DECREF(structmodule);
1962 if (Struct == NULL)
1963 return NULL;
1964
1965 x = unpacker_new();
1966 if (x == NULL)
1967 goto error;
1968
1969 format = PyBytes_FromString(fmt);
1970 if (format == NULL)
1971 goto error;
1972
1973 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1974 if (structobj == NULL)
1975 goto error;
1976
1977 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1978 if (x->unpack_from == NULL)
1979 goto error;
1980
1981 x->item = PyMem_Malloc(itemsize);
1982 if (x->item == NULL) {
1983 PyErr_NoMemory();
1984 goto error;
1985 }
1986 x->itemsize = itemsize;
1987
1988 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1989 if (x->mview == NULL)
1990 goto error;
1991
1992
1993out:
1994 Py_XDECREF(Struct);
1995 Py_XDECREF(format);
1996 Py_XDECREF(structobj);
1997 return x;
1998
1999error:
2000 unpacker_free(x);
2001 x = NULL;
2002 goto out;
2003}
2004
2005/* unpack a single item */
2006static PyObject *
2007struct_unpack_single(const char *ptr, struct unpacker *x)
2008{
2009 PyObject *v;
2010
2011 memcpy(x->item, ptr, x->itemsize);
2012 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
2013 if (v == NULL)
2014 return NULL;
2015
2016 if (PyTuple_GET_SIZE(v) == 1) {
2017 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2018 Py_INCREF(tmp);
2019 Py_DECREF(v);
2020 return tmp;
2021 }
2022
2023 return v;
2024}
2025
2026
2027/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002028/* Representations */
2029/****************************************************************************/
2030
2031/* allow explicit form of native format */
2032Py_LOCAL_INLINE(const char *)
2033adjust_fmt(const Py_buffer *view)
2034{
2035 const char *fmt;
2036
2037 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2038 if (fmt[0] && fmt[1] == '\0')
2039 return fmt;
2040
2041 PyErr_Format(PyExc_NotImplementedError,
2042 "memoryview: unsupported format %s", view->format);
2043 return NULL;
2044}
2045
2046/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2047static PyObject *
2048tolist_base(const char *ptr, const Py_ssize_t *shape,
2049 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2050 const char *fmt)
2051{
2052 PyObject *lst, *item;
2053 Py_ssize_t i;
2054
2055 lst = PyList_New(shape[0]);
2056 if (lst == NULL)
2057 return NULL;
2058
2059 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002060 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002061 item = unpack_single(xptr, fmt);
2062 if (item == NULL) {
2063 Py_DECREF(lst);
2064 return NULL;
2065 }
2066 PyList_SET_ITEM(lst, i, item);
2067 }
2068
2069 return lst;
2070}
2071
2072/* Unpack a multi-dimensional array into a nested list.
2073 Assumption: ndim >= 1. */
2074static PyObject *
2075tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2076 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2077 const char *fmt)
2078{
2079 PyObject *lst, *item;
2080 Py_ssize_t i;
2081
2082 assert(ndim >= 1);
2083 assert(shape != NULL);
2084 assert(strides != NULL);
2085
2086 if (ndim == 1)
2087 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2088
2089 lst = PyList_New(shape[0]);
2090 if (lst == NULL)
2091 return NULL;
2092
2093 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002094 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002095 item = tolist_rec(xptr, ndim-1, shape+1,
2096 strides+1, suboffsets ? suboffsets+1 : NULL,
2097 fmt);
2098 if (item == NULL) {
2099 Py_DECREF(lst);
2100 return NULL;
2101 }
2102 PyList_SET_ITEM(lst, i, item);
2103 }
2104
2105 return lst;
2106}
2107
2108/* Return a list representation of the memoryview. Currently only buffers
2109 with native format strings are supported. */
2110static PyObject *
2111memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2112{
2113 const Py_buffer *view = &(mv->view);
2114 const char *fmt;
2115
2116 CHECK_RELEASED(mv);
2117
2118 fmt = adjust_fmt(view);
2119 if (fmt == NULL)
2120 return NULL;
2121 if (view->ndim == 0) {
2122 return unpack_single(view->buf, fmt);
2123 }
2124 else if (view->ndim == 1) {
2125 return tolist_base(view->buf, view->shape,
2126 view->strides, view->suboffsets,
2127 fmt);
2128 }
2129 else {
2130 return tolist_rec(view->buf, view->ndim, view->shape,
2131 view->strides, view->suboffsets,
2132 fmt);
2133 }
2134}
2135
2136static PyObject *
2137memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
2138{
2139 Py_buffer *src = VIEW_ADDR(self);
2140 PyObject *bytes = NULL;
2141
2142 CHECK_RELEASED(self);
2143
2144 if (MV_C_CONTIGUOUS(self->flags)) {
2145 return PyBytes_FromStringAndSize(src->buf, src->len);
2146 }
2147
2148 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2149 if (bytes == NULL)
2150 return NULL;
2151
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002152 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002153 Py_DECREF(bytes);
2154 return NULL;
2155 }
2156
2157 return bytes;
2158}
2159
2160static PyObject *
2161memory_repr(PyMemoryViewObject *self)
2162{
2163 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2164 return PyUnicode_FromFormat("<released memory at %p>", self);
2165 else
2166 return PyUnicode_FromFormat("<memory at %p>", self);
2167}
2168
2169
2170/**************************************************************************/
2171/* Indexing and slicing */
2172/**************************************************************************/
2173
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002174static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002175lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002176{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002177 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002178
2179 assert(view->shape);
2180 assert(view->strides);
2181
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002182 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002183 if (index < 0) {
2184 index += nitems;
2185 }
2186 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002187 PyErr_Format(PyExc_IndexError,
2188 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002189 return NULL;
2190 }
2191
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002192 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002193
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002194 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002195
2196 return ptr;
2197}
2198
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002199/* Get the pointer to the item at index. */
2200static char *
2201ptr_from_index(Py_buffer *view, Py_ssize_t index)
2202{
2203 char *ptr = (char *)view->buf;
2204 return lookup_dimension(view, ptr, 0, index);
2205}
2206
2207/* Get the pointer to the item at tuple. */
2208static char *
2209ptr_from_tuple(Py_buffer *view, PyObject *tup)
2210{
2211 char *ptr = (char *)view->buf;
2212 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2213
2214 if (nindices > view->ndim) {
2215 PyErr_Format(PyExc_TypeError,
2216 "cannot index %zd-dimension view with %zd-element tuple",
2217 view->ndim, nindices);
2218 return NULL;
2219 }
2220
2221 for (dim = 0; dim < nindices; dim++) {
2222 Py_ssize_t index;
2223 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2224 PyExc_IndexError);
2225 if (index == -1 && PyErr_Occurred())
2226 return NULL;
2227 ptr = lookup_dimension(view, ptr, dim, index);
2228 if (ptr == NULL)
2229 return NULL;
2230 }
2231 return ptr;
2232}
2233
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002234/* Return the item at index. In a one-dimensional view, this is an object
2235 with the type specified by view->format. Otherwise, the item is a sub-view.
2236 The function is used in memory_subscript() and memory_as_sequence. */
2237static PyObject *
2238memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2239{
2240 Py_buffer *view = &(self->view);
2241 const char *fmt;
2242
2243 CHECK_RELEASED(self);
2244
2245 fmt = adjust_fmt(view);
2246 if (fmt == NULL)
2247 return NULL;
2248
2249 if (view->ndim == 0) {
2250 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2251 return NULL;
2252 }
2253 if (view->ndim == 1) {
2254 char *ptr = ptr_from_index(view, index);
2255 if (ptr == NULL)
2256 return NULL;
2257 return unpack_single(ptr, fmt);
2258 }
2259
2260 PyErr_SetString(PyExc_NotImplementedError,
2261 "multi-dimensional sub-views are not implemented");
2262 return NULL;
2263}
2264
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002265/* Return the item at position *key* (a tuple of indices). */
2266static PyObject *
2267memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2268{
2269 Py_buffer *view = &(self->view);
2270 const char *fmt;
2271 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2272 char *ptr;
2273
2274 CHECK_RELEASED(self);
2275
2276 fmt = adjust_fmt(view);
2277 if (fmt == NULL)
2278 return NULL;
2279
2280 if (nindices < view->ndim) {
2281 PyErr_SetString(PyExc_NotImplementedError,
2282 "sub-views are not implemented");
2283 return NULL;
2284 }
2285 ptr = ptr_from_tuple(view, tup);
2286 if (ptr == NULL)
2287 return NULL;
2288 return unpack_single(ptr, fmt);
2289}
2290
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002291Py_LOCAL_INLINE(int)
2292init_slice(Py_buffer *base, PyObject *key, int dim)
2293{
2294 Py_ssize_t start, stop, step, slicelength;
2295
2296 if (PySlice_GetIndicesEx(key, base->shape[dim],
2297 &start, &stop, &step, &slicelength) < 0) {
2298 return -1;
2299 }
2300
2301
2302 if (base->suboffsets == NULL || dim == 0) {
2303 adjust_buf:
2304 base->buf = (char *)base->buf + base->strides[dim] * start;
2305 }
2306 else {
2307 Py_ssize_t n = dim-1;
2308 while (n >= 0 && base->suboffsets[n] < 0)
2309 n--;
2310 if (n < 0)
2311 goto adjust_buf; /* all suboffsets are negative */
2312 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2313 }
2314 base->shape[dim] = slicelength;
2315 base->strides[dim] = base->strides[dim] * step;
2316
2317 return 0;
2318}
2319
2320static int
2321is_multislice(PyObject *key)
2322{
2323 Py_ssize_t size, i;
2324
2325 if (!PyTuple_Check(key))
2326 return 0;
2327 size = PyTuple_GET_SIZE(key);
2328 if (size == 0)
2329 return 0;
2330
2331 for (i = 0; i < size; i++) {
2332 PyObject *x = PyTuple_GET_ITEM(key, i);
2333 if (!PySlice_Check(x))
2334 return 0;
2335 }
2336 return 1;
2337}
2338
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002339static Py_ssize_t
2340is_multiindex(PyObject *key)
2341{
2342 Py_ssize_t size, i;
2343
2344 if (!PyTuple_Check(key))
2345 return 0;
2346 size = PyTuple_GET_SIZE(key);
2347 for (i = 0; i < size; i++) {
2348 PyObject *x = PyTuple_GET_ITEM(key, i);
2349 if (!PyIndex_Check(x))
2350 return 0;
2351 }
2352 return 1;
2353}
2354
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002355/* mv[obj] returns an object holding the data for one element if obj
2356 fully indexes the memoryview or another memoryview object if it
2357 does not.
2358
2359 0-d memoryview objects can be referenced using mv[...] or mv[()]
2360 but not with anything else. */
2361static PyObject *
2362memory_subscript(PyMemoryViewObject *self, PyObject *key)
2363{
2364 Py_buffer *view;
2365 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002366
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002367 CHECK_RELEASED(self);
2368
2369 if (view->ndim == 0) {
2370 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2371 const char *fmt = adjust_fmt(view);
2372 if (fmt == NULL)
2373 return NULL;
2374 return unpack_single(view->buf, fmt);
2375 }
2376 else if (key == Py_Ellipsis) {
2377 Py_INCREF(self);
2378 return (PyObject *)self;
2379 }
2380 else {
2381 PyErr_SetString(PyExc_TypeError,
2382 "invalid indexing of 0-dim memory");
2383 return NULL;
2384 }
2385 }
2386
2387 if (PyIndex_Check(key)) {
2388 Py_ssize_t index;
2389 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2390 if (index == -1 && PyErr_Occurred())
2391 return NULL;
2392 return memory_item(self, index);
2393 }
2394 else if (PySlice_Check(key)) {
2395 PyMemoryViewObject *sliced;
2396
2397 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2398 if (sliced == NULL)
2399 return NULL;
2400
2401 if (init_slice(&sliced->view, key, 0) < 0) {
2402 Py_DECREF(sliced);
2403 return NULL;
2404 }
2405 init_len(&sliced->view);
2406 init_flags(sliced);
2407
2408 return (PyObject *)sliced;
2409 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002410 else if (is_multiindex(key)) {
2411 return memory_item_multi(self, key);
2412 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002413 else if (is_multislice(key)) {
2414 PyErr_SetString(PyExc_NotImplementedError,
2415 "multi-dimensional slicing is not implemented");
2416 return NULL;
2417 }
2418
2419 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2420 return NULL;
2421}
2422
2423static int
2424memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2425{
2426 Py_buffer *view = &(self->view);
2427 Py_buffer src;
2428 const char *fmt;
2429 char *ptr;
2430
2431 CHECK_RELEASED_INT(self);
2432
2433 fmt = adjust_fmt(view);
2434 if (fmt == NULL)
2435 return -1;
2436
2437 if (view->readonly) {
2438 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2439 return -1;
2440 }
2441 if (value == NULL) {
2442 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2443 return -1;
2444 }
2445 if (view->ndim == 0) {
2446 if (key == Py_Ellipsis ||
2447 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2448 ptr = (char *)view->buf;
2449 return pack_single(ptr, value, fmt);
2450 }
2451 else {
2452 PyErr_SetString(PyExc_TypeError,
2453 "invalid indexing of 0-dim memory");
2454 return -1;
2455 }
2456 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002457
2458 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002459 Py_ssize_t index;
2460 if (1 < view->ndim) {
2461 PyErr_SetString(PyExc_NotImplementedError,
2462 "sub-views are not implemented");
2463 return -1;
2464 }
2465 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002466 if (index == -1 && PyErr_Occurred())
2467 return -1;
2468 ptr = ptr_from_index(view, index);
2469 if (ptr == NULL)
2470 return -1;
2471 return pack_single(ptr, value, fmt);
2472 }
2473 /* one-dimensional: fast path */
2474 if (PySlice_Check(key) && view->ndim == 1) {
2475 Py_buffer dest; /* sliced view */
2476 Py_ssize_t arrays[3];
2477 int ret = -1;
2478
2479 /* rvalue must be an exporter */
2480 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2481 return ret;
2482
2483 dest = *view;
2484 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2485 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2486 if (view->suboffsets) {
2487 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2488 }
2489
2490 if (init_slice(&dest, key, 0) < 0)
2491 goto end_block;
2492 dest.len = dest.shape[0] * dest.itemsize;
2493
2494 ret = copy_single(&dest, &src);
2495
2496 end_block:
2497 PyBuffer_Release(&src);
2498 return ret;
2499 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002500 if (is_multiindex(key)) {
2501 char *ptr;
2502 if (PyTuple_GET_SIZE(key) < view->ndim) {
2503 PyErr_SetString(PyExc_NotImplementedError,
2504 "sub-views are not implemented");
2505 return -1;
2506 }
2507 ptr = ptr_from_tuple(view, key);
2508 if (ptr == NULL)
2509 return -1;
2510 return pack_single(ptr, value, fmt);
2511 }
2512 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002513 /* Call memory_subscript() to produce a sliced lvalue, then copy
2514 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2515 PyErr_SetString(PyExc_NotImplementedError,
2516 "memoryview slice assignments are currently restricted "
2517 "to ndim = 1");
2518 return -1;
2519 }
2520
2521 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2522 return -1;
2523}
2524
2525static Py_ssize_t
2526memory_length(PyMemoryViewObject *self)
2527{
2528 CHECK_RELEASED_INT(self);
2529 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2530}
2531
2532/* As mapping */
2533static PyMappingMethods memory_as_mapping = {
2534 (lenfunc)memory_length, /* mp_length */
2535 (binaryfunc)memory_subscript, /* mp_subscript */
2536 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2537};
2538
2539/* As sequence */
2540static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002541 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002542 0, /* sq_concat */
2543 0, /* sq_repeat */
2544 (ssizeargfunc)memory_item, /* sq_item */
2545};
2546
2547
2548/**************************************************************************/
2549/* Comparisons */
2550/**************************************************************************/
2551
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002552#define MV_COMPARE_EX -1 /* exception */
2553#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2554
2555/* Translate a StructError to "not equal". Preserve other exceptions. */
2556static int
2557fix_struct_error_int(void)
2558{
2559 assert(PyErr_Occurred());
2560 /* XXX Cannot get at StructError directly? */
2561 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2562 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2563 return MV_COMPARE_EX;
2564 }
2565 /* StructError: invalid or unknown format -> not equal */
2566 PyErr_Clear();
2567 return 0;
2568}
2569
2570/* Unpack and compare single items of p and q using the struct module. */
2571static int
2572struct_unpack_cmp(const char *p, const char *q,
2573 struct unpacker *unpack_p, struct unpacker *unpack_q)
2574{
2575 PyObject *v, *w;
2576 int ret;
2577
2578 /* At this point any exception from the struct module should not be
2579 StructError, since both formats have been accepted already. */
2580 v = struct_unpack_single(p, unpack_p);
2581 if (v == NULL)
2582 return MV_COMPARE_EX;
2583
2584 w = struct_unpack_single(q, unpack_q);
2585 if (w == NULL) {
2586 Py_DECREF(v);
2587 return MV_COMPARE_EX;
2588 }
2589
2590 /* MV_COMPARE_EX == -1: exceptions are preserved */
2591 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2592 Py_DECREF(v);
2593 Py_DECREF(w);
2594
2595 return ret;
2596}
2597
2598/* Unpack and compare single items of p and q. If both p and q have the same
2599 single element native format, the comparison uses a fast path (gcc creates
2600 a jump table and converts memcpy into simple assignments on x86/x64).
2601
2602 Otherwise, the comparison is delegated to the struct module, which is
2603 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002604#define CMP_SINGLE(p, q, type) \
2605 do { \
2606 type x; \
2607 type y; \
2608 memcpy((char *)&x, p, sizeof x); \
2609 memcpy((char *)&y, q, sizeof y); \
2610 equal = (x == y); \
2611 } while (0)
2612
2613Py_LOCAL_INLINE(int)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002614unpack_cmp(const char *p, const char *q, char fmt,
2615 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002616{
2617 int equal;
2618
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002619 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002620
2621 /* signed integers and fast path for 'B' */
2622 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2623 case 'b': return *((signed char *)p) == *((signed char *)q);
2624 case 'h': CMP_SINGLE(p, q, short); return equal;
2625 case 'i': CMP_SINGLE(p, q, int); return equal;
2626 case 'l': CMP_SINGLE(p, q, long); return equal;
2627
2628 /* boolean */
2629 #ifdef HAVE_C99_BOOL
2630 case '?': CMP_SINGLE(p, q, _Bool); return equal;
2631 #else
2632 case '?': CMP_SINGLE(p, q, char); return equal;
2633 #endif
2634
2635 /* unsigned integers */
2636 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2637 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2638 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2639
2640 /* native 64-bit */
2641 #ifdef HAVE_LONG_LONG
2642 case 'q': CMP_SINGLE(p, q, PY_LONG_LONG); return equal;
2643 case 'Q': CMP_SINGLE(p, q, unsigned PY_LONG_LONG); return equal;
2644 #endif
2645
2646 /* ssize_t and size_t */
2647 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2648 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2649
2650 /* floats */
2651 /* XXX DBL_EPSILON? */
2652 case 'f': CMP_SINGLE(p, q, float); return equal;
2653 case 'd': CMP_SINGLE(p, q, double); return equal;
2654
2655 /* bytes object */
2656 case 'c': return *p == *q;
2657
2658 /* pointer */
2659 case 'P': CMP_SINGLE(p, q, void *); return equal;
2660
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002661 /* use the struct module */
2662 case '_':
2663 assert(unpack_p);
2664 assert(unpack_q);
2665 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002666 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002667
2668 /* NOT REACHED */
2669 PyErr_SetString(PyExc_RuntimeError,
2670 "memoryview: internal error in richcompare");
2671 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002672}
2673
2674/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2675static int
2676cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2677 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2678 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002679 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002680{
2681 Py_ssize_t i;
2682 int equal;
2683
2684 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002685 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2686 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002687 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002688 if (equal <= 0)
2689 return equal;
2690 }
2691
2692 return 1;
2693}
2694
2695/* Recursively compare two multi-dimensional arrays that have the same
2696 logical structure. Assumption: ndim >= 1. */
2697static int
2698cmp_rec(const char *p, const char *q,
2699 Py_ssize_t ndim, const Py_ssize_t *shape,
2700 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2701 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002702 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002703{
2704 Py_ssize_t i;
2705 int equal;
2706
2707 assert(ndim >= 1);
2708 assert(shape != NULL);
2709 assert(pstrides != NULL);
2710 assert(qstrides != NULL);
2711
2712 if (ndim == 1) {
2713 return cmp_base(p, q, shape,
2714 pstrides, psuboffsets,
2715 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002716 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002717 }
2718
2719 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002720 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2721 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002722 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2723 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2724 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002725 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002726 if (equal <= 0)
2727 return equal;
2728 }
2729
2730 return 1;
2731}
2732
2733static PyObject *
2734memory_richcompare(PyObject *v, PyObject *w, int op)
2735{
2736 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002737 Py_buffer wbuf, *vv;
2738 Py_buffer *ww = NULL;
2739 struct unpacker *unpack_v = NULL;
2740 struct unpacker *unpack_w = NULL;
2741 char vfmt, wfmt;
2742 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002743
2744 if (op != Py_EQ && op != Py_NE)
2745 goto result; /* Py_NotImplemented */
2746
2747 assert(PyMemoryView_Check(v));
2748 if (BASE_INACCESSIBLE(v)) {
2749 equal = (v == w);
2750 goto result;
2751 }
2752 vv = VIEW_ADDR(v);
2753
2754 if (PyMemoryView_Check(w)) {
2755 if (BASE_INACCESSIBLE(w)) {
2756 equal = (v == w);
2757 goto result;
2758 }
2759 ww = VIEW_ADDR(w);
2760 }
2761 else {
2762 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2763 PyErr_Clear();
2764 goto result; /* Py_NotImplemented */
2765 }
2766 ww = &wbuf;
2767 }
2768
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002769 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002770 PyErr_Clear();
2771 equal = 0;
2772 goto result;
2773 }
2774
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002775 /* Use fast unpacking for identical primitive C type formats. */
2776 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2777 vfmt = '_';
2778 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2779 wfmt = '_';
2780 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2781 /* Use struct module unpacking. NOTE: Even for equal format strings,
2782 memcmp() cannot be used for item comparison since it would give
2783 incorrect results in the case of NaNs or uninitialized padding
2784 bytes. */
2785 vfmt = '_';
2786 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2787 if (unpack_v == NULL) {
2788 equal = fix_struct_error_int();
2789 goto result;
2790 }
2791 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2792 if (unpack_w == NULL) {
2793 equal = fix_struct_error_int();
2794 goto result;
2795 }
2796 }
2797
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002798 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002799 equal = unpack_cmp(vv->buf, ww->buf,
2800 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002801 }
2802 else if (vv->ndim == 1) {
2803 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2804 vv->strides, vv->suboffsets,
2805 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002806 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002807 }
2808 else {
2809 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2810 vv->strides, vv->suboffsets,
2811 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002812 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002813 }
2814
2815result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002816 if (equal < 0) {
2817 if (equal == MV_COMPARE_NOT_IMPL)
2818 res = Py_NotImplemented;
2819 else /* exception */
2820 res = NULL;
2821 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002822 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2823 res = Py_True;
2824 else
2825 res = Py_False;
2826
2827 if (ww == &wbuf)
2828 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002829
2830 unpacker_free(unpack_v);
2831 unpacker_free(unpack_w);
2832
2833 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002834 return res;
2835}
2836
2837/**************************************************************************/
2838/* Hash */
2839/**************************************************************************/
2840
2841static Py_hash_t
2842memory_hash(PyMemoryViewObject *self)
2843{
2844 if (self->hash == -1) {
2845 Py_buffer *view = &self->view;
2846 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002847 Py_ssize_t ret;
2848 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002849
2850 CHECK_RELEASED_INT(self);
2851
2852 if (!view->readonly) {
2853 PyErr_SetString(PyExc_ValueError,
2854 "cannot hash writable memoryview object");
2855 return -1;
2856 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002857 ret = get_native_fmtchar(&fmt, view->format);
2858 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2859 PyErr_SetString(PyExc_ValueError,
2860 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2861 return -1;
2862 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002863 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2864 /* Keep the original error message */
2865 return -1;
2866 }
2867
2868 if (!MV_C_CONTIGUOUS(self->flags)) {
2869 mem = PyMem_Malloc(view->len);
2870 if (mem == NULL) {
2871 PyErr_NoMemory();
2872 return -1;
2873 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002874 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002875 PyMem_Free(mem);
2876 return -1;
2877 }
2878 }
2879
2880 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002881 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002882
2883 if (mem != view->buf)
2884 PyMem_Free(mem);
2885 }
2886
2887 return self->hash;
2888}
2889
2890
2891/**************************************************************************/
2892/* getters */
2893/**************************************************************************/
2894
2895static PyObject *
2896_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2897{
2898 int i;
2899 PyObject *o;
2900 PyObject *intTuple;
2901
2902 if (vals == NULL)
2903 return PyTuple_New(0);
2904
2905 intTuple = PyTuple_New(len);
2906 if (!intTuple)
2907 return NULL;
2908 for (i=0; i<len; i++) {
2909 o = PyLong_FromSsize_t(vals[i]);
2910 if (!o) {
2911 Py_DECREF(intTuple);
2912 return NULL;
2913 }
2914 PyTuple_SET_ITEM(intTuple, i, o);
2915 }
2916 return intTuple;
2917}
2918
2919static PyObject *
2920memory_obj_get(PyMemoryViewObject *self)
2921{
2922 Py_buffer *view = &self->view;
2923
2924 CHECK_RELEASED(self);
2925 if (view->obj == NULL) {
2926 Py_RETURN_NONE;
2927 }
2928 Py_INCREF(view->obj);
2929 return view->obj;
2930}
2931
2932static PyObject *
2933memory_nbytes_get(PyMemoryViewObject *self)
2934{
2935 CHECK_RELEASED(self);
2936 return PyLong_FromSsize_t(self->view.len);
2937}
2938
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002939static PyObject *
2940memory_format_get(PyMemoryViewObject *self)
2941{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002942 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002943 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002944}
2945
2946static PyObject *
2947memory_itemsize_get(PyMemoryViewObject *self)
2948{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002949 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002950 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002951}
2952
2953static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002954memory_shape_get(PyMemoryViewObject *self)
2955{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002956 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002957 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002958}
2959
2960static PyObject *
2961memory_strides_get(PyMemoryViewObject *self)
2962{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002963 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002964 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002965}
2966
2967static PyObject *
2968memory_suboffsets_get(PyMemoryViewObject *self)
2969{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002970 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002971 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002972}
2973
2974static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002975memory_readonly_get(PyMemoryViewObject *self)
2976{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002977 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002978 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002979}
2980
2981static PyObject *
2982memory_ndim_get(PyMemoryViewObject *self)
2983{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002984 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002985 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002986}
2987
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002988static PyObject *
2989memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2990{
2991 CHECK_RELEASED(self);
2992 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
2993}
2994
2995static PyObject *
2996memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2997{
2998 CHECK_RELEASED(self);
2999 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3000}
3001
3002static PyObject *
3003memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3004{
3005 CHECK_RELEASED(self);
3006 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3007}
3008
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003009PyDoc_STRVAR(memory_obj_doc,
3010 "The underlying object of the memoryview.");
3011PyDoc_STRVAR(memory_nbytes_doc,
3012 "The amount of space in bytes that the array would use in\n"
3013 " a contiguous representation.");
3014PyDoc_STRVAR(memory_readonly_doc,
3015 "A bool indicating whether the memory is read only.");
3016PyDoc_STRVAR(memory_itemsize_doc,
3017 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003018PyDoc_STRVAR(memory_format_doc,
3019 "A string containing the format (in struct module style)\n"
3020 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003021PyDoc_STRVAR(memory_ndim_doc,
3022 "An integer indicating how many dimensions of a multi-dimensional\n"
3023 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003024PyDoc_STRVAR(memory_shape_doc,
3025 "A tuple of ndim integers giving the shape of the memory\n"
3026 " as an N-dimensional array.");
3027PyDoc_STRVAR(memory_strides_doc,
3028 "A tuple of ndim integers giving the size in bytes to access\n"
3029 " each element for each dimension of the array.");
3030PyDoc_STRVAR(memory_suboffsets_doc,
3031 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003032PyDoc_STRVAR(memory_c_contiguous_doc,
3033 "A bool indicating whether the memory is C contiguous.");
3034PyDoc_STRVAR(memory_f_contiguous_doc,
3035 "A bool indicating whether the memory is Fortran contiguous.");
3036PyDoc_STRVAR(memory_contiguous_doc,
3037 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003038
Stefan Krahbcaf5992014-05-18 00:35:09 +02003039
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003040static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003041 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3042 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003043 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3044 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3045 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3046 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3047 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3048 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3049 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003050 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3051 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3052 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003053 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003054};
3055
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003056PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003057"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003058\n\
3059Release the underlying buffer exposed by the memoryview object.");
3060PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003061"tobytes($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003062\n\
3063Return the data in the buffer as a byte string.");
3064PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003065"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003066\n\
3067Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003068PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003069"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003070\n\
3071Cast a memoryview to a new format or shape.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003072
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003073static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003074 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3075 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
3076 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003077 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003078 {"__enter__", memory_enter, METH_NOARGS, NULL},
3079 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003080 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003081};
3082
3083
3084PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003085 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003086 "memoryview", /* tp_name */
3087 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3088 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003089 (destructor)memory_dealloc, /* tp_dealloc */
3090 0, /* tp_print */
3091 0, /* tp_getattr */
3092 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003093 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003094 (reprfunc)memory_repr, /* tp_repr */
3095 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003096 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003097 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003098 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003099 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003100 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003101 PyObject_GenericGetAttr, /* tp_getattro */
3102 0, /* tp_setattro */
3103 &memory_as_buffer, /* tp_as_buffer */
3104 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3105 memory_doc, /* tp_doc */
3106 (traverseproc)memory_traverse, /* tp_traverse */
3107 (inquiry)memory_clear, /* tp_clear */
3108 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003109 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003110 0, /* tp_iter */
3111 0, /* tp_iternext */
3112 memory_methods, /* tp_methods */
3113 0, /* tp_members */
3114 memory_getsetlist, /* tp_getset */
3115 0, /* tp_base */
3116 0, /* tp_dict */
3117 0, /* tp_descr_get */
3118 0, /* tp_descr_set */
3119 0, /* tp_dictoffset */
3120 0, /* tp_init */
3121 0, /* tp_alloc */
3122 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003123};