blob: 7f9c90035f57424cc54713dc31fd98c8942e2181 [file] [log] [blame]
Stefan Krahee3bac42020-02-24 11:15:26 +01001/*
2 * Memoryview object implementation
3 * --------------------------------
4 *
5 * This implementation is a complete rewrite contributed by Stefan Krah in
6 * Python 3.3. Substantial credit goes to Antoine Pitrou (who had already
7 * fortified and rewritten the previous implementation) and Nick Coghlan
8 * (who came up with the idea of the ManagedBuffer) for analyzing the complex
9 * ownership rules.
10 *
11 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000012
13#include "Python.h"
Victor 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
Victor Stinner47ee8a62020-01-27 22:37:44 +01001061 PyErr_SetString(PyExc_SystemError,
1062 "_memory_release(): negative export count");
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001063 return -1;
1064}
1065
1066static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001067memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001068{
1069 if (_memory_release(self) < 0)
1070 return NULL;
1071 Py_RETURN_NONE;
1072}
1073
1074static void
1075memory_dealloc(PyMemoryViewObject *self)
1076{
1077 assert(self->exports == 0);
1078 _PyObject_GC_UNTRACK(self);
1079 (void)_memory_release(self);
1080 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001081 if (self->weakreflist != NULL)
1082 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001083 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001084}
1085
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001086static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001087memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001088{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001089 Py_VISIT(self->mbuf);
1090 return 0;
1091}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001092
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001093static int
1094memory_clear(PyMemoryViewObject *self)
1095{
1096 (void)_memory_release(self);
1097 Py_CLEAR(self->mbuf);
1098 return 0;
1099}
1100
1101static PyObject *
1102memory_enter(PyObject *self, PyObject *args)
1103{
1104 CHECK_RELEASED(self);
1105 Py_INCREF(self);
1106 return self;
1107}
1108
1109static PyObject *
1110memory_exit(PyObject *self, PyObject *args)
1111{
Stefan Krahe4c07992012-07-28 14:10:02 +02001112 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001113}
1114
1115
1116/****************************************************************************/
1117/* Casting format and shape */
1118/****************************************************************************/
1119
1120#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1121
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001122static inline Py_ssize_t
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001123get_native_fmtchar(char *result, const char *fmt)
1124{
1125 Py_ssize_t size = -1;
1126
1127 if (fmt[0] == '@') fmt++;
1128
1129 switch (fmt[0]) {
1130 case 'c': case 'b': case 'B': size = sizeof(char); break;
1131 case 'h': case 'H': size = sizeof(short); break;
1132 case 'i': case 'I': size = sizeof(int); break;
1133 case 'l': case 'L': size = sizeof(long); break;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001134 case 'q': case 'Q': size = sizeof(long long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001135 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1136 case 'f': size = sizeof(float); break;
1137 case 'd': size = sizeof(double); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001138 case '?': size = sizeof(_Bool); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001139 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001140 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001141
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001142 if (size > 0 && fmt[1] == '\0') {
1143 *result = fmt[0];
1144 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001145 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001146
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001147 return -1;
1148}
1149
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001150static inline const char *
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001151get_native_fmtstr(const char *fmt)
1152{
1153 int at = 0;
1154
1155 if (fmt[0] == '@') {
1156 at = 1;
1157 fmt++;
1158 }
1159 if (fmt[0] == '\0' || fmt[1] != '\0') {
1160 return NULL;
1161 }
1162
1163#define RETURN(s) do { return at ? "@" s : s; } while (0)
1164
1165 switch (fmt[0]) {
1166 case 'c': RETURN("c");
1167 case 'b': RETURN("b");
1168 case 'B': RETURN("B");
1169 case 'h': RETURN("h");
1170 case 'H': RETURN("H");
1171 case 'i': RETURN("i");
1172 case 'I': RETURN("I");
1173 case 'l': RETURN("l");
1174 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001175 case 'q': RETURN("q");
1176 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001177 case 'n': RETURN("n");
1178 case 'N': RETURN("N");
1179 case 'f': RETURN("f");
1180 case 'd': RETURN("d");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001181 case '?': RETURN("?");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001182 case 'P': RETURN("P");
1183 }
1184
1185 return NULL;
1186}
1187
1188
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001189/* Cast a memoryview's data type to 'format'. The input array must be
1190 C-contiguous. At least one of input-format, output-format must have
1191 byte size. The output array is 1-D, with the same byte length as the
1192 input array. Thus, view->len must be a multiple of the new itemsize. */
1193static int
1194cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1195{
1196 Py_buffer *view = &mv->view;
1197 PyObject *asciifmt;
1198 char srcchar, destchar;
1199 Py_ssize_t itemsize;
1200 int ret = -1;
1201
1202 assert(view->ndim >= 1);
1203 assert(Py_SIZE(mv) == 3*view->ndim);
1204 assert(view->shape == mv->ob_array);
1205 assert(view->strides == mv->ob_array + view->ndim);
1206 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1207
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001208 asciifmt = PyUnicode_AsASCIIString(format);
1209 if (asciifmt == NULL)
1210 return ret;
1211
1212 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1213 if (itemsize < 0) {
1214 PyErr_SetString(PyExc_ValueError,
1215 "memoryview: destination format must be a native single "
1216 "character format prefixed with an optional '@'");
1217 goto out;
1218 }
1219
Stefan Krah0c515952015-08-08 13:38:10 +02001220 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1221 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001222 PyErr_SetString(PyExc_TypeError,
1223 "memoryview: cannot cast between two non-byte formats");
1224 goto out;
1225 }
1226 if (view->len % itemsize) {
1227 PyErr_SetString(PyExc_TypeError,
1228 "memoryview: length is not a multiple of itemsize");
1229 goto out;
1230 }
1231
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001232 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001233 if (view->format == NULL) {
1234 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1235 PyErr_SetString(PyExc_RuntimeError,
1236 "memoryview: internal error");
1237 goto out;
1238 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001239 view->itemsize = itemsize;
1240
1241 view->ndim = 1;
1242 view->shape[0] = view->len / view->itemsize;
1243 view->strides[0] = view->itemsize;
1244 view->suboffsets = NULL;
1245
1246 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001247
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001248 ret = 0;
1249
1250out:
1251 Py_DECREF(asciifmt);
1252 return ret;
1253}
1254
1255/* The memoryview must have space for 3*len(seq) elements. */
1256static Py_ssize_t
1257copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1258 Py_ssize_t itemsize)
1259{
1260 Py_ssize_t x, i;
1261 Py_ssize_t len = itemsize;
1262
1263 for (i = 0; i < ndim; i++) {
1264 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1265 if (!PyLong_Check(tmp)) {
1266 PyErr_SetString(PyExc_TypeError,
1267 "memoryview.cast(): elements of shape must be integers");
1268 return -1;
1269 }
1270 x = PyLong_AsSsize_t(tmp);
1271 if (x == -1 && PyErr_Occurred()) {
1272 return -1;
1273 }
1274 if (x <= 0) {
1275 /* In general elements of shape may be 0, but not for casting. */
1276 PyErr_Format(PyExc_ValueError,
1277 "memoryview.cast(): elements of shape must be integers > 0");
1278 return -1;
1279 }
1280 if (x > PY_SSIZE_T_MAX / len) {
1281 PyErr_Format(PyExc_ValueError,
1282 "memoryview.cast(): product(shape) > SSIZE_MAX");
1283 return -1;
1284 }
1285 len *= x;
1286 shape[i] = x;
1287 }
1288
1289 return len;
1290}
1291
1292/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1293 If the result array does not have exactly the same byte length as the
1294 input array, raise ValueError. */
1295static int
1296cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1297{
1298 Py_buffer *view = &mv->view;
1299 Py_ssize_t len;
1300
1301 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1302 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1303 assert(view->shape == mv->ob_array);
1304 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1305 assert(view->suboffsets == NULL);
1306
1307 view->ndim = ndim;
1308 if (view->ndim == 0) {
1309 view->shape = NULL;
1310 view->strides = NULL;
1311 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001312 }
1313 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001314 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1315 if (len < 0)
1316 return -1;
1317 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001318 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001319
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001320 if (view->len != len) {
1321 PyErr_SetString(PyExc_TypeError,
1322 "memoryview: product(shape) * itemsize != buffer size");
1323 return -1;
1324 }
1325
1326 init_flags(mv);
1327
1328 return 0;
1329}
1330
1331static int
1332zero_in_shape(PyMemoryViewObject *mv)
1333{
1334 Py_buffer *view = &mv->view;
1335 Py_ssize_t i;
1336
1337 for (i = 0; i < view->ndim; i++)
1338 if (view->shape[i] == 0)
1339 return 1;
1340
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001341 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001342}
1343
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001344/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001345 Cast a copy of 'self' to a different view. The input view must
1346 be C-contiguous. The function always casts the input view to a
1347 1-D output according to 'format'. At least one of input-format,
1348 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001349
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001350 If 'shape' is given, the 1-D view from the previous step will
1351 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001352
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001353 All casts must result in views that will have the exact byte
1354 size of the original input. Otherwise, an error is raised.
1355*/
1356static PyObject *
1357memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001358{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001359 static char *kwlist[] = {"format", "shape", NULL};
1360 PyMemoryViewObject *mv = NULL;
1361 PyObject *shape = NULL;
1362 PyObject *format;
1363 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001364
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001365 CHECK_RELEASED(self);
1366
1367 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1368 &format, &shape)) {
1369 return NULL;
1370 }
1371 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001372 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001373 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001374 return NULL;
1375 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001376 if (!MV_C_CONTIGUOUS(self->flags)) {
1377 PyErr_SetString(PyExc_TypeError,
1378 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001379 return NULL;
1380 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001381 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001382 PyErr_SetString(PyExc_TypeError,
1383 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001384 return NULL;
1385 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001386 if (shape) {
1387 CHECK_LIST_OR_TUPLE(shape)
1388 ndim = PySequence_Fast_GET_SIZE(shape);
1389 if (ndim > PyBUF_MAX_NDIM) {
1390 PyErr_SetString(PyExc_ValueError,
1391 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001392 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001393 return NULL;
1394 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001395 if (self->view.ndim != 1 && ndim != 1) {
1396 PyErr_SetString(PyExc_TypeError,
1397 "memoryview: cast must be 1D -> ND or ND -> 1D");
1398 return NULL;
1399 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001400 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001401
1402 mv = (PyMemoryViewObject *)
1403 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1404 if (mv == NULL)
1405 return NULL;
1406
1407 if (cast_to_1D(mv, format) < 0)
1408 goto error;
1409 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1410 goto error;
1411
1412 return (PyObject *)mv;
1413
1414error:
1415 Py_DECREF(mv);
1416 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001417}
1418
Antoine Pitrou480ab052018-04-14 19:49:21 +02001419static PyObject *
1420memory_toreadonly(PyMemoryViewObject *self, PyObject *noargs)
1421{
1422 CHECK_RELEASED(self);
1423 /* Even if self is already readonly, we still need to create a new
1424 * object for .release() to work correctly.
1425 */
1426 self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1427 if (self != NULL) {
1428 self->view.readonly = 1;
1429 };
1430 return (PyObject *) self;
1431}
1432
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001433
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001434/**************************************************************************/
1435/* getbuffer */
1436/**************************************************************************/
1437
1438static int
1439memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1440{
1441 Py_buffer *base = &self->view;
1442 int baseflags = self->flags;
1443
1444 CHECK_RELEASED_INT(self);
1445
1446 /* start with complete information */
1447 *view = *base;
1448 view->obj = NULL;
1449
1450 if (REQ_WRITABLE(flags) && base->readonly) {
1451 PyErr_SetString(PyExc_BufferError,
1452 "memoryview: underlying buffer is not writable");
1453 return -1;
1454 }
1455 if (!REQ_FORMAT(flags)) {
1456 /* NULL indicates that the buffer's data type has been cast to 'B'.
1457 view->itemsize is the _previous_ itemsize. If shape is present,
1458 the equality product(shape) * itemsize = len still holds at this
1459 point. The equality calcsize(format) = itemsize does _not_ hold
1460 from here on! */
1461 view->format = NULL;
1462 }
1463
1464 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1465 PyErr_SetString(PyExc_BufferError,
1466 "memoryview: underlying buffer is not C-contiguous");
1467 return -1;
1468 }
1469 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1470 PyErr_SetString(PyExc_BufferError,
1471 "memoryview: underlying buffer is not Fortran contiguous");
1472 return -1;
1473 }
1474 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1475 PyErr_SetString(PyExc_BufferError,
1476 "memoryview: underlying buffer is not contiguous");
1477 return -1;
1478 }
1479 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1480 PyErr_SetString(PyExc_BufferError,
1481 "memoryview: underlying buffer requires suboffsets");
1482 return -1;
1483 }
1484 if (!REQ_STRIDES(flags)) {
1485 if (!MV_C_CONTIGUOUS(baseflags)) {
1486 PyErr_SetString(PyExc_BufferError,
1487 "memoryview: underlying buffer is not C-contiguous");
1488 return -1;
1489 }
1490 view->strides = NULL;
1491 }
1492 if (!REQ_SHAPE(flags)) {
1493 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1494 so base->buf = ndbuf->data. */
1495 if (view->format != NULL) {
1496 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1497 not make sense. */
1498 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001499 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001500 "is present");
1501 return -1;
1502 }
1503 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1504 do _not_ hold from here on! */
1505 view->ndim = 1;
1506 view->shape = NULL;
1507 }
1508
1509
1510 view->obj = (PyObject *)self;
1511 Py_INCREF(view->obj);
1512 self->exports++;
1513
1514 return 0;
1515}
1516
1517static void
1518memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1519{
1520 self->exports--;
1521 return;
1522 /* PyBuffer_Release() decrements view->obj after this function returns. */
1523}
1524
1525/* Buffer methods */
1526static PyBufferProcs memory_as_buffer = {
1527 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1528 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1529};
1530
1531
1532/****************************************************************************/
1533/* Optimized pack/unpack for all native format specifiers */
1534/****************************************************************************/
1535
1536/*
1537 Fix exceptions:
1538 1) Include format string in the error message.
1539 2) OverflowError -> ValueError.
1540 3) The error message from PyNumber_Index() is not ideal.
1541*/
1542static int
1543type_error_int(const char *fmt)
1544{
1545 PyErr_Format(PyExc_TypeError,
1546 "memoryview: invalid type for format '%s'", fmt);
1547 return -1;
1548}
1549
1550static int
1551value_error_int(const char *fmt)
1552{
1553 PyErr_Format(PyExc_ValueError,
1554 "memoryview: invalid value for format '%s'", fmt);
1555 return -1;
1556}
1557
1558static int
1559fix_error_int(const char *fmt)
1560{
1561 assert(PyErr_Occurred());
1562 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1563 PyErr_Clear();
1564 return type_error_int(fmt);
1565 }
1566 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1567 PyErr_ExceptionMatches(PyExc_ValueError)) {
1568 PyErr_Clear();
1569 return value_error_int(fmt);
1570 }
1571
1572 return -1;
1573}
1574
1575/* Accept integer objects or objects with an __index__() method. */
1576static long
1577pylong_as_ld(PyObject *item)
1578{
1579 PyObject *tmp;
1580 long ld;
1581
1582 tmp = PyNumber_Index(item);
1583 if (tmp == NULL)
1584 return -1;
1585
1586 ld = PyLong_AsLong(tmp);
1587 Py_DECREF(tmp);
1588 return ld;
1589}
1590
1591static unsigned long
1592pylong_as_lu(PyObject *item)
1593{
1594 PyObject *tmp;
1595 unsigned long lu;
1596
1597 tmp = PyNumber_Index(item);
1598 if (tmp == NULL)
1599 return (unsigned long)-1;
1600
1601 lu = PyLong_AsUnsignedLong(tmp);
1602 Py_DECREF(tmp);
1603 return lu;
1604}
1605
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001606static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001607pylong_as_lld(PyObject *item)
1608{
1609 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001610 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001611
1612 tmp = PyNumber_Index(item);
1613 if (tmp == NULL)
1614 return -1;
1615
1616 lld = PyLong_AsLongLong(tmp);
1617 Py_DECREF(tmp);
1618 return lld;
1619}
1620
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001621static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001622pylong_as_llu(PyObject *item)
1623{
1624 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001625 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001626
1627 tmp = PyNumber_Index(item);
1628 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001629 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001630
1631 llu = PyLong_AsUnsignedLongLong(tmp);
1632 Py_DECREF(tmp);
1633 return llu;
1634}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001635
1636static Py_ssize_t
1637pylong_as_zd(PyObject *item)
1638{
1639 PyObject *tmp;
1640 Py_ssize_t zd;
1641
1642 tmp = PyNumber_Index(item);
1643 if (tmp == NULL)
1644 return -1;
1645
1646 zd = PyLong_AsSsize_t(tmp);
1647 Py_DECREF(tmp);
1648 return zd;
1649}
1650
1651static size_t
1652pylong_as_zu(PyObject *item)
1653{
1654 PyObject *tmp;
1655 size_t zu;
1656
1657 tmp = PyNumber_Index(item);
1658 if (tmp == NULL)
1659 return (size_t)-1;
1660
1661 zu = PyLong_AsSize_t(tmp);
1662 Py_DECREF(tmp);
1663 return zu;
1664}
1665
1666/* Timings with the ndarray from _testbuffer.c indicate that using the
1667 struct module is around 15x slower than the two functions below. */
1668
1669#define UNPACK_SINGLE(dest, ptr, type) \
1670 do { \
1671 type x; \
1672 memcpy((char *)&x, ptr, sizeof x); \
1673 dest = x; \
1674 } while (0)
1675
1676/* Unpack a single item. 'fmt' can be any native format character in struct
1677 module syntax. This function is very sensitive to small changes. With this
1678 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001679static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001680unpack_single(const char *ptr, const char *fmt)
1681{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001682 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001683 unsigned long lu;
1684 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001685 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001686 long ld;
1687 Py_ssize_t zd;
1688 double d;
1689 unsigned char uc;
1690 void *p;
1691
1692 switch (fmt[0]) {
1693
1694 /* signed integers and fast path for 'B' */
Andy Lestere6be9b52020-02-11 20:28:35 -06001695 case 'B': uc = *((const unsigned char *)ptr); goto convert_uc;
1696 case 'b': ld = *((const signed char *)ptr); goto convert_ld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001697 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1698 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1699 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1700
1701 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001702 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001703
1704 /* unsigned integers */
1705 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1706 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1707 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1708
1709 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001710 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1711 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001712
1713 /* ssize_t and size_t */
1714 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1715 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1716
1717 /* floats */
1718 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1719 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1720
1721 /* bytes object */
1722 case 'c': goto convert_bytes;
1723
1724 /* pointer */
1725 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1726
1727 /* default */
1728 default: goto err_format;
1729 }
1730
1731convert_uc:
1732 /* PyLong_FromUnsignedLong() is slower */
1733 return PyLong_FromLong(uc);
1734convert_ld:
1735 return PyLong_FromLong(ld);
1736convert_lu:
1737 return PyLong_FromUnsignedLong(lu);
1738convert_lld:
1739 return PyLong_FromLongLong(lld);
1740convert_llu:
1741 return PyLong_FromUnsignedLongLong(llu);
1742convert_zd:
1743 return PyLong_FromSsize_t(zd);
1744convert_zu:
1745 return PyLong_FromSize_t(zu);
1746convert_double:
1747 return PyFloat_FromDouble(d);
1748convert_bool:
1749 return PyBool_FromLong(ld);
1750convert_bytes:
1751 return PyBytes_FromStringAndSize(ptr, 1);
1752convert_pointer:
1753 return PyLong_FromVoidPtr(p);
1754err_format:
1755 PyErr_Format(PyExc_NotImplementedError,
1756 "memoryview: format %s not supported", fmt);
1757 return NULL;
1758}
1759
1760#define PACK_SINGLE(ptr, src, type) \
1761 do { \
1762 type x; \
1763 x = (type)src; \
1764 memcpy(ptr, (char *)&x, sizeof x); \
1765 } while (0)
1766
1767/* Pack a single item. 'fmt' can be any native format character in
1768 struct module syntax. */
1769static int
1770pack_single(char *ptr, PyObject *item, const char *fmt)
1771{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001772 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001773 unsigned long lu;
1774 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001775 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001776 long ld;
1777 Py_ssize_t zd;
1778 double d;
1779 void *p;
1780
1781 switch (fmt[0]) {
1782 /* signed integers */
1783 case 'b': case 'h': case 'i': case 'l':
1784 ld = pylong_as_ld(item);
1785 if (ld == -1 && PyErr_Occurred())
1786 goto err_occurred;
1787 switch (fmt[0]) {
1788 case 'b':
1789 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1790 *((signed char *)ptr) = (signed char)ld; break;
1791 case 'h':
1792 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1793 PACK_SINGLE(ptr, ld, short); break;
1794 case 'i':
1795 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1796 PACK_SINGLE(ptr, ld, int); break;
1797 default: /* 'l' */
1798 PACK_SINGLE(ptr, ld, long); break;
1799 }
1800 break;
1801
1802 /* unsigned integers */
1803 case 'B': case 'H': case 'I': case 'L':
1804 lu = pylong_as_lu(item);
1805 if (lu == (unsigned long)-1 && PyErr_Occurred())
1806 goto err_occurred;
1807 switch (fmt[0]) {
1808 case 'B':
1809 if (lu > UCHAR_MAX) goto err_range;
1810 *((unsigned char *)ptr) = (unsigned char)lu; break;
1811 case 'H':
1812 if (lu > USHRT_MAX) goto err_range;
1813 PACK_SINGLE(ptr, lu, unsigned short); break;
1814 case 'I':
1815 if (lu > UINT_MAX) goto err_range;
1816 PACK_SINGLE(ptr, lu, unsigned int); break;
1817 default: /* 'L' */
1818 PACK_SINGLE(ptr, lu, unsigned long); break;
1819 }
1820 break;
1821
1822 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001823 case 'q':
1824 lld = pylong_as_lld(item);
1825 if (lld == -1 && PyErr_Occurred())
1826 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001827 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001828 break;
1829 case 'Q':
1830 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001831 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001832 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001833 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001834 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001835
1836 /* ssize_t and size_t */
1837 case 'n':
1838 zd = pylong_as_zd(item);
1839 if (zd == -1 && PyErr_Occurred())
1840 goto err_occurred;
1841 PACK_SINGLE(ptr, zd, Py_ssize_t);
1842 break;
1843 case 'N':
1844 zu = pylong_as_zu(item);
1845 if (zu == (size_t)-1 && PyErr_Occurred())
1846 goto err_occurred;
1847 PACK_SINGLE(ptr, zu, size_t);
1848 break;
1849
1850 /* floats */
1851 case 'f': case 'd':
1852 d = PyFloat_AsDouble(item);
1853 if (d == -1.0 && PyErr_Occurred())
1854 goto err_occurred;
1855 if (fmt[0] == 'f') {
1856 PACK_SINGLE(ptr, d, float);
1857 }
1858 else {
1859 PACK_SINGLE(ptr, d, double);
1860 }
1861 break;
1862
1863 /* bool */
1864 case '?':
1865 ld = PyObject_IsTrue(item);
1866 if (ld < 0)
1867 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001868 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001869 break;
1870
1871 /* bytes object */
1872 case 'c':
1873 if (!PyBytes_Check(item))
1874 return type_error_int(fmt);
1875 if (PyBytes_GET_SIZE(item) != 1)
1876 return value_error_int(fmt);
1877 *ptr = PyBytes_AS_STRING(item)[0];
1878 break;
1879
1880 /* pointer */
1881 case 'P':
1882 p = PyLong_AsVoidPtr(item);
1883 if (p == NULL && PyErr_Occurred())
1884 goto err_occurred;
1885 PACK_SINGLE(ptr, p, void *);
1886 break;
1887
1888 /* default */
1889 default: goto err_format;
1890 }
1891
1892 return 0;
1893
1894err_occurred:
1895 return fix_error_int(fmt);
1896err_range:
1897 return value_error_int(fmt);
1898err_format:
1899 PyErr_Format(PyExc_NotImplementedError,
1900 "memoryview: format %s not supported", fmt);
1901 return -1;
1902}
1903
1904
1905/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001906/* unpack using the struct module */
1907/****************************************************************************/
1908
1909/* For reasonable performance it is necessary to cache all objects required
1910 for unpacking. An unpacker can handle the format passed to unpack_from().
1911 Invariant: All pointer fields of the struct should either be NULL or valid
1912 pointers. */
1913struct unpacker {
1914 PyObject *unpack_from; /* Struct.unpack_from(format) */
1915 PyObject *mview; /* cached memoryview */
1916 char *item; /* buffer for mview */
1917 Py_ssize_t itemsize; /* len(item) */
1918};
1919
1920static struct unpacker *
1921unpacker_new(void)
1922{
1923 struct unpacker *x = PyMem_Malloc(sizeof *x);
1924
1925 if (x == NULL) {
1926 PyErr_NoMemory();
1927 return NULL;
1928 }
1929
1930 x->unpack_from = NULL;
1931 x->mview = NULL;
1932 x->item = NULL;
1933 x->itemsize = 0;
1934
1935 return x;
1936}
1937
1938static void
1939unpacker_free(struct unpacker *x)
1940{
1941 if (x) {
1942 Py_XDECREF(x->unpack_from);
1943 Py_XDECREF(x->mview);
1944 PyMem_Free(x->item);
1945 PyMem_Free(x);
1946 }
1947}
1948
1949/* Return a new unpacker for the given format. */
1950static struct unpacker *
1951struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1952{
1953 PyObject *structmodule; /* XXX cache these two */
1954 PyObject *Struct = NULL; /* XXX in globals? */
1955 PyObject *structobj = NULL;
1956 PyObject *format = NULL;
1957 struct unpacker *x = NULL;
1958
1959 structmodule = PyImport_ImportModule("struct");
1960 if (structmodule == NULL)
1961 return NULL;
1962
1963 Struct = PyObject_GetAttrString(structmodule, "Struct");
1964 Py_DECREF(structmodule);
1965 if (Struct == NULL)
1966 return NULL;
1967
1968 x = unpacker_new();
1969 if (x == NULL)
1970 goto error;
1971
1972 format = PyBytes_FromString(fmt);
1973 if (format == NULL)
1974 goto error;
1975
Petr Viktorinffd97532020-02-11 17:46:57 +01001976 structobj = PyObject_CallOneArg(Struct, format);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001977 if (structobj == NULL)
1978 goto error;
1979
1980 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1981 if (x->unpack_from == NULL)
1982 goto error;
1983
1984 x->item = PyMem_Malloc(itemsize);
1985 if (x->item == NULL) {
1986 PyErr_NoMemory();
1987 goto error;
1988 }
1989 x->itemsize = itemsize;
1990
1991 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1992 if (x->mview == NULL)
1993 goto error;
1994
1995
1996out:
1997 Py_XDECREF(Struct);
1998 Py_XDECREF(format);
1999 Py_XDECREF(structobj);
2000 return x;
2001
2002error:
2003 unpacker_free(x);
2004 x = NULL;
2005 goto out;
2006}
2007
2008/* unpack a single item */
2009static PyObject *
2010struct_unpack_single(const char *ptr, struct unpacker *x)
2011{
2012 PyObject *v;
2013
2014 memcpy(x->item, ptr, x->itemsize);
Petr Viktorinffd97532020-02-11 17:46:57 +01002015 v = PyObject_CallOneArg(x->unpack_from, x->mview);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002016 if (v == NULL)
2017 return NULL;
2018
2019 if (PyTuple_GET_SIZE(v) == 1) {
2020 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2021 Py_INCREF(tmp);
2022 Py_DECREF(v);
2023 return tmp;
2024 }
2025
2026 return v;
2027}
2028
2029
2030/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002031/* Representations */
2032/****************************************************************************/
2033
2034/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002035static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002036adjust_fmt(const Py_buffer *view)
2037{
2038 const char *fmt;
2039
2040 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2041 if (fmt[0] && fmt[1] == '\0')
2042 return fmt;
2043
2044 PyErr_Format(PyExc_NotImplementedError,
2045 "memoryview: unsupported format %s", view->format);
2046 return NULL;
2047}
2048
2049/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2050static PyObject *
2051tolist_base(const char *ptr, const Py_ssize_t *shape,
2052 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2053 const char *fmt)
2054{
2055 PyObject *lst, *item;
2056 Py_ssize_t i;
2057
2058 lst = PyList_New(shape[0]);
2059 if (lst == NULL)
2060 return NULL;
2061
2062 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002063 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002064 item = unpack_single(xptr, fmt);
2065 if (item == NULL) {
2066 Py_DECREF(lst);
2067 return NULL;
2068 }
2069 PyList_SET_ITEM(lst, i, item);
2070 }
2071
2072 return lst;
2073}
2074
2075/* Unpack a multi-dimensional array into a nested list.
2076 Assumption: ndim >= 1. */
2077static PyObject *
2078tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2079 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2080 const char *fmt)
2081{
2082 PyObject *lst, *item;
2083 Py_ssize_t i;
2084
2085 assert(ndim >= 1);
2086 assert(shape != NULL);
2087 assert(strides != NULL);
2088
2089 if (ndim == 1)
2090 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2091
2092 lst = PyList_New(shape[0]);
2093 if (lst == NULL)
2094 return NULL;
2095
2096 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002097 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002098 item = tolist_rec(xptr, ndim-1, shape+1,
2099 strides+1, suboffsets ? suboffsets+1 : NULL,
2100 fmt);
2101 if (item == NULL) {
2102 Py_DECREF(lst);
2103 return NULL;
2104 }
2105 PyList_SET_ITEM(lst, i, item);
2106 }
2107
2108 return lst;
2109}
2110
2111/* Return a list representation of the memoryview. Currently only buffers
2112 with native format strings are supported. */
2113static PyObject *
2114memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2115{
2116 const Py_buffer *view = &(mv->view);
2117 const char *fmt;
2118
2119 CHECK_RELEASED(mv);
2120
2121 fmt = adjust_fmt(view);
2122 if (fmt == NULL)
2123 return NULL;
2124 if (view->ndim == 0) {
2125 return unpack_single(view->buf, fmt);
2126 }
2127 else if (view->ndim == 1) {
2128 return tolist_base(view->buf, view->shape,
2129 view->strides, view->suboffsets,
2130 fmt);
2131 }
2132 else {
2133 return tolist_rec(view->buf, view->ndim, view->shape,
2134 view->strides, view->suboffsets,
2135 fmt);
2136 }
2137}
2138
2139static PyObject *
Stefan Krahd08ea702019-02-02 18:57:41 +01002140memory_tobytes(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002141{
Stefan Krahd08ea702019-02-02 18:57:41 +01002142 static char *kwlist[] = {"order", NULL};
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002143 Py_buffer *src = VIEW_ADDR(self);
Stefan Krahd08ea702019-02-02 18:57:41 +01002144 char *order = NULL;
2145 char ord = 'C';
2146 PyObject *bytes;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002147
2148 CHECK_RELEASED(self);
2149
Stefan Krahd08ea702019-02-02 18:57:41 +01002150 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z", kwlist, &order)) {
2151 return NULL;
2152 }
2153
2154 if (order) {
2155 if (strcmp(order, "F") == 0) {
2156 ord = 'F';
2157 }
2158 else if (strcmp(order, "A") == 0) {
2159 ord = 'A';
2160 }
2161 else if (strcmp(order, "C") != 0) {
2162 PyErr_SetString(PyExc_ValueError,
2163 "order must be 'C', 'F' or 'A'");
2164 return NULL;
2165 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002166 }
2167
2168 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2169 if (bytes == NULL)
2170 return NULL;
2171
Stefan Krahd08ea702019-02-02 18:57:41 +01002172 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, ord) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002173 Py_DECREF(bytes);
2174 return NULL;
2175 }
2176
2177 return bytes;
2178}
2179
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002180/*[clinic input]
2181memoryview.hex
2182
2183 sep: object = NULL
2184 An optional single character or byte to separate hex bytes.
2185 bytes_per_sep: int = 1
2186 How many bytes between separators. Positive values count from the
2187 right, negative values count from the left.
2188
2189Return the data in the buffer as a str of hexadecimal numbers.
2190
2191Example:
2192>>> value = memoryview(b'\xb9\x01\xef')
2193>>> value.hex()
2194'b901ef'
2195>>> value.hex(':')
2196'b9:01:ef'
2197>>> value.hex(':', 2)
2198'b9:01ef'
2199>>> value.hex(':', -2)
2200'b901:ef'
2201[clinic start generated code]*/
2202
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002203static PyObject *
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002204memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
2205 int bytes_per_sep)
2206/*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002207{
2208 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002209 PyObject *bytes;
2210 PyObject *ret;
2211
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002212 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002213
2214 if (MV_C_CONTIGUOUS(self->flags)) {
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002215 return _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002216 }
2217
Stefan Krahd08ea702019-02-02 18:57:41 +01002218 bytes = PyBytes_FromStringAndSize(NULL, src->len);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002219 if (bytes == NULL)
2220 return NULL;
2221
Stefan Krahd08ea702019-02-02 18:57:41 +01002222 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, 'C') < 0) {
2223 Py_DECREF(bytes);
2224 return NULL;
2225 }
2226
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002227 ret = _Py_strhex_with_sep(
2228 PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes),
2229 sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002230 Py_DECREF(bytes);
2231
2232 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002233}
2234
2235static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002236memory_repr(PyMemoryViewObject *self)
2237{
2238 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2239 return PyUnicode_FromFormat("<released memory at %p>", self);
2240 else
2241 return PyUnicode_FromFormat("<memory at %p>", self);
2242}
2243
2244
2245/**************************************************************************/
2246/* Indexing and slicing */
2247/**************************************************************************/
2248
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002249static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002250lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002251{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002252 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002253
2254 assert(view->shape);
2255 assert(view->strides);
2256
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002257 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002258 if (index < 0) {
2259 index += nitems;
2260 }
2261 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002262 PyErr_Format(PyExc_IndexError,
2263 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002264 return NULL;
2265 }
2266
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002267 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002268
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002269 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002270
2271 return ptr;
2272}
2273
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002274/* Get the pointer to the item at index. */
2275static char *
2276ptr_from_index(Py_buffer *view, Py_ssize_t index)
2277{
2278 char *ptr = (char *)view->buf;
2279 return lookup_dimension(view, ptr, 0, index);
2280}
2281
2282/* Get the pointer to the item at tuple. */
2283static char *
2284ptr_from_tuple(Py_buffer *view, PyObject *tup)
2285{
2286 char *ptr = (char *)view->buf;
2287 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2288
2289 if (nindices > view->ndim) {
2290 PyErr_Format(PyExc_TypeError,
2291 "cannot index %zd-dimension view with %zd-element tuple",
2292 view->ndim, nindices);
2293 return NULL;
2294 }
2295
2296 for (dim = 0; dim < nindices; dim++) {
2297 Py_ssize_t index;
2298 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2299 PyExc_IndexError);
2300 if (index == -1 && PyErr_Occurred())
2301 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002302 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002303 if (ptr == NULL)
2304 return NULL;
2305 }
2306 return ptr;
2307}
2308
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002309/* Return the item at index. In a one-dimensional view, this is an object
2310 with the type specified by view->format. Otherwise, the item is a sub-view.
2311 The function is used in memory_subscript() and memory_as_sequence. */
2312static PyObject *
2313memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2314{
2315 Py_buffer *view = &(self->view);
2316 const char *fmt;
2317
2318 CHECK_RELEASED(self);
2319
2320 fmt = adjust_fmt(view);
2321 if (fmt == NULL)
2322 return NULL;
2323
2324 if (view->ndim == 0) {
2325 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2326 return NULL;
2327 }
2328 if (view->ndim == 1) {
2329 char *ptr = ptr_from_index(view, index);
2330 if (ptr == NULL)
2331 return NULL;
2332 return unpack_single(ptr, fmt);
2333 }
2334
2335 PyErr_SetString(PyExc_NotImplementedError,
2336 "multi-dimensional sub-views are not implemented");
2337 return NULL;
2338}
2339
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002340/* Return the item at position *key* (a tuple of indices). */
2341static PyObject *
2342memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2343{
2344 Py_buffer *view = &(self->view);
2345 const char *fmt;
2346 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2347 char *ptr;
2348
2349 CHECK_RELEASED(self);
2350
2351 fmt = adjust_fmt(view);
2352 if (fmt == NULL)
2353 return NULL;
2354
2355 if (nindices < view->ndim) {
2356 PyErr_SetString(PyExc_NotImplementedError,
2357 "sub-views are not implemented");
2358 return NULL;
2359 }
2360 ptr = ptr_from_tuple(view, tup);
2361 if (ptr == NULL)
2362 return NULL;
2363 return unpack_single(ptr, fmt);
2364}
2365
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002366static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002367init_slice(Py_buffer *base, PyObject *key, int dim)
2368{
2369 Py_ssize_t start, stop, step, slicelength;
2370
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002371 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002372 return -1;
2373 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002374 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002375
2376
2377 if (base->suboffsets == NULL || dim == 0) {
2378 adjust_buf:
2379 base->buf = (char *)base->buf + base->strides[dim] * start;
2380 }
2381 else {
2382 Py_ssize_t n = dim-1;
2383 while (n >= 0 && base->suboffsets[n] < 0)
2384 n--;
2385 if (n < 0)
2386 goto adjust_buf; /* all suboffsets are negative */
2387 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2388 }
2389 base->shape[dim] = slicelength;
2390 base->strides[dim] = base->strides[dim] * step;
2391
2392 return 0;
2393}
2394
2395static int
2396is_multislice(PyObject *key)
2397{
2398 Py_ssize_t size, i;
2399
2400 if (!PyTuple_Check(key))
2401 return 0;
2402 size = PyTuple_GET_SIZE(key);
2403 if (size == 0)
2404 return 0;
2405
2406 for (i = 0; i < size; i++) {
2407 PyObject *x = PyTuple_GET_ITEM(key, i);
2408 if (!PySlice_Check(x))
2409 return 0;
2410 }
2411 return 1;
2412}
2413
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002414static Py_ssize_t
2415is_multiindex(PyObject *key)
2416{
2417 Py_ssize_t size, i;
2418
2419 if (!PyTuple_Check(key))
2420 return 0;
2421 size = PyTuple_GET_SIZE(key);
2422 for (i = 0; i < size; i++) {
2423 PyObject *x = PyTuple_GET_ITEM(key, i);
2424 if (!PyIndex_Check(x))
2425 return 0;
2426 }
2427 return 1;
2428}
2429
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002430/* mv[obj] returns an object holding the data for one element if obj
2431 fully indexes the memoryview or another memoryview object if it
2432 does not.
2433
2434 0-d memoryview objects can be referenced using mv[...] or mv[()]
2435 but not with anything else. */
2436static PyObject *
2437memory_subscript(PyMemoryViewObject *self, PyObject *key)
2438{
2439 Py_buffer *view;
2440 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002441
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002442 CHECK_RELEASED(self);
2443
2444 if (view->ndim == 0) {
2445 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2446 const char *fmt = adjust_fmt(view);
2447 if (fmt == NULL)
2448 return NULL;
2449 return unpack_single(view->buf, fmt);
2450 }
2451 else if (key == Py_Ellipsis) {
2452 Py_INCREF(self);
2453 return (PyObject *)self;
2454 }
2455 else {
2456 PyErr_SetString(PyExc_TypeError,
2457 "invalid indexing of 0-dim memory");
2458 return NULL;
2459 }
2460 }
2461
2462 if (PyIndex_Check(key)) {
2463 Py_ssize_t index;
2464 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2465 if (index == -1 && PyErr_Occurred())
2466 return NULL;
2467 return memory_item(self, index);
2468 }
2469 else if (PySlice_Check(key)) {
2470 PyMemoryViewObject *sliced;
2471
2472 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2473 if (sliced == NULL)
2474 return NULL;
2475
2476 if (init_slice(&sliced->view, key, 0) < 0) {
2477 Py_DECREF(sliced);
2478 return NULL;
2479 }
2480 init_len(&sliced->view);
2481 init_flags(sliced);
2482
2483 return (PyObject *)sliced;
2484 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002485 else if (is_multiindex(key)) {
2486 return memory_item_multi(self, key);
2487 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002488 else if (is_multislice(key)) {
2489 PyErr_SetString(PyExc_NotImplementedError,
2490 "multi-dimensional slicing is not implemented");
2491 return NULL;
2492 }
2493
2494 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2495 return NULL;
2496}
2497
2498static int
2499memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2500{
2501 Py_buffer *view = &(self->view);
2502 Py_buffer src;
2503 const char *fmt;
2504 char *ptr;
2505
2506 CHECK_RELEASED_INT(self);
2507
2508 fmt = adjust_fmt(view);
2509 if (fmt == NULL)
2510 return -1;
2511
2512 if (view->readonly) {
2513 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2514 return -1;
2515 }
2516 if (value == NULL) {
2517 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2518 return -1;
2519 }
2520 if (view->ndim == 0) {
2521 if (key == Py_Ellipsis ||
2522 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2523 ptr = (char *)view->buf;
2524 return pack_single(ptr, value, fmt);
2525 }
2526 else {
2527 PyErr_SetString(PyExc_TypeError,
2528 "invalid indexing of 0-dim memory");
2529 return -1;
2530 }
2531 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002532
2533 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002534 Py_ssize_t index;
2535 if (1 < view->ndim) {
2536 PyErr_SetString(PyExc_NotImplementedError,
2537 "sub-views are not implemented");
2538 return -1;
2539 }
2540 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002541 if (index == -1 && PyErr_Occurred())
2542 return -1;
2543 ptr = ptr_from_index(view, index);
2544 if (ptr == NULL)
2545 return -1;
2546 return pack_single(ptr, value, fmt);
2547 }
2548 /* one-dimensional: fast path */
2549 if (PySlice_Check(key) && view->ndim == 1) {
2550 Py_buffer dest; /* sliced view */
2551 Py_ssize_t arrays[3];
2552 int ret = -1;
2553
2554 /* rvalue must be an exporter */
2555 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2556 return ret;
2557
2558 dest = *view;
2559 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2560 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2561 if (view->suboffsets) {
2562 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2563 }
2564
2565 if (init_slice(&dest, key, 0) < 0)
2566 goto end_block;
2567 dest.len = dest.shape[0] * dest.itemsize;
2568
2569 ret = copy_single(&dest, &src);
2570
2571 end_block:
2572 PyBuffer_Release(&src);
2573 return ret;
2574 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002575 if (is_multiindex(key)) {
2576 char *ptr;
2577 if (PyTuple_GET_SIZE(key) < view->ndim) {
2578 PyErr_SetString(PyExc_NotImplementedError,
2579 "sub-views are not implemented");
2580 return -1;
2581 }
2582 ptr = ptr_from_tuple(view, key);
2583 if (ptr == NULL)
2584 return -1;
2585 return pack_single(ptr, value, fmt);
2586 }
2587 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002588 /* Call memory_subscript() to produce a sliced lvalue, then copy
2589 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2590 PyErr_SetString(PyExc_NotImplementedError,
2591 "memoryview slice assignments are currently restricted "
2592 "to ndim = 1");
2593 return -1;
2594 }
2595
2596 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2597 return -1;
2598}
2599
2600static Py_ssize_t
2601memory_length(PyMemoryViewObject *self)
2602{
2603 CHECK_RELEASED_INT(self);
2604 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2605}
2606
2607/* As mapping */
2608static PyMappingMethods memory_as_mapping = {
2609 (lenfunc)memory_length, /* mp_length */
2610 (binaryfunc)memory_subscript, /* mp_subscript */
2611 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2612};
2613
2614/* As sequence */
2615static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002616 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002617 0, /* sq_concat */
2618 0, /* sq_repeat */
2619 (ssizeargfunc)memory_item, /* sq_item */
2620};
2621
2622
2623/**************************************************************************/
2624/* Comparisons */
2625/**************************************************************************/
2626
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002627#define MV_COMPARE_EX -1 /* exception */
2628#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2629
2630/* Translate a StructError to "not equal". Preserve other exceptions. */
2631static int
2632fix_struct_error_int(void)
2633{
2634 assert(PyErr_Occurred());
2635 /* XXX Cannot get at StructError directly? */
2636 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2637 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2638 return MV_COMPARE_EX;
2639 }
2640 /* StructError: invalid or unknown format -> not equal */
2641 PyErr_Clear();
2642 return 0;
2643}
2644
2645/* Unpack and compare single items of p and q using the struct module. */
2646static int
2647struct_unpack_cmp(const char *p, const char *q,
2648 struct unpacker *unpack_p, struct unpacker *unpack_q)
2649{
2650 PyObject *v, *w;
2651 int ret;
2652
2653 /* At this point any exception from the struct module should not be
2654 StructError, since both formats have been accepted already. */
2655 v = struct_unpack_single(p, unpack_p);
2656 if (v == NULL)
2657 return MV_COMPARE_EX;
2658
2659 w = struct_unpack_single(q, unpack_q);
2660 if (w == NULL) {
2661 Py_DECREF(v);
2662 return MV_COMPARE_EX;
2663 }
2664
2665 /* MV_COMPARE_EX == -1: exceptions are preserved */
2666 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2667 Py_DECREF(v);
2668 Py_DECREF(w);
2669
2670 return ret;
2671}
2672
2673/* Unpack and compare single items of p and q. If both p and q have the same
2674 single element native format, the comparison uses a fast path (gcc creates
2675 a jump table and converts memcpy into simple assignments on x86/x64).
2676
2677 Otherwise, the comparison is delegated to the struct module, which is
2678 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002679#define CMP_SINGLE(p, q, type) \
2680 do { \
2681 type x; \
2682 type y; \
2683 memcpy((char *)&x, p, sizeof x); \
2684 memcpy((char *)&y, q, sizeof y); \
2685 equal = (x == y); \
2686 } while (0)
2687
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002688static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002689unpack_cmp(const char *p, const char *q, char fmt,
2690 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002691{
2692 int equal;
2693
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002694 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002695
2696 /* signed integers and fast path for 'B' */
Andy Lestere6be9b52020-02-11 20:28:35 -06002697 case 'B': return *((const unsigned char *)p) == *((const unsigned char *)q);
2698 case 'b': return *((const signed char *)p) == *((const signed char *)q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002699 case 'h': CMP_SINGLE(p, q, short); return equal;
2700 case 'i': CMP_SINGLE(p, q, int); return equal;
2701 case 'l': CMP_SINGLE(p, q, long); return equal;
2702
2703 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002704 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002705
2706 /* unsigned integers */
2707 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2708 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2709 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2710
2711 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002712 case 'q': CMP_SINGLE(p, q, long long); return equal;
2713 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002714
2715 /* ssize_t and size_t */
2716 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2717 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2718
2719 /* floats */
2720 /* XXX DBL_EPSILON? */
2721 case 'f': CMP_SINGLE(p, q, float); return equal;
2722 case 'd': CMP_SINGLE(p, q, double); return equal;
2723
2724 /* bytes object */
2725 case 'c': return *p == *q;
2726
2727 /* pointer */
2728 case 'P': CMP_SINGLE(p, q, void *); return equal;
2729
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002730 /* use the struct module */
2731 case '_':
2732 assert(unpack_p);
2733 assert(unpack_q);
2734 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002735 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002736
2737 /* NOT REACHED */
2738 PyErr_SetString(PyExc_RuntimeError,
2739 "memoryview: internal error in richcompare");
2740 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002741}
2742
2743/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2744static int
2745cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2746 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2747 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002748 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002749{
2750 Py_ssize_t i;
2751 int equal;
2752
2753 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002754 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2755 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002756 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002757 if (equal <= 0)
2758 return equal;
2759 }
2760
2761 return 1;
2762}
2763
2764/* Recursively compare two multi-dimensional arrays that have the same
2765 logical structure. Assumption: ndim >= 1. */
2766static int
2767cmp_rec(const char *p, const char *q,
2768 Py_ssize_t ndim, const Py_ssize_t *shape,
2769 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2770 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002771 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002772{
2773 Py_ssize_t i;
2774 int equal;
2775
2776 assert(ndim >= 1);
2777 assert(shape != NULL);
2778 assert(pstrides != NULL);
2779 assert(qstrides != NULL);
2780
2781 if (ndim == 1) {
2782 return cmp_base(p, q, shape,
2783 pstrides, psuboffsets,
2784 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002785 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002786 }
2787
2788 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002789 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2790 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002791 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2792 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2793 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002794 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002795 if (equal <= 0)
2796 return equal;
2797 }
2798
2799 return 1;
2800}
2801
2802static PyObject *
2803memory_richcompare(PyObject *v, PyObject *w, int op)
2804{
2805 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002806 Py_buffer wbuf, *vv;
2807 Py_buffer *ww = NULL;
2808 struct unpacker *unpack_v = NULL;
2809 struct unpacker *unpack_w = NULL;
2810 char vfmt, wfmt;
2811 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002812
2813 if (op != Py_EQ && op != Py_NE)
2814 goto result; /* Py_NotImplemented */
2815
2816 assert(PyMemoryView_Check(v));
2817 if (BASE_INACCESSIBLE(v)) {
2818 equal = (v == w);
2819 goto result;
2820 }
2821 vv = VIEW_ADDR(v);
2822
2823 if (PyMemoryView_Check(w)) {
2824 if (BASE_INACCESSIBLE(w)) {
2825 equal = (v == w);
2826 goto result;
2827 }
2828 ww = VIEW_ADDR(w);
2829 }
2830 else {
2831 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2832 PyErr_Clear();
2833 goto result; /* Py_NotImplemented */
2834 }
2835 ww = &wbuf;
2836 }
2837
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002838 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002839 PyErr_Clear();
2840 equal = 0;
2841 goto result;
2842 }
2843
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002844 /* Use fast unpacking for identical primitive C type formats. */
2845 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2846 vfmt = '_';
2847 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2848 wfmt = '_';
2849 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2850 /* Use struct module unpacking. NOTE: Even for equal format strings,
2851 memcmp() cannot be used for item comparison since it would give
2852 incorrect results in the case of NaNs or uninitialized padding
2853 bytes. */
2854 vfmt = '_';
2855 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2856 if (unpack_v == NULL) {
2857 equal = fix_struct_error_int();
2858 goto result;
2859 }
2860 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2861 if (unpack_w == NULL) {
2862 equal = fix_struct_error_int();
2863 goto result;
2864 }
2865 }
2866
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002867 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002868 equal = unpack_cmp(vv->buf, ww->buf,
2869 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002870 }
2871 else if (vv->ndim == 1) {
2872 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2873 vv->strides, vv->suboffsets,
2874 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002875 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002876 }
2877 else {
2878 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2879 vv->strides, vv->suboffsets,
2880 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002881 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002882 }
2883
2884result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002885 if (equal < 0) {
2886 if (equal == MV_COMPARE_NOT_IMPL)
2887 res = Py_NotImplemented;
2888 else /* exception */
2889 res = NULL;
2890 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002891 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2892 res = Py_True;
2893 else
2894 res = Py_False;
2895
2896 if (ww == &wbuf)
2897 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002898
2899 unpacker_free(unpack_v);
2900 unpacker_free(unpack_w);
2901
2902 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002903 return res;
2904}
2905
2906/**************************************************************************/
2907/* Hash */
2908/**************************************************************************/
2909
2910static Py_hash_t
2911memory_hash(PyMemoryViewObject *self)
2912{
2913 if (self->hash == -1) {
2914 Py_buffer *view = &self->view;
2915 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002916 Py_ssize_t ret;
2917 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002918
2919 CHECK_RELEASED_INT(self);
2920
2921 if (!view->readonly) {
2922 PyErr_SetString(PyExc_ValueError,
2923 "cannot hash writable memoryview object");
2924 return -1;
2925 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002926 ret = get_native_fmtchar(&fmt, view->format);
2927 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2928 PyErr_SetString(PyExc_ValueError,
2929 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2930 return -1;
2931 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002932 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2933 /* Keep the original error message */
2934 return -1;
2935 }
2936
2937 if (!MV_C_CONTIGUOUS(self->flags)) {
2938 mem = PyMem_Malloc(view->len);
2939 if (mem == NULL) {
2940 PyErr_NoMemory();
2941 return -1;
2942 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002943 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002944 PyMem_Free(mem);
2945 return -1;
2946 }
2947 }
2948
2949 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002950 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002951
2952 if (mem != view->buf)
2953 PyMem_Free(mem);
2954 }
2955
2956 return self->hash;
2957}
2958
2959
2960/**************************************************************************/
2961/* getters */
2962/**************************************************************************/
2963
2964static PyObject *
2965_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2966{
2967 int i;
2968 PyObject *o;
2969 PyObject *intTuple;
2970
2971 if (vals == NULL)
2972 return PyTuple_New(0);
2973
2974 intTuple = PyTuple_New(len);
2975 if (!intTuple)
2976 return NULL;
2977 for (i=0; i<len; i++) {
2978 o = PyLong_FromSsize_t(vals[i]);
2979 if (!o) {
2980 Py_DECREF(intTuple);
2981 return NULL;
2982 }
2983 PyTuple_SET_ITEM(intTuple, i, o);
2984 }
2985 return intTuple;
2986}
2987
2988static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002989memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002990{
2991 Py_buffer *view = &self->view;
2992
2993 CHECK_RELEASED(self);
2994 if (view->obj == NULL) {
2995 Py_RETURN_NONE;
2996 }
2997 Py_INCREF(view->obj);
2998 return view->obj;
2999}
3000
3001static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003002memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003003{
3004 CHECK_RELEASED(self);
3005 return PyLong_FromSsize_t(self->view.len);
3006}
3007
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003008static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003009memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003010{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003011 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003012 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003013}
3014
3015static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003016memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003017{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003018 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003019 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003020}
3021
3022static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003023memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003024{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003025 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003026 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003027}
3028
3029static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003030memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003031{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003032 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003033 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003034}
3035
3036static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003037memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003038{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003039 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003040 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003041}
3042
3043static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003044memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003045{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003046 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003047 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003048}
3049
3050static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003051memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003052{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003053 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003054 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003055}
3056
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003057static PyObject *
3058memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3059{
3060 CHECK_RELEASED(self);
3061 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3062}
3063
3064static PyObject *
3065memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3066{
3067 CHECK_RELEASED(self);
3068 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3069}
3070
3071static PyObject *
3072memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3073{
3074 CHECK_RELEASED(self);
3075 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3076}
3077
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003078PyDoc_STRVAR(memory_obj_doc,
3079 "The underlying object of the memoryview.");
3080PyDoc_STRVAR(memory_nbytes_doc,
3081 "The amount of space in bytes that the array would use in\n"
3082 " a contiguous representation.");
3083PyDoc_STRVAR(memory_readonly_doc,
3084 "A bool indicating whether the memory is read only.");
3085PyDoc_STRVAR(memory_itemsize_doc,
3086 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003087PyDoc_STRVAR(memory_format_doc,
3088 "A string containing the format (in struct module style)\n"
3089 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003090PyDoc_STRVAR(memory_ndim_doc,
3091 "An integer indicating how many dimensions of a multi-dimensional\n"
3092 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003093PyDoc_STRVAR(memory_shape_doc,
3094 "A tuple of ndim integers giving the shape of the memory\n"
3095 " as an N-dimensional array.");
3096PyDoc_STRVAR(memory_strides_doc,
3097 "A tuple of ndim integers giving the size in bytes to access\n"
3098 " each element for each dimension of the array.");
3099PyDoc_STRVAR(memory_suboffsets_doc,
3100 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003101PyDoc_STRVAR(memory_c_contiguous_doc,
3102 "A bool indicating whether the memory is C contiguous.");
3103PyDoc_STRVAR(memory_f_contiguous_doc,
3104 "A bool indicating whether the memory is Fortran contiguous.");
3105PyDoc_STRVAR(memory_contiguous_doc,
3106 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003107
Stefan Krahbcaf5992014-05-18 00:35:09 +02003108
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003109static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003110 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3111 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003112 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3113 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3114 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3115 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3116 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3117 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3118 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003119 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3120 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3121 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003122 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003123};
3124
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003125PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003126"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003127\n\
3128Release the underlying buffer exposed by the memoryview object.");
3129PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahd08ea702019-02-02 18:57:41 +01003130"tobytes($self, /, order=None)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003131\n\
Stefan Krahd08ea702019-02-02 18:57:41 +01003132Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
3133When order is 'C' or 'F', the data of the original array is converted to C or\n\
3134Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
3135memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
3136views, the data is converted to C first. order=None is the same as order='C'.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003137PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003138"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003139\n\
3140Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003141PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003142"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003143\n\
3144Cast a memoryview to a new format or shape.");
Antoine Pitrou480ab052018-04-14 19:49:21 +02003145PyDoc_STRVAR(memory_toreadonly_doc,
3146"toreadonly($self, /)\n--\n\
3147\n\
3148Return a readonly version of the memoryview.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003149
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003150static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003151 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
Stéphane Wirtel359a2f32019-03-05 16:10:53 +01003152 {"tobytes", (PyCFunction)(void(*)(void))memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07003153 MEMORYVIEW_HEX_METHODDEF
Alexander Belopolskye370c382012-09-03 16:43:55 -04003154 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02003155 {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Antoine Pitrou480ab052018-04-14 19:49:21 +02003156 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003157 {"__enter__", memory_enter, METH_NOARGS, NULL},
3158 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003159 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003160};
3161
3162
3163PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003164 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003165 "memoryview", /* tp_name */
3166 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3167 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003168 (destructor)memory_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003169 0, /* tp_vectorcall_offset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003170 0, /* tp_getattr */
3171 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003172 0, /* tp_as_async */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003173 (reprfunc)memory_repr, /* tp_repr */
3174 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003175 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003176 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003177 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003178 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003179 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003180 PyObject_GenericGetAttr, /* tp_getattro */
3181 0, /* tp_setattro */
3182 &memory_as_buffer, /* tp_as_buffer */
3183 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3184 memory_doc, /* tp_doc */
3185 (traverseproc)memory_traverse, /* tp_traverse */
3186 (inquiry)memory_clear, /* tp_clear */
3187 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003188 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003189 0, /* tp_iter */
3190 0, /* tp_iternext */
3191 memory_methods, /* tp_methods */
3192 0, /* tp_members */
3193 memory_getsetlist, /* tp_getset */
3194 0, /* tp_base */
3195 0, /* tp_dict */
3196 0, /* tp_descr_get */
3197 0, /* tp_descr_set */
3198 0, /* tp_dictoffset */
3199 0, /* tp_init */
3200 0, /* tp_alloc */
3201 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003202};