blob: 0f528eec68bc41cf01fc07f4c9653dabe4da3c8c [file] [log] [blame]
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001/* Memoryview object implementation */
2
3#include "Python.h"
Victor Stinnerbcda8f12018-11-21 22:27:47 +01004#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01005#include "pycore_pymem.h"
6#include "pycore_pystate.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +00007#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +01008#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00009
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000010
Stefan Krah9a2d99e2012-02-25 12:24:21 +010011/****************************************************************************/
12/* ManagedBuffer Object */
13/****************************************************************************/
14
15/*
16 ManagedBuffer Object:
17 ---------------------
18
19 The purpose of this object is to facilitate the handling of chained
20 memoryviews that have the same underlying exporting object. PEP-3118
21 allows the underlying object to change while a view is exported. This
22 could lead to unexpected results when constructing a new memoryview
23 from an existing memoryview.
24
25 Rather than repeatedly redirecting buffer requests to the original base
26 object, all chained memoryviews use a single buffer snapshot. This
27 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
28
29 Ownership rules:
30 ----------------
31
32 The master buffer inside a managed buffer is filled in by the original
33 base object. shape, strides, suboffsets and format are read-only for
34 all consumers.
35
36 A memoryview's buffer is a private copy of the exporter's buffer. shape,
37 strides and suboffsets belong to the memoryview and are thus writable.
38
39 If a memoryview itself exports several buffers via memory_getbuf(), all
40 buffer copies share shape, strides and suboffsets. In this case, the
41 arrays are NOT writable.
42
43 Reference count assumptions:
44 ----------------------------
45
46 The 'obj' member of a Py_buffer must either be NULL or refer to the
47 exporting base object. In the Python codebase, all getbufferprocs
48 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
49
50 PyBuffer_Release() decrements view.obj (if non-NULL), so the
51 releasebufferprocs must NOT decrement view.obj.
52*/
53
54
Stefan Krah9a2d99e2012-02-25 12:24:21 +010055#define CHECK_MBUF_RELEASED(mbuf) \
56 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
57 PyErr_SetString(PyExc_ValueError, \
58 "operation forbidden on released memoryview object"); \
59 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000060 }
61
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000062
Benjamin Peterson82cce4c2016-09-08 11:56:06 -070063static inline _PyManagedBufferObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +010064mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000065{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010066 _PyManagedBufferObject *mbuf;
67
68 mbuf = (_PyManagedBufferObject *)
69 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
70 if (mbuf == NULL)
71 return NULL;
72 mbuf->flags = 0;
73 mbuf->exports = 0;
74 mbuf->master.obj = NULL;
75 _PyObject_GC_TRACK(mbuf);
76
77 return mbuf;
78}
79
80static PyObject *
81_PyManagedBuffer_FromObject(PyObject *base)
82{
83 _PyManagedBufferObject *mbuf;
84
85 mbuf = mbuf_alloc();
86 if (mbuf == NULL)
87 return NULL;
88
89 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +010090 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +010091 Py_DECREF(mbuf);
92 return NULL;
93 }
94
Stefan Krah9a2d99e2012-02-25 12:24:21 +010095 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +000096}
97
98static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +010099mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000100{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100101 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
102 return;
103
104 /* NOTE: at this point self->exports can still be > 0 if this function
105 is called from mbuf_clear() to break up a reference cycle. */
106 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
107
108 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
109 _PyObject_GC_UNTRACK(self);
110 PyBuffer_Release(&self->master);
111}
112
113static void
114mbuf_dealloc(_PyManagedBufferObject *self)
115{
116 assert(self->exports == 0);
117 mbuf_release(self);
118 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
119 PyMem_Free(self->master.format);
120 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000121}
122
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000123static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100124mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000125{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100126 Py_VISIT(self->master.obj);
127 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000128}
129
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100130static int
131mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000132{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100133 assert(self->exports >= 0);
134 mbuf_release(self);
135 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000136}
137
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100138PyTypeObject _PyManagedBuffer_Type = {
139 PyVarObject_HEAD_INIT(&PyType_Type, 0)
140 "managedbuffer",
141 sizeof(_PyManagedBufferObject),
142 0,
143 (destructor)mbuf_dealloc, /* tp_dealloc */
144 0, /* tp_print */
145 0, /* tp_getattr */
146 0, /* tp_setattr */
147 0, /* tp_reserved */
148 0, /* tp_repr */
149 0, /* tp_as_number */
150 0, /* tp_as_sequence */
151 0, /* tp_as_mapping */
152 0, /* tp_hash */
153 0, /* tp_call */
154 0, /* tp_str */
155 PyObject_GenericGetAttr, /* tp_getattro */
156 0, /* tp_setattro */
157 0, /* tp_as_buffer */
158 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
159 0, /* tp_doc */
160 (traverseproc)mbuf_traverse, /* tp_traverse */
161 (inquiry)mbuf_clear /* tp_clear */
162};
163
164
165/****************************************************************************/
166/* MemoryView Object */
167/****************************************************************************/
168
169/* In the process of breaking reference cycles mbuf_release() can be
170 called before memory_release(). */
171#define BASE_INACCESSIBLE(mv) \
172 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
173 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
174
175#define CHECK_RELEASED(mv) \
176 if (BASE_INACCESSIBLE(mv)) { \
177 PyErr_SetString(PyExc_ValueError, \
178 "operation forbidden on released memoryview object"); \
179 return NULL; \
180 }
181
182#define CHECK_RELEASED_INT(mv) \
183 if (BASE_INACCESSIBLE(mv)) { \
184 PyErr_SetString(PyExc_ValueError, \
185 "operation forbidden on released memoryview object"); \
186 return -1; \
187 }
188
189#define CHECK_LIST_OR_TUPLE(v) \
190 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
191 PyErr_SetString(PyExc_TypeError, \
192 #v " must be a list or a tuple"); \
193 return NULL; \
194 }
195
196#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
197
198/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100199#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100200/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100201#define ADJUST_PTR(ptr, suboffsets, dim) \
202 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100203
204/* Memoryview buffer properties */
205#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
206#define MV_F_CONTIGUOUS(flags) \
207 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
208#define MV_ANY_CONTIGUOUS(flags) \
209 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
210
211/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
212#define MV_CONTIGUOUS_NDIM1(view) \
213 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
214
215/* getbuffer() requests */
216#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
217#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
218#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
219#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
220#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
221#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
222#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
223#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
224
225
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000226PyDoc_STRVAR(memory_doc,
Stefan Krah195319e2016-12-30 12:23:35 +0100227"memoryview(object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000228\n\
229Create a new memoryview object which references the given object.");
230
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100231
232/**************************************************************************/
233/* Copy memoryview buffers */
234/**************************************************************************/
235
236/* The functions in this section take a source and a destination buffer
237 with the same logical structure: format, itemsize, ndim and shape
238 are identical, with ndim > 0.
239
240 NOTE: All buffers are assumed to have PyBUF_FULL information, which
241 is the case for memoryviews! */
242
243
244/* Assumptions: ndim >= 1. The macro tests for a corner case that should
245 perhaps be explicitly forbidden in the PEP. */
246#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
247 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
248
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700249static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000250last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100251{
252 assert(dest->ndim > 0 && src->ndim > 0);
253 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
254 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
255 dest->strides[dest->ndim-1] == dest->itemsize &&
256 src->strides[src->ndim-1] == src->itemsize);
257}
258
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000259/* This is not a general function for determining format equivalence.
260 It is used in copy_single() and copy_buffer() to weed out non-matching
261 formats. Skipping the '@' character is specifically used in slice
262 assignments, where the lvalue is already known to have a single character
263 format. This is a performance hack that could be rewritten (if properly
264 benchmarked). */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700265static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000266equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100267{
268 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100269
270 assert(dest->format && src->format);
271 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
272 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
273
274 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000275 dest->itemsize != src->itemsize) {
276 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100277 }
278
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000279 return 1;
280}
281
282/* Two shapes are equivalent if they are either equal or identical up
283 to a zero element at the same position. For example, in NumPy arrays
284 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700285static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000286equiv_shape(const Py_buffer *dest, const Py_buffer *src)
287{
288 int i;
289
290 if (dest->ndim != src->ndim)
291 return 0;
292
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100293 for (i = 0; i < dest->ndim; i++) {
294 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000295 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100296 if (dest->shape[i] == 0)
297 break;
298 }
299
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000300 return 1;
301}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100302
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000303/* Check that the logical structure of the destination and source buffers
304 is identical. */
305static int
306equiv_structure(const Py_buffer *dest, const Py_buffer *src)
307{
308 if (!equiv_format(dest, src) ||
309 !equiv_shape(dest, src)) {
310 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100311 "memoryview assignment: lvalue and rvalue have different "
312 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000313 return 0;
314 }
315
316 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100317}
318
319/* Base case for recursive multi-dimensional copying. Contiguous arrays are
320 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
321 sizeof(mem) == shape[0] * itemsize. */
322static void
323copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
324 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
325 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
326 char *mem)
327{
328 if (mem == NULL) { /* contiguous */
329 Py_ssize_t size = shape[0] * itemsize;
330 if (dptr + size < sptr || sptr + size < dptr)
331 memcpy(dptr, sptr, size); /* no overlapping */
332 else
333 memmove(dptr, sptr, size);
334 }
335 else {
336 char *p;
337 Py_ssize_t i;
338 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100339 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100340 memcpy(p, xsptr, itemsize);
341 }
342 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100343 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100344 memcpy(xdptr, p, itemsize);
345 }
346 }
347
348}
349
350/* Recursively copy a source buffer to a destination buffer. The two buffers
351 have the same ndim, shape and itemsize. */
352static void
353copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
354 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
355 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
356 char *mem)
357{
358 Py_ssize_t i;
359
360 assert(ndim >= 1);
361
362 if (ndim == 1) {
363 copy_base(shape, itemsize,
364 dptr, dstrides, dsuboffsets,
365 sptr, sstrides, ssuboffsets,
366 mem);
367 return;
368 }
369
370 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100371 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
372 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100373
374 copy_rec(shape+1, ndim-1, itemsize,
375 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
376 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
377 mem);
378 }
379}
380
381/* Faster copying of one-dimensional arrays. */
382static int
383copy_single(Py_buffer *dest, Py_buffer *src)
384{
385 char *mem = NULL;
386
387 assert(dest->ndim == 1);
388
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000389 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100390 return -1;
391
392 if (!last_dim_is_contiguous(dest, src)) {
393 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
394 if (mem == NULL) {
395 PyErr_NoMemory();
396 return -1;
397 }
398 }
399
400 copy_base(dest->shape, dest->itemsize,
401 dest->buf, dest->strides, dest->suboffsets,
402 src->buf, src->strides, src->suboffsets,
403 mem);
404
405 if (mem)
406 PyMem_Free(mem);
407
408 return 0;
409}
410
411/* Recursively copy src to dest. Both buffers must have the same basic
412 structure. Copying is atomic, the function never fails with a partial
413 copy. */
414static int
415copy_buffer(Py_buffer *dest, Py_buffer *src)
416{
417 char *mem = NULL;
418
419 assert(dest->ndim > 0);
420
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000421 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100422 return -1;
423
424 if (!last_dim_is_contiguous(dest, src)) {
425 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
426 if (mem == NULL) {
427 PyErr_NoMemory();
428 return -1;
429 }
430 }
431
432 copy_rec(dest->shape, dest->ndim, dest->itemsize,
433 dest->buf, dest->strides, dest->suboffsets,
434 src->buf, src->strides, src->suboffsets,
435 mem);
436
437 if (mem)
438 PyMem_Free(mem);
439
440 return 0;
441}
442
443/* Initialize strides for a C-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700444static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100445init_strides_from_shape(Py_buffer *view)
446{
447 Py_ssize_t i;
448
449 assert(view->ndim > 0);
450
451 view->strides[view->ndim-1] = view->itemsize;
452 for (i = view->ndim-2; i >= 0; i--)
453 view->strides[i] = view->strides[i+1] * view->shape[i+1];
454}
455
456/* Initialize strides for a Fortran-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700457static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100458init_fortran_strides_from_shape(Py_buffer *view)
459{
460 Py_ssize_t i;
461
462 assert(view->ndim > 0);
463
464 view->strides[0] = view->itemsize;
465 for (i = 1; i < view->ndim; i++)
466 view->strides[i] = view->strides[i-1] * view->shape[i-1];
467}
468
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200469/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
470 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100471 len(mem) == src->len. */
472static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200473buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100474{
475 Py_buffer dest;
476 Py_ssize_t *strides;
477 int ret;
478
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200479 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100480 assert(src->shape != NULL);
481 assert(src->strides != NULL);
482
483 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
484 if (strides == NULL) {
485 PyErr_NoMemory();
486 return -1;
487 }
488
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200489 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100490 dest = *src;
491 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200492 /* shape is constant and shared: the logical representation of the
493 array is unaltered. */
494
495 /* The physical representation determined by strides (and possibly
496 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100497 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200498 if (order == 'C' || order == 'A') {
499 init_strides_from_shape(&dest);
500 }
501 else {
502 init_fortran_strides_from_shape(&dest);
503 }
504
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100505 dest.suboffsets = NULL;
506
507 ret = copy_buffer(&dest, src);
508
509 PyMem_Free(strides);
510 return ret;
511}
512
513
514/****************************************************************************/
515/* Constructors */
516/****************************************************************************/
517
518/* Initialize values that are shared with the managed buffer. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700519static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100520init_shared_values(Py_buffer *dest, const Py_buffer *src)
521{
522 dest->obj = src->obj;
523 dest->buf = src->buf;
524 dest->len = src->len;
525 dest->itemsize = src->itemsize;
526 dest->readonly = src->readonly;
527 dest->format = src->format ? src->format : "B";
528 dest->internal = src->internal;
529}
530
531/* Copy shape and strides. Reconstruct missing values. */
532static void
533init_shape_strides(Py_buffer *dest, const Py_buffer *src)
534{
535 Py_ssize_t i;
536
537 if (src->ndim == 0) {
538 dest->shape = NULL;
539 dest->strides = NULL;
540 return;
541 }
542 if (src->ndim == 1) {
543 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
544 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
545 return;
546 }
547
548 for (i = 0; i < src->ndim; i++)
549 dest->shape[i] = src->shape[i];
550 if (src->strides) {
551 for (i = 0; i < src->ndim; i++)
552 dest->strides[i] = src->strides[i];
553 }
554 else {
555 init_strides_from_shape(dest);
556 }
557}
558
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700559static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100560init_suboffsets(Py_buffer *dest, const Py_buffer *src)
561{
562 Py_ssize_t i;
563
564 if (src->suboffsets == NULL) {
565 dest->suboffsets = NULL;
566 return;
567 }
568 for (i = 0; i < src->ndim; i++)
569 dest->suboffsets[i] = src->suboffsets[i];
570}
571
572/* len = product(shape) * itemsize */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700573static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100574init_len(Py_buffer *view)
575{
576 Py_ssize_t i, len;
577
578 len = 1;
579 for (i = 0; i < view->ndim; i++)
580 len *= view->shape[i];
581 len *= view->itemsize;
582
583 view->len = len;
584}
585
586/* Initialize memoryview buffer properties. */
587static void
588init_flags(PyMemoryViewObject *mv)
589{
590 const Py_buffer *view = &mv->view;
591 int flags = 0;
592
593 switch (view->ndim) {
594 case 0:
595 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
596 _Py_MEMORYVIEW_FORTRAN);
597 break;
598 case 1:
599 if (MV_CONTIGUOUS_NDIM1(view))
600 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
601 break;
602 default:
603 if (PyBuffer_IsContiguous(view, 'C'))
604 flags |= _Py_MEMORYVIEW_C;
605 if (PyBuffer_IsContiguous(view, 'F'))
606 flags |= _Py_MEMORYVIEW_FORTRAN;
607 break;
608 }
609
610 if (view->suboffsets) {
611 flags |= _Py_MEMORYVIEW_PIL;
612 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
613 }
614
615 mv->flags = flags;
616}
617
618/* Allocate a new memoryview and perform basic initialization. New memoryviews
619 are exclusively created through the mbuf_add functions. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700620static inline PyMemoryViewObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100621memory_alloc(int ndim)
622{
623 PyMemoryViewObject *mv;
624
625 mv = (PyMemoryViewObject *)
626 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
627 if (mv == NULL)
628 return NULL;
629
630 mv->mbuf = NULL;
631 mv->hash = -1;
632 mv->flags = 0;
633 mv->exports = 0;
634 mv->view.ndim = ndim;
635 mv->view.shape = mv->ob_array;
636 mv->view.strides = mv->ob_array + ndim;
637 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100638 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100639
640 _PyObject_GC_TRACK(mv);
641 return mv;
642}
643
644/*
645 Return a new memoryview that is registered with mbuf. If src is NULL,
646 use mbuf->master as the underlying buffer. Otherwise, use src.
647
648 The new memoryview has full buffer information: shape and strides
649 are always present, suboffsets as needed. Arrays are copied to
650 the memoryview's ob_array field.
651 */
652static PyObject *
653mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
654{
655 PyMemoryViewObject *mv;
656 Py_buffer *dest;
657
658 if (src == NULL)
659 src = &mbuf->master;
660
661 if (src->ndim > PyBUF_MAX_NDIM) {
662 PyErr_SetString(PyExc_ValueError,
663 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200664 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100665 return NULL;
666 }
667
668 mv = memory_alloc(src->ndim);
669 if (mv == NULL)
670 return NULL;
671
672 dest = &mv->view;
673 init_shared_values(dest, src);
674 init_shape_strides(dest, src);
675 init_suboffsets(dest, src);
676 init_flags(mv);
677
678 mv->mbuf = mbuf;
679 Py_INCREF(mbuf);
680 mbuf->exports++;
681
682 return (PyObject *)mv;
683}
684
685/* Register an incomplete view: shape, strides, suboffsets and flags still
686 need to be initialized. Use 'ndim' instead of src->ndim to determine the
687 size of the memoryview's ob_array.
688
689 Assumption: ndim <= PyBUF_MAX_NDIM. */
690static PyObject *
691mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
692 int ndim)
693{
694 PyMemoryViewObject *mv;
695 Py_buffer *dest;
696
697 if (src == NULL)
698 src = &mbuf->master;
699
700 assert(ndim <= PyBUF_MAX_NDIM);
701
702 mv = memory_alloc(ndim);
703 if (mv == NULL)
704 return NULL;
705
706 dest = &mv->view;
707 init_shared_values(dest, src);
708
709 mv->mbuf = mbuf;
710 Py_INCREF(mbuf);
711 mbuf->exports++;
712
713 return (PyObject *)mv;
714}
715
716/* Expose a raw memory area as a view of contiguous bytes. flags can be
717 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
718 The memoryview has complete buffer information. */
719PyObject *
720PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
721{
722 _PyManagedBufferObject *mbuf;
723 PyObject *mv;
724 int readonly;
725
726 assert(mem != NULL);
727 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
728
729 mbuf = mbuf_alloc();
730 if (mbuf == NULL)
731 return NULL;
732
733 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
734 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
735 PyBUF_FULL_RO);
736
737 mv = mbuf_add_view(mbuf, NULL);
738 Py_DECREF(mbuf);
739
740 return mv;
741}
742
743/* Create a memoryview from a given Py_buffer. For simple byte views,
744 PyMemoryView_FromMemory() should be used instead.
745 This function is the only entry point that can create a master buffer
746 without full information. Because of this fact init_shape_strides()
747 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000748PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000749PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000750{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100751 _PyManagedBufferObject *mbuf;
752 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000753
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000754 if (info->buf == NULL) {
755 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100756 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000757 return NULL;
758 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100759
760 mbuf = mbuf_alloc();
761 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000762 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100763
764 /* info->obj is either NULL or a borrowed reference. This reference
765 should not be decremented in PyBuffer_Release(). */
766 mbuf->master = *info;
767 mbuf->master.obj = NULL;
768
769 mv = mbuf_add_view(mbuf, NULL);
770 Py_DECREF(mbuf);
771
772 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000773}
774
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100775/* Create a memoryview from an object that implements the buffer protocol.
776 If the object is a memoryview, the new memoryview must be registered
777 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000778PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100779PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000780{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100781 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000782
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100783 if (PyMemoryView_Check(v)) {
784 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
785 CHECK_RELEASED(mv);
786 return mbuf_add_view(mv->mbuf, &mv->view);
787 }
788 else if (PyObject_CheckBuffer(v)) {
789 PyObject *ret;
790 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
791 if (mbuf == NULL)
792 return NULL;
793 ret = mbuf_add_view(mbuf, NULL);
794 Py_DECREF(mbuf);
795 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000796 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000797
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100798 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400799 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100800 Py_TYPE(v)->tp_name);
801 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000802}
803
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100804/* Copy the format string from a base object that might vanish. */
805static int
806mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
807{
808 if (fmt != NULL) {
809 char *cp = PyMem_Malloc(strlen(fmt)+1);
810 if (cp == NULL) {
811 PyErr_NoMemory();
812 return -1;
813 }
814 mbuf->master.format = strcpy(cp, fmt);
815 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
816 }
817
818 return 0;
819}
820
821/*
822 Return a memoryview that is based on a contiguous copy of src.
823 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
824
825 Ownership rules:
826 1) As usual, the returned memoryview has a private copy
827 of src->shape, src->strides and src->suboffsets.
828 2) src->format is copied to the master buffer and released
829 in mbuf_dealloc(). The releasebufferproc of the bytes
830 object is NULL, so it does not matter that mbuf_release()
831 passes the altered format pointer to PyBuffer_Release().
832*/
833static PyObject *
834memory_from_contiguous_copy(Py_buffer *src, char order)
835{
836 _PyManagedBufferObject *mbuf;
837 PyMemoryViewObject *mv;
838 PyObject *bytes;
839 Py_buffer *dest;
840 int i;
841
842 assert(src->ndim > 0);
843 assert(src->shape != NULL);
844
845 bytes = PyBytes_FromStringAndSize(NULL, src->len);
846 if (bytes == NULL)
847 return NULL;
848
849 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
850 Py_DECREF(bytes);
851 if (mbuf == NULL)
852 return NULL;
853
854 if (mbuf_copy_format(mbuf, src->format) < 0) {
855 Py_DECREF(mbuf);
856 return NULL;
857 }
858
859 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
860 Py_DECREF(mbuf);
861 if (mv == NULL)
862 return NULL;
863
864 dest = &mv->view;
865
866 /* shared values are initialized correctly except for itemsize */
867 dest->itemsize = src->itemsize;
868
869 /* shape and strides */
870 for (i = 0; i < src->ndim; i++) {
871 dest->shape[i] = src->shape[i];
872 }
873 if (order == 'C' || order == 'A') {
874 init_strides_from_shape(dest);
875 }
876 else {
877 init_fortran_strides_from_shape(dest);
878 }
879 /* suboffsets */
880 dest->suboffsets = NULL;
881
882 /* flags */
883 init_flags(mv);
884
885 if (copy_buffer(dest, src) < 0) {
886 Py_DECREF(mv);
887 return NULL;
888 }
889
890 return (PyObject *)mv;
891}
892
893/*
894 Return a new memoryview object based on a contiguous exporter with
895 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
896 The logical structure of the input and output buffers is the same
897 (i.e. tolist(input) == tolist(output)), but the physical layout in
898 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200899
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100900 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
901 otherwise it may be writable or read-only.
902
903 If the exporter is already contiguous with the desired target order,
904 the memoryview will be directly based on the exporter.
905
906 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
907 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
908 'F'ortran order otherwise.
909*/
910PyObject *
911PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
912{
913 PyMemoryViewObject *mv;
914 PyObject *ret;
915 Py_buffer *view;
916
917 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
918 assert(order == 'C' || order == 'F' || order == 'A');
919
920 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
921 if (mv == NULL)
922 return NULL;
923
924 view = &mv->view;
925 if (buffertype == PyBUF_WRITE && view->readonly) {
926 PyErr_SetString(PyExc_BufferError,
927 "underlying buffer is not writable");
928 Py_DECREF(mv);
929 return NULL;
930 }
931
932 if (PyBuffer_IsContiguous(view, order))
933 return (PyObject *)mv;
934
935 if (buffertype == PyBUF_WRITE) {
936 PyErr_SetString(PyExc_BufferError,
937 "writable contiguous buffer requested "
938 "for a non-contiguous object.");
939 Py_DECREF(mv);
940 return NULL;
941 }
942
943 ret = memory_from_contiguous_copy(view, order);
944 Py_DECREF(mv);
945 return ret;
946}
947
948
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000949static PyObject *
950memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
951{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000952 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100953 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000954
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000955 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
956 &obj)) {
957 return NULL;
958 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000959
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000960 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000961}
962
963
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100964/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200965/* Previously in abstract.c */
966/****************************************************************************/
967
968typedef struct {
969 Py_buffer view;
970 Py_ssize_t array[1];
971} Py_buffer_full;
972
973int
974PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
975{
976 Py_buffer_full *fb = NULL;
977 int ret;
978
979 assert(order == 'C' || order == 'F' || order == 'A');
980
981 if (len != src->len) {
982 PyErr_SetString(PyExc_ValueError,
983 "PyBuffer_ToContiguous: len != view->len");
984 return -1;
985 }
986
987 if (PyBuffer_IsContiguous(src, order)) {
988 memcpy((char *)buf, src->buf, len);
989 return 0;
990 }
991
992 /* buffer_to_contiguous() assumes PyBUF_FULL */
993 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
994 if (fb == NULL) {
995 PyErr_NoMemory();
996 return -1;
997 }
998 fb->view.ndim = src->ndim;
999 fb->view.shape = fb->array;
1000 fb->view.strides = fb->array + src->ndim;
1001 fb->view.suboffsets = fb->array + 2 * src->ndim;
1002
1003 init_shared_values(&fb->view, src);
1004 init_shape_strides(&fb->view, src);
1005 init_suboffsets(&fb->view, src);
1006
1007 src = &fb->view;
1008
1009 ret = buffer_to_contiguous(buf, src, order);
1010 PyMem_Free(fb);
1011 return ret;
1012}
1013
1014
1015/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001016/* Release/GC management */
1017/****************************************************************************/
1018
1019/* Inform the managed buffer that this particular memoryview will not access
1020 the underlying buffer again. If no other memoryviews are registered with
1021 the managed buffer, the underlying buffer is released instantly and
1022 marked as inaccessible for both the memoryview and the managed buffer.
1023
1024 This function fails if the memoryview itself has exported buffers. */
1025static int
1026_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001027{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001028 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1029 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001030
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001031 if (self->exports == 0) {
1032 self->flags |= _Py_MEMORYVIEW_RELEASED;
1033 assert(self->mbuf->exports > 0);
1034 if (--self->mbuf->exports == 0)
1035 mbuf_release(self->mbuf);
1036 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001037 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001038 if (self->exports > 0) {
1039 PyErr_Format(PyExc_BufferError,
1040 "memoryview has %zd exported buffer%s", self->exports,
1041 self->exports==1 ? "" : "s");
1042 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001043 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001044
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001045 Py_FatalError("_memory_release(): negative export count");
1046 return -1;
1047}
1048
1049static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001050memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001051{
1052 if (_memory_release(self) < 0)
1053 return NULL;
1054 Py_RETURN_NONE;
1055}
1056
1057static void
1058memory_dealloc(PyMemoryViewObject *self)
1059{
1060 assert(self->exports == 0);
1061 _PyObject_GC_UNTRACK(self);
1062 (void)_memory_release(self);
1063 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001064 if (self->weakreflist != NULL)
1065 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001066 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001067}
1068
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001069static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001070memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001071{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001072 Py_VISIT(self->mbuf);
1073 return 0;
1074}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001075
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001076static int
1077memory_clear(PyMemoryViewObject *self)
1078{
1079 (void)_memory_release(self);
1080 Py_CLEAR(self->mbuf);
1081 return 0;
1082}
1083
1084static PyObject *
1085memory_enter(PyObject *self, PyObject *args)
1086{
1087 CHECK_RELEASED(self);
1088 Py_INCREF(self);
1089 return self;
1090}
1091
1092static PyObject *
1093memory_exit(PyObject *self, PyObject *args)
1094{
Stefan Krahe4c07992012-07-28 14:10:02 +02001095 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001096}
1097
1098
1099/****************************************************************************/
1100/* Casting format and shape */
1101/****************************************************************************/
1102
1103#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1104
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001105static inline Py_ssize_t
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001106get_native_fmtchar(char *result, const char *fmt)
1107{
1108 Py_ssize_t size = -1;
1109
1110 if (fmt[0] == '@') fmt++;
1111
1112 switch (fmt[0]) {
1113 case 'c': case 'b': case 'B': size = sizeof(char); break;
1114 case 'h': case 'H': size = sizeof(short); break;
1115 case 'i': case 'I': size = sizeof(int); break;
1116 case 'l': case 'L': size = sizeof(long); break;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001117 case 'q': case 'Q': size = sizeof(long long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001118 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1119 case 'f': size = sizeof(float); break;
1120 case 'd': size = sizeof(double); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001121 case '?': size = sizeof(_Bool); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001122 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001123 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001124
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001125 if (size > 0 && fmt[1] == '\0') {
1126 *result = fmt[0];
1127 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001128 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001129
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001130 return -1;
1131}
1132
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001133static inline const char *
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001134get_native_fmtstr(const char *fmt)
1135{
1136 int at = 0;
1137
1138 if (fmt[0] == '@') {
1139 at = 1;
1140 fmt++;
1141 }
1142 if (fmt[0] == '\0' || fmt[1] != '\0') {
1143 return NULL;
1144 }
1145
1146#define RETURN(s) do { return at ? "@" s : s; } while (0)
1147
1148 switch (fmt[0]) {
1149 case 'c': RETURN("c");
1150 case 'b': RETURN("b");
1151 case 'B': RETURN("B");
1152 case 'h': RETURN("h");
1153 case 'H': RETURN("H");
1154 case 'i': RETURN("i");
1155 case 'I': RETURN("I");
1156 case 'l': RETURN("l");
1157 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001158 case 'q': RETURN("q");
1159 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001160 case 'n': RETURN("n");
1161 case 'N': RETURN("N");
1162 case 'f': RETURN("f");
1163 case 'd': RETURN("d");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001164 case '?': RETURN("?");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001165 case 'P': RETURN("P");
1166 }
1167
1168 return NULL;
1169}
1170
1171
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001172/* Cast a memoryview's data type to 'format'. The input array must be
1173 C-contiguous. At least one of input-format, output-format must have
1174 byte size. The output array is 1-D, with the same byte length as the
1175 input array. Thus, view->len must be a multiple of the new itemsize. */
1176static int
1177cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1178{
1179 Py_buffer *view = &mv->view;
1180 PyObject *asciifmt;
1181 char srcchar, destchar;
1182 Py_ssize_t itemsize;
1183 int ret = -1;
1184
1185 assert(view->ndim >= 1);
1186 assert(Py_SIZE(mv) == 3*view->ndim);
1187 assert(view->shape == mv->ob_array);
1188 assert(view->strides == mv->ob_array + view->ndim);
1189 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1190
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001191 asciifmt = PyUnicode_AsASCIIString(format);
1192 if (asciifmt == NULL)
1193 return ret;
1194
1195 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1196 if (itemsize < 0) {
1197 PyErr_SetString(PyExc_ValueError,
1198 "memoryview: destination format must be a native single "
1199 "character format prefixed with an optional '@'");
1200 goto out;
1201 }
1202
Stefan Krah0c515952015-08-08 13:38:10 +02001203 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1204 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001205 PyErr_SetString(PyExc_TypeError,
1206 "memoryview: cannot cast between two non-byte formats");
1207 goto out;
1208 }
1209 if (view->len % itemsize) {
1210 PyErr_SetString(PyExc_TypeError,
1211 "memoryview: length is not a multiple of itemsize");
1212 goto out;
1213 }
1214
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001215 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001216 if (view->format == NULL) {
1217 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1218 PyErr_SetString(PyExc_RuntimeError,
1219 "memoryview: internal error");
1220 goto out;
1221 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001222 view->itemsize = itemsize;
1223
1224 view->ndim = 1;
1225 view->shape[0] = view->len / view->itemsize;
1226 view->strides[0] = view->itemsize;
1227 view->suboffsets = NULL;
1228
1229 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001230
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001231 ret = 0;
1232
1233out:
1234 Py_DECREF(asciifmt);
1235 return ret;
1236}
1237
1238/* The memoryview must have space for 3*len(seq) elements. */
1239static Py_ssize_t
1240copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1241 Py_ssize_t itemsize)
1242{
1243 Py_ssize_t x, i;
1244 Py_ssize_t len = itemsize;
1245
1246 for (i = 0; i < ndim; i++) {
1247 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1248 if (!PyLong_Check(tmp)) {
1249 PyErr_SetString(PyExc_TypeError,
1250 "memoryview.cast(): elements of shape must be integers");
1251 return -1;
1252 }
1253 x = PyLong_AsSsize_t(tmp);
1254 if (x == -1 && PyErr_Occurred()) {
1255 return -1;
1256 }
1257 if (x <= 0) {
1258 /* In general elements of shape may be 0, but not for casting. */
1259 PyErr_Format(PyExc_ValueError,
1260 "memoryview.cast(): elements of shape must be integers > 0");
1261 return -1;
1262 }
1263 if (x > PY_SSIZE_T_MAX / len) {
1264 PyErr_Format(PyExc_ValueError,
1265 "memoryview.cast(): product(shape) > SSIZE_MAX");
1266 return -1;
1267 }
1268 len *= x;
1269 shape[i] = x;
1270 }
1271
1272 return len;
1273}
1274
1275/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1276 If the result array does not have exactly the same byte length as the
1277 input array, raise ValueError. */
1278static int
1279cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1280{
1281 Py_buffer *view = &mv->view;
1282 Py_ssize_t len;
1283
1284 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1285 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1286 assert(view->shape == mv->ob_array);
1287 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1288 assert(view->suboffsets == NULL);
1289
1290 view->ndim = ndim;
1291 if (view->ndim == 0) {
1292 view->shape = NULL;
1293 view->strides = NULL;
1294 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001295 }
1296 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001297 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1298 if (len < 0)
1299 return -1;
1300 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001301 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001302
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001303 if (view->len != len) {
1304 PyErr_SetString(PyExc_TypeError,
1305 "memoryview: product(shape) * itemsize != buffer size");
1306 return -1;
1307 }
1308
1309 init_flags(mv);
1310
1311 return 0;
1312}
1313
1314static int
1315zero_in_shape(PyMemoryViewObject *mv)
1316{
1317 Py_buffer *view = &mv->view;
1318 Py_ssize_t i;
1319
1320 for (i = 0; i < view->ndim; i++)
1321 if (view->shape[i] == 0)
1322 return 1;
1323
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001324 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001325}
1326
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001327/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001328 Cast a copy of 'self' to a different view. The input view must
1329 be C-contiguous. The function always casts the input view to a
1330 1-D output according to 'format'. At least one of input-format,
1331 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001332
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001333 If 'shape' is given, the 1-D view from the previous step will
1334 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001335
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001336 All casts must result in views that will have the exact byte
1337 size of the original input. Otherwise, an error is raised.
1338*/
1339static PyObject *
1340memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001341{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001342 static char *kwlist[] = {"format", "shape", NULL};
1343 PyMemoryViewObject *mv = NULL;
1344 PyObject *shape = NULL;
1345 PyObject *format;
1346 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001347
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001348 CHECK_RELEASED(self);
1349
1350 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1351 &format, &shape)) {
1352 return NULL;
1353 }
1354 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001355 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001356 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001357 return NULL;
1358 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001359 if (!MV_C_CONTIGUOUS(self->flags)) {
1360 PyErr_SetString(PyExc_TypeError,
1361 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001362 return NULL;
1363 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001364 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001365 PyErr_SetString(PyExc_TypeError,
1366 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001367 return NULL;
1368 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001369 if (shape) {
1370 CHECK_LIST_OR_TUPLE(shape)
1371 ndim = PySequence_Fast_GET_SIZE(shape);
1372 if (ndim > PyBUF_MAX_NDIM) {
1373 PyErr_SetString(PyExc_ValueError,
1374 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001375 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001376 return NULL;
1377 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001378 if (self->view.ndim != 1 && ndim != 1) {
1379 PyErr_SetString(PyExc_TypeError,
1380 "memoryview: cast must be 1D -> ND or ND -> 1D");
1381 return NULL;
1382 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001383 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001384
1385 mv = (PyMemoryViewObject *)
1386 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1387 if (mv == NULL)
1388 return NULL;
1389
1390 if (cast_to_1D(mv, format) < 0)
1391 goto error;
1392 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1393 goto error;
1394
1395 return (PyObject *)mv;
1396
1397error:
1398 Py_DECREF(mv);
1399 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001400}
1401
Antoine Pitrou480ab052018-04-14 19:49:21 +02001402static PyObject *
1403memory_toreadonly(PyMemoryViewObject *self, PyObject *noargs)
1404{
1405 CHECK_RELEASED(self);
1406 /* Even if self is already readonly, we still need to create a new
1407 * object for .release() to work correctly.
1408 */
1409 self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1410 if (self != NULL) {
1411 self->view.readonly = 1;
1412 };
1413 return (PyObject *) self;
1414}
1415
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001416
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001417/**************************************************************************/
1418/* getbuffer */
1419/**************************************************************************/
1420
1421static int
1422memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1423{
1424 Py_buffer *base = &self->view;
1425 int baseflags = self->flags;
1426
1427 CHECK_RELEASED_INT(self);
1428
1429 /* start with complete information */
1430 *view = *base;
1431 view->obj = NULL;
1432
1433 if (REQ_WRITABLE(flags) && base->readonly) {
1434 PyErr_SetString(PyExc_BufferError,
1435 "memoryview: underlying buffer is not writable");
1436 return -1;
1437 }
1438 if (!REQ_FORMAT(flags)) {
1439 /* NULL indicates that the buffer's data type has been cast to 'B'.
1440 view->itemsize is the _previous_ itemsize. If shape is present,
1441 the equality product(shape) * itemsize = len still holds at this
1442 point. The equality calcsize(format) = itemsize does _not_ hold
1443 from here on! */
1444 view->format = NULL;
1445 }
1446
1447 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1448 PyErr_SetString(PyExc_BufferError,
1449 "memoryview: underlying buffer is not C-contiguous");
1450 return -1;
1451 }
1452 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1453 PyErr_SetString(PyExc_BufferError,
1454 "memoryview: underlying buffer is not Fortran contiguous");
1455 return -1;
1456 }
1457 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1458 PyErr_SetString(PyExc_BufferError,
1459 "memoryview: underlying buffer is not contiguous");
1460 return -1;
1461 }
1462 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1463 PyErr_SetString(PyExc_BufferError,
1464 "memoryview: underlying buffer requires suboffsets");
1465 return -1;
1466 }
1467 if (!REQ_STRIDES(flags)) {
1468 if (!MV_C_CONTIGUOUS(baseflags)) {
1469 PyErr_SetString(PyExc_BufferError,
1470 "memoryview: underlying buffer is not C-contiguous");
1471 return -1;
1472 }
1473 view->strides = NULL;
1474 }
1475 if (!REQ_SHAPE(flags)) {
1476 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1477 so base->buf = ndbuf->data. */
1478 if (view->format != NULL) {
1479 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1480 not make sense. */
1481 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001482 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001483 "is present");
1484 return -1;
1485 }
1486 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1487 do _not_ hold from here on! */
1488 view->ndim = 1;
1489 view->shape = NULL;
1490 }
1491
1492
1493 view->obj = (PyObject *)self;
1494 Py_INCREF(view->obj);
1495 self->exports++;
1496
1497 return 0;
1498}
1499
1500static void
1501memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1502{
1503 self->exports--;
1504 return;
1505 /* PyBuffer_Release() decrements view->obj after this function returns. */
1506}
1507
1508/* Buffer methods */
1509static PyBufferProcs memory_as_buffer = {
1510 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1511 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1512};
1513
1514
1515/****************************************************************************/
1516/* Optimized pack/unpack for all native format specifiers */
1517/****************************************************************************/
1518
1519/*
1520 Fix exceptions:
1521 1) Include format string in the error message.
1522 2) OverflowError -> ValueError.
1523 3) The error message from PyNumber_Index() is not ideal.
1524*/
1525static int
1526type_error_int(const char *fmt)
1527{
1528 PyErr_Format(PyExc_TypeError,
1529 "memoryview: invalid type for format '%s'", fmt);
1530 return -1;
1531}
1532
1533static int
1534value_error_int(const char *fmt)
1535{
1536 PyErr_Format(PyExc_ValueError,
1537 "memoryview: invalid value for format '%s'", fmt);
1538 return -1;
1539}
1540
1541static int
1542fix_error_int(const char *fmt)
1543{
1544 assert(PyErr_Occurred());
1545 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1546 PyErr_Clear();
1547 return type_error_int(fmt);
1548 }
1549 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1550 PyErr_ExceptionMatches(PyExc_ValueError)) {
1551 PyErr_Clear();
1552 return value_error_int(fmt);
1553 }
1554
1555 return -1;
1556}
1557
1558/* Accept integer objects or objects with an __index__() method. */
1559static long
1560pylong_as_ld(PyObject *item)
1561{
1562 PyObject *tmp;
1563 long ld;
1564
1565 tmp = PyNumber_Index(item);
1566 if (tmp == NULL)
1567 return -1;
1568
1569 ld = PyLong_AsLong(tmp);
1570 Py_DECREF(tmp);
1571 return ld;
1572}
1573
1574static unsigned long
1575pylong_as_lu(PyObject *item)
1576{
1577 PyObject *tmp;
1578 unsigned long lu;
1579
1580 tmp = PyNumber_Index(item);
1581 if (tmp == NULL)
1582 return (unsigned long)-1;
1583
1584 lu = PyLong_AsUnsignedLong(tmp);
1585 Py_DECREF(tmp);
1586 return lu;
1587}
1588
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001589static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001590pylong_as_lld(PyObject *item)
1591{
1592 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001593 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001594
1595 tmp = PyNumber_Index(item);
1596 if (tmp == NULL)
1597 return -1;
1598
1599 lld = PyLong_AsLongLong(tmp);
1600 Py_DECREF(tmp);
1601 return lld;
1602}
1603
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001604static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001605pylong_as_llu(PyObject *item)
1606{
1607 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001608 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001609
1610 tmp = PyNumber_Index(item);
1611 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001612 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001613
1614 llu = PyLong_AsUnsignedLongLong(tmp);
1615 Py_DECREF(tmp);
1616 return llu;
1617}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001618
1619static Py_ssize_t
1620pylong_as_zd(PyObject *item)
1621{
1622 PyObject *tmp;
1623 Py_ssize_t zd;
1624
1625 tmp = PyNumber_Index(item);
1626 if (tmp == NULL)
1627 return -1;
1628
1629 zd = PyLong_AsSsize_t(tmp);
1630 Py_DECREF(tmp);
1631 return zd;
1632}
1633
1634static size_t
1635pylong_as_zu(PyObject *item)
1636{
1637 PyObject *tmp;
1638 size_t zu;
1639
1640 tmp = PyNumber_Index(item);
1641 if (tmp == NULL)
1642 return (size_t)-1;
1643
1644 zu = PyLong_AsSize_t(tmp);
1645 Py_DECREF(tmp);
1646 return zu;
1647}
1648
1649/* Timings with the ndarray from _testbuffer.c indicate that using the
1650 struct module is around 15x slower than the two functions below. */
1651
1652#define UNPACK_SINGLE(dest, ptr, type) \
1653 do { \
1654 type x; \
1655 memcpy((char *)&x, ptr, sizeof x); \
1656 dest = x; \
1657 } while (0)
1658
1659/* Unpack a single item. 'fmt' can be any native format character in struct
1660 module syntax. This function is very sensitive to small changes. With this
1661 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001662static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001663unpack_single(const char *ptr, const char *fmt)
1664{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001665 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001666 unsigned long lu;
1667 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001668 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001669 long ld;
1670 Py_ssize_t zd;
1671 double d;
1672 unsigned char uc;
1673 void *p;
1674
1675 switch (fmt[0]) {
1676
1677 /* signed integers and fast path for 'B' */
1678 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1679 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1680 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1681 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1682 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1683
1684 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001685 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001686
1687 /* unsigned integers */
1688 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1689 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1690 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1691
1692 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001693 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1694 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001695
1696 /* ssize_t and size_t */
1697 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1698 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1699
1700 /* floats */
1701 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1702 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1703
1704 /* bytes object */
1705 case 'c': goto convert_bytes;
1706
1707 /* pointer */
1708 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1709
1710 /* default */
1711 default: goto err_format;
1712 }
1713
1714convert_uc:
1715 /* PyLong_FromUnsignedLong() is slower */
1716 return PyLong_FromLong(uc);
1717convert_ld:
1718 return PyLong_FromLong(ld);
1719convert_lu:
1720 return PyLong_FromUnsignedLong(lu);
1721convert_lld:
1722 return PyLong_FromLongLong(lld);
1723convert_llu:
1724 return PyLong_FromUnsignedLongLong(llu);
1725convert_zd:
1726 return PyLong_FromSsize_t(zd);
1727convert_zu:
1728 return PyLong_FromSize_t(zu);
1729convert_double:
1730 return PyFloat_FromDouble(d);
1731convert_bool:
1732 return PyBool_FromLong(ld);
1733convert_bytes:
1734 return PyBytes_FromStringAndSize(ptr, 1);
1735convert_pointer:
1736 return PyLong_FromVoidPtr(p);
1737err_format:
1738 PyErr_Format(PyExc_NotImplementedError,
1739 "memoryview: format %s not supported", fmt);
1740 return NULL;
1741}
1742
1743#define PACK_SINGLE(ptr, src, type) \
1744 do { \
1745 type x; \
1746 x = (type)src; \
1747 memcpy(ptr, (char *)&x, sizeof x); \
1748 } while (0)
1749
1750/* Pack a single item. 'fmt' can be any native format character in
1751 struct module syntax. */
1752static int
1753pack_single(char *ptr, PyObject *item, const char *fmt)
1754{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001755 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001756 unsigned long lu;
1757 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001758 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001759 long ld;
1760 Py_ssize_t zd;
1761 double d;
1762 void *p;
1763
1764 switch (fmt[0]) {
1765 /* signed integers */
1766 case 'b': case 'h': case 'i': case 'l':
1767 ld = pylong_as_ld(item);
1768 if (ld == -1 && PyErr_Occurred())
1769 goto err_occurred;
1770 switch (fmt[0]) {
1771 case 'b':
1772 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1773 *((signed char *)ptr) = (signed char)ld; break;
1774 case 'h':
1775 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1776 PACK_SINGLE(ptr, ld, short); break;
1777 case 'i':
1778 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1779 PACK_SINGLE(ptr, ld, int); break;
1780 default: /* 'l' */
1781 PACK_SINGLE(ptr, ld, long); break;
1782 }
1783 break;
1784
1785 /* unsigned integers */
1786 case 'B': case 'H': case 'I': case 'L':
1787 lu = pylong_as_lu(item);
1788 if (lu == (unsigned long)-1 && PyErr_Occurred())
1789 goto err_occurred;
1790 switch (fmt[0]) {
1791 case 'B':
1792 if (lu > UCHAR_MAX) goto err_range;
1793 *((unsigned char *)ptr) = (unsigned char)lu; break;
1794 case 'H':
1795 if (lu > USHRT_MAX) goto err_range;
1796 PACK_SINGLE(ptr, lu, unsigned short); break;
1797 case 'I':
1798 if (lu > UINT_MAX) goto err_range;
1799 PACK_SINGLE(ptr, lu, unsigned int); break;
1800 default: /* 'L' */
1801 PACK_SINGLE(ptr, lu, unsigned long); break;
1802 }
1803 break;
1804
1805 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001806 case 'q':
1807 lld = pylong_as_lld(item);
1808 if (lld == -1 && PyErr_Occurred())
1809 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001810 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001811 break;
1812 case 'Q':
1813 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001814 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001815 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001816 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001817 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001818
1819 /* ssize_t and size_t */
1820 case 'n':
1821 zd = pylong_as_zd(item);
1822 if (zd == -1 && PyErr_Occurred())
1823 goto err_occurred;
1824 PACK_SINGLE(ptr, zd, Py_ssize_t);
1825 break;
1826 case 'N':
1827 zu = pylong_as_zu(item);
1828 if (zu == (size_t)-1 && PyErr_Occurred())
1829 goto err_occurred;
1830 PACK_SINGLE(ptr, zu, size_t);
1831 break;
1832
1833 /* floats */
1834 case 'f': case 'd':
1835 d = PyFloat_AsDouble(item);
1836 if (d == -1.0 && PyErr_Occurred())
1837 goto err_occurred;
1838 if (fmt[0] == 'f') {
1839 PACK_SINGLE(ptr, d, float);
1840 }
1841 else {
1842 PACK_SINGLE(ptr, d, double);
1843 }
1844 break;
1845
1846 /* bool */
1847 case '?':
1848 ld = PyObject_IsTrue(item);
1849 if (ld < 0)
1850 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001851 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001852 break;
1853
1854 /* bytes object */
1855 case 'c':
1856 if (!PyBytes_Check(item))
1857 return type_error_int(fmt);
1858 if (PyBytes_GET_SIZE(item) != 1)
1859 return value_error_int(fmt);
1860 *ptr = PyBytes_AS_STRING(item)[0];
1861 break;
1862
1863 /* pointer */
1864 case 'P':
1865 p = PyLong_AsVoidPtr(item);
1866 if (p == NULL && PyErr_Occurred())
1867 goto err_occurred;
1868 PACK_SINGLE(ptr, p, void *);
1869 break;
1870
1871 /* default */
1872 default: goto err_format;
1873 }
1874
1875 return 0;
1876
1877err_occurred:
1878 return fix_error_int(fmt);
1879err_range:
1880 return value_error_int(fmt);
1881err_format:
1882 PyErr_Format(PyExc_NotImplementedError,
1883 "memoryview: format %s not supported", fmt);
1884 return -1;
1885}
1886
1887
1888/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001889/* unpack using the struct module */
1890/****************************************************************************/
1891
1892/* For reasonable performance it is necessary to cache all objects required
1893 for unpacking. An unpacker can handle the format passed to unpack_from().
1894 Invariant: All pointer fields of the struct should either be NULL or valid
1895 pointers. */
1896struct unpacker {
1897 PyObject *unpack_from; /* Struct.unpack_from(format) */
1898 PyObject *mview; /* cached memoryview */
1899 char *item; /* buffer for mview */
1900 Py_ssize_t itemsize; /* len(item) */
1901};
1902
1903static struct unpacker *
1904unpacker_new(void)
1905{
1906 struct unpacker *x = PyMem_Malloc(sizeof *x);
1907
1908 if (x == NULL) {
1909 PyErr_NoMemory();
1910 return NULL;
1911 }
1912
1913 x->unpack_from = NULL;
1914 x->mview = NULL;
1915 x->item = NULL;
1916 x->itemsize = 0;
1917
1918 return x;
1919}
1920
1921static void
1922unpacker_free(struct unpacker *x)
1923{
1924 if (x) {
1925 Py_XDECREF(x->unpack_from);
1926 Py_XDECREF(x->mview);
1927 PyMem_Free(x->item);
1928 PyMem_Free(x);
1929 }
1930}
1931
1932/* Return a new unpacker for the given format. */
1933static struct unpacker *
1934struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1935{
1936 PyObject *structmodule; /* XXX cache these two */
1937 PyObject *Struct = NULL; /* XXX in globals? */
1938 PyObject *structobj = NULL;
1939 PyObject *format = NULL;
1940 struct unpacker *x = NULL;
1941
1942 structmodule = PyImport_ImportModule("struct");
1943 if (structmodule == NULL)
1944 return NULL;
1945
1946 Struct = PyObject_GetAttrString(structmodule, "Struct");
1947 Py_DECREF(structmodule);
1948 if (Struct == NULL)
1949 return NULL;
1950
1951 x = unpacker_new();
1952 if (x == NULL)
1953 goto error;
1954
1955 format = PyBytes_FromString(fmt);
1956 if (format == NULL)
1957 goto error;
1958
1959 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1960 if (structobj == NULL)
1961 goto error;
1962
1963 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1964 if (x->unpack_from == NULL)
1965 goto error;
1966
1967 x->item = PyMem_Malloc(itemsize);
1968 if (x->item == NULL) {
1969 PyErr_NoMemory();
1970 goto error;
1971 }
1972 x->itemsize = itemsize;
1973
1974 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1975 if (x->mview == NULL)
1976 goto error;
1977
1978
1979out:
1980 Py_XDECREF(Struct);
1981 Py_XDECREF(format);
1982 Py_XDECREF(structobj);
1983 return x;
1984
1985error:
1986 unpacker_free(x);
1987 x = NULL;
1988 goto out;
1989}
1990
1991/* unpack a single item */
1992static PyObject *
1993struct_unpack_single(const char *ptr, struct unpacker *x)
1994{
1995 PyObject *v;
1996
1997 memcpy(x->item, ptr, x->itemsize);
1998 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
1999 if (v == NULL)
2000 return NULL;
2001
2002 if (PyTuple_GET_SIZE(v) == 1) {
2003 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2004 Py_INCREF(tmp);
2005 Py_DECREF(v);
2006 return tmp;
2007 }
2008
2009 return v;
2010}
2011
2012
2013/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002014/* Representations */
2015/****************************************************************************/
2016
2017/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002018static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002019adjust_fmt(const Py_buffer *view)
2020{
2021 const char *fmt;
2022
2023 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2024 if (fmt[0] && fmt[1] == '\0')
2025 return fmt;
2026
2027 PyErr_Format(PyExc_NotImplementedError,
2028 "memoryview: unsupported format %s", view->format);
2029 return NULL;
2030}
2031
2032/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2033static PyObject *
2034tolist_base(const char *ptr, const Py_ssize_t *shape,
2035 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2036 const char *fmt)
2037{
2038 PyObject *lst, *item;
2039 Py_ssize_t i;
2040
2041 lst = PyList_New(shape[0]);
2042 if (lst == NULL)
2043 return NULL;
2044
2045 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002046 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002047 item = unpack_single(xptr, fmt);
2048 if (item == NULL) {
2049 Py_DECREF(lst);
2050 return NULL;
2051 }
2052 PyList_SET_ITEM(lst, i, item);
2053 }
2054
2055 return lst;
2056}
2057
2058/* Unpack a multi-dimensional array into a nested list.
2059 Assumption: ndim >= 1. */
2060static PyObject *
2061tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2062 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2063 const char *fmt)
2064{
2065 PyObject *lst, *item;
2066 Py_ssize_t i;
2067
2068 assert(ndim >= 1);
2069 assert(shape != NULL);
2070 assert(strides != NULL);
2071
2072 if (ndim == 1)
2073 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2074
2075 lst = PyList_New(shape[0]);
2076 if (lst == NULL)
2077 return NULL;
2078
2079 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002080 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002081 item = tolist_rec(xptr, ndim-1, shape+1,
2082 strides+1, suboffsets ? suboffsets+1 : NULL,
2083 fmt);
2084 if (item == NULL) {
2085 Py_DECREF(lst);
2086 return NULL;
2087 }
2088 PyList_SET_ITEM(lst, i, item);
2089 }
2090
2091 return lst;
2092}
2093
2094/* Return a list representation of the memoryview. Currently only buffers
2095 with native format strings are supported. */
2096static PyObject *
2097memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2098{
2099 const Py_buffer *view = &(mv->view);
2100 const char *fmt;
2101
2102 CHECK_RELEASED(mv);
2103
2104 fmt = adjust_fmt(view);
2105 if (fmt == NULL)
2106 return NULL;
2107 if (view->ndim == 0) {
2108 return unpack_single(view->buf, fmt);
2109 }
2110 else if (view->ndim == 1) {
2111 return tolist_base(view->buf, view->shape,
2112 view->strides, view->suboffsets,
2113 fmt);
2114 }
2115 else {
2116 return tolist_rec(view->buf, view->ndim, view->shape,
2117 view->strides, view->suboffsets,
2118 fmt);
2119 }
2120}
2121
2122static PyObject *
2123memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
2124{
2125 Py_buffer *src = VIEW_ADDR(self);
2126 PyObject *bytes = NULL;
2127
2128 CHECK_RELEASED(self);
2129
2130 if (MV_C_CONTIGUOUS(self->flags)) {
2131 return PyBytes_FromStringAndSize(src->buf, src->len);
2132 }
2133
2134 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2135 if (bytes == NULL)
2136 return NULL;
2137
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002138 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002139 Py_DECREF(bytes);
2140 return NULL;
2141 }
2142
2143 return bytes;
2144}
2145
2146static PyObject *
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002147memory_hex(PyMemoryViewObject *self, PyObject *dummy)
2148{
2149 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002150 PyObject *bytes;
2151 PyObject *ret;
2152
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002153 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002154
2155 if (MV_C_CONTIGUOUS(self->flags)) {
2156 return _Py_strhex(src->buf, src->len);
2157 }
2158
2159 bytes = memory_tobytes(self, dummy);
2160 if (bytes == NULL)
2161 return NULL;
2162
Serhiy Storchakafff9a312017-03-21 08:53:25 +02002163 ret = _Py_strhex(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002164 Py_DECREF(bytes);
2165
2166 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002167}
2168
2169static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002170memory_repr(PyMemoryViewObject *self)
2171{
2172 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2173 return PyUnicode_FromFormat("<released memory at %p>", self);
2174 else
2175 return PyUnicode_FromFormat("<memory at %p>", self);
2176}
2177
2178
2179/**************************************************************************/
2180/* Indexing and slicing */
2181/**************************************************************************/
2182
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002183static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002184lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002185{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002186 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002187
2188 assert(view->shape);
2189 assert(view->strides);
2190
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002191 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002192 if (index < 0) {
2193 index += nitems;
2194 }
2195 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002196 PyErr_Format(PyExc_IndexError,
2197 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002198 return NULL;
2199 }
2200
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002201 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002202
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002203 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002204
2205 return ptr;
2206}
2207
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002208/* Get the pointer to the item at index. */
2209static char *
2210ptr_from_index(Py_buffer *view, Py_ssize_t index)
2211{
2212 char *ptr = (char *)view->buf;
2213 return lookup_dimension(view, ptr, 0, index);
2214}
2215
2216/* Get the pointer to the item at tuple. */
2217static char *
2218ptr_from_tuple(Py_buffer *view, PyObject *tup)
2219{
2220 char *ptr = (char *)view->buf;
2221 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2222
2223 if (nindices > view->ndim) {
2224 PyErr_Format(PyExc_TypeError,
2225 "cannot index %zd-dimension view with %zd-element tuple",
2226 view->ndim, nindices);
2227 return NULL;
2228 }
2229
2230 for (dim = 0; dim < nindices; dim++) {
2231 Py_ssize_t index;
2232 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2233 PyExc_IndexError);
2234 if (index == -1 && PyErr_Occurred())
2235 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002236 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002237 if (ptr == NULL)
2238 return NULL;
2239 }
2240 return ptr;
2241}
2242
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002243/* Return the item at index. In a one-dimensional view, this is an object
2244 with the type specified by view->format. Otherwise, the item is a sub-view.
2245 The function is used in memory_subscript() and memory_as_sequence. */
2246static PyObject *
2247memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2248{
2249 Py_buffer *view = &(self->view);
2250 const char *fmt;
2251
2252 CHECK_RELEASED(self);
2253
2254 fmt = adjust_fmt(view);
2255 if (fmt == NULL)
2256 return NULL;
2257
2258 if (view->ndim == 0) {
2259 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2260 return NULL;
2261 }
2262 if (view->ndim == 1) {
2263 char *ptr = ptr_from_index(view, index);
2264 if (ptr == NULL)
2265 return NULL;
2266 return unpack_single(ptr, fmt);
2267 }
2268
2269 PyErr_SetString(PyExc_NotImplementedError,
2270 "multi-dimensional sub-views are not implemented");
2271 return NULL;
2272}
2273
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002274/* Return the item at position *key* (a tuple of indices). */
2275static PyObject *
2276memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2277{
2278 Py_buffer *view = &(self->view);
2279 const char *fmt;
2280 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2281 char *ptr;
2282
2283 CHECK_RELEASED(self);
2284
2285 fmt = adjust_fmt(view);
2286 if (fmt == NULL)
2287 return NULL;
2288
2289 if (nindices < view->ndim) {
2290 PyErr_SetString(PyExc_NotImplementedError,
2291 "sub-views are not implemented");
2292 return NULL;
2293 }
2294 ptr = ptr_from_tuple(view, tup);
2295 if (ptr == NULL)
2296 return NULL;
2297 return unpack_single(ptr, fmt);
2298}
2299
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002300static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002301init_slice(Py_buffer *base, PyObject *key, int dim)
2302{
2303 Py_ssize_t start, stop, step, slicelength;
2304
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002305 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002306 return -1;
2307 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002308 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002309
2310
2311 if (base->suboffsets == NULL || dim == 0) {
2312 adjust_buf:
2313 base->buf = (char *)base->buf + base->strides[dim] * start;
2314 }
2315 else {
2316 Py_ssize_t n = dim-1;
2317 while (n >= 0 && base->suboffsets[n] < 0)
2318 n--;
2319 if (n < 0)
2320 goto adjust_buf; /* all suboffsets are negative */
2321 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2322 }
2323 base->shape[dim] = slicelength;
2324 base->strides[dim] = base->strides[dim] * step;
2325
2326 return 0;
2327}
2328
2329static int
2330is_multislice(PyObject *key)
2331{
2332 Py_ssize_t size, i;
2333
2334 if (!PyTuple_Check(key))
2335 return 0;
2336 size = PyTuple_GET_SIZE(key);
2337 if (size == 0)
2338 return 0;
2339
2340 for (i = 0; i < size; i++) {
2341 PyObject *x = PyTuple_GET_ITEM(key, i);
2342 if (!PySlice_Check(x))
2343 return 0;
2344 }
2345 return 1;
2346}
2347
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002348static Py_ssize_t
2349is_multiindex(PyObject *key)
2350{
2351 Py_ssize_t size, i;
2352
2353 if (!PyTuple_Check(key))
2354 return 0;
2355 size = PyTuple_GET_SIZE(key);
2356 for (i = 0; i < size; i++) {
2357 PyObject *x = PyTuple_GET_ITEM(key, i);
2358 if (!PyIndex_Check(x))
2359 return 0;
2360 }
2361 return 1;
2362}
2363
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002364/* mv[obj] returns an object holding the data for one element if obj
2365 fully indexes the memoryview or another memoryview object if it
2366 does not.
2367
2368 0-d memoryview objects can be referenced using mv[...] or mv[()]
2369 but not with anything else. */
2370static PyObject *
2371memory_subscript(PyMemoryViewObject *self, PyObject *key)
2372{
2373 Py_buffer *view;
2374 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002375
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002376 CHECK_RELEASED(self);
2377
2378 if (view->ndim == 0) {
2379 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2380 const char *fmt = adjust_fmt(view);
2381 if (fmt == NULL)
2382 return NULL;
2383 return unpack_single(view->buf, fmt);
2384 }
2385 else if (key == Py_Ellipsis) {
2386 Py_INCREF(self);
2387 return (PyObject *)self;
2388 }
2389 else {
2390 PyErr_SetString(PyExc_TypeError,
2391 "invalid indexing of 0-dim memory");
2392 return NULL;
2393 }
2394 }
2395
2396 if (PyIndex_Check(key)) {
2397 Py_ssize_t index;
2398 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2399 if (index == -1 && PyErr_Occurred())
2400 return NULL;
2401 return memory_item(self, index);
2402 }
2403 else if (PySlice_Check(key)) {
2404 PyMemoryViewObject *sliced;
2405
2406 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2407 if (sliced == NULL)
2408 return NULL;
2409
2410 if (init_slice(&sliced->view, key, 0) < 0) {
2411 Py_DECREF(sliced);
2412 return NULL;
2413 }
2414 init_len(&sliced->view);
2415 init_flags(sliced);
2416
2417 return (PyObject *)sliced;
2418 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002419 else if (is_multiindex(key)) {
2420 return memory_item_multi(self, key);
2421 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002422 else if (is_multislice(key)) {
2423 PyErr_SetString(PyExc_NotImplementedError,
2424 "multi-dimensional slicing is not implemented");
2425 return NULL;
2426 }
2427
2428 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2429 return NULL;
2430}
2431
2432static int
2433memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2434{
2435 Py_buffer *view = &(self->view);
2436 Py_buffer src;
2437 const char *fmt;
2438 char *ptr;
2439
2440 CHECK_RELEASED_INT(self);
2441
2442 fmt = adjust_fmt(view);
2443 if (fmt == NULL)
2444 return -1;
2445
2446 if (view->readonly) {
2447 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2448 return -1;
2449 }
2450 if (value == NULL) {
2451 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2452 return -1;
2453 }
2454 if (view->ndim == 0) {
2455 if (key == Py_Ellipsis ||
2456 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2457 ptr = (char *)view->buf;
2458 return pack_single(ptr, value, fmt);
2459 }
2460 else {
2461 PyErr_SetString(PyExc_TypeError,
2462 "invalid indexing of 0-dim memory");
2463 return -1;
2464 }
2465 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002466
2467 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002468 Py_ssize_t index;
2469 if (1 < view->ndim) {
2470 PyErr_SetString(PyExc_NotImplementedError,
2471 "sub-views are not implemented");
2472 return -1;
2473 }
2474 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002475 if (index == -1 && PyErr_Occurred())
2476 return -1;
2477 ptr = ptr_from_index(view, index);
2478 if (ptr == NULL)
2479 return -1;
2480 return pack_single(ptr, value, fmt);
2481 }
2482 /* one-dimensional: fast path */
2483 if (PySlice_Check(key) && view->ndim == 1) {
2484 Py_buffer dest; /* sliced view */
2485 Py_ssize_t arrays[3];
2486 int ret = -1;
2487
2488 /* rvalue must be an exporter */
2489 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2490 return ret;
2491
2492 dest = *view;
2493 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2494 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2495 if (view->suboffsets) {
2496 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2497 }
2498
2499 if (init_slice(&dest, key, 0) < 0)
2500 goto end_block;
2501 dest.len = dest.shape[0] * dest.itemsize;
2502
2503 ret = copy_single(&dest, &src);
2504
2505 end_block:
2506 PyBuffer_Release(&src);
2507 return ret;
2508 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002509 if (is_multiindex(key)) {
2510 char *ptr;
2511 if (PyTuple_GET_SIZE(key) < view->ndim) {
2512 PyErr_SetString(PyExc_NotImplementedError,
2513 "sub-views are not implemented");
2514 return -1;
2515 }
2516 ptr = ptr_from_tuple(view, key);
2517 if (ptr == NULL)
2518 return -1;
2519 return pack_single(ptr, value, fmt);
2520 }
2521 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002522 /* Call memory_subscript() to produce a sliced lvalue, then copy
2523 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2524 PyErr_SetString(PyExc_NotImplementedError,
2525 "memoryview slice assignments are currently restricted "
2526 "to ndim = 1");
2527 return -1;
2528 }
2529
2530 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2531 return -1;
2532}
2533
2534static Py_ssize_t
2535memory_length(PyMemoryViewObject *self)
2536{
2537 CHECK_RELEASED_INT(self);
2538 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2539}
2540
2541/* As mapping */
2542static PyMappingMethods memory_as_mapping = {
2543 (lenfunc)memory_length, /* mp_length */
2544 (binaryfunc)memory_subscript, /* mp_subscript */
2545 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2546};
2547
2548/* As sequence */
2549static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002550 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002551 0, /* sq_concat */
2552 0, /* sq_repeat */
2553 (ssizeargfunc)memory_item, /* sq_item */
2554};
2555
2556
2557/**************************************************************************/
2558/* Comparisons */
2559/**************************************************************************/
2560
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002561#define MV_COMPARE_EX -1 /* exception */
2562#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2563
2564/* Translate a StructError to "not equal". Preserve other exceptions. */
2565static int
2566fix_struct_error_int(void)
2567{
2568 assert(PyErr_Occurred());
2569 /* XXX Cannot get at StructError directly? */
2570 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2571 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2572 return MV_COMPARE_EX;
2573 }
2574 /* StructError: invalid or unknown format -> not equal */
2575 PyErr_Clear();
2576 return 0;
2577}
2578
2579/* Unpack and compare single items of p and q using the struct module. */
2580static int
2581struct_unpack_cmp(const char *p, const char *q,
2582 struct unpacker *unpack_p, struct unpacker *unpack_q)
2583{
2584 PyObject *v, *w;
2585 int ret;
2586
2587 /* At this point any exception from the struct module should not be
2588 StructError, since both formats have been accepted already. */
2589 v = struct_unpack_single(p, unpack_p);
2590 if (v == NULL)
2591 return MV_COMPARE_EX;
2592
2593 w = struct_unpack_single(q, unpack_q);
2594 if (w == NULL) {
2595 Py_DECREF(v);
2596 return MV_COMPARE_EX;
2597 }
2598
2599 /* MV_COMPARE_EX == -1: exceptions are preserved */
2600 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2601 Py_DECREF(v);
2602 Py_DECREF(w);
2603
2604 return ret;
2605}
2606
2607/* Unpack and compare single items of p and q. If both p and q have the same
2608 single element native format, the comparison uses a fast path (gcc creates
2609 a jump table and converts memcpy into simple assignments on x86/x64).
2610
2611 Otherwise, the comparison is delegated to the struct module, which is
2612 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002613#define CMP_SINGLE(p, q, type) \
2614 do { \
2615 type x; \
2616 type y; \
2617 memcpy((char *)&x, p, sizeof x); \
2618 memcpy((char *)&y, q, sizeof y); \
2619 equal = (x == y); \
2620 } while (0)
2621
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002622static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002623unpack_cmp(const char *p, const char *q, char fmt,
2624 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002625{
2626 int equal;
2627
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002628 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002629
2630 /* signed integers and fast path for 'B' */
2631 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2632 case 'b': return *((signed char *)p) == *((signed char *)q);
2633 case 'h': CMP_SINGLE(p, q, short); return equal;
2634 case 'i': CMP_SINGLE(p, q, int); return equal;
2635 case 'l': CMP_SINGLE(p, q, long); return equal;
2636
2637 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002638 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002639
2640 /* unsigned integers */
2641 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2642 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2643 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2644
2645 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002646 case 'q': CMP_SINGLE(p, q, long long); return equal;
2647 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002648
2649 /* ssize_t and size_t */
2650 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2651 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2652
2653 /* floats */
2654 /* XXX DBL_EPSILON? */
2655 case 'f': CMP_SINGLE(p, q, float); return equal;
2656 case 'd': CMP_SINGLE(p, q, double); return equal;
2657
2658 /* bytes object */
2659 case 'c': return *p == *q;
2660
2661 /* pointer */
2662 case 'P': CMP_SINGLE(p, q, void *); return equal;
2663
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002664 /* use the struct module */
2665 case '_':
2666 assert(unpack_p);
2667 assert(unpack_q);
2668 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002669 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002670
2671 /* NOT REACHED */
2672 PyErr_SetString(PyExc_RuntimeError,
2673 "memoryview: internal error in richcompare");
2674 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002675}
2676
2677/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2678static int
2679cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2680 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2681 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002682 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002683{
2684 Py_ssize_t i;
2685 int equal;
2686
2687 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002688 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2689 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002690 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002691 if (equal <= 0)
2692 return equal;
2693 }
2694
2695 return 1;
2696}
2697
2698/* Recursively compare two multi-dimensional arrays that have the same
2699 logical structure. Assumption: ndim >= 1. */
2700static int
2701cmp_rec(const char *p, const char *q,
2702 Py_ssize_t ndim, const Py_ssize_t *shape,
2703 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2704 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002705 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002706{
2707 Py_ssize_t i;
2708 int equal;
2709
2710 assert(ndim >= 1);
2711 assert(shape != NULL);
2712 assert(pstrides != NULL);
2713 assert(qstrides != NULL);
2714
2715 if (ndim == 1) {
2716 return cmp_base(p, q, shape,
2717 pstrides, psuboffsets,
2718 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002719 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002720 }
2721
2722 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002723 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2724 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002725 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2726 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2727 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002728 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002729 if (equal <= 0)
2730 return equal;
2731 }
2732
2733 return 1;
2734}
2735
2736static PyObject *
2737memory_richcompare(PyObject *v, PyObject *w, int op)
2738{
2739 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002740 Py_buffer wbuf, *vv;
2741 Py_buffer *ww = NULL;
2742 struct unpacker *unpack_v = NULL;
2743 struct unpacker *unpack_w = NULL;
2744 char vfmt, wfmt;
2745 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002746
2747 if (op != Py_EQ && op != Py_NE)
2748 goto result; /* Py_NotImplemented */
2749
2750 assert(PyMemoryView_Check(v));
2751 if (BASE_INACCESSIBLE(v)) {
2752 equal = (v == w);
2753 goto result;
2754 }
2755 vv = VIEW_ADDR(v);
2756
2757 if (PyMemoryView_Check(w)) {
2758 if (BASE_INACCESSIBLE(w)) {
2759 equal = (v == w);
2760 goto result;
2761 }
2762 ww = VIEW_ADDR(w);
2763 }
2764 else {
2765 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2766 PyErr_Clear();
2767 goto result; /* Py_NotImplemented */
2768 }
2769 ww = &wbuf;
2770 }
2771
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002772 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002773 PyErr_Clear();
2774 equal = 0;
2775 goto result;
2776 }
2777
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002778 /* Use fast unpacking for identical primitive C type formats. */
2779 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2780 vfmt = '_';
2781 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2782 wfmt = '_';
2783 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2784 /* Use struct module unpacking. NOTE: Even for equal format strings,
2785 memcmp() cannot be used for item comparison since it would give
2786 incorrect results in the case of NaNs or uninitialized padding
2787 bytes. */
2788 vfmt = '_';
2789 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2790 if (unpack_v == NULL) {
2791 equal = fix_struct_error_int();
2792 goto result;
2793 }
2794 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2795 if (unpack_w == NULL) {
2796 equal = fix_struct_error_int();
2797 goto result;
2798 }
2799 }
2800
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002801 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002802 equal = unpack_cmp(vv->buf, ww->buf,
2803 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002804 }
2805 else if (vv->ndim == 1) {
2806 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2807 vv->strides, vv->suboffsets,
2808 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002809 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002810 }
2811 else {
2812 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2813 vv->strides, vv->suboffsets,
2814 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002815 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002816 }
2817
2818result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002819 if (equal < 0) {
2820 if (equal == MV_COMPARE_NOT_IMPL)
2821 res = Py_NotImplemented;
2822 else /* exception */
2823 res = NULL;
2824 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002825 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2826 res = Py_True;
2827 else
2828 res = Py_False;
2829
2830 if (ww == &wbuf)
2831 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002832
2833 unpacker_free(unpack_v);
2834 unpacker_free(unpack_w);
2835
2836 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002837 return res;
2838}
2839
2840/**************************************************************************/
2841/* Hash */
2842/**************************************************************************/
2843
2844static Py_hash_t
2845memory_hash(PyMemoryViewObject *self)
2846{
2847 if (self->hash == -1) {
2848 Py_buffer *view = &self->view;
2849 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002850 Py_ssize_t ret;
2851 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002852
2853 CHECK_RELEASED_INT(self);
2854
2855 if (!view->readonly) {
2856 PyErr_SetString(PyExc_ValueError,
2857 "cannot hash writable memoryview object");
2858 return -1;
2859 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002860 ret = get_native_fmtchar(&fmt, view->format);
2861 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2862 PyErr_SetString(PyExc_ValueError,
2863 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2864 return -1;
2865 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002866 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2867 /* Keep the original error message */
2868 return -1;
2869 }
2870
2871 if (!MV_C_CONTIGUOUS(self->flags)) {
2872 mem = PyMem_Malloc(view->len);
2873 if (mem == NULL) {
2874 PyErr_NoMemory();
2875 return -1;
2876 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002877 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002878 PyMem_Free(mem);
2879 return -1;
2880 }
2881 }
2882
2883 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002884 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002885
2886 if (mem != view->buf)
2887 PyMem_Free(mem);
2888 }
2889
2890 return self->hash;
2891}
2892
2893
2894/**************************************************************************/
2895/* getters */
2896/**************************************************************************/
2897
2898static PyObject *
2899_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2900{
2901 int i;
2902 PyObject *o;
2903 PyObject *intTuple;
2904
2905 if (vals == NULL)
2906 return PyTuple_New(0);
2907
2908 intTuple = PyTuple_New(len);
2909 if (!intTuple)
2910 return NULL;
2911 for (i=0; i<len; i++) {
2912 o = PyLong_FromSsize_t(vals[i]);
2913 if (!o) {
2914 Py_DECREF(intTuple);
2915 return NULL;
2916 }
2917 PyTuple_SET_ITEM(intTuple, i, o);
2918 }
2919 return intTuple;
2920}
2921
2922static PyObject *
2923memory_obj_get(PyMemoryViewObject *self)
2924{
2925 Py_buffer *view = &self->view;
2926
2927 CHECK_RELEASED(self);
2928 if (view->obj == NULL) {
2929 Py_RETURN_NONE;
2930 }
2931 Py_INCREF(view->obj);
2932 return view->obj;
2933}
2934
2935static PyObject *
2936memory_nbytes_get(PyMemoryViewObject *self)
2937{
2938 CHECK_RELEASED(self);
2939 return PyLong_FromSsize_t(self->view.len);
2940}
2941
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002942static PyObject *
2943memory_format_get(PyMemoryViewObject *self)
2944{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002945 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002946 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002947}
2948
2949static PyObject *
2950memory_itemsize_get(PyMemoryViewObject *self)
2951{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002952 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002953 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002954}
2955
2956static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002957memory_shape_get(PyMemoryViewObject *self)
2958{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002959 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002960 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002961}
2962
2963static PyObject *
2964memory_strides_get(PyMemoryViewObject *self)
2965{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002966 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002967 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002968}
2969
2970static PyObject *
2971memory_suboffsets_get(PyMemoryViewObject *self)
2972{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002973 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002974 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002975}
2976
2977static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002978memory_readonly_get(PyMemoryViewObject *self)
2979{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002980 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002981 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002982}
2983
2984static PyObject *
2985memory_ndim_get(PyMemoryViewObject *self)
2986{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002987 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002988 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002989}
2990
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002991static PyObject *
2992memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2993{
2994 CHECK_RELEASED(self);
2995 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
2996}
2997
2998static PyObject *
2999memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3000{
3001 CHECK_RELEASED(self);
3002 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3003}
3004
3005static PyObject *
3006memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3007{
3008 CHECK_RELEASED(self);
3009 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3010}
3011
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003012PyDoc_STRVAR(memory_obj_doc,
3013 "The underlying object of the memoryview.");
3014PyDoc_STRVAR(memory_nbytes_doc,
3015 "The amount of space in bytes that the array would use in\n"
3016 " a contiguous representation.");
3017PyDoc_STRVAR(memory_readonly_doc,
3018 "A bool indicating whether the memory is read only.");
3019PyDoc_STRVAR(memory_itemsize_doc,
3020 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003021PyDoc_STRVAR(memory_format_doc,
3022 "A string containing the format (in struct module style)\n"
3023 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003024PyDoc_STRVAR(memory_ndim_doc,
3025 "An integer indicating how many dimensions of a multi-dimensional\n"
3026 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003027PyDoc_STRVAR(memory_shape_doc,
3028 "A tuple of ndim integers giving the shape of the memory\n"
3029 " as an N-dimensional array.");
3030PyDoc_STRVAR(memory_strides_doc,
3031 "A tuple of ndim integers giving the size in bytes to access\n"
3032 " each element for each dimension of the array.");
3033PyDoc_STRVAR(memory_suboffsets_doc,
3034 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003035PyDoc_STRVAR(memory_c_contiguous_doc,
3036 "A bool indicating whether the memory is C contiguous.");
3037PyDoc_STRVAR(memory_f_contiguous_doc,
3038 "A bool indicating whether the memory is Fortran contiguous.");
3039PyDoc_STRVAR(memory_contiguous_doc,
3040 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003041
Stefan Krahbcaf5992014-05-18 00:35:09 +02003042
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003043static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003044 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3045 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003046 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3047 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3048 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3049 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3050 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3051 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3052 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003053 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3054 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3055 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003056 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003057};
3058
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003059PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003060"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003061\n\
3062Release the underlying buffer exposed by the memoryview object.");
3063PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003064"tobytes($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003065\n\
3066Return the data in the buffer as a byte string.");
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003067PyDoc_STRVAR(memory_hex_doc,
3068"hex($self, /)\n--\n\
3069\n\
3070Return the data in the buffer as a string of hexadecimal numbers.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003071PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003072"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003073\n\
3074Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003075PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003076"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003077\n\
3078Cast a memoryview to a new format or shape.");
Antoine Pitrou480ab052018-04-14 19:49:21 +02003079PyDoc_STRVAR(memory_toreadonly_doc,
3080"toreadonly($self, /)\n--\n\
3081\n\
3082Return a readonly version of the memoryview.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003083
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003084static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003085 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3086 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003087 {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003088 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003089 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Antoine Pitrou480ab052018-04-14 19:49:21 +02003090 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003091 {"__enter__", memory_enter, METH_NOARGS, NULL},
3092 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003093 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003094};
3095
3096
3097PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003098 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003099 "memoryview", /* tp_name */
3100 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3101 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003102 (destructor)memory_dealloc, /* tp_dealloc */
3103 0, /* tp_print */
3104 0, /* tp_getattr */
3105 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003106 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003107 (reprfunc)memory_repr, /* tp_repr */
3108 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003109 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003110 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003111 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003112 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003113 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003114 PyObject_GenericGetAttr, /* tp_getattro */
3115 0, /* tp_setattro */
3116 &memory_as_buffer, /* tp_as_buffer */
3117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3118 memory_doc, /* tp_doc */
3119 (traverseproc)memory_traverse, /* tp_traverse */
3120 (inquiry)memory_clear, /* tp_clear */
3121 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003122 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003123 0, /* tp_iter */
3124 0, /* tp_iternext */
3125 memory_methods, /* tp_methods */
3126 0, /* tp_members */
3127 memory_getsetlist, /* tp_getset */
3128 0, /* tp_base */
3129 0, /* tp_dict */
3130 0, /* tp_descr_get */
3131 0, /* tp_descr_set */
3132 0, /* tp_dictoffset */
3133 0, /* tp_init */
3134 0, /* tp_alloc */
3135 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003136};