blob: 682bbe8a61e85e0ba190db2c1c75ba86c7190e1c [file] [log] [blame]
Stefan Krahee3bac42020-02-24 11:15:26 +01001/*
2 * Memoryview object implementation
3 * --------------------------------
4 *
5 * This implementation is a complete rewrite contributed by Stefan Krah in
6 * Python 3.3. Substantial credit goes to Antoine Pitrou (who had already
7 * fortified and rewritten the previous implementation) and Nick Coghlan
8 * (who came up with the idea of the ManagedBuffer) for analyzing the complex
9 * ownership rules.
10 *
11 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000012
13#include "Python.h"
Victor Stinnera15e2602020-04-08 02:01:56 +020014#include "pycore_abstract.h" // _PyIndex_Check()
Victor Stinnerbcda8f12018-11-21 22:27:47 +010015#include "pycore_object.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +000016#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +010017#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000018
Gregory P. Smith0c2f9302019-05-29 11:46:58 -070019/*[clinic input]
20class memoryview "PyMemoryViewObject *" "&PyMemoryView_Type"
21[clinic start generated code]*/
22/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2e49d2192835219]*/
23
24#include "clinic/memoryobject.c.h"
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000025
Stefan Krah9a2d99e2012-02-25 12:24:21 +010026/****************************************************************************/
27/* ManagedBuffer Object */
28/****************************************************************************/
29
30/*
31 ManagedBuffer Object:
32 ---------------------
33
34 The purpose of this object is to facilitate the handling of chained
35 memoryviews that have the same underlying exporting object. PEP-3118
36 allows the underlying object to change while a view is exported. This
37 could lead to unexpected results when constructing a new memoryview
38 from an existing memoryview.
39
40 Rather than repeatedly redirecting buffer requests to the original base
41 object, all chained memoryviews use a single buffer snapshot. This
42 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
43
44 Ownership rules:
45 ----------------
46
47 The master buffer inside a managed buffer is filled in by the original
48 base object. shape, strides, suboffsets and format are read-only for
49 all consumers.
50
51 A memoryview's buffer is a private copy of the exporter's buffer. shape,
52 strides and suboffsets belong to the memoryview and are thus writable.
53
54 If a memoryview itself exports several buffers via memory_getbuf(), all
55 buffer copies share shape, strides and suboffsets. In this case, the
56 arrays are NOT writable.
57
58 Reference count assumptions:
59 ----------------------------
60
61 The 'obj' member of a Py_buffer must either be NULL or refer to the
62 exporting base object. In the Python codebase, all getbufferprocs
63 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
64
65 PyBuffer_Release() decrements view.obj (if non-NULL), so the
66 releasebufferprocs must NOT decrement view.obj.
67*/
68
69
Stefan Krah9a2d99e2012-02-25 12:24:21 +010070#define CHECK_MBUF_RELEASED(mbuf) \
71 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
72 PyErr_SetString(PyExc_ValueError, \
73 "operation forbidden on released memoryview object"); \
74 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000075 }
76
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000077
Benjamin Peterson82cce4c2016-09-08 11:56:06 -070078static inline _PyManagedBufferObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +010079mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000080{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010081 _PyManagedBufferObject *mbuf;
82
83 mbuf = (_PyManagedBufferObject *)
84 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
85 if (mbuf == NULL)
86 return NULL;
87 mbuf->flags = 0;
88 mbuf->exports = 0;
89 mbuf->master.obj = NULL;
90 _PyObject_GC_TRACK(mbuf);
91
92 return mbuf;
93}
94
95static PyObject *
96_PyManagedBuffer_FromObject(PyObject *base)
97{
98 _PyManagedBufferObject *mbuf;
99
100 mbuf = mbuf_alloc();
101 if (mbuf == NULL)
102 return NULL;
103
104 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +0100105 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100106 Py_DECREF(mbuf);
107 return NULL;
108 }
109
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100110 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000111}
112
113static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100114mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000115{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100116 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
117 return;
118
119 /* NOTE: at this point self->exports can still be > 0 if this function
120 is called from mbuf_clear() to break up a reference cycle. */
121 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
122
123 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
124 _PyObject_GC_UNTRACK(self);
125 PyBuffer_Release(&self->master);
126}
127
128static void
129mbuf_dealloc(_PyManagedBufferObject *self)
130{
131 assert(self->exports == 0);
132 mbuf_release(self);
133 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
134 PyMem_Free(self->master.format);
135 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000136}
137
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000138static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100139mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000140{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100141 Py_VISIT(self->master.obj);
142 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000143}
144
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100145static int
146mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000147{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100148 assert(self->exports >= 0);
149 mbuf_release(self);
150 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000151}
152
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100153PyTypeObject _PyManagedBuffer_Type = {
154 PyVarObject_HEAD_INIT(&PyType_Type, 0)
155 "managedbuffer",
156 sizeof(_PyManagedBufferObject),
157 0,
158 (destructor)mbuf_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200159 0, /* tp_vectorcall_offset */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100160 0, /* tp_getattr */
161 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200162 0, /* tp_as_async */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100163 0, /* tp_repr */
164 0, /* tp_as_number */
165 0, /* tp_as_sequence */
166 0, /* tp_as_mapping */
167 0, /* tp_hash */
168 0, /* tp_call */
169 0, /* tp_str */
170 PyObject_GenericGetAttr, /* tp_getattro */
171 0, /* tp_setattro */
172 0, /* tp_as_buffer */
173 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
174 0, /* tp_doc */
175 (traverseproc)mbuf_traverse, /* tp_traverse */
176 (inquiry)mbuf_clear /* tp_clear */
177};
178
179
180/****************************************************************************/
181/* MemoryView Object */
182/****************************************************************************/
183
184/* In the process of breaking reference cycles mbuf_release() can be
185 called before memory_release(). */
186#define BASE_INACCESSIBLE(mv) \
187 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
188 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
189
190#define CHECK_RELEASED(mv) \
191 if (BASE_INACCESSIBLE(mv)) { \
192 PyErr_SetString(PyExc_ValueError, \
193 "operation forbidden on released memoryview object"); \
194 return NULL; \
195 }
196
197#define CHECK_RELEASED_INT(mv) \
198 if (BASE_INACCESSIBLE(mv)) { \
199 PyErr_SetString(PyExc_ValueError, \
200 "operation forbidden on released memoryview object"); \
201 return -1; \
202 }
203
204#define CHECK_LIST_OR_TUPLE(v) \
205 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
206 PyErr_SetString(PyExc_TypeError, \
207 #v " must be a list or a tuple"); \
208 return NULL; \
209 }
210
211#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
212
213/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100214#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100215/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100216#define ADJUST_PTR(ptr, suboffsets, dim) \
217 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100218
219/* Memoryview buffer properties */
220#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
221#define MV_F_CONTIGUOUS(flags) \
222 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
223#define MV_ANY_CONTIGUOUS(flags) \
224 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
225
226/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
227#define MV_CONTIGUOUS_NDIM1(view) \
228 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
229
230/* getbuffer() requests */
231#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
232#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
233#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
234#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
235#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
236#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
237#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
238#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
239
240
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000241PyDoc_STRVAR(memory_doc,
Stefan Krah195319e2016-12-30 12:23:35 +0100242"memoryview(object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000243\n\
244Create a new memoryview object which references the given object.");
245
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100246
247/**************************************************************************/
248/* Copy memoryview buffers */
249/**************************************************************************/
250
251/* The functions in this section take a source and a destination buffer
252 with the same logical structure: format, itemsize, ndim and shape
253 are identical, with ndim > 0.
254
255 NOTE: All buffers are assumed to have PyBUF_FULL information, which
256 is the case for memoryviews! */
257
258
259/* Assumptions: ndim >= 1. The macro tests for a corner case that should
260 perhaps be explicitly forbidden in the PEP. */
261#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
262 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
263
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700264static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000265last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100266{
267 assert(dest->ndim > 0 && src->ndim > 0);
268 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
269 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
270 dest->strides[dest->ndim-1] == dest->itemsize &&
271 src->strides[src->ndim-1] == src->itemsize);
272}
273
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000274/* This is not a general function for determining format equivalence.
275 It is used in copy_single() and copy_buffer() to weed out non-matching
276 formats. Skipping the '@' character is specifically used in slice
277 assignments, where the lvalue is already known to have a single character
278 format. This is a performance hack that could be rewritten (if properly
279 benchmarked). */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700280static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000281equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100282{
283 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100284
285 assert(dest->format && src->format);
286 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
287 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
288
289 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000290 dest->itemsize != src->itemsize) {
291 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100292 }
293
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000294 return 1;
295}
296
297/* Two shapes are equivalent if they are either equal or identical up
298 to a zero element at the same position. For example, in NumPy arrays
299 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700300static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000301equiv_shape(const Py_buffer *dest, const Py_buffer *src)
302{
303 int i;
304
305 if (dest->ndim != src->ndim)
306 return 0;
307
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100308 for (i = 0; i < dest->ndim; i++) {
309 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000310 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100311 if (dest->shape[i] == 0)
312 break;
313 }
314
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000315 return 1;
316}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100317
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000318/* Check that the logical structure of the destination and source buffers
319 is identical. */
320static int
321equiv_structure(const Py_buffer *dest, const Py_buffer *src)
322{
323 if (!equiv_format(dest, src) ||
324 !equiv_shape(dest, src)) {
325 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100326 "memoryview assignment: lvalue and rvalue have different "
327 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000328 return 0;
329 }
330
331 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100332}
333
334/* Base case for recursive multi-dimensional copying. Contiguous arrays are
335 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
336 sizeof(mem) == shape[0] * itemsize. */
337static void
338copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
339 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
340 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
341 char *mem)
342{
343 if (mem == NULL) { /* contiguous */
344 Py_ssize_t size = shape[0] * itemsize;
345 if (dptr + size < sptr || sptr + size < dptr)
346 memcpy(dptr, sptr, size); /* no overlapping */
347 else
348 memmove(dptr, sptr, size);
349 }
350 else {
351 char *p;
352 Py_ssize_t i;
353 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100354 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100355 memcpy(p, xsptr, itemsize);
356 }
357 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100358 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100359 memcpy(xdptr, p, itemsize);
360 }
361 }
362
363}
364
365/* Recursively copy a source buffer to a destination buffer. The two buffers
366 have the same ndim, shape and itemsize. */
367static void
368copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
369 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
370 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
371 char *mem)
372{
373 Py_ssize_t i;
374
375 assert(ndim >= 1);
376
377 if (ndim == 1) {
378 copy_base(shape, itemsize,
379 dptr, dstrides, dsuboffsets,
380 sptr, sstrides, ssuboffsets,
381 mem);
382 return;
383 }
384
385 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100386 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
387 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100388
389 copy_rec(shape+1, ndim-1, itemsize,
390 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
391 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
392 mem);
393 }
394}
395
396/* Faster copying of one-dimensional arrays. */
397static int
398copy_single(Py_buffer *dest, Py_buffer *src)
399{
400 char *mem = NULL;
401
402 assert(dest->ndim == 1);
403
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000404 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100405 return -1;
406
407 if (!last_dim_is_contiguous(dest, src)) {
408 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
409 if (mem == NULL) {
410 PyErr_NoMemory();
411 return -1;
412 }
413 }
414
415 copy_base(dest->shape, dest->itemsize,
416 dest->buf, dest->strides, dest->suboffsets,
417 src->buf, src->strides, src->suboffsets,
418 mem);
419
420 if (mem)
421 PyMem_Free(mem);
422
423 return 0;
424}
425
426/* Recursively copy src to dest. Both buffers must have the same basic
427 structure. Copying is atomic, the function never fails with a partial
428 copy. */
429static int
430copy_buffer(Py_buffer *dest, Py_buffer *src)
431{
432 char *mem = NULL;
433
434 assert(dest->ndim > 0);
435
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000436 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100437 return -1;
438
439 if (!last_dim_is_contiguous(dest, src)) {
440 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
441 if (mem == NULL) {
442 PyErr_NoMemory();
443 return -1;
444 }
445 }
446
447 copy_rec(dest->shape, dest->ndim, dest->itemsize,
448 dest->buf, dest->strides, dest->suboffsets,
449 src->buf, src->strides, src->suboffsets,
450 mem);
451
452 if (mem)
453 PyMem_Free(mem);
454
455 return 0;
456}
457
458/* Initialize strides for a C-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700459static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100460init_strides_from_shape(Py_buffer *view)
461{
462 Py_ssize_t i;
463
464 assert(view->ndim > 0);
465
466 view->strides[view->ndim-1] = view->itemsize;
467 for (i = view->ndim-2; i >= 0; i--)
468 view->strides[i] = view->strides[i+1] * view->shape[i+1];
469}
470
471/* Initialize strides for a Fortran-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700472static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100473init_fortran_strides_from_shape(Py_buffer *view)
474{
475 Py_ssize_t i;
476
477 assert(view->ndim > 0);
478
479 view->strides[0] = view->itemsize;
480 for (i = 1; i < view->ndim; i++)
481 view->strides[i] = view->strides[i-1] * view->shape[i-1];
482}
483
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200484/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
485 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100486 len(mem) == src->len. */
487static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200488buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100489{
490 Py_buffer dest;
491 Py_ssize_t *strides;
492 int ret;
493
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200494 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100495 assert(src->shape != NULL);
496 assert(src->strides != NULL);
497
498 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
499 if (strides == NULL) {
500 PyErr_NoMemory();
501 return -1;
502 }
503
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200504 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100505 dest = *src;
506 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200507 /* shape is constant and shared: the logical representation of the
508 array is unaltered. */
509
510 /* The physical representation determined by strides (and possibly
511 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100512 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200513 if (order == 'C' || order == 'A') {
514 init_strides_from_shape(&dest);
515 }
516 else {
517 init_fortran_strides_from_shape(&dest);
518 }
519
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100520 dest.suboffsets = NULL;
521
522 ret = copy_buffer(&dest, src);
523
524 PyMem_Free(strides);
525 return ret;
526}
527
528
529/****************************************************************************/
530/* Constructors */
531/****************************************************************************/
532
533/* Initialize values that are shared with the managed buffer. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700534static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100535init_shared_values(Py_buffer *dest, const Py_buffer *src)
536{
537 dest->obj = src->obj;
538 dest->buf = src->buf;
539 dest->len = src->len;
540 dest->itemsize = src->itemsize;
541 dest->readonly = src->readonly;
542 dest->format = src->format ? src->format : "B";
543 dest->internal = src->internal;
544}
545
546/* Copy shape and strides. Reconstruct missing values. */
547static void
548init_shape_strides(Py_buffer *dest, const Py_buffer *src)
549{
550 Py_ssize_t i;
551
552 if (src->ndim == 0) {
553 dest->shape = NULL;
554 dest->strides = NULL;
555 return;
556 }
557 if (src->ndim == 1) {
558 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
559 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
560 return;
561 }
562
563 for (i = 0; i < src->ndim; i++)
564 dest->shape[i] = src->shape[i];
565 if (src->strides) {
566 for (i = 0; i < src->ndim; i++)
567 dest->strides[i] = src->strides[i];
568 }
569 else {
570 init_strides_from_shape(dest);
571 }
572}
573
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700574static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100575init_suboffsets(Py_buffer *dest, const Py_buffer *src)
576{
577 Py_ssize_t i;
578
579 if (src->suboffsets == NULL) {
580 dest->suboffsets = NULL;
581 return;
582 }
583 for (i = 0; i < src->ndim; i++)
584 dest->suboffsets[i] = src->suboffsets[i];
585}
586
587/* len = product(shape) * itemsize */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700588static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100589init_len(Py_buffer *view)
590{
591 Py_ssize_t i, len;
592
593 len = 1;
594 for (i = 0; i < view->ndim; i++)
595 len *= view->shape[i];
596 len *= view->itemsize;
597
598 view->len = len;
599}
600
601/* Initialize memoryview buffer properties. */
602static void
603init_flags(PyMemoryViewObject *mv)
604{
605 const Py_buffer *view = &mv->view;
606 int flags = 0;
607
608 switch (view->ndim) {
609 case 0:
610 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
611 _Py_MEMORYVIEW_FORTRAN);
612 break;
613 case 1:
614 if (MV_CONTIGUOUS_NDIM1(view))
615 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
616 break;
617 default:
618 if (PyBuffer_IsContiguous(view, 'C'))
619 flags |= _Py_MEMORYVIEW_C;
620 if (PyBuffer_IsContiguous(view, 'F'))
621 flags |= _Py_MEMORYVIEW_FORTRAN;
622 break;
623 }
624
625 if (view->suboffsets) {
626 flags |= _Py_MEMORYVIEW_PIL;
627 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
628 }
629
630 mv->flags = flags;
631}
632
633/* Allocate a new memoryview and perform basic initialization. New memoryviews
634 are exclusively created through the mbuf_add functions. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700635static inline PyMemoryViewObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100636memory_alloc(int ndim)
637{
638 PyMemoryViewObject *mv;
639
640 mv = (PyMemoryViewObject *)
641 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
642 if (mv == NULL)
643 return NULL;
644
645 mv->mbuf = NULL;
646 mv->hash = -1;
647 mv->flags = 0;
648 mv->exports = 0;
649 mv->view.ndim = ndim;
650 mv->view.shape = mv->ob_array;
651 mv->view.strides = mv->ob_array + ndim;
652 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100653 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100654
655 _PyObject_GC_TRACK(mv);
656 return mv;
657}
658
659/*
660 Return a new memoryview that is registered with mbuf. If src is NULL,
661 use mbuf->master as the underlying buffer. Otherwise, use src.
662
663 The new memoryview has full buffer information: shape and strides
664 are always present, suboffsets as needed. Arrays are copied to
665 the memoryview's ob_array field.
666 */
667static PyObject *
668mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
669{
670 PyMemoryViewObject *mv;
671 Py_buffer *dest;
672
673 if (src == NULL)
674 src = &mbuf->master;
675
676 if (src->ndim > PyBUF_MAX_NDIM) {
677 PyErr_SetString(PyExc_ValueError,
678 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200679 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100680 return NULL;
681 }
682
683 mv = memory_alloc(src->ndim);
684 if (mv == NULL)
685 return NULL;
686
687 dest = &mv->view;
688 init_shared_values(dest, src);
689 init_shape_strides(dest, src);
690 init_suboffsets(dest, src);
691 init_flags(mv);
692
693 mv->mbuf = mbuf;
694 Py_INCREF(mbuf);
695 mbuf->exports++;
696
697 return (PyObject *)mv;
698}
699
700/* Register an incomplete view: shape, strides, suboffsets and flags still
701 need to be initialized. Use 'ndim' instead of src->ndim to determine the
702 size of the memoryview's ob_array.
703
704 Assumption: ndim <= PyBUF_MAX_NDIM. */
705static PyObject *
706mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
707 int ndim)
708{
709 PyMemoryViewObject *mv;
710 Py_buffer *dest;
711
712 if (src == NULL)
713 src = &mbuf->master;
714
715 assert(ndim <= PyBUF_MAX_NDIM);
716
717 mv = memory_alloc(ndim);
718 if (mv == NULL)
719 return NULL;
720
721 dest = &mv->view;
722 init_shared_values(dest, src);
723
724 mv->mbuf = mbuf;
725 Py_INCREF(mbuf);
726 mbuf->exports++;
727
728 return (PyObject *)mv;
729}
730
731/* Expose a raw memory area as a view of contiguous bytes. flags can be
732 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
733 The memoryview has complete buffer information. */
734PyObject *
735PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
736{
737 _PyManagedBufferObject *mbuf;
738 PyObject *mv;
739 int readonly;
740
741 assert(mem != NULL);
742 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
743
744 mbuf = mbuf_alloc();
745 if (mbuf == NULL)
746 return NULL;
747
748 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
749 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
750 PyBUF_FULL_RO);
751
752 mv = mbuf_add_view(mbuf, NULL);
753 Py_DECREF(mbuf);
754
755 return mv;
756}
757
758/* Create a memoryview from a given Py_buffer. For simple byte views,
759 PyMemoryView_FromMemory() should be used instead.
760 This function is the only entry point that can create a master buffer
761 without full information. Because of this fact init_shape_strides()
762 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000763PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000764PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000765{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100766 _PyManagedBufferObject *mbuf;
767 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000768
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000769 if (info->buf == NULL) {
770 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100771 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000772 return NULL;
773 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100774
775 mbuf = mbuf_alloc();
776 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000777 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100778
779 /* info->obj is either NULL or a borrowed reference. This reference
780 should not be decremented in PyBuffer_Release(). */
781 mbuf->master = *info;
782 mbuf->master.obj = NULL;
783
784 mv = mbuf_add_view(mbuf, NULL);
785 Py_DECREF(mbuf);
786
787 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000788}
789
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100790/* Create a memoryview from an object that implements the buffer protocol.
791 If the object is a memoryview, the new memoryview must be registered
792 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000793PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100794PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000795{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100796 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000797
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100798 if (PyMemoryView_Check(v)) {
799 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
800 CHECK_RELEASED(mv);
801 return mbuf_add_view(mv->mbuf, &mv->view);
802 }
803 else if (PyObject_CheckBuffer(v)) {
804 PyObject *ret;
805 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
806 if (mbuf == NULL)
807 return NULL;
808 ret = mbuf_add_view(mbuf, NULL);
809 Py_DECREF(mbuf);
810 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000811 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000812
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100813 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400814 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100815 Py_TYPE(v)->tp_name);
816 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000817}
818
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100819/* Copy the format string from a base object that might vanish. */
820static int
821mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
822{
823 if (fmt != NULL) {
824 char *cp = PyMem_Malloc(strlen(fmt)+1);
825 if (cp == NULL) {
826 PyErr_NoMemory();
827 return -1;
828 }
829 mbuf->master.format = strcpy(cp, fmt);
830 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
831 }
832
833 return 0;
834}
835
836/*
837 Return a memoryview that is based on a contiguous copy of src.
838 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
839
840 Ownership rules:
841 1) As usual, the returned memoryview has a private copy
842 of src->shape, src->strides and src->suboffsets.
843 2) src->format is copied to the master buffer and released
844 in mbuf_dealloc(). The releasebufferproc of the bytes
845 object is NULL, so it does not matter that mbuf_release()
846 passes the altered format pointer to PyBuffer_Release().
847*/
848static PyObject *
849memory_from_contiguous_copy(Py_buffer *src, char order)
850{
851 _PyManagedBufferObject *mbuf;
852 PyMemoryViewObject *mv;
853 PyObject *bytes;
854 Py_buffer *dest;
855 int i;
856
857 assert(src->ndim > 0);
858 assert(src->shape != NULL);
859
860 bytes = PyBytes_FromStringAndSize(NULL, src->len);
861 if (bytes == NULL)
862 return NULL;
863
864 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
865 Py_DECREF(bytes);
866 if (mbuf == NULL)
867 return NULL;
868
869 if (mbuf_copy_format(mbuf, src->format) < 0) {
870 Py_DECREF(mbuf);
871 return NULL;
872 }
873
874 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
875 Py_DECREF(mbuf);
876 if (mv == NULL)
877 return NULL;
878
879 dest = &mv->view;
880
881 /* shared values are initialized correctly except for itemsize */
882 dest->itemsize = src->itemsize;
883
884 /* shape and strides */
885 for (i = 0; i < src->ndim; i++) {
886 dest->shape[i] = src->shape[i];
887 }
888 if (order == 'C' || order == 'A') {
889 init_strides_from_shape(dest);
890 }
891 else {
892 init_fortran_strides_from_shape(dest);
893 }
894 /* suboffsets */
895 dest->suboffsets = NULL;
896
897 /* flags */
898 init_flags(mv);
899
900 if (copy_buffer(dest, src) < 0) {
901 Py_DECREF(mv);
902 return NULL;
903 }
904
905 return (PyObject *)mv;
906}
907
908/*
909 Return a new memoryview object based on a contiguous exporter with
910 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
911 The logical structure of the input and output buffers is the same
912 (i.e. tolist(input) == tolist(output)), but the physical layout in
913 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200914
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100915 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
916 otherwise it may be writable or read-only.
917
918 If the exporter is already contiguous with the desired target order,
919 the memoryview will be directly based on the exporter.
920
921 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
922 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
923 'F'ortran order otherwise.
924*/
925PyObject *
926PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
927{
928 PyMemoryViewObject *mv;
929 PyObject *ret;
930 Py_buffer *view;
931
932 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
933 assert(order == 'C' || order == 'F' || order == 'A');
934
935 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
936 if (mv == NULL)
937 return NULL;
938
939 view = &mv->view;
940 if (buffertype == PyBUF_WRITE && view->readonly) {
941 PyErr_SetString(PyExc_BufferError,
942 "underlying buffer is not writable");
943 Py_DECREF(mv);
944 return NULL;
945 }
946
947 if (PyBuffer_IsContiguous(view, order))
948 return (PyObject *)mv;
949
950 if (buffertype == PyBUF_WRITE) {
951 PyErr_SetString(PyExc_BufferError,
952 "writable contiguous buffer requested "
953 "for a non-contiguous object.");
954 Py_DECREF(mv);
955 return NULL;
956 }
957
958 ret = memory_from_contiguous_copy(view, order);
959 Py_DECREF(mv);
960 return ret;
961}
962
963
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000964static PyObject *
965memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
966{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000967 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100968 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000969
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000970 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
971 &obj)) {
972 return NULL;
973 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000974
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000975 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000976}
977
978
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100979/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200980/* Previously in abstract.c */
981/****************************************************************************/
982
983typedef struct {
984 Py_buffer view;
985 Py_ssize_t array[1];
986} Py_buffer_full;
987
988int
989PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
990{
991 Py_buffer_full *fb = NULL;
992 int ret;
993
994 assert(order == 'C' || order == 'F' || order == 'A');
995
996 if (len != src->len) {
997 PyErr_SetString(PyExc_ValueError,
998 "PyBuffer_ToContiguous: len != view->len");
999 return -1;
1000 }
1001
1002 if (PyBuffer_IsContiguous(src, order)) {
1003 memcpy((char *)buf, src->buf, len);
1004 return 0;
1005 }
1006
1007 /* buffer_to_contiguous() assumes PyBUF_FULL */
1008 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
1009 if (fb == NULL) {
1010 PyErr_NoMemory();
1011 return -1;
1012 }
1013 fb->view.ndim = src->ndim;
1014 fb->view.shape = fb->array;
1015 fb->view.strides = fb->array + src->ndim;
1016 fb->view.suboffsets = fb->array + 2 * src->ndim;
1017
1018 init_shared_values(&fb->view, src);
1019 init_shape_strides(&fb->view, src);
1020 init_suboffsets(&fb->view, src);
1021
1022 src = &fb->view;
1023
1024 ret = buffer_to_contiguous(buf, src, order);
1025 PyMem_Free(fb);
1026 return ret;
1027}
1028
1029
1030/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001031/* Release/GC management */
1032/****************************************************************************/
1033
1034/* Inform the managed buffer that this particular memoryview will not access
1035 the underlying buffer again. If no other memoryviews are registered with
1036 the managed buffer, the underlying buffer is released instantly and
1037 marked as inaccessible for both the memoryview and the managed buffer.
1038
1039 This function fails if the memoryview itself has exported buffers. */
1040static int
1041_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001042{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001043 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1044 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001045
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001046 if (self->exports == 0) {
1047 self->flags |= _Py_MEMORYVIEW_RELEASED;
1048 assert(self->mbuf->exports > 0);
1049 if (--self->mbuf->exports == 0)
1050 mbuf_release(self->mbuf);
1051 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001052 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001053 if (self->exports > 0) {
1054 PyErr_Format(PyExc_BufferError,
1055 "memoryview has %zd exported buffer%s", self->exports,
1056 self->exports==1 ? "" : "s");
1057 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001058 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001059
Victor Stinner47ee8a62020-01-27 22:37:44 +01001060 PyErr_SetString(PyExc_SystemError,
1061 "_memory_release(): negative export count");
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001062 return -1;
1063}
1064
1065static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001066memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001067{
1068 if (_memory_release(self) < 0)
1069 return NULL;
1070 Py_RETURN_NONE;
1071}
1072
1073static void
1074memory_dealloc(PyMemoryViewObject *self)
1075{
1076 assert(self->exports == 0);
1077 _PyObject_GC_UNTRACK(self);
1078 (void)_memory_release(self);
1079 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001080 if (self->weakreflist != NULL)
1081 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001082 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001083}
1084
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001085static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001086memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001087{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001088 Py_VISIT(self->mbuf);
1089 return 0;
1090}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001091
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001092static int
1093memory_clear(PyMemoryViewObject *self)
1094{
1095 (void)_memory_release(self);
1096 Py_CLEAR(self->mbuf);
1097 return 0;
1098}
1099
1100static PyObject *
1101memory_enter(PyObject *self, PyObject *args)
1102{
1103 CHECK_RELEASED(self);
1104 Py_INCREF(self);
1105 return self;
1106}
1107
1108static PyObject *
1109memory_exit(PyObject *self, PyObject *args)
1110{
Stefan Krahe4c07992012-07-28 14:10:02 +02001111 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001112}
1113
1114
1115/****************************************************************************/
1116/* Casting format and shape */
1117/****************************************************************************/
1118
1119#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1120
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001121static inline Py_ssize_t
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001122get_native_fmtchar(char *result, const char *fmt)
1123{
1124 Py_ssize_t size = -1;
1125
1126 if (fmt[0] == '@') fmt++;
1127
1128 switch (fmt[0]) {
1129 case 'c': case 'b': case 'B': size = sizeof(char); break;
1130 case 'h': case 'H': size = sizeof(short); break;
1131 case 'i': case 'I': size = sizeof(int); break;
1132 case 'l': case 'L': size = sizeof(long); break;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001133 case 'q': case 'Q': size = sizeof(long long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001134 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1135 case 'f': size = sizeof(float); break;
1136 case 'd': size = sizeof(double); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001137 case '?': size = sizeof(_Bool); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001138 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001139 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001140
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001141 if (size > 0 && fmt[1] == '\0') {
1142 *result = fmt[0];
1143 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001144 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001145
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001146 return -1;
1147}
1148
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001149static inline const char *
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001150get_native_fmtstr(const char *fmt)
1151{
1152 int at = 0;
1153
1154 if (fmt[0] == '@') {
1155 at = 1;
1156 fmt++;
1157 }
1158 if (fmt[0] == '\0' || fmt[1] != '\0') {
1159 return NULL;
1160 }
1161
1162#define RETURN(s) do { return at ? "@" s : s; } while (0)
1163
1164 switch (fmt[0]) {
1165 case 'c': RETURN("c");
1166 case 'b': RETURN("b");
1167 case 'B': RETURN("B");
1168 case 'h': RETURN("h");
1169 case 'H': RETURN("H");
1170 case 'i': RETURN("i");
1171 case 'I': RETURN("I");
1172 case 'l': RETURN("l");
1173 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001174 case 'q': RETURN("q");
1175 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001176 case 'n': RETURN("n");
1177 case 'N': RETURN("N");
1178 case 'f': RETURN("f");
1179 case 'd': RETURN("d");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001180 case '?': RETURN("?");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001181 case 'P': RETURN("P");
1182 }
1183
1184 return NULL;
1185}
1186
1187
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001188/* Cast a memoryview's data type to 'format'. The input array must be
1189 C-contiguous. At least one of input-format, output-format must have
1190 byte size. The output array is 1-D, with the same byte length as the
1191 input array. Thus, view->len must be a multiple of the new itemsize. */
1192static int
1193cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1194{
1195 Py_buffer *view = &mv->view;
1196 PyObject *asciifmt;
1197 char srcchar, destchar;
1198 Py_ssize_t itemsize;
1199 int ret = -1;
1200
1201 assert(view->ndim >= 1);
1202 assert(Py_SIZE(mv) == 3*view->ndim);
1203 assert(view->shape == mv->ob_array);
1204 assert(view->strides == mv->ob_array + view->ndim);
1205 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1206
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001207 asciifmt = PyUnicode_AsASCIIString(format);
1208 if (asciifmt == NULL)
1209 return ret;
1210
1211 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1212 if (itemsize < 0) {
1213 PyErr_SetString(PyExc_ValueError,
1214 "memoryview: destination format must be a native single "
1215 "character format prefixed with an optional '@'");
1216 goto out;
1217 }
1218
Stefan Krah0c515952015-08-08 13:38:10 +02001219 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1220 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001221 PyErr_SetString(PyExc_TypeError,
1222 "memoryview: cannot cast between two non-byte formats");
1223 goto out;
1224 }
1225 if (view->len % itemsize) {
1226 PyErr_SetString(PyExc_TypeError,
1227 "memoryview: length is not a multiple of itemsize");
1228 goto out;
1229 }
1230
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001231 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001232 if (view->format == NULL) {
1233 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1234 PyErr_SetString(PyExc_RuntimeError,
1235 "memoryview: internal error");
1236 goto out;
1237 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001238 view->itemsize = itemsize;
1239
1240 view->ndim = 1;
1241 view->shape[0] = view->len / view->itemsize;
1242 view->strides[0] = view->itemsize;
1243 view->suboffsets = NULL;
1244
1245 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001246
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001247 ret = 0;
1248
1249out:
1250 Py_DECREF(asciifmt);
1251 return ret;
1252}
1253
1254/* The memoryview must have space for 3*len(seq) elements. */
1255static Py_ssize_t
1256copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1257 Py_ssize_t itemsize)
1258{
1259 Py_ssize_t x, i;
1260 Py_ssize_t len = itemsize;
1261
1262 for (i = 0; i < ndim; i++) {
1263 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1264 if (!PyLong_Check(tmp)) {
1265 PyErr_SetString(PyExc_TypeError,
1266 "memoryview.cast(): elements of shape must be integers");
1267 return -1;
1268 }
1269 x = PyLong_AsSsize_t(tmp);
1270 if (x == -1 && PyErr_Occurred()) {
1271 return -1;
1272 }
1273 if (x <= 0) {
1274 /* In general elements of shape may be 0, but not for casting. */
1275 PyErr_Format(PyExc_ValueError,
1276 "memoryview.cast(): elements of shape must be integers > 0");
1277 return -1;
1278 }
1279 if (x > PY_SSIZE_T_MAX / len) {
1280 PyErr_Format(PyExc_ValueError,
1281 "memoryview.cast(): product(shape) > SSIZE_MAX");
1282 return -1;
1283 }
1284 len *= x;
1285 shape[i] = x;
1286 }
1287
1288 return len;
1289}
1290
1291/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1292 If the result array does not have exactly the same byte length as the
1293 input array, raise ValueError. */
1294static int
1295cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1296{
1297 Py_buffer *view = &mv->view;
1298 Py_ssize_t len;
1299
1300 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1301 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1302 assert(view->shape == mv->ob_array);
1303 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1304 assert(view->suboffsets == NULL);
1305
1306 view->ndim = ndim;
1307 if (view->ndim == 0) {
1308 view->shape = NULL;
1309 view->strides = NULL;
1310 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001311 }
1312 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001313 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1314 if (len < 0)
1315 return -1;
1316 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001317 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001318
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001319 if (view->len != len) {
1320 PyErr_SetString(PyExc_TypeError,
1321 "memoryview: product(shape) * itemsize != buffer size");
1322 return -1;
1323 }
1324
1325 init_flags(mv);
1326
1327 return 0;
1328}
1329
1330static int
1331zero_in_shape(PyMemoryViewObject *mv)
1332{
1333 Py_buffer *view = &mv->view;
1334 Py_ssize_t i;
1335
1336 for (i = 0; i < view->ndim; i++)
1337 if (view->shape[i] == 0)
1338 return 1;
1339
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001340 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001341}
1342
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001343/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001344 Cast a copy of 'self' to a different view. The input view must
1345 be C-contiguous. The function always casts the input view to a
1346 1-D output according to 'format'. At least one of input-format,
1347 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001348
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001349 If 'shape' is given, the 1-D view from the previous step will
1350 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001351
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001352 All casts must result in views that will have the exact byte
1353 size of the original input. Otherwise, an error is raised.
1354*/
1355static PyObject *
1356memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001357{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001358 static char *kwlist[] = {"format", "shape", NULL};
1359 PyMemoryViewObject *mv = NULL;
1360 PyObject *shape = NULL;
1361 PyObject *format;
1362 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001363
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001364 CHECK_RELEASED(self);
1365
1366 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1367 &format, &shape)) {
1368 return NULL;
1369 }
1370 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001371 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001372 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001373 return NULL;
1374 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001375 if (!MV_C_CONTIGUOUS(self->flags)) {
1376 PyErr_SetString(PyExc_TypeError,
1377 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001378 return NULL;
1379 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001380 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001381 PyErr_SetString(PyExc_TypeError,
1382 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001383 return NULL;
1384 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001385 if (shape) {
1386 CHECK_LIST_OR_TUPLE(shape)
1387 ndim = PySequence_Fast_GET_SIZE(shape);
1388 if (ndim > PyBUF_MAX_NDIM) {
1389 PyErr_SetString(PyExc_ValueError,
1390 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001391 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001392 return NULL;
1393 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001394 if (self->view.ndim != 1 && ndim != 1) {
1395 PyErr_SetString(PyExc_TypeError,
1396 "memoryview: cast must be 1D -> ND or ND -> 1D");
1397 return NULL;
1398 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001399 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001400
1401 mv = (PyMemoryViewObject *)
1402 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1403 if (mv == NULL)
1404 return NULL;
1405
1406 if (cast_to_1D(mv, format) < 0)
1407 goto error;
1408 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1409 goto error;
1410
1411 return (PyObject *)mv;
1412
1413error:
1414 Py_DECREF(mv);
1415 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001416}
1417
Antoine Pitrou480ab052018-04-14 19:49:21 +02001418static PyObject *
1419memory_toreadonly(PyMemoryViewObject *self, PyObject *noargs)
1420{
1421 CHECK_RELEASED(self);
1422 /* Even if self is already readonly, we still need to create a new
1423 * object for .release() to work correctly.
1424 */
1425 self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1426 if (self != NULL) {
1427 self->view.readonly = 1;
1428 };
1429 return (PyObject *) self;
1430}
1431
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001432
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001433/**************************************************************************/
1434/* getbuffer */
1435/**************************************************************************/
1436
1437static int
1438memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1439{
1440 Py_buffer *base = &self->view;
1441 int baseflags = self->flags;
1442
1443 CHECK_RELEASED_INT(self);
1444
1445 /* start with complete information */
1446 *view = *base;
1447 view->obj = NULL;
1448
1449 if (REQ_WRITABLE(flags) && base->readonly) {
1450 PyErr_SetString(PyExc_BufferError,
1451 "memoryview: underlying buffer is not writable");
1452 return -1;
1453 }
1454 if (!REQ_FORMAT(flags)) {
1455 /* NULL indicates that the buffer's data type has been cast to 'B'.
1456 view->itemsize is the _previous_ itemsize. If shape is present,
1457 the equality product(shape) * itemsize = len still holds at this
1458 point. The equality calcsize(format) = itemsize does _not_ hold
1459 from here on! */
1460 view->format = NULL;
1461 }
1462
1463 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1464 PyErr_SetString(PyExc_BufferError,
1465 "memoryview: underlying buffer is not C-contiguous");
1466 return -1;
1467 }
1468 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1469 PyErr_SetString(PyExc_BufferError,
1470 "memoryview: underlying buffer is not Fortran contiguous");
1471 return -1;
1472 }
1473 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1474 PyErr_SetString(PyExc_BufferError,
1475 "memoryview: underlying buffer is not contiguous");
1476 return -1;
1477 }
1478 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1479 PyErr_SetString(PyExc_BufferError,
1480 "memoryview: underlying buffer requires suboffsets");
1481 return -1;
1482 }
1483 if (!REQ_STRIDES(flags)) {
1484 if (!MV_C_CONTIGUOUS(baseflags)) {
1485 PyErr_SetString(PyExc_BufferError,
1486 "memoryview: underlying buffer is not C-contiguous");
1487 return -1;
1488 }
1489 view->strides = NULL;
1490 }
1491 if (!REQ_SHAPE(flags)) {
1492 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1493 so base->buf = ndbuf->data. */
1494 if (view->format != NULL) {
1495 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1496 not make sense. */
1497 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001498 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001499 "is present");
1500 return -1;
1501 }
1502 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1503 do _not_ hold from here on! */
1504 view->ndim = 1;
1505 view->shape = NULL;
1506 }
1507
1508
1509 view->obj = (PyObject *)self;
1510 Py_INCREF(view->obj);
1511 self->exports++;
1512
1513 return 0;
1514}
1515
1516static void
1517memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1518{
1519 self->exports--;
1520 return;
1521 /* PyBuffer_Release() decrements view->obj after this function returns. */
1522}
1523
1524/* Buffer methods */
1525static PyBufferProcs memory_as_buffer = {
1526 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1527 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1528};
1529
1530
1531/****************************************************************************/
1532/* Optimized pack/unpack for all native format specifiers */
1533/****************************************************************************/
1534
1535/*
1536 Fix exceptions:
1537 1) Include format string in the error message.
1538 2) OverflowError -> ValueError.
1539 3) The error message from PyNumber_Index() is not ideal.
1540*/
1541static int
1542type_error_int(const char *fmt)
1543{
1544 PyErr_Format(PyExc_TypeError,
1545 "memoryview: invalid type for format '%s'", fmt);
1546 return -1;
1547}
1548
1549static int
1550value_error_int(const char *fmt)
1551{
1552 PyErr_Format(PyExc_ValueError,
1553 "memoryview: invalid value for format '%s'", fmt);
1554 return -1;
1555}
1556
1557static int
1558fix_error_int(const char *fmt)
1559{
1560 assert(PyErr_Occurred());
1561 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1562 PyErr_Clear();
1563 return type_error_int(fmt);
1564 }
1565 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1566 PyErr_ExceptionMatches(PyExc_ValueError)) {
1567 PyErr_Clear();
1568 return value_error_int(fmt);
1569 }
1570
1571 return -1;
1572}
1573
1574/* Accept integer objects or objects with an __index__() method. */
1575static long
1576pylong_as_ld(PyObject *item)
1577{
1578 PyObject *tmp;
1579 long ld;
1580
1581 tmp = PyNumber_Index(item);
1582 if (tmp == NULL)
1583 return -1;
1584
1585 ld = PyLong_AsLong(tmp);
1586 Py_DECREF(tmp);
1587 return ld;
1588}
1589
1590static unsigned long
1591pylong_as_lu(PyObject *item)
1592{
1593 PyObject *tmp;
1594 unsigned long lu;
1595
1596 tmp = PyNumber_Index(item);
1597 if (tmp == NULL)
1598 return (unsigned long)-1;
1599
1600 lu = PyLong_AsUnsignedLong(tmp);
1601 Py_DECREF(tmp);
1602 return lu;
1603}
1604
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001605static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001606pylong_as_lld(PyObject *item)
1607{
1608 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001609 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001610
1611 tmp = PyNumber_Index(item);
1612 if (tmp == NULL)
1613 return -1;
1614
1615 lld = PyLong_AsLongLong(tmp);
1616 Py_DECREF(tmp);
1617 return lld;
1618}
1619
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001620static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001621pylong_as_llu(PyObject *item)
1622{
1623 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001624 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001625
1626 tmp = PyNumber_Index(item);
1627 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001628 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001629
1630 llu = PyLong_AsUnsignedLongLong(tmp);
1631 Py_DECREF(tmp);
1632 return llu;
1633}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001634
1635static Py_ssize_t
1636pylong_as_zd(PyObject *item)
1637{
1638 PyObject *tmp;
1639 Py_ssize_t zd;
1640
1641 tmp = PyNumber_Index(item);
1642 if (tmp == NULL)
1643 return -1;
1644
1645 zd = PyLong_AsSsize_t(tmp);
1646 Py_DECREF(tmp);
1647 return zd;
1648}
1649
1650static size_t
1651pylong_as_zu(PyObject *item)
1652{
1653 PyObject *tmp;
1654 size_t zu;
1655
1656 tmp = PyNumber_Index(item);
1657 if (tmp == NULL)
1658 return (size_t)-1;
1659
1660 zu = PyLong_AsSize_t(tmp);
1661 Py_DECREF(tmp);
1662 return zu;
1663}
1664
1665/* Timings with the ndarray from _testbuffer.c indicate that using the
1666 struct module is around 15x slower than the two functions below. */
1667
1668#define UNPACK_SINGLE(dest, ptr, type) \
1669 do { \
1670 type x; \
1671 memcpy((char *)&x, ptr, sizeof x); \
1672 dest = x; \
1673 } while (0)
1674
1675/* Unpack a single item. 'fmt' can be any native format character in struct
1676 module syntax. This function is very sensitive to small changes. With this
1677 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001678static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001679unpack_single(const char *ptr, const char *fmt)
1680{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001681 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001682 unsigned long lu;
1683 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001684 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001685 long ld;
1686 Py_ssize_t zd;
1687 double d;
1688 unsigned char uc;
1689 void *p;
1690
1691 switch (fmt[0]) {
1692
1693 /* signed integers and fast path for 'B' */
Andy Lestere6be9b52020-02-11 20:28:35 -06001694 case 'B': uc = *((const unsigned char *)ptr); goto convert_uc;
1695 case 'b': ld = *((const signed char *)ptr); goto convert_ld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001696 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1697 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1698 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1699
1700 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001701 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001702
1703 /* unsigned integers */
1704 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1705 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1706 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1707
1708 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001709 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1710 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001711
1712 /* ssize_t and size_t */
1713 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1714 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1715
1716 /* floats */
1717 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1718 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1719
1720 /* bytes object */
1721 case 'c': goto convert_bytes;
1722
1723 /* pointer */
1724 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1725
1726 /* default */
1727 default: goto err_format;
1728 }
1729
1730convert_uc:
1731 /* PyLong_FromUnsignedLong() is slower */
1732 return PyLong_FromLong(uc);
1733convert_ld:
1734 return PyLong_FromLong(ld);
1735convert_lu:
1736 return PyLong_FromUnsignedLong(lu);
1737convert_lld:
1738 return PyLong_FromLongLong(lld);
1739convert_llu:
1740 return PyLong_FromUnsignedLongLong(llu);
1741convert_zd:
1742 return PyLong_FromSsize_t(zd);
1743convert_zu:
1744 return PyLong_FromSize_t(zu);
1745convert_double:
1746 return PyFloat_FromDouble(d);
1747convert_bool:
1748 return PyBool_FromLong(ld);
1749convert_bytes:
1750 return PyBytes_FromStringAndSize(ptr, 1);
1751convert_pointer:
1752 return PyLong_FromVoidPtr(p);
1753err_format:
1754 PyErr_Format(PyExc_NotImplementedError,
1755 "memoryview: format %s not supported", fmt);
1756 return NULL;
1757}
1758
1759#define PACK_SINGLE(ptr, src, type) \
1760 do { \
1761 type x; \
1762 x = (type)src; \
1763 memcpy(ptr, (char *)&x, sizeof x); \
1764 } while (0)
1765
1766/* Pack a single item. 'fmt' can be any native format character in
1767 struct module syntax. */
1768static int
1769pack_single(char *ptr, PyObject *item, const char *fmt)
1770{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001771 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001772 unsigned long lu;
1773 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001774 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001775 long ld;
1776 Py_ssize_t zd;
1777 double d;
1778 void *p;
1779
1780 switch (fmt[0]) {
1781 /* signed integers */
1782 case 'b': case 'h': case 'i': case 'l':
1783 ld = pylong_as_ld(item);
1784 if (ld == -1 && PyErr_Occurred())
1785 goto err_occurred;
1786 switch (fmt[0]) {
1787 case 'b':
1788 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1789 *((signed char *)ptr) = (signed char)ld; break;
1790 case 'h':
1791 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1792 PACK_SINGLE(ptr, ld, short); break;
1793 case 'i':
1794 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1795 PACK_SINGLE(ptr, ld, int); break;
1796 default: /* 'l' */
1797 PACK_SINGLE(ptr, ld, long); break;
1798 }
1799 break;
1800
1801 /* unsigned integers */
1802 case 'B': case 'H': case 'I': case 'L':
1803 lu = pylong_as_lu(item);
1804 if (lu == (unsigned long)-1 && PyErr_Occurred())
1805 goto err_occurred;
1806 switch (fmt[0]) {
1807 case 'B':
1808 if (lu > UCHAR_MAX) goto err_range;
1809 *((unsigned char *)ptr) = (unsigned char)lu; break;
1810 case 'H':
1811 if (lu > USHRT_MAX) goto err_range;
1812 PACK_SINGLE(ptr, lu, unsigned short); break;
1813 case 'I':
1814 if (lu > UINT_MAX) goto err_range;
1815 PACK_SINGLE(ptr, lu, unsigned int); break;
1816 default: /* 'L' */
1817 PACK_SINGLE(ptr, lu, unsigned long); break;
1818 }
1819 break;
1820
1821 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001822 case 'q':
1823 lld = pylong_as_lld(item);
1824 if (lld == -1 && PyErr_Occurred())
1825 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001826 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001827 break;
1828 case 'Q':
1829 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001830 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001831 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001832 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001833 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001834
1835 /* ssize_t and size_t */
1836 case 'n':
1837 zd = pylong_as_zd(item);
1838 if (zd == -1 && PyErr_Occurred())
1839 goto err_occurred;
1840 PACK_SINGLE(ptr, zd, Py_ssize_t);
1841 break;
1842 case 'N':
1843 zu = pylong_as_zu(item);
1844 if (zu == (size_t)-1 && PyErr_Occurred())
1845 goto err_occurred;
1846 PACK_SINGLE(ptr, zu, size_t);
1847 break;
1848
1849 /* floats */
1850 case 'f': case 'd':
1851 d = PyFloat_AsDouble(item);
1852 if (d == -1.0 && PyErr_Occurred())
1853 goto err_occurred;
1854 if (fmt[0] == 'f') {
1855 PACK_SINGLE(ptr, d, float);
1856 }
1857 else {
1858 PACK_SINGLE(ptr, d, double);
1859 }
1860 break;
1861
1862 /* bool */
1863 case '?':
1864 ld = PyObject_IsTrue(item);
1865 if (ld < 0)
1866 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001867 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001868 break;
1869
1870 /* bytes object */
1871 case 'c':
1872 if (!PyBytes_Check(item))
1873 return type_error_int(fmt);
1874 if (PyBytes_GET_SIZE(item) != 1)
1875 return value_error_int(fmt);
1876 *ptr = PyBytes_AS_STRING(item)[0];
1877 break;
1878
1879 /* pointer */
1880 case 'P':
1881 p = PyLong_AsVoidPtr(item);
1882 if (p == NULL && PyErr_Occurred())
1883 goto err_occurred;
1884 PACK_SINGLE(ptr, p, void *);
1885 break;
1886
1887 /* default */
1888 default: goto err_format;
1889 }
1890
1891 return 0;
1892
1893err_occurred:
1894 return fix_error_int(fmt);
1895err_range:
1896 return value_error_int(fmt);
1897err_format:
1898 PyErr_Format(PyExc_NotImplementedError,
1899 "memoryview: format %s not supported", fmt);
1900 return -1;
1901}
1902
1903
1904/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001905/* unpack using the struct module */
1906/****************************************************************************/
1907
1908/* For reasonable performance it is necessary to cache all objects required
1909 for unpacking. An unpacker can handle the format passed to unpack_from().
1910 Invariant: All pointer fields of the struct should either be NULL or valid
1911 pointers. */
1912struct unpacker {
1913 PyObject *unpack_from; /* Struct.unpack_from(format) */
1914 PyObject *mview; /* cached memoryview */
1915 char *item; /* buffer for mview */
1916 Py_ssize_t itemsize; /* len(item) */
1917};
1918
1919static struct unpacker *
1920unpacker_new(void)
1921{
1922 struct unpacker *x = PyMem_Malloc(sizeof *x);
1923
1924 if (x == NULL) {
1925 PyErr_NoMemory();
1926 return NULL;
1927 }
1928
1929 x->unpack_from = NULL;
1930 x->mview = NULL;
1931 x->item = NULL;
1932 x->itemsize = 0;
1933
1934 return x;
1935}
1936
1937static void
1938unpacker_free(struct unpacker *x)
1939{
1940 if (x) {
1941 Py_XDECREF(x->unpack_from);
1942 Py_XDECREF(x->mview);
1943 PyMem_Free(x->item);
1944 PyMem_Free(x);
1945 }
1946}
1947
1948/* Return a new unpacker for the given format. */
1949static struct unpacker *
1950struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1951{
1952 PyObject *structmodule; /* XXX cache these two */
1953 PyObject *Struct = NULL; /* XXX in globals? */
1954 PyObject *structobj = NULL;
1955 PyObject *format = NULL;
1956 struct unpacker *x = NULL;
1957
1958 structmodule = PyImport_ImportModule("struct");
1959 if (structmodule == NULL)
1960 return NULL;
1961
1962 Struct = PyObject_GetAttrString(structmodule, "Struct");
1963 Py_DECREF(structmodule);
1964 if (Struct == NULL)
1965 return NULL;
1966
1967 x = unpacker_new();
1968 if (x == NULL)
1969 goto error;
1970
1971 format = PyBytes_FromString(fmt);
1972 if (format == NULL)
1973 goto error;
1974
Petr Viktorinffd97532020-02-11 17:46:57 +01001975 structobj = PyObject_CallOneArg(Struct, format);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001976 if (structobj == NULL)
1977 goto error;
1978
1979 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1980 if (x->unpack_from == NULL)
1981 goto error;
1982
1983 x->item = PyMem_Malloc(itemsize);
1984 if (x->item == NULL) {
1985 PyErr_NoMemory();
1986 goto error;
1987 }
1988 x->itemsize = itemsize;
1989
1990 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1991 if (x->mview == NULL)
1992 goto error;
1993
1994
1995out:
1996 Py_XDECREF(Struct);
1997 Py_XDECREF(format);
1998 Py_XDECREF(structobj);
1999 return x;
2000
2001error:
2002 unpacker_free(x);
2003 x = NULL;
2004 goto out;
2005}
2006
2007/* unpack a single item */
2008static PyObject *
2009struct_unpack_single(const char *ptr, struct unpacker *x)
2010{
2011 PyObject *v;
2012
2013 memcpy(x->item, ptr, x->itemsize);
Petr Viktorinffd97532020-02-11 17:46:57 +01002014 v = PyObject_CallOneArg(x->unpack_from, x->mview);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002015 if (v == NULL)
2016 return NULL;
2017
2018 if (PyTuple_GET_SIZE(v) == 1) {
2019 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2020 Py_INCREF(tmp);
2021 Py_DECREF(v);
2022 return tmp;
2023 }
2024
2025 return v;
2026}
2027
2028
2029/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002030/* Representations */
2031/****************************************************************************/
2032
2033/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002034static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002035adjust_fmt(const Py_buffer *view)
2036{
2037 const char *fmt;
2038
2039 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2040 if (fmt[0] && fmt[1] == '\0')
2041 return fmt;
2042
2043 PyErr_Format(PyExc_NotImplementedError,
2044 "memoryview: unsupported format %s", view->format);
2045 return NULL;
2046}
2047
2048/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2049static PyObject *
2050tolist_base(const char *ptr, const Py_ssize_t *shape,
2051 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2052 const char *fmt)
2053{
2054 PyObject *lst, *item;
2055 Py_ssize_t i;
2056
2057 lst = PyList_New(shape[0]);
2058 if (lst == NULL)
2059 return NULL;
2060
2061 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002062 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002063 item = unpack_single(xptr, fmt);
2064 if (item == NULL) {
2065 Py_DECREF(lst);
2066 return NULL;
2067 }
2068 PyList_SET_ITEM(lst, i, item);
2069 }
2070
2071 return lst;
2072}
2073
2074/* Unpack a multi-dimensional array into a nested list.
2075 Assumption: ndim >= 1. */
2076static PyObject *
2077tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2078 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2079 const char *fmt)
2080{
2081 PyObject *lst, *item;
2082 Py_ssize_t i;
2083
2084 assert(ndim >= 1);
2085 assert(shape != NULL);
2086 assert(strides != NULL);
2087
2088 if (ndim == 1)
2089 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2090
2091 lst = PyList_New(shape[0]);
2092 if (lst == NULL)
2093 return NULL;
2094
2095 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002096 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002097 item = tolist_rec(xptr, ndim-1, shape+1,
2098 strides+1, suboffsets ? suboffsets+1 : NULL,
2099 fmt);
2100 if (item == NULL) {
2101 Py_DECREF(lst);
2102 return NULL;
2103 }
2104 PyList_SET_ITEM(lst, i, item);
2105 }
2106
2107 return lst;
2108}
2109
2110/* Return a list representation of the memoryview. Currently only buffers
2111 with native format strings are supported. */
2112static PyObject *
2113memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2114{
2115 const Py_buffer *view = &(mv->view);
2116 const char *fmt;
2117
2118 CHECK_RELEASED(mv);
2119
2120 fmt = adjust_fmt(view);
2121 if (fmt == NULL)
2122 return NULL;
2123 if (view->ndim == 0) {
2124 return unpack_single(view->buf, fmt);
2125 }
2126 else if (view->ndim == 1) {
2127 return tolist_base(view->buf, view->shape,
2128 view->strides, view->suboffsets,
2129 fmt);
2130 }
2131 else {
2132 return tolist_rec(view->buf, view->ndim, view->shape,
2133 view->strides, view->suboffsets,
2134 fmt);
2135 }
2136}
2137
2138static PyObject *
Stefan Krahd08ea702019-02-02 18:57:41 +01002139memory_tobytes(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002140{
Stefan Krahd08ea702019-02-02 18:57:41 +01002141 static char *kwlist[] = {"order", NULL};
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002142 Py_buffer *src = VIEW_ADDR(self);
Stefan Krahd08ea702019-02-02 18:57:41 +01002143 char *order = NULL;
2144 char ord = 'C';
2145 PyObject *bytes;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002146
2147 CHECK_RELEASED(self);
2148
Stefan Krahd08ea702019-02-02 18:57:41 +01002149 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z", kwlist, &order)) {
2150 return NULL;
2151 }
2152
2153 if (order) {
2154 if (strcmp(order, "F") == 0) {
2155 ord = 'F';
2156 }
2157 else if (strcmp(order, "A") == 0) {
2158 ord = 'A';
2159 }
2160 else if (strcmp(order, "C") != 0) {
2161 PyErr_SetString(PyExc_ValueError,
2162 "order must be 'C', 'F' or 'A'");
2163 return NULL;
2164 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002165 }
2166
2167 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2168 if (bytes == NULL)
2169 return NULL;
2170
Stefan Krahd08ea702019-02-02 18:57:41 +01002171 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, ord) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002172 Py_DECREF(bytes);
2173 return NULL;
2174 }
2175
2176 return bytes;
2177}
2178
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002179/*[clinic input]
2180memoryview.hex
2181
2182 sep: object = NULL
2183 An optional single character or byte to separate hex bytes.
2184 bytes_per_sep: int = 1
2185 How many bytes between separators. Positive values count from the
2186 right, negative values count from the left.
2187
2188Return the data in the buffer as a str of hexadecimal numbers.
2189
2190Example:
2191>>> value = memoryview(b'\xb9\x01\xef')
2192>>> value.hex()
2193'b901ef'
2194>>> value.hex(':')
2195'b9:01:ef'
2196>>> value.hex(':', 2)
2197'b9:01ef'
2198>>> value.hex(':', -2)
2199'b901:ef'
2200[clinic start generated code]*/
2201
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002202static PyObject *
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002203memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
2204 int bytes_per_sep)
2205/*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002206{
2207 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002208 PyObject *bytes;
2209 PyObject *ret;
2210
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002211 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002212
2213 if (MV_C_CONTIGUOUS(self->flags)) {
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002214 return _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002215 }
2216
Stefan Krahd08ea702019-02-02 18:57:41 +01002217 bytes = PyBytes_FromStringAndSize(NULL, src->len);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002218 if (bytes == NULL)
2219 return NULL;
2220
Stefan Krahd08ea702019-02-02 18:57:41 +01002221 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, 'C') < 0) {
2222 Py_DECREF(bytes);
2223 return NULL;
2224 }
2225
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002226 ret = _Py_strhex_with_sep(
2227 PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes),
2228 sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002229 Py_DECREF(bytes);
2230
2231 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002232}
2233
2234static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002235memory_repr(PyMemoryViewObject *self)
2236{
2237 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2238 return PyUnicode_FromFormat("<released memory at %p>", self);
2239 else
2240 return PyUnicode_FromFormat("<memory at %p>", self);
2241}
2242
2243
2244/**************************************************************************/
2245/* Indexing and slicing */
2246/**************************************************************************/
2247
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002248static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002249lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002250{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002251 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002252
2253 assert(view->shape);
2254 assert(view->strides);
2255
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002256 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002257 if (index < 0) {
2258 index += nitems;
2259 }
2260 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002261 PyErr_Format(PyExc_IndexError,
2262 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002263 return NULL;
2264 }
2265
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002266 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002267
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002268 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002269
2270 return ptr;
2271}
2272
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002273/* Get the pointer to the item at index. */
2274static char *
2275ptr_from_index(Py_buffer *view, Py_ssize_t index)
2276{
2277 char *ptr = (char *)view->buf;
2278 return lookup_dimension(view, ptr, 0, index);
2279}
2280
2281/* Get the pointer to the item at tuple. */
2282static char *
2283ptr_from_tuple(Py_buffer *view, PyObject *tup)
2284{
2285 char *ptr = (char *)view->buf;
2286 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2287
2288 if (nindices > view->ndim) {
2289 PyErr_Format(PyExc_TypeError,
2290 "cannot index %zd-dimension view with %zd-element tuple",
2291 view->ndim, nindices);
2292 return NULL;
2293 }
2294
2295 for (dim = 0; dim < nindices; dim++) {
2296 Py_ssize_t index;
2297 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2298 PyExc_IndexError);
2299 if (index == -1 && PyErr_Occurred())
2300 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002301 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002302 if (ptr == NULL)
2303 return NULL;
2304 }
2305 return ptr;
2306}
2307
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002308/* Return the item at index. In a one-dimensional view, this is an object
2309 with the type specified by view->format. Otherwise, the item is a sub-view.
2310 The function is used in memory_subscript() and memory_as_sequence. */
2311static PyObject *
2312memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2313{
2314 Py_buffer *view = &(self->view);
2315 const char *fmt;
2316
2317 CHECK_RELEASED(self);
2318
2319 fmt = adjust_fmt(view);
2320 if (fmt == NULL)
2321 return NULL;
2322
2323 if (view->ndim == 0) {
2324 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2325 return NULL;
2326 }
2327 if (view->ndim == 1) {
2328 char *ptr = ptr_from_index(view, index);
2329 if (ptr == NULL)
2330 return NULL;
2331 return unpack_single(ptr, fmt);
2332 }
2333
2334 PyErr_SetString(PyExc_NotImplementedError,
2335 "multi-dimensional sub-views are not implemented");
2336 return NULL;
2337}
2338
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002339/* Return the item at position *key* (a tuple of indices). */
2340static PyObject *
2341memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2342{
2343 Py_buffer *view = &(self->view);
2344 const char *fmt;
2345 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2346 char *ptr;
2347
2348 CHECK_RELEASED(self);
2349
2350 fmt = adjust_fmt(view);
2351 if (fmt == NULL)
2352 return NULL;
2353
2354 if (nindices < view->ndim) {
2355 PyErr_SetString(PyExc_NotImplementedError,
2356 "sub-views are not implemented");
2357 return NULL;
2358 }
2359 ptr = ptr_from_tuple(view, tup);
2360 if (ptr == NULL)
2361 return NULL;
2362 return unpack_single(ptr, fmt);
2363}
2364
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002365static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002366init_slice(Py_buffer *base, PyObject *key, int dim)
2367{
2368 Py_ssize_t start, stop, step, slicelength;
2369
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002370 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002371 return -1;
2372 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002373 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002374
2375
2376 if (base->suboffsets == NULL || dim == 0) {
2377 adjust_buf:
2378 base->buf = (char *)base->buf + base->strides[dim] * start;
2379 }
2380 else {
2381 Py_ssize_t n = dim-1;
2382 while (n >= 0 && base->suboffsets[n] < 0)
2383 n--;
2384 if (n < 0)
2385 goto adjust_buf; /* all suboffsets are negative */
2386 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2387 }
2388 base->shape[dim] = slicelength;
2389 base->strides[dim] = base->strides[dim] * step;
2390
2391 return 0;
2392}
2393
2394static int
2395is_multislice(PyObject *key)
2396{
2397 Py_ssize_t size, i;
2398
2399 if (!PyTuple_Check(key))
2400 return 0;
2401 size = PyTuple_GET_SIZE(key);
2402 if (size == 0)
2403 return 0;
2404
2405 for (i = 0; i < size; i++) {
2406 PyObject *x = PyTuple_GET_ITEM(key, i);
2407 if (!PySlice_Check(x))
2408 return 0;
2409 }
2410 return 1;
2411}
2412
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002413static Py_ssize_t
2414is_multiindex(PyObject *key)
2415{
2416 Py_ssize_t size, i;
2417
2418 if (!PyTuple_Check(key))
2419 return 0;
2420 size = PyTuple_GET_SIZE(key);
2421 for (i = 0; i < size; i++) {
2422 PyObject *x = PyTuple_GET_ITEM(key, i);
Victor Stinnera15e2602020-04-08 02:01:56 +02002423 if (!_PyIndex_Check(x)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002424 return 0;
Victor Stinnera15e2602020-04-08 02:01:56 +02002425 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002426 }
2427 return 1;
2428}
2429
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002430/* mv[obj] returns an object holding the data for one element if obj
2431 fully indexes the memoryview or another memoryview object if it
2432 does not.
2433
2434 0-d memoryview objects can be referenced using mv[...] or mv[()]
2435 but not with anything else. */
2436static PyObject *
2437memory_subscript(PyMemoryViewObject *self, PyObject *key)
2438{
2439 Py_buffer *view;
2440 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002441
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002442 CHECK_RELEASED(self);
2443
2444 if (view->ndim == 0) {
2445 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2446 const char *fmt = adjust_fmt(view);
2447 if (fmt == NULL)
2448 return NULL;
2449 return unpack_single(view->buf, fmt);
2450 }
2451 else if (key == Py_Ellipsis) {
2452 Py_INCREF(self);
2453 return (PyObject *)self;
2454 }
2455 else {
2456 PyErr_SetString(PyExc_TypeError,
2457 "invalid indexing of 0-dim memory");
2458 return NULL;
2459 }
2460 }
2461
Victor Stinnera15e2602020-04-08 02:01:56 +02002462 if (_PyIndex_Check(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002463 Py_ssize_t index;
2464 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2465 if (index == -1 && PyErr_Occurred())
2466 return NULL;
2467 return memory_item(self, index);
2468 }
2469 else if (PySlice_Check(key)) {
2470 PyMemoryViewObject *sliced;
2471
2472 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2473 if (sliced == NULL)
2474 return NULL;
2475
2476 if (init_slice(&sliced->view, key, 0) < 0) {
2477 Py_DECREF(sliced);
2478 return NULL;
2479 }
2480 init_len(&sliced->view);
2481 init_flags(sliced);
2482
2483 return (PyObject *)sliced;
2484 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002485 else if (is_multiindex(key)) {
2486 return memory_item_multi(self, key);
2487 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002488 else if (is_multislice(key)) {
2489 PyErr_SetString(PyExc_NotImplementedError,
2490 "multi-dimensional slicing is not implemented");
2491 return NULL;
2492 }
2493
2494 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2495 return NULL;
2496}
2497
2498static int
2499memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2500{
2501 Py_buffer *view = &(self->view);
2502 Py_buffer src;
2503 const char *fmt;
2504 char *ptr;
2505
2506 CHECK_RELEASED_INT(self);
2507
2508 fmt = adjust_fmt(view);
2509 if (fmt == NULL)
2510 return -1;
2511
2512 if (view->readonly) {
2513 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2514 return -1;
2515 }
2516 if (value == NULL) {
2517 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2518 return -1;
2519 }
2520 if (view->ndim == 0) {
2521 if (key == Py_Ellipsis ||
2522 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2523 ptr = (char *)view->buf;
2524 return pack_single(ptr, value, fmt);
2525 }
2526 else {
2527 PyErr_SetString(PyExc_TypeError,
2528 "invalid indexing of 0-dim memory");
2529 return -1;
2530 }
2531 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002532
Victor Stinnera15e2602020-04-08 02:01:56 +02002533 if (_PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002534 Py_ssize_t index;
2535 if (1 < view->ndim) {
2536 PyErr_SetString(PyExc_NotImplementedError,
2537 "sub-views are not implemented");
2538 return -1;
2539 }
2540 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002541 if (index == -1 && PyErr_Occurred())
2542 return -1;
2543 ptr = ptr_from_index(view, index);
2544 if (ptr == NULL)
2545 return -1;
2546 return pack_single(ptr, value, fmt);
2547 }
2548 /* one-dimensional: fast path */
2549 if (PySlice_Check(key) && view->ndim == 1) {
2550 Py_buffer dest; /* sliced view */
2551 Py_ssize_t arrays[3];
2552 int ret = -1;
2553
2554 /* rvalue must be an exporter */
2555 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2556 return ret;
2557
2558 dest = *view;
2559 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2560 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2561 if (view->suboffsets) {
2562 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2563 }
2564
2565 if (init_slice(&dest, key, 0) < 0)
2566 goto end_block;
2567 dest.len = dest.shape[0] * dest.itemsize;
2568
2569 ret = copy_single(&dest, &src);
2570
2571 end_block:
2572 PyBuffer_Release(&src);
2573 return ret;
2574 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002575 if (is_multiindex(key)) {
2576 char *ptr;
2577 if (PyTuple_GET_SIZE(key) < view->ndim) {
2578 PyErr_SetString(PyExc_NotImplementedError,
2579 "sub-views are not implemented");
2580 return -1;
2581 }
2582 ptr = ptr_from_tuple(view, key);
2583 if (ptr == NULL)
2584 return -1;
2585 return pack_single(ptr, value, fmt);
2586 }
2587 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002588 /* Call memory_subscript() to produce a sliced lvalue, then copy
2589 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2590 PyErr_SetString(PyExc_NotImplementedError,
2591 "memoryview slice assignments are currently restricted "
2592 "to ndim = 1");
2593 return -1;
2594 }
2595
2596 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2597 return -1;
2598}
2599
2600static Py_ssize_t
2601memory_length(PyMemoryViewObject *self)
2602{
2603 CHECK_RELEASED_INT(self);
2604 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2605}
2606
2607/* As mapping */
2608static PyMappingMethods memory_as_mapping = {
2609 (lenfunc)memory_length, /* mp_length */
2610 (binaryfunc)memory_subscript, /* mp_subscript */
2611 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2612};
2613
2614/* As sequence */
2615static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002616 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002617 0, /* sq_concat */
2618 0, /* sq_repeat */
2619 (ssizeargfunc)memory_item, /* sq_item */
2620};
2621
2622
2623/**************************************************************************/
2624/* Comparisons */
2625/**************************************************************************/
2626
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002627#define MV_COMPARE_EX -1 /* exception */
2628#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2629
2630/* Translate a StructError to "not equal". Preserve other exceptions. */
2631static int
2632fix_struct_error_int(void)
2633{
2634 assert(PyErr_Occurred());
2635 /* XXX Cannot get at StructError directly? */
2636 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2637 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2638 return MV_COMPARE_EX;
2639 }
2640 /* StructError: invalid or unknown format -> not equal */
2641 PyErr_Clear();
2642 return 0;
2643}
2644
2645/* Unpack and compare single items of p and q using the struct module. */
2646static int
2647struct_unpack_cmp(const char *p, const char *q,
2648 struct unpacker *unpack_p, struct unpacker *unpack_q)
2649{
2650 PyObject *v, *w;
2651 int ret;
2652
2653 /* At this point any exception from the struct module should not be
2654 StructError, since both formats have been accepted already. */
2655 v = struct_unpack_single(p, unpack_p);
2656 if (v == NULL)
2657 return MV_COMPARE_EX;
2658
2659 w = struct_unpack_single(q, unpack_q);
2660 if (w == NULL) {
2661 Py_DECREF(v);
2662 return MV_COMPARE_EX;
2663 }
2664
2665 /* MV_COMPARE_EX == -1: exceptions are preserved */
2666 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2667 Py_DECREF(v);
2668 Py_DECREF(w);
2669
2670 return ret;
2671}
2672
2673/* Unpack and compare single items of p and q. If both p and q have the same
2674 single element native format, the comparison uses a fast path (gcc creates
2675 a jump table and converts memcpy into simple assignments on x86/x64).
2676
2677 Otherwise, the comparison is delegated to the struct module, which is
2678 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002679#define CMP_SINGLE(p, q, type) \
2680 do { \
2681 type x; \
2682 type y; \
2683 memcpy((char *)&x, p, sizeof x); \
2684 memcpy((char *)&y, q, sizeof y); \
2685 equal = (x == y); \
2686 } while (0)
2687
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002688static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002689unpack_cmp(const char *p, const char *q, char fmt,
2690 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002691{
2692 int equal;
2693
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002694 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002695
2696 /* signed integers and fast path for 'B' */
Andy Lestere6be9b52020-02-11 20:28:35 -06002697 case 'B': return *((const unsigned char *)p) == *((const unsigned char *)q);
2698 case 'b': return *((const signed char *)p) == *((const signed char *)q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002699 case 'h': CMP_SINGLE(p, q, short); return equal;
2700 case 'i': CMP_SINGLE(p, q, int); return equal;
2701 case 'l': CMP_SINGLE(p, q, long); return equal;
2702
2703 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002704 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002705
2706 /* unsigned integers */
2707 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2708 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2709 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2710
2711 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002712 case 'q': CMP_SINGLE(p, q, long long); return equal;
2713 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002714
2715 /* ssize_t and size_t */
2716 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2717 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2718
2719 /* floats */
2720 /* XXX DBL_EPSILON? */
2721 case 'f': CMP_SINGLE(p, q, float); return equal;
2722 case 'd': CMP_SINGLE(p, q, double); return equal;
2723
2724 /* bytes object */
2725 case 'c': return *p == *q;
2726
2727 /* pointer */
2728 case 'P': CMP_SINGLE(p, q, void *); return equal;
2729
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002730 /* use the struct module */
2731 case '_':
2732 assert(unpack_p);
2733 assert(unpack_q);
2734 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002735 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002736
2737 /* NOT REACHED */
2738 PyErr_SetString(PyExc_RuntimeError,
2739 "memoryview: internal error in richcompare");
2740 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002741}
2742
2743/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2744static int
2745cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2746 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2747 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002748 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002749{
2750 Py_ssize_t i;
2751 int equal;
2752
2753 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002754 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2755 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002756 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002757 if (equal <= 0)
2758 return equal;
2759 }
2760
2761 return 1;
2762}
2763
2764/* Recursively compare two multi-dimensional arrays that have the same
2765 logical structure. Assumption: ndim >= 1. */
2766static int
2767cmp_rec(const char *p, const char *q,
2768 Py_ssize_t ndim, const Py_ssize_t *shape,
2769 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2770 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002771 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002772{
2773 Py_ssize_t i;
2774 int equal;
2775
2776 assert(ndim >= 1);
2777 assert(shape != NULL);
2778 assert(pstrides != NULL);
2779 assert(qstrides != NULL);
2780
2781 if (ndim == 1) {
2782 return cmp_base(p, q, shape,
2783 pstrides, psuboffsets,
2784 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002785 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002786 }
2787
2788 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002789 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2790 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002791 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2792 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2793 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002794 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002795 if (equal <= 0)
2796 return equal;
2797 }
2798
2799 return 1;
2800}
2801
2802static PyObject *
2803memory_richcompare(PyObject *v, PyObject *w, int op)
2804{
2805 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002806 Py_buffer wbuf, *vv;
2807 Py_buffer *ww = NULL;
2808 struct unpacker *unpack_v = NULL;
2809 struct unpacker *unpack_w = NULL;
2810 char vfmt, wfmt;
2811 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002812
2813 if (op != Py_EQ && op != Py_NE)
2814 goto result; /* Py_NotImplemented */
2815
2816 assert(PyMemoryView_Check(v));
2817 if (BASE_INACCESSIBLE(v)) {
2818 equal = (v == w);
2819 goto result;
2820 }
2821 vv = VIEW_ADDR(v);
2822
2823 if (PyMemoryView_Check(w)) {
2824 if (BASE_INACCESSIBLE(w)) {
2825 equal = (v == w);
2826 goto result;
2827 }
2828 ww = VIEW_ADDR(w);
2829 }
2830 else {
2831 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2832 PyErr_Clear();
2833 goto result; /* Py_NotImplemented */
2834 }
2835 ww = &wbuf;
2836 }
2837
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002838 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002839 PyErr_Clear();
2840 equal = 0;
2841 goto result;
2842 }
2843
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002844 /* Use fast unpacking for identical primitive C type formats. */
2845 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2846 vfmt = '_';
2847 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2848 wfmt = '_';
2849 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2850 /* Use struct module unpacking. NOTE: Even for equal format strings,
2851 memcmp() cannot be used for item comparison since it would give
2852 incorrect results in the case of NaNs or uninitialized padding
2853 bytes. */
2854 vfmt = '_';
2855 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2856 if (unpack_v == NULL) {
2857 equal = fix_struct_error_int();
2858 goto result;
2859 }
2860 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2861 if (unpack_w == NULL) {
2862 equal = fix_struct_error_int();
2863 goto result;
2864 }
2865 }
2866
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002867 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002868 equal = unpack_cmp(vv->buf, ww->buf,
2869 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002870 }
2871 else if (vv->ndim == 1) {
2872 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2873 vv->strides, vv->suboffsets,
2874 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002875 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002876 }
2877 else {
2878 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2879 vv->strides, vv->suboffsets,
2880 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002881 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002882 }
2883
2884result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002885 if (equal < 0) {
2886 if (equal == MV_COMPARE_NOT_IMPL)
2887 res = Py_NotImplemented;
2888 else /* exception */
2889 res = NULL;
2890 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002891 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2892 res = Py_True;
2893 else
2894 res = Py_False;
2895
2896 if (ww == &wbuf)
2897 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002898
2899 unpacker_free(unpack_v);
2900 unpacker_free(unpack_w);
2901
2902 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002903 return res;
2904}
2905
2906/**************************************************************************/
2907/* Hash */
2908/**************************************************************************/
2909
2910static Py_hash_t
2911memory_hash(PyMemoryViewObject *self)
2912{
2913 if (self->hash == -1) {
2914 Py_buffer *view = &self->view;
2915 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002916 Py_ssize_t ret;
2917 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002918
2919 CHECK_RELEASED_INT(self);
2920
2921 if (!view->readonly) {
2922 PyErr_SetString(PyExc_ValueError,
2923 "cannot hash writable memoryview object");
2924 return -1;
2925 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002926 ret = get_native_fmtchar(&fmt, view->format);
2927 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2928 PyErr_SetString(PyExc_ValueError,
2929 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2930 return -1;
2931 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002932 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2933 /* Keep the original error message */
2934 return -1;
2935 }
2936
2937 if (!MV_C_CONTIGUOUS(self->flags)) {
2938 mem = PyMem_Malloc(view->len);
2939 if (mem == NULL) {
2940 PyErr_NoMemory();
2941 return -1;
2942 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002943 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002944 PyMem_Free(mem);
2945 return -1;
2946 }
2947 }
2948
2949 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002950 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002951
2952 if (mem != view->buf)
2953 PyMem_Free(mem);
2954 }
2955
2956 return self->hash;
2957}
2958
2959
2960/**************************************************************************/
2961/* getters */
2962/**************************************************************************/
2963
2964static PyObject *
2965_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2966{
2967 int i;
2968 PyObject *o;
2969 PyObject *intTuple;
2970
2971 if (vals == NULL)
2972 return PyTuple_New(0);
2973
2974 intTuple = PyTuple_New(len);
2975 if (!intTuple)
2976 return NULL;
2977 for (i=0; i<len; i++) {
2978 o = PyLong_FromSsize_t(vals[i]);
2979 if (!o) {
2980 Py_DECREF(intTuple);
2981 return NULL;
2982 }
2983 PyTuple_SET_ITEM(intTuple, i, o);
2984 }
2985 return intTuple;
2986}
2987
2988static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002989memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002990{
2991 Py_buffer *view = &self->view;
2992
2993 CHECK_RELEASED(self);
2994 if (view->obj == NULL) {
2995 Py_RETURN_NONE;
2996 }
2997 Py_INCREF(view->obj);
2998 return view->obj;
2999}
3000
3001static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003002memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003003{
3004 CHECK_RELEASED(self);
3005 return PyLong_FromSsize_t(self->view.len);
3006}
3007
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003008static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003009memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003010{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003011 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003012 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003013}
3014
3015static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003016memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003017{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003018 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003019 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003020}
3021
3022static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003023memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003024{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003025 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003026 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003027}
3028
3029static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003030memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003031{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003032 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003033 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003034}
3035
3036static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003037memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003038{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003039 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003040 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003041}
3042
3043static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003044memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003045{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003046 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003047 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003048}
3049
3050static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003051memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003052{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003053 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003054 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003055}
3056
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003057static PyObject *
3058memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3059{
3060 CHECK_RELEASED(self);
3061 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3062}
3063
3064static PyObject *
3065memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3066{
3067 CHECK_RELEASED(self);
3068 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3069}
3070
3071static PyObject *
3072memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3073{
3074 CHECK_RELEASED(self);
3075 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3076}
3077
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003078PyDoc_STRVAR(memory_obj_doc,
3079 "The underlying object of the memoryview.");
3080PyDoc_STRVAR(memory_nbytes_doc,
3081 "The amount of space in bytes that the array would use in\n"
3082 " a contiguous representation.");
3083PyDoc_STRVAR(memory_readonly_doc,
3084 "A bool indicating whether the memory is read only.");
3085PyDoc_STRVAR(memory_itemsize_doc,
3086 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003087PyDoc_STRVAR(memory_format_doc,
3088 "A string containing the format (in struct module style)\n"
3089 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003090PyDoc_STRVAR(memory_ndim_doc,
3091 "An integer indicating how many dimensions of a multi-dimensional\n"
3092 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003093PyDoc_STRVAR(memory_shape_doc,
3094 "A tuple of ndim integers giving the shape of the memory\n"
3095 " as an N-dimensional array.");
3096PyDoc_STRVAR(memory_strides_doc,
3097 "A tuple of ndim integers giving the size in bytes to access\n"
3098 " each element for each dimension of the array.");
3099PyDoc_STRVAR(memory_suboffsets_doc,
3100 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003101PyDoc_STRVAR(memory_c_contiguous_doc,
3102 "A bool indicating whether the memory is C contiguous.");
3103PyDoc_STRVAR(memory_f_contiguous_doc,
3104 "A bool indicating whether the memory is Fortran contiguous.");
3105PyDoc_STRVAR(memory_contiguous_doc,
3106 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003107
Stefan Krahbcaf5992014-05-18 00:35:09 +02003108
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003109static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003110 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3111 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003112 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3113 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3114 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3115 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3116 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3117 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3118 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003119 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3120 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3121 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003122 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003123};
3124
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003125PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003126"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003127\n\
3128Release the underlying buffer exposed by the memoryview object.");
3129PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahd08ea702019-02-02 18:57:41 +01003130"tobytes($self, /, order=None)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003131\n\
Stefan Krahd08ea702019-02-02 18:57:41 +01003132Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
3133When order is 'C' or 'F', the data of the original array is converted to C or\n\
3134Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
3135memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
3136views, the data is converted to C first. order=None is the same as order='C'.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003137PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003138"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003139\n\
3140Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003141PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003142"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003143\n\
3144Cast a memoryview to a new format or shape.");
Antoine Pitrou480ab052018-04-14 19:49:21 +02003145PyDoc_STRVAR(memory_toreadonly_doc,
3146"toreadonly($self, /)\n--\n\
3147\n\
3148Return a readonly version of the memoryview.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003149
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003150static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003151 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
Stéphane Wirtel359a2f32019-03-05 16:10:53 +01003152 {"tobytes", (PyCFunction)(void(*)(void))memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07003153 MEMORYVIEW_HEX_METHODDEF
Alexander Belopolskye370c382012-09-03 16:43:55 -04003154 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02003155 {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Antoine Pitrou480ab052018-04-14 19:49:21 +02003156 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003157 {"__enter__", memory_enter, METH_NOARGS, NULL},
3158 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003159 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003160};
3161
3162
3163PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003164 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003165 "memoryview", /* tp_name */
3166 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3167 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003168 (destructor)memory_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003169 0, /* tp_vectorcall_offset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003170 0, /* tp_getattr */
3171 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003172 0, /* tp_as_async */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003173 (reprfunc)memory_repr, /* tp_repr */
3174 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003175 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003176 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003177 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003178 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003179 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003180 PyObject_GenericGetAttr, /* tp_getattro */
3181 0, /* tp_setattro */
3182 &memory_as_buffer, /* tp_as_buffer */
3183 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3184 memory_doc, /* tp_doc */
3185 (traverseproc)memory_traverse, /* tp_traverse */
3186 (inquiry)memory_clear, /* tp_clear */
3187 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003188 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003189 0, /* tp_iter */
3190 0, /* tp_iternext */
3191 memory_methods, /* tp_methods */
3192 0, /* tp_members */
3193 memory_getsetlist, /* tp_getset */
3194 0, /* tp_base */
3195 0, /* tp_dict */
3196 0, /* tp_descr_get */
3197 0, /* tp_descr_set */
3198 0, /* tp_dictoffset */
3199 0, /* tp_init */
3200 0, /* tp_alloc */
3201 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003202};