blob: ccf45ffc5826081e3c3a273041f41493d13750c7 [file] [log] [blame]
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001/* Memoryview object implementation */
2
3#include "Python.h"
Eric Snow2ebc5ce2017-09-07 23:51:28 -06004#include "internal/mem.h"
5#include "internal/pystate.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +00006#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +01007#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00008
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00009
Stefan Krah9a2d99e2012-02-25 12:24:21 +010010/****************************************************************************/
11/* ManagedBuffer Object */
12/****************************************************************************/
13
14/*
15 ManagedBuffer Object:
16 ---------------------
17
18 The purpose of this object is to facilitate the handling of chained
19 memoryviews that have the same underlying exporting object. PEP-3118
20 allows the underlying object to change while a view is exported. This
21 could lead to unexpected results when constructing a new memoryview
22 from an existing memoryview.
23
24 Rather than repeatedly redirecting buffer requests to the original base
25 object, all chained memoryviews use a single buffer snapshot. This
26 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
27
28 Ownership rules:
29 ----------------
30
31 The master buffer inside a managed buffer is filled in by the original
32 base object. shape, strides, suboffsets and format are read-only for
33 all consumers.
34
35 A memoryview's buffer is a private copy of the exporter's buffer. shape,
36 strides and suboffsets belong to the memoryview and are thus writable.
37
38 If a memoryview itself exports several buffers via memory_getbuf(), all
39 buffer copies share shape, strides and suboffsets. In this case, the
40 arrays are NOT writable.
41
42 Reference count assumptions:
43 ----------------------------
44
45 The 'obj' member of a Py_buffer must either be NULL or refer to the
46 exporting base object. In the Python codebase, all getbufferprocs
47 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
48
49 PyBuffer_Release() decrements view.obj (if non-NULL), so the
50 releasebufferprocs must NOT decrement view.obj.
51*/
52
53
Stefan Krah9a2d99e2012-02-25 12:24:21 +010054#define CHECK_MBUF_RELEASED(mbuf) \
55 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
56 PyErr_SetString(PyExc_ValueError, \
57 "operation forbidden on released memoryview object"); \
58 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000059 }
60
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000061
Benjamin Peterson82cce4c2016-09-08 11:56:06 -070062static inline _PyManagedBufferObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +010063mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000064{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010065 _PyManagedBufferObject *mbuf;
66
67 mbuf = (_PyManagedBufferObject *)
68 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
69 if (mbuf == NULL)
70 return NULL;
71 mbuf->flags = 0;
72 mbuf->exports = 0;
73 mbuf->master.obj = NULL;
74 _PyObject_GC_TRACK(mbuf);
75
76 return mbuf;
77}
78
79static PyObject *
80_PyManagedBuffer_FromObject(PyObject *base)
81{
82 _PyManagedBufferObject *mbuf;
83
84 mbuf = mbuf_alloc();
85 if (mbuf == NULL)
86 return NULL;
87
88 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +010089 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +010090 Py_DECREF(mbuf);
91 return NULL;
92 }
93
Stefan Krah9a2d99e2012-02-25 12:24:21 +010094 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +000095}
96
97static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +010098mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +000099{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100100 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
101 return;
102
103 /* NOTE: at this point self->exports can still be > 0 if this function
104 is called from mbuf_clear() to break up a reference cycle. */
105 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
106
107 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
108 _PyObject_GC_UNTRACK(self);
109 PyBuffer_Release(&self->master);
110}
111
112static void
113mbuf_dealloc(_PyManagedBufferObject *self)
114{
115 assert(self->exports == 0);
116 mbuf_release(self);
117 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
118 PyMem_Free(self->master.format);
119 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000120}
121
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000122static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100123mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000124{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100125 Py_VISIT(self->master.obj);
126 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000127}
128
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100129static int
130mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000131{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100132 assert(self->exports >= 0);
133 mbuf_release(self);
134 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000135}
136
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100137PyTypeObject _PyManagedBuffer_Type = {
138 PyVarObject_HEAD_INIT(&PyType_Type, 0)
139 "managedbuffer",
140 sizeof(_PyManagedBufferObject),
141 0,
142 (destructor)mbuf_dealloc, /* tp_dealloc */
143 0, /* tp_print */
144 0, /* tp_getattr */
145 0, /* tp_setattr */
146 0, /* tp_reserved */
147 0, /* tp_repr */
148 0, /* tp_as_number */
149 0, /* tp_as_sequence */
150 0, /* tp_as_mapping */
151 0, /* tp_hash */
152 0, /* tp_call */
153 0, /* tp_str */
154 PyObject_GenericGetAttr, /* tp_getattro */
155 0, /* tp_setattro */
156 0, /* tp_as_buffer */
157 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
158 0, /* tp_doc */
159 (traverseproc)mbuf_traverse, /* tp_traverse */
160 (inquiry)mbuf_clear /* tp_clear */
161};
162
163
164/****************************************************************************/
165/* MemoryView Object */
166/****************************************************************************/
167
168/* In the process of breaking reference cycles mbuf_release() can be
169 called before memory_release(). */
170#define BASE_INACCESSIBLE(mv) \
171 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
172 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
173
174#define CHECK_RELEASED(mv) \
175 if (BASE_INACCESSIBLE(mv)) { \
176 PyErr_SetString(PyExc_ValueError, \
177 "operation forbidden on released memoryview object"); \
178 return NULL; \
179 }
180
181#define CHECK_RELEASED_INT(mv) \
182 if (BASE_INACCESSIBLE(mv)) { \
183 PyErr_SetString(PyExc_ValueError, \
184 "operation forbidden on released memoryview object"); \
185 return -1; \
186 }
187
188#define CHECK_LIST_OR_TUPLE(v) \
189 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
190 PyErr_SetString(PyExc_TypeError, \
191 #v " must be a list or a tuple"); \
192 return NULL; \
193 }
194
195#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
196
197/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100198#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100199/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100200#define ADJUST_PTR(ptr, suboffsets, dim) \
201 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100202
203/* Memoryview buffer properties */
204#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
205#define MV_F_CONTIGUOUS(flags) \
206 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
207#define MV_ANY_CONTIGUOUS(flags) \
208 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
209
210/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
211#define MV_CONTIGUOUS_NDIM1(view) \
212 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
213
214/* getbuffer() requests */
215#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
216#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
217#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
218#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
219#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
220#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
221#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
222#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
223
224
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000225PyDoc_STRVAR(memory_doc,
Stefan Krah195319e2016-12-30 12:23:35 +0100226"memoryview(object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000227\n\
228Create a new memoryview object which references the given object.");
229
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100230
231/**************************************************************************/
232/* Copy memoryview buffers */
233/**************************************************************************/
234
235/* The functions in this section take a source and a destination buffer
236 with the same logical structure: format, itemsize, ndim and shape
237 are identical, with ndim > 0.
238
239 NOTE: All buffers are assumed to have PyBUF_FULL information, which
240 is the case for memoryviews! */
241
242
243/* Assumptions: ndim >= 1. The macro tests for a corner case that should
244 perhaps be explicitly forbidden in the PEP. */
245#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
246 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
247
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700248static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000249last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100250{
251 assert(dest->ndim > 0 && src->ndim > 0);
252 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
253 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
254 dest->strides[dest->ndim-1] == dest->itemsize &&
255 src->strides[src->ndim-1] == src->itemsize);
256}
257
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000258/* This is not a general function for determining format equivalence.
259 It is used in copy_single() and copy_buffer() to weed out non-matching
260 formats. Skipping the '@' character is specifically used in slice
261 assignments, where the lvalue is already known to have a single character
262 format. This is a performance hack that could be rewritten (if properly
263 benchmarked). */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700264static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000265equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100266{
267 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100268
269 assert(dest->format && src->format);
270 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
271 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
272
273 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000274 dest->itemsize != src->itemsize) {
275 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100276 }
277
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000278 return 1;
279}
280
281/* Two shapes are equivalent if they are either equal or identical up
282 to a zero element at the same position. For example, in NumPy arrays
283 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700284static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000285equiv_shape(const Py_buffer *dest, const Py_buffer *src)
286{
287 int i;
288
289 if (dest->ndim != src->ndim)
290 return 0;
291
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100292 for (i = 0; i < dest->ndim; i++) {
293 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000294 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100295 if (dest->shape[i] == 0)
296 break;
297 }
298
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000299 return 1;
300}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100301
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000302/* Check that the logical structure of the destination and source buffers
303 is identical. */
304static int
305equiv_structure(const Py_buffer *dest, const Py_buffer *src)
306{
307 if (!equiv_format(dest, src) ||
308 !equiv_shape(dest, src)) {
309 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100310 "memoryview assignment: lvalue and rvalue have different "
311 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000312 return 0;
313 }
314
315 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100316}
317
318/* Base case for recursive multi-dimensional copying. Contiguous arrays are
319 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
320 sizeof(mem) == shape[0] * itemsize. */
321static void
322copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
323 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
324 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
325 char *mem)
326{
327 if (mem == NULL) { /* contiguous */
328 Py_ssize_t size = shape[0] * itemsize;
329 if (dptr + size < sptr || sptr + size < dptr)
330 memcpy(dptr, sptr, size); /* no overlapping */
331 else
332 memmove(dptr, sptr, size);
333 }
334 else {
335 char *p;
336 Py_ssize_t i;
337 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100338 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100339 memcpy(p, xsptr, itemsize);
340 }
341 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100342 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100343 memcpy(xdptr, p, itemsize);
344 }
345 }
346
347}
348
349/* Recursively copy a source buffer to a destination buffer. The two buffers
350 have the same ndim, shape and itemsize. */
351static void
352copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
353 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
354 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
355 char *mem)
356{
357 Py_ssize_t i;
358
359 assert(ndim >= 1);
360
361 if (ndim == 1) {
362 copy_base(shape, itemsize,
363 dptr, dstrides, dsuboffsets,
364 sptr, sstrides, ssuboffsets,
365 mem);
366 return;
367 }
368
369 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100370 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
371 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100372
373 copy_rec(shape+1, ndim-1, itemsize,
374 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
375 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
376 mem);
377 }
378}
379
380/* Faster copying of one-dimensional arrays. */
381static int
382copy_single(Py_buffer *dest, Py_buffer *src)
383{
384 char *mem = NULL;
385
386 assert(dest->ndim == 1);
387
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000388 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100389 return -1;
390
391 if (!last_dim_is_contiguous(dest, src)) {
392 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
393 if (mem == NULL) {
394 PyErr_NoMemory();
395 return -1;
396 }
397 }
398
399 copy_base(dest->shape, dest->itemsize,
400 dest->buf, dest->strides, dest->suboffsets,
401 src->buf, src->strides, src->suboffsets,
402 mem);
403
404 if (mem)
405 PyMem_Free(mem);
406
407 return 0;
408}
409
410/* Recursively copy src to dest. Both buffers must have the same basic
411 structure. Copying is atomic, the function never fails with a partial
412 copy. */
413static int
414copy_buffer(Py_buffer *dest, Py_buffer *src)
415{
416 char *mem = NULL;
417
418 assert(dest->ndim > 0);
419
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000420 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100421 return -1;
422
423 if (!last_dim_is_contiguous(dest, src)) {
424 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
425 if (mem == NULL) {
426 PyErr_NoMemory();
427 return -1;
428 }
429 }
430
431 copy_rec(dest->shape, dest->ndim, dest->itemsize,
432 dest->buf, dest->strides, dest->suboffsets,
433 src->buf, src->strides, src->suboffsets,
434 mem);
435
436 if (mem)
437 PyMem_Free(mem);
438
439 return 0;
440}
441
442/* Initialize strides for a C-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700443static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100444init_strides_from_shape(Py_buffer *view)
445{
446 Py_ssize_t i;
447
448 assert(view->ndim > 0);
449
450 view->strides[view->ndim-1] = view->itemsize;
451 for (i = view->ndim-2; i >= 0; i--)
452 view->strides[i] = view->strides[i+1] * view->shape[i+1];
453}
454
455/* Initialize strides for a Fortran-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700456static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100457init_fortran_strides_from_shape(Py_buffer *view)
458{
459 Py_ssize_t i;
460
461 assert(view->ndim > 0);
462
463 view->strides[0] = view->itemsize;
464 for (i = 1; i < view->ndim; i++)
465 view->strides[i] = view->strides[i-1] * view->shape[i-1];
466}
467
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200468/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
469 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100470 len(mem) == src->len. */
471static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200472buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100473{
474 Py_buffer dest;
475 Py_ssize_t *strides;
476 int ret;
477
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200478 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100479 assert(src->shape != NULL);
480 assert(src->strides != NULL);
481
482 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
483 if (strides == NULL) {
484 PyErr_NoMemory();
485 return -1;
486 }
487
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200488 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100489 dest = *src;
490 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200491 /* shape is constant and shared: the logical representation of the
492 array is unaltered. */
493
494 /* The physical representation determined by strides (and possibly
495 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100496 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200497 if (order == 'C' || order == 'A') {
498 init_strides_from_shape(&dest);
499 }
500 else {
501 init_fortran_strides_from_shape(&dest);
502 }
503
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100504 dest.suboffsets = NULL;
505
506 ret = copy_buffer(&dest, src);
507
508 PyMem_Free(strides);
509 return ret;
510}
511
512
513/****************************************************************************/
514/* Constructors */
515/****************************************************************************/
516
517/* Initialize values that are shared with the managed buffer. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700518static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100519init_shared_values(Py_buffer *dest, const Py_buffer *src)
520{
521 dest->obj = src->obj;
522 dest->buf = src->buf;
523 dest->len = src->len;
524 dest->itemsize = src->itemsize;
525 dest->readonly = src->readonly;
526 dest->format = src->format ? src->format : "B";
527 dest->internal = src->internal;
528}
529
530/* Copy shape and strides. Reconstruct missing values. */
531static void
532init_shape_strides(Py_buffer *dest, const Py_buffer *src)
533{
534 Py_ssize_t i;
535
536 if (src->ndim == 0) {
537 dest->shape = NULL;
538 dest->strides = NULL;
539 return;
540 }
541 if (src->ndim == 1) {
542 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
543 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
544 return;
545 }
546
547 for (i = 0; i < src->ndim; i++)
548 dest->shape[i] = src->shape[i];
549 if (src->strides) {
550 for (i = 0; i < src->ndim; i++)
551 dest->strides[i] = src->strides[i];
552 }
553 else {
554 init_strides_from_shape(dest);
555 }
556}
557
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700558static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100559init_suboffsets(Py_buffer *dest, const Py_buffer *src)
560{
561 Py_ssize_t i;
562
563 if (src->suboffsets == NULL) {
564 dest->suboffsets = NULL;
565 return;
566 }
567 for (i = 0; i < src->ndim; i++)
568 dest->suboffsets[i] = src->suboffsets[i];
569}
570
571/* len = product(shape) * itemsize */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700572static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100573init_len(Py_buffer *view)
574{
575 Py_ssize_t i, len;
576
577 len = 1;
578 for (i = 0; i < view->ndim; i++)
579 len *= view->shape[i];
580 len *= view->itemsize;
581
582 view->len = len;
583}
584
585/* Initialize memoryview buffer properties. */
586static void
587init_flags(PyMemoryViewObject *mv)
588{
589 const Py_buffer *view = &mv->view;
590 int flags = 0;
591
592 switch (view->ndim) {
593 case 0:
594 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
595 _Py_MEMORYVIEW_FORTRAN);
596 break;
597 case 1:
598 if (MV_CONTIGUOUS_NDIM1(view))
599 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
600 break;
601 default:
602 if (PyBuffer_IsContiguous(view, 'C'))
603 flags |= _Py_MEMORYVIEW_C;
604 if (PyBuffer_IsContiguous(view, 'F'))
605 flags |= _Py_MEMORYVIEW_FORTRAN;
606 break;
607 }
608
609 if (view->suboffsets) {
610 flags |= _Py_MEMORYVIEW_PIL;
611 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
612 }
613
614 mv->flags = flags;
615}
616
617/* Allocate a new memoryview and perform basic initialization. New memoryviews
618 are exclusively created through the mbuf_add functions. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700619static inline PyMemoryViewObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100620memory_alloc(int ndim)
621{
622 PyMemoryViewObject *mv;
623
624 mv = (PyMemoryViewObject *)
625 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
626 if (mv == NULL)
627 return NULL;
628
629 mv->mbuf = NULL;
630 mv->hash = -1;
631 mv->flags = 0;
632 mv->exports = 0;
633 mv->view.ndim = ndim;
634 mv->view.shape = mv->ob_array;
635 mv->view.strides = mv->ob_array + ndim;
636 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100637 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100638
639 _PyObject_GC_TRACK(mv);
640 return mv;
641}
642
643/*
644 Return a new memoryview that is registered with mbuf. If src is NULL,
645 use mbuf->master as the underlying buffer. Otherwise, use src.
646
647 The new memoryview has full buffer information: shape and strides
648 are always present, suboffsets as needed. Arrays are copied to
649 the memoryview's ob_array field.
650 */
651static PyObject *
652mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
653{
654 PyMemoryViewObject *mv;
655 Py_buffer *dest;
656
657 if (src == NULL)
658 src = &mbuf->master;
659
660 if (src->ndim > PyBUF_MAX_NDIM) {
661 PyErr_SetString(PyExc_ValueError,
662 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200663 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100664 return NULL;
665 }
666
667 mv = memory_alloc(src->ndim);
668 if (mv == NULL)
669 return NULL;
670
671 dest = &mv->view;
672 init_shared_values(dest, src);
673 init_shape_strides(dest, src);
674 init_suboffsets(dest, src);
675 init_flags(mv);
676
677 mv->mbuf = mbuf;
678 Py_INCREF(mbuf);
679 mbuf->exports++;
680
681 return (PyObject *)mv;
682}
683
684/* Register an incomplete view: shape, strides, suboffsets and flags still
685 need to be initialized. Use 'ndim' instead of src->ndim to determine the
686 size of the memoryview's ob_array.
687
688 Assumption: ndim <= PyBUF_MAX_NDIM. */
689static PyObject *
690mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
691 int ndim)
692{
693 PyMemoryViewObject *mv;
694 Py_buffer *dest;
695
696 if (src == NULL)
697 src = &mbuf->master;
698
699 assert(ndim <= PyBUF_MAX_NDIM);
700
701 mv = memory_alloc(ndim);
702 if (mv == NULL)
703 return NULL;
704
705 dest = &mv->view;
706 init_shared_values(dest, src);
707
708 mv->mbuf = mbuf;
709 Py_INCREF(mbuf);
710 mbuf->exports++;
711
712 return (PyObject *)mv;
713}
714
715/* Expose a raw memory area as a view of contiguous bytes. flags can be
716 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
717 The memoryview has complete buffer information. */
718PyObject *
719PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
720{
721 _PyManagedBufferObject *mbuf;
722 PyObject *mv;
723 int readonly;
724
725 assert(mem != NULL);
726 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
727
728 mbuf = mbuf_alloc();
729 if (mbuf == NULL)
730 return NULL;
731
732 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
733 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
734 PyBUF_FULL_RO);
735
736 mv = mbuf_add_view(mbuf, NULL);
737 Py_DECREF(mbuf);
738
739 return mv;
740}
741
742/* Create a memoryview from a given Py_buffer. For simple byte views,
743 PyMemoryView_FromMemory() should be used instead.
744 This function is the only entry point that can create a master buffer
745 without full information. Because of this fact init_shape_strides()
746 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000747PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000748PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000749{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100750 _PyManagedBufferObject *mbuf;
751 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000752
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000753 if (info->buf == NULL) {
754 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100755 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000756 return NULL;
757 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100758
759 mbuf = mbuf_alloc();
760 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000761 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100762
763 /* info->obj is either NULL or a borrowed reference. This reference
764 should not be decremented in PyBuffer_Release(). */
765 mbuf->master = *info;
766 mbuf->master.obj = NULL;
767
768 mv = mbuf_add_view(mbuf, NULL);
769 Py_DECREF(mbuf);
770
771 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000772}
773
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100774/* Create a memoryview from an object that implements the buffer protocol.
775 If the object is a memoryview, the new memoryview must be registered
776 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000777PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100778PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000779{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100780 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000781
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100782 if (PyMemoryView_Check(v)) {
783 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
784 CHECK_RELEASED(mv);
785 return mbuf_add_view(mv->mbuf, &mv->view);
786 }
787 else if (PyObject_CheckBuffer(v)) {
788 PyObject *ret;
789 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
790 if (mbuf == NULL)
791 return NULL;
792 ret = mbuf_add_view(mbuf, NULL);
793 Py_DECREF(mbuf);
794 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000795 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000796
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100797 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400798 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100799 Py_TYPE(v)->tp_name);
800 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000801}
802
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100803/* Copy the format string from a base object that might vanish. */
804static int
805mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
806{
807 if (fmt != NULL) {
808 char *cp = PyMem_Malloc(strlen(fmt)+1);
809 if (cp == NULL) {
810 PyErr_NoMemory();
811 return -1;
812 }
813 mbuf->master.format = strcpy(cp, fmt);
814 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
815 }
816
817 return 0;
818}
819
820/*
821 Return a memoryview that is based on a contiguous copy of src.
822 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
823
824 Ownership rules:
825 1) As usual, the returned memoryview has a private copy
826 of src->shape, src->strides and src->suboffsets.
827 2) src->format is copied to the master buffer and released
828 in mbuf_dealloc(). The releasebufferproc of the bytes
829 object is NULL, so it does not matter that mbuf_release()
830 passes the altered format pointer to PyBuffer_Release().
831*/
832static PyObject *
833memory_from_contiguous_copy(Py_buffer *src, char order)
834{
835 _PyManagedBufferObject *mbuf;
836 PyMemoryViewObject *mv;
837 PyObject *bytes;
838 Py_buffer *dest;
839 int i;
840
841 assert(src->ndim > 0);
842 assert(src->shape != NULL);
843
844 bytes = PyBytes_FromStringAndSize(NULL, src->len);
845 if (bytes == NULL)
846 return NULL;
847
848 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
849 Py_DECREF(bytes);
850 if (mbuf == NULL)
851 return NULL;
852
853 if (mbuf_copy_format(mbuf, src->format) < 0) {
854 Py_DECREF(mbuf);
855 return NULL;
856 }
857
858 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
859 Py_DECREF(mbuf);
860 if (mv == NULL)
861 return NULL;
862
863 dest = &mv->view;
864
865 /* shared values are initialized correctly except for itemsize */
866 dest->itemsize = src->itemsize;
867
868 /* shape and strides */
869 for (i = 0; i < src->ndim; i++) {
870 dest->shape[i] = src->shape[i];
871 }
872 if (order == 'C' || order == 'A') {
873 init_strides_from_shape(dest);
874 }
875 else {
876 init_fortran_strides_from_shape(dest);
877 }
878 /* suboffsets */
879 dest->suboffsets = NULL;
880
881 /* flags */
882 init_flags(mv);
883
884 if (copy_buffer(dest, src) < 0) {
885 Py_DECREF(mv);
886 return NULL;
887 }
888
889 return (PyObject *)mv;
890}
891
892/*
893 Return a new memoryview object based on a contiguous exporter with
894 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
895 The logical structure of the input and output buffers is the same
896 (i.e. tolist(input) == tolist(output)), but the physical layout in
897 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200898
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100899 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
900 otherwise it may be writable or read-only.
901
902 If the exporter is already contiguous with the desired target order,
903 the memoryview will be directly based on the exporter.
904
905 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
906 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
907 'F'ortran order otherwise.
908*/
909PyObject *
910PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
911{
912 PyMemoryViewObject *mv;
913 PyObject *ret;
914 Py_buffer *view;
915
916 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
917 assert(order == 'C' || order == 'F' || order == 'A');
918
919 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
920 if (mv == NULL)
921 return NULL;
922
923 view = &mv->view;
924 if (buffertype == PyBUF_WRITE && view->readonly) {
925 PyErr_SetString(PyExc_BufferError,
926 "underlying buffer is not writable");
927 Py_DECREF(mv);
928 return NULL;
929 }
930
931 if (PyBuffer_IsContiguous(view, order))
932 return (PyObject *)mv;
933
934 if (buffertype == PyBUF_WRITE) {
935 PyErr_SetString(PyExc_BufferError,
936 "writable contiguous buffer requested "
937 "for a non-contiguous object.");
938 Py_DECREF(mv);
939 return NULL;
940 }
941
942 ret = memory_from_contiguous_copy(view, order);
943 Py_DECREF(mv);
944 return ret;
945}
946
947
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000948static PyObject *
949memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
950{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000951 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100952 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000953
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000954 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
955 &obj)) {
956 return NULL;
957 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000958
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000959 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000960}
961
962
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100963/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200964/* Previously in abstract.c */
965/****************************************************************************/
966
967typedef struct {
968 Py_buffer view;
969 Py_ssize_t array[1];
970} Py_buffer_full;
971
972int
973PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
974{
975 Py_buffer_full *fb = NULL;
976 int ret;
977
978 assert(order == 'C' || order == 'F' || order == 'A');
979
980 if (len != src->len) {
981 PyErr_SetString(PyExc_ValueError,
982 "PyBuffer_ToContiguous: len != view->len");
983 return -1;
984 }
985
986 if (PyBuffer_IsContiguous(src, order)) {
987 memcpy((char *)buf, src->buf, len);
988 return 0;
989 }
990
991 /* buffer_to_contiguous() assumes PyBUF_FULL */
992 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
993 if (fb == NULL) {
994 PyErr_NoMemory();
995 return -1;
996 }
997 fb->view.ndim = src->ndim;
998 fb->view.shape = fb->array;
999 fb->view.strides = fb->array + src->ndim;
1000 fb->view.suboffsets = fb->array + 2 * src->ndim;
1001
1002 init_shared_values(&fb->view, src);
1003 init_shape_strides(&fb->view, src);
1004 init_suboffsets(&fb->view, src);
1005
1006 src = &fb->view;
1007
1008 ret = buffer_to_contiguous(buf, src, order);
1009 PyMem_Free(fb);
1010 return ret;
1011}
1012
1013
1014/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001015/* Release/GC management */
1016/****************************************************************************/
1017
1018/* Inform the managed buffer that this particular memoryview will not access
1019 the underlying buffer again. If no other memoryviews are registered with
1020 the managed buffer, the underlying buffer is released instantly and
1021 marked as inaccessible for both the memoryview and the managed buffer.
1022
1023 This function fails if the memoryview itself has exported buffers. */
1024static int
1025_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001026{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001027 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1028 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001029
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001030 if (self->exports == 0) {
1031 self->flags |= _Py_MEMORYVIEW_RELEASED;
1032 assert(self->mbuf->exports > 0);
1033 if (--self->mbuf->exports == 0)
1034 mbuf_release(self->mbuf);
1035 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001036 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001037 if (self->exports > 0) {
1038 PyErr_Format(PyExc_BufferError,
1039 "memoryview has %zd exported buffer%s", self->exports,
1040 self->exports==1 ? "" : "s");
1041 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001042 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001043
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001044 Py_FatalError("_memory_release(): negative export count");
1045 return -1;
1046}
1047
1048static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001049memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001050{
1051 if (_memory_release(self) < 0)
1052 return NULL;
1053 Py_RETURN_NONE;
1054}
1055
1056static void
1057memory_dealloc(PyMemoryViewObject *self)
1058{
1059 assert(self->exports == 0);
1060 _PyObject_GC_UNTRACK(self);
1061 (void)_memory_release(self);
1062 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001063 if (self->weakreflist != NULL)
1064 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001065 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001066}
1067
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001068static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001069memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001070{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001071 Py_VISIT(self->mbuf);
1072 return 0;
1073}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001074
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001075static int
1076memory_clear(PyMemoryViewObject *self)
1077{
1078 (void)_memory_release(self);
1079 Py_CLEAR(self->mbuf);
1080 return 0;
1081}
1082
1083static PyObject *
1084memory_enter(PyObject *self, PyObject *args)
1085{
1086 CHECK_RELEASED(self);
1087 Py_INCREF(self);
1088 return self;
1089}
1090
1091static PyObject *
1092memory_exit(PyObject *self, PyObject *args)
1093{
Stefan Krahe4c07992012-07-28 14:10:02 +02001094 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001095}
1096
1097
1098/****************************************************************************/
1099/* Casting format and shape */
1100/****************************************************************************/
1101
1102#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1103
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001104static inline Py_ssize_t
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001105get_native_fmtchar(char *result, const char *fmt)
1106{
1107 Py_ssize_t size = -1;
1108
1109 if (fmt[0] == '@') fmt++;
1110
1111 switch (fmt[0]) {
1112 case 'c': case 'b': case 'B': size = sizeof(char); break;
1113 case 'h': case 'H': size = sizeof(short); break;
1114 case 'i': case 'I': size = sizeof(int); break;
1115 case 'l': case 'L': size = sizeof(long); break;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001116 case 'q': case 'Q': size = sizeof(long long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001117 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1118 case 'f': size = sizeof(float); break;
1119 case 'd': size = sizeof(double); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001120 case '?': size = sizeof(_Bool); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001121 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001122 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001123
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001124 if (size > 0 && fmt[1] == '\0') {
1125 *result = fmt[0];
1126 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001127 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001128
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001129 return -1;
1130}
1131
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001132static inline const char *
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001133get_native_fmtstr(const char *fmt)
1134{
1135 int at = 0;
1136
1137 if (fmt[0] == '@') {
1138 at = 1;
1139 fmt++;
1140 }
1141 if (fmt[0] == '\0' || fmt[1] != '\0') {
1142 return NULL;
1143 }
1144
1145#define RETURN(s) do { return at ? "@" s : s; } while (0)
1146
1147 switch (fmt[0]) {
1148 case 'c': RETURN("c");
1149 case 'b': RETURN("b");
1150 case 'B': RETURN("B");
1151 case 'h': RETURN("h");
1152 case 'H': RETURN("H");
1153 case 'i': RETURN("i");
1154 case 'I': RETURN("I");
1155 case 'l': RETURN("l");
1156 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001157 case 'q': RETURN("q");
1158 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001159 case 'n': RETURN("n");
1160 case 'N': RETURN("N");
1161 case 'f': RETURN("f");
1162 case 'd': RETURN("d");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001163 case '?': RETURN("?");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001164 case 'P': RETURN("P");
1165 }
1166
1167 return NULL;
1168}
1169
1170
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001171/* Cast a memoryview's data type to 'format'. The input array must be
1172 C-contiguous. At least one of input-format, output-format must have
1173 byte size. The output array is 1-D, with the same byte length as the
1174 input array. Thus, view->len must be a multiple of the new itemsize. */
1175static int
1176cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1177{
1178 Py_buffer *view = &mv->view;
1179 PyObject *asciifmt;
1180 char srcchar, destchar;
1181 Py_ssize_t itemsize;
1182 int ret = -1;
1183
1184 assert(view->ndim >= 1);
1185 assert(Py_SIZE(mv) == 3*view->ndim);
1186 assert(view->shape == mv->ob_array);
1187 assert(view->strides == mv->ob_array + view->ndim);
1188 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1189
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001190 asciifmt = PyUnicode_AsASCIIString(format);
1191 if (asciifmt == NULL)
1192 return ret;
1193
1194 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1195 if (itemsize < 0) {
1196 PyErr_SetString(PyExc_ValueError,
1197 "memoryview: destination format must be a native single "
1198 "character format prefixed with an optional '@'");
1199 goto out;
1200 }
1201
Stefan Krah0c515952015-08-08 13:38:10 +02001202 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1203 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001204 PyErr_SetString(PyExc_TypeError,
1205 "memoryview: cannot cast between two non-byte formats");
1206 goto out;
1207 }
1208 if (view->len % itemsize) {
1209 PyErr_SetString(PyExc_TypeError,
1210 "memoryview: length is not a multiple of itemsize");
1211 goto out;
1212 }
1213
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001214 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001215 if (view->format == NULL) {
1216 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1217 PyErr_SetString(PyExc_RuntimeError,
1218 "memoryview: internal error");
1219 goto out;
1220 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001221 view->itemsize = itemsize;
1222
1223 view->ndim = 1;
1224 view->shape[0] = view->len / view->itemsize;
1225 view->strides[0] = view->itemsize;
1226 view->suboffsets = NULL;
1227
1228 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001229
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001230 ret = 0;
1231
1232out:
1233 Py_DECREF(asciifmt);
1234 return ret;
1235}
1236
1237/* The memoryview must have space for 3*len(seq) elements. */
1238static Py_ssize_t
1239copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1240 Py_ssize_t itemsize)
1241{
1242 Py_ssize_t x, i;
1243 Py_ssize_t len = itemsize;
1244
1245 for (i = 0; i < ndim; i++) {
1246 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1247 if (!PyLong_Check(tmp)) {
1248 PyErr_SetString(PyExc_TypeError,
1249 "memoryview.cast(): elements of shape must be integers");
1250 return -1;
1251 }
1252 x = PyLong_AsSsize_t(tmp);
1253 if (x == -1 && PyErr_Occurred()) {
1254 return -1;
1255 }
1256 if (x <= 0) {
1257 /* In general elements of shape may be 0, but not for casting. */
1258 PyErr_Format(PyExc_ValueError,
1259 "memoryview.cast(): elements of shape must be integers > 0");
1260 return -1;
1261 }
1262 if (x > PY_SSIZE_T_MAX / len) {
1263 PyErr_Format(PyExc_ValueError,
1264 "memoryview.cast(): product(shape) > SSIZE_MAX");
1265 return -1;
1266 }
1267 len *= x;
1268 shape[i] = x;
1269 }
1270
1271 return len;
1272}
1273
1274/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1275 If the result array does not have exactly the same byte length as the
1276 input array, raise ValueError. */
1277static int
1278cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1279{
1280 Py_buffer *view = &mv->view;
1281 Py_ssize_t len;
1282
1283 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1284 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1285 assert(view->shape == mv->ob_array);
1286 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1287 assert(view->suboffsets == NULL);
1288
1289 view->ndim = ndim;
1290 if (view->ndim == 0) {
1291 view->shape = NULL;
1292 view->strides = NULL;
1293 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001294 }
1295 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001296 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1297 if (len < 0)
1298 return -1;
1299 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001300 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001301
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001302 if (view->len != len) {
1303 PyErr_SetString(PyExc_TypeError,
1304 "memoryview: product(shape) * itemsize != buffer size");
1305 return -1;
1306 }
1307
1308 init_flags(mv);
1309
1310 return 0;
1311}
1312
1313static int
1314zero_in_shape(PyMemoryViewObject *mv)
1315{
1316 Py_buffer *view = &mv->view;
1317 Py_ssize_t i;
1318
1319 for (i = 0; i < view->ndim; i++)
1320 if (view->shape[i] == 0)
1321 return 1;
1322
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001323 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001324}
1325
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001326/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001327 Cast a copy of 'self' to a different view. The input view must
1328 be C-contiguous. The function always casts the input view to a
1329 1-D output according to 'format'. At least one of input-format,
1330 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001331
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001332 If 'shape' is given, the 1-D view from the previous step will
1333 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001334
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001335 All casts must result in views that will have the exact byte
1336 size of the original input. Otherwise, an error is raised.
1337*/
1338static PyObject *
1339memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001340{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001341 static char *kwlist[] = {"format", "shape", NULL};
1342 PyMemoryViewObject *mv = NULL;
1343 PyObject *shape = NULL;
1344 PyObject *format;
1345 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001346
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001347 CHECK_RELEASED(self);
1348
1349 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1350 &format, &shape)) {
1351 return NULL;
1352 }
1353 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001354 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001355 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001356 return NULL;
1357 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001358 if (!MV_C_CONTIGUOUS(self->flags)) {
1359 PyErr_SetString(PyExc_TypeError,
1360 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001361 return NULL;
1362 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001363 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001364 PyErr_SetString(PyExc_TypeError,
1365 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001366 return NULL;
1367 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001368 if (shape) {
1369 CHECK_LIST_OR_TUPLE(shape)
1370 ndim = PySequence_Fast_GET_SIZE(shape);
1371 if (ndim > PyBUF_MAX_NDIM) {
1372 PyErr_SetString(PyExc_ValueError,
1373 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001374 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001375 return NULL;
1376 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001377 if (self->view.ndim != 1 && ndim != 1) {
1378 PyErr_SetString(PyExc_TypeError,
1379 "memoryview: cast must be 1D -> ND or ND -> 1D");
1380 return NULL;
1381 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001382 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001383
1384 mv = (PyMemoryViewObject *)
1385 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1386 if (mv == NULL)
1387 return NULL;
1388
1389 if (cast_to_1D(mv, format) < 0)
1390 goto error;
1391 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1392 goto error;
1393
1394 return (PyObject *)mv;
1395
1396error:
1397 Py_DECREF(mv);
1398 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001399}
1400
1401
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001402/**************************************************************************/
1403/* getbuffer */
1404/**************************************************************************/
1405
1406static int
1407memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1408{
1409 Py_buffer *base = &self->view;
1410 int baseflags = self->flags;
1411
1412 CHECK_RELEASED_INT(self);
1413
1414 /* start with complete information */
1415 *view = *base;
1416 view->obj = NULL;
1417
1418 if (REQ_WRITABLE(flags) && base->readonly) {
1419 PyErr_SetString(PyExc_BufferError,
1420 "memoryview: underlying buffer is not writable");
1421 return -1;
1422 }
1423 if (!REQ_FORMAT(flags)) {
1424 /* NULL indicates that the buffer's data type has been cast to 'B'.
1425 view->itemsize is the _previous_ itemsize. If shape is present,
1426 the equality product(shape) * itemsize = len still holds at this
1427 point. The equality calcsize(format) = itemsize does _not_ hold
1428 from here on! */
1429 view->format = NULL;
1430 }
1431
1432 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1433 PyErr_SetString(PyExc_BufferError,
1434 "memoryview: underlying buffer is not C-contiguous");
1435 return -1;
1436 }
1437 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1438 PyErr_SetString(PyExc_BufferError,
1439 "memoryview: underlying buffer is not Fortran contiguous");
1440 return -1;
1441 }
1442 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1443 PyErr_SetString(PyExc_BufferError,
1444 "memoryview: underlying buffer is not contiguous");
1445 return -1;
1446 }
1447 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1448 PyErr_SetString(PyExc_BufferError,
1449 "memoryview: underlying buffer requires suboffsets");
1450 return -1;
1451 }
1452 if (!REQ_STRIDES(flags)) {
1453 if (!MV_C_CONTIGUOUS(baseflags)) {
1454 PyErr_SetString(PyExc_BufferError,
1455 "memoryview: underlying buffer is not C-contiguous");
1456 return -1;
1457 }
1458 view->strides = NULL;
1459 }
1460 if (!REQ_SHAPE(flags)) {
1461 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1462 so base->buf = ndbuf->data. */
1463 if (view->format != NULL) {
1464 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1465 not make sense. */
1466 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001467 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001468 "is present");
1469 return -1;
1470 }
1471 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1472 do _not_ hold from here on! */
1473 view->ndim = 1;
1474 view->shape = NULL;
1475 }
1476
1477
1478 view->obj = (PyObject *)self;
1479 Py_INCREF(view->obj);
1480 self->exports++;
1481
1482 return 0;
1483}
1484
1485static void
1486memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1487{
1488 self->exports--;
1489 return;
1490 /* PyBuffer_Release() decrements view->obj after this function returns. */
1491}
1492
1493/* Buffer methods */
1494static PyBufferProcs memory_as_buffer = {
1495 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1496 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1497};
1498
1499
1500/****************************************************************************/
1501/* Optimized pack/unpack for all native format specifiers */
1502/****************************************************************************/
1503
1504/*
1505 Fix exceptions:
1506 1) Include format string in the error message.
1507 2) OverflowError -> ValueError.
1508 3) The error message from PyNumber_Index() is not ideal.
1509*/
1510static int
1511type_error_int(const char *fmt)
1512{
1513 PyErr_Format(PyExc_TypeError,
1514 "memoryview: invalid type for format '%s'", fmt);
1515 return -1;
1516}
1517
1518static int
1519value_error_int(const char *fmt)
1520{
1521 PyErr_Format(PyExc_ValueError,
1522 "memoryview: invalid value for format '%s'", fmt);
1523 return -1;
1524}
1525
1526static int
1527fix_error_int(const char *fmt)
1528{
1529 assert(PyErr_Occurred());
1530 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1531 PyErr_Clear();
1532 return type_error_int(fmt);
1533 }
1534 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1535 PyErr_ExceptionMatches(PyExc_ValueError)) {
1536 PyErr_Clear();
1537 return value_error_int(fmt);
1538 }
1539
1540 return -1;
1541}
1542
1543/* Accept integer objects or objects with an __index__() method. */
1544static long
1545pylong_as_ld(PyObject *item)
1546{
1547 PyObject *tmp;
1548 long ld;
1549
1550 tmp = PyNumber_Index(item);
1551 if (tmp == NULL)
1552 return -1;
1553
1554 ld = PyLong_AsLong(tmp);
1555 Py_DECREF(tmp);
1556 return ld;
1557}
1558
1559static unsigned long
1560pylong_as_lu(PyObject *item)
1561{
1562 PyObject *tmp;
1563 unsigned long lu;
1564
1565 tmp = PyNumber_Index(item);
1566 if (tmp == NULL)
1567 return (unsigned long)-1;
1568
1569 lu = PyLong_AsUnsignedLong(tmp);
1570 Py_DECREF(tmp);
1571 return lu;
1572}
1573
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001574static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001575pylong_as_lld(PyObject *item)
1576{
1577 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001578 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001579
1580 tmp = PyNumber_Index(item);
1581 if (tmp == NULL)
1582 return -1;
1583
1584 lld = PyLong_AsLongLong(tmp);
1585 Py_DECREF(tmp);
1586 return lld;
1587}
1588
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001589static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001590pylong_as_llu(PyObject *item)
1591{
1592 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001593 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001594
1595 tmp = PyNumber_Index(item);
1596 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001597 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001598
1599 llu = PyLong_AsUnsignedLongLong(tmp);
1600 Py_DECREF(tmp);
1601 return llu;
1602}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001603
1604static Py_ssize_t
1605pylong_as_zd(PyObject *item)
1606{
1607 PyObject *tmp;
1608 Py_ssize_t zd;
1609
1610 tmp = PyNumber_Index(item);
1611 if (tmp == NULL)
1612 return -1;
1613
1614 zd = PyLong_AsSsize_t(tmp);
1615 Py_DECREF(tmp);
1616 return zd;
1617}
1618
1619static size_t
1620pylong_as_zu(PyObject *item)
1621{
1622 PyObject *tmp;
1623 size_t zu;
1624
1625 tmp = PyNumber_Index(item);
1626 if (tmp == NULL)
1627 return (size_t)-1;
1628
1629 zu = PyLong_AsSize_t(tmp);
1630 Py_DECREF(tmp);
1631 return zu;
1632}
1633
1634/* Timings with the ndarray from _testbuffer.c indicate that using the
1635 struct module is around 15x slower than the two functions below. */
1636
1637#define UNPACK_SINGLE(dest, ptr, type) \
1638 do { \
1639 type x; \
1640 memcpy((char *)&x, ptr, sizeof x); \
1641 dest = x; \
1642 } while (0)
1643
1644/* Unpack a single item. 'fmt' can be any native format character in struct
1645 module syntax. This function is very sensitive to small changes. With this
1646 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001647static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001648unpack_single(const char *ptr, const char *fmt)
1649{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001650 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001651 unsigned long lu;
1652 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001653 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001654 long ld;
1655 Py_ssize_t zd;
1656 double d;
1657 unsigned char uc;
1658 void *p;
1659
1660 switch (fmt[0]) {
1661
1662 /* signed integers and fast path for 'B' */
1663 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1664 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1665 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1666 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1667 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1668
1669 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001670 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001671
1672 /* unsigned integers */
1673 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1674 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1675 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1676
1677 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001678 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1679 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001680
1681 /* ssize_t and size_t */
1682 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1683 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1684
1685 /* floats */
1686 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1687 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1688
1689 /* bytes object */
1690 case 'c': goto convert_bytes;
1691
1692 /* pointer */
1693 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1694
1695 /* default */
1696 default: goto err_format;
1697 }
1698
1699convert_uc:
1700 /* PyLong_FromUnsignedLong() is slower */
1701 return PyLong_FromLong(uc);
1702convert_ld:
1703 return PyLong_FromLong(ld);
1704convert_lu:
1705 return PyLong_FromUnsignedLong(lu);
1706convert_lld:
1707 return PyLong_FromLongLong(lld);
1708convert_llu:
1709 return PyLong_FromUnsignedLongLong(llu);
1710convert_zd:
1711 return PyLong_FromSsize_t(zd);
1712convert_zu:
1713 return PyLong_FromSize_t(zu);
1714convert_double:
1715 return PyFloat_FromDouble(d);
1716convert_bool:
1717 return PyBool_FromLong(ld);
1718convert_bytes:
1719 return PyBytes_FromStringAndSize(ptr, 1);
1720convert_pointer:
1721 return PyLong_FromVoidPtr(p);
1722err_format:
1723 PyErr_Format(PyExc_NotImplementedError,
1724 "memoryview: format %s not supported", fmt);
1725 return NULL;
1726}
1727
1728#define PACK_SINGLE(ptr, src, type) \
1729 do { \
1730 type x; \
1731 x = (type)src; \
1732 memcpy(ptr, (char *)&x, sizeof x); \
1733 } while (0)
1734
1735/* Pack a single item. 'fmt' can be any native format character in
1736 struct module syntax. */
1737static int
1738pack_single(char *ptr, PyObject *item, const char *fmt)
1739{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001740 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001741 unsigned long lu;
1742 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001743 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001744 long ld;
1745 Py_ssize_t zd;
1746 double d;
1747 void *p;
1748
1749 switch (fmt[0]) {
1750 /* signed integers */
1751 case 'b': case 'h': case 'i': case 'l':
1752 ld = pylong_as_ld(item);
1753 if (ld == -1 && PyErr_Occurred())
1754 goto err_occurred;
1755 switch (fmt[0]) {
1756 case 'b':
1757 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1758 *((signed char *)ptr) = (signed char)ld; break;
1759 case 'h':
1760 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1761 PACK_SINGLE(ptr, ld, short); break;
1762 case 'i':
1763 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1764 PACK_SINGLE(ptr, ld, int); break;
1765 default: /* 'l' */
1766 PACK_SINGLE(ptr, ld, long); break;
1767 }
1768 break;
1769
1770 /* unsigned integers */
1771 case 'B': case 'H': case 'I': case 'L':
1772 lu = pylong_as_lu(item);
1773 if (lu == (unsigned long)-1 && PyErr_Occurred())
1774 goto err_occurred;
1775 switch (fmt[0]) {
1776 case 'B':
1777 if (lu > UCHAR_MAX) goto err_range;
1778 *((unsigned char *)ptr) = (unsigned char)lu; break;
1779 case 'H':
1780 if (lu > USHRT_MAX) goto err_range;
1781 PACK_SINGLE(ptr, lu, unsigned short); break;
1782 case 'I':
1783 if (lu > UINT_MAX) goto err_range;
1784 PACK_SINGLE(ptr, lu, unsigned int); break;
1785 default: /* 'L' */
1786 PACK_SINGLE(ptr, lu, unsigned long); break;
1787 }
1788 break;
1789
1790 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001791 case 'q':
1792 lld = pylong_as_lld(item);
1793 if (lld == -1 && PyErr_Occurred())
1794 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001795 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001796 break;
1797 case 'Q':
1798 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001799 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001800 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001801 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001802 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001803
1804 /* ssize_t and size_t */
1805 case 'n':
1806 zd = pylong_as_zd(item);
1807 if (zd == -1 && PyErr_Occurred())
1808 goto err_occurred;
1809 PACK_SINGLE(ptr, zd, Py_ssize_t);
1810 break;
1811 case 'N':
1812 zu = pylong_as_zu(item);
1813 if (zu == (size_t)-1 && PyErr_Occurred())
1814 goto err_occurred;
1815 PACK_SINGLE(ptr, zu, size_t);
1816 break;
1817
1818 /* floats */
1819 case 'f': case 'd':
1820 d = PyFloat_AsDouble(item);
1821 if (d == -1.0 && PyErr_Occurred())
1822 goto err_occurred;
1823 if (fmt[0] == 'f') {
1824 PACK_SINGLE(ptr, d, float);
1825 }
1826 else {
1827 PACK_SINGLE(ptr, d, double);
1828 }
1829 break;
1830
1831 /* bool */
1832 case '?':
1833 ld = PyObject_IsTrue(item);
1834 if (ld < 0)
1835 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001836 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001837 break;
1838
1839 /* bytes object */
1840 case 'c':
1841 if (!PyBytes_Check(item))
1842 return type_error_int(fmt);
1843 if (PyBytes_GET_SIZE(item) != 1)
1844 return value_error_int(fmt);
1845 *ptr = PyBytes_AS_STRING(item)[0];
1846 break;
1847
1848 /* pointer */
1849 case 'P':
1850 p = PyLong_AsVoidPtr(item);
1851 if (p == NULL && PyErr_Occurred())
1852 goto err_occurred;
1853 PACK_SINGLE(ptr, p, void *);
1854 break;
1855
1856 /* default */
1857 default: goto err_format;
1858 }
1859
1860 return 0;
1861
1862err_occurred:
1863 return fix_error_int(fmt);
1864err_range:
1865 return value_error_int(fmt);
1866err_format:
1867 PyErr_Format(PyExc_NotImplementedError,
1868 "memoryview: format %s not supported", fmt);
1869 return -1;
1870}
1871
1872
1873/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001874/* unpack using the struct module */
1875/****************************************************************************/
1876
1877/* For reasonable performance it is necessary to cache all objects required
1878 for unpacking. An unpacker can handle the format passed to unpack_from().
1879 Invariant: All pointer fields of the struct should either be NULL or valid
1880 pointers. */
1881struct unpacker {
1882 PyObject *unpack_from; /* Struct.unpack_from(format) */
1883 PyObject *mview; /* cached memoryview */
1884 char *item; /* buffer for mview */
1885 Py_ssize_t itemsize; /* len(item) */
1886};
1887
1888static struct unpacker *
1889unpacker_new(void)
1890{
1891 struct unpacker *x = PyMem_Malloc(sizeof *x);
1892
1893 if (x == NULL) {
1894 PyErr_NoMemory();
1895 return NULL;
1896 }
1897
1898 x->unpack_from = NULL;
1899 x->mview = NULL;
1900 x->item = NULL;
1901 x->itemsize = 0;
1902
1903 return x;
1904}
1905
1906static void
1907unpacker_free(struct unpacker *x)
1908{
1909 if (x) {
1910 Py_XDECREF(x->unpack_from);
1911 Py_XDECREF(x->mview);
1912 PyMem_Free(x->item);
1913 PyMem_Free(x);
1914 }
1915}
1916
1917/* Return a new unpacker for the given format. */
1918static struct unpacker *
1919struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1920{
1921 PyObject *structmodule; /* XXX cache these two */
1922 PyObject *Struct = NULL; /* XXX in globals? */
1923 PyObject *structobj = NULL;
1924 PyObject *format = NULL;
1925 struct unpacker *x = NULL;
1926
1927 structmodule = PyImport_ImportModule("struct");
1928 if (structmodule == NULL)
1929 return NULL;
1930
1931 Struct = PyObject_GetAttrString(structmodule, "Struct");
1932 Py_DECREF(structmodule);
1933 if (Struct == NULL)
1934 return NULL;
1935
1936 x = unpacker_new();
1937 if (x == NULL)
1938 goto error;
1939
1940 format = PyBytes_FromString(fmt);
1941 if (format == NULL)
1942 goto error;
1943
1944 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1945 if (structobj == NULL)
1946 goto error;
1947
1948 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1949 if (x->unpack_from == NULL)
1950 goto error;
1951
1952 x->item = PyMem_Malloc(itemsize);
1953 if (x->item == NULL) {
1954 PyErr_NoMemory();
1955 goto error;
1956 }
1957 x->itemsize = itemsize;
1958
1959 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1960 if (x->mview == NULL)
1961 goto error;
1962
1963
1964out:
1965 Py_XDECREF(Struct);
1966 Py_XDECREF(format);
1967 Py_XDECREF(structobj);
1968 return x;
1969
1970error:
1971 unpacker_free(x);
1972 x = NULL;
1973 goto out;
1974}
1975
1976/* unpack a single item */
1977static PyObject *
1978struct_unpack_single(const char *ptr, struct unpacker *x)
1979{
1980 PyObject *v;
1981
1982 memcpy(x->item, ptr, x->itemsize);
1983 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
1984 if (v == NULL)
1985 return NULL;
1986
1987 if (PyTuple_GET_SIZE(v) == 1) {
1988 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
1989 Py_INCREF(tmp);
1990 Py_DECREF(v);
1991 return tmp;
1992 }
1993
1994 return v;
1995}
1996
1997
1998/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001999/* Representations */
2000/****************************************************************************/
2001
2002/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002003static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002004adjust_fmt(const Py_buffer *view)
2005{
2006 const char *fmt;
2007
2008 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2009 if (fmt[0] && fmt[1] == '\0')
2010 return fmt;
2011
2012 PyErr_Format(PyExc_NotImplementedError,
2013 "memoryview: unsupported format %s", view->format);
2014 return NULL;
2015}
2016
2017/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2018static PyObject *
2019tolist_base(const char *ptr, const Py_ssize_t *shape,
2020 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2021 const char *fmt)
2022{
2023 PyObject *lst, *item;
2024 Py_ssize_t i;
2025
2026 lst = PyList_New(shape[0]);
2027 if (lst == NULL)
2028 return NULL;
2029
2030 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002031 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002032 item = unpack_single(xptr, fmt);
2033 if (item == NULL) {
2034 Py_DECREF(lst);
2035 return NULL;
2036 }
2037 PyList_SET_ITEM(lst, i, item);
2038 }
2039
2040 return lst;
2041}
2042
2043/* Unpack a multi-dimensional array into a nested list.
2044 Assumption: ndim >= 1. */
2045static PyObject *
2046tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2047 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2048 const char *fmt)
2049{
2050 PyObject *lst, *item;
2051 Py_ssize_t i;
2052
2053 assert(ndim >= 1);
2054 assert(shape != NULL);
2055 assert(strides != NULL);
2056
2057 if (ndim == 1)
2058 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2059
2060 lst = PyList_New(shape[0]);
2061 if (lst == NULL)
2062 return NULL;
2063
2064 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002065 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002066 item = tolist_rec(xptr, ndim-1, shape+1,
2067 strides+1, suboffsets ? suboffsets+1 : NULL,
2068 fmt);
2069 if (item == NULL) {
2070 Py_DECREF(lst);
2071 return NULL;
2072 }
2073 PyList_SET_ITEM(lst, i, item);
2074 }
2075
2076 return lst;
2077}
2078
2079/* Return a list representation of the memoryview. Currently only buffers
2080 with native format strings are supported. */
2081static PyObject *
2082memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2083{
2084 const Py_buffer *view = &(mv->view);
2085 const char *fmt;
2086
2087 CHECK_RELEASED(mv);
2088
2089 fmt = adjust_fmt(view);
2090 if (fmt == NULL)
2091 return NULL;
2092 if (view->ndim == 0) {
2093 return unpack_single(view->buf, fmt);
2094 }
2095 else if (view->ndim == 1) {
2096 return tolist_base(view->buf, view->shape,
2097 view->strides, view->suboffsets,
2098 fmt);
2099 }
2100 else {
2101 return tolist_rec(view->buf, view->ndim, view->shape,
2102 view->strides, view->suboffsets,
2103 fmt);
2104 }
2105}
2106
2107static PyObject *
2108memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
2109{
2110 Py_buffer *src = VIEW_ADDR(self);
2111 PyObject *bytes = NULL;
2112
2113 CHECK_RELEASED(self);
2114
2115 if (MV_C_CONTIGUOUS(self->flags)) {
2116 return PyBytes_FromStringAndSize(src->buf, src->len);
2117 }
2118
2119 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2120 if (bytes == NULL)
2121 return NULL;
2122
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002123 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002124 Py_DECREF(bytes);
2125 return NULL;
2126 }
2127
2128 return bytes;
2129}
2130
2131static PyObject *
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002132memory_hex(PyMemoryViewObject *self, PyObject *dummy)
2133{
2134 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002135 PyObject *bytes;
2136 PyObject *ret;
2137
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002138 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002139
2140 if (MV_C_CONTIGUOUS(self->flags)) {
2141 return _Py_strhex(src->buf, src->len);
2142 }
2143
2144 bytes = memory_tobytes(self, dummy);
2145 if (bytes == NULL)
2146 return NULL;
2147
Serhiy Storchakafff9a312017-03-21 08:53:25 +02002148 ret = _Py_strhex(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002149 Py_DECREF(bytes);
2150
2151 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002152}
2153
2154static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002155memory_repr(PyMemoryViewObject *self)
2156{
2157 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2158 return PyUnicode_FromFormat("<released memory at %p>", self);
2159 else
2160 return PyUnicode_FromFormat("<memory at %p>", self);
2161}
2162
2163
2164/**************************************************************************/
2165/* Indexing and slicing */
2166/**************************************************************************/
2167
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002168static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002169lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002170{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002171 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002172
2173 assert(view->shape);
2174 assert(view->strides);
2175
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002176 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002177 if (index < 0) {
2178 index += nitems;
2179 }
2180 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002181 PyErr_Format(PyExc_IndexError,
2182 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002183 return NULL;
2184 }
2185
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002186 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002187
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002188 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002189
2190 return ptr;
2191}
2192
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002193/* Get the pointer to the item at index. */
2194static char *
2195ptr_from_index(Py_buffer *view, Py_ssize_t index)
2196{
2197 char *ptr = (char *)view->buf;
2198 return lookup_dimension(view, ptr, 0, index);
2199}
2200
2201/* Get the pointer to the item at tuple. */
2202static char *
2203ptr_from_tuple(Py_buffer *view, PyObject *tup)
2204{
2205 char *ptr = (char *)view->buf;
2206 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2207
2208 if (nindices > view->ndim) {
2209 PyErr_Format(PyExc_TypeError,
2210 "cannot index %zd-dimension view with %zd-element tuple",
2211 view->ndim, nindices);
2212 return NULL;
2213 }
2214
2215 for (dim = 0; dim < nindices; dim++) {
2216 Py_ssize_t index;
2217 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2218 PyExc_IndexError);
2219 if (index == -1 && PyErr_Occurred())
2220 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002221 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002222 if (ptr == NULL)
2223 return NULL;
2224 }
2225 return ptr;
2226}
2227
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002228/* Return the item at index. In a one-dimensional view, this is an object
2229 with the type specified by view->format. Otherwise, the item is a sub-view.
2230 The function is used in memory_subscript() and memory_as_sequence. */
2231static PyObject *
2232memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2233{
2234 Py_buffer *view = &(self->view);
2235 const char *fmt;
2236
2237 CHECK_RELEASED(self);
2238
2239 fmt = adjust_fmt(view);
2240 if (fmt == NULL)
2241 return NULL;
2242
2243 if (view->ndim == 0) {
2244 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2245 return NULL;
2246 }
2247 if (view->ndim == 1) {
2248 char *ptr = ptr_from_index(view, index);
2249 if (ptr == NULL)
2250 return NULL;
2251 return unpack_single(ptr, fmt);
2252 }
2253
2254 PyErr_SetString(PyExc_NotImplementedError,
2255 "multi-dimensional sub-views are not implemented");
2256 return NULL;
2257}
2258
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002259/* Return the item at position *key* (a tuple of indices). */
2260static PyObject *
2261memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2262{
2263 Py_buffer *view = &(self->view);
2264 const char *fmt;
2265 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2266 char *ptr;
2267
2268 CHECK_RELEASED(self);
2269
2270 fmt = adjust_fmt(view);
2271 if (fmt == NULL)
2272 return NULL;
2273
2274 if (nindices < view->ndim) {
2275 PyErr_SetString(PyExc_NotImplementedError,
2276 "sub-views are not implemented");
2277 return NULL;
2278 }
2279 ptr = ptr_from_tuple(view, tup);
2280 if (ptr == NULL)
2281 return NULL;
2282 return unpack_single(ptr, fmt);
2283}
2284
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002285static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002286init_slice(Py_buffer *base, PyObject *key, int dim)
2287{
2288 Py_ssize_t start, stop, step, slicelength;
2289
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002290 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002291 return -1;
2292 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002293 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002294
2295
2296 if (base->suboffsets == NULL || dim == 0) {
2297 adjust_buf:
2298 base->buf = (char *)base->buf + base->strides[dim] * start;
2299 }
2300 else {
2301 Py_ssize_t n = dim-1;
2302 while (n >= 0 && base->suboffsets[n] < 0)
2303 n--;
2304 if (n < 0)
2305 goto adjust_buf; /* all suboffsets are negative */
2306 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2307 }
2308 base->shape[dim] = slicelength;
2309 base->strides[dim] = base->strides[dim] * step;
2310
2311 return 0;
2312}
2313
2314static int
2315is_multislice(PyObject *key)
2316{
2317 Py_ssize_t size, i;
2318
2319 if (!PyTuple_Check(key))
2320 return 0;
2321 size = PyTuple_GET_SIZE(key);
2322 if (size == 0)
2323 return 0;
2324
2325 for (i = 0; i < size; i++) {
2326 PyObject *x = PyTuple_GET_ITEM(key, i);
2327 if (!PySlice_Check(x))
2328 return 0;
2329 }
2330 return 1;
2331}
2332
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002333static Py_ssize_t
2334is_multiindex(PyObject *key)
2335{
2336 Py_ssize_t size, i;
2337
2338 if (!PyTuple_Check(key))
2339 return 0;
2340 size = PyTuple_GET_SIZE(key);
2341 for (i = 0; i < size; i++) {
2342 PyObject *x = PyTuple_GET_ITEM(key, i);
2343 if (!PyIndex_Check(x))
2344 return 0;
2345 }
2346 return 1;
2347}
2348
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002349/* mv[obj] returns an object holding the data for one element if obj
2350 fully indexes the memoryview or another memoryview object if it
2351 does not.
2352
2353 0-d memoryview objects can be referenced using mv[...] or mv[()]
2354 but not with anything else. */
2355static PyObject *
2356memory_subscript(PyMemoryViewObject *self, PyObject *key)
2357{
2358 Py_buffer *view;
2359 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002360
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002361 CHECK_RELEASED(self);
2362
2363 if (view->ndim == 0) {
2364 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2365 const char *fmt = adjust_fmt(view);
2366 if (fmt == NULL)
2367 return NULL;
2368 return unpack_single(view->buf, fmt);
2369 }
2370 else if (key == Py_Ellipsis) {
2371 Py_INCREF(self);
2372 return (PyObject *)self;
2373 }
2374 else {
2375 PyErr_SetString(PyExc_TypeError,
2376 "invalid indexing of 0-dim memory");
2377 return NULL;
2378 }
2379 }
2380
2381 if (PyIndex_Check(key)) {
2382 Py_ssize_t index;
2383 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2384 if (index == -1 && PyErr_Occurred())
2385 return NULL;
2386 return memory_item(self, index);
2387 }
2388 else if (PySlice_Check(key)) {
2389 PyMemoryViewObject *sliced;
2390
2391 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2392 if (sliced == NULL)
2393 return NULL;
2394
2395 if (init_slice(&sliced->view, key, 0) < 0) {
2396 Py_DECREF(sliced);
2397 return NULL;
2398 }
2399 init_len(&sliced->view);
2400 init_flags(sliced);
2401
2402 return (PyObject *)sliced;
2403 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002404 else if (is_multiindex(key)) {
2405 return memory_item_multi(self, key);
2406 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002407 else if (is_multislice(key)) {
2408 PyErr_SetString(PyExc_NotImplementedError,
2409 "multi-dimensional slicing is not implemented");
2410 return NULL;
2411 }
2412
2413 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2414 return NULL;
2415}
2416
2417static int
2418memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2419{
2420 Py_buffer *view = &(self->view);
2421 Py_buffer src;
2422 const char *fmt;
2423 char *ptr;
2424
2425 CHECK_RELEASED_INT(self);
2426
2427 fmt = adjust_fmt(view);
2428 if (fmt == NULL)
2429 return -1;
2430
2431 if (view->readonly) {
2432 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2433 return -1;
2434 }
2435 if (value == NULL) {
2436 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2437 return -1;
2438 }
2439 if (view->ndim == 0) {
2440 if (key == Py_Ellipsis ||
2441 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2442 ptr = (char *)view->buf;
2443 return pack_single(ptr, value, fmt);
2444 }
2445 else {
2446 PyErr_SetString(PyExc_TypeError,
2447 "invalid indexing of 0-dim memory");
2448 return -1;
2449 }
2450 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002451
2452 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002453 Py_ssize_t index;
2454 if (1 < view->ndim) {
2455 PyErr_SetString(PyExc_NotImplementedError,
2456 "sub-views are not implemented");
2457 return -1;
2458 }
2459 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002460 if (index == -1 && PyErr_Occurred())
2461 return -1;
2462 ptr = ptr_from_index(view, index);
2463 if (ptr == NULL)
2464 return -1;
2465 return pack_single(ptr, value, fmt);
2466 }
2467 /* one-dimensional: fast path */
2468 if (PySlice_Check(key) && view->ndim == 1) {
2469 Py_buffer dest; /* sliced view */
2470 Py_ssize_t arrays[3];
2471 int ret = -1;
2472
2473 /* rvalue must be an exporter */
2474 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2475 return ret;
2476
2477 dest = *view;
2478 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2479 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2480 if (view->suboffsets) {
2481 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2482 }
2483
2484 if (init_slice(&dest, key, 0) < 0)
2485 goto end_block;
2486 dest.len = dest.shape[0] * dest.itemsize;
2487
2488 ret = copy_single(&dest, &src);
2489
2490 end_block:
2491 PyBuffer_Release(&src);
2492 return ret;
2493 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002494 if (is_multiindex(key)) {
2495 char *ptr;
2496 if (PyTuple_GET_SIZE(key) < view->ndim) {
2497 PyErr_SetString(PyExc_NotImplementedError,
2498 "sub-views are not implemented");
2499 return -1;
2500 }
2501 ptr = ptr_from_tuple(view, key);
2502 if (ptr == NULL)
2503 return -1;
2504 return pack_single(ptr, value, fmt);
2505 }
2506 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002507 /* Call memory_subscript() to produce a sliced lvalue, then copy
2508 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2509 PyErr_SetString(PyExc_NotImplementedError,
2510 "memoryview slice assignments are currently restricted "
2511 "to ndim = 1");
2512 return -1;
2513 }
2514
2515 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2516 return -1;
2517}
2518
2519static Py_ssize_t
2520memory_length(PyMemoryViewObject *self)
2521{
2522 CHECK_RELEASED_INT(self);
2523 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2524}
2525
2526/* As mapping */
2527static PyMappingMethods memory_as_mapping = {
2528 (lenfunc)memory_length, /* mp_length */
2529 (binaryfunc)memory_subscript, /* mp_subscript */
2530 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2531};
2532
2533/* As sequence */
2534static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002535 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002536 0, /* sq_concat */
2537 0, /* sq_repeat */
2538 (ssizeargfunc)memory_item, /* sq_item */
2539};
2540
2541
2542/**************************************************************************/
2543/* Comparisons */
2544/**************************************************************************/
2545
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002546#define MV_COMPARE_EX -1 /* exception */
2547#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2548
2549/* Translate a StructError to "not equal". Preserve other exceptions. */
2550static int
2551fix_struct_error_int(void)
2552{
2553 assert(PyErr_Occurred());
2554 /* XXX Cannot get at StructError directly? */
2555 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2556 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2557 return MV_COMPARE_EX;
2558 }
2559 /* StructError: invalid or unknown format -> not equal */
2560 PyErr_Clear();
2561 return 0;
2562}
2563
2564/* Unpack and compare single items of p and q using the struct module. */
2565static int
2566struct_unpack_cmp(const char *p, const char *q,
2567 struct unpacker *unpack_p, struct unpacker *unpack_q)
2568{
2569 PyObject *v, *w;
2570 int ret;
2571
2572 /* At this point any exception from the struct module should not be
2573 StructError, since both formats have been accepted already. */
2574 v = struct_unpack_single(p, unpack_p);
2575 if (v == NULL)
2576 return MV_COMPARE_EX;
2577
2578 w = struct_unpack_single(q, unpack_q);
2579 if (w == NULL) {
2580 Py_DECREF(v);
2581 return MV_COMPARE_EX;
2582 }
2583
2584 /* MV_COMPARE_EX == -1: exceptions are preserved */
2585 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2586 Py_DECREF(v);
2587 Py_DECREF(w);
2588
2589 return ret;
2590}
2591
2592/* Unpack and compare single items of p and q. If both p and q have the same
2593 single element native format, the comparison uses a fast path (gcc creates
2594 a jump table and converts memcpy into simple assignments on x86/x64).
2595
2596 Otherwise, the comparison is delegated to the struct module, which is
2597 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002598#define CMP_SINGLE(p, q, type) \
2599 do { \
2600 type x; \
2601 type y; \
2602 memcpy((char *)&x, p, sizeof x); \
2603 memcpy((char *)&y, q, sizeof y); \
2604 equal = (x == y); \
2605 } while (0)
2606
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002607static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002608unpack_cmp(const char *p, const char *q, char fmt,
2609 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002610{
2611 int equal;
2612
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002613 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002614
2615 /* signed integers and fast path for 'B' */
2616 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2617 case 'b': return *((signed char *)p) == *((signed char *)q);
2618 case 'h': CMP_SINGLE(p, q, short); return equal;
2619 case 'i': CMP_SINGLE(p, q, int); return equal;
2620 case 'l': CMP_SINGLE(p, q, long); return equal;
2621
2622 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002623 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002624
2625 /* unsigned integers */
2626 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2627 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2628 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2629
2630 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002631 case 'q': CMP_SINGLE(p, q, long long); return equal;
2632 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002633
2634 /* ssize_t and size_t */
2635 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2636 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2637
2638 /* floats */
2639 /* XXX DBL_EPSILON? */
2640 case 'f': CMP_SINGLE(p, q, float); return equal;
2641 case 'd': CMP_SINGLE(p, q, double); return equal;
2642
2643 /* bytes object */
2644 case 'c': return *p == *q;
2645
2646 /* pointer */
2647 case 'P': CMP_SINGLE(p, q, void *); return equal;
2648
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002649 /* use the struct module */
2650 case '_':
2651 assert(unpack_p);
2652 assert(unpack_q);
2653 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002654 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002655
2656 /* NOT REACHED */
2657 PyErr_SetString(PyExc_RuntimeError,
2658 "memoryview: internal error in richcompare");
2659 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002660}
2661
2662/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2663static int
2664cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2665 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2666 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002667 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002668{
2669 Py_ssize_t i;
2670 int equal;
2671
2672 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002673 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2674 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002675 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002676 if (equal <= 0)
2677 return equal;
2678 }
2679
2680 return 1;
2681}
2682
2683/* Recursively compare two multi-dimensional arrays that have the same
2684 logical structure. Assumption: ndim >= 1. */
2685static int
2686cmp_rec(const char *p, const char *q,
2687 Py_ssize_t ndim, const Py_ssize_t *shape,
2688 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2689 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002690 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002691{
2692 Py_ssize_t i;
2693 int equal;
2694
2695 assert(ndim >= 1);
2696 assert(shape != NULL);
2697 assert(pstrides != NULL);
2698 assert(qstrides != NULL);
2699
2700 if (ndim == 1) {
2701 return cmp_base(p, q, shape,
2702 pstrides, psuboffsets,
2703 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002704 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002705 }
2706
2707 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002708 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2709 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002710 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2711 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2712 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002713 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002714 if (equal <= 0)
2715 return equal;
2716 }
2717
2718 return 1;
2719}
2720
2721static PyObject *
2722memory_richcompare(PyObject *v, PyObject *w, int op)
2723{
2724 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002725 Py_buffer wbuf, *vv;
2726 Py_buffer *ww = NULL;
2727 struct unpacker *unpack_v = NULL;
2728 struct unpacker *unpack_w = NULL;
2729 char vfmt, wfmt;
2730 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002731
2732 if (op != Py_EQ && op != Py_NE)
2733 goto result; /* Py_NotImplemented */
2734
2735 assert(PyMemoryView_Check(v));
2736 if (BASE_INACCESSIBLE(v)) {
2737 equal = (v == w);
2738 goto result;
2739 }
2740 vv = VIEW_ADDR(v);
2741
2742 if (PyMemoryView_Check(w)) {
2743 if (BASE_INACCESSIBLE(w)) {
2744 equal = (v == w);
2745 goto result;
2746 }
2747 ww = VIEW_ADDR(w);
2748 }
2749 else {
2750 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2751 PyErr_Clear();
2752 goto result; /* Py_NotImplemented */
2753 }
2754 ww = &wbuf;
2755 }
2756
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002757 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002758 PyErr_Clear();
2759 equal = 0;
2760 goto result;
2761 }
2762
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002763 /* Use fast unpacking for identical primitive C type formats. */
2764 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2765 vfmt = '_';
2766 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2767 wfmt = '_';
2768 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2769 /* Use struct module unpacking. NOTE: Even for equal format strings,
2770 memcmp() cannot be used for item comparison since it would give
2771 incorrect results in the case of NaNs or uninitialized padding
2772 bytes. */
2773 vfmt = '_';
2774 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2775 if (unpack_v == NULL) {
2776 equal = fix_struct_error_int();
2777 goto result;
2778 }
2779 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2780 if (unpack_w == NULL) {
2781 equal = fix_struct_error_int();
2782 goto result;
2783 }
2784 }
2785
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002786 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002787 equal = unpack_cmp(vv->buf, ww->buf,
2788 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002789 }
2790 else if (vv->ndim == 1) {
2791 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2792 vv->strides, vv->suboffsets,
2793 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002794 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002795 }
2796 else {
2797 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2798 vv->strides, vv->suboffsets,
2799 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002800 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002801 }
2802
2803result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002804 if (equal < 0) {
2805 if (equal == MV_COMPARE_NOT_IMPL)
2806 res = Py_NotImplemented;
2807 else /* exception */
2808 res = NULL;
2809 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002810 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2811 res = Py_True;
2812 else
2813 res = Py_False;
2814
2815 if (ww == &wbuf)
2816 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002817
2818 unpacker_free(unpack_v);
2819 unpacker_free(unpack_w);
2820
2821 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002822 return res;
2823}
2824
2825/**************************************************************************/
2826/* Hash */
2827/**************************************************************************/
2828
2829static Py_hash_t
2830memory_hash(PyMemoryViewObject *self)
2831{
2832 if (self->hash == -1) {
2833 Py_buffer *view = &self->view;
2834 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002835 Py_ssize_t ret;
2836 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002837
2838 CHECK_RELEASED_INT(self);
2839
2840 if (!view->readonly) {
2841 PyErr_SetString(PyExc_ValueError,
2842 "cannot hash writable memoryview object");
2843 return -1;
2844 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002845 ret = get_native_fmtchar(&fmt, view->format);
2846 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2847 PyErr_SetString(PyExc_ValueError,
2848 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2849 return -1;
2850 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002851 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2852 /* Keep the original error message */
2853 return -1;
2854 }
2855
2856 if (!MV_C_CONTIGUOUS(self->flags)) {
2857 mem = PyMem_Malloc(view->len);
2858 if (mem == NULL) {
2859 PyErr_NoMemory();
2860 return -1;
2861 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002862 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002863 PyMem_Free(mem);
2864 return -1;
2865 }
2866 }
2867
2868 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002869 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002870
2871 if (mem != view->buf)
2872 PyMem_Free(mem);
2873 }
2874
2875 return self->hash;
2876}
2877
2878
2879/**************************************************************************/
2880/* getters */
2881/**************************************************************************/
2882
2883static PyObject *
2884_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2885{
2886 int i;
2887 PyObject *o;
2888 PyObject *intTuple;
2889
2890 if (vals == NULL)
2891 return PyTuple_New(0);
2892
2893 intTuple = PyTuple_New(len);
2894 if (!intTuple)
2895 return NULL;
2896 for (i=0; i<len; i++) {
2897 o = PyLong_FromSsize_t(vals[i]);
2898 if (!o) {
2899 Py_DECREF(intTuple);
2900 return NULL;
2901 }
2902 PyTuple_SET_ITEM(intTuple, i, o);
2903 }
2904 return intTuple;
2905}
2906
2907static PyObject *
2908memory_obj_get(PyMemoryViewObject *self)
2909{
2910 Py_buffer *view = &self->view;
2911
2912 CHECK_RELEASED(self);
2913 if (view->obj == NULL) {
2914 Py_RETURN_NONE;
2915 }
2916 Py_INCREF(view->obj);
2917 return view->obj;
2918}
2919
2920static PyObject *
2921memory_nbytes_get(PyMemoryViewObject *self)
2922{
2923 CHECK_RELEASED(self);
2924 return PyLong_FromSsize_t(self->view.len);
2925}
2926
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002927static PyObject *
2928memory_format_get(PyMemoryViewObject *self)
2929{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002930 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002931 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002932}
2933
2934static PyObject *
2935memory_itemsize_get(PyMemoryViewObject *self)
2936{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002937 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002938 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002939}
2940
2941static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002942memory_shape_get(PyMemoryViewObject *self)
2943{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002944 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002945 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002946}
2947
2948static PyObject *
2949memory_strides_get(PyMemoryViewObject *self)
2950{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002951 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002952 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002953}
2954
2955static PyObject *
2956memory_suboffsets_get(PyMemoryViewObject *self)
2957{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002958 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002959 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002960}
2961
2962static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002963memory_readonly_get(PyMemoryViewObject *self)
2964{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002965 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002966 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002967}
2968
2969static PyObject *
2970memory_ndim_get(PyMemoryViewObject *self)
2971{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002972 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002973 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002974}
2975
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002976static PyObject *
2977memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2978{
2979 CHECK_RELEASED(self);
2980 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
2981}
2982
2983static PyObject *
2984memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2985{
2986 CHECK_RELEASED(self);
2987 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
2988}
2989
2990static PyObject *
2991memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2992{
2993 CHECK_RELEASED(self);
2994 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
2995}
2996
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04002997PyDoc_STRVAR(memory_obj_doc,
2998 "The underlying object of the memoryview.");
2999PyDoc_STRVAR(memory_nbytes_doc,
3000 "The amount of space in bytes that the array would use in\n"
3001 " a contiguous representation.");
3002PyDoc_STRVAR(memory_readonly_doc,
3003 "A bool indicating whether the memory is read only.");
3004PyDoc_STRVAR(memory_itemsize_doc,
3005 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003006PyDoc_STRVAR(memory_format_doc,
3007 "A string containing the format (in struct module style)\n"
3008 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003009PyDoc_STRVAR(memory_ndim_doc,
3010 "An integer indicating how many dimensions of a multi-dimensional\n"
3011 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003012PyDoc_STRVAR(memory_shape_doc,
3013 "A tuple of ndim integers giving the shape of the memory\n"
3014 " as an N-dimensional array.");
3015PyDoc_STRVAR(memory_strides_doc,
3016 "A tuple of ndim integers giving the size in bytes to access\n"
3017 " each element for each dimension of the array.");
3018PyDoc_STRVAR(memory_suboffsets_doc,
3019 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003020PyDoc_STRVAR(memory_c_contiguous_doc,
3021 "A bool indicating whether the memory is C contiguous.");
3022PyDoc_STRVAR(memory_f_contiguous_doc,
3023 "A bool indicating whether the memory is Fortran contiguous.");
3024PyDoc_STRVAR(memory_contiguous_doc,
3025 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003026
Stefan Krahbcaf5992014-05-18 00:35:09 +02003027
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003028static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003029 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3030 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003031 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3032 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3033 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3034 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3035 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3036 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3037 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003038 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3039 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3040 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003041 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003042};
3043
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003044PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003045"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003046\n\
3047Release the underlying buffer exposed by the memoryview object.");
3048PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003049"tobytes($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003050\n\
3051Return the data in the buffer as a byte string.");
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003052PyDoc_STRVAR(memory_hex_doc,
3053"hex($self, /)\n--\n\
3054\n\
3055Return the data in the buffer as a string of hexadecimal numbers.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003056PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003057"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003058\n\
3059Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003060PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003061"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003062\n\
3063Cast a memoryview to a new format or shape.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003064
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003065static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003066 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3067 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003068 {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003069 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003070 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003071 {"__enter__", memory_enter, METH_NOARGS, NULL},
3072 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003073 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003074};
3075
3076
3077PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003078 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003079 "memoryview", /* tp_name */
3080 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3081 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003082 (destructor)memory_dealloc, /* tp_dealloc */
3083 0, /* tp_print */
3084 0, /* tp_getattr */
3085 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003086 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003087 (reprfunc)memory_repr, /* tp_repr */
3088 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003089 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003090 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003091 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003092 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003093 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003094 PyObject_GenericGetAttr, /* tp_getattro */
3095 0, /* tp_setattro */
3096 &memory_as_buffer, /* tp_as_buffer */
3097 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3098 memory_doc, /* tp_doc */
3099 (traverseproc)memory_traverse, /* tp_traverse */
3100 (inquiry)memory_clear, /* tp_clear */
3101 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003102 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003103 0, /* tp_iter */
3104 0, /* tp_iternext */
3105 memory_methods, /* tp_methods */
3106 0, /* tp_members */
3107 memory_getsetlist, /* tp_getset */
3108 0, /* tp_base */
3109 0, /* tp_dict */
3110 0, /* tp_descr_get */
3111 0, /* tp_descr_set */
3112 0, /* tp_dictoffset */
3113 0, /* tp_init */
3114 0, /* tp_alloc */
3115 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003116};