blob: 060ae4dd3cd0f2fa32bfc6dfa298821b06388880 [file] [log] [blame]
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001/* Memoryview object implementation */
2
3#include "Python.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01004#include "pycore_pymem.h"
5#include "pycore_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
Antoine Pitrou480ab052018-04-14 19:49:21 +02001401static PyObject *
1402memory_toreadonly(PyMemoryViewObject *self, PyObject *noargs)
1403{
1404 CHECK_RELEASED(self);
1405 /* Even if self is already readonly, we still need to create a new
1406 * object for .release() to work correctly.
1407 */
1408 self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1409 if (self != NULL) {
1410 self->view.readonly = 1;
1411 };
1412 return (PyObject *) self;
1413}
1414
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001415
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001416/**************************************************************************/
1417/* getbuffer */
1418/**************************************************************************/
1419
1420static int
1421memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1422{
1423 Py_buffer *base = &self->view;
1424 int baseflags = self->flags;
1425
1426 CHECK_RELEASED_INT(self);
1427
1428 /* start with complete information */
1429 *view = *base;
1430 view->obj = NULL;
1431
1432 if (REQ_WRITABLE(flags) && base->readonly) {
1433 PyErr_SetString(PyExc_BufferError,
1434 "memoryview: underlying buffer is not writable");
1435 return -1;
1436 }
1437 if (!REQ_FORMAT(flags)) {
1438 /* NULL indicates that the buffer's data type has been cast to 'B'.
1439 view->itemsize is the _previous_ itemsize. If shape is present,
1440 the equality product(shape) * itemsize = len still holds at this
1441 point. The equality calcsize(format) = itemsize does _not_ hold
1442 from here on! */
1443 view->format = NULL;
1444 }
1445
1446 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1447 PyErr_SetString(PyExc_BufferError,
1448 "memoryview: underlying buffer is not C-contiguous");
1449 return -1;
1450 }
1451 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1452 PyErr_SetString(PyExc_BufferError,
1453 "memoryview: underlying buffer is not Fortran contiguous");
1454 return -1;
1455 }
1456 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1457 PyErr_SetString(PyExc_BufferError,
1458 "memoryview: underlying buffer is not contiguous");
1459 return -1;
1460 }
1461 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1462 PyErr_SetString(PyExc_BufferError,
1463 "memoryview: underlying buffer requires suboffsets");
1464 return -1;
1465 }
1466 if (!REQ_STRIDES(flags)) {
1467 if (!MV_C_CONTIGUOUS(baseflags)) {
1468 PyErr_SetString(PyExc_BufferError,
1469 "memoryview: underlying buffer is not C-contiguous");
1470 return -1;
1471 }
1472 view->strides = NULL;
1473 }
1474 if (!REQ_SHAPE(flags)) {
1475 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1476 so base->buf = ndbuf->data. */
1477 if (view->format != NULL) {
1478 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1479 not make sense. */
1480 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001481 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001482 "is present");
1483 return -1;
1484 }
1485 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1486 do _not_ hold from here on! */
1487 view->ndim = 1;
1488 view->shape = NULL;
1489 }
1490
1491
1492 view->obj = (PyObject *)self;
1493 Py_INCREF(view->obj);
1494 self->exports++;
1495
1496 return 0;
1497}
1498
1499static void
1500memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1501{
1502 self->exports--;
1503 return;
1504 /* PyBuffer_Release() decrements view->obj after this function returns. */
1505}
1506
1507/* Buffer methods */
1508static PyBufferProcs memory_as_buffer = {
1509 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1510 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1511};
1512
1513
1514/****************************************************************************/
1515/* Optimized pack/unpack for all native format specifiers */
1516/****************************************************************************/
1517
1518/*
1519 Fix exceptions:
1520 1) Include format string in the error message.
1521 2) OverflowError -> ValueError.
1522 3) The error message from PyNumber_Index() is not ideal.
1523*/
1524static int
1525type_error_int(const char *fmt)
1526{
1527 PyErr_Format(PyExc_TypeError,
1528 "memoryview: invalid type for format '%s'", fmt);
1529 return -1;
1530}
1531
1532static int
1533value_error_int(const char *fmt)
1534{
1535 PyErr_Format(PyExc_ValueError,
1536 "memoryview: invalid value for format '%s'", fmt);
1537 return -1;
1538}
1539
1540static int
1541fix_error_int(const char *fmt)
1542{
1543 assert(PyErr_Occurred());
1544 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1545 PyErr_Clear();
1546 return type_error_int(fmt);
1547 }
1548 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1549 PyErr_ExceptionMatches(PyExc_ValueError)) {
1550 PyErr_Clear();
1551 return value_error_int(fmt);
1552 }
1553
1554 return -1;
1555}
1556
1557/* Accept integer objects or objects with an __index__() method. */
1558static long
1559pylong_as_ld(PyObject *item)
1560{
1561 PyObject *tmp;
1562 long ld;
1563
1564 tmp = PyNumber_Index(item);
1565 if (tmp == NULL)
1566 return -1;
1567
1568 ld = PyLong_AsLong(tmp);
1569 Py_DECREF(tmp);
1570 return ld;
1571}
1572
1573static unsigned long
1574pylong_as_lu(PyObject *item)
1575{
1576 PyObject *tmp;
1577 unsigned long lu;
1578
1579 tmp = PyNumber_Index(item);
1580 if (tmp == NULL)
1581 return (unsigned long)-1;
1582
1583 lu = PyLong_AsUnsignedLong(tmp);
1584 Py_DECREF(tmp);
1585 return lu;
1586}
1587
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001588static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001589pylong_as_lld(PyObject *item)
1590{
1591 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001592 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001593
1594 tmp = PyNumber_Index(item);
1595 if (tmp == NULL)
1596 return -1;
1597
1598 lld = PyLong_AsLongLong(tmp);
1599 Py_DECREF(tmp);
1600 return lld;
1601}
1602
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001603static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001604pylong_as_llu(PyObject *item)
1605{
1606 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001607 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001608
1609 tmp = PyNumber_Index(item);
1610 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001611 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001612
1613 llu = PyLong_AsUnsignedLongLong(tmp);
1614 Py_DECREF(tmp);
1615 return llu;
1616}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001617
1618static Py_ssize_t
1619pylong_as_zd(PyObject *item)
1620{
1621 PyObject *tmp;
1622 Py_ssize_t zd;
1623
1624 tmp = PyNumber_Index(item);
1625 if (tmp == NULL)
1626 return -1;
1627
1628 zd = PyLong_AsSsize_t(tmp);
1629 Py_DECREF(tmp);
1630 return zd;
1631}
1632
1633static size_t
1634pylong_as_zu(PyObject *item)
1635{
1636 PyObject *tmp;
1637 size_t zu;
1638
1639 tmp = PyNumber_Index(item);
1640 if (tmp == NULL)
1641 return (size_t)-1;
1642
1643 zu = PyLong_AsSize_t(tmp);
1644 Py_DECREF(tmp);
1645 return zu;
1646}
1647
1648/* Timings with the ndarray from _testbuffer.c indicate that using the
1649 struct module is around 15x slower than the two functions below. */
1650
1651#define UNPACK_SINGLE(dest, ptr, type) \
1652 do { \
1653 type x; \
1654 memcpy((char *)&x, ptr, sizeof x); \
1655 dest = x; \
1656 } while (0)
1657
1658/* Unpack a single item. 'fmt' can be any native format character in struct
1659 module syntax. This function is very sensitive to small changes. With this
1660 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001661static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001662unpack_single(const char *ptr, const char *fmt)
1663{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001664 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001665 unsigned long lu;
1666 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001667 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001668 long ld;
1669 Py_ssize_t zd;
1670 double d;
1671 unsigned char uc;
1672 void *p;
1673
1674 switch (fmt[0]) {
1675
1676 /* signed integers and fast path for 'B' */
1677 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1678 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1679 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1680 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1681 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1682
1683 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001684 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001685
1686 /* unsigned integers */
1687 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1688 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1689 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1690
1691 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001692 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1693 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001694
1695 /* ssize_t and size_t */
1696 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1697 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1698
1699 /* floats */
1700 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1701 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1702
1703 /* bytes object */
1704 case 'c': goto convert_bytes;
1705
1706 /* pointer */
1707 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1708
1709 /* default */
1710 default: goto err_format;
1711 }
1712
1713convert_uc:
1714 /* PyLong_FromUnsignedLong() is slower */
1715 return PyLong_FromLong(uc);
1716convert_ld:
1717 return PyLong_FromLong(ld);
1718convert_lu:
1719 return PyLong_FromUnsignedLong(lu);
1720convert_lld:
1721 return PyLong_FromLongLong(lld);
1722convert_llu:
1723 return PyLong_FromUnsignedLongLong(llu);
1724convert_zd:
1725 return PyLong_FromSsize_t(zd);
1726convert_zu:
1727 return PyLong_FromSize_t(zu);
1728convert_double:
1729 return PyFloat_FromDouble(d);
1730convert_bool:
1731 return PyBool_FromLong(ld);
1732convert_bytes:
1733 return PyBytes_FromStringAndSize(ptr, 1);
1734convert_pointer:
1735 return PyLong_FromVoidPtr(p);
1736err_format:
1737 PyErr_Format(PyExc_NotImplementedError,
1738 "memoryview: format %s not supported", fmt);
1739 return NULL;
1740}
1741
1742#define PACK_SINGLE(ptr, src, type) \
1743 do { \
1744 type x; \
1745 x = (type)src; \
1746 memcpy(ptr, (char *)&x, sizeof x); \
1747 } while (0)
1748
1749/* Pack a single item. 'fmt' can be any native format character in
1750 struct module syntax. */
1751static int
1752pack_single(char *ptr, PyObject *item, const char *fmt)
1753{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001754 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001755 unsigned long lu;
1756 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001757 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001758 long ld;
1759 Py_ssize_t zd;
1760 double d;
1761 void *p;
1762
1763 switch (fmt[0]) {
1764 /* signed integers */
1765 case 'b': case 'h': case 'i': case 'l':
1766 ld = pylong_as_ld(item);
1767 if (ld == -1 && PyErr_Occurred())
1768 goto err_occurred;
1769 switch (fmt[0]) {
1770 case 'b':
1771 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1772 *((signed char *)ptr) = (signed char)ld; break;
1773 case 'h':
1774 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1775 PACK_SINGLE(ptr, ld, short); break;
1776 case 'i':
1777 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1778 PACK_SINGLE(ptr, ld, int); break;
1779 default: /* 'l' */
1780 PACK_SINGLE(ptr, ld, long); break;
1781 }
1782 break;
1783
1784 /* unsigned integers */
1785 case 'B': case 'H': case 'I': case 'L':
1786 lu = pylong_as_lu(item);
1787 if (lu == (unsigned long)-1 && PyErr_Occurred())
1788 goto err_occurred;
1789 switch (fmt[0]) {
1790 case 'B':
1791 if (lu > UCHAR_MAX) goto err_range;
1792 *((unsigned char *)ptr) = (unsigned char)lu; break;
1793 case 'H':
1794 if (lu > USHRT_MAX) goto err_range;
1795 PACK_SINGLE(ptr, lu, unsigned short); break;
1796 case 'I':
1797 if (lu > UINT_MAX) goto err_range;
1798 PACK_SINGLE(ptr, lu, unsigned int); break;
1799 default: /* 'L' */
1800 PACK_SINGLE(ptr, lu, unsigned long); break;
1801 }
1802 break;
1803
1804 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001805 case 'q':
1806 lld = pylong_as_lld(item);
1807 if (lld == -1 && PyErr_Occurred())
1808 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001809 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001810 break;
1811 case 'Q':
1812 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001813 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001814 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001815 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001816 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001817
1818 /* ssize_t and size_t */
1819 case 'n':
1820 zd = pylong_as_zd(item);
1821 if (zd == -1 && PyErr_Occurred())
1822 goto err_occurred;
1823 PACK_SINGLE(ptr, zd, Py_ssize_t);
1824 break;
1825 case 'N':
1826 zu = pylong_as_zu(item);
1827 if (zu == (size_t)-1 && PyErr_Occurred())
1828 goto err_occurred;
1829 PACK_SINGLE(ptr, zu, size_t);
1830 break;
1831
1832 /* floats */
1833 case 'f': case 'd':
1834 d = PyFloat_AsDouble(item);
1835 if (d == -1.0 && PyErr_Occurred())
1836 goto err_occurred;
1837 if (fmt[0] == 'f') {
1838 PACK_SINGLE(ptr, d, float);
1839 }
1840 else {
1841 PACK_SINGLE(ptr, d, double);
1842 }
1843 break;
1844
1845 /* bool */
1846 case '?':
1847 ld = PyObject_IsTrue(item);
1848 if (ld < 0)
1849 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001850 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001851 break;
1852
1853 /* bytes object */
1854 case 'c':
1855 if (!PyBytes_Check(item))
1856 return type_error_int(fmt);
1857 if (PyBytes_GET_SIZE(item) != 1)
1858 return value_error_int(fmt);
1859 *ptr = PyBytes_AS_STRING(item)[0];
1860 break;
1861
1862 /* pointer */
1863 case 'P':
1864 p = PyLong_AsVoidPtr(item);
1865 if (p == NULL && PyErr_Occurred())
1866 goto err_occurred;
1867 PACK_SINGLE(ptr, p, void *);
1868 break;
1869
1870 /* default */
1871 default: goto err_format;
1872 }
1873
1874 return 0;
1875
1876err_occurred:
1877 return fix_error_int(fmt);
1878err_range:
1879 return value_error_int(fmt);
1880err_format:
1881 PyErr_Format(PyExc_NotImplementedError,
1882 "memoryview: format %s not supported", fmt);
1883 return -1;
1884}
1885
1886
1887/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001888/* unpack using the struct module */
1889/****************************************************************************/
1890
1891/* For reasonable performance it is necessary to cache all objects required
1892 for unpacking. An unpacker can handle the format passed to unpack_from().
1893 Invariant: All pointer fields of the struct should either be NULL or valid
1894 pointers. */
1895struct unpacker {
1896 PyObject *unpack_from; /* Struct.unpack_from(format) */
1897 PyObject *mview; /* cached memoryview */
1898 char *item; /* buffer for mview */
1899 Py_ssize_t itemsize; /* len(item) */
1900};
1901
1902static struct unpacker *
1903unpacker_new(void)
1904{
1905 struct unpacker *x = PyMem_Malloc(sizeof *x);
1906
1907 if (x == NULL) {
1908 PyErr_NoMemory();
1909 return NULL;
1910 }
1911
1912 x->unpack_from = NULL;
1913 x->mview = NULL;
1914 x->item = NULL;
1915 x->itemsize = 0;
1916
1917 return x;
1918}
1919
1920static void
1921unpacker_free(struct unpacker *x)
1922{
1923 if (x) {
1924 Py_XDECREF(x->unpack_from);
1925 Py_XDECREF(x->mview);
1926 PyMem_Free(x->item);
1927 PyMem_Free(x);
1928 }
1929}
1930
1931/* Return a new unpacker for the given format. */
1932static struct unpacker *
1933struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1934{
1935 PyObject *structmodule; /* XXX cache these two */
1936 PyObject *Struct = NULL; /* XXX in globals? */
1937 PyObject *structobj = NULL;
1938 PyObject *format = NULL;
1939 struct unpacker *x = NULL;
1940
1941 structmodule = PyImport_ImportModule("struct");
1942 if (structmodule == NULL)
1943 return NULL;
1944
1945 Struct = PyObject_GetAttrString(structmodule, "Struct");
1946 Py_DECREF(structmodule);
1947 if (Struct == NULL)
1948 return NULL;
1949
1950 x = unpacker_new();
1951 if (x == NULL)
1952 goto error;
1953
1954 format = PyBytes_FromString(fmt);
1955 if (format == NULL)
1956 goto error;
1957
1958 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1959 if (structobj == NULL)
1960 goto error;
1961
1962 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1963 if (x->unpack_from == NULL)
1964 goto error;
1965
1966 x->item = PyMem_Malloc(itemsize);
1967 if (x->item == NULL) {
1968 PyErr_NoMemory();
1969 goto error;
1970 }
1971 x->itemsize = itemsize;
1972
1973 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1974 if (x->mview == NULL)
1975 goto error;
1976
1977
1978out:
1979 Py_XDECREF(Struct);
1980 Py_XDECREF(format);
1981 Py_XDECREF(structobj);
1982 return x;
1983
1984error:
1985 unpacker_free(x);
1986 x = NULL;
1987 goto out;
1988}
1989
1990/* unpack a single item */
1991static PyObject *
1992struct_unpack_single(const char *ptr, struct unpacker *x)
1993{
1994 PyObject *v;
1995
1996 memcpy(x->item, ptr, x->itemsize);
1997 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
1998 if (v == NULL)
1999 return NULL;
2000
2001 if (PyTuple_GET_SIZE(v) == 1) {
2002 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2003 Py_INCREF(tmp);
2004 Py_DECREF(v);
2005 return tmp;
2006 }
2007
2008 return v;
2009}
2010
2011
2012/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002013/* Representations */
2014/****************************************************************************/
2015
2016/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002017static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002018adjust_fmt(const Py_buffer *view)
2019{
2020 const char *fmt;
2021
2022 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2023 if (fmt[0] && fmt[1] == '\0')
2024 return fmt;
2025
2026 PyErr_Format(PyExc_NotImplementedError,
2027 "memoryview: unsupported format %s", view->format);
2028 return NULL;
2029}
2030
2031/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2032static PyObject *
2033tolist_base(const char *ptr, const Py_ssize_t *shape,
2034 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2035 const char *fmt)
2036{
2037 PyObject *lst, *item;
2038 Py_ssize_t i;
2039
2040 lst = PyList_New(shape[0]);
2041 if (lst == NULL)
2042 return NULL;
2043
2044 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002045 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002046 item = unpack_single(xptr, fmt);
2047 if (item == NULL) {
2048 Py_DECREF(lst);
2049 return NULL;
2050 }
2051 PyList_SET_ITEM(lst, i, item);
2052 }
2053
2054 return lst;
2055}
2056
2057/* Unpack a multi-dimensional array into a nested list.
2058 Assumption: ndim >= 1. */
2059static PyObject *
2060tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2061 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2062 const char *fmt)
2063{
2064 PyObject *lst, *item;
2065 Py_ssize_t i;
2066
2067 assert(ndim >= 1);
2068 assert(shape != NULL);
2069 assert(strides != NULL);
2070
2071 if (ndim == 1)
2072 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2073
2074 lst = PyList_New(shape[0]);
2075 if (lst == NULL)
2076 return NULL;
2077
2078 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002079 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002080 item = tolist_rec(xptr, ndim-1, shape+1,
2081 strides+1, suboffsets ? suboffsets+1 : NULL,
2082 fmt);
2083 if (item == NULL) {
2084 Py_DECREF(lst);
2085 return NULL;
2086 }
2087 PyList_SET_ITEM(lst, i, item);
2088 }
2089
2090 return lst;
2091}
2092
2093/* Return a list representation of the memoryview. Currently only buffers
2094 with native format strings are supported. */
2095static PyObject *
2096memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2097{
2098 const Py_buffer *view = &(mv->view);
2099 const char *fmt;
2100
2101 CHECK_RELEASED(mv);
2102
2103 fmt = adjust_fmt(view);
2104 if (fmt == NULL)
2105 return NULL;
2106 if (view->ndim == 0) {
2107 return unpack_single(view->buf, fmt);
2108 }
2109 else if (view->ndim == 1) {
2110 return tolist_base(view->buf, view->shape,
2111 view->strides, view->suboffsets,
2112 fmt);
2113 }
2114 else {
2115 return tolist_rec(view->buf, view->ndim, view->shape,
2116 view->strides, view->suboffsets,
2117 fmt);
2118 }
2119}
2120
2121static PyObject *
2122memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
2123{
2124 Py_buffer *src = VIEW_ADDR(self);
2125 PyObject *bytes = NULL;
2126
2127 CHECK_RELEASED(self);
2128
2129 if (MV_C_CONTIGUOUS(self->flags)) {
2130 return PyBytes_FromStringAndSize(src->buf, src->len);
2131 }
2132
2133 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2134 if (bytes == NULL)
2135 return NULL;
2136
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002137 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002138 Py_DECREF(bytes);
2139 return NULL;
2140 }
2141
2142 return bytes;
2143}
2144
2145static PyObject *
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002146memory_hex(PyMemoryViewObject *self, PyObject *dummy)
2147{
2148 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002149 PyObject *bytes;
2150 PyObject *ret;
2151
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002152 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002153
2154 if (MV_C_CONTIGUOUS(self->flags)) {
2155 return _Py_strhex(src->buf, src->len);
2156 }
2157
2158 bytes = memory_tobytes(self, dummy);
2159 if (bytes == NULL)
2160 return NULL;
2161
Serhiy Storchakafff9a312017-03-21 08:53:25 +02002162 ret = _Py_strhex(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002163 Py_DECREF(bytes);
2164
2165 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002166}
2167
2168static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002169memory_repr(PyMemoryViewObject *self)
2170{
2171 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2172 return PyUnicode_FromFormat("<released memory at %p>", self);
2173 else
2174 return PyUnicode_FromFormat("<memory at %p>", self);
2175}
2176
2177
2178/**************************************************************************/
2179/* Indexing and slicing */
2180/**************************************************************************/
2181
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002182static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002183lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002184{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002185 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002186
2187 assert(view->shape);
2188 assert(view->strides);
2189
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002190 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002191 if (index < 0) {
2192 index += nitems;
2193 }
2194 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002195 PyErr_Format(PyExc_IndexError,
2196 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002197 return NULL;
2198 }
2199
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002200 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002201
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002202 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002203
2204 return ptr;
2205}
2206
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002207/* Get the pointer to the item at index. */
2208static char *
2209ptr_from_index(Py_buffer *view, Py_ssize_t index)
2210{
2211 char *ptr = (char *)view->buf;
2212 return lookup_dimension(view, ptr, 0, index);
2213}
2214
2215/* Get the pointer to the item at tuple. */
2216static char *
2217ptr_from_tuple(Py_buffer *view, PyObject *tup)
2218{
2219 char *ptr = (char *)view->buf;
2220 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2221
2222 if (nindices > view->ndim) {
2223 PyErr_Format(PyExc_TypeError,
2224 "cannot index %zd-dimension view with %zd-element tuple",
2225 view->ndim, nindices);
2226 return NULL;
2227 }
2228
2229 for (dim = 0; dim < nindices; dim++) {
2230 Py_ssize_t index;
2231 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2232 PyExc_IndexError);
2233 if (index == -1 && PyErr_Occurred())
2234 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002235 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002236 if (ptr == NULL)
2237 return NULL;
2238 }
2239 return ptr;
2240}
2241
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002242/* Return the item at index. In a one-dimensional view, this is an object
2243 with the type specified by view->format. Otherwise, the item is a sub-view.
2244 The function is used in memory_subscript() and memory_as_sequence. */
2245static PyObject *
2246memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2247{
2248 Py_buffer *view = &(self->view);
2249 const char *fmt;
2250
2251 CHECK_RELEASED(self);
2252
2253 fmt = adjust_fmt(view);
2254 if (fmt == NULL)
2255 return NULL;
2256
2257 if (view->ndim == 0) {
2258 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2259 return NULL;
2260 }
2261 if (view->ndim == 1) {
2262 char *ptr = ptr_from_index(view, index);
2263 if (ptr == NULL)
2264 return NULL;
2265 return unpack_single(ptr, fmt);
2266 }
2267
2268 PyErr_SetString(PyExc_NotImplementedError,
2269 "multi-dimensional sub-views are not implemented");
2270 return NULL;
2271}
2272
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002273/* Return the item at position *key* (a tuple of indices). */
2274static PyObject *
2275memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2276{
2277 Py_buffer *view = &(self->view);
2278 const char *fmt;
2279 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2280 char *ptr;
2281
2282 CHECK_RELEASED(self);
2283
2284 fmt = adjust_fmt(view);
2285 if (fmt == NULL)
2286 return NULL;
2287
2288 if (nindices < view->ndim) {
2289 PyErr_SetString(PyExc_NotImplementedError,
2290 "sub-views are not implemented");
2291 return NULL;
2292 }
2293 ptr = ptr_from_tuple(view, tup);
2294 if (ptr == NULL)
2295 return NULL;
2296 return unpack_single(ptr, fmt);
2297}
2298
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002299static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002300init_slice(Py_buffer *base, PyObject *key, int dim)
2301{
2302 Py_ssize_t start, stop, step, slicelength;
2303
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002304 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002305 return -1;
2306 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002307 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002308
2309
2310 if (base->suboffsets == NULL || dim == 0) {
2311 adjust_buf:
2312 base->buf = (char *)base->buf + base->strides[dim] * start;
2313 }
2314 else {
2315 Py_ssize_t n = dim-1;
2316 while (n >= 0 && base->suboffsets[n] < 0)
2317 n--;
2318 if (n < 0)
2319 goto adjust_buf; /* all suboffsets are negative */
2320 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2321 }
2322 base->shape[dim] = slicelength;
2323 base->strides[dim] = base->strides[dim] * step;
2324
2325 return 0;
2326}
2327
2328static int
2329is_multislice(PyObject *key)
2330{
2331 Py_ssize_t size, i;
2332
2333 if (!PyTuple_Check(key))
2334 return 0;
2335 size = PyTuple_GET_SIZE(key);
2336 if (size == 0)
2337 return 0;
2338
2339 for (i = 0; i < size; i++) {
2340 PyObject *x = PyTuple_GET_ITEM(key, i);
2341 if (!PySlice_Check(x))
2342 return 0;
2343 }
2344 return 1;
2345}
2346
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002347static Py_ssize_t
2348is_multiindex(PyObject *key)
2349{
2350 Py_ssize_t size, i;
2351
2352 if (!PyTuple_Check(key))
2353 return 0;
2354 size = PyTuple_GET_SIZE(key);
2355 for (i = 0; i < size; i++) {
2356 PyObject *x = PyTuple_GET_ITEM(key, i);
2357 if (!PyIndex_Check(x))
2358 return 0;
2359 }
2360 return 1;
2361}
2362
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002363/* mv[obj] returns an object holding the data for one element if obj
2364 fully indexes the memoryview or another memoryview object if it
2365 does not.
2366
2367 0-d memoryview objects can be referenced using mv[...] or mv[()]
2368 but not with anything else. */
2369static PyObject *
2370memory_subscript(PyMemoryViewObject *self, PyObject *key)
2371{
2372 Py_buffer *view;
2373 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002374
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002375 CHECK_RELEASED(self);
2376
2377 if (view->ndim == 0) {
2378 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2379 const char *fmt = adjust_fmt(view);
2380 if (fmt == NULL)
2381 return NULL;
2382 return unpack_single(view->buf, fmt);
2383 }
2384 else if (key == Py_Ellipsis) {
2385 Py_INCREF(self);
2386 return (PyObject *)self;
2387 }
2388 else {
2389 PyErr_SetString(PyExc_TypeError,
2390 "invalid indexing of 0-dim memory");
2391 return NULL;
2392 }
2393 }
2394
2395 if (PyIndex_Check(key)) {
2396 Py_ssize_t index;
2397 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2398 if (index == -1 && PyErr_Occurred())
2399 return NULL;
2400 return memory_item(self, index);
2401 }
2402 else if (PySlice_Check(key)) {
2403 PyMemoryViewObject *sliced;
2404
2405 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2406 if (sliced == NULL)
2407 return NULL;
2408
2409 if (init_slice(&sliced->view, key, 0) < 0) {
2410 Py_DECREF(sliced);
2411 return NULL;
2412 }
2413 init_len(&sliced->view);
2414 init_flags(sliced);
2415
2416 return (PyObject *)sliced;
2417 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002418 else if (is_multiindex(key)) {
2419 return memory_item_multi(self, key);
2420 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002421 else if (is_multislice(key)) {
2422 PyErr_SetString(PyExc_NotImplementedError,
2423 "multi-dimensional slicing is not implemented");
2424 return NULL;
2425 }
2426
2427 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2428 return NULL;
2429}
2430
2431static int
2432memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2433{
2434 Py_buffer *view = &(self->view);
2435 Py_buffer src;
2436 const char *fmt;
2437 char *ptr;
2438
2439 CHECK_RELEASED_INT(self);
2440
2441 fmt = adjust_fmt(view);
2442 if (fmt == NULL)
2443 return -1;
2444
2445 if (view->readonly) {
2446 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2447 return -1;
2448 }
2449 if (value == NULL) {
2450 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2451 return -1;
2452 }
2453 if (view->ndim == 0) {
2454 if (key == Py_Ellipsis ||
2455 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2456 ptr = (char *)view->buf;
2457 return pack_single(ptr, value, fmt);
2458 }
2459 else {
2460 PyErr_SetString(PyExc_TypeError,
2461 "invalid indexing of 0-dim memory");
2462 return -1;
2463 }
2464 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002465
2466 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002467 Py_ssize_t index;
2468 if (1 < view->ndim) {
2469 PyErr_SetString(PyExc_NotImplementedError,
2470 "sub-views are not implemented");
2471 return -1;
2472 }
2473 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002474 if (index == -1 && PyErr_Occurred())
2475 return -1;
2476 ptr = ptr_from_index(view, index);
2477 if (ptr == NULL)
2478 return -1;
2479 return pack_single(ptr, value, fmt);
2480 }
2481 /* one-dimensional: fast path */
2482 if (PySlice_Check(key) && view->ndim == 1) {
2483 Py_buffer dest; /* sliced view */
2484 Py_ssize_t arrays[3];
2485 int ret = -1;
2486
2487 /* rvalue must be an exporter */
2488 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2489 return ret;
2490
2491 dest = *view;
2492 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2493 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2494 if (view->suboffsets) {
2495 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2496 }
2497
2498 if (init_slice(&dest, key, 0) < 0)
2499 goto end_block;
2500 dest.len = dest.shape[0] * dest.itemsize;
2501
2502 ret = copy_single(&dest, &src);
2503
2504 end_block:
2505 PyBuffer_Release(&src);
2506 return ret;
2507 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002508 if (is_multiindex(key)) {
2509 char *ptr;
2510 if (PyTuple_GET_SIZE(key) < view->ndim) {
2511 PyErr_SetString(PyExc_NotImplementedError,
2512 "sub-views are not implemented");
2513 return -1;
2514 }
2515 ptr = ptr_from_tuple(view, key);
2516 if (ptr == NULL)
2517 return -1;
2518 return pack_single(ptr, value, fmt);
2519 }
2520 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002521 /* Call memory_subscript() to produce a sliced lvalue, then copy
2522 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2523 PyErr_SetString(PyExc_NotImplementedError,
2524 "memoryview slice assignments are currently restricted "
2525 "to ndim = 1");
2526 return -1;
2527 }
2528
2529 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2530 return -1;
2531}
2532
2533static Py_ssize_t
2534memory_length(PyMemoryViewObject *self)
2535{
2536 CHECK_RELEASED_INT(self);
2537 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2538}
2539
2540/* As mapping */
2541static PyMappingMethods memory_as_mapping = {
2542 (lenfunc)memory_length, /* mp_length */
2543 (binaryfunc)memory_subscript, /* mp_subscript */
2544 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2545};
2546
2547/* As sequence */
2548static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002549 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002550 0, /* sq_concat */
2551 0, /* sq_repeat */
2552 (ssizeargfunc)memory_item, /* sq_item */
2553};
2554
2555
2556/**************************************************************************/
2557/* Comparisons */
2558/**************************************************************************/
2559
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002560#define MV_COMPARE_EX -1 /* exception */
2561#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2562
2563/* Translate a StructError to "not equal". Preserve other exceptions. */
2564static int
2565fix_struct_error_int(void)
2566{
2567 assert(PyErr_Occurred());
2568 /* XXX Cannot get at StructError directly? */
2569 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2570 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2571 return MV_COMPARE_EX;
2572 }
2573 /* StructError: invalid or unknown format -> not equal */
2574 PyErr_Clear();
2575 return 0;
2576}
2577
2578/* Unpack and compare single items of p and q using the struct module. */
2579static int
2580struct_unpack_cmp(const char *p, const char *q,
2581 struct unpacker *unpack_p, struct unpacker *unpack_q)
2582{
2583 PyObject *v, *w;
2584 int ret;
2585
2586 /* At this point any exception from the struct module should not be
2587 StructError, since both formats have been accepted already. */
2588 v = struct_unpack_single(p, unpack_p);
2589 if (v == NULL)
2590 return MV_COMPARE_EX;
2591
2592 w = struct_unpack_single(q, unpack_q);
2593 if (w == NULL) {
2594 Py_DECREF(v);
2595 return MV_COMPARE_EX;
2596 }
2597
2598 /* MV_COMPARE_EX == -1: exceptions are preserved */
2599 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2600 Py_DECREF(v);
2601 Py_DECREF(w);
2602
2603 return ret;
2604}
2605
2606/* Unpack and compare single items of p and q. If both p and q have the same
2607 single element native format, the comparison uses a fast path (gcc creates
2608 a jump table and converts memcpy into simple assignments on x86/x64).
2609
2610 Otherwise, the comparison is delegated to the struct module, which is
2611 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002612#define CMP_SINGLE(p, q, type) \
2613 do { \
2614 type x; \
2615 type y; \
2616 memcpy((char *)&x, p, sizeof x); \
2617 memcpy((char *)&y, q, sizeof y); \
2618 equal = (x == y); \
2619 } while (0)
2620
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002621static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002622unpack_cmp(const char *p, const char *q, char fmt,
2623 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002624{
2625 int equal;
2626
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002627 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002628
2629 /* signed integers and fast path for 'B' */
2630 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2631 case 'b': return *((signed char *)p) == *((signed char *)q);
2632 case 'h': CMP_SINGLE(p, q, short); return equal;
2633 case 'i': CMP_SINGLE(p, q, int); return equal;
2634 case 'l': CMP_SINGLE(p, q, long); return equal;
2635
2636 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002637 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002638
2639 /* unsigned integers */
2640 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2641 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2642 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2643
2644 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002645 case 'q': CMP_SINGLE(p, q, long long); return equal;
2646 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002647
2648 /* ssize_t and size_t */
2649 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2650 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2651
2652 /* floats */
2653 /* XXX DBL_EPSILON? */
2654 case 'f': CMP_SINGLE(p, q, float); return equal;
2655 case 'd': CMP_SINGLE(p, q, double); return equal;
2656
2657 /* bytes object */
2658 case 'c': return *p == *q;
2659
2660 /* pointer */
2661 case 'P': CMP_SINGLE(p, q, void *); return equal;
2662
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002663 /* use the struct module */
2664 case '_':
2665 assert(unpack_p);
2666 assert(unpack_q);
2667 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002668 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002669
2670 /* NOT REACHED */
2671 PyErr_SetString(PyExc_RuntimeError,
2672 "memoryview: internal error in richcompare");
2673 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002674}
2675
2676/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2677static int
2678cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2679 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2680 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002681 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002682{
2683 Py_ssize_t i;
2684 int equal;
2685
2686 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002687 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2688 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002689 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002690 if (equal <= 0)
2691 return equal;
2692 }
2693
2694 return 1;
2695}
2696
2697/* Recursively compare two multi-dimensional arrays that have the same
2698 logical structure. Assumption: ndim >= 1. */
2699static int
2700cmp_rec(const char *p, const char *q,
2701 Py_ssize_t ndim, const Py_ssize_t *shape,
2702 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2703 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002704 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002705{
2706 Py_ssize_t i;
2707 int equal;
2708
2709 assert(ndim >= 1);
2710 assert(shape != NULL);
2711 assert(pstrides != NULL);
2712 assert(qstrides != NULL);
2713
2714 if (ndim == 1) {
2715 return cmp_base(p, q, shape,
2716 pstrides, psuboffsets,
2717 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002718 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002719 }
2720
2721 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002722 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2723 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002724 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2725 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2726 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002727 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002728 if (equal <= 0)
2729 return equal;
2730 }
2731
2732 return 1;
2733}
2734
2735static PyObject *
2736memory_richcompare(PyObject *v, PyObject *w, int op)
2737{
2738 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002739 Py_buffer wbuf, *vv;
2740 Py_buffer *ww = NULL;
2741 struct unpacker *unpack_v = NULL;
2742 struct unpacker *unpack_w = NULL;
2743 char vfmt, wfmt;
2744 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002745
2746 if (op != Py_EQ && op != Py_NE)
2747 goto result; /* Py_NotImplemented */
2748
2749 assert(PyMemoryView_Check(v));
2750 if (BASE_INACCESSIBLE(v)) {
2751 equal = (v == w);
2752 goto result;
2753 }
2754 vv = VIEW_ADDR(v);
2755
2756 if (PyMemoryView_Check(w)) {
2757 if (BASE_INACCESSIBLE(w)) {
2758 equal = (v == w);
2759 goto result;
2760 }
2761 ww = VIEW_ADDR(w);
2762 }
2763 else {
2764 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2765 PyErr_Clear();
2766 goto result; /* Py_NotImplemented */
2767 }
2768 ww = &wbuf;
2769 }
2770
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002771 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002772 PyErr_Clear();
2773 equal = 0;
2774 goto result;
2775 }
2776
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002777 /* Use fast unpacking for identical primitive C type formats. */
2778 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2779 vfmt = '_';
2780 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2781 wfmt = '_';
2782 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2783 /* Use struct module unpacking. NOTE: Even for equal format strings,
2784 memcmp() cannot be used for item comparison since it would give
2785 incorrect results in the case of NaNs or uninitialized padding
2786 bytes. */
2787 vfmt = '_';
2788 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2789 if (unpack_v == NULL) {
2790 equal = fix_struct_error_int();
2791 goto result;
2792 }
2793 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2794 if (unpack_w == NULL) {
2795 equal = fix_struct_error_int();
2796 goto result;
2797 }
2798 }
2799
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002800 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002801 equal = unpack_cmp(vv->buf, ww->buf,
2802 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002803 }
2804 else if (vv->ndim == 1) {
2805 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2806 vv->strides, vv->suboffsets,
2807 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002808 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002809 }
2810 else {
2811 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2812 vv->strides, vv->suboffsets,
2813 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002814 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002815 }
2816
2817result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002818 if (equal < 0) {
2819 if (equal == MV_COMPARE_NOT_IMPL)
2820 res = Py_NotImplemented;
2821 else /* exception */
2822 res = NULL;
2823 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002824 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2825 res = Py_True;
2826 else
2827 res = Py_False;
2828
2829 if (ww == &wbuf)
2830 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002831
2832 unpacker_free(unpack_v);
2833 unpacker_free(unpack_w);
2834
2835 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002836 return res;
2837}
2838
2839/**************************************************************************/
2840/* Hash */
2841/**************************************************************************/
2842
2843static Py_hash_t
2844memory_hash(PyMemoryViewObject *self)
2845{
2846 if (self->hash == -1) {
2847 Py_buffer *view = &self->view;
2848 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002849 Py_ssize_t ret;
2850 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002851
2852 CHECK_RELEASED_INT(self);
2853
2854 if (!view->readonly) {
2855 PyErr_SetString(PyExc_ValueError,
2856 "cannot hash writable memoryview object");
2857 return -1;
2858 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002859 ret = get_native_fmtchar(&fmt, view->format);
2860 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2861 PyErr_SetString(PyExc_ValueError,
2862 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2863 return -1;
2864 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002865 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2866 /* Keep the original error message */
2867 return -1;
2868 }
2869
2870 if (!MV_C_CONTIGUOUS(self->flags)) {
2871 mem = PyMem_Malloc(view->len);
2872 if (mem == NULL) {
2873 PyErr_NoMemory();
2874 return -1;
2875 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002876 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002877 PyMem_Free(mem);
2878 return -1;
2879 }
2880 }
2881
2882 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002883 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002884
2885 if (mem != view->buf)
2886 PyMem_Free(mem);
2887 }
2888
2889 return self->hash;
2890}
2891
2892
2893/**************************************************************************/
2894/* getters */
2895/**************************************************************************/
2896
2897static PyObject *
2898_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2899{
2900 int i;
2901 PyObject *o;
2902 PyObject *intTuple;
2903
2904 if (vals == NULL)
2905 return PyTuple_New(0);
2906
2907 intTuple = PyTuple_New(len);
2908 if (!intTuple)
2909 return NULL;
2910 for (i=0; i<len; i++) {
2911 o = PyLong_FromSsize_t(vals[i]);
2912 if (!o) {
2913 Py_DECREF(intTuple);
2914 return NULL;
2915 }
2916 PyTuple_SET_ITEM(intTuple, i, o);
2917 }
2918 return intTuple;
2919}
2920
2921static PyObject *
2922memory_obj_get(PyMemoryViewObject *self)
2923{
2924 Py_buffer *view = &self->view;
2925
2926 CHECK_RELEASED(self);
2927 if (view->obj == NULL) {
2928 Py_RETURN_NONE;
2929 }
2930 Py_INCREF(view->obj);
2931 return view->obj;
2932}
2933
2934static PyObject *
2935memory_nbytes_get(PyMemoryViewObject *self)
2936{
2937 CHECK_RELEASED(self);
2938 return PyLong_FromSsize_t(self->view.len);
2939}
2940
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002941static PyObject *
2942memory_format_get(PyMemoryViewObject *self)
2943{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002944 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002945 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002946}
2947
2948static PyObject *
2949memory_itemsize_get(PyMemoryViewObject *self)
2950{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002951 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002952 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002953}
2954
2955static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002956memory_shape_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.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002960}
2961
2962static PyObject *
2963memory_strides_get(PyMemoryViewObject *self)
2964{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002965 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002966 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002967}
2968
2969static PyObject *
2970memory_suboffsets_get(PyMemoryViewObject *self)
2971{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002972 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002973 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002974}
2975
2976static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002977memory_readonly_get(PyMemoryViewObject *self)
2978{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002979 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002980 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002981}
2982
2983static PyObject *
2984memory_ndim_get(PyMemoryViewObject *self)
2985{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002986 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002987 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002988}
2989
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002990static PyObject *
2991memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2992{
2993 CHECK_RELEASED(self);
2994 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
2995}
2996
2997static PyObject *
2998memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2999{
3000 CHECK_RELEASED(self);
3001 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3002}
3003
3004static PyObject *
3005memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3006{
3007 CHECK_RELEASED(self);
3008 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3009}
3010
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003011PyDoc_STRVAR(memory_obj_doc,
3012 "The underlying object of the memoryview.");
3013PyDoc_STRVAR(memory_nbytes_doc,
3014 "The amount of space in bytes that the array would use in\n"
3015 " a contiguous representation.");
3016PyDoc_STRVAR(memory_readonly_doc,
3017 "A bool indicating whether the memory is read only.");
3018PyDoc_STRVAR(memory_itemsize_doc,
3019 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003020PyDoc_STRVAR(memory_format_doc,
3021 "A string containing the format (in struct module style)\n"
3022 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003023PyDoc_STRVAR(memory_ndim_doc,
3024 "An integer indicating how many dimensions of a multi-dimensional\n"
3025 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003026PyDoc_STRVAR(memory_shape_doc,
3027 "A tuple of ndim integers giving the shape of the memory\n"
3028 " as an N-dimensional array.");
3029PyDoc_STRVAR(memory_strides_doc,
3030 "A tuple of ndim integers giving the size in bytes to access\n"
3031 " each element for each dimension of the array.");
3032PyDoc_STRVAR(memory_suboffsets_doc,
3033 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003034PyDoc_STRVAR(memory_c_contiguous_doc,
3035 "A bool indicating whether the memory is C contiguous.");
3036PyDoc_STRVAR(memory_f_contiguous_doc,
3037 "A bool indicating whether the memory is Fortran contiguous.");
3038PyDoc_STRVAR(memory_contiguous_doc,
3039 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003040
Stefan Krahbcaf5992014-05-18 00:35:09 +02003041
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003042static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003043 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3044 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003045 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3046 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3047 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3048 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3049 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3050 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3051 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003052 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3053 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3054 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003055 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003056};
3057
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003058PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003059"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003060\n\
3061Release the underlying buffer exposed by the memoryview object.");
3062PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003063"tobytes($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003064\n\
3065Return the data in the buffer as a byte string.");
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003066PyDoc_STRVAR(memory_hex_doc,
3067"hex($self, /)\n--\n\
3068\n\
3069Return the data in the buffer as a string of hexadecimal numbers.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003070PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003071"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003072\n\
3073Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003074PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003075"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003076\n\
3077Cast a memoryview to a new format or shape.");
Antoine Pitrou480ab052018-04-14 19:49:21 +02003078PyDoc_STRVAR(memory_toreadonly_doc,
3079"toreadonly($self, /)\n--\n\
3080\n\
3081Return a readonly version of the memoryview.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003082
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003083static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003084 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3085 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003086 {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003087 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003088 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Antoine Pitrou480ab052018-04-14 19:49:21 +02003089 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003090 {"__enter__", memory_enter, METH_NOARGS, NULL},
3091 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003092 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003093};
3094
3095
3096PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003097 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003098 "memoryview", /* tp_name */
3099 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3100 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003101 (destructor)memory_dealloc, /* tp_dealloc */
3102 0, /* tp_print */
3103 0, /* tp_getattr */
3104 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003105 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003106 (reprfunc)memory_repr, /* tp_repr */
3107 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003108 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003109 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003110 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003111 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003112 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003113 PyObject_GenericGetAttr, /* tp_getattro */
3114 0, /* tp_setattro */
3115 &memory_as_buffer, /* tp_as_buffer */
3116 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3117 memory_doc, /* tp_doc */
3118 (traverseproc)memory_traverse, /* tp_traverse */
3119 (inquiry)memory_clear, /* tp_clear */
3120 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003121 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003122 0, /* tp_iter */
3123 0, /* tp_iternext */
3124 memory_methods, /* tp_methods */
3125 0, /* tp_members */
3126 memory_getsetlist, /* tp_getset */
3127 0, /* tp_base */
3128 0, /* tp_dict */
3129 0, /* tp_descr_get */
3130 0, /* tp_descr_set */
3131 0, /* tp_dictoffset */
3132 0, /* tp_init */
3133 0, /* tp_alloc */
3134 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003135};