blob: adf3ec62dab4d538bde9cf52824ccee51150823a [file] [log] [blame]
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001/* Memoryview object implementation */
2
3#include "Python.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +00004#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +01005#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00006
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00007
Stefan Krah9a2d99e2012-02-25 12:24:21 +01008/****************************************************************************/
9/* ManagedBuffer Object */
10/****************************************************************************/
11
12/*
13 ManagedBuffer Object:
14 ---------------------
15
16 The purpose of this object is to facilitate the handling of chained
17 memoryviews that have the same underlying exporting object. PEP-3118
18 allows the underlying object to change while a view is exported. This
19 could lead to unexpected results when constructing a new memoryview
20 from an existing memoryview.
21
22 Rather than repeatedly redirecting buffer requests to the original base
23 object, all chained memoryviews use a single buffer snapshot. This
24 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
25
26 Ownership rules:
27 ----------------
28
29 The master buffer inside a managed buffer is filled in by the original
30 base object. shape, strides, suboffsets and format are read-only for
31 all consumers.
32
33 A memoryview's buffer is a private copy of the exporter's buffer. shape,
34 strides and suboffsets belong to the memoryview and are thus writable.
35
36 If a memoryview itself exports several buffers via memory_getbuf(), all
37 buffer copies share shape, strides and suboffsets. In this case, the
38 arrays are NOT writable.
39
40 Reference count assumptions:
41 ----------------------------
42
43 The 'obj' member of a Py_buffer must either be NULL or refer to the
44 exporting base object. In the Python codebase, all getbufferprocs
45 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
46
47 PyBuffer_Release() decrements view.obj (if non-NULL), so the
48 releasebufferprocs must NOT decrement view.obj.
49*/
50
51
Stefan Krah9a2d99e2012-02-25 12:24:21 +010052#define CHECK_MBUF_RELEASED(mbuf) \
53 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
54 PyErr_SetString(PyExc_ValueError, \
55 "operation forbidden on released memoryview object"); \
56 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000057 }
58
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000059
Stefan Krah9a2d99e2012-02-25 12:24:21 +010060Py_LOCAL_INLINE(_PyManagedBufferObject *)
61mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000062{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010063 _PyManagedBufferObject *mbuf;
64
65 mbuf = (_PyManagedBufferObject *)
66 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
67 if (mbuf == NULL)
68 return NULL;
69 mbuf->flags = 0;
70 mbuf->exports = 0;
71 mbuf->master.obj = NULL;
72 _PyObject_GC_TRACK(mbuf);
73
74 return mbuf;
75}
76
77static PyObject *
78_PyManagedBuffer_FromObject(PyObject *base)
79{
80 _PyManagedBufferObject *mbuf;
81
82 mbuf = mbuf_alloc();
83 if (mbuf == NULL)
84 return NULL;
85
86 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +010087 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +010088 Py_DECREF(mbuf);
89 return NULL;
90 }
91
Stefan Krah9a2d99e2012-02-25 12:24:21 +010092 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +000093}
94
95static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +010096mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +000097{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010098 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
99 return;
100
101 /* NOTE: at this point self->exports can still be > 0 if this function
102 is called from mbuf_clear() to break up a reference cycle. */
103 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
104
105 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
106 _PyObject_GC_UNTRACK(self);
107 PyBuffer_Release(&self->master);
108}
109
110static void
111mbuf_dealloc(_PyManagedBufferObject *self)
112{
113 assert(self->exports == 0);
114 mbuf_release(self);
115 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
116 PyMem_Free(self->master.format);
117 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000118}
119
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000120static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100121mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000122{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100123 Py_VISIT(self->master.obj);
124 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000125}
126
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100127static int
128mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000129{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100130 assert(self->exports >= 0);
131 mbuf_release(self);
132 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000133}
134
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100135PyTypeObject _PyManagedBuffer_Type = {
136 PyVarObject_HEAD_INIT(&PyType_Type, 0)
137 "managedbuffer",
138 sizeof(_PyManagedBufferObject),
139 0,
140 (destructor)mbuf_dealloc, /* tp_dealloc */
141 0, /* tp_print */
142 0, /* tp_getattr */
143 0, /* tp_setattr */
144 0, /* tp_reserved */
145 0, /* tp_repr */
146 0, /* tp_as_number */
147 0, /* tp_as_sequence */
148 0, /* tp_as_mapping */
149 0, /* tp_hash */
150 0, /* tp_call */
151 0, /* tp_str */
152 PyObject_GenericGetAttr, /* tp_getattro */
153 0, /* tp_setattro */
154 0, /* tp_as_buffer */
155 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
156 0, /* tp_doc */
157 (traverseproc)mbuf_traverse, /* tp_traverse */
158 (inquiry)mbuf_clear /* tp_clear */
159};
160
161
162/****************************************************************************/
163/* MemoryView Object */
164/****************************************************************************/
165
166/* In the process of breaking reference cycles mbuf_release() can be
167 called before memory_release(). */
168#define BASE_INACCESSIBLE(mv) \
169 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
170 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
171
172#define CHECK_RELEASED(mv) \
173 if (BASE_INACCESSIBLE(mv)) { \
174 PyErr_SetString(PyExc_ValueError, \
175 "operation forbidden on released memoryview object"); \
176 return NULL; \
177 }
178
179#define CHECK_RELEASED_INT(mv) \
180 if (BASE_INACCESSIBLE(mv)) { \
181 PyErr_SetString(PyExc_ValueError, \
182 "operation forbidden on released memoryview object"); \
183 return -1; \
184 }
185
186#define CHECK_LIST_OR_TUPLE(v) \
187 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
188 PyErr_SetString(PyExc_TypeError, \
189 #v " must be a list or a tuple"); \
190 return NULL; \
191 }
192
193#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
194
195/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100196#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100197/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100198#define ADJUST_PTR(ptr, suboffsets, dim) \
199 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100200
201/* Memoryview buffer properties */
202#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
203#define MV_F_CONTIGUOUS(flags) \
204 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
205#define MV_ANY_CONTIGUOUS(flags) \
206 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
207
208/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
209#define MV_CONTIGUOUS_NDIM1(view) \
210 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
211
212/* getbuffer() requests */
213#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
214#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
215#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
216#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
217#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
218#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
219#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
220#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
221
222
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000223PyDoc_STRVAR(memory_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +0200224"memoryview($module, object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000225\n\
226Create a new memoryview object which references the given object.");
227
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100228
229/**************************************************************************/
230/* Copy memoryview buffers */
231/**************************************************************************/
232
233/* The functions in this section take a source and a destination buffer
234 with the same logical structure: format, itemsize, ndim and shape
235 are identical, with ndim > 0.
236
237 NOTE: All buffers are assumed to have PyBUF_FULL information, which
238 is the case for memoryviews! */
239
240
241/* Assumptions: ndim >= 1. The macro tests for a corner case that should
242 perhaps be explicitly forbidden in the PEP. */
243#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
244 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
245
246Py_LOCAL_INLINE(int)
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000247last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100248{
249 assert(dest->ndim > 0 && src->ndim > 0);
250 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
251 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
252 dest->strides[dest->ndim-1] == dest->itemsize &&
253 src->strides[src->ndim-1] == src->itemsize);
254}
255
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000256/* This is not a general function for determining format equivalence.
257 It is used in copy_single() and copy_buffer() to weed out non-matching
258 formats. Skipping the '@' character is specifically used in slice
259 assignments, where the lvalue is already known to have a single character
260 format. This is a performance hack that could be rewritten (if properly
261 benchmarked). */
262Py_LOCAL_INLINE(int)
263equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100264{
265 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100266
267 assert(dest->format && src->format);
268 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
269 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
270
271 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000272 dest->itemsize != src->itemsize) {
273 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100274 }
275
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000276 return 1;
277}
278
279/* Two shapes are equivalent if they are either equal or identical up
280 to a zero element at the same position. For example, in NumPy arrays
281 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
282Py_LOCAL_INLINE(int)
283equiv_shape(const Py_buffer *dest, const Py_buffer *src)
284{
285 int i;
286
287 if (dest->ndim != src->ndim)
288 return 0;
289
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100290 for (i = 0; i < dest->ndim; i++) {
291 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000292 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100293 if (dest->shape[i] == 0)
294 break;
295 }
296
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000297 return 1;
298}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100299
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000300/* Check that the logical structure of the destination and source buffers
301 is identical. */
302static int
303equiv_structure(const Py_buffer *dest, const Py_buffer *src)
304{
305 if (!equiv_format(dest, src) ||
306 !equiv_shape(dest, src)) {
307 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100308 "memoryview assignment: lvalue and rvalue have different "
309 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000310 return 0;
311 }
312
313 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100314}
315
316/* Base case for recursive multi-dimensional copying. Contiguous arrays are
317 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
318 sizeof(mem) == shape[0] * itemsize. */
319static void
320copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
321 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
322 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
323 char *mem)
324{
325 if (mem == NULL) { /* contiguous */
326 Py_ssize_t size = shape[0] * itemsize;
327 if (dptr + size < sptr || sptr + size < dptr)
328 memcpy(dptr, sptr, size); /* no overlapping */
329 else
330 memmove(dptr, sptr, size);
331 }
332 else {
333 char *p;
334 Py_ssize_t i;
335 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100336 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100337 memcpy(p, xsptr, itemsize);
338 }
339 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100340 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100341 memcpy(xdptr, p, itemsize);
342 }
343 }
344
345}
346
347/* Recursively copy a source buffer to a destination buffer. The two buffers
348 have the same ndim, shape and itemsize. */
349static void
350copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
351 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
352 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
353 char *mem)
354{
355 Py_ssize_t i;
356
357 assert(ndim >= 1);
358
359 if (ndim == 1) {
360 copy_base(shape, itemsize,
361 dptr, dstrides, dsuboffsets,
362 sptr, sstrides, ssuboffsets,
363 mem);
364 return;
365 }
366
367 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100368 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
369 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100370
371 copy_rec(shape+1, ndim-1, itemsize,
372 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
373 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
374 mem);
375 }
376}
377
378/* Faster copying of one-dimensional arrays. */
379static int
380copy_single(Py_buffer *dest, Py_buffer *src)
381{
382 char *mem = NULL;
383
384 assert(dest->ndim == 1);
385
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000386 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100387 return -1;
388
389 if (!last_dim_is_contiguous(dest, src)) {
390 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
391 if (mem == NULL) {
392 PyErr_NoMemory();
393 return -1;
394 }
395 }
396
397 copy_base(dest->shape, dest->itemsize,
398 dest->buf, dest->strides, dest->suboffsets,
399 src->buf, src->strides, src->suboffsets,
400 mem);
401
402 if (mem)
403 PyMem_Free(mem);
404
405 return 0;
406}
407
408/* Recursively copy src to dest. Both buffers must have the same basic
409 structure. Copying is atomic, the function never fails with a partial
410 copy. */
411static int
412copy_buffer(Py_buffer *dest, Py_buffer *src)
413{
414 char *mem = NULL;
415
416 assert(dest->ndim > 0);
417
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000418 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100419 return -1;
420
421 if (!last_dim_is_contiguous(dest, src)) {
422 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
423 if (mem == NULL) {
424 PyErr_NoMemory();
425 return -1;
426 }
427 }
428
429 copy_rec(dest->shape, dest->ndim, dest->itemsize,
430 dest->buf, dest->strides, dest->suboffsets,
431 src->buf, src->strides, src->suboffsets,
432 mem);
433
434 if (mem)
435 PyMem_Free(mem);
436
437 return 0;
438}
439
440/* Initialize strides for a C-contiguous array. */
441Py_LOCAL_INLINE(void)
442init_strides_from_shape(Py_buffer *view)
443{
444 Py_ssize_t i;
445
446 assert(view->ndim > 0);
447
448 view->strides[view->ndim-1] = view->itemsize;
449 for (i = view->ndim-2; i >= 0; i--)
450 view->strides[i] = view->strides[i+1] * view->shape[i+1];
451}
452
453/* Initialize strides for a Fortran-contiguous array. */
454Py_LOCAL_INLINE(void)
455init_fortran_strides_from_shape(Py_buffer *view)
456{
457 Py_ssize_t i;
458
459 assert(view->ndim > 0);
460
461 view->strides[0] = view->itemsize;
462 for (i = 1; i < view->ndim; i++)
463 view->strides[i] = view->strides[i-1] * view->shape[i-1];
464}
465
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200466/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
467 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100468 len(mem) == src->len. */
469static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200470buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100471{
472 Py_buffer dest;
473 Py_ssize_t *strides;
474 int ret;
475
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200476 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100477 assert(src->shape != NULL);
478 assert(src->strides != NULL);
479
480 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
481 if (strides == NULL) {
482 PyErr_NoMemory();
483 return -1;
484 }
485
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200486 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100487 dest = *src;
488 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200489 /* shape is constant and shared: the logical representation of the
490 array is unaltered. */
491
492 /* The physical representation determined by strides (and possibly
493 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100494 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200495 if (order == 'C' || order == 'A') {
496 init_strides_from_shape(&dest);
497 }
498 else {
499 init_fortran_strides_from_shape(&dest);
500 }
501
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100502 dest.suboffsets = NULL;
503
504 ret = copy_buffer(&dest, src);
505
506 PyMem_Free(strides);
507 return ret;
508}
509
510
511/****************************************************************************/
512/* Constructors */
513/****************************************************************************/
514
515/* Initialize values that are shared with the managed buffer. */
516Py_LOCAL_INLINE(void)
517init_shared_values(Py_buffer *dest, const Py_buffer *src)
518{
519 dest->obj = src->obj;
520 dest->buf = src->buf;
521 dest->len = src->len;
522 dest->itemsize = src->itemsize;
523 dest->readonly = src->readonly;
524 dest->format = src->format ? src->format : "B";
525 dest->internal = src->internal;
526}
527
528/* Copy shape and strides. Reconstruct missing values. */
529static void
530init_shape_strides(Py_buffer *dest, const Py_buffer *src)
531{
532 Py_ssize_t i;
533
534 if (src->ndim == 0) {
535 dest->shape = NULL;
536 dest->strides = NULL;
537 return;
538 }
539 if (src->ndim == 1) {
540 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
541 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
542 return;
543 }
544
545 for (i = 0; i < src->ndim; i++)
546 dest->shape[i] = src->shape[i];
547 if (src->strides) {
548 for (i = 0; i < src->ndim; i++)
549 dest->strides[i] = src->strides[i];
550 }
551 else {
552 init_strides_from_shape(dest);
553 }
554}
555
556Py_LOCAL_INLINE(void)
557init_suboffsets(Py_buffer *dest, const Py_buffer *src)
558{
559 Py_ssize_t i;
560
561 if (src->suboffsets == NULL) {
562 dest->suboffsets = NULL;
563 return;
564 }
565 for (i = 0; i < src->ndim; i++)
566 dest->suboffsets[i] = src->suboffsets[i];
567}
568
569/* len = product(shape) * itemsize */
570Py_LOCAL_INLINE(void)
571init_len(Py_buffer *view)
572{
573 Py_ssize_t i, len;
574
575 len = 1;
576 for (i = 0; i < view->ndim; i++)
577 len *= view->shape[i];
578 len *= view->itemsize;
579
580 view->len = len;
581}
582
583/* Initialize memoryview buffer properties. */
584static void
585init_flags(PyMemoryViewObject *mv)
586{
587 const Py_buffer *view = &mv->view;
588 int flags = 0;
589
590 switch (view->ndim) {
591 case 0:
592 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
593 _Py_MEMORYVIEW_FORTRAN);
594 break;
595 case 1:
596 if (MV_CONTIGUOUS_NDIM1(view))
597 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
598 break;
599 default:
600 if (PyBuffer_IsContiguous(view, 'C'))
601 flags |= _Py_MEMORYVIEW_C;
602 if (PyBuffer_IsContiguous(view, 'F'))
603 flags |= _Py_MEMORYVIEW_FORTRAN;
604 break;
605 }
606
607 if (view->suboffsets) {
608 flags |= _Py_MEMORYVIEW_PIL;
609 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
610 }
611
612 mv->flags = flags;
613}
614
615/* Allocate a new memoryview and perform basic initialization. New memoryviews
616 are exclusively created through the mbuf_add functions. */
617Py_LOCAL_INLINE(PyMemoryViewObject *)
618memory_alloc(int ndim)
619{
620 PyMemoryViewObject *mv;
621
622 mv = (PyMemoryViewObject *)
623 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
624 if (mv == NULL)
625 return NULL;
626
627 mv->mbuf = NULL;
628 mv->hash = -1;
629 mv->flags = 0;
630 mv->exports = 0;
631 mv->view.ndim = ndim;
632 mv->view.shape = mv->ob_array;
633 mv->view.strides = mv->ob_array + ndim;
634 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100635 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100636
637 _PyObject_GC_TRACK(mv);
638 return mv;
639}
640
641/*
642 Return a new memoryview that is registered with mbuf. If src is NULL,
643 use mbuf->master as the underlying buffer. Otherwise, use src.
644
645 The new memoryview has full buffer information: shape and strides
646 are always present, suboffsets as needed. Arrays are copied to
647 the memoryview's ob_array field.
648 */
649static PyObject *
650mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
651{
652 PyMemoryViewObject *mv;
653 Py_buffer *dest;
654
655 if (src == NULL)
656 src = &mbuf->master;
657
658 if (src->ndim > PyBUF_MAX_NDIM) {
659 PyErr_SetString(PyExc_ValueError,
660 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200661 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100662 return NULL;
663 }
664
665 mv = memory_alloc(src->ndim);
666 if (mv == NULL)
667 return NULL;
668
669 dest = &mv->view;
670 init_shared_values(dest, src);
671 init_shape_strides(dest, src);
672 init_suboffsets(dest, src);
673 init_flags(mv);
674
675 mv->mbuf = mbuf;
676 Py_INCREF(mbuf);
677 mbuf->exports++;
678
679 return (PyObject *)mv;
680}
681
682/* Register an incomplete view: shape, strides, suboffsets and flags still
683 need to be initialized. Use 'ndim' instead of src->ndim to determine the
684 size of the memoryview's ob_array.
685
686 Assumption: ndim <= PyBUF_MAX_NDIM. */
687static PyObject *
688mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
689 int ndim)
690{
691 PyMemoryViewObject *mv;
692 Py_buffer *dest;
693
694 if (src == NULL)
695 src = &mbuf->master;
696
697 assert(ndim <= PyBUF_MAX_NDIM);
698
699 mv = memory_alloc(ndim);
700 if (mv == NULL)
701 return NULL;
702
703 dest = &mv->view;
704 init_shared_values(dest, src);
705
706 mv->mbuf = mbuf;
707 Py_INCREF(mbuf);
708 mbuf->exports++;
709
710 return (PyObject *)mv;
711}
712
713/* Expose a raw memory area as a view of contiguous bytes. flags can be
714 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
715 The memoryview has complete buffer information. */
716PyObject *
717PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
718{
719 _PyManagedBufferObject *mbuf;
720 PyObject *mv;
721 int readonly;
722
723 assert(mem != NULL);
724 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
725
726 mbuf = mbuf_alloc();
727 if (mbuf == NULL)
728 return NULL;
729
730 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
731 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
732 PyBUF_FULL_RO);
733
734 mv = mbuf_add_view(mbuf, NULL);
735 Py_DECREF(mbuf);
736
737 return mv;
738}
739
740/* Create a memoryview from a given Py_buffer. For simple byte views,
741 PyMemoryView_FromMemory() should be used instead.
742 This function is the only entry point that can create a master buffer
743 without full information. Because of this fact init_shape_strides()
744 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000745PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000746PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000747{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100748 _PyManagedBufferObject *mbuf;
749 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000750
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000751 if (info->buf == NULL) {
752 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100753 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000754 return NULL;
755 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100756
757 mbuf = mbuf_alloc();
758 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000759 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100760
761 /* info->obj is either NULL or a borrowed reference. This reference
762 should not be decremented in PyBuffer_Release(). */
763 mbuf->master = *info;
764 mbuf->master.obj = NULL;
765
766 mv = mbuf_add_view(mbuf, NULL);
767 Py_DECREF(mbuf);
768
769 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000770}
771
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100772/* Create a memoryview from an object that implements the buffer protocol.
773 If the object is a memoryview, the new memoryview must be registered
774 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000775PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100776PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000777{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100778 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000779
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100780 if (PyMemoryView_Check(v)) {
781 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
782 CHECK_RELEASED(mv);
783 return mbuf_add_view(mv->mbuf, &mv->view);
784 }
785 else if (PyObject_CheckBuffer(v)) {
786 PyObject *ret;
787 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
788 if (mbuf == NULL)
789 return NULL;
790 ret = mbuf_add_view(mbuf, NULL);
791 Py_DECREF(mbuf);
792 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000793 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000794
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100795 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400796 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100797 Py_TYPE(v)->tp_name);
798 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000799}
800
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100801/* Copy the format string from a base object that might vanish. */
802static int
803mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
804{
805 if (fmt != NULL) {
806 char *cp = PyMem_Malloc(strlen(fmt)+1);
807 if (cp == NULL) {
808 PyErr_NoMemory();
809 return -1;
810 }
811 mbuf->master.format = strcpy(cp, fmt);
812 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
813 }
814
815 return 0;
816}
817
818/*
819 Return a memoryview that is based on a contiguous copy of src.
820 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
821
822 Ownership rules:
823 1) As usual, the returned memoryview has a private copy
824 of src->shape, src->strides and src->suboffsets.
825 2) src->format is copied to the master buffer and released
826 in mbuf_dealloc(). The releasebufferproc of the bytes
827 object is NULL, so it does not matter that mbuf_release()
828 passes the altered format pointer to PyBuffer_Release().
829*/
830static PyObject *
831memory_from_contiguous_copy(Py_buffer *src, char order)
832{
833 _PyManagedBufferObject *mbuf;
834 PyMemoryViewObject *mv;
835 PyObject *bytes;
836 Py_buffer *dest;
837 int i;
838
839 assert(src->ndim > 0);
840 assert(src->shape != NULL);
841
842 bytes = PyBytes_FromStringAndSize(NULL, src->len);
843 if (bytes == NULL)
844 return NULL;
845
846 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
847 Py_DECREF(bytes);
848 if (mbuf == NULL)
849 return NULL;
850
851 if (mbuf_copy_format(mbuf, src->format) < 0) {
852 Py_DECREF(mbuf);
853 return NULL;
854 }
855
856 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
857 Py_DECREF(mbuf);
858 if (mv == NULL)
859 return NULL;
860
861 dest = &mv->view;
862
863 /* shared values are initialized correctly except for itemsize */
864 dest->itemsize = src->itemsize;
865
866 /* shape and strides */
867 for (i = 0; i < src->ndim; i++) {
868 dest->shape[i] = src->shape[i];
869 }
870 if (order == 'C' || order == 'A') {
871 init_strides_from_shape(dest);
872 }
873 else {
874 init_fortran_strides_from_shape(dest);
875 }
876 /* suboffsets */
877 dest->suboffsets = NULL;
878
879 /* flags */
880 init_flags(mv);
881
882 if (copy_buffer(dest, src) < 0) {
883 Py_DECREF(mv);
884 return NULL;
885 }
886
887 return (PyObject *)mv;
888}
889
890/*
891 Return a new memoryview object based on a contiguous exporter with
892 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
893 The logical structure of the input and output buffers is the same
894 (i.e. tolist(input) == tolist(output)), but the physical layout in
895 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200896
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100897 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
898 otherwise it may be writable or read-only.
899
900 If the exporter is already contiguous with the desired target order,
901 the memoryview will be directly based on the exporter.
902
903 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
904 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
905 'F'ortran order otherwise.
906*/
907PyObject *
908PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
909{
910 PyMemoryViewObject *mv;
911 PyObject *ret;
912 Py_buffer *view;
913
914 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
915 assert(order == 'C' || order == 'F' || order == 'A');
916
917 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
918 if (mv == NULL)
919 return NULL;
920
921 view = &mv->view;
922 if (buffertype == PyBUF_WRITE && view->readonly) {
923 PyErr_SetString(PyExc_BufferError,
924 "underlying buffer is not writable");
925 Py_DECREF(mv);
926 return NULL;
927 }
928
929 if (PyBuffer_IsContiguous(view, order))
930 return (PyObject *)mv;
931
932 if (buffertype == PyBUF_WRITE) {
933 PyErr_SetString(PyExc_BufferError,
934 "writable contiguous buffer requested "
935 "for a non-contiguous object.");
936 Py_DECREF(mv);
937 return NULL;
938 }
939
940 ret = memory_from_contiguous_copy(view, order);
941 Py_DECREF(mv);
942 return ret;
943}
944
945
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000946static PyObject *
947memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
948{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000949 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100950 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000951
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000952 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
953 &obj)) {
954 return NULL;
955 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000956
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000957 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000958}
959
960
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100961/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200962/* Previously in abstract.c */
963/****************************************************************************/
964
965typedef struct {
966 Py_buffer view;
967 Py_ssize_t array[1];
968} Py_buffer_full;
969
970int
971PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
972{
973 Py_buffer_full *fb = NULL;
974 int ret;
975
976 assert(order == 'C' || order == 'F' || order == 'A');
977
978 if (len != src->len) {
979 PyErr_SetString(PyExc_ValueError,
980 "PyBuffer_ToContiguous: len != view->len");
981 return -1;
982 }
983
984 if (PyBuffer_IsContiguous(src, order)) {
985 memcpy((char *)buf, src->buf, len);
986 return 0;
987 }
988
989 /* buffer_to_contiguous() assumes PyBUF_FULL */
990 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
991 if (fb == NULL) {
992 PyErr_NoMemory();
993 return -1;
994 }
995 fb->view.ndim = src->ndim;
996 fb->view.shape = fb->array;
997 fb->view.strides = fb->array + src->ndim;
998 fb->view.suboffsets = fb->array + 2 * src->ndim;
999
1000 init_shared_values(&fb->view, src);
1001 init_shape_strides(&fb->view, src);
1002 init_suboffsets(&fb->view, src);
1003
1004 src = &fb->view;
1005
1006 ret = buffer_to_contiguous(buf, src, order);
1007 PyMem_Free(fb);
1008 return ret;
1009}
1010
1011
1012/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001013/* Release/GC management */
1014/****************************************************************************/
1015
1016/* Inform the managed buffer that this particular memoryview will not access
1017 the underlying buffer again. If no other memoryviews are registered with
1018 the managed buffer, the underlying buffer is released instantly and
1019 marked as inaccessible for both the memoryview and the managed buffer.
1020
1021 This function fails if the memoryview itself has exported buffers. */
1022static int
1023_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001024{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001025 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1026 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001027
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001028 if (self->exports == 0) {
1029 self->flags |= _Py_MEMORYVIEW_RELEASED;
1030 assert(self->mbuf->exports > 0);
1031 if (--self->mbuf->exports == 0)
1032 mbuf_release(self->mbuf);
1033 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001034 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001035 if (self->exports > 0) {
1036 PyErr_Format(PyExc_BufferError,
1037 "memoryview has %zd exported buffer%s", self->exports,
1038 self->exports==1 ? "" : "s");
1039 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001040 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001041
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001042 Py_FatalError("_memory_release(): negative export count");
1043 return -1;
1044}
1045
1046static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001047memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001048{
1049 if (_memory_release(self) < 0)
1050 return NULL;
1051 Py_RETURN_NONE;
1052}
1053
1054static void
1055memory_dealloc(PyMemoryViewObject *self)
1056{
1057 assert(self->exports == 0);
1058 _PyObject_GC_UNTRACK(self);
1059 (void)_memory_release(self);
1060 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001061 if (self->weakreflist != NULL)
1062 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001063 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001064}
1065
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001066static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001067memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001068{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001069 Py_VISIT(self->mbuf);
1070 return 0;
1071}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001072
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001073static int
1074memory_clear(PyMemoryViewObject *self)
1075{
1076 (void)_memory_release(self);
1077 Py_CLEAR(self->mbuf);
1078 return 0;
1079}
1080
1081static PyObject *
1082memory_enter(PyObject *self, PyObject *args)
1083{
1084 CHECK_RELEASED(self);
1085 Py_INCREF(self);
1086 return self;
1087}
1088
1089static PyObject *
1090memory_exit(PyObject *self, PyObject *args)
1091{
Stefan Krahe4c07992012-07-28 14:10:02 +02001092 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001093}
1094
1095
1096/****************************************************************************/
1097/* Casting format and shape */
1098/****************************************************************************/
1099
1100#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1101
1102Py_LOCAL_INLINE(Py_ssize_t)
1103get_native_fmtchar(char *result, const char *fmt)
1104{
1105 Py_ssize_t size = -1;
1106
1107 if (fmt[0] == '@') fmt++;
1108
1109 switch (fmt[0]) {
1110 case 'c': case 'b': case 'B': size = sizeof(char); break;
1111 case 'h': case 'H': size = sizeof(short); break;
1112 case 'i': case 'I': size = sizeof(int); break;
1113 case 'l': case 'L': size = sizeof(long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001114 case 'q': case 'Q': size = sizeof(PY_LONG_LONG); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001115 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1116 case 'f': size = sizeof(float); break;
1117 case 'd': size = sizeof(double); break;
1118 #ifdef HAVE_C99_BOOL
1119 case '?': size = sizeof(_Bool); break;
1120 #else
1121 case '?': size = sizeof(char); break;
1122 #endif
1123 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001124 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001125
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001126 if (size > 0 && fmt[1] == '\0') {
1127 *result = fmt[0];
1128 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001129 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001130
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001131 return -1;
1132}
1133
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001134Py_LOCAL_INLINE(const char *)
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001135get_native_fmtstr(const char *fmt)
1136{
1137 int at = 0;
1138
1139 if (fmt[0] == '@') {
1140 at = 1;
1141 fmt++;
1142 }
1143 if (fmt[0] == '\0' || fmt[1] != '\0') {
1144 return NULL;
1145 }
1146
1147#define RETURN(s) do { return at ? "@" s : s; } while (0)
1148
1149 switch (fmt[0]) {
1150 case 'c': RETURN("c");
1151 case 'b': RETURN("b");
1152 case 'B': RETURN("B");
1153 case 'h': RETURN("h");
1154 case 'H': RETURN("H");
1155 case 'i': RETURN("i");
1156 case 'I': RETURN("I");
1157 case 'l': RETURN("l");
1158 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001159 case 'q': RETURN("q");
1160 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001161 case 'n': RETURN("n");
1162 case 'N': RETURN("N");
1163 case 'f': RETURN("f");
1164 case 'd': RETURN("d");
1165 #ifdef HAVE_C99_BOOL
1166 case '?': RETURN("?");
1167 #else
1168 case '?': RETURN("?");
1169 #endif
1170 case 'P': RETURN("P");
1171 }
1172
1173 return NULL;
1174}
1175
1176
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001177/* Cast a memoryview's data type to 'format'. The input array must be
1178 C-contiguous. At least one of input-format, output-format must have
1179 byte size. The output array is 1-D, with the same byte length as the
1180 input array. Thus, view->len must be a multiple of the new itemsize. */
1181static int
1182cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1183{
1184 Py_buffer *view = &mv->view;
1185 PyObject *asciifmt;
1186 char srcchar, destchar;
1187 Py_ssize_t itemsize;
1188 int ret = -1;
1189
1190 assert(view->ndim >= 1);
1191 assert(Py_SIZE(mv) == 3*view->ndim);
1192 assert(view->shape == mv->ob_array);
1193 assert(view->strides == mv->ob_array + view->ndim);
1194 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1195
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001196 asciifmt = PyUnicode_AsASCIIString(format);
1197 if (asciifmt == NULL)
1198 return ret;
1199
1200 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1201 if (itemsize < 0) {
1202 PyErr_SetString(PyExc_ValueError,
1203 "memoryview: destination format must be a native single "
1204 "character format prefixed with an optional '@'");
1205 goto out;
1206 }
1207
Stefan Krah0c515952015-08-08 13:38:10 +02001208 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1209 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001210 PyErr_SetString(PyExc_TypeError,
1211 "memoryview: cannot cast between two non-byte formats");
1212 goto out;
1213 }
1214 if (view->len % itemsize) {
1215 PyErr_SetString(PyExc_TypeError,
1216 "memoryview: length is not a multiple of itemsize");
1217 goto out;
1218 }
1219
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001220 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001221 if (view->format == NULL) {
1222 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1223 PyErr_SetString(PyExc_RuntimeError,
1224 "memoryview: internal error");
1225 goto out;
1226 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001227 view->itemsize = itemsize;
1228
1229 view->ndim = 1;
1230 view->shape[0] = view->len / view->itemsize;
1231 view->strides[0] = view->itemsize;
1232 view->suboffsets = NULL;
1233
1234 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001235
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001236 ret = 0;
1237
1238out:
1239 Py_DECREF(asciifmt);
1240 return ret;
1241}
1242
1243/* The memoryview must have space for 3*len(seq) elements. */
1244static Py_ssize_t
1245copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1246 Py_ssize_t itemsize)
1247{
1248 Py_ssize_t x, i;
1249 Py_ssize_t len = itemsize;
1250
1251 for (i = 0; i < ndim; i++) {
1252 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1253 if (!PyLong_Check(tmp)) {
1254 PyErr_SetString(PyExc_TypeError,
1255 "memoryview.cast(): elements of shape must be integers");
1256 return -1;
1257 }
1258 x = PyLong_AsSsize_t(tmp);
1259 if (x == -1 && PyErr_Occurred()) {
1260 return -1;
1261 }
1262 if (x <= 0) {
1263 /* In general elements of shape may be 0, but not for casting. */
1264 PyErr_Format(PyExc_ValueError,
1265 "memoryview.cast(): elements of shape must be integers > 0");
1266 return -1;
1267 }
1268 if (x > PY_SSIZE_T_MAX / len) {
1269 PyErr_Format(PyExc_ValueError,
1270 "memoryview.cast(): product(shape) > SSIZE_MAX");
1271 return -1;
1272 }
1273 len *= x;
1274 shape[i] = x;
1275 }
1276
1277 return len;
1278}
1279
1280/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1281 If the result array does not have exactly the same byte length as the
1282 input array, raise ValueError. */
1283static int
1284cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1285{
1286 Py_buffer *view = &mv->view;
1287 Py_ssize_t len;
1288
1289 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1290 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1291 assert(view->shape == mv->ob_array);
1292 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1293 assert(view->suboffsets == NULL);
1294
1295 view->ndim = ndim;
1296 if (view->ndim == 0) {
1297 view->shape = NULL;
1298 view->strides = NULL;
1299 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001300 }
1301 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001302 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1303 if (len < 0)
1304 return -1;
1305 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001306 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001307
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001308 if (view->len != len) {
1309 PyErr_SetString(PyExc_TypeError,
1310 "memoryview: product(shape) * itemsize != buffer size");
1311 return -1;
1312 }
1313
1314 init_flags(mv);
1315
1316 return 0;
1317}
1318
1319static int
1320zero_in_shape(PyMemoryViewObject *mv)
1321{
1322 Py_buffer *view = &mv->view;
1323 Py_ssize_t i;
1324
1325 for (i = 0; i < view->ndim; i++)
1326 if (view->shape[i] == 0)
1327 return 1;
1328
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001329 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001330}
1331
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001332/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001333 Cast a copy of 'self' to a different view. The input view must
1334 be C-contiguous. The function always casts the input view to a
1335 1-D output according to 'format'. At least one of input-format,
1336 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001337
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001338 If 'shape' is given, the 1-D view from the previous step will
1339 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001340
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001341 All casts must result in views that will have the exact byte
1342 size of the original input. Otherwise, an error is raised.
1343*/
1344static PyObject *
1345memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001346{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001347 static char *kwlist[] = {"format", "shape", NULL};
1348 PyMemoryViewObject *mv = NULL;
1349 PyObject *shape = NULL;
1350 PyObject *format;
1351 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001352
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001353 CHECK_RELEASED(self);
1354
1355 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1356 &format, &shape)) {
1357 return NULL;
1358 }
1359 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001360 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001361 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001362 return NULL;
1363 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001364 if (!MV_C_CONTIGUOUS(self->flags)) {
1365 PyErr_SetString(PyExc_TypeError,
1366 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001367 return NULL;
1368 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001369 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001370 PyErr_SetString(PyExc_TypeError,
1371 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001372 return NULL;
1373 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001374 if (shape) {
1375 CHECK_LIST_OR_TUPLE(shape)
1376 ndim = PySequence_Fast_GET_SIZE(shape);
1377 if (ndim > PyBUF_MAX_NDIM) {
1378 PyErr_SetString(PyExc_ValueError,
1379 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001380 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001381 return NULL;
1382 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001383 if (self->view.ndim != 1 && ndim != 1) {
1384 PyErr_SetString(PyExc_TypeError,
1385 "memoryview: cast must be 1D -> ND or ND -> 1D");
1386 return NULL;
1387 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001388 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001389
1390 mv = (PyMemoryViewObject *)
1391 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1392 if (mv == NULL)
1393 return NULL;
1394
1395 if (cast_to_1D(mv, format) < 0)
1396 goto error;
1397 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1398 goto error;
1399
1400 return (PyObject *)mv;
1401
1402error:
1403 Py_DECREF(mv);
1404 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001405}
1406
1407
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001408/**************************************************************************/
1409/* getbuffer */
1410/**************************************************************************/
1411
1412static int
1413memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1414{
1415 Py_buffer *base = &self->view;
1416 int baseflags = self->flags;
1417
1418 CHECK_RELEASED_INT(self);
1419
1420 /* start with complete information */
1421 *view = *base;
1422 view->obj = NULL;
1423
1424 if (REQ_WRITABLE(flags) && base->readonly) {
1425 PyErr_SetString(PyExc_BufferError,
1426 "memoryview: underlying buffer is not writable");
1427 return -1;
1428 }
1429 if (!REQ_FORMAT(flags)) {
1430 /* NULL indicates that the buffer's data type has been cast to 'B'.
1431 view->itemsize is the _previous_ itemsize. If shape is present,
1432 the equality product(shape) * itemsize = len still holds at this
1433 point. The equality calcsize(format) = itemsize does _not_ hold
1434 from here on! */
1435 view->format = NULL;
1436 }
1437
1438 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1439 PyErr_SetString(PyExc_BufferError,
1440 "memoryview: underlying buffer is not C-contiguous");
1441 return -1;
1442 }
1443 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1444 PyErr_SetString(PyExc_BufferError,
1445 "memoryview: underlying buffer is not Fortran contiguous");
1446 return -1;
1447 }
1448 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1449 PyErr_SetString(PyExc_BufferError,
1450 "memoryview: underlying buffer is not contiguous");
1451 return -1;
1452 }
1453 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1454 PyErr_SetString(PyExc_BufferError,
1455 "memoryview: underlying buffer requires suboffsets");
1456 return -1;
1457 }
1458 if (!REQ_STRIDES(flags)) {
1459 if (!MV_C_CONTIGUOUS(baseflags)) {
1460 PyErr_SetString(PyExc_BufferError,
1461 "memoryview: underlying buffer is not C-contiguous");
1462 return -1;
1463 }
1464 view->strides = NULL;
1465 }
1466 if (!REQ_SHAPE(flags)) {
1467 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1468 so base->buf = ndbuf->data. */
1469 if (view->format != NULL) {
1470 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1471 not make sense. */
1472 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001473 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001474 "is present");
1475 return -1;
1476 }
1477 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1478 do _not_ hold from here on! */
1479 view->ndim = 1;
1480 view->shape = NULL;
1481 }
1482
1483
1484 view->obj = (PyObject *)self;
1485 Py_INCREF(view->obj);
1486 self->exports++;
1487
1488 return 0;
1489}
1490
1491static void
1492memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1493{
1494 self->exports--;
1495 return;
1496 /* PyBuffer_Release() decrements view->obj after this function returns. */
1497}
1498
1499/* Buffer methods */
1500static PyBufferProcs memory_as_buffer = {
1501 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1502 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1503};
1504
1505
1506/****************************************************************************/
1507/* Optimized pack/unpack for all native format specifiers */
1508/****************************************************************************/
1509
1510/*
1511 Fix exceptions:
1512 1) Include format string in the error message.
1513 2) OverflowError -> ValueError.
1514 3) The error message from PyNumber_Index() is not ideal.
1515*/
1516static int
1517type_error_int(const char *fmt)
1518{
1519 PyErr_Format(PyExc_TypeError,
1520 "memoryview: invalid type for format '%s'", fmt);
1521 return -1;
1522}
1523
1524static int
1525value_error_int(const char *fmt)
1526{
1527 PyErr_Format(PyExc_ValueError,
1528 "memoryview: invalid value for format '%s'", fmt);
1529 return -1;
1530}
1531
1532static int
1533fix_error_int(const char *fmt)
1534{
1535 assert(PyErr_Occurred());
1536 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1537 PyErr_Clear();
1538 return type_error_int(fmt);
1539 }
1540 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1541 PyErr_ExceptionMatches(PyExc_ValueError)) {
1542 PyErr_Clear();
1543 return value_error_int(fmt);
1544 }
1545
1546 return -1;
1547}
1548
1549/* Accept integer objects or objects with an __index__() method. */
1550static long
1551pylong_as_ld(PyObject *item)
1552{
1553 PyObject *tmp;
1554 long ld;
1555
1556 tmp = PyNumber_Index(item);
1557 if (tmp == NULL)
1558 return -1;
1559
1560 ld = PyLong_AsLong(tmp);
1561 Py_DECREF(tmp);
1562 return ld;
1563}
1564
1565static unsigned long
1566pylong_as_lu(PyObject *item)
1567{
1568 PyObject *tmp;
1569 unsigned long lu;
1570
1571 tmp = PyNumber_Index(item);
1572 if (tmp == NULL)
1573 return (unsigned long)-1;
1574
1575 lu = PyLong_AsUnsignedLong(tmp);
1576 Py_DECREF(tmp);
1577 return lu;
1578}
1579
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001580static PY_LONG_LONG
1581pylong_as_lld(PyObject *item)
1582{
1583 PyObject *tmp;
1584 PY_LONG_LONG lld;
1585
1586 tmp = PyNumber_Index(item);
1587 if (tmp == NULL)
1588 return -1;
1589
1590 lld = PyLong_AsLongLong(tmp);
1591 Py_DECREF(tmp);
1592 return lld;
1593}
1594
1595static unsigned PY_LONG_LONG
1596pylong_as_llu(PyObject *item)
1597{
1598 PyObject *tmp;
1599 unsigned PY_LONG_LONG llu;
1600
1601 tmp = PyNumber_Index(item);
1602 if (tmp == NULL)
1603 return (unsigned PY_LONG_LONG)-1;
1604
1605 llu = PyLong_AsUnsignedLongLong(tmp);
1606 Py_DECREF(tmp);
1607 return llu;
1608}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001609
1610static Py_ssize_t
1611pylong_as_zd(PyObject *item)
1612{
1613 PyObject *tmp;
1614 Py_ssize_t zd;
1615
1616 tmp = PyNumber_Index(item);
1617 if (tmp == NULL)
1618 return -1;
1619
1620 zd = PyLong_AsSsize_t(tmp);
1621 Py_DECREF(tmp);
1622 return zd;
1623}
1624
1625static size_t
1626pylong_as_zu(PyObject *item)
1627{
1628 PyObject *tmp;
1629 size_t zu;
1630
1631 tmp = PyNumber_Index(item);
1632 if (tmp == NULL)
1633 return (size_t)-1;
1634
1635 zu = PyLong_AsSize_t(tmp);
1636 Py_DECREF(tmp);
1637 return zu;
1638}
1639
1640/* Timings with the ndarray from _testbuffer.c indicate that using the
1641 struct module is around 15x slower than the two functions below. */
1642
1643#define UNPACK_SINGLE(dest, ptr, type) \
1644 do { \
1645 type x; \
1646 memcpy((char *)&x, ptr, sizeof x); \
1647 dest = x; \
1648 } while (0)
1649
1650/* Unpack a single item. 'fmt' can be any native format character in struct
1651 module syntax. This function is very sensitive to small changes. With this
1652 layout gcc automatically generates a fast jump table. */
1653Py_LOCAL_INLINE(PyObject *)
1654unpack_single(const char *ptr, const char *fmt)
1655{
1656 unsigned PY_LONG_LONG llu;
1657 unsigned long lu;
1658 size_t zu;
1659 PY_LONG_LONG lld;
1660 long ld;
1661 Py_ssize_t zd;
1662 double d;
1663 unsigned char uc;
1664 void *p;
1665
1666 switch (fmt[0]) {
1667
1668 /* signed integers and fast path for 'B' */
1669 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1670 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1671 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1672 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1673 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1674
1675 /* boolean */
1676 #ifdef HAVE_C99_BOOL
1677 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
1678 #else
1679 case '?': UNPACK_SINGLE(ld, ptr, char); goto convert_bool;
1680 #endif
1681
1682 /* unsigned integers */
1683 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1684 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1685 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1686
1687 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001688 case 'q': UNPACK_SINGLE(lld, ptr, PY_LONG_LONG); goto convert_lld;
1689 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned PY_LONG_LONG); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001690
1691 /* ssize_t and size_t */
1692 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1693 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1694
1695 /* floats */
1696 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1697 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1698
1699 /* bytes object */
1700 case 'c': goto convert_bytes;
1701
1702 /* pointer */
1703 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1704
1705 /* default */
1706 default: goto err_format;
1707 }
1708
1709convert_uc:
1710 /* PyLong_FromUnsignedLong() is slower */
1711 return PyLong_FromLong(uc);
1712convert_ld:
1713 return PyLong_FromLong(ld);
1714convert_lu:
1715 return PyLong_FromUnsignedLong(lu);
1716convert_lld:
1717 return PyLong_FromLongLong(lld);
1718convert_llu:
1719 return PyLong_FromUnsignedLongLong(llu);
1720convert_zd:
1721 return PyLong_FromSsize_t(zd);
1722convert_zu:
1723 return PyLong_FromSize_t(zu);
1724convert_double:
1725 return PyFloat_FromDouble(d);
1726convert_bool:
1727 return PyBool_FromLong(ld);
1728convert_bytes:
1729 return PyBytes_FromStringAndSize(ptr, 1);
1730convert_pointer:
1731 return PyLong_FromVoidPtr(p);
1732err_format:
1733 PyErr_Format(PyExc_NotImplementedError,
1734 "memoryview: format %s not supported", fmt);
1735 return NULL;
1736}
1737
1738#define PACK_SINGLE(ptr, src, type) \
1739 do { \
1740 type x; \
1741 x = (type)src; \
1742 memcpy(ptr, (char *)&x, sizeof x); \
1743 } while (0)
1744
1745/* Pack a single item. 'fmt' can be any native format character in
1746 struct module syntax. */
1747static int
1748pack_single(char *ptr, PyObject *item, const char *fmt)
1749{
1750 unsigned PY_LONG_LONG llu;
1751 unsigned long lu;
1752 size_t zu;
1753 PY_LONG_LONG lld;
1754 long ld;
1755 Py_ssize_t zd;
1756 double d;
1757 void *p;
1758
1759 switch (fmt[0]) {
1760 /* signed integers */
1761 case 'b': case 'h': case 'i': case 'l':
1762 ld = pylong_as_ld(item);
1763 if (ld == -1 && PyErr_Occurred())
1764 goto err_occurred;
1765 switch (fmt[0]) {
1766 case 'b':
1767 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1768 *((signed char *)ptr) = (signed char)ld; break;
1769 case 'h':
1770 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1771 PACK_SINGLE(ptr, ld, short); break;
1772 case 'i':
1773 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1774 PACK_SINGLE(ptr, ld, int); break;
1775 default: /* 'l' */
1776 PACK_SINGLE(ptr, ld, long); break;
1777 }
1778 break;
1779
1780 /* unsigned integers */
1781 case 'B': case 'H': case 'I': case 'L':
1782 lu = pylong_as_lu(item);
1783 if (lu == (unsigned long)-1 && PyErr_Occurred())
1784 goto err_occurred;
1785 switch (fmt[0]) {
1786 case 'B':
1787 if (lu > UCHAR_MAX) goto err_range;
1788 *((unsigned char *)ptr) = (unsigned char)lu; break;
1789 case 'H':
1790 if (lu > USHRT_MAX) goto err_range;
1791 PACK_SINGLE(ptr, lu, unsigned short); break;
1792 case 'I':
1793 if (lu > UINT_MAX) goto err_range;
1794 PACK_SINGLE(ptr, lu, unsigned int); break;
1795 default: /* 'L' */
1796 PACK_SINGLE(ptr, lu, unsigned long); break;
1797 }
1798 break;
1799
1800 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001801 case 'q':
1802 lld = pylong_as_lld(item);
1803 if (lld == -1 && PyErr_Occurred())
1804 goto err_occurred;
1805 PACK_SINGLE(ptr, lld, PY_LONG_LONG);
1806 break;
1807 case 'Q':
1808 llu = pylong_as_llu(item);
1809 if (llu == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
1810 goto err_occurred;
1811 PACK_SINGLE(ptr, llu, unsigned PY_LONG_LONG);
1812 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001813
1814 /* ssize_t and size_t */
1815 case 'n':
1816 zd = pylong_as_zd(item);
1817 if (zd == -1 && PyErr_Occurred())
1818 goto err_occurred;
1819 PACK_SINGLE(ptr, zd, Py_ssize_t);
1820 break;
1821 case 'N':
1822 zu = pylong_as_zu(item);
1823 if (zu == (size_t)-1 && PyErr_Occurred())
1824 goto err_occurred;
1825 PACK_SINGLE(ptr, zu, size_t);
1826 break;
1827
1828 /* floats */
1829 case 'f': case 'd':
1830 d = PyFloat_AsDouble(item);
1831 if (d == -1.0 && PyErr_Occurred())
1832 goto err_occurred;
1833 if (fmt[0] == 'f') {
1834 PACK_SINGLE(ptr, d, float);
1835 }
1836 else {
1837 PACK_SINGLE(ptr, d, double);
1838 }
1839 break;
1840
1841 /* bool */
1842 case '?':
1843 ld = PyObject_IsTrue(item);
1844 if (ld < 0)
1845 return -1; /* preserve original error */
1846 #ifdef HAVE_C99_BOOL
1847 PACK_SINGLE(ptr, ld, _Bool);
1848 #else
1849 PACK_SINGLE(ptr, ld, char);
1850 #endif
1851 break;
1852
1853 /* bytes object */
1854 case 'c':
1855 if (!PyBytes_Check(item))
1856 return type_error_int(fmt);
1857 if (PyBytes_GET_SIZE(item) != 1)
1858 return value_error_int(fmt);
1859 *ptr = PyBytes_AS_STRING(item)[0];
1860 break;
1861
1862 /* pointer */
1863 case 'P':
1864 p = PyLong_AsVoidPtr(item);
1865 if (p == NULL && PyErr_Occurred())
1866 goto err_occurred;
1867 PACK_SINGLE(ptr, p, void *);
1868 break;
1869
1870 /* default */
1871 default: goto err_format;
1872 }
1873
1874 return 0;
1875
1876err_occurred:
1877 return fix_error_int(fmt);
1878err_range:
1879 return value_error_int(fmt);
1880err_format:
1881 PyErr_Format(PyExc_NotImplementedError,
1882 "memoryview: format %s not supported", fmt);
1883 return -1;
1884}
1885
1886
1887/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001888/* unpack using the struct module */
1889/****************************************************************************/
1890
1891/* For reasonable performance it is necessary to cache all objects required
1892 for unpacking. An unpacker can handle the format passed to unpack_from().
1893 Invariant: All pointer fields of the struct should either be NULL or valid
1894 pointers. */
1895struct unpacker {
1896 PyObject *unpack_from; /* Struct.unpack_from(format) */
1897 PyObject *mview; /* cached memoryview */
1898 char *item; /* buffer for mview */
1899 Py_ssize_t itemsize; /* len(item) */
1900};
1901
1902static struct unpacker *
1903unpacker_new(void)
1904{
1905 struct unpacker *x = PyMem_Malloc(sizeof *x);
1906
1907 if (x == NULL) {
1908 PyErr_NoMemory();
1909 return NULL;
1910 }
1911
1912 x->unpack_from = NULL;
1913 x->mview = NULL;
1914 x->item = NULL;
1915 x->itemsize = 0;
1916
1917 return x;
1918}
1919
1920static void
1921unpacker_free(struct unpacker *x)
1922{
1923 if (x) {
1924 Py_XDECREF(x->unpack_from);
1925 Py_XDECREF(x->mview);
1926 PyMem_Free(x->item);
1927 PyMem_Free(x);
1928 }
1929}
1930
1931/* Return a new unpacker for the given format. */
1932static struct unpacker *
1933struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1934{
1935 PyObject *structmodule; /* XXX cache these two */
1936 PyObject *Struct = NULL; /* XXX in globals? */
1937 PyObject *structobj = NULL;
1938 PyObject *format = NULL;
1939 struct unpacker *x = NULL;
1940
1941 structmodule = PyImport_ImportModule("struct");
1942 if (structmodule == NULL)
1943 return NULL;
1944
1945 Struct = PyObject_GetAttrString(structmodule, "Struct");
1946 Py_DECREF(structmodule);
1947 if (Struct == NULL)
1948 return NULL;
1949
1950 x = unpacker_new();
1951 if (x == NULL)
1952 goto error;
1953
1954 format = PyBytes_FromString(fmt);
1955 if (format == NULL)
1956 goto error;
1957
1958 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1959 if (structobj == NULL)
1960 goto error;
1961
1962 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1963 if (x->unpack_from == NULL)
1964 goto error;
1965
1966 x->item = PyMem_Malloc(itemsize);
1967 if (x->item == NULL) {
1968 PyErr_NoMemory();
1969 goto error;
1970 }
1971 x->itemsize = itemsize;
1972
1973 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1974 if (x->mview == NULL)
1975 goto error;
1976
1977
1978out:
1979 Py_XDECREF(Struct);
1980 Py_XDECREF(format);
1981 Py_XDECREF(structobj);
1982 return x;
1983
1984error:
1985 unpacker_free(x);
1986 x = NULL;
1987 goto out;
1988}
1989
1990/* unpack a single item */
1991static PyObject *
1992struct_unpack_single(const char *ptr, struct unpacker *x)
1993{
1994 PyObject *v;
1995
1996 memcpy(x->item, ptr, x->itemsize);
1997 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
1998 if (v == NULL)
1999 return NULL;
2000
2001 if (PyTuple_GET_SIZE(v) == 1) {
2002 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2003 Py_INCREF(tmp);
2004 Py_DECREF(v);
2005 return tmp;
2006 }
2007
2008 return v;
2009}
2010
2011
2012/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002013/* Representations */
2014/****************************************************************************/
2015
2016/* allow explicit form of native format */
2017Py_LOCAL_INLINE(const char *)
2018adjust_fmt(const Py_buffer *view)
2019{
2020 const char *fmt;
2021
2022 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2023 if (fmt[0] && fmt[1] == '\0')
2024 return fmt;
2025
2026 PyErr_Format(PyExc_NotImplementedError,
2027 "memoryview: unsupported format %s", view->format);
2028 return NULL;
2029}
2030
2031/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2032static PyObject *
2033tolist_base(const char *ptr, const Py_ssize_t *shape,
2034 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2035 const char *fmt)
2036{
2037 PyObject *lst, *item;
2038 Py_ssize_t i;
2039
2040 lst = PyList_New(shape[0]);
2041 if (lst == NULL)
2042 return NULL;
2043
2044 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002045 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002046 item = unpack_single(xptr, fmt);
2047 if (item == NULL) {
2048 Py_DECREF(lst);
2049 return NULL;
2050 }
2051 PyList_SET_ITEM(lst, i, item);
2052 }
2053
2054 return lst;
2055}
2056
2057/* Unpack a multi-dimensional array into a nested list.
2058 Assumption: ndim >= 1. */
2059static PyObject *
2060tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2061 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2062 const char *fmt)
2063{
2064 PyObject *lst, *item;
2065 Py_ssize_t i;
2066
2067 assert(ndim >= 1);
2068 assert(shape != NULL);
2069 assert(strides != NULL);
2070
2071 if (ndim == 1)
2072 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2073
2074 lst = PyList_New(shape[0]);
2075 if (lst == NULL)
2076 return NULL;
2077
2078 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002079 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002080 item = tolist_rec(xptr, ndim-1, shape+1,
2081 strides+1, suboffsets ? suboffsets+1 : NULL,
2082 fmt);
2083 if (item == NULL) {
2084 Py_DECREF(lst);
2085 return NULL;
2086 }
2087 PyList_SET_ITEM(lst, i, item);
2088 }
2089
2090 return lst;
2091}
2092
2093/* Return a list representation of the memoryview. Currently only buffers
2094 with native format strings are supported. */
2095static PyObject *
2096memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2097{
2098 const Py_buffer *view = &(mv->view);
2099 const char *fmt;
2100
2101 CHECK_RELEASED(mv);
2102
2103 fmt = adjust_fmt(view);
2104 if (fmt == NULL)
2105 return NULL;
2106 if (view->ndim == 0) {
2107 return unpack_single(view->buf, fmt);
2108 }
2109 else if (view->ndim == 1) {
2110 return tolist_base(view->buf, view->shape,
2111 view->strides, view->suboffsets,
2112 fmt);
2113 }
2114 else {
2115 return tolist_rec(view->buf, view->ndim, view->shape,
2116 view->strides, view->suboffsets,
2117 fmt);
2118 }
2119}
2120
2121static PyObject *
2122memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
2123{
2124 Py_buffer *src = VIEW_ADDR(self);
2125 PyObject *bytes = NULL;
2126
2127 CHECK_RELEASED(self);
2128
2129 if (MV_C_CONTIGUOUS(self->flags)) {
2130 return PyBytes_FromStringAndSize(src->buf, src->len);
2131 }
2132
2133 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2134 if (bytes == NULL)
2135 return NULL;
2136
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002137 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002138 Py_DECREF(bytes);
2139 return NULL;
2140 }
2141
2142 return bytes;
2143}
2144
2145static PyObject *
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002146memory_hex(PyMemoryViewObject *self, PyObject *dummy)
2147{
2148 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002149 PyObject *bytes;
2150 PyObject *ret;
2151
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002152 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002153
2154 if (MV_C_CONTIGUOUS(self->flags)) {
2155 return _Py_strhex(src->buf, src->len);
2156 }
2157
2158 bytes = memory_tobytes(self, dummy);
2159 if (bytes == NULL)
2160 return NULL;
2161
2162 ret = _Py_strhex(PyBytes_AS_STRING(bytes), Py_SIZE(bytes));
2163 Py_DECREF(bytes);
2164
2165 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002166}
2167
2168static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002169memory_repr(PyMemoryViewObject *self)
2170{
2171 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2172 return PyUnicode_FromFormat("<released memory at %p>", self);
2173 else
2174 return PyUnicode_FromFormat("<memory at %p>", self);
2175}
2176
2177
2178/**************************************************************************/
2179/* Indexing and slicing */
2180/**************************************************************************/
2181
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002182static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002183lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002184{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002185 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002186
2187 assert(view->shape);
2188 assert(view->strides);
2189
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002190 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002191 if (index < 0) {
2192 index += nitems;
2193 }
2194 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002195 PyErr_Format(PyExc_IndexError,
2196 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002197 return NULL;
2198 }
2199
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002200 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002201
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002202 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002203
2204 return ptr;
2205}
2206
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002207/* Get the pointer to the item at index. */
2208static char *
2209ptr_from_index(Py_buffer *view, Py_ssize_t index)
2210{
2211 char *ptr = (char *)view->buf;
2212 return lookup_dimension(view, ptr, 0, index);
2213}
2214
2215/* Get the pointer to the item at tuple. */
2216static char *
2217ptr_from_tuple(Py_buffer *view, PyObject *tup)
2218{
2219 char *ptr = (char *)view->buf;
2220 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2221
2222 if (nindices > view->ndim) {
2223 PyErr_Format(PyExc_TypeError,
2224 "cannot index %zd-dimension view with %zd-element tuple",
2225 view->ndim, nindices);
2226 return NULL;
2227 }
2228
2229 for (dim = 0; dim < nindices; dim++) {
2230 Py_ssize_t index;
2231 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2232 PyExc_IndexError);
2233 if (index == -1 && PyErr_Occurred())
2234 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002235 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002236 if (ptr == NULL)
2237 return NULL;
2238 }
2239 return ptr;
2240}
2241
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002242/* Return the item at index. In a one-dimensional view, this is an object
2243 with the type specified by view->format. Otherwise, the item is a sub-view.
2244 The function is used in memory_subscript() and memory_as_sequence. */
2245static PyObject *
2246memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2247{
2248 Py_buffer *view = &(self->view);
2249 const char *fmt;
2250
2251 CHECK_RELEASED(self);
2252
2253 fmt = adjust_fmt(view);
2254 if (fmt == NULL)
2255 return NULL;
2256
2257 if (view->ndim == 0) {
2258 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2259 return NULL;
2260 }
2261 if (view->ndim == 1) {
2262 char *ptr = ptr_from_index(view, index);
2263 if (ptr == NULL)
2264 return NULL;
2265 return unpack_single(ptr, fmt);
2266 }
2267
2268 PyErr_SetString(PyExc_NotImplementedError,
2269 "multi-dimensional sub-views are not implemented");
2270 return NULL;
2271}
2272
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002273/* Return the item at position *key* (a tuple of indices). */
2274static PyObject *
2275memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2276{
2277 Py_buffer *view = &(self->view);
2278 const char *fmt;
2279 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2280 char *ptr;
2281
2282 CHECK_RELEASED(self);
2283
2284 fmt = adjust_fmt(view);
2285 if (fmt == NULL)
2286 return NULL;
2287
2288 if (nindices < view->ndim) {
2289 PyErr_SetString(PyExc_NotImplementedError,
2290 "sub-views are not implemented");
2291 return NULL;
2292 }
2293 ptr = ptr_from_tuple(view, tup);
2294 if (ptr == NULL)
2295 return NULL;
2296 return unpack_single(ptr, fmt);
2297}
2298
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002299Py_LOCAL_INLINE(int)
2300init_slice(Py_buffer *base, PyObject *key, int dim)
2301{
2302 Py_ssize_t start, stop, step, slicelength;
2303
2304 if (PySlice_GetIndicesEx(key, base->shape[dim],
2305 &start, &stop, &step, &slicelength) < 0) {
2306 return -1;
2307 }
2308
2309
2310 if (base->suboffsets == NULL || dim == 0) {
2311 adjust_buf:
2312 base->buf = (char *)base->buf + base->strides[dim] * start;
2313 }
2314 else {
2315 Py_ssize_t n = dim-1;
2316 while (n >= 0 && base->suboffsets[n] < 0)
2317 n--;
2318 if (n < 0)
2319 goto adjust_buf; /* all suboffsets are negative */
2320 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2321 }
2322 base->shape[dim] = slicelength;
2323 base->strides[dim] = base->strides[dim] * step;
2324
2325 return 0;
2326}
2327
2328static int
2329is_multislice(PyObject *key)
2330{
2331 Py_ssize_t size, i;
2332
2333 if (!PyTuple_Check(key))
2334 return 0;
2335 size = PyTuple_GET_SIZE(key);
2336 if (size == 0)
2337 return 0;
2338
2339 for (i = 0; i < size; i++) {
2340 PyObject *x = PyTuple_GET_ITEM(key, i);
2341 if (!PySlice_Check(x))
2342 return 0;
2343 }
2344 return 1;
2345}
2346
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002347static Py_ssize_t
2348is_multiindex(PyObject *key)
2349{
2350 Py_ssize_t size, i;
2351
2352 if (!PyTuple_Check(key))
2353 return 0;
2354 size = PyTuple_GET_SIZE(key);
2355 for (i = 0; i < size; i++) {
2356 PyObject *x = PyTuple_GET_ITEM(key, i);
2357 if (!PyIndex_Check(x))
2358 return 0;
2359 }
2360 return 1;
2361}
2362
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002363/* mv[obj] returns an object holding the data for one element if obj
2364 fully indexes the memoryview or another memoryview object if it
2365 does not.
2366
2367 0-d memoryview objects can be referenced using mv[...] or mv[()]
2368 but not with anything else. */
2369static PyObject *
2370memory_subscript(PyMemoryViewObject *self, PyObject *key)
2371{
2372 Py_buffer *view;
2373 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002374
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002375 CHECK_RELEASED(self);
2376
2377 if (view->ndim == 0) {
2378 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2379 const char *fmt = adjust_fmt(view);
2380 if (fmt == NULL)
2381 return NULL;
2382 return unpack_single(view->buf, fmt);
2383 }
2384 else if (key == Py_Ellipsis) {
2385 Py_INCREF(self);
2386 return (PyObject *)self;
2387 }
2388 else {
2389 PyErr_SetString(PyExc_TypeError,
2390 "invalid indexing of 0-dim memory");
2391 return NULL;
2392 }
2393 }
2394
2395 if (PyIndex_Check(key)) {
2396 Py_ssize_t index;
2397 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2398 if (index == -1 && PyErr_Occurred())
2399 return NULL;
2400 return memory_item(self, index);
2401 }
2402 else if (PySlice_Check(key)) {
2403 PyMemoryViewObject *sliced;
2404
2405 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2406 if (sliced == NULL)
2407 return NULL;
2408
2409 if (init_slice(&sliced->view, key, 0) < 0) {
2410 Py_DECREF(sliced);
2411 return NULL;
2412 }
2413 init_len(&sliced->view);
2414 init_flags(sliced);
2415
2416 return (PyObject *)sliced;
2417 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002418 else if (is_multiindex(key)) {
2419 return memory_item_multi(self, key);
2420 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002421 else if (is_multislice(key)) {
2422 PyErr_SetString(PyExc_NotImplementedError,
2423 "multi-dimensional slicing is not implemented");
2424 return NULL;
2425 }
2426
2427 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2428 return NULL;
2429}
2430
2431static int
2432memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2433{
2434 Py_buffer *view = &(self->view);
2435 Py_buffer src;
2436 const char *fmt;
2437 char *ptr;
2438
2439 CHECK_RELEASED_INT(self);
2440
2441 fmt = adjust_fmt(view);
2442 if (fmt == NULL)
2443 return -1;
2444
2445 if (view->readonly) {
2446 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2447 return -1;
2448 }
2449 if (value == NULL) {
2450 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2451 return -1;
2452 }
2453 if (view->ndim == 0) {
2454 if (key == Py_Ellipsis ||
2455 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2456 ptr = (char *)view->buf;
2457 return pack_single(ptr, value, fmt);
2458 }
2459 else {
2460 PyErr_SetString(PyExc_TypeError,
2461 "invalid indexing of 0-dim memory");
2462 return -1;
2463 }
2464 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002465
2466 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002467 Py_ssize_t index;
2468 if (1 < view->ndim) {
2469 PyErr_SetString(PyExc_NotImplementedError,
2470 "sub-views are not implemented");
2471 return -1;
2472 }
2473 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002474 if (index == -1 && PyErr_Occurred())
2475 return -1;
2476 ptr = ptr_from_index(view, index);
2477 if (ptr == NULL)
2478 return -1;
2479 return pack_single(ptr, value, fmt);
2480 }
2481 /* one-dimensional: fast path */
2482 if (PySlice_Check(key) && view->ndim == 1) {
2483 Py_buffer dest; /* sliced view */
2484 Py_ssize_t arrays[3];
2485 int ret = -1;
2486
2487 /* rvalue must be an exporter */
2488 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2489 return ret;
2490
2491 dest = *view;
2492 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2493 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2494 if (view->suboffsets) {
2495 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2496 }
2497
2498 if (init_slice(&dest, key, 0) < 0)
2499 goto end_block;
2500 dest.len = dest.shape[0] * dest.itemsize;
2501
2502 ret = copy_single(&dest, &src);
2503
2504 end_block:
2505 PyBuffer_Release(&src);
2506 return ret;
2507 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002508 if (is_multiindex(key)) {
2509 char *ptr;
2510 if (PyTuple_GET_SIZE(key) < view->ndim) {
2511 PyErr_SetString(PyExc_NotImplementedError,
2512 "sub-views are not implemented");
2513 return -1;
2514 }
2515 ptr = ptr_from_tuple(view, key);
2516 if (ptr == NULL)
2517 return -1;
2518 return pack_single(ptr, value, fmt);
2519 }
2520 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002521 /* Call memory_subscript() to produce a sliced lvalue, then copy
2522 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2523 PyErr_SetString(PyExc_NotImplementedError,
2524 "memoryview slice assignments are currently restricted "
2525 "to ndim = 1");
2526 return -1;
2527 }
2528
2529 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2530 return -1;
2531}
2532
2533static Py_ssize_t
2534memory_length(PyMemoryViewObject *self)
2535{
2536 CHECK_RELEASED_INT(self);
2537 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2538}
2539
2540/* As mapping */
2541static PyMappingMethods memory_as_mapping = {
2542 (lenfunc)memory_length, /* mp_length */
2543 (binaryfunc)memory_subscript, /* mp_subscript */
2544 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2545};
2546
2547/* As sequence */
2548static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002549 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002550 0, /* sq_concat */
2551 0, /* sq_repeat */
2552 (ssizeargfunc)memory_item, /* sq_item */
2553};
2554
2555
2556/**************************************************************************/
2557/* Comparisons */
2558/**************************************************************************/
2559
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002560#define MV_COMPARE_EX -1 /* exception */
2561#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2562
2563/* Translate a StructError to "not equal". Preserve other exceptions. */
2564static int
2565fix_struct_error_int(void)
2566{
2567 assert(PyErr_Occurred());
2568 /* XXX Cannot get at StructError directly? */
2569 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2570 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2571 return MV_COMPARE_EX;
2572 }
2573 /* StructError: invalid or unknown format -> not equal */
2574 PyErr_Clear();
2575 return 0;
2576}
2577
2578/* Unpack and compare single items of p and q using the struct module. */
2579static int
2580struct_unpack_cmp(const char *p, const char *q,
2581 struct unpacker *unpack_p, struct unpacker *unpack_q)
2582{
2583 PyObject *v, *w;
2584 int ret;
2585
2586 /* At this point any exception from the struct module should not be
2587 StructError, since both formats have been accepted already. */
2588 v = struct_unpack_single(p, unpack_p);
2589 if (v == NULL)
2590 return MV_COMPARE_EX;
2591
2592 w = struct_unpack_single(q, unpack_q);
2593 if (w == NULL) {
2594 Py_DECREF(v);
2595 return MV_COMPARE_EX;
2596 }
2597
2598 /* MV_COMPARE_EX == -1: exceptions are preserved */
2599 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2600 Py_DECREF(v);
2601 Py_DECREF(w);
2602
2603 return ret;
2604}
2605
2606/* Unpack and compare single items of p and q. If both p and q have the same
2607 single element native format, the comparison uses a fast path (gcc creates
2608 a jump table and converts memcpy into simple assignments on x86/x64).
2609
2610 Otherwise, the comparison is delegated to the struct module, which is
2611 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002612#define CMP_SINGLE(p, q, type) \
2613 do { \
2614 type x; \
2615 type y; \
2616 memcpy((char *)&x, p, sizeof x); \
2617 memcpy((char *)&y, q, sizeof y); \
2618 equal = (x == y); \
2619 } while (0)
2620
2621Py_LOCAL_INLINE(int)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002622unpack_cmp(const char *p, const char *q, char fmt,
2623 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002624{
2625 int equal;
2626
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002627 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002628
2629 /* signed integers and fast path for 'B' */
2630 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2631 case 'b': return *((signed char *)p) == *((signed char *)q);
2632 case 'h': CMP_SINGLE(p, q, short); return equal;
2633 case 'i': CMP_SINGLE(p, q, int); return equal;
2634 case 'l': CMP_SINGLE(p, q, long); return equal;
2635
2636 /* boolean */
2637 #ifdef HAVE_C99_BOOL
2638 case '?': CMP_SINGLE(p, q, _Bool); return equal;
2639 #else
2640 case '?': CMP_SINGLE(p, q, char); return equal;
2641 #endif
2642
2643 /* unsigned integers */
2644 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2645 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2646 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2647
2648 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002649 case 'q': CMP_SINGLE(p, q, PY_LONG_LONG); return equal;
2650 case 'Q': CMP_SINGLE(p, q, unsigned PY_LONG_LONG); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002651
2652 /* ssize_t and size_t */
2653 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2654 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2655
2656 /* floats */
2657 /* XXX DBL_EPSILON? */
2658 case 'f': CMP_SINGLE(p, q, float); return equal;
2659 case 'd': CMP_SINGLE(p, q, double); return equal;
2660
2661 /* bytes object */
2662 case 'c': return *p == *q;
2663
2664 /* pointer */
2665 case 'P': CMP_SINGLE(p, q, void *); return equal;
2666
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002667 /* use the struct module */
2668 case '_':
2669 assert(unpack_p);
2670 assert(unpack_q);
2671 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002672 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002673
2674 /* NOT REACHED */
2675 PyErr_SetString(PyExc_RuntimeError,
2676 "memoryview: internal error in richcompare");
2677 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002678}
2679
2680/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2681static int
2682cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2683 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2684 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002685 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002686{
2687 Py_ssize_t i;
2688 int equal;
2689
2690 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002691 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2692 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002693 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002694 if (equal <= 0)
2695 return equal;
2696 }
2697
2698 return 1;
2699}
2700
2701/* Recursively compare two multi-dimensional arrays that have the same
2702 logical structure. Assumption: ndim >= 1. */
2703static int
2704cmp_rec(const char *p, const char *q,
2705 Py_ssize_t ndim, const Py_ssize_t *shape,
2706 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2707 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002708 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002709{
2710 Py_ssize_t i;
2711 int equal;
2712
2713 assert(ndim >= 1);
2714 assert(shape != NULL);
2715 assert(pstrides != NULL);
2716 assert(qstrides != NULL);
2717
2718 if (ndim == 1) {
2719 return cmp_base(p, q, shape,
2720 pstrides, psuboffsets,
2721 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002722 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002723 }
2724
2725 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002726 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2727 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002728 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2729 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2730 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002731 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002732 if (equal <= 0)
2733 return equal;
2734 }
2735
2736 return 1;
2737}
2738
2739static PyObject *
2740memory_richcompare(PyObject *v, PyObject *w, int op)
2741{
2742 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002743 Py_buffer wbuf, *vv;
2744 Py_buffer *ww = NULL;
2745 struct unpacker *unpack_v = NULL;
2746 struct unpacker *unpack_w = NULL;
2747 char vfmt, wfmt;
2748 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002749
2750 if (op != Py_EQ && op != Py_NE)
2751 goto result; /* Py_NotImplemented */
2752
2753 assert(PyMemoryView_Check(v));
2754 if (BASE_INACCESSIBLE(v)) {
2755 equal = (v == w);
2756 goto result;
2757 }
2758 vv = VIEW_ADDR(v);
2759
2760 if (PyMemoryView_Check(w)) {
2761 if (BASE_INACCESSIBLE(w)) {
2762 equal = (v == w);
2763 goto result;
2764 }
2765 ww = VIEW_ADDR(w);
2766 }
2767 else {
2768 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2769 PyErr_Clear();
2770 goto result; /* Py_NotImplemented */
2771 }
2772 ww = &wbuf;
2773 }
2774
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002775 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002776 PyErr_Clear();
2777 equal = 0;
2778 goto result;
2779 }
2780
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002781 /* Use fast unpacking for identical primitive C type formats. */
2782 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2783 vfmt = '_';
2784 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2785 wfmt = '_';
2786 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2787 /* Use struct module unpacking. NOTE: Even for equal format strings,
2788 memcmp() cannot be used for item comparison since it would give
2789 incorrect results in the case of NaNs or uninitialized padding
2790 bytes. */
2791 vfmt = '_';
2792 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2793 if (unpack_v == NULL) {
2794 equal = fix_struct_error_int();
2795 goto result;
2796 }
2797 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2798 if (unpack_w == NULL) {
2799 equal = fix_struct_error_int();
2800 goto result;
2801 }
2802 }
2803
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002804 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002805 equal = unpack_cmp(vv->buf, ww->buf,
2806 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002807 }
2808 else if (vv->ndim == 1) {
2809 equal = cmp_base(vv->buf, ww->buf, 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 else {
2815 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2816 vv->strides, vv->suboffsets,
2817 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002818 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002819 }
2820
2821result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002822 if (equal < 0) {
2823 if (equal == MV_COMPARE_NOT_IMPL)
2824 res = Py_NotImplemented;
2825 else /* exception */
2826 res = NULL;
2827 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002828 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2829 res = Py_True;
2830 else
2831 res = Py_False;
2832
2833 if (ww == &wbuf)
2834 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002835
2836 unpacker_free(unpack_v);
2837 unpacker_free(unpack_w);
2838
2839 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002840 return res;
2841}
2842
2843/**************************************************************************/
2844/* Hash */
2845/**************************************************************************/
2846
2847static Py_hash_t
2848memory_hash(PyMemoryViewObject *self)
2849{
2850 if (self->hash == -1) {
2851 Py_buffer *view = &self->view;
2852 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002853 Py_ssize_t ret;
2854 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002855
2856 CHECK_RELEASED_INT(self);
2857
2858 if (!view->readonly) {
2859 PyErr_SetString(PyExc_ValueError,
2860 "cannot hash writable memoryview object");
2861 return -1;
2862 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002863 ret = get_native_fmtchar(&fmt, view->format);
2864 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2865 PyErr_SetString(PyExc_ValueError,
2866 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2867 return -1;
2868 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002869 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2870 /* Keep the original error message */
2871 return -1;
2872 }
2873
2874 if (!MV_C_CONTIGUOUS(self->flags)) {
2875 mem = PyMem_Malloc(view->len);
2876 if (mem == NULL) {
2877 PyErr_NoMemory();
2878 return -1;
2879 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002880 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002881 PyMem_Free(mem);
2882 return -1;
2883 }
2884 }
2885
2886 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002887 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002888
2889 if (mem != view->buf)
2890 PyMem_Free(mem);
2891 }
2892
2893 return self->hash;
2894}
2895
2896
2897/**************************************************************************/
2898/* getters */
2899/**************************************************************************/
2900
2901static PyObject *
2902_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2903{
2904 int i;
2905 PyObject *o;
2906 PyObject *intTuple;
2907
2908 if (vals == NULL)
2909 return PyTuple_New(0);
2910
2911 intTuple = PyTuple_New(len);
2912 if (!intTuple)
2913 return NULL;
2914 for (i=0; i<len; i++) {
2915 o = PyLong_FromSsize_t(vals[i]);
2916 if (!o) {
2917 Py_DECREF(intTuple);
2918 return NULL;
2919 }
2920 PyTuple_SET_ITEM(intTuple, i, o);
2921 }
2922 return intTuple;
2923}
2924
2925static PyObject *
2926memory_obj_get(PyMemoryViewObject *self)
2927{
2928 Py_buffer *view = &self->view;
2929
2930 CHECK_RELEASED(self);
2931 if (view->obj == NULL) {
2932 Py_RETURN_NONE;
2933 }
2934 Py_INCREF(view->obj);
2935 return view->obj;
2936}
2937
2938static PyObject *
2939memory_nbytes_get(PyMemoryViewObject *self)
2940{
2941 CHECK_RELEASED(self);
2942 return PyLong_FromSsize_t(self->view.len);
2943}
2944
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002945static PyObject *
2946memory_format_get(PyMemoryViewObject *self)
2947{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002948 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002949 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002950}
2951
2952static PyObject *
2953memory_itemsize_get(PyMemoryViewObject *self)
2954{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002955 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002956 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002957}
2958
2959static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002960memory_shape_get(PyMemoryViewObject *self)
2961{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002962 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002963 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002964}
2965
2966static PyObject *
2967memory_strides_get(PyMemoryViewObject *self)
2968{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002969 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002970 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002971}
2972
2973static PyObject *
2974memory_suboffsets_get(PyMemoryViewObject *self)
2975{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002976 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002977 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002978}
2979
2980static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002981memory_readonly_get(PyMemoryViewObject *self)
2982{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002983 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002984 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002985}
2986
2987static PyObject *
2988memory_ndim_get(PyMemoryViewObject *self)
2989{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002990 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002991 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002992}
2993
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002994static PyObject *
2995memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2996{
2997 CHECK_RELEASED(self);
2998 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
2999}
3000
3001static PyObject *
3002memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3003{
3004 CHECK_RELEASED(self);
3005 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3006}
3007
3008static PyObject *
3009memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3010{
3011 CHECK_RELEASED(self);
3012 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3013}
3014
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003015PyDoc_STRVAR(memory_obj_doc,
3016 "The underlying object of the memoryview.");
3017PyDoc_STRVAR(memory_nbytes_doc,
3018 "The amount of space in bytes that the array would use in\n"
3019 " a contiguous representation.");
3020PyDoc_STRVAR(memory_readonly_doc,
3021 "A bool indicating whether the memory is read only.");
3022PyDoc_STRVAR(memory_itemsize_doc,
3023 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003024PyDoc_STRVAR(memory_format_doc,
3025 "A string containing the format (in struct module style)\n"
3026 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003027PyDoc_STRVAR(memory_ndim_doc,
3028 "An integer indicating how many dimensions of a multi-dimensional\n"
3029 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003030PyDoc_STRVAR(memory_shape_doc,
3031 "A tuple of ndim integers giving the shape of the memory\n"
3032 " as an N-dimensional array.");
3033PyDoc_STRVAR(memory_strides_doc,
3034 "A tuple of ndim integers giving the size in bytes to access\n"
3035 " each element for each dimension of the array.");
3036PyDoc_STRVAR(memory_suboffsets_doc,
3037 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003038PyDoc_STRVAR(memory_c_contiguous_doc,
3039 "A bool indicating whether the memory is C contiguous.");
3040PyDoc_STRVAR(memory_f_contiguous_doc,
3041 "A bool indicating whether the memory is Fortran contiguous.");
3042PyDoc_STRVAR(memory_contiguous_doc,
3043 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003044
Stefan Krahbcaf5992014-05-18 00:35:09 +02003045
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003046static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003047 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3048 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003049 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3050 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3051 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3052 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3053 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3054 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3055 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003056 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3057 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3058 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003059 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003060};
3061
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003062PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003063"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003064\n\
3065Release the underlying buffer exposed by the memoryview object.");
3066PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003067"tobytes($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003068\n\
3069Return the data in the buffer as a byte string.");
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003070PyDoc_STRVAR(memory_hex_doc,
3071"hex($self, /)\n--\n\
3072\n\
3073Return the data in the buffer as a string of hexadecimal numbers.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003074PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003075"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003076\n\
3077Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003078PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003079"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003080\n\
3081Cast a memoryview to a new format or shape.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003082
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003083static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003084 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3085 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003086 {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003087 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003088 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003089 {"__enter__", memory_enter, METH_NOARGS, NULL},
3090 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003091 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003092};
3093
3094
3095PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003096 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003097 "memoryview", /* tp_name */
3098 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3099 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003100 (destructor)memory_dealloc, /* tp_dealloc */
3101 0, /* tp_print */
3102 0, /* tp_getattr */
3103 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003104 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003105 (reprfunc)memory_repr, /* tp_repr */
3106 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003107 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003108 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003109 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003110 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003111 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003112 PyObject_GenericGetAttr, /* tp_getattro */
3113 0, /* tp_setattro */
3114 &memory_as_buffer, /* tp_as_buffer */
3115 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3116 memory_doc, /* tp_doc */
3117 (traverseproc)memory_traverse, /* tp_traverse */
3118 (inquiry)memory_clear, /* tp_clear */
3119 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003120 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003121 0, /* tp_iter */
3122 0, /* tp_iternext */
3123 memory_methods, /* tp_methods */
3124 0, /* tp_members */
3125 memory_getsetlist, /* tp_getset */
3126 0, /* tp_base */
3127 0, /* tp_dict */
3128 0, /* tp_descr_get */
3129 0, /* tp_descr_set */
3130 0, /* tp_dictoffset */
3131 0, /* tp_init */
3132 0, /* tp_alloc */
3133 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003134};