blob: 0bbcbb2e7eefa7db595e7a418f3410ed2c3f8c1a [file] [log] [blame]
Miss Islington (bot)aa821342020-02-24 02:52:10 -08001/*
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 Stinnerbcda8f12018-11-21 22:27:47 +010014#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +010015#include "pycore_pymem.h"
16#include "pycore_pystate.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +000017#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +010018#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000019
Gregory P. Smith0c2f9302019-05-29 11:46:58 -070020/*[clinic input]
21class memoryview "PyMemoryViewObject *" "&PyMemoryView_Type"
22[clinic start generated code]*/
23/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2e49d2192835219]*/
24
25#include "clinic/memoryobject.c.h"
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000026
Stefan Krah9a2d99e2012-02-25 12:24:21 +010027/****************************************************************************/
28/* ManagedBuffer Object */
29/****************************************************************************/
30
31/*
32 ManagedBuffer Object:
33 ---------------------
34
35 The purpose of this object is to facilitate the handling of chained
36 memoryviews that have the same underlying exporting object. PEP-3118
37 allows the underlying object to change while a view is exported. This
38 could lead to unexpected results when constructing a new memoryview
39 from an existing memoryview.
40
41 Rather than repeatedly redirecting buffer requests to the original base
42 object, all chained memoryviews use a single buffer snapshot. This
43 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
44
45 Ownership rules:
46 ----------------
47
48 The master buffer inside a managed buffer is filled in by the original
49 base object. shape, strides, suboffsets and format are read-only for
50 all consumers.
51
52 A memoryview's buffer is a private copy of the exporter's buffer. shape,
53 strides and suboffsets belong to the memoryview and are thus writable.
54
55 If a memoryview itself exports several buffers via memory_getbuf(), all
56 buffer copies share shape, strides and suboffsets. In this case, the
57 arrays are NOT writable.
58
59 Reference count assumptions:
60 ----------------------------
61
62 The 'obj' member of a Py_buffer must either be NULL or refer to the
63 exporting base object. In the Python codebase, all getbufferprocs
64 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
65
66 PyBuffer_Release() decrements view.obj (if non-NULL), so the
67 releasebufferprocs must NOT decrement view.obj.
68*/
69
70
Stefan Krah9a2d99e2012-02-25 12:24:21 +010071#define CHECK_MBUF_RELEASED(mbuf) \
72 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
73 PyErr_SetString(PyExc_ValueError, \
74 "operation forbidden on released memoryview object"); \
75 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000076 }
77
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000078
Benjamin Peterson82cce4c2016-09-08 11:56:06 -070079static inline _PyManagedBufferObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +010080mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000081{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010082 _PyManagedBufferObject *mbuf;
83
84 mbuf = (_PyManagedBufferObject *)
85 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
86 if (mbuf == NULL)
87 return NULL;
88 mbuf->flags = 0;
89 mbuf->exports = 0;
90 mbuf->master.obj = NULL;
91 _PyObject_GC_TRACK(mbuf);
92
93 return mbuf;
94}
95
96static PyObject *
97_PyManagedBuffer_FromObject(PyObject *base)
98{
99 _PyManagedBufferObject *mbuf;
100
101 mbuf = mbuf_alloc();
102 if (mbuf == NULL)
103 return NULL;
104
105 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +0100106 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100107 Py_DECREF(mbuf);
108 return NULL;
109 }
110
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100111 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000112}
113
114static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100115mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000116{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100117 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
118 return;
119
120 /* NOTE: at this point self->exports can still be > 0 if this function
121 is called from mbuf_clear() to break up a reference cycle. */
122 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
123
124 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
125 _PyObject_GC_UNTRACK(self);
126 PyBuffer_Release(&self->master);
127}
128
129static void
130mbuf_dealloc(_PyManagedBufferObject *self)
131{
132 assert(self->exports == 0);
133 mbuf_release(self);
134 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
135 PyMem_Free(self->master.format);
136 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000137}
138
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000139static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100140mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000141{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100142 Py_VISIT(self->master.obj);
143 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000144}
145
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100146static int
147mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000148{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100149 assert(self->exports >= 0);
150 mbuf_release(self);
151 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000152}
153
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100154PyTypeObject _PyManagedBuffer_Type = {
155 PyVarObject_HEAD_INIT(&PyType_Type, 0)
156 "managedbuffer",
157 sizeof(_PyManagedBufferObject),
158 0,
159 (destructor)mbuf_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200160 0, /* tp_vectorcall_offset */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100161 0, /* tp_getattr */
162 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200163 0, /* tp_as_async */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100164 0, /* tp_repr */
165 0, /* tp_as_number */
166 0, /* tp_as_sequence */
167 0, /* tp_as_mapping */
168 0, /* tp_hash */
169 0, /* tp_call */
170 0, /* tp_str */
171 PyObject_GenericGetAttr, /* tp_getattro */
172 0, /* tp_setattro */
173 0, /* tp_as_buffer */
174 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
175 0, /* tp_doc */
176 (traverseproc)mbuf_traverse, /* tp_traverse */
177 (inquiry)mbuf_clear /* tp_clear */
178};
179
180
181/****************************************************************************/
182/* MemoryView Object */
183/****************************************************************************/
184
185/* In the process of breaking reference cycles mbuf_release() can be
186 called before memory_release(). */
187#define BASE_INACCESSIBLE(mv) \
188 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
189 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
190
191#define CHECK_RELEASED(mv) \
192 if (BASE_INACCESSIBLE(mv)) { \
193 PyErr_SetString(PyExc_ValueError, \
194 "operation forbidden on released memoryview object"); \
195 return NULL; \
196 }
197
198#define CHECK_RELEASED_INT(mv) \
199 if (BASE_INACCESSIBLE(mv)) { \
200 PyErr_SetString(PyExc_ValueError, \
201 "operation forbidden on released memoryview object"); \
202 return -1; \
203 }
204
205#define CHECK_LIST_OR_TUPLE(v) \
206 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
207 PyErr_SetString(PyExc_TypeError, \
208 #v " must be a list or a tuple"); \
209 return NULL; \
210 }
211
212#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
213
214/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100215#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100216/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100217#define ADJUST_PTR(ptr, suboffsets, dim) \
218 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100219
220/* Memoryview buffer properties */
221#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
222#define MV_F_CONTIGUOUS(flags) \
223 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
224#define MV_ANY_CONTIGUOUS(flags) \
225 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
226
227/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
228#define MV_CONTIGUOUS_NDIM1(view) \
229 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
230
231/* getbuffer() requests */
232#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
233#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
234#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
235#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
236#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
237#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
238#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
239#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
240
241
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000242PyDoc_STRVAR(memory_doc,
Stefan Krah195319e2016-12-30 12:23:35 +0100243"memoryview(object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000244\n\
245Create a new memoryview object which references the given object.");
246
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100247
248/**************************************************************************/
249/* Copy memoryview buffers */
250/**************************************************************************/
251
252/* The functions in this section take a source and a destination buffer
253 with the same logical structure: format, itemsize, ndim and shape
254 are identical, with ndim > 0.
255
256 NOTE: All buffers are assumed to have PyBUF_FULL information, which
257 is the case for memoryviews! */
258
259
260/* Assumptions: ndim >= 1. The macro tests for a corner case that should
261 perhaps be explicitly forbidden in the PEP. */
262#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
263 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
264
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700265static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000266last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100267{
268 assert(dest->ndim > 0 && src->ndim > 0);
269 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
270 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
271 dest->strides[dest->ndim-1] == dest->itemsize &&
272 src->strides[src->ndim-1] == src->itemsize);
273}
274
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000275/* This is not a general function for determining format equivalence.
276 It is used in copy_single() and copy_buffer() to weed out non-matching
277 formats. Skipping the '@' character is specifically used in slice
278 assignments, where the lvalue is already known to have a single character
279 format. This is a performance hack that could be rewritten (if properly
280 benchmarked). */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700281static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000282equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100283{
284 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100285
286 assert(dest->format && src->format);
287 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
288 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
289
290 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000291 dest->itemsize != src->itemsize) {
292 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100293 }
294
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000295 return 1;
296}
297
298/* Two shapes are equivalent if they are either equal or identical up
299 to a zero element at the same position. For example, in NumPy arrays
300 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700301static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000302equiv_shape(const Py_buffer *dest, const Py_buffer *src)
303{
304 int i;
305
306 if (dest->ndim != src->ndim)
307 return 0;
308
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100309 for (i = 0; i < dest->ndim; i++) {
310 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000311 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100312 if (dest->shape[i] == 0)
313 break;
314 }
315
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000316 return 1;
317}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100318
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000319/* Check that the logical structure of the destination and source buffers
320 is identical. */
321static int
322equiv_structure(const Py_buffer *dest, const Py_buffer *src)
323{
324 if (!equiv_format(dest, src) ||
325 !equiv_shape(dest, src)) {
326 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100327 "memoryview assignment: lvalue and rvalue have different "
328 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000329 return 0;
330 }
331
332 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100333}
334
335/* Base case for recursive multi-dimensional copying. Contiguous arrays are
336 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
337 sizeof(mem) == shape[0] * itemsize. */
338static void
339copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
340 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
341 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
342 char *mem)
343{
344 if (mem == NULL) { /* contiguous */
345 Py_ssize_t size = shape[0] * itemsize;
346 if (dptr + size < sptr || sptr + size < dptr)
347 memcpy(dptr, sptr, size); /* no overlapping */
348 else
349 memmove(dptr, sptr, size);
350 }
351 else {
352 char *p;
353 Py_ssize_t i;
354 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100355 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100356 memcpy(p, xsptr, itemsize);
357 }
358 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100359 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100360 memcpy(xdptr, p, itemsize);
361 }
362 }
363
364}
365
366/* Recursively copy a source buffer to a destination buffer. The two buffers
367 have the same ndim, shape and itemsize. */
368static void
369copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
370 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
371 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
372 char *mem)
373{
374 Py_ssize_t i;
375
376 assert(ndim >= 1);
377
378 if (ndim == 1) {
379 copy_base(shape, itemsize,
380 dptr, dstrides, dsuboffsets,
381 sptr, sstrides, ssuboffsets,
382 mem);
383 return;
384 }
385
386 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100387 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
388 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100389
390 copy_rec(shape+1, ndim-1, itemsize,
391 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
392 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
393 mem);
394 }
395}
396
397/* Faster copying of one-dimensional arrays. */
398static int
399copy_single(Py_buffer *dest, Py_buffer *src)
400{
401 char *mem = NULL;
402
403 assert(dest->ndim == 1);
404
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000405 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100406 return -1;
407
408 if (!last_dim_is_contiguous(dest, src)) {
409 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
410 if (mem == NULL) {
411 PyErr_NoMemory();
412 return -1;
413 }
414 }
415
416 copy_base(dest->shape, dest->itemsize,
417 dest->buf, dest->strides, dest->suboffsets,
418 src->buf, src->strides, src->suboffsets,
419 mem);
420
421 if (mem)
422 PyMem_Free(mem);
423
424 return 0;
425}
426
427/* Recursively copy src to dest. Both buffers must have the same basic
428 structure. Copying is atomic, the function never fails with a partial
429 copy. */
430static int
431copy_buffer(Py_buffer *dest, Py_buffer *src)
432{
433 char *mem = NULL;
434
435 assert(dest->ndim > 0);
436
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000437 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100438 return -1;
439
440 if (!last_dim_is_contiguous(dest, src)) {
441 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
442 if (mem == NULL) {
443 PyErr_NoMemory();
444 return -1;
445 }
446 }
447
448 copy_rec(dest->shape, dest->ndim, dest->itemsize,
449 dest->buf, dest->strides, dest->suboffsets,
450 src->buf, src->strides, src->suboffsets,
451 mem);
452
453 if (mem)
454 PyMem_Free(mem);
455
456 return 0;
457}
458
459/* Initialize strides for a C-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700460static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100461init_strides_from_shape(Py_buffer *view)
462{
463 Py_ssize_t i;
464
465 assert(view->ndim > 0);
466
467 view->strides[view->ndim-1] = view->itemsize;
468 for (i = view->ndim-2; i >= 0; i--)
469 view->strides[i] = view->strides[i+1] * view->shape[i+1];
470}
471
472/* Initialize strides for a Fortran-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700473static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100474init_fortran_strides_from_shape(Py_buffer *view)
475{
476 Py_ssize_t i;
477
478 assert(view->ndim > 0);
479
480 view->strides[0] = view->itemsize;
481 for (i = 1; i < view->ndim; i++)
482 view->strides[i] = view->strides[i-1] * view->shape[i-1];
483}
484
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200485/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
486 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100487 len(mem) == src->len. */
488static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200489buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100490{
491 Py_buffer dest;
492 Py_ssize_t *strides;
493 int ret;
494
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200495 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100496 assert(src->shape != NULL);
497 assert(src->strides != NULL);
498
499 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
500 if (strides == NULL) {
501 PyErr_NoMemory();
502 return -1;
503 }
504
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200505 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100506 dest = *src;
507 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200508 /* shape is constant and shared: the logical representation of the
509 array is unaltered. */
510
511 /* The physical representation determined by strides (and possibly
512 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100513 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200514 if (order == 'C' || order == 'A') {
515 init_strides_from_shape(&dest);
516 }
517 else {
518 init_fortran_strides_from_shape(&dest);
519 }
520
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100521 dest.suboffsets = NULL;
522
523 ret = copy_buffer(&dest, src);
524
525 PyMem_Free(strides);
526 return ret;
527}
528
529
530/****************************************************************************/
531/* Constructors */
532/****************************************************************************/
533
534/* Initialize values that are shared with the managed buffer. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700535static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100536init_shared_values(Py_buffer *dest, const Py_buffer *src)
537{
538 dest->obj = src->obj;
539 dest->buf = src->buf;
540 dest->len = src->len;
541 dest->itemsize = src->itemsize;
542 dest->readonly = src->readonly;
543 dest->format = src->format ? src->format : "B";
544 dest->internal = src->internal;
545}
546
547/* Copy shape and strides. Reconstruct missing values. */
548static void
549init_shape_strides(Py_buffer *dest, const Py_buffer *src)
550{
551 Py_ssize_t i;
552
553 if (src->ndim == 0) {
554 dest->shape = NULL;
555 dest->strides = NULL;
556 return;
557 }
558 if (src->ndim == 1) {
559 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
560 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
561 return;
562 }
563
564 for (i = 0; i < src->ndim; i++)
565 dest->shape[i] = src->shape[i];
566 if (src->strides) {
567 for (i = 0; i < src->ndim; i++)
568 dest->strides[i] = src->strides[i];
569 }
570 else {
571 init_strides_from_shape(dest);
572 }
573}
574
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700575static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100576init_suboffsets(Py_buffer *dest, const Py_buffer *src)
577{
578 Py_ssize_t i;
579
580 if (src->suboffsets == NULL) {
581 dest->suboffsets = NULL;
582 return;
583 }
584 for (i = 0; i < src->ndim; i++)
585 dest->suboffsets[i] = src->suboffsets[i];
586}
587
588/* len = product(shape) * itemsize */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700589static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100590init_len(Py_buffer *view)
591{
592 Py_ssize_t i, len;
593
594 len = 1;
595 for (i = 0; i < view->ndim; i++)
596 len *= view->shape[i];
597 len *= view->itemsize;
598
599 view->len = len;
600}
601
602/* Initialize memoryview buffer properties. */
603static void
604init_flags(PyMemoryViewObject *mv)
605{
606 const Py_buffer *view = &mv->view;
607 int flags = 0;
608
609 switch (view->ndim) {
610 case 0:
611 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
612 _Py_MEMORYVIEW_FORTRAN);
613 break;
614 case 1:
615 if (MV_CONTIGUOUS_NDIM1(view))
616 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
617 break;
618 default:
619 if (PyBuffer_IsContiguous(view, 'C'))
620 flags |= _Py_MEMORYVIEW_C;
621 if (PyBuffer_IsContiguous(view, 'F'))
622 flags |= _Py_MEMORYVIEW_FORTRAN;
623 break;
624 }
625
626 if (view->suboffsets) {
627 flags |= _Py_MEMORYVIEW_PIL;
628 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
629 }
630
631 mv->flags = flags;
632}
633
634/* Allocate a new memoryview and perform basic initialization. New memoryviews
635 are exclusively created through the mbuf_add functions. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700636static inline PyMemoryViewObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100637memory_alloc(int ndim)
638{
639 PyMemoryViewObject *mv;
640
641 mv = (PyMemoryViewObject *)
642 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
643 if (mv == NULL)
644 return NULL;
645
646 mv->mbuf = NULL;
647 mv->hash = -1;
648 mv->flags = 0;
649 mv->exports = 0;
650 mv->view.ndim = ndim;
651 mv->view.shape = mv->ob_array;
652 mv->view.strides = mv->ob_array + ndim;
653 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100654 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100655
656 _PyObject_GC_TRACK(mv);
657 return mv;
658}
659
660/*
661 Return a new memoryview that is registered with mbuf. If src is NULL,
662 use mbuf->master as the underlying buffer. Otherwise, use src.
663
664 The new memoryview has full buffer information: shape and strides
665 are always present, suboffsets as needed. Arrays are copied to
666 the memoryview's ob_array field.
667 */
668static PyObject *
669mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
670{
671 PyMemoryViewObject *mv;
672 Py_buffer *dest;
673
674 if (src == NULL)
675 src = &mbuf->master;
676
677 if (src->ndim > PyBUF_MAX_NDIM) {
678 PyErr_SetString(PyExc_ValueError,
679 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200680 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100681 return NULL;
682 }
683
684 mv = memory_alloc(src->ndim);
685 if (mv == NULL)
686 return NULL;
687
688 dest = &mv->view;
689 init_shared_values(dest, src);
690 init_shape_strides(dest, src);
691 init_suboffsets(dest, src);
692 init_flags(mv);
693
694 mv->mbuf = mbuf;
695 Py_INCREF(mbuf);
696 mbuf->exports++;
697
698 return (PyObject *)mv;
699}
700
701/* Register an incomplete view: shape, strides, suboffsets and flags still
702 need to be initialized. Use 'ndim' instead of src->ndim to determine the
703 size of the memoryview's ob_array.
704
705 Assumption: ndim <= PyBUF_MAX_NDIM. */
706static PyObject *
707mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
708 int ndim)
709{
710 PyMemoryViewObject *mv;
711 Py_buffer *dest;
712
713 if (src == NULL)
714 src = &mbuf->master;
715
716 assert(ndim <= PyBUF_MAX_NDIM);
717
718 mv = memory_alloc(ndim);
719 if (mv == NULL)
720 return NULL;
721
722 dest = &mv->view;
723 init_shared_values(dest, src);
724
725 mv->mbuf = mbuf;
726 Py_INCREF(mbuf);
727 mbuf->exports++;
728
729 return (PyObject *)mv;
730}
731
732/* Expose a raw memory area as a view of contiguous bytes. flags can be
733 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
734 The memoryview has complete buffer information. */
735PyObject *
736PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
737{
738 _PyManagedBufferObject *mbuf;
739 PyObject *mv;
740 int readonly;
741
742 assert(mem != NULL);
743 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
744
745 mbuf = mbuf_alloc();
746 if (mbuf == NULL)
747 return NULL;
748
749 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
750 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
751 PyBUF_FULL_RO);
752
753 mv = mbuf_add_view(mbuf, NULL);
754 Py_DECREF(mbuf);
755
756 return mv;
757}
758
759/* Create a memoryview from a given Py_buffer. For simple byte views,
760 PyMemoryView_FromMemory() should be used instead.
761 This function is the only entry point that can create a master buffer
762 without full information. Because of this fact init_shape_strides()
763 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000764PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000765PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000766{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100767 _PyManagedBufferObject *mbuf;
768 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000769
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000770 if (info->buf == NULL) {
771 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100772 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000773 return NULL;
774 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100775
776 mbuf = mbuf_alloc();
777 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000778 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100779
780 /* info->obj is either NULL or a borrowed reference. This reference
781 should not be decremented in PyBuffer_Release(). */
782 mbuf->master = *info;
783 mbuf->master.obj = NULL;
784
785 mv = mbuf_add_view(mbuf, NULL);
786 Py_DECREF(mbuf);
787
788 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000789}
790
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100791/* Create a memoryview from an object that implements the buffer protocol.
792 If the object is a memoryview, the new memoryview must be registered
793 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000794PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100795PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000796{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100797 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000798
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100799 if (PyMemoryView_Check(v)) {
800 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
801 CHECK_RELEASED(mv);
802 return mbuf_add_view(mv->mbuf, &mv->view);
803 }
804 else if (PyObject_CheckBuffer(v)) {
805 PyObject *ret;
806 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
807 if (mbuf == NULL)
808 return NULL;
809 ret = mbuf_add_view(mbuf, NULL);
810 Py_DECREF(mbuf);
811 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000812 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000813
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100814 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400815 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100816 Py_TYPE(v)->tp_name);
817 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000818}
819
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100820/* Copy the format string from a base object that might vanish. */
821static int
822mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
823{
824 if (fmt != NULL) {
825 char *cp = PyMem_Malloc(strlen(fmt)+1);
826 if (cp == NULL) {
827 PyErr_NoMemory();
828 return -1;
829 }
830 mbuf->master.format = strcpy(cp, fmt);
831 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
832 }
833
834 return 0;
835}
836
837/*
838 Return a memoryview that is based on a contiguous copy of src.
839 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
840
841 Ownership rules:
842 1) As usual, the returned memoryview has a private copy
843 of src->shape, src->strides and src->suboffsets.
844 2) src->format is copied to the master buffer and released
845 in mbuf_dealloc(). The releasebufferproc of the bytes
846 object is NULL, so it does not matter that mbuf_release()
847 passes the altered format pointer to PyBuffer_Release().
848*/
849static PyObject *
850memory_from_contiguous_copy(Py_buffer *src, char order)
851{
852 _PyManagedBufferObject *mbuf;
853 PyMemoryViewObject *mv;
854 PyObject *bytes;
855 Py_buffer *dest;
856 int i;
857
858 assert(src->ndim > 0);
859 assert(src->shape != NULL);
860
861 bytes = PyBytes_FromStringAndSize(NULL, src->len);
862 if (bytes == NULL)
863 return NULL;
864
865 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
866 Py_DECREF(bytes);
867 if (mbuf == NULL)
868 return NULL;
869
870 if (mbuf_copy_format(mbuf, src->format) < 0) {
871 Py_DECREF(mbuf);
872 return NULL;
873 }
874
875 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
876 Py_DECREF(mbuf);
877 if (mv == NULL)
878 return NULL;
879
880 dest = &mv->view;
881
882 /* shared values are initialized correctly except for itemsize */
883 dest->itemsize = src->itemsize;
884
885 /* shape and strides */
886 for (i = 0; i < src->ndim; i++) {
887 dest->shape[i] = src->shape[i];
888 }
889 if (order == 'C' || order == 'A') {
890 init_strides_from_shape(dest);
891 }
892 else {
893 init_fortran_strides_from_shape(dest);
894 }
895 /* suboffsets */
896 dest->suboffsets = NULL;
897
898 /* flags */
899 init_flags(mv);
900
901 if (copy_buffer(dest, src) < 0) {
902 Py_DECREF(mv);
903 return NULL;
904 }
905
906 return (PyObject *)mv;
907}
908
909/*
910 Return a new memoryview object based on a contiguous exporter with
911 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
912 The logical structure of the input and output buffers is the same
913 (i.e. tolist(input) == tolist(output)), but the physical layout in
914 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200915
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100916 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
917 otherwise it may be writable or read-only.
918
919 If the exporter is already contiguous with the desired target order,
920 the memoryview will be directly based on the exporter.
921
922 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
923 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
924 'F'ortran order otherwise.
925*/
926PyObject *
927PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
928{
929 PyMemoryViewObject *mv;
930 PyObject *ret;
931 Py_buffer *view;
932
933 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
934 assert(order == 'C' || order == 'F' || order == 'A');
935
936 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
937 if (mv == NULL)
938 return NULL;
939
940 view = &mv->view;
941 if (buffertype == PyBUF_WRITE && view->readonly) {
942 PyErr_SetString(PyExc_BufferError,
943 "underlying buffer is not writable");
944 Py_DECREF(mv);
945 return NULL;
946 }
947
948 if (PyBuffer_IsContiguous(view, order))
949 return (PyObject *)mv;
950
951 if (buffertype == PyBUF_WRITE) {
952 PyErr_SetString(PyExc_BufferError,
953 "writable contiguous buffer requested "
954 "for a non-contiguous object.");
955 Py_DECREF(mv);
956 return NULL;
957 }
958
959 ret = memory_from_contiguous_copy(view, order);
960 Py_DECREF(mv);
961 return ret;
962}
963
964
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000965static PyObject *
966memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
967{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000968 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100969 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000970
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000971 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
972 &obj)) {
973 return NULL;
974 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000975
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000976 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000977}
978
979
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100980/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200981/* Previously in abstract.c */
982/****************************************************************************/
983
984typedef struct {
985 Py_buffer view;
986 Py_ssize_t array[1];
987} Py_buffer_full;
988
989int
990PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
991{
992 Py_buffer_full *fb = NULL;
993 int ret;
994
995 assert(order == 'C' || order == 'F' || order == 'A');
996
997 if (len != src->len) {
998 PyErr_SetString(PyExc_ValueError,
999 "PyBuffer_ToContiguous: len != view->len");
1000 return -1;
1001 }
1002
1003 if (PyBuffer_IsContiguous(src, order)) {
1004 memcpy((char *)buf, src->buf, len);
1005 return 0;
1006 }
1007
1008 /* buffer_to_contiguous() assumes PyBUF_FULL */
1009 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
1010 if (fb == NULL) {
1011 PyErr_NoMemory();
1012 return -1;
1013 }
1014 fb->view.ndim = src->ndim;
1015 fb->view.shape = fb->array;
1016 fb->view.strides = fb->array + src->ndim;
1017 fb->view.suboffsets = fb->array + 2 * src->ndim;
1018
1019 init_shared_values(&fb->view, src);
1020 init_shape_strides(&fb->view, src);
1021 init_suboffsets(&fb->view, src);
1022
1023 src = &fb->view;
1024
1025 ret = buffer_to_contiguous(buf, src, order);
1026 PyMem_Free(fb);
1027 return ret;
1028}
1029
1030
1031/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001032/* Release/GC management */
1033/****************************************************************************/
1034
1035/* Inform the managed buffer that this particular memoryview will not access
1036 the underlying buffer again. If no other memoryviews are registered with
1037 the managed buffer, the underlying buffer is released instantly and
1038 marked as inaccessible for both the memoryview and the managed buffer.
1039
1040 This function fails if the memoryview itself has exported buffers. */
1041static int
1042_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001043{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001044 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1045 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001046
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001047 if (self->exports == 0) {
1048 self->flags |= _Py_MEMORYVIEW_RELEASED;
1049 assert(self->mbuf->exports > 0);
1050 if (--self->mbuf->exports == 0)
1051 mbuf_release(self->mbuf);
1052 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001053 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001054 if (self->exports > 0) {
1055 PyErr_Format(PyExc_BufferError,
1056 "memoryview has %zd exported buffer%s", self->exports,
1057 self->exports==1 ? "" : "s");
1058 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001059 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001060
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001061 Py_FatalError("_memory_release(): negative export count");
1062 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' */
Miss Islington (bot)190433d2020-02-11 18:47:20 -08001694 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
1975 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1976 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);
2014 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
2015 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);
2423 if (!PyIndex_Check(x))
2424 return 0;
2425 }
2426 return 1;
2427}
2428
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002429/* mv[obj] returns an object holding the data for one element if obj
2430 fully indexes the memoryview or another memoryview object if it
2431 does not.
2432
2433 0-d memoryview objects can be referenced using mv[...] or mv[()]
2434 but not with anything else. */
2435static PyObject *
2436memory_subscript(PyMemoryViewObject *self, PyObject *key)
2437{
2438 Py_buffer *view;
2439 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002440
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002441 CHECK_RELEASED(self);
2442
2443 if (view->ndim == 0) {
2444 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2445 const char *fmt = adjust_fmt(view);
2446 if (fmt == NULL)
2447 return NULL;
2448 return unpack_single(view->buf, fmt);
2449 }
2450 else if (key == Py_Ellipsis) {
2451 Py_INCREF(self);
2452 return (PyObject *)self;
2453 }
2454 else {
2455 PyErr_SetString(PyExc_TypeError,
2456 "invalid indexing of 0-dim memory");
2457 return NULL;
2458 }
2459 }
2460
2461 if (PyIndex_Check(key)) {
2462 Py_ssize_t index;
2463 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2464 if (index == -1 && PyErr_Occurred())
2465 return NULL;
2466 return memory_item(self, index);
2467 }
2468 else if (PySlice_Check(key)) {
2469 PyMemoryViewObject *sliced;
2470
2471 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2472 if (sliced == NULL)
2473 return NULL;
2474
2475 if (init_slice(&sliced->view, key, 0) < 0) {
2476 Py_DECREF(sliced);
2477 return NULL;
2478 }
2479 init_len(&sliced->view);
2480 init_flags(sliced);
2481
2482 return (PyObject *)sliced;
2483 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002484 else if (is_multiindex(key)) {
2485 return memory_item_multi(self, key);
2486 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002487 else if (is_multislice(key)) {
2488 PyErr_SetString(PyExc_NotImplementedError,
2489 "multi-dimensional slicing is not implemented");
2490 return NULL;
2491 }
2492
2493 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2494 return NULL;
2495}
2496
2497static int
2498memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2499{
2500 Py_buffer *view = &(self->view);
2501 Py_buffer src;
2502 const char *fmt;
2503 char *ptr;
2504
2505 CHECK_RELEASED_INT(self);
2506
2507 fmt = adjust_fmt(view);
2508 if (fmt == NULL)
2509 return -1;
2510
2511 if (view->readonly) {
2512 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2513 return -1;
2514 }
2515 if (value == NULL) {
2516 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2517 return -1;
2518 }
2519 if (view->ndim == 0) {
2520 if (key == Py_Ellipsis ||
2521 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2522 ptr = (char *)view->buf;
2523 return pack_single(ptr, value, fmt);
2524 }
2525 else {
2526 PyErr_SetString(PyExc_TypeError,
2527 "invalid indexing of 0-dim memory");
2528 return -1;
2529 }
2530 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002531
2532 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002533 Py_ssize_t index;
2534 if (1 < view->ndim) {
2535 PyErr_SetString(PyExc_NotImplementedError,
2536 "sub-views are not implemented");
2537 return -1;
2538 }
2539 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002540 if (index == -1 && PyErr_Occurred())
2541 return -1;
2542 ptr = ptr_from_index(view, index);
2543 if (ptr == NULL)
2544 return -1;
2545 return pack_single(ptr, value, fmt);
2546 }
2547 /* one-dimensional: fast path */
2548 if (PySlice_Check(key) && view->ndim == 1) {
2549 Py_buffer dest; /* sliced view */
2550 Py_ssize_t arrays[3];
2551 int ret = -1;
2552
2553 /* rvalue must be an exporter */
2554 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2555 return ret;
2556
2557 dest = *view;
2558 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2559 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2560 if (view->suboffsets) {
2561 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2562 }
2563
2564 if (init_slice(&dest, key, 0) < 0)
2565 goto end_block;
2566 dest.len = dest.shape[0] * dest.itemsize;
2567
2568 ret = copy_single(&dest, &src);
2569
2570 end_block:
2571 PyBuffer_Release(&src);
2572 return ret;
2573 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002574 if (is_multiindex(key)) {
2575 char *ptr;
2576 if (PyTuple_GET_SIZE(key) < view->ndim) {
2577 PyErr_SetString(PyExc_NotImplementedError,
2578 "sub-views are not implemented");
2579 return -1;
2580 }
2581 ptr = ptr_from_tuple(view, key);
2582 if (ptr == NULL)
2583 return -1;
2584 return pack_single(ptr, value, fmt);
2585 }
2586 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002587 /* Call memory_subscript() to produce a sliced lvalue, then copy
2588 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2589 PyErr_SetString(PyExc_NotImplementedError,
2590 "memoryview slice assignments are currently restricted "
2591 "to ndim = 1");
2592 return -1;
2593 }
2594
2595 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2596 return -1;
2597}
2598
2599static Py_ssize_t
2600memory_length(PyMemoryViewObject *self)
2601{
2602 CHECK_RELEASED_INT(self);
2603 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2604}
2605
2606/* As mapping */
2607static PyMappingMethods memory_as_mapping = {
2608 (lenfunc)memory_length, /* mp_length */
2609 (binaryfunc)memory_subscript, /* mp_subscript */
2610 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2611};
2612
2613/* As sequence */
2614static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002615 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002616 0, /* sq_concat */
2617 0, /* sq_repeat */
2618 (ssizeargfunc)memory_item, /* sq_item */
2619};
2620
2621
2622/**************************************************************************/
2623/* Comparisons */
2624/**************************************************************************/
2625
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002626#define MV_COMPARE_EX -1 /* exception */
2627#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2628
2629/* Translate a StructError to "not equal". Preserve other exceptions. */
2630static int
2631fix_struct_error_int(void)
2632{
2633 assert(PyErr_Occurred());
2634 /* XXX Cannot get at StructError directly? */
2635 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2636 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2637 return MV_COMPARE_EX;
2638 }
2639 /* StructError: invalid or unknown format -> not equal */
2640 PyErr_Clear();
2641 return 0;
2642}
2643
2644/* Unpack and compare single items of p and q using the struct module. */
2645static int
2646struct_unpack_cmp(const char *p, const char *q,
2647 struct unpacker *unpack_p, struct unpacker *unpack_q)
2648{
2649 PyObject *v, *w;
2650 int ret;
2651
2652 /* At this point any exception from the struct module should not be
2653 StructError, since both formats have been accepted already. */
2654 v = struct_unpack_single(p, unpack_p);
2655 if (v == NULL)
2656 return MV_COMPARE_EX;
2657
2658 w = struct_unpack_single(q, unpack_q);
2659 if (w == NULL) {
2660 Py_DECREF(v);
2661 return MV_COMPARE_EX;
2662 }
2663
2664 /* MV_COMPARE_EX == -1: exceptions are preserved */
2665 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2666 Py_DECREF(v);
2667 Py_DECREF(w);
2668
2669 return ret;
2670}
2671
2672/* Unpack and compare single items of p and q. If both p and q have the same
2673 single element native format, the comparison uses a fast path (gcc creates
2674 a jump table and converts memcpy into simple assignments on x86/x64).
2675
2676 Otherwise, the comparison is delegated to the struct module, which is
2677 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002678#define CMP_SINGLE(p, q, type) \
2679 do { \
2680 type x; \
2681 type y; \
2682 memcpy((char *)&x, p, sizeof x); \
2683 memcpy((char *)&y, q, sizeof y); \
2684 equal = (x == y); \
2685 } while (0)
2686
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002687static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002688unpack_cmp(const char *p, const char *q, char fmt,
2689 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002690{
2691 int equal;
2692
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002693 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002694
2695 /* signed integers and fast path for 'B' */
Miss Islington (bot)190433d2020-02-11 18:47:20 -08002696 case 'B': return *((const unsigned char *)p) == *((const unsigned char *)q);
2697 case 'b': return *((const signed char *)p) == *((const signed char *)q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002698 case 'h': CMP_SINGLE(p, q, short); return equal;
2699 case 'i': CMP_SINGLE(p, q, int); return equal;
2700 case 'l': CMP_SINGLE(p, q, long); return equal;
2701
2702 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002703 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002704
2705 /* unsigned integers */
2706 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2707 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2708 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2709
2710 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002711 case 'q': CMP_SINGLE(p, q, long long); return equal;
2712 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002713
2714 /* ssize_t and size_t */
2715 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2716 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2717
2718 /* floats */
2719 /* XXX DBL_EPSILON? */
2720 case 'f': CMP_SINGLE(p, q, float); return equal;
2721 case 'd': CMP_SINGLE(p, q, double); return equal;
2722
2723 /* bytes object */
2724 case 'c': return *p == *q;
2725
2726 /* pointer */
2727 case 'P': CMP_SINGLE(p, q, void *); return equal;
2728
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002729 /* use the struct module */
2730 case '_':
2731 assert(unpack_p);
2732 assert(unpack_q);
2733 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002734 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002735
2736 /* NOT REACHED */
2737 PyErr_SetString(PyExc_RuntimeError,
2738 "memoryview: internal error in richcompare");
2739 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002740}
2741
2742/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2743static int
2744cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2745 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2746 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002747 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002748{
2749 Py_ssize_t i;
2750 int equal;
2751
2752 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002753 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2754 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002755 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002756 if (equal <= 0)
2757 return equal;
2758 }
2759
2760 return 1;
2761}
2762
2763/* Recursively compare two multi-dimensional arrays that have the same
2764 logical structure. Assumption: ndim >= 1. */
2765static int
2766cmp_rec(const char *p, const char *q,
2767 Py_ssize_t ndim, const Py_ssize_t *shape,
2768 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2769 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002770 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002771{
2772 Py_ssize_t i;
2773 int equal;
2774
2775 assert(ndim >= 1);
2776 assert(shape != NULL);
2777 assert(pstrides != NULL);
2778 assert(qstrides != NULL);
2779
2780 if (ndim == 1) {
2781 return cmp_base(p, q, shape,
2782 pstrides, psuboffsets,
2783 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002784 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002785 }
2786
2787 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002788 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2789 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002790 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2791 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2792 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002793 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002794 if (equal <= 0)
2795 return equal;
2796 }
2797
2798 return 1;
2799}
2800
2801static PyObject *
2802memory_richcompare(PyObject *v, PyObject *w, int op)
2803{
2804 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002805 Py_buffer wbuf, *vv;
2806 Py_buffer *ww = NULL;
2807 struct unpacker *unpack_v = NULL;
2808 struct unpacker *unpack_w = NULL;
2809 char vfmt, wfmt;
2810 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002811
2812 if (op != Py_EQ && op != Py_NE)
2813 goto result; /* Py_NotImplemented */
2814
2815 assert(PyMemoryView_Check(v));
2816 if (BASE_INACCESSIBLE(v)) {
2817 equal = (v == w);
2818 goto result;
2819 }
2820 vv = VIEW_ADDR(v);
2821
2822 if (PyMemoryView_Check(w)) {
2823 if (BASE_INACCESSIBLE(w)) {
2824 equal = (v == w);
2825 goto result;
2826 }
2827 ww = VIEW_ADDR(w);
2828 }
2829 else {
2830 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2831 PyErr_Clear();
2832 goto result; /* Py_NotImplemented */
2833 }
2834 ww = &wbuf;
2835 }
2836
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002837 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002838 PyErr_Clear();
2839 equal = 0;
2840 goto result;
2841 }
2842
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002843 /* Use fast unpacking for identical primitive C type formats. */
2844 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2845 vfmt = '_';
2846 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2847 wfmt = '_';
2848 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2849 /* Use struct module unpacking. NOTE: Even for equal format strings,
2850 memcmp() cannot be used for item comparison since it would give
2851 incorrect results in the case of NaNs or uninitialized padding
2852 bytes. */
2853 vfmt = '_';
2854 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2855 if (unpack_v == NULL) {
2856 equal = fix_struct_error_int();
2857 goto result;
2858 }
2859 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2860 if (unpack_w == NULL) {
2861 equal = fix_struct_error_int();
2862 goto result;
2863 }
2864 }
2865
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002866 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002867 equal = unpack_cmp(vv->buf, ww->buf,
2868 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002869 }
2870 else if (vv->ndim == 1) {
2871 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2872 vv->strides, vv->suboffsets,
2873 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002874 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002875 }
2876 else {
2877 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2878 vv->strides, vv->suboffsets,
2879 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002880 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002881 }
2882
2883result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002884 if (equal < 0) {
2885 if (equal == MV_COMPARE_NOT_IMPL)
2886 res = Py_NotImplemented;
2887 else /* exception */
2888 res = NULL;
2889 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002890 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2891 res = Py_True;
2892 else
2893 res = Py_False;
2894
2895 if (ww == &wbuf)
2896 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002897
2898 unpacker_free(unpack_v);
2899 unpacker_free(unpack_w);
2900
2901 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002902 return res;
2903}
2904
2905/**************************************************************************/
2906/* Hash */
2907/**************************************************************************/
2908
2909static Py_hash_t
2910memory_hash(PyMemoryViewObject *self)
2911{
2912 if (self->hash == -1) {
2913 Py_buffer *view = &self->view;
2914 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002915 Py_ssize_t ret;
2916 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002917
2918 CHECK_RELEASED_INT(self);
2919
2920 if (!view->readonly) {
2921 PyErr_SetString(PyExc_ValueError,
2922 "cannot hash writable memoryview object");
2923 return -1;
2924 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002925 ret = get_native_fmtchar(&fmt, view->format);
2926 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2927 PyErr_SetString(PyExc_ValueError,
2928 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2929 return -1;
2930 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002931 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2932 /* Keep the original error message */
2933 return -1;
2934 }
2935
2936 if (!MV_C_CONTIGUOUS(self->flags)) {
2937 mem = PyMem_Malloc(view->len);
2938 if (mem == NULL) {
2939 PyErr_NoMemory();
2940 return -1;
2941 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002942 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002943 PyMem_Free(mem);
2944 return -1;
2945 }
2946 }
2947
2948 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002949 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002950
2951 if (mem != view->buf)
2952 PyMem_Free(mem);
2953 }
2954
2955 return self->hash;
2956}
2957
2958
2959/**************************************************************************/
2960/* getters */
2961/**************************************************************************/
2962
2963static PyObject *
2964_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2965{
2966 int i;
2967 PyObject *o;
2968 PyObject *intTuple;
2969
2970 if (vals == NULL)
2971 return PyTuple_New(0);
2972
2973 intTuple = PyTuple_New(len);
2974 if (!intTuple)
2975 return NULL;
2976 for (i=0; i<len; i++) {
2977 o = PyLong_FromSsize_t(vals[i]);
2978 if (!o) {
2979 Py_DECREF(intTuple);
2980 return NULL;
2981 }
2982 PyTuple_SET_ITEM(intTuple, i, o);
2983 }
2984 return intTuple;
2985}
2986
2987static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002988memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002989{
2990 Py_buffer *view = &self->view;
2991
2992 CHECK_RELEASED(self);
2993 if (view->obj == NULL) {
2994 Py_RETURN_NONE;
2995 }
2996 Py_INCREF(view->obj);
2997 return view->obj;
2998}
2999
3000static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003001memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003002{
3003 CHECK_RELEASED(self);
3004 return PyLong_FromSsize_t(self->view.len);
3005}
3006
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003007static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003008memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003009{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003010 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003011 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003012}
3013
3014static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003015memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003016{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003017 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003018 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003019}
3020
3021static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003022memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003023{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003024 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003025 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003026}
3027
3028static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003029memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003030{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003031 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003032 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003033}
3034
3035static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003036memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003037{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003038 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003039 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003040}
3041
3042static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003043memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003044{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003045 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003046 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003047}
3048
3049static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003050memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003051{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003052 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003053 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003054}
3055
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003056static PyObject *
3057memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3058{
3059 CHECK_RELEASED(self);
3060 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3061}
3062
3063static PyObject *
3064memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3065{
3066 CHECK_RELEASED(self);
3067 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3068}
3069
3070static PyObject *
3071memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3072{
3073 CHECK_RELEASED(self);
3074 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3075}
3076
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003077PyDoc_STRVAR(memory_obj_doc,
3078 "The underlying object of the memoryview.");
3079PyDoc_STRVAR(memory_nbytes_doc,
3080 "The amount of space in bytes that the array would use in\n"
3081 " a contiguous representation.");
3082PyDoc_STRVAR(memory_readonly_doc,
3083 "A bool indicating whether the memory is read only.");
3084PyDoc_STRVAR(memory_itemsize_doc,
3085 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003086PyDoc_STRVAR(memory_format_doc,
3087 "A string containing the format (in struct module style)\n"
3088 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003089PyDoc_STRVAR(memory_ndim_doc,
3090 "An integer indicating how many dimensions of a multi-dimensional\n"
3091 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003092PyDoc_STRVAR(memory_shape_doc,
3093 "A tuple of ndim integers giving the shape of the memory\n"
3094 " as an N-dimensional array.");
3095PyDoc_STRVAR(memory_strides_doc,
3096 "A tuple of ndim integers giving the size in bytes to access\n"
3097 " each element for each dimension of the array.");
3098PyDoc_STRVAR(memory_suboffsets_doc,
3099 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003100PyDoc_STRVAR(memory_c_contiguous_doc,
3101 "A bool indicating whether the memory is C contiguous.");
3102PyDoc_STRVAR(memory_f_contiguous_doc,
3103 "A bool indicating whether the memory is Fortran contiguous.");
3104PyDoc_STRVAR(memory_contiguous_doc,
3105 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003106
Stefan Krahbcaf5992014-05-18 00:35:09 +02003107
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003108static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003109 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3110 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003111 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3112 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3113 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3114 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3115 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3116 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3117 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003118 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3119 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3120 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003121 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003122};
3123
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003124PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003125"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003126\n\
3127Release the underlying buffer exposed by the memoryview object.");
3128PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahd08ea702019-02-02 18:57:41 +01003129"tobytes($self, /, order=None)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003130\n\
Stefan Krahd08ea702019-02-02 18:57:41 +01003131Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
3132When order is 'C' or 'F', the data of the original array is converted to C or\n\
3133Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
3134memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
3135views, the data is converted to C first. order=None is the same as order='C'.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003136PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003137"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003138\n\
3139Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003140PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003141"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003142\n\
3143Cast a memoryview to a new format or shape.");
Antoine Pitrou480ab052018-04-14 19:49:21 +02003144PyDoc_STRVAR(memory_toreadonly_doc,
3145"toreadonly($self, /)\n--\n\
3146\n\
3147Return a readonly version of the memoryview.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003148
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003149static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003150 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
Stéphane Wirtel359a2f32019-03-05 16:10:53 +01003151 {"tobytes", (PyCFunction)(void(*)(void))memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07003152 MEMORYVIEW_HEX_METHODDEF
Alexander Belopolskye370c382012-09-03 16:43:55 -04003153 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02003154 {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Antoine Pitrou480ab052018-04-14 19:49:21 +02003155 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003156 {"__enter__", memory_enter, METH_NOARGS, NULL},
3157 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003158 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003159};
3160
3161
3162PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003163 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003164 "memoryview", /* tp_name */
3165 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3166 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003167 (destructor)memory_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003168 0, /* tp_vectorcall_offset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003169 0, /* tp_getattr */
3170 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003171 0, /* tp_as_async */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003172 (reprfunc)memory_repr, /* tp_repr */
3173 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003174 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003175 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003176 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003177 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003178 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003179 PyObject_GenericGetAttr, /* tp_getattro */
3180 0, /* tp_setattro */
3181 &memory_as_buffer, /* tp_as_buffer */
3182 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3183 memory_doc, /* tp_doc */
3184 (traverseproc)memory_traverse, /* tp_traverse */
3185 (inquiry)memory_clear, /* tp_clear */
3186 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003187 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003188 0, /* tp_iter */
3189 0, /* tp_iternext */
3190 memory_methods, /* tp_methods */
3191 0, /* tp_members */
3192 memory_getsetlist, /* tp_getset */
3193 0, /* tp_base */
3194 0, /* tp_dict */
3195 0, /* tp_descr_get */
3196 0, /* tp_descr_set */
3197 0, /* tp_dictoffset */
3198 0, /* tp_init */
3199 0, /* tp_alloc */
3200 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003201};