blob: 54fd05f6f61051df7b29bcb444f67bffaaa15f2e [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;
1114 #ifdef HAVE_LONG_LONG
1115 case 'q': case 'Q': size = sizeof(PY_LONG_LONG); break;
1116 #endif
1117 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1118 case 'f': size = sizeof(float); break;
1119 case 'd': size = sizeof(double); break;
1120 #ifdef HAVE_C99_BOOL
1121 case '?': size = sizeof(_Bool); break;
1122 #else
1123 case '?': size = sizeof(char); break;
1124 #endif
1125 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001126 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001127
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001128 if (size > 0 && fmt[1] == '\0') {
1129 *result = fmt[0];
1130 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001131 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001132
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001133 return -1;
1134}
1135
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001136Py_LOCAL_INLINE(char *)
1137get_native_fmtstr(const char *fmt)
1138{
1139 int at = 0;
1140
1141 if (fmt[0] == '@') {
1142 at = 1;
1143 fmt++;
1144 }
1145 if (fmt[0] == '\0' || fmt[1] != '\0') {
1146 return NULL;
1147 }
1148
1149#define RETURN(s) do { return at ? "@" s : s; } while (0)
1150
1151 switch (fmt[0]) {
1152 case 'c': RETURN("c");
1153 case 'b': RETURN("b");
1154 case 'B': RETURN("B");
1155 case 'h': RETURN("h");
1156 case 'H': RETURN("H");
1157 case 'i': RETURN("i");
1158 case 'I': RETURN("I");
1159 case 'l': RETURN("l");
1160 case 'L': RETURN("L");
1161 #ifdef HAVE_LONG_LONG
1162 case 'q': RETURN("q");
1163 case 'Q': RETURN("Q");
1164 #endif
1165 case 'n': RETURN("n");
1166 case 'N': RETURN("N");
1167 case 'f': RETURN("f");
1168 case 'd': RETURN("d");
1169 #ifdef HAVE_C99_BOOL
1170 case '?': RETURN("?");
1171 #else
1172 case '?': RETURN("?");
1173 #endif
1174 case 'P': RETURN("P");
1175 }
1176
1177 return NULL;
1178}
1179
1180
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001181/* Cast a memoryview's data type to 'format'. The input array must be
1182 C-contiguous. At least one of input-format, output-format must have
1183 byte size. The output array is 1-D, with the same byte length as the
1184 input array. Thus, view->len must be a multiple of the new itemsize. */
1185static int
1186cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1187{
1188 Py_buffer *view = &mv->view;
1189 PyObject *asciifmt;
1190 char srcchar, destchar;
1191 Py_ssize_t itemsize;
1192 int ret = -1;
1193
1194 assert(view->ndim >= 1);
1195 assert(Py_SIZE(mv) == 3*view->ndim);
1196 assert(view->shape == mv->ob_array);
1197 assert(view->strides == mv->ob_array + view->ndim);
1198 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1199
1200 if (get_native_fmtchar(&srcchar, view->format) < 0) {
1201 PyErr_SetString(PyExc_ValueError,
1202 "memoryview: source format must be a native single character "
1203 "format prefixed with an optional '@'");
1204 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001205 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001206
1207 asciifmt = PyUnicode_AsASCIIString(format);
1208 if (asciifmt == NULL)
1209 return ret;
1210
1211 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1212 if (itemsize < 0) {
1213 PyErr_SetString(PyExc_ValueError,
1214 "memoryview: destination format must be a native single "
1215 "character format prefixed with an optional '@'");
1216 goto out;
1217 }
1218
1219 if (!IS_BYTE_FORMAT(srcchar) && !IS_BYTE_FORMAT(destchar)) {
1220 PyErr_SetString(PyExc_TypeError,
1221 "memoryview: cannot cast between two non-byte formats");
1222 goto out;
1223 }
1224 if (view->len % itemsize) {
1225 PyErr_SetString(PyExc_TypeError,
1226 "memoryview: length is not a multiple of itemsize");
1227 goto out;
1228 }
1229
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001230 view->format = get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
1231 if (view->format == NULL) {
1232 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1233 PyErr_SetString(PyExc_RuntimeError,
1234 "memoryview: internal error");
1235 goto out;
1236 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001237 view->itemsize = itemsize;
1238
1239 view->ndim = 1;
1240 view->shape[0] = view->len / view->itemsize;
1241 view->strides[0] = view->itemsize;
1242 view->suboffsets = NULL;
1243
1244 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001245
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001246 ret = 0;
1247
1248out:
1249 Py_DECREF(asciifmt);
1250 return ret;
1251}
1252
1253/* The memoryview must have space for 3*len(seq) elements. */
1254static Py_ssize_t
1255copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1256 Py_ssize_t itemsize)
1257{
1258 Py_ssize_t x, i;
1259 Py_ssize_t len = itemsize;
1260
1261 for (i = 0; i < ndim; i++) {
1262 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1263 if (!PyLong_Check(tmp)) {
1264 PyErr_SetString(PyExc_TypeError,
1265 "memoryview.cast(): elements of shape must be integers");
1266 return -1;
1267 }
1268 x = PyLong_AsSsize_t(tmp);
1269 if (x == -1 && PyErr_Occurred()) {
1270 return -1;
1271 }
1272 if (x <= 0) {
1273 /* In general elements of shape may be 0, but not for casting. */
1274 PyErr_Format(PyExc_ValueError,
1275 "memoryview.cast(): elements of shape must be integers > 0");
1276 return -1;
1277 }
1278 if (x > PY_SSIZE_T_MAX / len) {
1279 PyErr_Format(PyExc_ValueError,
1280 "memoryview.cast(): product(shape) > SSIZE_MAX");
1281 return -1;
1282 }
1283 len *= x;
1284 shape[i] = x;
1285 }
1286
1287 return len;
1288}
1289
1290/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1291 If the result array does not have exactly the same byte length as the
1292 input array, raise ValueError. */
1293static int
1294cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1295{
1296 Py_buffer *view = &mv->view;
1297 Py_ssize_t len;
1298
1299 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1300 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1301 assert(view->shape == mv->ob_array);
1302 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1303 assert(view->suboffsets == NULL);
1304
1305 view->ndim = ndim;
1306 if (view->ndim == 0) {
1307 view->shape = NULL;
1308 view->strides = NULL;
1309 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001310 }
1311 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001312 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1313 if (len < 0)
1314 return -1;
1315 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001316 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001317
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001318 if (view->len != len) {
1319 PyErr_SetString(PyExc_TypeError,
1320 "memoryview: product(shape) * itemsize != buffer size");
1321 return -1;
1322 }
1323
1324 init_flags(mv);
1325
1326 return 0;
1327}
1328
1329static int
1330zero_in_shape(PyMemoryViewObject *mv)
1331{
1332 Py_buffer *view = &mv->view;
1333 Py_ssize_t i;
1334
1335 for (i = 0; i < view->ndim; i++)
1336 if (view->shape[i] == 0)
1337 return 1;
1338
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001339 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001340}
1341
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001342/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001343 Cast a copy of 'self' to a different view. The input view must
1344 be C-contiguous. The function always casts the input view to a
1345 1-D output according to 'format'. At least one of input-format,
1346 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001347
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001348 If 'shape' is given, the 1-D view from the previous step will
1349 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001350
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001351 All casts must result in views that will have the exact byte
1352 size of the original input. Otherwise, an error is raised.
1353*/
1354static PyObject *
1355memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001356{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001357 static char *kwlist[] = {"format", "shape", NULL};
1358 PyMemoryViewObject *mv = NULL;
1359 PyObject *shape = NULL;
1360 PyObject *format;
1361 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001362
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001363 CHECK_RELEASED(self);
1364
1365 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1366 &format, &shape)) {
1367 return NULL;
1368 }
1369 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001370 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001371 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001372 return NULL;
1373 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001374 if (!MV_C_CONTIGUOUS(self->flags)) {
1375 PyErr_SetString(PyExc_TypeError,
1376 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001377 return NULL;
1378 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001379 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001380 PyErr_SetString(PyExc_TypeError,
1381 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001382 return NULL;
1383 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001384 if (shape) {
1385 CHECK_LIST_OR_TUPLE(shape)
1386 ndim = PySequence_Fast_GET_SIZE(shape);
1387 if (ndim > PyBUF_MAX_NDIM) {
1388 PyErr_SetString(PyExc_ValueError,
1389 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001390 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001391 return NULL;
1392 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001393 if (self->view.ndim != 1 && ndim != 1) {
1394 PyErr_SetString(PyExc_TypeError,
1395 "memoryview: cast must be 1D -> ND or ND -> 1D");
1396 return NULL;
1397 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001398 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001399
1400 mv = (PyMemoryViewObject *)
1401 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1402 if (mv == NULL)
1403 return NULL;
1404
1405 if (cast_to_1D(mv, format) < 0)
1406 goto error;
1407 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1408 goto error;
1409
1410 return (PyObject *)mv;
1411
1412error:
1413 Py_DECREF(mv);
1414 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001415}
1416
1417
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001418/**************************************************************************/
1419/* getbuffer */
1420/**************************************************************************/
1421
1422static int
1423memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1424{
1425 Py_buffer *base = &self->view;
1426 int baseflags = self->flags;
1427
1428 CHECK_RELEASED_INT(self);
1429
1430 /* start with complete information */
1431 *view = *base;
1432 view->obj = NULL;
1433
1434 if (REQ_WRITABLE(flags) && base->readonly) {
1435 PyErr_SetString(PyExc_BufferError,
1436 "memoryview: underlying buffer is not writable");
1437 return -1;
1438 }
1439 if (!REQ_FORMAT(flags)) {
1440 /* NULL indicates that the buffer's data type has been cast to 'B'.
1441 view->itemsize is the _previous_ itemsize. If shape is present,
1442 the equality product(shape) * itemsize = len still holds at this
1443 point. The equality calcsize(format) = itemsize does _not_ hold
1444 from here on! */
1445 view->format = NULL;
1446 }
1447
1448 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1449 PyErr_SetString(PyExc_BufferError,
1450 "memoryview: underlying buffer is not C-contiguous");
1451 return -1;
1452 }
1453 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1454 PyErr_SetString(PyExc_BufferError,
1455 "memoryview: underlying buffer is not Fortran contiguous");
1456 return -1;
1457 }
1458 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1459 PyErr_SetString(PyExc_BufferError,
1460 "memoryview: underlying buffer is not contiguous");
1461 return -1;
1462 }
1463 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1464 PyErr_SetString(PyExc_BufferError,
1465 "memoryview: underlying buffer requires suboffsets");
1466 return -1;
1467 }
1468 if (!REQ_STRIDES(flags)) {
1469 if (!MV_C_CONTIGUOUS(baseflags)) {
1470 PyErr_SetString(PyExc_BufferError,
1471 "memoryview: underlying buffer is not C-contiguous");
1472 return -1;
1473 }
1474 view->strides = NULL;
1475 }
1476 if (!REQ_SHAPE(flags)) {
1477 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1478 so base->buf = ndbuf->data. */
1479 if (view->format != NULL) {
1480 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1481 not make sense. */
1482 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001483 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001484 "is present");
1485 return -1;
1486 }
1487 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1488 do _not_ hold from here on! */
1489 view->ndim = 1;
1490 view->shape = NULL;
1491 }
1492
1493
1494 view->obj = (PyObject *)self;
1495 Py_INCREF(view->obj);
1496 self->exports++;
1497
1498 return 0;
1499}
1500
1501static void
1502memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1503{
1504 self->exports--;
1505 return;
1506 /* PyBuffer_Release() decrements view->obj after this function returns. */
1507}
1508
1509/* Buffer methods */
1510static PyBufferProcs memory_as_buffer = {
1511 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1512 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1513};
1514
1515
1516/****************************************************************************/
1517/* Optimized pack/unpack for all native format specifiers */
1518/****************************************************************************/
1519
1520/*
1521 Fix exceptions:
1522 1) Include format string in the error message.
1523 2) OverflowError -> ValueError.
1524 3) The error message from PyNumber_Index() is not ideal.
1525*/
1526static int
1527type_error_int(const char *fmt)
1528{
1529 PyErr_Format(PyExc_TypeError,
1530 "memoryview: invalid type for format '%s'", fmt);
1531 return -1;
1532}
1533
1534static int
1535value_error_int(const char *fmt)
1536{
1537 PyErr_Format(PyExc_ValueError,
1538 "memoryview: invalid value for format '%s'", fmt);
1539 return -1;
1540}
1541
1542static int
1543fix_error_int(const char *fmt)
1544{
1545 assert(PyErr_Occurred());
1546 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1547 PyErr_Clear();
1548 return type_error_int(fmt);
1549 }
1550 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1551 PyErr_ExceptionMatches(PyExc_ValueError)) {
1552 PyErr_Clear();
1553 return value_error_int(fmt);
1554 }
1555
1556 return -1;
1557}
1558
1559/* Accept integer objects or objects with an __index__() method. */
1560static long
1561pylong_as_ld(PyObject *item)
1562{
1563 PyObject *tmp;
1564 long ld;
1565
1566 tmp = PyNumber_Index(item);
1567 if (tmp == NULL)
1568 return -1;
1569
1570 ld = PyLong_AsLong(tmp);
1571 Py_DECREF(tmp);
1572 return ld;
1573}
1574
1575static unsigned long
1576pylong_as_lu(PyObject *item)
1577{
1578 PyObject *tmp;
1579 unsigned long lu;
1580
1581 tmp = PyNumber_Index(item);
1582 if (tmp == NULL)
1583 return (unsigned long)-1;
1584
1585 lu = PyLong_AsUnsignedLong(tmp);
1586 Py_DECREF(tmp);
1587 return lu;
1588}
1589
1590#ifdef HAVE_LONG_LONG
1591static PY_LONG_LONG
1592pylong_as_lld(PyObject *item)
1593{
1594 PyObject *tmp;
1595 PY_LONG_LONG lld;
1596
1597 tmp = PyNumber_Index(item);
1598 if (tmp == NULL)
1599 return -1;
1600
1601 lld = PyLong_AsLongLong(tmp);
1602 Py_DECREF(tmp);
1603 return lld;
1604}
1605
1606static unsigned PY_LONG_LONG
1607pylong_as_llu(PyObject *item)
1608{
1609 PyObject *tmp;
1610 unsigned PY_LONG_LONG llu;
1611
1612 tmp = PyNumber_Index(item);
1613 if (tmp == NULL)
1614 return (unsigned PY_LONG_LONG)-1;
1615
1616 llu = PyLong_AsUnsignedLongLong(tmp);
1617 Py_DECREF(tmp);
1618 return llu;
1619}
1620#endif
1621
1622static Py_ssize_t
1623pylong_as_zd(PyObject *item)
1624{
1625 PyObject *tmp;
1626 Py_ssize_t zd;
1627
1628 tmp = PyNumber_Index(item);
1629 if (tmp == NULL)
1630 return -1;
1631
1632 zd = PyLong_AsSsize_t(tmp);
1633 Py_DECREF(tmp);
1634 return zd;
1635}
1636
1637static size_t
1638pylong_as_zu(PyObject *item)
1639{
1640 PyObject *tmp;
1641 size_t zu;
1642
1643 tmp = PyNumber_Index(item);
1644 if (tmp == NULL)
1645 return (size_t)-1;
1646
1647 zu = PyLong_AsSize_t(tmp);
1648 Py_DECREF(tmp);
1649 return zu;
1650}
1651
1652/* Timings with the ndarray from _testbuffer.c indicate that using the
1653 struct module is around 15x slower than the two functions below. */
1654
1655#define UNPACK_SINGLE(dest, ptr, type) \
1656 do { \
1657 type x; \
1658 memcpy((char *)&x, ptr, sizeof x); \
1659 dest = x; \
1660 } while (0)
1661
1662/* Unpack a single item. 'fmt' can be any native format character in struct
1663 module syntax. This function is very sensitive to small changes. With this
1664 layout gcc automatically generates a fast jump table. */
1665Py_LOCAL_INLINE(PyObject *)
1666unpack_single(const char *ptr, const char *fmt)
1667{
1668 unsigned PY_LONG_LONG llu;
1669 unsigned long lu;
1670 size_t zu;
1671 PY_LONG_LONG lld;
1672 long ld;
1673 Py_ssize_t zd;
1674 double d;
1675 unsigned char uc;
1676 void *p;
1677
1678 switch (fmt[0]) {
1679
1680 /* signed integers and fast path for 'B' */
1681 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1682 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1683 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1684 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1685 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1686
1687 /* boolean */
1688 #ifdef HAVE_C99_BOOL
1689 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
1690 #else
1691 case '?': UNPACK_SINGLE(ld, ptr, char); goto convert_bool;
1692 #endif
1693
1694 /* unsigned integers */
1695 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1696 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1697 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1698
1699 /* native 64-bit */
1700 #ifdef HAVE_LONG_LONG
1701 case 'q': UNPACK_SINGLE(lld, ptr, PY_LONG_LONG); goto convert_lld;
1702 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned PY_LONG_LONG); goto convert_llu;
1703 #endif
1704
1705 /* ssize_t and size_t */
1706 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1707 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1708
1709 /* floats */
1710 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1711 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1712
1713 /* bytes object */
1714 case 'c': goto convert_bytes;
1715
1716 /* pointer */
1717 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1718
1719 /* default */
1720 default: goto err_format;
1721 }
1722
1723convert_uc:
1724 /* PyLong_FromUnsignedLong() is slower */
1725 return PyLong_FromLong(uc);
1726convert_ld:
1727 return PyLong_FromLong(ld);
1728convert_lu:
1729 return PyLong_FromUnsignedLong(lu);
1730convert_lld:
1731 return PyLong_FromLongLong(lld);
1732convert_llu:
1733 return PyLong_FromUnsignedLongLong(llu);
1734convert_zd:
1735 return PyLong_FromSsize_t(zd);
1736convert_zu:
1737 return PyLong_FromSize_t(zu);
1738convert_double:
1739 return PyFloat_FromDouble(d);
1740convert_bool:
1741 return PyBool_FromLong(ld);
1742convert_bytes:
1743 return PyBytes_FromStringAndSize(ptr, 1);
1744convert_pointer:
1745 return PyLong_FromVoidPtr(p);
1746err_format:
1747 PyErr_Format(PyExc_NotImplementedError,
1748 "memoryview: format %s not supported", fmt);
1749 return NULL;
1750}
1751
1752#define PACK_SINGLE(ptr, src, type) \
1753 do { \
1754 type x; \
1755 x = (type)src; \
1756 memcpy(ptr, (char *)&x, sizeof x); \
1757 } while (0)
1758
1759/* Pack a single item. 'fmt' can be any native format character in
1760 struct module syntax. */
1761static int
1762pack_single(char *ptr, PyObject *item, const char *fmt)
1763{
1764 unsigned PY_LONG_LONG llu;
1765 unsigned long lu;
1766 size_t zu;
1767 PY_LONG_LONG lld;
1768 long ld;
1769 Py_ssize_t zd;
1770 double d;
1771 void *p;
1772
1773 switch (fmt[0]) {
1774 /* signed integers */
1775 case 'b': case 'h': case 'i': case 'l':
1776 ld = pylong_as_ld(item);
1777 if (ld == -1 && PyErr_Occurred())
1778 goto err_occurred;
1779 switch (fmt[0]) {
1780 case 'b':
1781 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1782 *((signed char *)ptr) = (signed char)ld; break;
1783 case 'h':
1784 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1785 PACK_SINGLE(ptr, ld, short); break;
1786 case 'i':
1787 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1788 PACK_SINGLE(ptr, ld, int); break;
1789 default: /* 'l' */
1790 PACK_SINGLE(ptr, ld, long); break;
1791 }
1792 break;
1793
1794 /* unsigned integers */
1795 case 'B': case 'H': case 'I': case 'L':
1796 lu = pylong_as_lu(item);
1797 if (lu == (unsigned long)-1 && PyErr_Occurred())
1798 goto err_occurred;
1799 switch (fmt[0]) {
1800 case 'B':
1801 if (lu > UCHAR_MAX) goto err_range;
1802 *((unsigned char *)ptr) = (unsigned char)lu; break;
1803 case 'H':
1804 if (lu > USHRT_MAX) goto err_range;
1805 PACK_SINGLE(ptr, lu, unsigned short); break;
1806 case 'I':
1807 if (lu > UINT_MAX) goto err_range;
1808 PACK_SINGLE(ptr, lu, unsigned int); break;
1809 default: /* 'L' */
1810 PACK_SINGLE(ptr, lu, unsigned long); break;
1811 }
1812 break;
1813
1814 /* native 64-bit */
1815 #ifdef HAVE_LONG_LONG
1816 case 'q':
1817 lld = pylong_as_lld(item);
1818 if (lld == -1 && PyErr_Occurred())
1819 goto err_occurred;
1820 PACK_SINGLE(ptr, lld, PY_LONG_LONG);
1821 break;
1822 case 'Q':
1823 llu = pylong_as_llu(item);
1824 if (llu == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
1825 goto err_occurred;
1826 PACK_SINGLE(ptr, llu, unsigned PY_LONG_LONG);
1827 break;
1828 #endif
1829
1830 /* ssize_t and size_t */
1831 case 'n':
1832 zd = pylong_as_zd(item);
1833 if (zd == -1 && PyErr_Occurred())
1834 goto err_occurred;
1835 PACK_SINGLE(ptr, zd, Py_ssize_t);
1836 break;
1837 case 'N':
1838 zu = pylong_as_zu(item);
1839 if (zu == (size_t)-1 && PyErr_Occurred())
1840 goto err_occurred;
1841 PACK_SINGLE(ptr, zu, size_t);
1842 break;
1843
1844 /* floats */
1845 case 'f': case 'd':
1846 d = PyFloat_AsDouble(item);
1847 if (d == -1.0 && PyErr_Occurred())
1848 goto err_occurred;
1849 if (fmt[0] == 'f') {
1850 PACK_SINGLE(ptr, d, float);
1851 }
1852 else {
1853 PACK_SINGLE(ptr, d, double);
1854 }
1855 break;
1856
1857 /* bool */
1858 case '?':
1859 ld = PyObject_IsTrue(item);
1860 if (ld < 0)
1861 return -1; /* preserve original error */
1862 #ifdef HAVE_C99_BOOL
1863 PACK_SINGLE(ptr, ld, _Bool);
1864 #else
1865 PACK_SINGLE(ptr, ld, char);
1866 #endif
1867 break;
1868
1869 /* bytes object */
1870 case 'c':
1871 if (!PyBytes_Check(item))
1872 return type_error_int(fmt);
1873 if (PyBytes_GET_SIZE(item) != 1)
1874 return value_error_int(fmt);
1875 *ptr = PyBytes_AS_STRING(item)[0];
1876 break;
1877
1878 /* pointer */
1879 case 'P':
1880 p = PyLong_AsVoidPtr(item);
1881 if (p == NULL && PyErr_Occurred())
1882 goto err_occurred;
1883 PACK_SINGLE(ptr, p, void *);
1884 break;
1885
1886 /* default */
1887 default: goto err_format;
1888 }
1889
1890 return 0;
1891
1892err_occurred:
1893 return fix_error_int(fmt);
1894err_range:
1895 return value_error_int(fmt);
1896err_format:
1897 PyErr_Format(PyExc_NotImplementedError,
1898 "memoryview: format %s not supported", fmt);
1899 return -1;
1900}
1901
1902
1903/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001904/* unpack using the struct module */
1905/****************************************************************************/
1906
1907/* For reasonable performance it is necessary to cache all objects required
1908 for unpacking. An unpacker can handle the format passed to unpack_from().
1909 Invariant: All pointer fields of the struct should either be NULL or valid
1910 pointers. */
1911struct unpacker {
1912 PyObject *unpack_from; /* Struct.unpack_from(format) */
1913 PyObject *mview; /* cached memoryview */
1914 char *item; /* buffer for mview */
1915 Py_ssize_t itemsize; /* len(item) */
1916};
1917
1918static struct unpacker *
1919unpacker_new(void)
1920{
1921 struct unpacker *x = PyMem_Malloc(sizeof *x);
1922
1923 if (x == NULL) {
1924 PyErr_NoMemory();
1925 return NULL;
1926 }
1927
1928 x->unpack_from = NULL;
1929 x->mview = NULL;
1930 x->item = NULL;
1931 x->itemsize = 0;
1932
1933 return x;
1934}
1935
1936static void
1937unpacker_free(struct unpacker *x)
1938{
1939 if (x) {
1940 Py_XDECREF(x->unpack_from);
1941 Py_XDECREF(x->mview);
1942 PyMem_Free(x->item);
1943 PyMem_Free(x);
1944 }
1945}
1946
1947/* Return a new unpacker for the given format. */
1948static struct unpacker *
1949struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1950{
1951 PyObject *structmodule; /* XXX cache these two */
1952 PyObject *Struct = NULL; /* XXX in globals? */
1953 PyObject *structobj = NULL;
1954 PyObject *format = NULL;
1955 struct unpacker *x = NULL;
1956
1957 structmodule = PyImport_ImportModule("struct");
1958 if (structmodule == NULL)
1959 return NULL;
1960
1961 Struct = PyObject_GetAttrString(structmodule, "Struct");
1962 Py_DECREF(structmodule);
1963 if (Struct == NULL)
1964 return NULL;
1965
1966 x = unpacker_new();
1967 if (x == NULL)
1968 goto error;
1969
1970 format = PyBytes_FromString(fmt);
1971 if (format == NULL)
1972 goto error;
1973
1974 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1975 if (structobj == NULL)
1976 goto error;
1977
1978 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1979 if (x->unpack_from == NULL)
1980 goto error;
1981
1982 x->item = PyMem_Malloc(itemsize);
1983 if (x->item == NULL) {
1984 PyErr_NoMemory();
1985 goto error;
1986 }
1987 x->itemsize = itemsize;
1988
1989 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1990 if (x->mview == NULL)
1991 goto error;
1992
1993
1994out:
1995 Py_XDECREF(Struct);
1996 Py_XDECREF(format);
1997 Py_XDECREF(structobj);
1998 return x;
1999
2000error:
2001 unpacker_free(x);
2002 x = NULL;
2003 goto out;
2004}
2005
2006/* unpack a single item */
2007static PyObject *
2008struct_unpack_single(const char *ptr, struct unpacker *x)
2009{
2010 PyObject *v;
2011
2012 memcpy(x->item, ptr, x->itemsize);
2013 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
2014 if (v == NULL)
2015 return NULL;
2016
2017 if (PyTuple_GET_SIZE(v) == 1) {
2018 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2019 Py_INCREF(tmp);
2020 Py_DECREF(v);
2021 return tmp;
2022 }
2023
2024 return v;
2025}
2026
2027
2028/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002029/* Representations */
2030/****************************************************************************/
2031
2032/* allow explicit form of native format */
2033Py_LOCAL_INLINE(const char *)
2034adjust_fmt(const Py_buffer *view)
2035{
2036 const char *fmt;
2037
2038 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2039 if (fmt[0] && fmt[1] == '\0')
2040 return fmt;
2041
2042 PyErr_Format(PyExc_NotImplementedError,
2043 "memoryview: unsupported format %s", view->format);
2044 return NULL;
2045}
2046
2047/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2048static PyObject *
2049tolist_base(const char *ptr, const Py_ssize_t *shape,
2050 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2051 const char *fmt)
2052{
2053 PyObject *lst, *item;
2054 Py_ssize_t i;
2055
2056 lst = PyList_New(shape[0]);
2057 if (lst == NULL)
2058 return NULL;
2059
2060 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002061 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002062 item = unpack_single(xptr, fmt);
2063 if (item == NULL) {
2064 Py_DECREF(lst);
2065 return NULL;
2066 }
2067 PyList_SET_ITEM(lst, i, item);
2068 }
2069
2070 return lst;
2071}
2072
2073/* Unpack a multi-dimensional array into a nested list.
2074 Assumption: ndim >= 1. */
2075static PyObject *
2076tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2077 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2078 const char *fmt)
2079{
2080 PyObject *lst, *item;
2081 Py_ssize_t i;
2082
2083 assert(ndim >= 1);
2084 assert(shape != NULL);
2085 assert(strides != NULL);
2086
2087 if (ndim == 1)
2088 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2089
2090 lst = PyList_New(shape[0]);
2091 if (lst == NULL)
2092 return NULL;
2093
2094 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002095 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002096 item = tolist_rec(xptr, ndim-1, shape+1,
2097 strides+1, suboffsets ? suboffsets+1 : NULL,
2098 fmt);
2099 if (item == NULL) {
2100 Py_DECREF(lst);
2101 return NULL;
2102 }
2103 PyList_SET_ITEM(lst, i, item);
2104 }
2105
2106 return lst;
2107}
2108
2109/* Return a list representation of the memoryview. Currently only buffers
2110 with native format strings are supported. */
2111static PyObject *
2112memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2113{
2114 const Py_buffer *view = &(mv->view);
2115 const char *fmt;
2116
2117 CHECK_RELEASED(mv);
2118
2119 fmt = adjust_fmt(view);
2120 if (fmt == NULL)
2121 return NULL;
2122 if (view->ndim == 0) {
2123 return unpack_single(view->buf, fmt);
2124 }
2125 else if (view->ndim == 1) {
2126 return tolist_base(view->buf, view->shape,
2127 view->strides, view->suboffsets,
2128 fmt);
2129 }
2130 else {
2131 return tolist_rec(view->buf, view->ndim, view->shape,
2132 view->strides, view->suboffsets,
2133 fmt);
2134 }
2135}
2136
2137static PyObject *
2138memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
2139{
2140 Py_buffer *src = VIEW_ADDR(self);
2141 PyObject *bytes = NULL;
2142
2143 CHECK_RELEASED(self);
2144
2145 if (MV_C_CONTIGUOUS(self->flags)) {
2146 return PyBytes_FromStringAndSize(src->buf, src->len);
2147 }
2148
2149 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2150 if (bytes == NULL)
2151 return NULL;
2152
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002153 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002154 Py_DECREF(bytes);
2155 return NULL;
2156 }
2157
2158 return bytes;
2159}
2160
2161static PyObject *
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002162memory_hex(PyMemoryViewObject *self, PyObject *dummy)
2163{
2164 Py_buffer *src = VIEW_ADDR(self);
2165 CHECK_RELEASED(self);
2166 return _Py_strhex(src->buf, src->len);
2167}
2168
2169static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002170memory_repr(PyMemoryViewObject *self)
2171{
2172 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2173 return PyUnicode_FromFormat("<released memory at %p>", self);
2174 else
2175 return PyUnicode_FromFormat("<memory at %p>", self);
2176}
2177
2178
2179/**************************************************************************/
2180/* Indexing and slicing */
2181/**************************************************************************/
2182
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002183static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002184lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002185{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002186 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002187
2188 assert(view->shape);
2189 assert(view->strides);
2190
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002191 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002192 if (index < 0) {
2193 index += nitems;
2194 }
2195 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002196 PyErr_Format(PyExc_IndexError,
2197 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002198 return NULL;
2199 }
2200
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002201 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002202
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002203 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002204
2205 return ptr;
2206}
2207
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002208/* Get the pointer to the item at index. */
2209static char *
2210ptr_from_index(Py_buffer *view, Py_ssize_t index)
2211{
2212 char *ptr = (char *)view->buf;
2213 return lookup_dimension(view, ptr, 0, index);
2214}
2215
2216/* Get the pointer to the item at tuple. */
2217static char *
2218ptr_from_tuple(Py_buffer *view, PyObject *tup)
2219{
2220 char *ptr = (char *)view->buf;
2221 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2222
2223 if (nindices > view->ndim) {
2224 PyErr_Format(PyExc_TypeError,
2225 "cannot index %zd-dimension view with %zd-element tuple",
2226 view->ndim, nindices);
2227 return NULL;
2228 }
2229
2230 for (dim = 0; dim < nindices; dim++) {
2231 Py_ssize_t index;
2232 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2233 PyExc_IndexError);
2234 if (index == -1 && PyErr_Occurred())
2235 return NULL;
2236 ptr = lookup_dimension(view, ptr, dim, index);
2237 if (ptr == NULL)
2238 return NULL;
2239 }
2240 return ptr;
2241}
2242
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002243/* Return the item at index. In a one-dimensional view, this is an object
2244 with the type specified by view->format. Otherwise, the item is a sub-view.
2245 The function is used in memory_subscript() and memory_as_sequence. */
2246static PyObject *
2247memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2248{
2249 Py_buffer *view = &(self->view);
2250 const char *fmt;
2251
2252 CHECK_RELEASED(self);
2253
2254 fmt = adjust_fmt(view);
2255 if (fmt == NULL)
2256 return NULL;
2257
2258 if (view->ndim == 0) {
2259 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2260 return NULL;
2261 }
2262 if (view->ndim == 1) {
2263 char *ptr = ptr_from_index(view, index);
2264 if (ptr == NULL)
2265 return NULL;
2266 return unpack_single(ptr, fmt);
2267 }
2268
2269 PyErr_SetString(PyExc_NotImplementedError,
2270 "multi-dimensional sub-views are not implemented");
2271 return NULL;
2272}
2273
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002274/* Return the item at position *key* (a tuple of indices). */
2275static PyObject *
2276memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2277{
2278 Py_buffer *view = &(self->view);
2279 const char *fmt;
2280 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2281 char *ptr;
2282
2283 CHECK_RELEASED(self);
2284
2285 fmt = adjust_fmt(view);
2286 if (fmt == NULL)
2287 return NULL;
2288
2289 if (nindices < view->ndim) {
2290 PyErr_SetString(PyExc_NotImplementedError,
2291 "sub-views are not implemented");
2292 return NULL;
2293 }
2294 ptr = ptr_from_tuple(view, tup);
2295 if (ptr == NULL)
2296 return NULL;
2297 return unpack_single(ptr, fmt);
2298}
2299
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002300Py_LOCAL_INLINE(int)
2301init_slice(Py_buffer *base, PyObject *key, int dim)
2302{
2303 Py_ssize_t start, stop, step, slicelength;
2304
2305 if (PySlice_GetIndicesEx(key, base->shape[dim],
2306 &start, &stop, &step, &slicelength) < 0) {
2307 return -1;
2308 }
2309
2310
2311 if (base->suboffsets == NULL || dim == 0) {
2312 adjust_buf:
2313 base->buf = (char *)base->buf + base->strides[dim] * start;
2314 }
2315 else {
2316 Py_ssize_t n = dim-1;
2317 while (n >= 0 && base->suboffsets[n] < 0)
2318 n--;
2319 if (n < 0)
2320 goto adjust_buf; /* all suboffsets are negative */
2321 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2322 }
2323 base->shape[dim] = slicelength;
2324 base->strides[dim] = base->strides[dim] * step;
2325
2326 return 0;
2327}
2328
2329static int
2330is_multislice(PyObject *key)
2331{
2332 Py_ssize_t size, i;
2333
2334 if (!PyTuple_Check(key))
2335 return 0;
2336 size = PyTuple_GET_SIZE(key);
2337 if (size == 0)
2338 return 0;
2339
2340 for (i = 0; i < size; i++) {
2341 PyObject *x = PyTuple_GET_ITEM(key, i);
2342 if (!PySlice_Check(x))
2343 return 0;
2344 }
2345 return 1;
2346}
2347
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002348static Py_ssize_t
2349is_multiindex(PyObject *key)
2350{
2351 Py_ssize_t size, i;
2352
2353 if (!PyTuple_Check(key))
2354 return 0;
2355 size = PyTuple_GET_SIZE(key);
2356 for (i = 0; i < size; i++) {
2357 PyObject *x = PyTuple_GET_ITEM(key, i);
2358 if (!PyIndex_Check(x))
2359 return 0;
2360 }
2361 return 1;
2362}
2363
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002364/* mv[obj] returns an object holding the data for one element if obj
2365 fully indexes the memoryview or another memoryview object if it
2366 does not.
2367
2368 0-d memoryview objects can be referenced using mv[...] or mv[()]
2369 but not with anything else. */
2370static PyObject *
2371memory_subscript(PyMemoryViewObject *self, PyObject *key)
2372{
2373 Py_buffer *view;
2374 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002375
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002376 CHECK_RELEASED(self);
2377
2378 if (view->ndim == 0) {
2379 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2380 const char *fmt = adjust_fmt(view);
2381 if (fmt == NULL)
2382 return NULL;
2383 return unpack_single(view->buf, fmt);
2384 }
2385 else if (key == Py_Ellipsis) {
2386 Py_INCREF(self);
2387 return (PyObject *)self;
2388 }
2389 else {
2390 PyErr_SetString(PyExc_TypeError,
2391 "invalid indexing of 0-dim memory");
2392 return NULL;
2393 }
2394 }
2395
2396 if (PyIndex_Check(key)) {
2397 Py_ssize_t index;
2398 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2399 if (index == -1 && PyErr_Occurred())
2400 return NULL;
2401 return memory_item(self, index);
2402 }
2403 else if (PySlice_Check(key)) {
2404 PyMemoryViewObject *sliced;
2405
2406 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2407 if (sliced == NULL)
2408 return NULL;
2409
2410 if (init_slice(&sliced->view, key, 0) < 0) {
2411 Py_DECREF(sliced);
2412 return NULL;
2413 }
2414 init_len(&sliced->view);
2415 init_flags(sliced);
2416
2417 return (PyObject *)sliced;
2418 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002419 else if (is_multiindex(key)) {
2420 return memory_item_multi(self, key);
2421 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002422 else if (is_multislice(key)) {
2423 PyErr_SetString(PyExc_NotImplementedError,
2424 "multi-dimensional slicing is not implemented");
2425 return NULL;
2426 }
2427
2428 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2429 return NULL;
2430}
2431
2432static int
2433memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2434{
2435 Py_buffer *view = &(self->view);
2436 Py_buffer src;
2437 const char *fmt;
2438 char *ptr;
2439
2440 CHECK_RELEASED_INT(self);
2441
2442 fmt = adjust_fmt(view);
2443 if (fmt == NULL)
2444 return -1;
2445
2446 if (view->readonly) {
2447 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2448 return -1;
2449 }
2450 if (value == NULL) {
2451 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2452 return -1;
2453 }
2454 if (view->ndim == 0) {
2455 if (key == Py_Ellipsis ||
2456 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2457 ptr = (char *)view->buf;
2458 return pack_single(ptr, value, fmt);
2459 }
2460 else {
2461 PyErr_SetString(PyExc_TypeError,
2462 "invalid indexing of 0-dim memory");
2463 return -1;
2464 }
2465 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002466
2467 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002468 Py_ssize_t index;
2469 if (1 < view->ndim) {
2470 PyErr_SetString(PyExc_NotImplementedError,
2471 "sub-views are not implemented");
2472 return -1;
2473 }
2474 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002475 if (index == -1 && PyErr_Occurred())
2476 return -1;
2477 ptr = ptr_from_index(view, index);
2478 if (ptr == NULL)
2479 return -1;
2480 return pack_single(ptr, value, fmt);
2481 }
2482 /* one-dimensional: fast path */
2483 if (PySlice_Check(key) && view->ndim == 1) {
2484 Py_buffer dest; /* sliced view */
2485 Py_ssize_t arrays[3];
2486 int ret = -1;
2487
2488 /* rvalue must be an exporter */
2489 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2490 return ret;
2491
2492 dest = *view;
2493 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2494 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2495 if (view->suboffsets) {
2496 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2497 }
2498
2499 if (init_slice(&dest, key, 0) < 0)
2500 goto end_block;
2501 dest.len = dest.shape[0] * dest.itemsize;
2502
2503 ret = copy_single(&dest, &src);
2504
2505 end_block:
2506 PyBuffer_Release(&src);
2507 return ret;
2508 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002509 if (is_multiindex(key)) {
2510 char *ptr;
2511 if (PyTuple_GET_SIZE(key) < view->ndim) {
2512 PyErr_SetString(PyExc_NotImplementedError,
2513 "sub-views are not implemented");
2514 return -1;
2515 }
2516 ptr = ptr_from_tuple(view, key);
2517 if (ptr == NULL)
2518 return -1;
2519 return pack_single(ptr, value, fmt);
2520 }
2521 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002522 /* Call memory_subscript() to produce a sliced lvalue, then copy
2523 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2524 PyErr_SetString(PyExc_NotImplementedError,
2525 "memoryview slice assignments are currently restricted "
2526 "to ndim = 1");
2527 return -1;
2528 }
2529
2530 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2531 return -1;
2532}
2533
2534static Py_ssize_t
2535memory_length(PyMemoryViewObject *self)
2536{
2537 CHECK_RELEASED_INT(self);
2538 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2539}
2540
2541/* As mapping */
2542static PyMappingMethods memory_as_mapping = {
2543 (lenfunc)memory_length, /* mp_length */
2544 (binaryfunc)memory_subscript, /* mp_subscript */
2545 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2546};
2547
2548/* As sequence */
2549static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002550 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002551 0, /* sq_concat */
2552 0, /* sq_repeat */
2553 (ssizeargfunc)memory_item, /* sq_item */
2554};
2555
2556
2557/**************************************************************************/
2558/* Comparisons */
2559/**************************************************************************/
2560
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002561#define MV_COMPARE_EX -1 /* exception */
2562#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2563
2564/* Translate a StructError to "not equal". Preserve other exceptions. */
2565static int
2566fix_struct_error_int(void)
2567{
2568 assert(PyErr_Occurred());
2569 /* XXX Cannot get at StructError directly? */
2570 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2571 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2572 return MV_COMPARE_EX;
2573 }
2574 /* StructError: invalid or unknown format -> not equal */
2575 PyErr_Clear();
2576 return 0;
2577}
2578
2579/* Unpack and compare single items of p and q using the struct module. */
2580static int
2581struct_unpack_cmp(const char *p, const char *q,
2582 struct unpacker *unpack_p, struct unpacker *unpack_q)
2583{
2584 PyObject *v, *w;
2585 int ret;
2586
2587 /* At this point any exception from the struct module should not be
2588 StructError, since both formats have been accepted already. */
2589 v = struct_unpack_single(p, unpack_p);
2590 if (v == NULL)
2591 return MV_COMPARE_EX;
2592
2593 w = struct_unpack_single(q, unpack_q);
2594 if (w == NULL) {
2595 Py_DECREF(v);
2596 return MV_COMPARE_EX;
2597 }
2598
2599 /* MV_COMPARE_EX == -1: exceptions are preserved */
2600 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2601 Py_DECREF(v);
2602 Py_DECREF(w);
2603
2604 return ret;
2605}
2606
2607/* Unpack and compare single items of p and q. If both p and q have the same
2608 single element native format, the comparison uses a fast path (gcc creates
2609 a jump table and converts memcpy into simple assignments on x86/x64).
2610
2611 Otherwise, the comparison is delegated to the struct module, which is
2612 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002613#define CMP_SINGLE(p, q, type) \
2614 do { \
2615 type x; \
2616 type y; \
2617 memcpy((char *)&x, p, sizeof x); \
2618 memcpy((char *)&y, q, sizeof y); \
2619 equal = (x == y); \
2620 } while (0)
2621
2622Py_LOCAL_INLINE(int)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002623unpack_cmp(const char *p, const char *q, char fmt,
2624 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002625{
2626 int equal;
2627
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002628 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002629
2630 /* signed integers and fast path for 'B' */
2631 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2632 case 'b': return *((signed char *)p) == *((signed char *)q);
2633 case 'h': CMP_SINGLE(p, q, short); return equal;
2634 case 'i': CMP_SINGLE(p, q, int); return equal;
2635 case 'l': CMP_SINGLE(p, q, long); return equal;
2636
2637 /* boolean */
2638 #ifdef HAVE_C99_BOOL
2639 case '?': CMP_SINGLE(p, q, _Bool); return equal;
2640 #else
2641 case '?': CMP_SINGLE(p, q, char); return equal;
2642 #endif
2643
2644 /* unsigned integers */
2645 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2646 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2647 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2648
2649 /* native 64-bit */
2650 #ifdef HAVE_LONG_LONG
2651 case 'q': CMP_SINGLE(p, q, PY_LONG_LONG); return equal;
2652 case 'Q': CMP_SINGLE(p, q, unsigned PY_LONG_LONG); return equal;
2653 #endif
2654
2655 /* ssize_t and size_t */
2656 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2657 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2658
2659 /* floats */
2660 /* XXX DBL_EPSILON? */
2661 case 'f': CMP_SINGLE(p, q, float); return equal;
2662 case 'd': CMP_SINGLE(p, q, double); return equal;
2663
2664 /* bytes object */
2665 case 'c': return *p == *q;
2666
2667 /* pointer */
2668 case 'P': CMP_SINGLE(p, q, void *); return equal;
2669
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002670 /* use the struct module */
2671 case '_':
2672 assert(unpack_p);
2673 assert(unpack_q);
2674 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002675 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002676
2677 /* NOT REACHED */
2678 PyErr_SetString(PyExc_RuntimeError,
2679 "memoryview: internal error in richcompare");
2680 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002681}
2682
2683/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2684static int
2685cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2686 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2687 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002688 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002689{
2690 Py_ssize_t i;
2691 int equal;
2692
2693 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002694 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2695 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002696 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002697 if (equal <= 0)
2698 return equal;
2699 }
2700
2701 return 1;
2702}
2703
2704/* Recursively compare two multi-dimensional arrays that have the same
2705 logical structure. Assumption: ndim >= 1. */
2706static int
2707cmp_rec(const char *p, const char *q,
2708 Py_ssize_t ndim, const Py_ssize_t *shape,
2709 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2710 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002711 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002712{
2713 Py_ssize_t i;
2714 int equal;
2715
2716 assert(ndim >= 1);
2717 assert(shape != NULL);
2718 assert(pstrides != NULL);
2719 assert(qstrides != NULL);
2720
2721 if (ndim == 1) {
2722 return cmp_base(p, q, shape,
2723 pstrides, psuboffsets,
2724 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002725 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002726 }
2727
2728 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002729 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2730 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002731 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2732 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2733 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002734 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002735 if (equal <= 0)
2736 return equal;
2737 }
2738
2739 return 1;
2740}
2741
2742static PyObject *
2743memory_richcompare(PyObject *v, PyObject *w, int op)
2744{
2745 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002746 Py_buffer wbuf, *vv;
2747 Py_buffer *ww = NULL;
2748 struct unpacker *unpack_v = NULL;
2749 struct unpacker *unpack_w = NULL;
2750 char vfmt, wfmt;
2751 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002752
2753 if (op != Py_EQ && op != Py_NE)
2754 goto result; /* Py_NotImplemented */
2755
2756 assert(PyMemoryView_Check(v));
2757 if (BASE_INACCESSIBLE(v)) {
2758 equal = (v == w);
2759 goto result;
2760 }
2761 vv = VIEW_ADDR(v);
2762
2763 if (PyMemoryView_Check(w)) {
2764 if (BASE_INACCESSIBLE(w)) {
2765 equal = (v == w);
2766 goto result;
2767 }
2768 ww = VIEW_ADDR(w);
2769 }
2770 else {
2771 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2772 PyErr_Clear();
2773 goto result; /* Py_NotImplemented */
2774 }
2775 ww = &wbuf;
2776 }
2777
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002778 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002779 PyErr_Clear();
2780 equal = 0;
2781 goto result;
2782 }
2783
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002784 /* Use fast unpacking for identical primitive C type formats. */
2785 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2786 vfmt = '_';
2787 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2788 wfmt = '_';
2789 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2790 /* Use struct module unpacking. NOTE: Even for equal format strings,
2791 memcmp() cannot be used for item comparison since it would give
2792 incorrect results in the case of NaNs or uninitialized padding
2793 bytes. */
2794 vfmt = '_';
2795 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2796 if (unpack_v == NULL) {
2797 equal = fix_struct_error_int();
2798 goto result;
2799 }
2800 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2801 if (unpack_w == NULL) {
2802 equal = fix_struct_error_int();
2803 goto result;
2804 }
2805 }
2806
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002807 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002808 equal = unpack_cmp(vv->buf, ww->buf,
2809 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002810 }
2811 else if (vv->ndim == 1) {
2812 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2813 vv->strides, vv->suboffsets,
2814 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002815 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002816 }
2817 else {
2818 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2819 vv->strides, vv->suboffsets,
2820 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002821 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002822 }
2823
2824result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002825 if (equal < 0) {
2826 if (equal == MV_COMPARE_NOT_IMPL)
2827 res = Py_NotImplemented;
2828 else /* exception */
2829 res = NULL;
2830 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002831 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2832 res = Py_True;
2833 else
2834 res = Py_False;
2835
2836 if (ww == &wbuf)
2837 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002838
2839 unpacker_free(unpack_v);
2840 unpacker_free(unpack_w);
2841
2842 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002843 return res;
2844}
2845
2846/**************************************************************************/
2847/* Hash */
2848/**************************************************************************/
2849
2850static Py_hash_t
2851memory_hash(PyMemoryViewObject *self)
2852{
2853 if (self->hash == -1) {
2854 Py_buffer *view = &self->view;
2855 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002856 Py_ssize_t ret;
2857 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002858
2859 CHECK_RELEASED_INT(self);
2860
2861 if (!view->readonly) {
2862 PyErr_SetString(PyExc_ValueError,
2863 "cannot hash writable memoryview object");
2864 return -1;
2865 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002866 ret = get_native_fmtchar(&fmt, view->format);
2867 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2868 PyErr_SetString(PyExc_ValueError,
2869 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2870 return -1;
2871 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002872 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2873 /* Keep the original error message */
2874 return -1;
2875 }
2876
2877 if (!MV_C_CONTIGUOUS(self->flags)) {
2878 mem = PyMem_Malloc(view->len);
2879 if (mem == NULL) {
2880 PyErr_NoMemory();
2881 return -1;
2882 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002883 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002884 PyMem_Free(mem);
2885 return -1;
2886 }
2887 }
2888
2889 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002890 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002891
2892 if (mem != view->buf)
2893 PyMem_Free(mem);
2894 }
2895
2896 return self->hash;
2897}
2898
2899
2900/**************************************************************************/
2901/* getters */
2902/**************************************************************************/
2903
2904static PyObject *
2905_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2906{
2907 int i;
2908 PyObject *o;
2909 PyObject *intTuple;
2910
2911 if (vals == NULL)
2912 return PyTuple_New(0);
2913
2914 intTuple = PyTuple_New(len);
2915 if (!intTuple)
2916 return NULL;
2917 for (i=0; i<len; i++) {
2918 o = PyLong_FromSsize_t(vals[i]);
2919 if (!o) {
2920 Py_DECREF(intTuple);
2921 return NULL;
2922 }
2923 PyTuple_SET_ITEM(intTuple, i, o);
2924 }
2925 return intTuple;
2926}
2927
2928static PyObject *
2929memory_obj_get(PyMemoryViewObject *self)
2930{
2931 Py_buffer *view = &self->view;
2932
2933 CHECK_RELEASED(self);
2934 if (view->obj == NULL) {
2935 Py_RETURN_NONE;
2936 }
2937 Py_INCREF(view->obj);
2938 return view->obj;
2939}
2940
2941static PyObject *
2942memory_nbytes_get(PyMemoryViewObject *self)
2943{
2944 CHECK_RELEASED(self);
2945 return PyLong_FromSsize_t(self->view.len);
2946}
2947
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002948static PyObject *
2949memory_format_get(PyMemoryViewObject *self)
2950{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002951 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002952 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002953}
2954
2955static PyObject *
2956memory_itemsize_get(PyMemoryViewObject *self)
2957{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002958 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002959 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002960}
2961
2962static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002963memory_shape_get(PyMemoryViewObject *self)
2964{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002965 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002966 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002967}
2968
2969static PyObject *
2970memory_strides_get(PyMemoryViewObject *self)
2971{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002972 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002973 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002974}
2975
2976static PyObject *
2977memory_suboffsets_get(PyMemoryViewObject *self)
2978{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002979 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002980 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002981}
2982
2983static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002984memory_readonly_get(PyMemoryViewObject *self)
2985{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002986 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002987 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002988}
2989
2990static PyObject *
2991memory_ndim_get(PyMemoryViewObject *self)
2992{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002993 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002994 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002995}
2996
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002997static PyObject *
2998memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2999{
3000 CHECK_RELEASED(self);
3001 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3002}
3003
3004static PyObject *
3005memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3006{
3007 CHECK_RELEASED(self);
3008 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3009}
3010
3011static PyObject *
3012memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3013{
3014 CHECK_RELEASED(self);
3015 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3016}
3017
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003018PyDoc_STRVAR(memory_obj_doc,
3019 "The underlying object of the memoryview.");
3020PyDoc_STRVAR(memory_nbytes_doc,
3021 "The amount of space in bytes that the array would use in\n"
3022 " a contiguous representation.");
3023PyDoc_STRVAR(memory_readonly_doc,
3024 "A bool indicating whether the memory is read only.");
3025PyDoc_STRVAR(memory_itemsize_doc,
3026 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003027PyDoc_STRVAR(memory_format_doc,
3028 "A string containing the format (in struct module style)\n"
3029 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003030PyDoc_STRVAR(memory_ndim_doc,
3031 "An integer indicating how many dimensions of a multi-dimensional\n"
3032 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003033PyDoc_STRVAR(memory_shape_doc,
3034 "A tuple of ndim integers giving the shape of the memory\n"
3035 " as an N-dimensional array.");
3036PyDoc_STRVAR(memory_strides_doc,
3037 "A tuple of ndim integers giving the size in bytes to access\n"
3038 " each element for each dimension of the array.");
3039PyDoc_STRVAR(memory_suboffsets_doc,
3040 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003041PyDoc_STRVAR(memory_c_contiguous_doc,
3042 "A bool indicating whether the memory is C contiguous.");
3043PyDoc_STRVAR(memory_f_contiguous_doc,
3044 "A bool indicating whether the memory is Fortran contiguous.");
3045PyDoc_STRVAR(memory_contiguous_doc,
3046 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003047
Stefan Krahbcaf5992014-05-18 00:35:09 +02003048
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003049static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003050 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3051 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003052 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3053 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3054 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3055 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3056 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3057 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3058 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003059 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3060 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3061 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003062 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003063};
3064
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003065PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003066"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003067\n\
3068Release the underlying buffer exposed by the memoryview object.");
3069PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003070"tobytes($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003071\n\
3072Return the data in the buffer as a byte string.");
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003073PyDoc_STRVAR(memory_hex_doc,
3074"hex($self, /)\n--\n\
3075\n\
3076Return the data in the buffer as a string of hexadecimal numbers.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003077PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003078"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003079\n\
3080Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003081PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003082"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003083\n\
3084Cast a memoryview to a new format or shape.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003085
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003086static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003087 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3088 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003089 {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003090 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003091 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003092 {"__enter__", memory_enter, METH_NOARGS, NULL},
3093 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003094 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003095};
3096
3097
3098PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003099 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003100 "memoryview", /* tp_name */
3101 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3102 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003103 (destructor)memory_dealloc, /* tp_dealloc */
3104 0, /* tp_print */
3105 0, /* tp_getattr */
3106 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003107 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003108 (reprfunc)memory_repr, /* tp_repr */
3109 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003110 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003111 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003112 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003113 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003114 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003115 PyObject_GenericGetAttr, /* tp_getattro */
3116 0, /* tp_setattro */
3117 &memory_as_buffer, /* tp_as_buffer */
3118 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3119 memory_doc, /* tp_doc */
3120 (traverseproc)memory_traverse, /* tp_traverse */
3121 (inquiry)memory_clear, /* tp_clear */
3122 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003123 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003124 0, /* tp_iter */
3125 0, /* tp_iternext */
3126 memory_methods, /* tp_methods */
3127 0, /* tp_members */
3128 memory_getsetlist, /* tp_getset */
3129 0, /* tp_base */
3130 0, /* tp_dict */
3131 0, /* tp_descr_get */
3132 0, /* tp_descr_set */
3133 0, /* tp_dictoffset */
3134 0, /* tp_init */
3135 0, /* tp_alloc */
3136 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003137};