blob: d835704bdaae306fc2dd18a9a64d7f01d1d50119 [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 *
Stefan Krahd08ea702019-02-02 18:57:41 +01002123memory_tobytes(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002124{
Stefan Krahd08ea702019-02-02 18:57:41 +01002125 static char *kwlist[] = {"order", NULL};
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002126 Py_buffer *src = VIEW_ADDR(self);
Stefan Krahd08ea702019-02-02 18:57:41 +01002127 char *order = NULL;
2128 char ord = 'C';
2129 PyObject *bytes;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002130
2131 CHECK_RELEASED(self);
2132
Stefan Krahd08ea702019-02-02 18:57:41 +01002133 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z", kwlist, &order)) {
2134 return NULL;
2135 }
2136
2137 if (order) {
2138 if (strcmp(order, "F") == 0) {
2139 ord = 'F';
2140 }
2141 else if (strcmp(order, "A") == 0) {
2142 ord = 'A';
2143 }
2144 else if (strcmp(order, "C") != 0) {
2145 PyErr_SetString(PyExc_ValueError,
2146 "order must be 'C', 'F' or 'A'");
2147 return NULL;
2148 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002149 }
2150
2151 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2152 if (bytes == NULL)
2153 return NULL;
2154
Stefan Krahd08ea702019-02-02 18:57:41 +01002155 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, ord) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002156 Py_DECREF(bytes);
2157 return NULL;
2158 }
2159
2160 return bytes;
2161}
2162
2163static PyObject *
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002164memory_hex(PyMemoryViewObject *self, PyObject *dummy)
2165{
2166 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002167 PyObject *bytes;
2168 PyObject *ret;
2169
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002170 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002171
2172 if (MV_C_CONTIGUOUS(self->flags)) {
2173 return _Py_strhex(src->buf, src->len);
2174 }
2175
Stefan Krahd08ea702019-02-02 18:57:41 +01002176 bytes = PyBytes_FromStringAndSize(NULL, src->len);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002177 if (bytes == NULL)
2178 return NULL;
2179
Stefan Krahd08ea702019-02-02 18:57:41 +01002180 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, 'C') < 0) {
2181 Py_DECREF(bytes);
2182 return NULL;
2183 }
2184
Serhiy Storchakafff9a312017-03-21 08:53:25 +02002185 ret = _Py_strhex(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002186 Py_DECREF(bytes);
2187
2188 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002189}
2190
2191static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002192memory_repr(PyMemoryViewObject *self)
2193{
2194 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2195 return PyUnicode_FromFormat("<released memory at %p>", self);
2196 else
2197 return PyUnicode_FromFormat("<memory at %p>", self);
2198}
2199
2200
2201/**************************************************************************/
2202/* Indexing and slicing */
2203/**************************************************************************/
2204
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002205static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002206lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002207{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002208 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002209
2210 assert(view->shape);
2211 assert(view->strides);
2212
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002213 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002214 if (index < 0) {
2215 index += nitems;
2216 }
2217 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002218 PyErr_Format(PyExc_IndexError,
2219 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002220 return NULL;
2221 }
2222
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002223 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002224
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002225 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002226
2227 return ptr;
2228}
2229
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002230/* Get the pointer to the item at index. */
2231static char *
2232ptr_from_index(Py_buffer *view, Py_ssize_t index)
2233{
2234 char *ptr = (char *)view->buf;
2235 return lookup_dimension(view, ptr, 0, index);
2236}
2237
2238/* Get the pointer to the item at tuple. */
2239static char *
2240ptr_from_tuple(Py_buffer *view, PyObject *tup)
2241{
2242 char *ptr = (char *)view->buf;
2243 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2244
2245 if (nindices > view->ndim) {
2246 PyErr_Format(PyExc_TypeError,
2247 "cannot index %zd-dimension view with %zd-element tuple",
2248 view->ndim, nindices);
2249 return NULL;
2250 }
2251
2252 for (dim = 0; dim < nindices; dim++) {
2253 Py_ssize_t index;
2254 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2255 PyExc_IndexError);
2256 if (index == -1 && PyErr_Occurred())
2257 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002258 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002259 if (ptr == NULL)
2260 return NULL;
2261 }
2262 return ptr;
2263}
2264
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002265/* Return the item at index. In a one-dimensional view, this is an object
2266 with the type specified by view->format. Otherwise, the item is a sub-view.
2267 The function is used in memory_subscript() and memory_as_sequence. */
2268static PyObject *
2269memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2270{
2271 Py_buffer *view = &(self->view);
2272 const char *fmt;
2273
2274 CHECK_RELEASED(self);
2275
2276 fmt = adjust_fmt(view);
2277 if (fmt == NULL)
2278 return NULL;
2279
2280 if (view->ndim == 0) {
2281 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2282 return NULL;
2283 }
2284 if (view->ndim == 1) {
2285 char *ptr = ptr_from_index(view, index);
2286 if (ptr == NULL)
2287 return NULL;
2288 return unpack_single(ptr, fmt);
2289 }
2290
2291 PyErr_SetString(PyExc_NotImplementedError,
2292 "multi-dimensional sub-views are not implemented");
2293 return NULL;
2294}
2295
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002296/* Return the item at position *key* (a tuple of indices). */
2297static PyObject *
2298memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2299{
2300 Py_buffer *view = &(self->view);
2301 const char *fmt;
2302 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2303 char *ptr;
2304
2305 CHECK_RELEASED(self);
2306
2307 fmt = adjust_fmt(view);
2308 if (fmt == NULL)
2309 return NULL;
2310
2311 if (nindices < view->ndim) {
2312 PyErr_SetString(PyExc_NotImplementedError,
2313 "sub-views are not implemented");
2314 return NULL;
2315 }
2316 ptr = ptr_from_tuple(view, tup);
2317 if (ptr == NULL)
2318 return NULL;
2319 return unpack_single(ptr, fmt);
2320}
2321
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002322static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002323init_slice(Py_buffer *base, PyObject *key, int dim)
2324{
2325 Py_ssize_t start, stop, step, slicelength;
2326
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002327 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002328 return -1;
2329 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002330 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002331
2332
2333 if (base->suboffsets == NULL || dim == 0) {
2334 adjust_buf:
2335 base->buf = (char *)base->buf + base->strides[dim] * start;
2336 }
2337 else {
2338 Py_ssize_t n = dim-1;
2339 while (n >= 0 && base->suboffsets[n] < 0)
2340 n--;
2341 if (n < 0)
2342 goto adjust_buf; /* all suboffsets are negative */
2343 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2344 }
2345 base->shape[dim] = slicelength;
2346 base->strides[dim] = base->strides[dim] * step;
2347
2348 return 0;
2349}
2350
2351static int
2352is_multislice(PyObject *key)
2353{
2354 Py_ssize_t size, i;
2355
2356 if (!PyTuple_Check(key))
2357 return 0;
2358 size = PyTuple_GET_SIZE(key);
2359 if (size == 0)
2360 return 0;
2361
2362 for (i = 0; i < size; i++) {
2363 PyObject *x = PyTuple_GET_ITEM(key, i);
2364 if (!PySlice_Check(x))
2365 return 0;
2366 }
2367 return 1;
2368}
2369
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002370static Py_ssize_t
2371is_multiindex(PyObject *key)
2372{
2373 Py_ssize_t size, i;
2374
2375 if (!PyTuple_Check(key))
2376 return 0;
2377 size = PyTuple_GET_SIZE(key);
2378 for (i = 0; i < size; i++) {
2379 PyObject *x = PyTuple_GET_ITEM(key, i);
2380 if (!PyIndex_Check(x))
2381 return 0;
2382 }
2383 return 1;
2384}
2385
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002386/* mv[obj] returns an object holding the data for one element if obj
2387 fully indexes the memoryview or another memoryview object if it
2388 does not.
2389
2390 0-d memoryview objects can be referenced using mv[...] or mv[()]
2391 but not with anything else. */
2392static PyObject *
2393memory_subscript(PyMemoryViewObject *self, PyObject *key)
2394{
2395 Py_buffer *view;
2396 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002397
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002398 CHECK_RELEASED(self);
2399
2400 if (view->ndim == 0) {
2401 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2402 const char *fmt = adjust_fmt(view);
2403 if (fmt == NULL)
2404 return NULL;
2405 return unpack_single(view->buf, fmt);
2406 }
2407 else if (key == Py_Ellipsis) {
2408 Py_INCREF(self);
2409 return (PyObject *)self;
2410 }
2411 else {
2412 PyErr_SetString(PyExc_TypeError,
2413 "invalid indexing of 0-dim memory");
2414 return NULL;
2415 }
2416 }
2417
2418 if (PyIndex_Check(key)) {
2419 Py_ssize_t index;
2420 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2421 if (index == -1 && PyErr_Occurred())
2422 return NULL;
2423 return memory_item(self, index);
2424 }
2425 else if (PySlice_Check(key)) {
2426 PyMemoryViewObject *sliced;
2427
2428 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2429 if (sliced == NULL)
2430 return NULL;
2431
2432 if (init_slice(&sliced->view, key, 0) < 0) {
2433 Py_DECREF(sliced);
2434 return NULL;
2435 }
2436 init_len(&sliced->view);
2437 init_flags(sliced);
2438
2439 return (PyObject *)sliced;
2440 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002441 else if (is_multiindex(key)) {
2442 return memory_item_multi(self, key);
2443 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002444 else if (is_multislice(key)) {
2445 PyErr_SetString(PyExc_NotImplementedError,
2446 "multi-dimensional slicing is not implemented");
2447 return NULL;
2448 }
2449
2450 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2451 return NULL;
2452}
2453
2454static int
2455memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2456{
2457 Py_buffer *view = &(self->view);
2458 Py_buffer src;
2459 const char *fmt;
2460 char *ptr;
2461
2462 CHECK_RELEASED_INT(self);
2463
2464 fmt = adjust_fmt(view);
2465 if (fmt == NULL)
2466 return -1;
2467
2468 if (view->readonly) {
2469 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2470 return -1;
2471 }
2472 if (value == NULL) {
2473 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2474 return -1;
2475 }
2476 if (view->ndim == 0) {
2477 if (key == Py_Ellipsis ||
2478 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2479 ptr = (char *)view->buf;
2480 return pack_single(ptr, value, fmt);
2481 }
2482 else {
2483 PyErr_SetString(PyExc_TypeError,
2484 "invalid indexing of 0-dim memory");
2485 return -1;
2486 }
2487 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002488
2489 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002490 Py_ssize_t index;
2491 if (1 < view->ndim) {
2492 PyErr_SetString(PyExc_NotImplementedError,
2493 "sub-views are not implemented");
2494 return -1;
2495 }
2496 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002497 if (index == -1 && PyErr_Occurred())
2498 return -1;
2499 ptr = ptr_from_index(view, index);
2500 if (ptr == NULL)
2501 return -1;
2502 return pack_single(ptr, value, fmt);
2503 }
2504 /* one-dimensional: fast path */
2505 if (PySlice_Check(key) && view->ndim == 1) {
2506 Py_buffer dest; /* sliced view */
2507 Py_ssize_t arrays[3];
2508 int ret = -1;
2509
2510 /* rvalue must be an exporter */
2511 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2512 return ret;
2513
2514 dest = *view;
2515 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2516 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2517 if (view->suboffsets) {
2518 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2519 }
2520
2521 if (init_slice(&dest, key, 0) < 0)
2522 goto end_block;
2523 dest.len = dest.shape[0] * dest.itemsize;
2524
2525 ret = copy_single(&dest, &src);
2526
2527 end_block:
2528 PyBuffer_Release(&src);
2529 return ret;
2530 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002531 if (is_multiindex(key)) {
2532 char *ptr;
2533 if (PyTuple_GET_SIZE(key) < view->ndim) {
2534 PyErr_SetString(PyExc_NotImplementedError,
2535 "sub-views are not implemented");
2536 return -1;
2537 }
2538 ptr = ptr_from_tuple(view, key);
2539 if (ptr == NULL)
2540 return -1;
2541 return pack_single(ptr, value, fmt);
2542 }
2543 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002544 /* Call memory_subscript() to produce a sliced lvalue, then copy
2545 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2546 PyErr_SetString(PyExc_NotImplementedError,
2547 "memoryview slice assignments are currently restricted "
2548 "to ndim = 1");
2549 return -1;
2550 }
2551
2552 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2553 return -1;
2554}
2555
2556static Py_ssize_t
2557memory_length(PyMemoryViewObject *self)
2558{
2559 CHECK_RELEASED_INT(self);
2560 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2561}
2562
2563/* As mapping */
2564static PyMappingMethods memory_as_mapping = {
2565 (lenfunc)memory_length, /* mp_length */
2566 (binaryfunc)memory_subscript, /* mp_subscript */
2567 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2568};
2569
2570/* As sequence */
2571static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002572 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002573 0, /* sq_concat */
2574 0, /* sq_repeat */
2575 (ssizeargfunc)memory_item, /* sq_item */
2576};
2577
2578
2579/**************************************************************************/
2580/* Comparisons */
2581/**************************************************************************/
2582
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002583#define MV_COMPARE_EX -1 /* exception */
2584#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2585
2586/* Translate a StructError to "not equal". Preserve other exceptions. */
2587static int
2588fix_struct_error_int(void)
2589{
2590 assert(PyErr_Occurred());
2591 /* XXX Cannot get at StructError directly? */
2592 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2593 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2594 return MV_COMPARE_EX;
2595 }
2596 /* StructError: invalid or unknown format -> not equal */
2597 PyErr_Clear();
2598 return 0;
2599}
2600
2601/* Unpack and compare single items of p and q using the struct module. */
2602static int
2603struct_unpack_cmp(const char *p, const char *q,
2604 struct unpacker *unpack_p, struct unpacker *unpack_q)
2605{
2606 PyObject *v, *w;
2607 int ret;
2608
2609 /* At this point any exception from the struct module should not be
2610 StructError, since both formats have been accepted already. */
2611 v = struct_unpack_single(p, unpack_p);
2612 if (v == NULL)
2613 return MV_COMPARE_EX;
2614
2615 w = struct_unpack_single(q, unpack_q);
2616 if (w == NULL) {
2617 Py_DECREF(v);
2618 return MV_COMPARE_EX;
2619 }
2620
2621 /* MV_COMPARE_EX == -1: exceptions are preserved */
2622 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2623 Py_DECREF(v);
2624 Py_DECREF(w);
2625
2626 return ret;
2627}
2628
2629/* Unpack and compare single items of p and q. If both p and q have the same
2630 single element native format, the comparison uses a fast path (gcc creates
2631 a jump table and converts memcpy into simple assignments on x86/x64).
2632
2633 Otherwise, the comparison is delegated to the struct module, which is
2634 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002635#define CMP_SINGLE(p, q, type) \
2636 do { \
2637 type x; \
2638 type y; \
2639 memcpy((char *)&x, p, sizeof x); \
2640 memcpy((char *)&y, q, sizeof y); \
2641 equal = (x == y); \
2642 } while (0)
2643
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002644static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002645unpack_cmp(const char *p, const char *q, char fmt,
2646 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002647{
2648 int equal;
2649
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002650 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002651
2652 /* signed integers and fast path for 'B' */
2653 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2654 case 'b': return *((signed char *)p) == *((signed char *)q);
2655 case 'h': CMP_SINGLE(p, q, short); return equal;
2656 case 'i': CMP_SINGLE(p, q, int); return equal;
2657 case 'l': CMP_SINGLE(p, q, long); return equal;
2658
2659 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002660 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002661
2662 /* unsigned integers */
2663 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2664 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2665 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2666
2667 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002668 case 'q': CMP_SINGLE(p, q, long long); return equal;
2669 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002670
2671 /* ssize_t and size_t */
2672 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2673 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2674
2675 /* floats */
2676 /* XXX DBL_EPSILON? */
2677 case 'f': CMP_SINGLE(p, q, float); return equal;
2678 case 'd': CMP_SINGLE(p, q, double); return equal;
2679
2680 /* bytes object */
2681 case 'c': return *p == *q;
2682
2683 /* pointer */
2684 case 'P': CMP_SINGLE(p, q, void *); return equal;
2685
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002686 /* use the struct module */
2687 case '_':
2688 assert(unpack_p);
2689 assert(unpack_q);
2690 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002691 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002692
2693 /* NOT REACHED */
2694 PyErr_SetString(PyExc_RuntimeError,
2695 "memoryview: internal error in richcompare");
2696 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002697}
2698
2699/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2700static int
2701cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2702 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2703 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002704 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002705{
2706 Py_ssize_t i;
2707 int equal;
2708
2709 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002710 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2711 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002712 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002713 if (equal <= 0)
2714 return equal;
2715 }
2716
2717 return 1;
2718}
2719
2720/* Recursively compare two multi-dimensional arrays that have the same
2721 logical structure. Assumption: ndim >= 1. */
2722static int
2723cmp_rec(const char *p, const char *q,
2724 Py_ssize_t ndim, const Py_ssize_t *shape,
2725 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2726 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002727 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002728{
2729 Py_ssize_t i;
2730 int equal;
2731
2732 assert(ndim >= 1);
2733 assert(shape != NULL);
2734 assert(pstrides != NULL);
2735 assert(qstrides != NULL);
2736
2737 if (ndim == 1) {
2738 return cmp_base(p, q, shape,
2739 pstrides, psuboffsets,
2740 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002741 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002742 }
2743
2744 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002745 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2746 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002747 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2748 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2749 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002750 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002751 if (equal <= 0)
2752 return equal;
2753 }
2754
2755 return 1;
2756}
2757
2758static PyObject *
2759memory_richcompare(PyObject *v, PyObject *w, int op)
2760{
2761 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002762 Py_buffer wbuf, *vv;
2763 Py_buffer *ww = NULL;
2764 struct unpacker *unpack_v = NULL;
2765 struct unpacker *unpack_w = NULL;
2766 char vfmt, wfmt;
2767 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002768
2769 if (op != Py_EQ && op != Py_NE)
2770 goto result; /* Py_NotImplemented */
2771
2772 assert(PyMemoryView_Check(v));
2773 if (BASE_INACCESSIBLE(v)) {
2774 equal = (v == w);
2775 goto result;
2776 }
2777 vv = VIEW_ADDR(v);
2778
2779 if (PyMemoryView_Check(w)) {
2780 if (BASE_INACCESSIBLE(w)) {
2781 equal = (v == w);
2782 goto result;
2783 }
2784 ww = VIEW_ADDR(w);
2785 }
2786 else {
2787 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2788 PyErr_Clear();
2789 goto result; /* Py_NotImplemented */
2790 }
2791 ww = &wbuf;
2792 }
2793
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002794 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002795 PyErr_Clear();
2796 equal = 0;
2797 goto result;
2798 }
2799
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002800 /* Use fast unpacking for identical primitive C type formats. */
2801 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2802 vfmt = '_';
2803 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2804 wfmt = '_';
2805 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2806 /* Use struct module unpacking. NOTE: Even for equal format strings,
2807 memcmp() cannot be used for item comparison since it would give
2808 incorrect results in the case of NaNs or uninitialized padding
2809 bytes. */
2810 vfmt = '_';
2811 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2812 if (unpack_v == NULL) {
2813 equal = fix_struct_error_int();
2814 goto result;
2815 }
2816 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2817 if (unpack_w == NULL) {
2818 equal = fix_struct_error_int();
2819 goto result;
2820 }
2821 }
2822
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002823 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002824 equal = unpack_cmp(vv->buf, ww->buf,
2825 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002826 }
2827 else if (vv->ndim == 1) {
2828 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2829 vv->strides, vv->suboffsets,
2830 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002831 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002832 }
2833 else {
2834 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2835 vv->strides, vv->suboffsets,
2836 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002837 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002838 }
2839
2840result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002841 if (equal < 0) {
2842 if (equal == MV_COMPARE_NOT_IMPL)
2843 res = Py_NotImplemented;
2844 else /* exception */
2845 res = NULL;
2846 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002847 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2848 res = Py_True;
2849 else
2850 res = Py_False;
2851
2852 if (ww == &wbuf)
2853 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002854
2855 unpacker_free(unpack_v);
2856 unpacker_free(unpack_w);
2857
2858 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002859 return res;
2860}
2861
2862/**************************************************************************/
2863/* Hash */
2864/**************************************************************************/
2865
2866static Py_hash_t
2867memory_hash(PyMemoryViewObject *self)
2868{
2869 if (self->hash == -1) {
2870 Py_buffer *view = &self->view;
2871 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002872 Py_ssize_t ret;
2873 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002874
2875 CHECK_RELEASED_INT(self);
2876
2877 if (!view->readonly) {
2878 PyErr_SetString(PyExc_ValueError,
2879 "cannot hash writable memoryview object");
2880 return -1;
2881 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002882 ret = get_native_fmtchar(&fmt, view->format);
2883 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2884 PyErr_SetString(PyExc_ValueError,
2885 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2886 return -1;
2887 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002888 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2889 /* Keep the original error message */
2890 return -1;
2891 }
2892
2893 if (!MV_C_CONTIGUOUS(self->flags)) {
2894 mem = PyMem_Malloc(view->len);
2895 if (mem == NULL) {
2896 PyErr_NoMemory();
2897 return -1;
2898 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002899 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002900 PyMem_Free(mem);
2901 return -1;
2902 }
2903 }
2904
2905 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002906 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002907
2908 if (mem != view->buf)
2909 PyMem_Free(mem);
2910 }
2911
2912 return self->hash;
2913}
2914
2915
2916/**************************************************************************/
2917/* getters */
2918/**************************************************************************/
2919
2920static PyObject *
2921_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2922{
2923 int i;
2924 PyObject *o;
2925 PyObject *intTuple;
2926
2927 if (vals == NULL)
2928 return PyTuple_New(0);
2929
2930 intTuple = PyTuple_New(len);
2931 if (!intTuple)
2932 return NULL;
2933 for (i=0; i<len; i++) {
2934 o = PyLong_FromSsize_t(vals[i]);
2935 if (!o) {
2936 Py_DECREF(intTuple);
2937 return NULL;
2938 }
2939 PyTuple_SET_ITEM(intTuple, i, o);
2940 }
2941 return intTuple;
2942}
2943
2944static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002945memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002946{
2947 Py_buffer *view = &self->view;
2948
2949 CHECK_RELEASED(self);
2950 if (view->obj == NULL) {
2951 Py_RETURN_NONE;
2952 }
2953 Py_INCREF(view->obj);
2954 return view->obj;
2955}
2956
2957static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002958memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002959{
2960 CHECK_RELEASED(self);
2961 return PyLong_FromSsize_t(self->view.len);
2962}
2963
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002964static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002965memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002966{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002967 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002968 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002969}
2970
2971static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002972memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002973{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002974 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002975 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002976}
2977
2978static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002979memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002980{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002981 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002982 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002983}
2984
2985static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002986memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002987{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002988 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002989 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002990}
2991
2992static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002993memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002994{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002995 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002996 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002997}
2998
2999static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003000memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003001{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003002 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003003 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003004}
3005
3006static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003007memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003008{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003009 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003010 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003011}
3012
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003013static PyObject *
3014memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3015{
3016 CHECK_RELEASED(self);
3017 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3018}
3019
3020static PyObject *
3021memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3022{
3023 CHECK_RELEASED(self);
3024 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3025}
3026
3027static PyObject *
3028memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3029{
3030 CHECK_RELEASED(self);
3031 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3032}
3033
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003034PyDoc_STRVAR(memory_obj_doc,
3035 "The underlying object of the memoryview.");
3036PyDoc_STRVAR(memory_nbytes_doc,
3037 "The amount of space in bytes that the array would use in\n"
3038 " a contiguous representation.");
3039PyDoc_STRVAR(memory_readonly_doc,
3040 "A bool indicating whether the memory is read only.");
3041PyDoc_STRVAR(memory_itemsize_doc,
3042 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003043PyDoc_STRVAR(memory_format_doc,
3044 "A string containing the format (in struct module style)\n"
3045 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003046PyDoc_STRVAR(memory_ndim_doc,
3047 "An integer indicating how many dimensions of a multi-dimensional\n"
3048 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003049PyDoc_STRVAR(memory_shape_doc,
3050 "A tuple of ndim integers giving the shape of the memory\n"
3051 " as an N-dimensional array.");
3052PyDoc_STRVAR(memory_strides_doc,
3053 "A tuple of ndim integers giving the size in bytes to access\n"
3054 " each element for each dimension of the array.");
3055PyDoc_STRVAR(memory_suboffsets_doc,
3056 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003057PyDoc_STRVAR(memory_c_contiguous_doc,
3058 "A bool indicating whether the memory is C contiguous.");
3059PyDoc_STRVAR(memory_f_contiguous_doc,
3060 "A bool indicating whether the memory is Fortran contiguous.");
3061PyDoc_STRVAR(memory_contiguous_doc,
3062 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003063
Stefan Krahbcaf5992014-05-18 00:35:09 +02003064
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003065static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003066 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3067 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003068 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3069 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3070 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3071 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3072 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3073 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3074 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003075 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3076 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3077 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003078 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003079};
3080
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003081PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003082"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003083\n\
3084Release the underlying buffer exposed by the memoryview object.");
3085PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahd08ea702019-02-02 18:57:41 +01003086"tobytes($self, /, order=None)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003087\n\
Stefan Krahd08ea702019-02-02 18:57:41 +01003088Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
3089When order is 'C' or 'F', the data of the original array is converted to C or\n\
3090Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
3091memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
3092views, the data is converted to C first. order=None is the same as order='C'.");
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003093PyDoc_STRVAR(memory_hex_doc,
3094"hex($self, /)\n--\n\
3095\n\
3096Return the data in the buffer as a string of hexadecimal numbers.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003097PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003098"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003099\n\
3100Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003101PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003102"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003103\n\
3104Cast a memoryview to a new format or shape.");
Antoine Pitrou480ab052018-04-14 19:49:21 +02003105PyDoc_STRVAR(memory_toreadonly_doc,
3106"toreadonly($self, /)\n--\n\
3107\n\
3108Return a readonly version of the memoryview.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003109
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003110static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003111 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
Stefan Krahd08ea702019-02-02 18:57:41 +01003112 {"tobytes", (PyCFunction)memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003113 {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003114 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02003115 {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Antoine Pitrou480ab052018-04-14 19:49:21 +02003116 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003117 {"__enter__", memory_enter, METH_NOARGS, NULL},
3118 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003119 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003120};
3121
3122
3123PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003124 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003125 "memoryview", /* tp_name */
3126 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3127 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003128 (destructor)memory_dealloc, /* tp_dealloc */
3129 0, /* tp_print */
3130 0, /* tp_getattr */
3131 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003132 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003133 (reprfunc)memory_repr, /* tp_repr */
3134 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003135 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003136 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003137 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003138 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003139 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003140 PyObject_GenericGetAttr, /* tp_getattro */
3141 0, /* tp_setattro */
3142 &memory_as_buffer, /* tp_as_buffer */
3143 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3144 memory_doc, /* tp_doc */
3145 (traverseproc)memory_traverse, /* tp_traverse */
3146 (inquiry)memory_clear, /* tp_clear */
3147 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003148 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003149 0, /* tp_iter */
3150 0, /* tp_iternext */
3151 memory_methods, /* tp_methods */
3152 0, /* tp_members */
3153 memory_getsetlist, /* tp_getset */
3154 0, /* tp_base */
3155 0, /* tp_dict */
3156 0, /* tp_descr_get */
3157 0, /* tp_descr_set */
3158 0, /* tp_dictoffset */
3159 0, /* tp_init */
3160 0, /* tp_alloc */
3161 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003162};