blob: 10162cb92ded6eefc17214be877006ab1a7e5699 [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
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001200 asciifmt = PyUnicode_AsASCIIString(format);
1201 if (asciifmt == NULL)
1202 return ret;
1203
1204 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1205 if (itemsize < 0) {
1206 PyErr_SetString(PyExc_ValueError,
1207 "memoryview: destination format must be a native single "
1208 "character format prefixed with an optional '@'");
1209 goto out;
1210 }
1211
Stefan Krah0c515952015-08-08 13:38:10 +02001212 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1213 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001214 PyErr_SetString(PyExc_TypeError,
1215 "memoryview: cannot cast between two non-byte formats");
1216 goto out;
1217 }
1218 if (view->len % itemsize) {
1219 PyErr_SetString(PyExc_TypeError,
1220 "memoryview: length is not a multiple of itemsize");
1221 goto out;
1222 }
1223
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001224 view->format = get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
1225 if (view->format == NULL) {
1226 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1227 PyErr_SetString(PyExc_RuntimeError,
1228 "memoryview: internal error");
1229 goto out;
1230 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001231 view->itemsize = itemsize;
1232
1233 view->ndim = 1;
1234 view->shape[0] = view->len / view->itemsize;
1235 view->strides[0] = view->itemsize;
1236 view->suboffsets = NULL;
1237
1238 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001239
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001240 ret = 0;
1241
1242out:
1243 Py_DECREF(asciifmt);
1244 return ret;
1245}
1246
1247/* The memoryview must have space for 3*len(seq) elements. */
1248static Py_ssize_t
1249copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1250 Py_ssize_t itemsize)
1251{
1252 Py_ssize_t x, i;
1253 Py_ssize_t len = itemsize;
1254
1255 for (i = 0; i < ndim; i++) {
1256 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1257 if (!PyLong_Check(tmp)) {
1258 PyErr_SetString(PyExc_TypeError,
1259 "memoryview.cast(): elements of shape must be integers");
1260 return -1;
1261 }
1262 x = PyLong_AsSsize_t(tmp);
1263 if (x == -1 && PyErr_Occurred()) {
1264 return -1;
1265 }
1266 if (x <= 0) {
1267 /* In general elements of shape may be 0, but not for casting. */
1268 PyErr_Format(PyExc_ValueError,
1269 "memoryview.cast(): elements of shape must be integers > 0");
1270 return -1;
1271 }
1272 if (x > PY_SSIZE_T_MAX / len) {
1273 PyErr_Format(PyExc_ValueError,
1274 "memoryview.cast(): product(shape) > SSIZE_MAX");
1275 return -1;
1276 }
1277 len *= x;
1278 shape[i] = x;
1279 }
1280
1281 return len;
1282}
1283
1284/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1285 If the result array does not have exactly the same byte length as the
1286 input array, raise ValueError. */
1287static int
1288cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1289{
1290 Py_buffer *view = &mv->view;
1291 Py_ssize_t len;
1292
1293 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1294 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1295 assert(view->shape == mv->ob_array);
1296 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1297 assert(view->suboffsets == NULL);
1298
1299 view->ndim = ndim;
1300 if (view->ndim == 0) {
1301 view->shape = NULL;
1302 view->strides = NULL;
1303 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001304 }
1305 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001306 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1307 if (len < 0)
1308 return -1;
1309 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001310 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001311
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001312 if (view->len != len) {
1313 PyErr_SetString(PyExc_TypeError,
1314 "memoryview: product(shape) * itemsize != buffer size");
1315 return -1;
1316 }
1317
1318 init_flags(mv);
1319
1320 return 0;
1321}
1322
1323static int
1324zero_in_shape(PyMemoryViewObject *mv)
1325{
1326 Py_buffer *view = &mv->view;
1327 Py_ssize_t i;
1328
1329 for (i = 0; i < view->ndim; i++)
1330 if (view->shape[i] == 0)
1331 return 1;
1332
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001333 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001334}
1335
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001336/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001337 Cast a copy of 'self' to a different view. The input view must
1338 be C-contiguous. The function always casts the input view to a
1339 1-D output according to 'format'. At least one of input-format,
1340 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001341
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001342 If 'shape' is given, the 1-D view from the previous step will
1343 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001344
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001345 All casts must result in views that will have the exact byte
1346 size of the original input. Otherwise, an error is raised.
1347*/
1348static PyObject *
1349memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001350{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001351 static char *kwlist[] = {"format", "shape", NULL};
1352 PyMemoryViewObject *mv = NULL;
1353 PyObject *shape = NULL;
1354 PyObject *format;
1355 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001356
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001357 CHECK_RELEASED(self);
1358
1359 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1360 &format, &shape)) {
1361 return NULL;
1362 }
1363 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001364 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001365 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001366 return NULL;
1367 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001368 if (!MV_C_CONTIGUOUS(self->flags)) {
1369 PyErr_SetString(PyExc_TypeError,
1370 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001371 return NULL;
1372 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001373 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001374 PyErr_SetString(PyExc_TypeError,
1375 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001376 return NULL;
1377 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001378 if (shape) {
1379 CHECK_LIST_OR_TUPLE(shape)
1380 ndim = PySequence_Fast_GET_SIZE(shape);
1381 if (ndim > PyBUF_MAX_NDIM) {
1382 PyErr_SetString(PyExc_ValueError,
1383 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001384 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001385 return NULL;
1386 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001387 if (self->view.ndim != 1 && ndim != 1) {
1388 PyErr_SetString(PyExc_TypeError,
1389 "memoryview: cast must be 1D -> ND or ND -> 1D");
1390 return NULL;
1391 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001392 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001393
1394 mv = (PyMemoryViewObject *)
1395 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1396 if (mv == NULL)
1397 return NULL;
1398
1399 if (cast_to_1D(mv, format) < 0)
1400 goto error;
1401 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1402 goto error;
1403
1404 return (PyObject *)mv;
1405
1406error:
1407 Py_DECREF(mv);
1408 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001409}
1410
1411
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001412/**************************************************************************/
1413/* getbuffer */
1414/**************************************************************************/
1415
1416static int
1417memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1418{
1419 Py_buffer *base = &self->view;
1420 int baseflags = self->flags;
1421
1422 CHECK_RELEASED_INT(self);
1423
1424 /* start with complete information */
1425 *view = *base;
1426 view->obj = NULL;
1427
1428 if (REQ_WRITABLE(flags) && base->readonly) {
1429 PyErr_SetString(PyExc_BufferError,
1430 "memoryview: underlying buffer is not writable");
1431 return -1;
1432 }
1433 if (!REQ_FORMAT(flags)) {
1434 /* NULL indicates that the buffer's data type has been cast to 'B'.
1435 view->itemsize is the _previous_ itemsize. If shape is present,
1436 the equality product(shape) * itemsize = len still holds at this
1437 point. The equality calcsize(format) = itemsize does _not_ hold
1438 from here on! */
1439 view->format = NULL;
1440 }
1441
1442 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1443 PyErr_SetString(PyExc_BufferError,
1444 "memoryview: underlying buffer is not C-contiguous");
1445 return -1;
1446 }
1447 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1448 PyErr_SetString(PyExc_BufferError,
1449 "memoryview: underlying buffer is not Fortran contiguous");
1450 return -1;
1451 }
1452 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1453 PyErr_SetString(PyExc_BufferError,
1454 "memoryview: underlying buffer is not contiguous");
1455 return -1;
1456 }
1457 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1458 PyErr_SetString(PyExc_BufferError,
1459 "memoryview: underlying buffer requires suboffsets");
1460 return -1;
1461 }
1462 if (!REQ_STRIDES(flags)) {
1463 if (!MV_C_CONTIGUOUS(baseflags)) {
1464 PyErr_SetString(PyExc_BufferError,
1465 "memoryview: underlying buffer is not C-contiguous");
1466 return -1;
1467 }
1468 view->strides = NULL;
1469 }
1470 if (!REQ_SHAPE(flags)) {
1471 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1472 so base->buf = ndbuf->data. */
1473 if (view->format != NULL) {
1474 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1475 not make sense. */
1476 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001477 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001478 "is present");
1479 return -1;
1480 }
1481 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1482 do _not_ hold from here on! */
1483 view->ndim = 1;
1484 view->shape = NULL;
1485 }
1486
1487
1488 view->obj = (PyObject *)self;
1489 Py_INCREF(view->obj);
1490 self->exports++;
1491
1492 return 0;
1493}
1494
1495static void
1496memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1497{
1498 self->exports--;
1499 return;
1500 /* PyBuffer_Release() decrements view->obj after this function returns. */
1501}
1502
1503/* Buffer methods */
1504static PyBufferProcs memory_as_buffer = {
1505 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1506 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1507};
1508
1509
1510/****************************************************************************/
1511/* Optimized pack/unpack for all native format specifiers */
1512/****************************************************************************/
1513
1514/*
1515 Fix exceptions:
1516 1) Include format string in the error message.
1517 2) OverflowError -> ValueError.
1518 3) The error message from PyNumber_Index() is not ideal.
1519*/
1520static int
1521type_error_int(const char *fmt)
1522{
1523 PyErr_Format(PyExc_TypeError,
1524 "memoryview: invalid type for format '%s'", fmt);
1525 return -1;
1526}
1527
1528static int
1529value_error_int(const char *fmt)
1530{
1531 PyErr_Format(PyExc_ValueError,
1532 "memoryview: invalid value for format '%s'", fmt);
1533 return -1;
1534}
1535
1536static int
1537fix_error_int(const char *fmt)
1538{
1539 assert(PyErr_Occurred());
1540 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1541 PyErr_Clear();
1542 return type_error_int(fmt);
1543 }
1544 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1545 PyErr_ExceptionMatches(PyExc_ValueError)) {
1546 PyErr_Clear();
1547 return value_error_int(fmt);
1548 }
1549
1550 return -1;
1551}
1552
1553/* Accept integer objects or objects with an __index__() method. */
1554static long
1555pylong_as_ld(PyObject *item)
1556{
1557 PyObject *tmp;
1558 long ld;
1559
1560 tmp = PyNumber_Index(item);
1561 if (tmp == NULL)
1562 return -1;
1563
1564 ld = PyLong_AsLong(tmp);
1565 Py_DECREF(tmp);
1566 return ld;
1567}
1568
1569static unsigned long
1570pylong_as_lu(PyObject *item)
1571{
1572 PyObject *tmp;
1573 unsigned long lu;
1574
1575 tmp = PyNumber_Index(item);
1576 if (tmp == NULL)
1577 return (unsigned long)-1;
1578
1579 lu = PyLong_AsUnsignedLong(tmp);
1580 Py_DECREF(tmp);
1581 return lu;
1582}
1583
1584#ifdef HAVE_LONG_LONG
1585static PY_LONG_LONG
1586pylong_as_lld(PyObject *item)
1587{
1588 PyObject *tmp;
1589 PY_LONG_LONG lld;
1590
1591 tmp = PyNumber_Index(item);
1592 if (tmp == NULL)
1593 return -1;
1594
1595 lld = PyLong_AsLongLong(tmp);
1596 Py_DECREF(tmp);
1597 return lld;
1598}
1599
1600static unsigned PY_LONG_LONG
1601pylong_as_llu(PyObject *item)
1602{
1603 PyObject *tmp;
1604 unsigned PY_LONG_LONG llu;
1605
1606 tmp = PyNumber_Index(item);
1607 if (tmp == NULL)
1608 return (unsigned PY_LONG_LONG)-1;
1609
1610 llu = PyLong_AsUnsignedLongLong(tmp);
1611 Py_DECREF(tmp);
1612 return llu;
1613}
1614#endif
1615
1616static Py_ssize_t
1617pylong_as_zd(PyObject *item)
1618{
1619 PyObject *tmp;
1620 Py_ssize_t zd;
1621
1622 tmp = PyNumber_Index(item);
1623 if (tmp == NULL)
1624 return -1;
1625
1626 zd = PyLong_AsSsize_t(tmp);
1627 Py_DECREF(tmp);
1628 return zd;
1629}
1630
1631static size_t
1632pylong_as_zu(PyObject *item)
1633{
1634 PyObject *tmp;
1635 size_t zu;
1636
1637 tmp = PyNumber_Index(item);
1638 if (tmp == NULL)
1639 return (size_t)-1;
1640
1641 zu = PyLong_AsSize_t(tmp);
1642 Py_DECREF(tmp);
1643 return zu;
1644}
1645
1646/* Timings with the ndarray from _testbuffer.c indicate that using the
1647 struct module is around 15x slower than the two functions below. */
1648
1649#define UNPACK_SINGLE(dest, ptr, type) \
1650 do { \
1651 type x; \
1652 memcpy((char *)&x, ptr, sizeof x); \
1653 dest = x; \
1654 } while (0)
1655
1656/* Unpack a single item. 'fmt' can be any native format character in struct
1657 module syntax. This function is very sensitive to small changes. With this
1658 layout gcc automatically generates a fast jump table. */
1659Py_LOCAL_INLINE(PyObject *)
1660unpack_single(const char *ptr, const char *fmt)
1661{
1662 unsigned PY_LONG_LONG llu;
1663 unsigned long lu;
1664 size_t zu;
1665 PY_LONG_LONG lld;
1666 long ld;
1667 Py_ssize_t zd;
1668 double d;
1669 unsigned char uc;
1670 void *p;
1671
1672 switch (fmt[0]) {
1673
1674 /* signed integers and fast path for 'B' */
1675 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1676 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1677 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1678 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1679 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1680
1681 /* boolean */
1682 #ifdef HAVE_C99_BOOL
1683 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
1684 #else
1685 case '?': UNPACK_SINGLE(ld, ptr, char); goto convert_bool;
1686 #endif
1687
1688 /* unsigned integers */
1689 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1690 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1691 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1692
1693 /* native 64-bit */
1694 #ifdef HAVE_LONG_LONG
1695 case 'q': UNPACK_SINGLE(lld, ptr, PY_LONG_LONG); goto convert_lld;
1696 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned PY_LONG_LONG); goto convert_llu;
1697 #endif
1698
1699 /* ssize_t and size_t */
1700 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1701 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1702
1703 /* floats */
1704 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1705 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1706
1707 /* bytes object */
1708 case 'c': goto convert_bytes;
1709
1710 /* pointer */
1711 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1712
1713 /* default */
1714 default: goto err_format;
1715 }
1716
1717convert_uc:
1718 /* PyLong_FromUnsignedLong() is slower */
1719 return PyLong_FromLong(uc);
1720convert_ld:
1721 return PyLong_FromLong(ld);
1722convert_lu:
1723 return PyLong_FromUnsignedLong(lu);
1724convert_lld:
1725 return PyLong_FromLongLong(lld);
1726convert_llu:
1727 return PyLong_FromUnsignedLongLong(llu);
1728convert_zd:
1729 return PyLong_FromSsize_t(zd);
1730convert_zu:
1731 return PyLong_FromSize_t(zu);
1732convert_double:
1733 return PyFloat_FromDouble(d);
1734convert_bool:
1735 return PyBool_FromLong(ld);
1736convert_bytes:
1737 return PyBytes_FromStringAndSize(ptr, 1);
1738convert_pointer:
1739 return PyLong_FromVoidPtr(p);
1740err_format:
1741 PyErr_Format(PyExc_NotImplementedError,
1742 "memoryview: format %s not supported", fmt);
1743 return NULL;
1744}
1745
1746#define PACK_SINGLE(ptr, src, type) \
1747 do { \
1748 type x; \
1749 x = (type)src; \
1750 memcpy(ptr, (char *)&x, sizeof x); \
1751 } while (0)
1752
1753/* Pack a single item. 'fmt' can be any native format character in
1754 struct module syntax. */
1755static int
1756pack_single(char *ptr, PyObject *item, const char *fmt)
1757{
1758 unsigned PY_LONG_LONG llu;
1759 unsigned long lu;
1760 size_t zu;
1761 PY_LONG_LONG lld;
1762 long ld;
1763 Py_ssize_t zd;
1764 double d;
1765 void *p;
1766
1767 switch (fmt[0]) {
1768 /* signed integers */
1769 case 'b': case 'h': case 'i': case 'l':
1770 ld = pylong_as_ld(item);
1771 if (ld == -1 && PyErr_Occurred())
1772 goto err_occurred;
1773 switch (fmt[0]) {
1774 case 'b':
1775 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1776 *((signed char *)ptr) = (signed char)ld; break;
1777 case 'h':
1778 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1779 PACK_SINGLE(ptr, ld, short); break;
1780 case 'i':
1781 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1782 PACK_SINGLE(ptr, ld, int); break;
1783 default: /* 'l' */
1784 PACK_SINGLE(ptr, ld, long); break;
1785 }
1786 break;
1787
1788 /* unsigned integers */
1789 case 'B': case 'H': case 'I': case 'L':
1790 lu = pylong_as_lu(item);
1791 if (lu == (unsigned long)-1 && PyErr_Occurred())
1792 goto err_occurred;
1793 switch (fmt[0]) {
1794 case 'B':
1795 if (lu > UCHAR_MAX) goto err_range;
1796 *((unsigned char *)ptr) = (unsigned char)lu; break;
1797 case 'H':
1798 if (lu > USHRT_MAX) goto err_range;
1799 PACK_SINGLE(ptr, lu, unsigned short); break;
1800 case 'I':
1801 if (lu > UINT_MAX) goto err_range;
1802 PACK_SINGLE(ptr, lu, unsigned int); break;
1803 default: /* 'L' */
1804 PACK_SINGLE(ptr, lu, unsigned long); break;
1805 }
1806 break;
1807
1808 /* native 64-bit */
1809 #ifdef HAVE_LONG_LONG
1810 case 'q':
1811 lld = pylong_as_lld(item);
1812 if (lld == -1 && PyErr_Occurred())
1813 goto err_occurred;
1814 PACK_SINGLE(ptr, lld, PY_LONG_LONG);
1815 break;
1816 case 'Q':
1817 llu = pylong_as_llu(item);
1818 if (llu == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
1819 goto err_occurred;
1820 PACK_SINGLE(ptr, llu, unsigned PY_LONG_LONG);
1821 break;
1822 #endif
1823
1824 /* ssize_t and size_t */
1825 case 'n':
1826 zd = pylong_as_zd(item);
1827 if (zd == -1 && PyErr_Occurred())
1828 goto err_occurred;
1829 PACK_SINGLE(ptr, zd, Py_ssize_t);
1830 break;
1831 case 'N':
1832 zu = pylong_as_zu(item);
1833 if (zu == (size_t)-1 && PyErr_Occurred())
1834 goto err_occurred;
1835 PACK_SINGLE(ptr, zu, size_t);
1836 break;
1837
1838 /* floats */
1839 case 'f': case 'd':
1840 d = PyFloat_AsDouble(item);
1841 if (d == -1.0 && PyErr_Occurred())
1842 goto err_occurred;
1843 if (fmt[0] == 'f') {
1844 PACK_SINGLE(ptr, d, float);
1845 }
1846 else {
1847 PACK_SINGLE(ptr, d, double);
1848 }
1849 break;
1850
1851 /* bool */
1852 case '?':
1853 ld = PyObject_IsTrue(item);
1854 if (ld < 0)
1855 return -1; /* preserve original error */
1856 #ifdef HAVE_C99_BOOL
1857 PACK_SINGLE(ptr, ld, _Bool);
1858 #else
1859 PACK_SINGLE(ptr, ld, char);
1860 #endif
1861 break;
1862
1863 /* bytes object */
1864 case 'c':
1865 if (!PyBytes_Check(item))
1866 return type_error_int(fmt);
1867 if (PyBytes_GET_SIZE(item) != 1)
1868 return value_error_int(fmt);
1869 *ptr = PyBytes_AS_STRING(item)[0];
1870 break;
1871
1872 /* pointer */
1873 case 'P':
1874 p = PyLong_AsVoidPtr(item);
1875 if (p == NULL && PyErr_Occurred())
1876 goto err_occurred;
1877 PACK_SINGLE(ptr, p, void *);
1878 break;
1879
1880 /* default */
1881 default: goto err_format;
1882 }
1883
1884 return 0;
1885
1886err_occurred:
1887 return fix_error_int(fmt);
1888err_range:
1889 return value_error_int(fmt);
1890err_format:
1891 PyErr_Format(PyExc_NotImplementedError,
1892 "memoryview: format %s not supported", fmt);
1893 return -1;
1894}
1895
1896
1897/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001898/* unpack using the struct module */
1899/****************************************************************************/
1900
1901/* For reasonable performance it is necessary to cache all objects required
1902 for unpacking. An unpacker can handle the format passed to unpack_from().
1903 Invariant: All pointer fields of the struct should either be NULL or valid
1904 pointers. */
1905struct unpacker {
1906 PyObject *unpack_from; /* Struct.unpack_from(format) */
1907 PyObject *mview; /* cached memoryview */
1908 char *item; /* buffer for mview */
1909 Py_ssize_t itemsize; /* len(item) */
1910};
1911
1912static struct unpacker *
1913unpacker_new(void)
1914{
1915 struct unpacker *x = PyMem_Malloc(sizeof *x);
1916
1917 if (x == NULL) {
1918 PyErr_NoMemory();
1919 return NULL;
1920 }
1921
1922 x->unpack_from = NULL;
1923 x->mview = NULL;
1924 x->item = NULL;
1925 x->itemsize = 0;
1926
1927 return x;
1928}
1929
1930static void
1931unpacker_free(struct unpacker *x)
1932{
1933 if (x) {
1934 Py_XDECREF(x->unpack_from);
1935 Py_XDECREF(x->mview);
1936 PyMem_Free(x->item);
1937 PyMem_Free(x);
1938 }
1939}
1940
1941/* Return a new unpacker for the given format. */
1942static struct unpacker *
1943struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1944{
1945 PyObject *structmodule; /* XXX cache these two */
1946 PyObject *Struct = NULL; /* XXX in globals? */
1947 PyObject *structobj = NULL;
1948 PyObject *format = NULL;
1949 struct unpacker *x = NULL;
1950
1951 structmodule = PyImport_ImportModule("struct");
1952 if (structmodule == NULL)
1953 return NULL;
1954
1955 Struct = PyObject_GetAttrString(structmodule, "Struct");
1956 Py_DECREF(structmodule);
1957 if (Struct == NULL)
1958 return NULL;
1959
1960 x = unpacker_new();
1961 if (x == NULL)
1962 goto error;
1963
1964 format = PyBytes_FromString(fmt);
1965 if (format == NULL)
1966 goto error;
1967
1968 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1969 if (structobj == NULL)
1970 goto error;
1971
1972 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1973 if (x->unpack_from == NULL)
1974 goto error;
1975
1976 x->item = PyMem_Malloc(itemsize);
1977 if (x->item == NULL) {
1978 PyErr_NoMemory();
1979 goto error;
1980 }
1981 x->itemsize = itemsize;
1982
1983 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1984 if (x->mview == NULL)
1985 goto error;
1986
1987
1988out:
1989 Py_XDECREF(Struct);
1990 Py_XDECREF(format);
1991 Py_XDECREF(structobj);
1992 return x;
1993
1994error:
1995 unpacker_free(x);
1996 x = NULL;
1997 goto out;
1998}
1999
2000/* unpack a single item */
2001static PyObject *
2002struct_unpack_single(const char *ptr, struct unpacker *x)
2003{
2004 PyObject *v;
2005
2006 memcpy(x->item, ptr, x->itemsize);
2007 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
2008 if (v == NULL)
2009 return NULL;
2010
2011 if (PyTuple_GET_SIZE(v) == 1) {
2012 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2013 Py_INCREF(tmp);
2014 Py_DECREF(v);
2015 return tmp;
2016 }
2017
2018 return v;
2019}
2020
2021
2022/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002023/* Representations */
2024/****************************************************************************/
2025
2026/* allow explicit form of native format */
2027Py_LOCAL_INLINE(const char *)
2028adjust_fmt(const Py_buffer *view)
2029{
2030 const char *fmt;
2031
2032 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2033 if (fmt[0] && fmt[1] == '\0')
2034 return fmt;
2035
2036 PyErr_Format(PyExc_NotImplementedError,
2037 "memoryview: unsupported format %s", view->format);
2038 return NULL;
2039}
2040
2041/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2042static PyObject *
2043tolist_base(const char *ptr, const Py_ssize_t *shape,
2044 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2045 const char *fmt)
2046{
2047 PyObject *lst, *item;
2048 Py_ssize_t i;
2049
2050 lst = PyList_New(shape[0]);
2051 if (lst == NULL)
2052 return NULL;
2053
2054 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002055 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002056 item = unpack_single(xptr, fmt);
2057 if (item == NULL) {
2058 Py_DECREF(lst);
2059 return NULL;
2060 }
2061 PyList_SET_ITEM(lst, i, item);
2062 }
2063
2064 return lst;
2065}
2066
2067/* Unpack a multi-dimensional array into a nested list.
2068 Assumption: ndim >= 1. */
2069static PyObject *
2070tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2071 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2072 const char *fmt)
2073{
2074 PyObject *lst, *item;
2075 Py_ssize_t i;
2076
2077 assert(ndim >= 1);
2078 assert(shape != NULL);
2079 assert(strides != NULL);
2080
2081 if (ndim == 1)
2082 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2083
2084 lst = PyList_New(shape[0]);
2085 if (lst == NULL)
2086 return NULL;
2087
2088 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002089 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002090 item = tolist_rec(xptr, ndim-1, shape+1,
2091 strides+1, suboffsets ? suboffsets+1 : NULL,
2092 fmt);
2093 if (item == NULL) {
2094 Py_DECREF(lst);
2095 return NULL;
2096 }
2097 PyList_SET_ITEM(lst, i, item);
2098 }
2099
2100 return lst;
2101}
2102
2103/* Return a list representation of the memoryview. Currently only buffers
2104 with native format strings are supported. */
2105static PyObject *
2106memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2107{
2108 const Py_buffer *view = &(mv->view);
2109 const char *fmt;
2110
2111 CHECK_RELEASED(mv);
2112
2113 fmt = adjust_fmt(view);
2114 if (fmt == NULL)
2115 return NULL;
2116 if (view->ndim == 0) {
2117 return unpack_single(view->buf, fmt);
2118 }
2119 else if (view->ndim == 1) {
2120 return tolist_base(view->buf, view->shape,
2121 view->strides, view->suboffsets,
2122 fmt);
2123 }
2124 else {
2125 return tolist_rec(view->buf, view->ndim, view->shape,
2126 view->strides, view->suboffsets,
2127 fmt);
2128 }
2129}
2130
2131static PyObject *
2132memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
2133{
2134 Py_buffer *src = VIEW_ADDR(self);
2135 PyObject *bytes = NULL;
2136
2137 CHECK_RELEASED(self);
2138
2139 if (MV_C_CONTIGUOUS(self->flags)) {
2140 return PyBytes_FromStringAndSize(src->buf, src->len);
2141 }
2142
2143 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2144 if (bytes == NULL)
2145 return NULL;
2146
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002147 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002148 Py_DECREF(bytes);
2149 return NULL;
2150 }
2151
2152 return bytes;
2153}
2154
2155static PyObject *
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002156memory_hex(PyMemoryViewObject *self, PyObject *dummy)
2157{
2158 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002159 PyObject *bytes;
2160 PyObject *ret;
2161
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002162 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002163
2164 if (MV_C_CONTIGUOUS(self->flags)) {
2165 return _Py_strhex(src->buf, src->len);
2166 }
2167
2168 bytes = memory_tobytes(self, dummy);
2169 if (bytes == NULL)
2170 return NULL;
2171
2172 ret = _Py_strhex(PyBytes_AS_STRING(bytes), Py_SIZE(bytes));
2173 Py_DECREF(bytes);
2174
2175 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002176}
2177
2178static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002179memory_repr(PyMemoryViewObject *self)
2180{
2181 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2182 return PyUnicode_FromFormat("<released memory at %p>", self);
2183 else
2184 return PyUnicode_FromFormat("<memory at %p>", self);
2185}
2186
2187
2188/**************************************************************************/
2189/* Indexing and slicing */
2190/**************************************************************************/
2191
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002192static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002193lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002194{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002195 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002196
2197 assert(view->shape);
2198 assert(view->strides);
2199
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002200 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002201 if (index < 0) {
2202 index += nitems;
2203 }
2204 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002205 PyErr_Format(PyExc_IndexError,
2206 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002207 return NULL;
2208 }
2209
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002210 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002211
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002212 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002213
2214 return ptr;
2215}
2216
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002217/* Get the pointer to the item at index. */
2218static char *
2219ptr_from_index(Py_buffer *view, Py_ssize_t index)
2220{
2221 char *ptr = (char *)view->buf;
2222 return lookup_dimension(view, ptr, 0, index);
2223}
2224
2225/* Get the pointer to the item at tuple. */
2226static char *
2227ptr_from_tuple(Py_buffer *view, PyObject *tup)
2228{
2229 char *ptr = (char *)view->buf;
2230 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2231
2232 if (nindices > view->ndim) {
2233 PyErr_Format(PyExc_TypeError,
2234 "cannot index %zd-dimension view with %zd-element tuple",
2235 view->ndim, nindices);
2236 return NULL;
2237 }
2238
2239 for (dim = 0; dim < nindices; dim++) {
2240 Py_ssize_t index;
2241 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2242 PyExc_IndexError);
2243 if (index == -1 && PyErr_Occurred())
2244 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002245 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002246 if (ptr == NULL)
2247 return NULL;
2248 }
2249 return ptr;
2250}
2251
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002252/* Return the item at index. In a one-dimensional view, this is an object
2253 with the type specified by view->format. Otherwise, the item is a sub-view.
2254 The function is used in memory_subscript() and memory_as_sequence. */
2255static PyObject *
2256memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2257{
2258 Py_buffer *view = &(self->view);
2259 const char *fmt;
2260
2261 CHECK_RELEASED(self);
2262
2263 fmt = adjust_fmt(view);
2264 if (fmt == NULL)
2265 return NULL;
2266
2267 if (view->ndim == 0) {
2268 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2269 return NULL;
2270 }
2271 if (view->ndim == 1) {
2272 char *ptr = ptr_from_index(view, index);
2273 if (ptr == NULL)
2274 return NULL;
2275 return unpack_single(ptr, fmt);
2276 }
2277
2278 PyErr_SetString(PyExc_NotImplementedError,
2279 "multi-dimensional sub-views are not implemented");
2280 return NULL;
2281}
2282
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002283/* Return the item at position *key* (a tuple of indices). */
2284static PyObject *
2285memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2286{
2287 Py_buffer *view = &(self->view);
2288 const char *fmt;
2289 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2290 char *ptr;
2291
2292 CHECK_RELEASED(self);
2293
2294 fmt = adjust_fmt(view);
2295 if (fmt == NULL)
2296 return NULL;
2297
2298 if (nindices < view->ndim) {
2299 PyErr_SetString(PyExc_NotImplementedError,
2300 "sub-views are not implemented");
2301 return NULL;
2302 }
2303 ptr = ptr_from_tuple(view, tup);
2304 if (ptr == NULL)
2305 return NULL;
2306 return unpack_single(ptr, fmt);
2307}
2308
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002309Py_LOCAL_INLINE(int)
2310init_slice(Py_buffer *base, PyObject *key, int dim)
2311{
2312 Py_ssize_t start, stop, step, slicelength;
2313
2314 if (PySlice_GetIndicesEx(key, base->shape[dim],
2315 &start, &stop, &step, &slicelength) < 0) {
2316 return -1;
2317 }
2318
2319
2320 if (base->suboffsets == NULL || dim == 0) {
2321 adjust_buf:
2322 base->buf = (char *)base->buf + base->strides[dim] * start;
2323 }
2324 else {
2325 Py_ssize_t n = dim-1;
2326 while (n >= 0 && base->suboffsets[n] < 0)
2327 n--;
2328 if (n < 0)
2329 goto adjust_buf; /* all suboffsets are negative */
2330 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2331 }
2332 base->shape[dim] = slicelength;
2333 base->strides[dim] = base->strides[dim] * step;
2334
2335 return 0;
2336}
2337
2338static int
2339is_multislice(PyObject *key)
2340{
2341 Py_ssize_t size, i;
2342
2343 if (!PyTuple_Check(key))
2344 return 0;
2345 size = PyTuple_GET_SIZE(key);
2346 if (size == 0)
2347 return 0;
2348
2349 for (i = 0; i < size; i++) {
2350 PyObject *x = PyTuple_GET_ITEM(key, i);
2351 if (!PySlice_Check(x))
2352 return 0;
2353 }
2354 return 1;
2355}
2356
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002357static Py_ssize_t
2358is_multiindex(PyObject *key)
2359{
2360 Py_ssize_t size, i;
2361
2362 if (!PyTuple_Check(key))
2363 return 0;
2364 size = PyTuple_GET_SIZE(key);
2365 for (i = 0; i < size; i++) {
2366 PyObject *x = PyTuple_GET_ITEM(key, i);
2367 if (!PyIndex_Check(x))
2368 return 0;
2369 }
2370 return 1;
2371}
2372
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002373/* mv[obj] returns an object holding the data for one element if obj
2374 fully indexes the memoryview or another memoryview object if it
2375 does not.
2376
2377 0-d memoryview objects can be referenced using mv[...] or mv[()]
2378 but not with anything else. */
2379static PyObject *
2380memory_subscript(PyMemoryViewObject *self, PyObject *key)
2381{
2382 Py_buffer *view;
2383 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002384
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002385 CHECK_RELEASED(self);
2386
2387 if (view->ndim == 0) {
2388 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2389 const char *fmt = adjust_fmt(view);
2390 if (fmt == NULL)
2391 return NULL;
2392 return unpack_single(view->buf, fmt);
2393 }
2394 else if (key == Py_Ellipsis) {
2395 Py_INCREF(self);
2396 return (PyObject *)self;
2397 }
2398 else {
2399 PyErr_SetString(PyExc_TypeError,
2400 "invalid indexing of 0-dim memory");
2401 return NULL;
2402 }
2403 }
2404
2405 if (PyIndex_Check(key)) {
2406 Py_ssize_t index;
2407 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2408 if (index == -1 && PyErr_Occurred())
2409 return NULL;
2410 return memory_item(self, index);
2411 }
2412 else if (PySlice_Check(key)) {
2413 PyMemoryViewObject *sliced;
2414
2415 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2416 if (sliced == NULL)
2417 return NULL;
2418
2419 if (init_slice(&sliced->view, key, 0) < 0) {
2420 Py_DECREF(sliced);
2421 return NULL;
2422 }
2423 init_len(&sliced->view);
2424 init_flags(sliced);
2425
2426 return (PyObject *)sliced;
2427 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002428 else if (is_multiindex(key)) {
2429 return memory_item_multi(self, key);
2430 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002431 else if (is_multislice(key)) {
2432 PyErr_SetString(PyExc_NotImplementedError,
2433 "multi-dimensional slicing is not implemented");
2434 return NULL;
2435 }
2436
2437 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2438 return NULL;
2439}
2440
2441static int
2442memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2443{
2444 Py_buffer *view = &(self->view);
2445 Py_buffer src;
2446 const char *fmt;
2447 char *ptr;
2448
2449 CHECK_RELEASED_INT(self);
2450
2451 fmt = adjust_fmt(view);
2452 if (fmt == NULL)
2453 return -1;
2454
2455 if (view->readonly) {
2456 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2457 return -1;
2458 }
2459 if (value == NULL) {
2460 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2461 return -1;
2462 }
2463 if (view->ndim == 0) {
2464 if (key == Py_Ellipsis ||
2465 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2466 ptr = (char *)view->buf;
2467 return pack_single(ptr, value, fmt);
2468 }
2469 else {
2470 PyErr_SetString(PyExc_TypeError,
2471 "invalid indexing of 0-dim memory");
2472 return -1;
2473 }
2474 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002475
2476 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002477 Py_ssize_t index;
2478 if (1 < view->ndim) {
2479 PyErr_SetString(PyExc_NotImplementedError,
2480 "sub-views are not implemented");
2481 return -1;
2482 }
2483 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002484 if (index == -1 && PyErr_Occurred())
2485 return -1;
2486 ptr = ptr_from_index(view, index);
2487 if (ptr == NULL)
2488 return -1;
2489 return pack_single(ptr, value, fmt);
2490 }
2491 /* one-dimensional: fast path */
2492 if (PySlice_Check(key) && view->ndim == 1) {
2493 Py_buffer dest; /* sliced view */
2494 Py_ssize_t arrays[3];
2495 int ret = -1;
2496
2497 /* rvalue must be an exporter */
2498 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2499 return ret;
2500
2501 dest = *view;
2502 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2503 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2504 if (view->suboffsets) {
2505 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2506 }
2507
2508 if (init_slice(&dest, key, 0) < 0)
2509 goto end_block;
2510 dest.len = dest.shape[0] * dest.itemsize;
2511
2512 ret = copy_single(&dest, &src);
2513
2514 end_block:
2515 PyBuffer_Release(&src);
2516 return ret;
2517 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002518 if (is_multiindex(key)) {
2519 char *ptr;
2520 if (PyTuple_GET_SIZE(key) < view->ndim) {
2521 PyErr_SetString(PyExc_NotImplementedError,
2522 "sub-views are not implemented");
2523 return -1;
2524 }
2525 ptr = ptr_from_tuple(view, key);
2526 if (ptr == NULL)
2527 return -1;
2528 return pack_single(ptr, value, fmt);
2529 }
2530 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002531 /* Call memory_subscript() to produce a sliced lvalue, then copy
2532 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2533 PyErr_SetString(PyExc_NotImplementedError,
2534 "memoryview slice assignments are currently restricted "
2535 "to ndim = 1");
2536 return -1;
2537 }
2538
2539 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2540 return -1;
2541}
2542
2543static Py_ssize_t
2544memory_length(PyMemoryViewObject *self)
2545{
2546 CHECK_RELEASED_INT(self);
2547 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2548}
2549
2550/* As mapping */
2551static PyMappingMethods memory_as_mapping = {
2552 (lenfunc)memory_length, /* mp_length */
2553 (binaryfunc)memory_subscript, /* mp_subscript */
2554 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2555};
2556
2557/* As sequence */
2558static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002559 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002560 0, /* sq_concat */
2561 0, /* sq_repeat */
2562 (ssizeargfunc)memory_item, /* sq_item */
2563};
2564
2565
2566/**************************************************************************/
2567/* Comparisons */
2568/**************************************************************************/
2569
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002570#define MV_COMPARE_EX -1 /* exception */
2571#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2572
2573/* Translate a StructError to "not equal". Preserve other exceptions. */
2574static int
2575fix_struct_error_int(void)
2576{
2577 assert(PyErr_Occurred());
2578 /* XXX Cannot get at StructError directly? */
2579 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2580 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2581 return MV_COMPARE_EX;
2582 }
2583 /* StructError: invalid or unknown format -> not equal */
2584 PyErr_Clear();
2585 return 0;
2586}
2587
2588/* Unpack and compare single items of p and q using the struct module. */
2589static int
2590struct_unpack_cmp(const char *p, const char *q,
2591 struct unpacker *unpack_p, struct unpacker *unpack_q)
2592{
2593 PyObject *v, *w;
2594 int ret;
2595
2596 /* At this point any exception from the struct module should not be
2597 StructError, since both formats have been accepted already. */
2598 v = struct_unpack_single(p, unpack_p);
2599 if (v == NULL)
2600 return MV_COMPARE_EX;
2601
2602 w = struct_unpack_single(q, unpack_q);
2603 if (w == NULL) {
2604 Py_DECREF(v);
2605 return MV_COMPARE_EX;
2606 }
2607
2608 /* MV_COMPARE_EX == -1: exceptions are preserved */
2609 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2610 Py_DECREF(v);
2611 Py_DECREF(w);
2612
2613 return ret;
2614}
2615
2616/* Unpack and compare single items of p and q. If both p and q have the same
2617 single element native format, the comparison uses a fast path (gcc creates
2618 a jump table and converts memcpy into simple assignments on x86/x64).
2619
2620 Otherwise, the comparison is delegated to the struct module, which is
2621 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002622#define CMP_SINGLE(p, q, type) \
2623 do { \
2624 type x; \
2625 type y; \
2626 memcpy((char *)&x, p, sizeof x); \
2627 memcpy((char *)&y, q, sizeof y); \
2628 equal = (x == y); \
2629 } while (0)
2630
2631Py_LOCAL_INLINE(int)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002632unpack_cmp(const char *p, const char *q, char fmt,
2633 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002634{
2635 int equal;
2636
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002637 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002638
2639 /* signed integers and fast path for 'B' */
2640 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2641 case 'b': return *((signed char *)p) == *((signed char *)q);
2642 case 'h': CMP_SINGLE(p, q, short); return equal;
2643 case 'i': CMP_SINGLE(p, q, int); return equal;
2644 case 'l': CMP_SINGLE(p, q, long); return equal;
2645
2646 /* boolean */
2647 #ifdef HAVE_C99_BOOL
2648 case '?': CMP_SINGLE(p, q, _Bool); return equal;
2649 #else
2650 case '?': CMP_SINGLE(p, q, char); return equal;
2651 #endif
2652
2653 /* unsigned integers */
2654 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2655 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2656 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2657
2658 /* native 64-bit */
2659 #ifdef HAVE_LONG_LONG
2660 case 'q': CMP_SINGLE(p, q, PY_LONG_LONG); return equal;
2661 case 'Q': CMP_SINGLE(p, q, unsigned PY_LONG_LONG); return equal;
2662 #endif
2663
2664 /* ssize_t and size_t */
2665 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2666 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2667
2668 /* floats */
2669 /* XXX DBL_EPSILON? */
2670 case 'f': CMP_SINGLE(p, q, float); return equal;
2671 case 'd': CMP_SINGLE(p, q, double); return equal;
2672
2673 /* bytes object */
2674 case 'c': return *p == *q;
2675
2676 /* pointer */
2677 case 'P': CMP_SINGLE(p, q, void *); return equal;
2678
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002679 /* use the struct module */
2680 case '_':
2681 assert(unpack_p);
2682 assert(unpack_q);
2683 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002684 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002685
2686 /* NOT REACHED */
2687 PyErr_SetString(PyExc_RuntimeError,
2688 "memoryview: internal error in richcompare");
2689 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002690}
2691
2692/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2693static int
2694cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2695 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2696 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002697 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002698{
2699 Py_ssize_t i;
2700 int equal;
2701
2702 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002703 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2704 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002705 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002706 if (equal <= 0)
2707 return equal;
2708 }
2709
2710 return 1;
2711}
2712
2713/* Recursively compare two multi-dimensional arrays that have the same
2714 logical structure. Assumption: ndim >= 1. */
2715static int
2716cmp_rec(const char *p, const char *q,
2717 Py_ssize_t ndim, const Py_ssize_t *shape,
2718 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2719 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002720 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002721{
2722 Py_ssize_t i;
2723 int equal;
2724
2725 assert(ndim >= 1);
2726 assert(shape != NULL);
2727 assert(pstrides != NULL);
2728 assert(qstrides != NULL);
2729
2730 if (ndim == 1) {
2731 return cmp_base(p, q, shape,
2732 pstrides, psuboffsets,
2733 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002734 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002735 }
2736
2737 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002738 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2739 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002740 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2741 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2742 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002743 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002744 if (equal <= 0)
2745 return equal;
2746 }
2747
2748 return 1;
2749}
2750
2751static PyObject *
2752memory_richcompare(PyObject *v, PyObject *w, int op)
2753{
2754 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002755 Py_buffer wbuf, *vv;
2756 Py_buffer *ww = NULL;
2757 struct unpacker *unpack_v = NULL;
2758 struct unpacker *unpack_w = NULL;
2759 char vfmt, wfmt;
2760 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002761
2762 if (op != Py_EQ && op != Py_NE)
2763 goto result; /* Py_NotImplemented */
2764
2765 assert(PyMemoryView_Check(v));
2766 if (BASE_INACCESSIBLE(v)) {
2767 equal = (v == w);
2768 goto result;
2769 }
2770 vv = VIEW_ADDR(v);
2771
2772 if (PyMemoryView_Check(w)) {
2773 if (BASE_INACCESSIBLE(w)) {
2774 equal = (v == w);
2775 goto result;
2776 }
2777 ww = VIEW_ADDR(w);
2778 }
2779 else {
2780 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2781 PyErr_Clear();
2782 goto result; /* Py_NotImplemented */
2783 }
2784 ww = &wbuf;
2785 }
2786
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002787 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002788 PyErr_Clear();
2789 equal = 0;
2790 goto result;
2791 }
2792
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002793 /* Use fast unpacking for identical primitive C type formats. */
2794 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2795 vfmt = '_';
2796 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2797 wfmt = '_';
2798 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2799 /* Use struct module unpacking. NOTE: Even for equal format strings,
2800 memcmp() cannot be used for item comparison since it would give
2801 incorrect results in the case of NaNs or uninitialized padding
2802 bytes. */
2803 vfmt = '_';
2804 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2805 if (unpack_v == NULL) {
2806 equal = fix_struct_error_int();
2807 goto result;
2808 }
2809 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2810 if (unpack_w == NULL) {
2811 equal = fix_struct_error_int();
2812 goto result;
2813 }
2814 }
2815
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002816 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002817 equal = unpack_cmp(vv->buf, ww->buf,
2818 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002819 }
2820 else if (vv->ndim == 1) {
2821 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2822 vv->strides, vv->suboffsets,
2823 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002824 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002825 }
2826 else {
2827 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2828 vv->strides, vv->suboffsets,
2829 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002830 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002831 }
2832
2833result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002834 if (equal < 0) {
2835 if (equal == MV_COMPARE_NOT_IMPL)
2836 res = Py_NotImplemented;
2837 else /* exception */
2838 res = NULL;
2839 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002840 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2841 res = Py_True;
2842 else
2843 res = Py_False;
2844
2845 if (ww == &wbuf)
2846 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002847
2848 unpacker_free(unpack_v);
2849 unpacker_free(unpack_w);
2850
2851 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002852 return res;
2853}
2854
2855/**************************************************************************/
2856/* Hash */
2857/**************************************************************************/
2858
2859static Py_hash_t
2860memory_hash(PyMemoryViewObject *self)
2861{
2862 if (self->hash == -1) {
2863 Py_buffer *view = &self->view;
2864 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002865 Py_ssize_t ret;
2866 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002867
2868 CHECK_RELEASED_INT(self);
2869
2870 if (!view->readonly) {
2871 PyErr_SetString(PyExc_ValueError,
2872 "cannot hash writable memoryview object");
2873 return -1;
2874 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002875 ret = get_native_fmtchar(&fmt, view->format);
2876 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2877 PyErr_SetString(PyExc_ValueError,
2878 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2879 return -1;
2880 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002881 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2882 /* Keep the original error message */
2883 return -1;
2884 }
2885
2886 if (!MV_C_CONTIGUOUS(self->flags)) {
2887 mem = PyMem_Malloc(view->len);
2888 if (mem == NULL) {
2889 PyErr_NoMemory();
2890 return -1;
2891 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002892 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002893 PyMem_Free(mem);
2894 return -1;
2895 }
2896 }
2897
2898 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002899 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002900
2901 if (mem != view->buf)
2902 PyMem_Free(mem);
2903 }
2904
2905 return self->hash;
2906}
2907
2908
2909/**************************************************************************/
2910/* getters */
2911/**************************************************************************/
2912
2913static PyObject *
2914_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2915{
2916 int i;
2917 PyObject *o;
2918 PyObject *intTuple;
2919
2920 if (vals == NULL)
2921 return PyTuple_New(0);
2922
2923 intTuple = PyTuple_New(len);
2924 if (!intTuple)
2925 return NULL;
2926 for (i=0; i<len; i++) {
2927 o = PyLong_FromSsize_t(vals[i]);
2928 if (!o) {
2929 Py_DECREF(intTuple);
2930 return NULL;
2931 }
2932 PyTuple_SET_ITEM(intTuple, i, o);
2933 }
2934 return intTuple;
2935}
2936
2937static PyObject *
2938memory_obj_get(PyMemoryViewObject *self)
2939{
2940 Py_buffer *view = &self->view;
2941
2942 CHECK_RELEASED(self);
2943 if (view->obj == NULL) {
2944 Py_RETURN_NONE;
2945 }
2946 Py_INCREF(view->obj);
2947 return view->obj;
2948}
2949
2950static PyObject *
2951memory_nbytes_get(PyMemoryViewObject *self)
2952{
2953 CHECK_RELEASED(self);
2954 return PyLong_FromSsize_t(self->view.len);
2955}
2956
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002957static PyObject *
2958memory_format_get(PyMemoryViewObject *self)
2959{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002960 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002961 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002962}
2963
2964static PyObject *
2965memory_itemsize_get(PyMemoryViewObject *self)
2966{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002967 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002968 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002969}
2970
2971static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002972memory_shape_get(PyMemoryViewObject *self)
2973{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002974 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002975 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002976}
2977
2978static PyObject *
2979memory_strides_get(PyMemoryViewObject *self)
2980{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002981 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002982 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002983}
2984
2985static PyObject *
2986memory_suboffsets_get(PyMemoryViewObject *self)
2987{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002988 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002989 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002990}
2991
2992static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002993memory_readonly_get(PyMemoryViewObject *self)
2994{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002995 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002996 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002997}
2998
2999static PyObject *
3000memory_ndim_get(PyMemoryViewObject *self)
3001{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003002 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003003 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003004}
3005
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003006static PyObject *
3007memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3008{
3009 CHECK_RELEASED(self);
3010 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3011}
3012
3013static PyObject *
3014memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3015{
3016 CHECK_RELEASED(self);
3017 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3018}
3019
3020static PyObject *
3021memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3022{
3023 CHECK_RELEASED(self);
3024 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3025}
3026
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003027PyDoc_STRVAR(memory_obj_doc,
3028 "The underlying object of the memoryview.");
3029PyDoc_STRVAR(memory_nbytes_doc,
3030 "The amount of space in bytes that the array would use in\n"
3031 " a contiguous representation.");
3032PyDoc_STRVAR(memory_readonly_doc,
3033 "A bool indicating whether the memory is read only.");
3034PyDoc_STRVAR(memory_itemsize_doc,
3035 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003036PyDoc_STRVAR(memory_format_doc,
3037 "A string containing the format (in struct module style)\n"
3038 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003039PyDoc_STRVAR(memory_ndim_doc,
3040 "An integer indicating how many dimensions of a multi-dimensional\n"
3041 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003042PyDoc_STRVAR(memory_shape_doc,
3043 "A tuple of ndim integers giving the shape of the memory\n"
3044 " as an N-dimensional array.");
3045PyDoc_STRVAR(memory_strides_doc,
3046 "A tuple of ndim integers giving the size in bytes to access\n"
3047 " each element for each dimension of the array.");
3048PyDoc_STRVAR(memory_suboffsets_doc,
3049 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003050PyDoc_STRVAR(memory_c_contiguous_doc,
3051 "A bool indicating whether the memory is C contiguous.");
3052PyDoc_STRVAR(memory_f_contiguous_doc,
3053 "A bool indicating whether the memory is Fortran contiguous.");
3054PyDoc_STRVAR(memory_contiguous_doc,
3055 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003056
Stefan Krahbcaf5992014-05-18 00:35:09 +02003057
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003058static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003059 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3060 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003061 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3062 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3063 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3064 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3065 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3066 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3067 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003068 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3069 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3070 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003071 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003072};
3073
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003074PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003075"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003076\n\
3077Release the underlying buffer exposed by the memoryview object.");
3078PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003079"tobytes($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003080\n\
3081Return the data in the buffer as a byte string.");
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003082PyDoc_STRVAR(memory_hex_doc,
3083"hex($self, /)\n--\n\
3084\n\
3085Return the data in the buffer as a string of hexadecimal numbers.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003086PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003087"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003088\n\
3089Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003090PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003091"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003092\n\
3093Cast a memoryview to a new format or shape.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003094
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003095static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003096 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3097 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003098 {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003099 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003100 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003101 {"__enter__", memory_enter, METH_NOARGS, NULL},
3102 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003103 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003104};
3105
3106
3107PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003108 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003109 "memoryview", /* tp_name */
3110 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3111 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003112 (destructor)memory_dealloc, /* tp_dealloc */
3113 0, /* tp_print */
3114 0, /* tp_getattr */
3115 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003116 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003117 (reprfunc)memory_repr, /* tp_repr */
3118 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003119 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003120 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003121 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003122 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003123 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003124 PyObject_GenericGetAttr, /* tp_getattro */
3125 0, /* tp_setattro */
3126 &memory_as_buffer, /* tp_as_buffer */
3127 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3128 memory_doc, /* tp_doc */
3129 (traverseproc)memory_traverse, /* tp_traverse */
3130 (inquiry)memory_clear, /* tp_clear */
3131 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003132 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003133 0, /* tp_iter */
3134 0, /* tp_iternext */
3135 memory_methods, /* tp_methods */
3136 0, /* tp_members */
3137 memory_getsetlist, /* tp_getset */
3138 0, /* tp_base */
3139 0, /* tp_dict */
3140 0, /* tp_descr_get */
3141 0, /* tp_descr_set */
3142 0, /* tp_dictoffset */
3143 0, /* tp_init */
3144 0, /* tp_alloc */
3145 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003146};