blob: da06338017caebd598b8d0eb0bbe300324702bfc [file] [log] [blame]
Stefan Krahee3bac42020-02-24 11:15:26 +01001/*
2 * Memoryview object implementation
3 * --------------------------------
4 *
5 * This implementation is a complete rewrite contributed by Stefan Krah in
6 * Python 3.3. Substantial credit goes to Antoine Pitrou (who had already
7 * fortified and rewritten the previous implementation) and Nick Coghlan
8 * (who came up with the idea of the ManagedBuffer) for analyzing the complex
9 * ownership rules.
10 *
11 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000012
13#include "Python.h"
Victor Stinnera15e2602020-04-08 02:01:56 +020014#include "pycore_abstract.h" // _PyIndex_Check()
Victor Stinnerbcda8f12018-11-21 22:27:47 +010015#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +010016#include "pycore_pymem.h"
17#include "pycore_pystate.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +000018#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +010019#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000020
Gregory P. Smith0c2f9302019-05-29 11:46:58 -070021/*[clinic input]
22class memoryview "PyMemoryViewObject *" "&PyMemoryView_Type"
23[clinic start generated code]*/
24/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2e49d2192835219]*/
25
26#include "clinic/memoryobject.c.h"
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000027
Stefan Krah9a2d99e2012-02-25 12:24:21 +010028/****************************************************************************/
29/* ManagedBuffer Object */
30/****************************************************************************/
31
32/*
33 ManagedBuffer Object:
34 ---------------------
35
36 The purpose of this object is to facilitate the handling of chained
37 memoryviews that have the same underlying exporting object. PEP-3118
38 allows the underlying object to change while a view is exported. This
39 could lead to unexpected results when constructing a new memoryview
40 from an existing memoryview.
41
42 Rather than repeatedly redirecting buffer requests to the original base
43 object, all chained memoryviews use a single buffer snapshot. This
44 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
45
46 Ownership rules:
47 ----------------
48
49 The master buffer inside a managed buffer is filled in by the original
50 base object. shape, strides, suboffsets and format are read-only for
51 all consumers.
52
53 A memoryview's buffer is a private copy of the exporter's buffer. shape,
54 strides and suboffsets belong to the memoryview and are thus writable.
55
56 If a memoryview itself exports several buffers via memory_getbuf(), all
57 buffer copies share shape, strides and suboffsets. In this case, the
58 arrays are NOT writable.
59
60 Reference count assumptions:
61 ----------------------------
62
63 The 'obj' member of a Py_buffer must either be NULL or refer to the
64 exporting base object. In the Python codebase, all getbufferprocs
65 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
66
67 PyBuffer_Release() decrements view.obj (if non-NULL), so the
68 releasebufferprocs must NOT decrement view.obj.
69*/
70
71
Stefan Krah9a2d99e2012-02-25 12:24:21 +010072#define CHECK_MBUF_RELEASED(mbuf) \
73 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
74 PyErr_SetString(PyExc_ValueError, \
75 "operation forbidden on released memoryview object"); \
76 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000077 }
78
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000079
Benjamin Peterson82cce4c2016-09-08 11:56:06 -070080static inline _PyManagedBufferObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +010081mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000082{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010083 _PyManagedBufferObject *mbuf;
84
85 mbuf = (_PyManagedBufferObject *)
86 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
87 if (mbuf == NULL)
88 return NULL;
89 mbuf->flags = 0;
90 mbuf->exports = 0;
91 mbuf->master.obj = NULL;
92 _PyObject_GC_TRACK(mbuf);
93
94 return mbuf;
95}
96
97static PyObject *
98_PyManagedBuffer_FromObject(PyObject *base)
99{
100 _PyManagedBufferObject *mbuf;
101
102 mbuf = mbuf_alloc();
103 if (mbuf == NULL)
104 return NULL;
105
106 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +0100107 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100108 Py_DECREF(mbuf);
109 return NULL;
110 }
111
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100112 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000113}
114
115static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100116mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000117{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100118 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
119 return;
120
121 /* NOTE: at this point self->exports can still be > 0 if this function
122 is called from mbuf_clear() to break up a reference cycle. */
123 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
124
125 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
126 _PyObject_GC_UNTRACK(self);
127 PyBuffer_Release(&self->master);
128}
129
130static void
131mbuf_dealloc(_PyManagedBufferObject *self)
132{
133 assert(self->exports == 0);
134 mbuf_release(self);
135 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
136 PyMem_Free(self->master.format);
137 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000138}
139
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000140static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100141mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000142{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100143 Py_VISIT(self->master.obj);
144 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000145}
146
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100147static int
148mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000149{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100150 assert(self->exports >= 0);
151 mbuf_release(self);
152 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000153}
154
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100155PyTypeObject _PyManagedBuffer_Type = {
156 PyVarObject_HEAD_INIT(&PyType_Type, 0)
157 "managedbuffer",
158 sizeof(_PyManagedBufferObject),
159 0,
160 (destructor)mbuf_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200161 0, /* tp_vectorcall_offset */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100162 0, /* tp_getattr */
163 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200164 0, /* tp_as_async */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100165 0, /* tp_repr */
166 0, /* tp_as_number */
167 0, /* tp_as_sequence */
168 0, /* tp_as_mapping */
169 0, /* tp_hash */
170 0, /* tp_call */
171 0, /* tp_str */
172 PyObject_GenericGetAttr, /* tp_getattro */
173 0, /* tp_setattro */
174 0, /* tp_as_buffer */
175 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
176 0, /* tp_doc */
177 (traverseproc)mbuf_traverse, /* tp_traverse */
178 (inquiry)mbuf_clear /* tp_clear */
179};
180
181
182/****************************************************************************/
183/* MemoryView Object */
184/****************************************************************************/
185
186/* In the process of breaking reference cycles mbuf_release() can be
187 called before memory_release(). */
188#define BASE_INACCESSIBLE(mv) \
189 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
190 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
191
192#define CHECK_RELEASED(mv) \
193 if (BASE_INACCESSIBLE(mv)) { \
194 PyErr_SetString(PyExc_ValueError, \
195 "operation forbidden on released memoryview object"); \
196 return NULL; \
197 }
198
199#define CHECK_RELEASED_INT(mv) \
200 if (BASE_INACCESSIBLE(mv)) { \
201 PyErr_SetString(PyExc_ValueError, \
202 "operation forbidden on released memoryview object"); \
203 return -1; \
204 }
205
206#define CHECK_LIST_OR_TUPLE(v) \
207 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
208 PyErr_SetString(PyExc_TypeError, \
209 #v " must be a list or a tuple"); \
210 return NULL; \
211 }
212
213#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
214
215/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100216#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100217/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100218#define ADJUST_PTR(ptr, suboffsets, dim) \
219 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100220
221/* Memoryview buffer properties */
222#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
223#define MV_F_CONTIGUOUS(flags) \
224 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
225#define MV_ANY_CONTIGUOUS(flags) \
226 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
227
228/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
229#define MV_CONTIGUOUS_NDIM1(view) \
230 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
231
232/* getbuffer() requests */
233#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
234#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
235#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
236#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
237#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
238#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
239#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
240#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
241
242
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000243PyDoc_STRVAR(memory_doc,
Stefan Krah195319e2016-12-30 12:23:35 +0100244"memoryview(object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000245\n\
246Create a new memoryview object which references the given object.");
247
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100248
249/**************************************************************************/
250/* Copy memoryview buffers */
251/**************************************************************************/
252
253/* The functions in this section take a source and a destination buffer
254 with the same logical structure: format, itemsize, ndim and shape
255 are identical, with ndim > 0.
256
257 NOTE: All buffers are assumed to have PyBUF_FULL information, which
258 is the case for memoryviews! */
259
260
261/* Assumptions: ndim >= 1. The macro tests for a corner case that should
262 perhaps be explicitly forbidden in the PEP. */
263#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
264 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
265
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700266static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000267last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100268{
269 assert(dest->ndim > 0 && src->ndim > 0);
270 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
271 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
272 dest->strides[dest->ndim-1] == dest->itemsize &&
273 src->strides[src->ndim-1] == src->itemsize);
274}
275
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000276/* This is not a general function for determining format equivalence.
277 It is used in copy_single() and copy_buffer() to weed out non-matching
278 formats. Skipping the '@' character is specifically used in slice
279 assignments, where the lvalue is already known to have a single character
280 format. This is a performance hack that could be rewritten (if properly
281 benchmarked). */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700282static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000283equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100284{
285 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100286
287 assert(dest->format && src->format);
288 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
289 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
290
291 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000292 dest->itemsize != src->itemsize) {
293 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100294 }
295
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000296 return 1;
297}
298
299/* Two shapes are equivalent if they are either equal or identical up
300 to a zero element at the same position. For example, in NumPy arrays
301 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700302static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000303equiv_shape(const Py_buffer *dest, const Py_buffer *src)
304{
305 int i;
306
307 if (dest->ndim != src->ndim)
308 return 0;
309
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100310 for (i = 0; i < dest->ndim; i++) {
311 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000312 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100313 if (dest->shape[i] == 0)
314 break;
315 }
316
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000317 return 1;
318}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100319
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000320/* Check that the logical structure of the destination and source buffers
321 is identical. */
322static int
323equiv_structure(const Py_buffer *dest, const Py_buffer *src)
324{
325 if (!equiv_format(dest, src) ||
326 !equiv_shape(dest, src)) {
327 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100328 "memoryview assignment: lvalue and rvalue have different "
329 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000330 return 0;
331 }
332
333 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100334}
335
336/* Base case for recursive multi-dimensional copying. Contiguous arrays are
337 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
338 sizeof(mem) == shape[0] * itemsize. */
339static void
340copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
341 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
342 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
343 char *mem)
344{
345 if (mem == NULL) { /* contiguous */
346 Py_ssize_t size = shape[0] * itemsize;
347 if (dptr + size < sptr || sptr + size < dptr)
348 memcpy(dptr, sptr, size); /* no overlapping */
349 else
350 memmove(dptr, sptr, size);
351 }
352 else {
353 char *p;
354 Py_ssize_t i;
355 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100356 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100357 memcpy(p, xsptr, itemsize);
358 }
359 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100360 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100361 memcpy(xdptr, p, itemsize);
362 }
363 }
364
365}
366
367/* Recursively copy a source buffer to a destination buffer. The two buffers
368 have the same ndim, shape and itemsize. */
369static void
370copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
371 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
372 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
373 char *mem)
374{
375 Py_ssize_t i;
376
377 assert(ndim >= 1);
378
379 if (ndim == 1) {
380 copy_base(shape, itemsize,
381 dptr, dstrides, dsuboffsets,
382 sptr, sstrides, ssuboffsets,
383 mem);
384 return;
385 }
386
387 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100388 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
389 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100390
391 copy_rec(shape+1, ndim-1, itemsize,
392 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
393 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
394 mem);
395 }
396}
397
398/* Faster copying of one-dimensional arrays. */
399static int
400copy_single(Py_buffer *dest, Py_buffer *src)
401{
402 char *mem = NULL;
403
404 assert(dest->ndim == 1);
405
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000406 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100407 return -1;
408
409 if (!last_dim_is_contiguous(dest, src)) {
410 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
411 if (mem == NULL) {
412 PyErr_NoMemory();
413 return -1;
414 }
415 }
416
417 copy_base(dest->shape, dest->itemsize,
418 dest->buf, dest->strides, dest->suboffsets,
419 src->buf, src->strides, src->suboffsets,
420 mem);
421
422 if (mem)
423 PyMem_Free(mem);
424
425 return 0;
426}
427
428/* Recursively copy src to dest. Both buffers must have the same basic
429 structure. Copying is atomic, the function never fails with a partial
430 copy. */
431static int
432copy_buffer(Py_buffer *dest, Py_buffer *src)
433{
434 char *mem = NULL;
435
436 assert(dest->ndim > 0);
437
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000438 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100439 return -1;
440
441 if (!last_dim_is_contiguous(dest, src)) {
442 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
443 if (mem == NULL) {
444 PyErr_NoMemory();
445 return -1;
446 }
447 }
448
449 copy_rec(dest->shape, dest->ndim, dest->itemsize,
450 dest->buf, dest->strides, dest->suboffsets,
451 src->buf, src->strides, src->suboffsets,
452 mem);
453
454 if (mem)
455 PyMem_Free(mem);
456
457 return 0;
458}
459
460/* Initialize strides for a C-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700461static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100462init_strides_from_shape(Py_buffer *view)
463{
464 Py_ssize_t i;
465
466 assert(view->ndim > 0);
467
468 view->strides[view->ndim-1] = view->itemsize;
469 for (i = view->ndim-2; i >= 0; i--)
470 view->strides[i] = view->strides[i+1] * view->shape[i+1];
471}
472
473/* Initialize strides for a Fortran-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700474static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100475init_fortran_strides_from_shape(Py_buffer *view)
476{
477 Py_ssize_t i;
478
479 assert(view->ndim > 0);
480
481 view->strides[0] = view->itemsize;
482 for (i = 1; i < view->ndim; i++)
483 view->strides[i] = view->strides[i-1] * view->shape[i-1];
484}
485
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200486/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
487 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100488 len(mem) == src->len. */
489static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200490buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100491{
492 Py_buffer dest;
493 Py_ssize_t *strides;
494 int ret;
495
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200496 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100497 assert(src->shape != NULL);
498 assert(src->strides != NULL);
499
500 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
501 if (strides == NULL) {
502 PyErr_NoMemory();
503 return -1;
504 }
505
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200506 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100507 dest = *src;
508 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200509 /* shape is constant and shared: the logical representation of the
510 array is unaltered. */
511
512 /* The physical representation determined by strides (and possibly
513 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100514 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200515 if (order == 'C' || order == 'A') {
516 init_strides_from_shape(&dest);
517 }
518 else {
519 init_fortran_strides_from_shape(&dest);
520 }
521
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100522 dest.suboffsets = NULL;
523
524 ret = copy_buffer(&dest, src);
525
526 PyMem_Free(strides);
527 return ret;
528}
529
530
531/****************************************************************************/
532/* Constructors */
533/****************************************************************************/
534
535/* Initialize values that are shared with the managed buffer. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700536static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100537init_shared_values(Py_buffer *dest, const Py_buffer *src)
538{
539 dest->obj = src->obj;
540 dest->buf = src->buf;
541 dest->len = src->len;
542 dest->itemsize = src->itemsize;
543 dest->readonly = src->readonly;
544 dest->format = src->format ? src->format : "B";
545 dest->internal = src->internal;
546}
547
548/* Copy shape and strides. Reconstruct missing values. */
549static void
550init_shape_strides(Py_buffer *dest, const Py_buffer *src)
551{
552 Py_ssize_t i;
553
554 if (src->ndim == 0) {
555 dest->shape = NULL;
556 dest->strides = NULL;
557 return;
558 }
559 if (src->ndim == 1) {
560 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
561 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
562 return;
563 }
564
565 for (i = 0; i < src->ndim; i++)
566 dest->shape[i] = src->shape[i];
567 if (src->strides) {
568 for (i = 0; i < src->ndim; i++)
569 dest->strides[i] = src->strides[i];
570 }
571 else {
572 init_strides_from_shape(dest);
573 }
574}
575
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700576static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100577init_suboffsets(Py_buffer *dest, const Py_buffer *src)
578{
579 Py_ssize_t i;
580
581 if (src->suboffsets == NULL) {
582 dest->suboffsets = NULL;
583 return;
584 }
585 for (i = 0; i < src->ndim; i++)
586 dest->suboffsets[i] = src->suboffsets[i];
587}
588
589/* len = product(shape) * itemsize */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700590static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100591init_len(Py_buffer *view)
592{
593 Py_ssize_t i, len;
594
595 len = 1;
596 for (i = 0; i < view->ndim; i++)
597 len *= view->shape[i];
598 len *= view->itemsize;
599
600 view->len = len;
601}
602
603/* Initialize memoryview buffer properties. */
604static void
605init_flags(PyMemoryViewObject *mv)
606{
607 const Py_buffer *view = &mv->view;
608 int flags = 0;
609
610 switch (view->ndim) {
611 case 0:
612 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
613 _Py_MEMORYVIEW_FORTRAN);
614 break;
615 case 1:
616 if (MV_CONTIGUOUS_NDIM1(view))
617 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
618 break;
619 default:
620 if (PyBuffer_IsContiguous(view, 'C'))
621 flags |= _Py_MEMORYVIEW_C;
622 if (PyBuffer_IsContiguous(view, 'F'))
623 flags |= _Py_MEMORYVIEW_FORTRAN;
624 break;
625 }
626
627 if (view->suboffsets) {
628 flags |= _Py_MEMORYVIEW_PIL;
629 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
630 }
631
632 mv->flags = flags;
633}
634
635/* Allocate a new memoryview and perform basic initialization. New memoryviews
636 are exclusively created through the mbuf_add functions. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700637static inline PyMemoryViewObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100638memory_alloc(int ndim)
639{
640 PyMemoryViewObject *mv;
641
642 mv = (PyMemoryViewObject *)
643 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
644 if (mv == NULL)
645 return NULL;
646
647 mv->mbuf = NULL;
648 mv->hash = -1;
649 mv->flags = 0;
650 mv->exports = 0;
651 mv->view.ndim = ndim;
652 mv->view.shape = mv->ob_array;
653 mv->view.strides = mv->ob_array + ndim;
654 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100655 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100656
657 _PyObject_GC_TRACK(mv);
658 return mv;
659}
660
661/*
662 Return a new memoryview that is registered with mbuf. If src is NULL,
663 use mbuf->master as the underlying buffer. Otherwise, use src.
664
665 The new memoryview has full buffer information: shape and strides
666 are always present, suboffsets as needed. Arrays are copied to
667 the memoryview's ob_array field.
668 */
669static PyObject *
670mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
671{
672 PyMemoryViewObject *mv;
673 Py_buffer *dest;
674
675 if (src == NULL)
676 src = &mbuf->master;
677
678 if (src->ndim > PyBUF_MAX_NDIM) {
679 PyErr_SetString(PyExc_ValueError,
680 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200681 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100682 return NULL;
683 }
684
685 mv = memory_alloc(src->ndim);
686 if (mv == NULL)
687 return NULL;
688
689 dest = &mv->view;
690 init_shared_values(dest, src);
691 init_shape_strides(dest, src);
692 init_suboffsets(dest, src);
693 init_flags(mv);
694
695 mv->mbuf = mbuf;
696 Py_INCREF(mbuf);
697 mbuf->exports++;
698
699 return (PyObject *)mv;
700}
701
702/* Register an incomplete view: shape, strides, suboffsets and flags still
703 need to be initialized. Use 'ndim' instead of src->ndim to determine the
704 size of the memoryview's ob_array.
705
706 Assumption: ndim <= PyBUF_MAX_NDIM. */
707static PyObject *
708mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
709 int ndim)
710{
711 PyMemoryViewObject *mv;
712 Py_buffer *dest;
713
714 if (src == NULL)
715 src = &mbuf->master;
716
717 assert(ndim <= PyBUF_MAX_NDIM);
718
719 mv = memory_alloc(ndim);
720 if (mv == NULL)
721 return NULL;
722
723 dest = &mv->view;
724 init_shared_values(dest, src);
725
726 mv->mbuf = mbuf;
727 Py_INCREF(mbuf);
728 mbuf->exports++;
729
730 return (PyObject *)mv;
731}
732
733/* Expose a raw memory area as a view of contiguous bytes. flags can be
734 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
735 The memoryview has complete buffer information. */
736PyObject *
737PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
738{
739 _PyManagedBufferObject *mbuf;
740 PyObject *mv;
741 int readonly;
742
743 assert(mem != NULL);
744 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
745
746 mbuf = mbuf_alloc();
747 if (mbuf == NULL)
748 return NULL;
749
750 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
751 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
752 PyBUF_FULL_RO);
753
754 mv = mbuf_add_view(mbuf, NULL);
755 Py_DECREF(mbuf);
756
757 return mv;
758}
759
760/* Create a memoryview from a given Py_buffer. For simple byte views,
761 PyMemoryView_FromMemory() should be used instead.
762 This function is the only entry point that can create a master buffer
763 without full information. Because of this fact init_shape_strides()
764 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000765PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000766PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000767{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100768 _PyManagedBufferObject *mbuf;
769 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000770
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000771 if (info->buf == NULL) {
772 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100773 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000774 return NULL;
775 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100776
777 mbuf = mbuf_alloc();
778 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000779 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100780
781 /* info->obj is either NULL or a borrowed reference. This reference
782 should not be decremented in PyBuffer_Release(). */
783 mbuf->master = *info;
784 mbuf->master.obj = NULL;
785
786 mv = mbuf_add_view(mbuf, NULL);
787 Py_DECREF(mbuf);
788
789 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000790}
791
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100792/* Create a memoryview from an object that implements the buffer protocol.
793 If the object is a memoryview, the new memoryview must be registered
794 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000795PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100796PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000797{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100798 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000799
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100800 if (PyMemoryView_Check(v)) {
801 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
802 CHECK_RELEASED(mv);
803 return mbuf_add_view(mv->mbuf, &mv->view);
804 }
805 else if (PyObject_CheckBuffer(v)) {
806 PyObject *ret;
807 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
808 if (mbuf == NULL)
809 return NULL;
810 ret = mbuf_add_view(mbuf, NULL);
811 Py_DECREF(mbuf);
812 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000813 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000814
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100815 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400816 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100817 Py_TYPE(v)->tp_name);
818 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000819}
820
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100821/* Copy the format string from a base object that might vanish. */
822static int
823mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
824{
825 if (fmt != NULL) {
826 char *cp = PyMem_Malloc(strlen(fmt)+1);
827 if (cp == NULL) {
828 PyErr_NoMemory();
829 return -1;
830 }
831 mbuf->master.format = strcpy(cp, fmt);
832 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
833 }
834
835 return 0;
836}
837
838/*
839 Return a memoryview that is based on a contiguous copy of src.
840 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
841
842 Ownership rules:
843 1) As usual, the returned memoryview has a private copy
844 of src->shape, src->strides and src->suboffsets.
845 2) src->format is copied to the master buffer and released
846 in mbuf_dealloc(). The releasebufferproc of the bytes
847 object is NULL, so it does not matter that mbuf_release()
848 passes the altered format pointer to PyBuffer_Release().
849*/
850static PyObject *
851memory_from_contiguous_copy(Py_buffer *src, char order)
852{
853 _PyManagedBufferObject *mbuf;
854 PyMemoryViewObject *mv;
855 PyObject *bytes;
856 Py_buffer *dest;
857 int i;
858
859 assert(src->ndim > 0);
860 assert(src->shape != NULL);
861
862 bytes = PyBytes_FromStringAndSize(NULL, src->len);
863 if (bytes == NULL)
864 return NULL;
865
866 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
867 Py_DECREF(bytes);
868 if (mbuf == NULL)
869 return NULL;
870
871 if (mbuf_copy_format(mbuf, src->format) < 0) {
872 Py_DECREF(mbuf);
873 return NULL;
874 }
875
876 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
877 Py_DECREF(mbuf);
878 if (mv == NULL)
879 return NULL;
880
881 dest = &mv->view;
882
883 /* shared values are initialized correctly except for itemsize */
884 dest->itemsize = src->itemsize;
885
886 /* shape and strides */
887 for (i = 0; i < src->ndim; i++) {
888 dest->shape[i] = src->shape[i];
889 }
890 if (order == 'C' || order == 'A') {
891 init_strides_from_shape(dest);
892 }
893 else {
894 init_fortran_strides_from_shape(dest);
895 }
896 /* suboffsets */
897 dest->suboffsets = NULL;
898
899 /* flags */
900 init_flags(mv);
901
902 if (copy_buffer(dest, src) < 0) {
903 Py_DECREF(mv);
904 return NULL;
905 }
906
907 return (PyObject *)mv;
908}
909
910/*
911 Return a new memoryview object based on a contiguous exporter with
912 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
913 The logical structure of the input and output buffers is the same
914 (i.e. tolist(input) == tolist(output)), but the physical layout in
915 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200916
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100917 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
918 otherwise it may be writable or read-only.
919
920 If the exporter is already contiguous with the desired target order,
921 the memoryview will be directly based on the exporter.
922
923 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
924 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
925 'F'ortran order otherwise.
926*/
927PyObject *
928PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
929{
930 PyMemoryViewObject *mv;
931 PyObject *ret;
932 Py_buffer *view;
933
934 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
935 assert(order == 'C' || order == 'F' || order == 'A');
936
937 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
938 if (mv == NULL)
939 return NULL;
940
941 view = &mv->view;
942 if (buffertype == PyBUF_WRITE && view->readonly) {
943 PyErr_SetString(PyExc_BufferError,
944 "underlying buffer is not writable");
945 Py_DECREF(mv);
946 return NULL;
947 }
948
949 if (PyBuffer_IsContiguous(view, order))
950 return (PyObject *)mv;
951
952 if (buffertype == PyBUF_WRITE) {
953 PyErr_SetString(PyExc_BufferError,
954 "writable contiguous buffer requested "
955 "for a non-contiguous object.");
956 Py_DECREF(mv);
957 return NULL;
958 }
959
960 ret = memory_from_contiguous_copy(view, order);
961 Py_DECREF(mv);
962 return ret;
963}
964
965
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000966static PyObject *
967memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
968{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000969 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100970 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000971
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000972 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
973 &obj)) {
974 return NULL;
975 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000976
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000977 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000978}
979
980
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100981/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200982/* Previously in abstract.c */
983/****************************************************************************/
984
985typedef struct {
986 Py_buffer view;
987 Py_ssize_t array[1];
988} Py_buffer_full;
989
990int
991PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
992{
993 Py_buffer_full *fb = NULL;
994 int ret;
995
996 assert(order == 'C' || order == 'F' || order == 'A');
997
998 if (len != src->len) {
999 PyErr_SetString(PyExc_ValueError,
1000 "PyBuffer_ToContiguous: len != view->len");
1001 return -1;
1002 }
1003
1004 if (PyBuffer_IsContiguous(src, order)) {
1005 memcpy((char *)buf, src->buf, len);
1006 return 0;
1007 }
1008
1009 /* buffer_to_contiguous() assumes PyBUF_FULL */
1010 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
1011 if (fb == NULL) {
1012 PyErr_NoMemory();
1013 return -1;
1014 }
1015 fb->view.ndim = src->ndim;
1016 fb->view.shape = fb->array;
1017 fb->view.strides = fb->array + src->ndim;
1018 fb->view.suboffsets = fb->array + 2 * src->ndim;
1019
1020 init_shared_values(&fb->view, src);
1021 init_shape_strides(&fb->view, src);
1022 init_suboffsets(&fb->view, src);
1023
1024 src = &fb->view;
1025
1026 ret = buffer_to_contiguous(buf, src, order);
1027 PyMem_Free(fb);
1028 return ret;
1029}
1030
1031
1032/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001033/* Release/GC management */
1034/****************************************************************************/
1035
1036/* Inform the managed buffer that this particular memoryview will not access
1037 the underlying buffer again. If no other memoryviews are registered with
1038 the managed buffer, the underlying buffer is released instantly and
1039 marked as inaccessible for both the memoryview and the managed buffer.
1040
1041 This function fails if the memoryview itself has exported buffers. */
1042static int
1043_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001044{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001045 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1046 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001047
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001048 if (self->exports == 0) {
1049 self->flags |= _Py_MEMORYVIEW_RELEASED;
1050 assert(self->mbuf->exports > 0);
1051 if (--self->mbuf->exports == 0)
1052 mbuf_release(self->mbuf);
1053 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001054 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001055 if (self->exports > 0) {
1056 PyErr_Format(PyExc_BufferError,
1057 "memoryview has %zd exported buffer%s", self->exports,
1058 self->exports==1 ? "" : "s");
1059 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001060 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001061
Victor Stinner47ee8a62020-01-27 22:37:44 +01001062 PyErr_SetString(PyExc_SystemError,
1063 "_memory_release(): negative export count");
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001064 return -1;
1065}
1066
1067static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001068memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001069{
1070 if (_memory_release(self) < 0)
1071 return NULL;
1072 Py_RETURN_NONE;
1073}
1074
1075static void
1076memory_dealloc(PyMemoryViewObject *self)
1077{
1078 assert(self->exports == 0);
1079 _PyObject_GC_UNTRACK(self);
1080 (void)_memory_release(self);
1081 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001082 if (self->weakreflist != NULL)
1083 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001084 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001085}
1086
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001087static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001088memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001089{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001090 Py_VISIT(self->mbuf);
1091 return 0;
1092}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001093
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001094static int
1095memory_clear(PyMemoryViewObject *self)
1096{
1097 (void)_memory_release(self);
1098 Py_CLEAR(self->mbuf);
1099 return 0;
1100}
1101
1102static PyObject *
1103memory_enter(PyObject *self, PyObject *args)
1104{
1105 CHECK_RELEASED(self);
1106 Py_INCREF(self);
1107 return self;
1108}
1109
1110static PyObject *
1111memory_exit(PyObject *self, PyObject *args)
1112{
Stefan Krahe4c07992012-07-28 14:10:02 +02001113 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001114}
1115
1116
1117/****************************************************************************/
1118/* Casting format and shape */
1119/****************************************************************************/
1120
1121#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1122
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001123static inline Py_ssize_t
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001124get_native_fmtchar(char *result, const char *fmt)
1125{
1126 Py_ssize_t size = -1;
1127
1128 if (fmt[0] == '@') fmt++;
1129
1130 switch (fmt[0]) {
1131 case 'c': case 'b': case 'B': size = sizeof(char); break;
1132 case 'h': case 'H': size = sizeof(short); break;
1133 case 'i': case 'I': size = sizeof(int); break;
1134 case 'l': case 'L': size = sizeof(long); break;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001135 case 'q': case 'Q': size = sizeof(long long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001136 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1137 case 'f': size = sizeof(float); break;
1138 case 'd': size = sizeof(double); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001139 case '?': size = sizeof(_Bool); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001140 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001141 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001142
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001143 if (size > 0 && fmt[1] == '\0') {
1144 *result = fmt[0];
1145 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001146 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001147
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001148 return -1;
1149}
1150
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001151static inline const char *
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001152get_native_fmtstr(const char *fmt)
1153{
1154 int at = 0;
1155
1156 if (fmt[0] == '@') {
1157 at = 1;
1158 fmt++;
1159 }
1160 if (fmt[0] == '\0' || fmt[1] != '\0') {
1161 return NULL;
1162 }
1163
1164#define RETURN(s) do { return at ? "@" s : s; } while (0)
1165
1166 switch (fmt[0]) {
1167 case 'c': RETURN("c");
1168 case 'b': RETURN("b");
1169 case 'B': RETURN("B");
1170 case 'h': RETURN("h");
1171 case 'H': RETURN("H");
1172 case 'i': RETURN("i");
1173 case 'I': RETURN("I");
1174 case 'l': RETURN("l");
1175 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001176 case 'q': RETURN("q");
1177 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001178 case 'n': RETURN("n");
1179 case 'N': RETURN("N");
1180 case 'f': RETURN("f");
1181 case 'd': RETURN("d");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001182 case '?': RETURN("?");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001183 case 'P': RETURN("P");
1184 }
1185
1186 return NULL;
1187}
1188
1189
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001190/* Cast a memoryview's data type to 'format'. The input array must be
1191 C-contiguous. At least one of input-format, output-format must have
1192 byte size. The output array is 1-D, with the same byte length as the
1193 input array. Thus, view->len must be a multiple of the new itemsize. */
1194static int
1195cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1196{
1197 Py_buffer *view = &mv->view;
1198 PyObject *asciifmt;
1199 char srcchar, destchar;
1200 Py_ssize_t itemsize;
1201 int ret = -1;
1202
1203 assert(view->ndim >= 1);
1204 assert(Py_SIZE(mv) == 3*view->ndim);
1205 assert(view->shape == mv->ob_array);
1206 assert(view->strides == mv->ob_array + view->ndim);
1207 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1208
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001209 asciifmt = PyUnicode_AsASCIIString(format);
1210 if (asciifmt == NULL)
1211 return ret;
1212
1213 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1214 if (itemsize < 0) {
1215 PyErr_SetString(PyExc_ValueError,
1216 "memoryview: destination format must be a native single "
1217 "character format prefixed with an optional '@'");
1218 goto out;
1219 }
1220
Stefan Krah0c515952015-08-08 13:38:10 +02001221 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1222 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001223 PyErr_SetString(PyExc_TypeError,
1224 "memoryview: cannot cast between two non-byte formats");
1225 goto out;
1226 }
1227 if (view->len % itemsize) {
1228 PyErr_SetString(PyExc_TypeError,
1229 "memoryview: length is not a multiple of itemsize");
1230 goto out;
1231 }
1232
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001233 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001234 if (view->format == NULL) {
1235 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1236 PyErr_SetString(PyExc_RuntimeError,
1237 "memoryview: internal error");
1238 goto out;
1239 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001240 view->itemsize = itemsize;
1241
1242 view->ndim = 1;
1243 view->shape[0] = view->len / view->itemsize;
1244 view->strides[0] = view->itemsize;
1245 view->suboffsets = NULL;
1246
1247 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001248
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001249 ret = 0;
1250
1251out:
1252 Py_DECREF(asciifmt);
1253 return ret;
1254}
1255
1256/* The memoryview must have space for 3*len(seq) elements. */
1257static Py_ssize_t
1258copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1259 Py_ssize_t itemsize)
1260{
1261 Py_ssize_t x, i;
1262 Py_ssize_t len = itemsize;
1263
1264 for (i = 0; i < ndim; i++) {
1265 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1266 if (!PyLong_Check(tmp)) {
1267 PyErr_SetString(PyExc_TypeError,
1268 "memoryview.cast(): elements of shape must be integers");
1269 return -1;
1270 }
1271 x = PyLong_AsSsize_t(tmp);
1272 if (x == -1 && PyErr_Occurred()) {
1273 return -1;
1274 }
1275 if (x <= 0) {
1276 /* In general elements of shape may be 0, but not for casting. */
1277 PyErr_Format(PyExc_ValueError,
1278 "memoryview.cast(): elements of shape must be integers > 0");
1279 return -1;
1280 }
1281 if (x > PY_SSIZE_T_MAX / len) {
1282 PyErr_Format(PyExc_ValueError,
1283 "memoryview.cast(): product(shape) > SSIZE_MAX");
1284 return -1;
1285 }
1286 len *= x;
1287 shape[i] = x;
1288 }
1289
1290 return len;
1291}
1292
1293/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1294 If the result array does not have exactly the same byte length as the
1295 input array, raise ValueError. */
1296static int
1297cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1298{
1299 Py_buffer *view = &mv->view;
1300 Py_ssize_t len;
1301
1302 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1303 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1304 assert(view->shape == mv->ob_array);
1305 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1306 assert(view->suboffsets == NULL);
1307
1308 view->ndim = ndim;
1309 if (view->ndim == 0) {
1310 view->shape = NULL;
1311 view->strides = NULL;
1312 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001313 }
1314 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001315 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1316 if (len < 0)
1317 return -1;
1318 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001319 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001320
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001321 if (view->len != len) {
1322 PyErr_SetString(PyExc_TypeError,
1323 "memoryview: product(shape) * itemsize != buffer size");
1324 return -1;
1325 }
1326
1327 init_flags(mv);
1328
1329 return 0;
1330}
1331
1332static int
1333zero_in_shape(PyMemoryViewObject *mv)
1334{
1335 Py_buffer *view = &mv->view;
1336 Py_ssize_t i;
1337
1338 for (i = 0; i < view->ndim; i++)
1339 if (view->shape[i] == 0)
1340 return 1;
1341
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001342 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001343}
1344
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001345/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001346 Cast a copy of 'self' to a different view. The input view must
1347 be C-contiguous. The function always casts the input view to a
1348 1-D output according to 'format'. At least one of input-format,
1349 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001350
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001351 If 'shape' is given, the 1-D view from the previous step will
1352 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001353
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001354 All casts must result in views that will have the exact byte
1355 size of the original input. Otherwise, an error is raised.
1356*/
1357static PyObject *
1358memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001359{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001360 static char *kwlist[] = {"format", "shape", NULL};
1361 PyMemoryViewObject *mv = NULL;
1362 PyObject *shape = NULL;
1363 PyObject *format;
1364 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001365
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001366 CHECK_RELEASED(self);
1367
1368 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1369 &format, &shape)) {
1370 return NULL;
1371 }
1372 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001373 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001374 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001375 return NULL;
1376 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001377 if (!MV_C_CONTIGUOUS(self->flags)) {
1378 PyErr_SetString(PyExc_TypeError,
1379 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001380 return NULL;
1381 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001382 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001383 PyErr_SetString(PyExc_TypeError,
1384 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001385 return NULL;
1386 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001387 if (shape) {
1388 CHECK_LIST_OR_TUPLE(shape)
1389 ndim = PySequence_Fast_GET_SIZE(shape);
1390 if (ndim > PyBUF_MAX_NDIM) {
1391 PyErr_SetString(PyExc_ValueError,
1392 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001393 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001394 return NULL;
1395 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001396 if (self->view.ndim != 1 && ndim != 1) {
1397 PyErr_SetString(PyExc_TypeError,
1398 "memoryview: cast must be 1D -> ND or ND -> 1D");
1399 return NULL;
1400 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001401 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001402
1403 mv = (PyMemoryViewObject *)
1404 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1405 if (mv == NULL)
1406 return NULL;
1407
1408 if (cast_to_1D(mv, format) < 0)
1409 goto error;
1410 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1411 goto error;
1412
1413 return (PyObject *)mv;
1414
1415error:
1416 Py_DECREF(mv);
1417 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001418}
1419
Antoine Pitrou480ab052018-04-14 19:49:21 +02001420static PyObject *
1421memory_toreadonly(PyMemoryViewObject *self, PyObject *noargs)
1422{
1423 CHECK_RELEASED(self);
1424 /* Even if self is already readonly, we still need to create a new
1425 * object for .release() to work correctly.
1426 */
1427 self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1428 if (self != NULL) {
1429 self->view.readonly = 1;
1430 };
1431 return (PyObject *) self;
1432}
1433
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001434
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001435/**************************************************************************/
1436/* getbuffer */
1437/**************************************************************************/
1438
1439static int
1440memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1441{
1442 Py_buffer *base = &self->view;
1443 int baseflags = self->flags;
1444
1445 CHECK_RELEASED_INT(self);
1446
1447 /* start with complete information */
1448 *view = *base;
1449 view->obj = NULL;
1450
1451 if (REQ_WRITABLE(flags) && base->readonly) {
1452 PyErr_SetString(PyExc_BufferError,
1453 "memoryview: underlying buffer is not writable");
1454 return -1;
1455 }
1456 if (!REQ_FORMAT(flags)) {
1457 /* NULL indicates that the buffer's data type has been cast to 'B'.
1458 view->itemsize is the _previous_ itemsize. If shape is present,
1459 the equality product(shape) * itemsize = len still holds at this
1460 point. The equality calcsize(format) = itemsize does _not_ hold
1461 from here on! */
1462 view->format = NULL;
1463 }
1464
1465 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1466 PyErr_SetString(PyExc_BufferError,
1467 "memoryview: underlying buffer is not C-contiguous");
1468 return -1;
1469 }
1470 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1471 PyErr_SetString(PyExc_BufferError,
1472 "memoryview: underlying buffer is not Fortran contiguous");
1473 return -1;
1474 }
1475 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1476 PyErr_SetString(PyExc_BufferError,
1477 "memoryview: underlying buffer is not contiguous");
1478 return -1;
1479 }
1480 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1481 PyErr_SetString(PyExc_BufferError,
1482 "memoryview: underlying buffer requires suboffsets");
1483 return -1;
1484 }
1485 if (!REQ_STRIDES(flags)) {
1486 if (!MV_C_CONTIGUOUS(baseflags)) {
1487 PyErr_SetString(PyExc_BufferError,
1488 "memoryview: underlying buffer is not C-contiguous");
1489 return -1;
1490 }
1491 view->strides = NULL;
1492 }
1493 if (!REQ_SHAPE(flags)) {
1494 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1495 so base->buf = ndbuf->data. */
1496 if (view->format != NULL) {
1497 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1498 not make sense. */
1499 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001500 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001501 "is present");
1502 return -1;
1503 }
1504 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1505 do _not_ hold from here on! */
1506 view->ndim = 1;
1507 view->shape = NULL;
1508 }
1509
1510
1511 view->obj = (PyObject *)self;
1512 Py_INCREF(view->obj);
1513 self->exports++;
1514
1515 return 0;
1516}
1517
1518static void
1519memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1520{
1521 self->exports--;
1522 return;
1523 /* PyBuffer_Release() decrements view->obj after this function returns. */
1524}
1525
1526/* Buffer methods */
1527static PyBufferProcs memory_as_buffer = {
1528 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1529 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1530};
1531
1532
1533/****************************************************************************/
1534/* Optimized pack/unpack for all native format specifiers */
1535/****************************************************************************/
1536
1537/*
1538 Fix exceptions:
1539 1) Include format string in the error message.
1540 2) OverflowError -> ValueError.
1541 3) The error message from PyNumber_Index() is not ideal.
1542*/
1543static int
1544type_error_int(const char *fmt)
1545{
1546 PyErr_Format(PyExc_TypeError,
1547 "memoryview: invalid type for format '%s'", fmt);
1548 return -1;
1549}
1550
1551static int
1552value_error_int(const char *fmt)
1553{
1554 PyErr_Format(PyExc_ValueError,
1555 "memoryview: invalid value for format '%s'", fmt);
1556 return -1;
1557}
1558
1559static int
1560fix_error_int(const char *fmt)
1561{
1562 assert(PyErr_Occurred());
1563 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1564 PyErr_Clear();
1565 return type_error_int(fmt);
1566 }
1567 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1568 PyErr_ExceptionMatches(PyExc_ValueError)) {
1569 PyErr_Clear();
1570 return value_error_int(fmt);
1571 }
1572
1573 return -1;
1574}
1575
1576/* Accept integer objects or objects with an __index__() method. */
1577static long
1578pylong_as_ld(PyObject *item)
1579{
1580 PyObject *tmp;
1581 long ld;
1582
1583 tmp = PyNumber_Index(item);
1584 if (tmp == NULL)
1585 return -1;
1586
1587 ld = PyLong_AsLong(tmp);
1588 Py_DECREF(tmp);
1589 return ld;
1590}
1591
1592static unsigned long
1593pylong_as_lu(PyObject *item)
1594{
1595 PyObject *tmp;
1596 unsigned long lu;
1597
1598 tmp = PyNumber_Index(item);
1599 if (tmp == NULL)
1600 return (unsigned long)-1;
1601
1602 lu = PyLong_AsUnsignedLong(tmp);
1603 Py_DECREF(tmp);
1604 return lu;
1605}
1606
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001607static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001608pylong_as_lld(PyObject *item)
1609{
1610 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001611 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001612
1613 tmp = PyNumber_Index(item);
1614 if (tmp == NULL)
1615 return -1;
1616
1617 lld = PyLong_AsLongLong(tmp);
1618 Py_DECREF(tmp);
1619 return lld;
1620}
1621
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001622static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001623pylong_as_llu(PyObject *item)
1624{
1625 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001626 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001627
1628 tmp = PyNumber_Index(item);
1629 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001630 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001631
1632 llu = PyLong_AsUnsignedLongLong(tmp);
1633 Py_DECREF(tmp);
1634 return llu;
1635}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001636
1637static Py_ssize_t
1638pylong_as_zd(PyObject *item)
1639{
1640 PyObject *tmp;
1641 Py_ssize_t zd;
1642
1643 tmp = PyNumber_Index(item);
1644 if (tmp == NULL)
1645 return -1;
1646
1647 zd = PyLong_AsSsize_t(tmp);
1648 Py_DECREF(tmp);
1649 return zd;
1650}
1651
1652static size_t
1653pylong_as_zu(PyObject *item)
1654{
1655 PyObject *tmp;
1656 size_t zu;
1657
1658 tmp = PyNumber_Index(item);
1659 if (tmp == NULL)
1660 return (size_t)-1;
1661
1662 zu = PyLong_AsSize_t(tmp);
1663 Py_DECREF(tmp);
1664 return zu;
1665}
1666
1667/* Timings with the ndarray from _testbuffer.c indicate that using the
1668 struct module is around 15x slower than the two functions below. */
1669
1670#define UNPACK_SINGLE(dest, ptr, type) \
1671 do { \
1672 type x; \
1673 memcpy((char *)&x, ptr, sizeof x); \
1674 dest = x; \
1675 } while (0)
1676
1677/* Unpack a single item. 'fmt' can be any native format character in struct
1678 module syntax. This function is very sensitive to small changes. With this
1679 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001680static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001681unpack_single(const char *ptr, const char *fmt)
1682{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001683 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001684 unsigned long lu;
1685 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001686 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001687 long ld;
1688 Py_ssize_t zd;
1689 double d;
1690 unsigned char uc;
1691 void *p;
1692
1693 switch (fmt[0]) {
1694
1695 /* signed integers and fast path for 'B' */
Andy Lestere6be9b52020-02-11 20:28:35 -06001696 case 'B': uc = *((const unsigned char *)ptr); goto convert_uc;
1697 case 'b': ld = *((const signed char *)ptr); goto convert_ld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001698 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1699 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1700 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1701
1702 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001703 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001704
1705 /* unsigned integers */
1706 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1707 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1708 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1709
1710 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001711 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1712 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001713
1714 /* ssize_t and size_t */
1715 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1716 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1717
1718 /* floats */
1719 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1720 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1721
1722 /* bytes object */
1723 case 'c': goto convert_bytes;
1724
1725 /* pointer */
1726 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1727
1728 /* default */
1729 default: goto err_format;
1730 }
1731
1732convert_uc:
1733 /* PyLong_FromUnsignedLong() is slower */
1734 return PyLong_FromLong(uc);
1735convert_ld:
1736 return PyLong_FromLong(ld);
1737convert_lu:
1738 return PyLong_FromUnsignedLong(lu);
1739convert_lld:
1740 return PyLong_FromLongLong(lld);
1741convert_llu:
1742 return PyLong_FromUnsignedLongLong(llu);
1743convert_zd:
1744 return PyLong_FromSsize_t(zd);
1745convert_zu:
1746 return PyLong_FromSize_t(zu);
1747convert_double:
1748 return PyFloat_FromDouble(d);
1749convert_bool:
1750 return PyBool_FromLong(ld);
1751convert_bytes:
1752 return PyBytes_FromStringAndSize(ptr, 1);
1753convert_pointer:
1754 return PyLong_FromVoidPtr(p);
1755err_format:
1756 PyErr_Format(PyExc_NotImplementedError,
1757 "memoryview: format %s not supported", fmt);
1758 return NULL;
1759}
1760
1761#define PACK_SINGLE(ptr, src, type) \
1762 do { \
1763 type x; \
1764 x = (type)src; \
1765 memcpy(ptr, (char *)&x, sizeof x); \
1766 } while (0)
1767
1768/* Pack a single item. 'fmt' can be any native format character in
1769 struct module syntax. */
1770static int
1771pack_single(char *ptr, PyObject *item, const char *fmt)
1772{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001773 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001774 unsigned long lu;
1775 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001776 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001777 long ld;
1778 Py_ssize_t zd;
1779 double d;
1780 void *p;
1781
1782 switch (fmt[0]) {
1783 /* signed integers */
1784 case 'b': case 'h': case 'i': case 'l':
1785 ld = pylong_as_ld(item);
1786 if (ld == -1 && PyErr_Occurred())
1787 goto err_occurred;
1788 switch (fmt[0]) {
1789 case 'b':
1790 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1791 *((signed char *)ptr) = (signed char)ld; break;
1792 case 'h':
1793 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1794 PACK_SINGLE(ptr, ld, short); break;
1795 case 'i':
1796 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1797 PACK_SINGLE(ptr, ld, int); break;
1798 default: /* 'l' */
1799 PACK_SINGLE(ptr, ld, long); break;
1800 }
1801 break;
1802
1803 /* unsigned integers */
1804 case 'B': case 'H': case 'I': case 'L':
1805 lu = pylong_as_lu(item);
1806 if (lu == (unsigned long)-1 && PyErr_Occurred())
1807 goto err_occurred;
1808 switch (fmt[0]) {
1809 case 'B':
1810 if (lu > UCHAR_MAX) goto err_range;
1811 *((unsigned char *)ptr) = (unsigned char)lu; break;
1812 case 'H':
1813 if (lu > USHRT_MAX) goto err_range;
1814 PACK_SINGLE(ptr, lu, unsigned short); break;
1815 case 'I':
1816 if (lu > UINT_MAX) goto err_range;
1817 PACK_SINGLE(ptr, lu, unsigned int); break;
1818 default: /* 'L' */
1819 PACK_SINGLE(ptr, lu, unsigned long); break;
1820 }
1821 break;
1822
1823 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001824 case 'q':
1825 lld = pylong_as_lld(item);
1826 if (lld == -1 && PyErr_Occurred())
1827 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001828 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001829 break;
1830 case 'Q':
1831 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001832 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001833 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001834 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001835 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001836
1837 /* ssize_t and size_t */
1838 case 'n':
1839 zd = pylong_as_zd(item);
1840 if (zd == -1 && PyErr_Occurred())
1841 goto err_occurred;
1842 PACK_SINGLE(ptr, zd, Py_ssize_t);
1843 break;
1844 case 'N':
1845 zu = pylong_as_zu(item);
1846 if (zu == (size_t)-1 && PyErr_Occurred())
1847 goto err_occurred;
1848 PACK_SINGLE(ptr, zu, size_t);
1849 break;
1850
1851 /* floats */
1852 case 'f': case 'd':
1853 d = PyFloat_AsDouble(item);
1854 if (d == -1.0 && PyErr_Occurred())
1855 goto err_occurred;
1856 if (fmt[0] == 'f') {
1857 PACK_SINGLE(ptr, d, float);
1858 }
1859 else {
1860 PACK_SINGLE(ptr, d, double);
1861 }
1862 break;
1863
1864 /* bool */
1865 case '?':
1866 ld = PyObject_IsTrue(item);
1867 if (ld < 0)
1868 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001869 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001870 break;
1871
1872 /* bytes object */
1873 case 'c':
1874 if (!PyBytes_Check(item))
1875 return type_error_int(fmt);
1876 if (PyBytes_GET_SIZE(item) != 1)
1877 return value_error_int(fmt);
1878 *ptr = PyBytes_AS_STRING(item)[0];
1879 break;
1880
1881 /* pointer */
1882 case 'P':
1883 p = PyLong_AsVoidPtr(item);
1884 if (p == NULL && PyErr_Occurred())
1885 goto err_occurred;
1886 PACK_SINGLE(ptr, p, void *);
1887 break;
1888
1889 /* default */
1890 default: goto err_format;
1891 }
1892
1893 return 0;
1894
1895err_occurred:
1896 return fix_error_int(fmt);
1897err_range:
1898 return value_error_int(fmt);
1899err_format:
1900 PyErr_Format(PyExc_NotImplementedError,
1901 "memoryview: format %s not supported", fmt);
1902 return -1;
1903}
1904
1905
1906/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001907/* unpack using the struct module */
1908/****************************************************************************/
1909
1910/* For reasonable performance it is necessary to cache all objects required
1911 for unpacking. An unpacker can handle the format passed to unpack_from().
1912 Invariant: All pointer fields of the struct should either be NULL or valid
1913 pointers. */
1914struct unpacker {
1915 PyObject *unpack_from; /* Struct.unpack_from(format) */
1916 PyObject *mview; /* cached memoryview */
1917 char *item; /* buffer for mview */
1918 Py_ssize_t itemsize; /* len(item) */
1919};
1920
1921static struct unpacker *
1922unpacker_new(void)
1923{
1924 struct unpacker *x = PyMem_Malloc(sizeof *x);
1925
1926 if (x == NULL) {
1927 PyErr_NoMemory();
1928 return NULL;
1929 }
1930
1931 x->unpack_from = NULL;
1932 x->mview = NULL;
1933 x->item = NULL;
1934 x->itemsize = 0;
1935
1936 return x;
1937}
1938
1939static void
1940unpacker_free(struct unpacker *x)
1941{
1942 if (x) {
1943 Py_XDECREF(x->unpack_from);
1944 Py_XDECREF(x->mview);
1945 PyMem_Free(x->item);
1946 PyMem_Free(x);
1947 }
1948}
1949
1950/* Return a new unpacker for the given format. */
1951static struct unpacker *
1952struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1953{
1954 PyObject *structmodule; /* XXX cache these two */
1955 PyObject *Struct = NULL; /* XXX in globals? */
1956 PyObject *structobj = NULL;
1957 PyObject *format = NULL;
1958 struct unpacker *x = NULL;
1959
1960 structmodule = PyImport_ImportModule("struct");
1961 if (structmodule == NULL)
1962 return NULL;
1963
1964 Struct = PyObject_GetAttrString(structmodule, "Struct");
1965 Py_DECREF(structmodule);
1966 if (Struct == NULL)
1967 return NULL;
1968
1969 x = unpacker_new();
1970 if (x == NULL)
1971 goto error;
1972
1973 format = PyBytes_FromString(fmt);
1974 if (format == NULL)
1975 goto error;
1976
Petr Viktorinffd97532020-02-11 17:46:57 +01001977 structobj = PyObject_CallOneArg(Struct, format);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001978 if (structobj == NULL)
1979 goto error;
1980
1981 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1982 if (x->unpack_from == NULL)
1983 goto error;
1984
1985 x->item = PyMem_Malloc(itemsize);
1986 if (x->item == NULL) {
1987 PyErr_NoMemory();
1988 goto error;
1989 }
1990 x->itemsize = itemsize;
1991
1992 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1993 if (x->mview == NULL)
1994 goto error;
1995
1996
1997out:
1998 Py_XDECREF(Struct);
1999 Py_XDECREF(format);
2000 Py_XDECREF(structobj);
2001 return x;
2002
2003error:
2004 unpacker_free(x);
2005 x = NULL;
2006 goto out;
2007}
2008
2009/* unpack a single item */
2010static PyObject *
2011struct_unpack_single(const char *ptr, struct unpacker *x)
2012{
2013 PyObject *v;
2014
2015 memcpy(x->item, ptr, x->itemsize);
Petr Viktorinffd97532020-02-11 17:46:57 +01002016 v = PyObject_CallOneArg(x->unpack_from, x->mview);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002017 if (v == NULL)
2018 return NULL;
2019
2020 if (PyTuple_GET_SIZE(v) == 1) {
2021 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2022 Py_INCREF(tmp);
2023 Py_DECREF(v);
2024 return tmp;
2025 }
2026
2027 return v;
2028}
2029
2030
2031/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002032/* Representations */
2033/****************************************************************************/
2034
2035/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002036static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002037adjust_fmt(const Py_buffer *view)
2038{
2039 const char *fmt;
2040
2041 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2042 if (fmt[0] && fmt[1] == '\0')
2043 return fmt;
2044
2045 PyErr_Format(PyExc_NotImplementedError,
2046 "memoryview: unsupported format %s", view->format);
2047 return NULL;
2048}
2049
2050/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2051static PyObject *
2052tolist_base(const char *ptr, const Py_ssize_t *shape,
2053 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2054 const char *fmt)
2055{
2056 PyObject *lst, *item;
2057 Py_ssize_t i;
2058
2059 lst = PyList_New(shape[0]);
2060 if (lst == NULL)
2061 return NULL;
2062
2063 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002064 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002065 item = unpack_single(xptr, fmt);
2066 if (item == NULL) {
2067 Py_DECREF(lst);
2068 return NULL;
2069 }
2070 PyList_SET_ITEM(lst, i, item);
2071 }
2072
2073 return lst;
2074}
2075
2076/* Unpack a multi-dimensional array into a nested list.
2077 Assumption: ndim >= 1. */
2078static PyObject *
2079tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2080 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2081 const char *fmt)
2082{
2083 PyObject *lst, *item;
2084 Py_ssize_t i;
2085
2086 assert(ndim >= 1);
2087 assert(shape != NULL);
2088 assert(strides != NULL);
2089
2090 if (ndim == 1)
2091 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2092
2093 lst = PyList_New(shape[0]);
2094 if (lst == NULL)
2095 return NULL;
2096
2097 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002098 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002099 item = tolist_rec(xptr, ndim-1, shape+1,
2100 strides+1, suboffsets ? suboffsets+1 : NULL,
2101 fmt);
2102 if (item == NULL) {
2103 Py_DECREF(lst);
2104 return NULL;
2105 }
2106 PyList_SET_ITEM(lst, i, item);
2107 }
2108
2109 return lst;
2110}
2111
2112/* Return a list representation of the memoryview. Currently only buffers
2113 with native format strings are supported. */
2114static PyObject *
2115memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2116{
2117 const Py_buffer *view = &(mv->view);
2118 const char *fmt;
2119
2120 CHECK_RELEASED(mv);
2121
2122 fmt = adjust_fmt(view);
2123 if (fmt == NULL)
2124 return NULL;
2125 if (view->ndim == 0) {
2126 return unpack_single(view->buf, fmt);
2127 }
2128 else if (view->ndim == 1) {
2129 return tolist_base(view->buf, view->shape,
2130 view->strides, view->suboffsets,
2131 fmt);
2132 }
2133 else {
2134 return tolist_rec(view->buf, view->ndim, view->shape,
2135 view->strides, view->suboffsets,
2136 fmt);
2137 }
2138}
2139
2140static PyObject *
Stefan Krahd08ea702019-02-02 18:57:41 +01002141memory_tobytes(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002142{
Stefan Krahd08ea702019-02-02 18:57:41 +01002143 static char *kwlist[] = {"order", NULL};
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002144 Py_buffer *src = VIEW_ADDR(self);
Stefan Krahd08ea702019-02-02 18:57:41 +01002145 char *order = NULL;
2146 char ord = 'C';
2147 PyObject *bytes;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002148
2149 CHECK_RELEASED(self);
2150
Stefan Krahd08ea702019-02-02 18:57:41 +01002151 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z", kwlist, &order)) {
2152 return NULL;
2153 }
2154
2155 if (order) {
2156 if (strcmp(order, "F") == 0) {
2157 ord = 'F';
2158 }
2159 else if (strcmp(order, "A") == 0) {
2160 ord = 'A';
2161 }
2162 else if (strcmp(order, "C") != 0) {
2163 PyErr_SetString(PyExc_ValueError,
2164 "order must be 'C', 'F' or 'A'");
2165 return NULL;
2166 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002167 }
2168
2169 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2170 if (bytes == NULL)
2171 return NULL;
2172
Stefan Krahd08ea702019-02-02 18:57:41 +01002173 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, ord) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002174 Py_DECREF(bytes);
2175 return NULL;
2176 }
2177
2178 return bytes;
2179}
2180
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002181/*[clinic input]
2182memoryview.hex
2183
2184 sep: object = NULL
2185 An optional single character or byte to separate hex bytes.
2186 bytes_per_sep: int = 1
2187 How many bytes between separators. Positive values count from the
2188 right, negative values count from the left.
2189
2190Return the data in the buffer as a str of hexadecimal numbers.
2191
2192Example:
2193>>> value = memoryview(b'\xb9\x01\xef')
2194>>> value.hex()
2195'b901ef'
2196>>> value.hex(':')
2197'b9:01:ef'
2198>>> value.hex(':', 2)
2199'b9:01ef'
2200>>> value.hex(':', -2)
2201'b901:ef'
2202[clinic start generated code]*/
2203
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002204static PyObject *
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002205memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
2206 int bytes_per_sep)
2207/*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002208{
2209 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002210 PyObject *bytes;
2211 PyObject *ret;
2212
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002213 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002214
2215 if (MV_C_CONTIGUOUS(self->flags)) {
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002216 return _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002217 }
2218
Stefan Krahd08ea702019-02-02 18:57:41 +01002219 bytes = PyBytes_FromStringAndSize(NULL, src->len);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002220 if (bytes == NULL)
2221 return NULL;
2222
Stefan Krahd08ea702019-02-02 18:57:41 +01002223 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, 'C') < 0) {
2224 Py_DECREF(bytes);
2225 return NULL;
2226 }
2227
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002228 ret = _Py_strhex_with_sep(
2229 PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes),
2230 sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002231 Py_DECREF(bytes);
2232
2233 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002234}
2235
2236static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002237memory_repr(PyMemoryViewObject *self)
2238{
2239 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2240 return PyUnicode_FromFormat("<released memory at %p>", self);
2241 else
2242 return PyUnicode_FromFormat("<memory at %p>", self);
2243}
2244
2245
2246/**************************************************************************/
2247/* Indexing and slicing */
2248/**************************************************************************/
2249
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002250static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002251lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002252{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002253 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002254
2255 assert(view->shape);
2256 assert(view->strides);
2257
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002258 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002259 if (index < 0) {
2260 index += nitems;
2261 }
2262 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002263 PyErr_Format(PyExc_IndexError,
2264 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002265 return NULL;
2266 }
2267
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002268 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002269
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002270 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002271
2272 return ptr;
2273}
2274
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002275/* Get the pointer to the item at index. */
2276static char *
2277ptr_from_index(Py_buffer *view, Py_ssize_t index)
2278{
2279 char *ptr = (char *)view->buf;
2280 return lookup_dimension(view, ptr, 0, index);
2281}
2282
2283/* Get the pointer to the item at tuple. */
2284static char *
2285ptr_from_tuple(Py_buffer *view, PyObject *tup)
2286{
2287 char *ptr = (char *)view->buf;
2288 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2289
2290 if (nindices > view->ndim) {
2291 PyErr_Format(PyExc_TypeError,
2292 "cannot index %zd-dimension view with %zd-element tuple",
2293 view->ndim, nindices);
2294 return NULL;
2295 }
2296
2297 for (dim = 0; dim < nindices; dim++) {
2298 Py_ssize_t index;
2299 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2300 PyExc_IndexError);
2301 if (index == -1 && PyErr_Occurred())
2302 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002303 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002304 if (ptr == NULL)
2305 return NULL;
2306 }
2307 return ptr;
2308}
2309
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002310/* Return the item at index. In a one-dimensional view, this is an object
2311 with the type specified by view->format. Otherwise, the item is a sub-view.
2312 The function is used in memory_subscript() and memory_as_sequence. */
2313static PyObject *
2314memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2315{
2316 Py_buffer *view = &(self->view);
2317 const char *fmt;
2318
2319 CHECK_RELEASED(self);
2320
2321 fmt = adjust_fmt(view);
2322 if (fmt == NULL)
2323 return NULL;
2324
2325 if (view->ndim == 0) {
2326 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2327 return NULL;
2328 }
2329 if (view->ndim == 1) {
2330 char *ptr = ptr_from_index(view, index);
2331 if (ptr == NULL)
2332 return NULL;
2333 return unpack_single(ptr, fmt);
2334 }
2335
2336 PyErr_SetString(PyExc_NotImplementedError,
2337 "multi-dimensional sub-views are not implemented");
2338 return NULL;
2339}
2340
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002341/* Return the item at position *key* (a tuple of indices). */
2342static PyObject *
2343memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2344{
2345 Py_buffer *view = &(self->view);
2346 const char *fmt;
2347 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2348 char *ptr;
2349
2350 CHECK_RELEASED(self);
2351
2352 fmt = adjust_fmt(view);
2353 if (fmt == NULL)
2354 return NULL;
2355
2356 if (nindices < view->ndim) {
2357 PyErr_SetString(PyExc_NotImplementedError,
2358 "sub-views are not implemented");
2359 return NULL;
2360 }
2361 ptr = ptr_from_tuple(view, tup);
2362 if (ptr == NULL)
2363 return NULL;
2364 return unpack_single(ptr, fmt);
2365}
2366
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002367static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002368init_slice(Py_buffer *base, PyObject *key, int dim)
2369{
2370 Py_ssize_t start, stop, step, slicelength;
2371
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002372 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002373 return -1;
2374 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002375 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002376
2377
2378 if (base->suboffsets == NULL || dim == 0) {
2379 adjust_buf:
2380 base->buf = (char *)base->buf + base->strides[dim] * start;
2381 }
2382 else {
2383 Py_ssize_t n = dim-1;
2384 while (n >= 0 && base->suboffsets[n] < 0)
2385 n--;
2386 if (n < 0)
2387 goto adjust_buf; /* all suboffsets are negative */
2388 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2389 }
2390 base->shape[dim] = slicelength;
2391 base->strides[dim] = base->strides[dim] * step;
2392
2393 return 0;
2394}
2395
2396static int
2397is_multislice(PyObject *key)
2398{
2399 Py_ssize_t size, i;
2400
2401 if (!PyTuple_Check(key))
2402 return 0;
2403 size = PyTuple_GET_SIZE(key);
2404 if (size == 0)
2405 return 0;
2406
2407 for (i = 0; i < size; i++) {
2408 PyObject *x = PyTuple_GET_ITEM(key, i);
2409 if (!PySlice_Check(x))
2410 return 0;
2411 }
2412 return 1;
2413}
2414
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002415static Py_ssize_t
2416is_multiindex(PyObject *key)
2417{
2418 Py_ssize_t size, i;
2419
2420 if (!PyTuple_Check(key))
2421 return 0;
2422 size = PyTuple_GET_SIZE(key);
2423 for (i = 0; i < size; i++) {
2424 PyObject *x = PyTuple_GET_ITEM(key, i);
Victor Stinnera15e2602020-04-08 02:01:56 +02002425 if (!_PyIndex_Check(x)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002426 return 0;
Victor Stinnera15e2602020-04-08 02:01:56 +02002427 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002428 }
2429 return 1;
2430}
2431
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002432/* mv[obj] returns an object holding the data for one element if obj
2433 fully indexes the memoryview or another memoryview object if it
2434 does not.
2435
2436 0-d memoryview objects can be referenced using mv[...] or mv[()]
2437 but not with anything else. */
2438static PyObject *
2439memory_subscript(PyMemoryViewObject *self, PyObject *key)
2440{
2441 Py_buffer *view;
2442 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002443
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002444 CHECK_RELEASED(self);
2445
2446 if (view->ndim == 0) {
2447 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2448 const char *fmt = adjust_fmt(view);
2449 if (fmt == NULL)
2450 return NULL;
2451 return unpack_single(view->buf, fmt);
2452 }
2453 else if (key == Py_Ellipsis) {
2454 Py_INCREF(self);
2455 return (PyObject *)self;
2456 }
2457 else {
2458 PyErr_SetString(PyExc_TypeError,
2459 "invalid indexing of 0-dim memory");
2460 return NULL;
2461 }
2462 }
2463
Victor Stinnera15e2602020-04-08 02:01:56 +02002464 if (_PyIndex_Check(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002465 Py_ssize_t index;
2466 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2467 if (index == -1 && PyErr_Occurred())
2468 return NULL;
2469 return memory_item(self, index);
2470 }
2471 else if (PySlice_Check(key)) {
2472 PyMemoryViewObject *sliced;
2473
2474 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2475 if (sliced == NULL)
2476 return NULL;
2477
2478 if (init_slice(&sliced->view, key, 0) < 0) {
2479 Py_DECREF(sliced);
2480 return NULL;
2481 }
2482 init_len(&sliced->view);
2483 init_flags(sliced);
2484
2485 return (PyObject *)sliced;
2486 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002487 else if (is_multiindex(key)) {
2488 return memory_item_multi(self, key);
2489 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002490 else if (is_multislice(key)) {
2491 PyErr_SetString(PyExc_NotImplementedError,
2492 "multi-dimensional slicing is not implemented");
2493 return NULL;
2494 }
2495
2496 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2497 return NULL;
2498}
2499
2500static int
2501memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2502{
2503 Py_buffer *view = &(self->view);
2504 Py_buffer src;
2505 const char *fmt;
2506 char *ptr;
2507
2508 CHECK_RELEASED_INT(self);
2509
2510 fmt = adjust_fmt(view);
2511 if (fmt == NULL)
2512 return -1;
2513
2514 if (view->readonly) {
2515 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2516 return -1;
2517 }
2518 if (value == NULL) {
2519 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2520 return -1;
2521 }
2522 if (view->ndim == 0) {
2523 if (key == Py_Ellipsis ||
2524 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2525 ptr = (char *)view->buf;
2526 return pack_single(ptr, value, fmt);
2527 }
2528 else {
2529 PyErr_SetString(PyExc_TypeError,
2530 "invalid indexing of 0-dim memory");
2531 return -1;
2532 }
2533 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002534
Victor Stinnera15e2602020-04-08 02:01:56 +02002535 if (_PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002536 Py_ssize_t index;
2537 if (1 < view->ndim) {
2538 PyErr_SetString(PyExc_NotImplementedError,
2539 "sub-views are not implemented");
2540 return -1;
2541 }
2542 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002543 if (index == -1 && PyErr_Occurred())
2544 return -1;
2545 ptr = ptr_from_index(view, index);
2546 if (ptr == NULL)
2547 return -1;
2548 return pack_single(ptr, value, fmt);
2549 }
2550 /* one-dimensional: fast path */
2551 if (PySlice_Check(key) && view->ndim == 1) {
2552 Py_buffer dest; /* sliced view */
2553 Py_ssize_t arrays[3];
2554 int ret = -1;
2555
2556 /* rvalue must be an exporter */
2557 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2558 return ret;
2559
2560 dest = *view;
2561 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2562 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2563 if (view->suboffsets) {
2564 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2565 }
2566
2567 if (init_slice(&dest, key, 0) < 0)
2568 goto end_block;
2569 dest.len = dest.shape[0] * dest.itemsize;
2570
2571 ret = copy_single(&dest, &src);
2572
2573 end_block:
2574 PyBuffer_Release(&src);
2575 return ret;
2576 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002577 if (is_multiindex(key)) {
2578 char *ptr;
2579 if (PyTuple_GET_SIZE(key) < view->ndim) {
2580 PyErr_SetString(PyExc_NotImplementedError,
2581 "sub-views are not implemented");
2582 return -1;
2583 }
2584 ptr = ptr_from_tuple(view, key);
2585 if (ptr == NULL)
2586 return -1;
2587 return pack_single(ptr, value, fmt);
2588 }
2589 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002590 /* Call memory_subscript() to produce a sliced lvalue, then copy
2591 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2592 PyErr_SetString(PyExc_NotImplementedError,
2593 "memoryview slice assignments are currently restricted "
2594 "to ndim = 1");
2595 return -1;
2596 }
2597
2598 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2599 return -1;
2600}
2601
2602static Py_ssize_t
2603memory_length(PyMemoryViewObject *self)
2604{
2605 CHECK_RELEASED_INT(self);
2606 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2607}
2608
2609/* As mapping */
2610static PyMappingMethods memory_as_mapping = {
2611 (lenfunc)memory_length, /* mp_length */
2612 (binaryfunc)memory_subscript, /* mp_subscript */
2613 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2614};
2615
2616/* As sequence */
2617static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002618 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002619 0, /* sq_concat */
2620 0, /* sq_repeat */
2621 (ssizeargfunc)memory_item, /* sq_item */
2622};
2623
2624
2625/**************************************************************************/
2626/* Comparisons */
2627/**************************************************************************/
2628
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002629#define MV_COMPARE_EX -1 /* exception */
2630#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2631
2632/* Translate a StructError to "not equal". Preserve other exceptions. */
2633static int
2634fix_struct_error_int(void)
2635{
2636 assert(PyErr_Occurred());
2637 /* XXX Cannot get at StructError directly? */
2638 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2639 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2640 return MV_COMPARE_EX;
2641 }
2642 /* StructError: invalid or unknown format -> not equal */
2643 PyErr_Clear();
2644 return 0;
2645}
2646
2647/* Unpack and compare single items of p and q using the struct module. */
2648static int
2649struct_unpack_cmp(const char *p, const char *q,
2650 struct unpacker *unpack_p, struct unpacker *unpack_q)
2651{
2652 PyObject *v, *w;
2653 int ret;
2654
2655 /* At this point any exception from the struct module should not be
2656 StructError, since both formats have been accepted already. */
2657 v = struct_unpack_single(p, unpack_p);
2658 if (v == NULL)
2659 return MV_COMPARE_EX;
2660
2661 w = struct_unpack_single(q, unpack_q);
2662 if (w == NULL) {
2663 Py_DECREF(v);
2664 return MV_COMPARE_EX;
2665 }
2666
2667 /* MV_COMPARE_EX == -1: exceptions are preserved */
2668 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2669 Py_DECREF(v);
2670 Py_DECREF(w);
2671
2672 return ret;
2673}
2674
2675/* Unpack and compare single items of p and q. If both p and q have the same
2676 single element native format, the comparison uses a fast path (gcc creates
2677 a jump table and converts memcpy into simple assignments on x86/x64).
2678
2679 Otherwise, the comparison is delegated to the struct module, which is
2680 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002681#define CMP_SINGLE(p, q, type) \
2682 do { \
2683 type x; \
2684 type y; \
2685 memcpy((char *)&x, p, sizeof x); \
2686 memcpy((char *)&y, q, sizeof y); \
2687 equal = (x == y); \
2688 } while (0)
2689
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002690static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002691unpack_cmp(const char *p, const char *q, char fmt,
2692 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002693{
2694 int equal;
2695
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002696 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002697
2698 /* signed integers and fast path for 'B' */
Andy Lestere6be9b52020-02-11 20:28:35 -06002699 case 'B': return *((const unsigned char *)p) == *((const unsigned char *)q);
2700 case 'b': return *((const signed char *)p) == *((const signed char *)q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002701 case 'h': CMP_SINGLE(p, q, short); return equal;
2702 case 'i': CMP_SINGLE(p, q, int); return equal;
2703 case 'l': CMP_SINGLE(p, q, long); return equal;
2704
2705 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002706 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002707
2708 /* unsigned integers */
2709 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2710 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2711 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2712
2713 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002714 case 'q': CMP_SINGLE(p, q, long long); return equal;
2715 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002716
2717 /* ssize_t and size_t */
2718 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2719 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2720
2721 /* floats */
2722 /* XXX DBL_EPSILON? */
2723 case 'f': CMP_SINGLE(p, q, float); return equal;
2724 case 'd': CMP_SINGLE(p, q, double); return equal;
2725
2726 /* bytes object */
2727 case 'c': return *p == *q;
2728
2729 /* pointer */
2730 case 'P': CMP_SINGLE(p, q, void *); return equal;
2731
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002732 /* use the struct module */
2733 case '_':
2734 assert(unpack_p);
2735 assert(unpack_q);
2736 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002737 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002738
2739 /* NOT REACHED */
2740 PyErr_SetString(PyExc_RuntimeError,
2741 "memoryview: internal error in richcompare");
2742 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002743}
2744
2745/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2746static int
2747cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2748 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2749 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002750 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002751{
2752 Py_ssize_t i;
2753 int equal;
2754
2755 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002756 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2757 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002758 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002759 if (equal <= 0)
2760 return equal;
2761 }
2762
2763 return 1;
2764}
2765
2766/* Recursively compare two multi-dimensional arrays that have the same
2767 logical structure. Assumption: ndim >= 1. */
2768static int
2769cmp_rec(const char *p, const char *q,
2770 Py_ssize_t ndim, const Py_ssize_t *shape,
2771 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2772 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002773 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002774{
2775 Py_ssize_t i;
2776 int equal;
2777
2778 assert(ndim >= 1);
2779 assert(shape != NULL);
2780 assert(pstrides != NULL);
2781 assert(qstrides != NULL);
2782
2783 if (ndim == 1) {
2784 return cmp_base(p, q, shape,
2785 pstrides, psuboffsets,
2786 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002787 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002788 }
2789
2790 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002791 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2792 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002793 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2794 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2795 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002796 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002797 if (equal <= 0)
2798 return equal;
2799 }
2800
2801 return 1;
2802}
2803
2804static PyObject *
2805memory_richcompare(PyObject *v, PyObject *w, int op)
2806{
2807 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002808 Py_buffer wbuf, *vv;
2809 Py_buffer *ww = NULL;
2810 struct unpacker *unpack_v = NULL;
2811 struct unpacker *unpack_w = NULL;
2812 char vfmt, wfmt;
2813 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002814
2815 if (op != Py_EQ && op != Py_NE)
2816 goto result; /* Py_NotImplemented */
2817
2818 assert(PyMemoryView_Check(v));
2819 if (BASE_INACCESSIBLE(v)) {
2820 equal = (v == w);
2821 goto result;
2822 }
2823 vv = VIEW_ADDR(v);
2824
2825 if (PyMemoryView_Check(w)) {
2826 if (BASE_INACCESSIBLE(w)) {
2827 equal = (v == w);
2828 goto result;
2829 }
2830 ww = VIEW_ADDR(w);
2831 }
2832 else {
2833 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2834 PyErr_Clear();
2835 goto result; /* Py_NotImplemented */
2836 }
2837 ww = &wbuf;
2838 }
2839
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002840 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002841 PyErr_Clear();
2842 equal = 0;
2843 goto result;
2844 }
2845
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002846 /* Use fast unpacking for identical primitive C type formats. */
2847 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2848 vfmt = '_';
2849 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2850 wfmt = '_';
2851 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2852 /* Use struct module unpacking. NOTE: Even for equal format strings,
2853 memcmp() cannot be used for item comparison since it would give
2854 incorrect results in the case of NaNs or uninitialized padding
2855 bytes. */
2856 vfmt = '_';
2857 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2858 if (unpack_v == NULL) {
2859 equal = fix_struct_error_int();
2860 goto result;
2861 }
2862 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2863 if (unpack_w == NULL) {
2864 equal = fix_struct_error_int();
2865 goto result;
2866 }
2867 }
2868
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002869 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002870 equal = unpack_cmp(vv->buf, ww->buf,
2871 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002872 }
2873 else if (vv->ndim == 1) {
2874 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2875 vv->strides, vv->suboffsets,
2876 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002877 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002878 }
2879 else {
2880 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2881 vv->strides, vv->suboffsets,
2882 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002883 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002884 }
2885
2886result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002887 if (equal < 0) {
2888 if (equal == MV_COMPARE_NOT_IMPL)
2889 res = Py_NotImplemented;
2890 else /* exception */
2891 res = NULL;
2892 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002893 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2894 res = Py_True;
2895 else
2896 res = Py_False;
2897
2898 if (ww == &wbuf)
2899 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002900
2901 unpacker_free(unpack_v);
2902 unpacker_free(unpack_w);
2903
2904 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002905 return res;
2906}
2907
2908/**************************************************************************/
2909/* Hash */
2910/**************************************************************************/
2911
2912static Py_hash_t
2913memory_hash(PyMemoryViewObject *self)
2914{
2915 if (self->hash == -1) {
2916 Py_buffer *view = &self->view;
2917 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002918 Py_ssize_t ret;
2919 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002920
2921 CHECK_RELEASED_INT(self);
2922
2923 if (!view->readonly) {
2924 PyErr_SetString(PyExc_ValueError,
2925 "cannot hash writable memoryview object");
2926 return -1;
2927 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002928 ret = get_native_fmtchar(&fmt, view->format);
2929 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2930 PyErr_SetString(PyExc_ValueError,
2931 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2932 return -1;
2933 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002934 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2935 /* Keep the original error message */
2936 return -1;
2937 }
2938
2939 if (!MV_C_CONTIGUOUS(self->flags)) {
2940 mem = PyMem_Malloc(view->len);
2941 if (mem == NULL) {
2942 PyErr_NoMemory();
2943 return -1;
2944 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002945 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002946 PyMem_Free(mem);
2947 return -1;
2948 }
2949 }
2950
2951 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002952 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002953
2954 if (mem != view->buf)
2955 PyMem_Free(mem);
2956 }
2957
2958 return self->hash;
2959}
2960
2961
2962/**************************************************************************/
2963/* getters */
2964/**************************************************************************/
2965
2966static PyObject *
2967_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2968{
2969 int i;
2970 PyObject *o;
2971 PyObject *intTuple;
2972
2973 if (vals == NULL)
2974 return PyTuple_New(0);
2975
2976 intTuple = PyTuple_New(len);
2977 if (!intTuple)
2978 return NULL;
2979 for (i=0; i<len; i++) {
2980 o = PyLong_FromSsize_t(vals[i]);
2981 if (!o) {
2982 Py_DECREF(intTuple);
2983 return NULL;
2984 }
2985 PyTuple_SET_ITEM(intTuple, i, o);
2986 }
2987 return intTuple;
2988}
2989
2990static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002991memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002992{
2993 Py_buffer *view = &self->view;
2994
2995 CHECK_RELEASED(self);
2996 if (view->obj == NULL) {
2997 Py_RETURN_NONE;
2998 }
2999 Py_INCREF(view->obj);
3000 return view->obj;
3001}
3002
3003static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003004memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003005{
3006 CHECK_RELEASED(self);
3007 return PyLong_FromSsize_t(self->view.len);
3008}
3009
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003010static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003011memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003012{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003013 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003014 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003015}
3016
3017static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003018memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003019{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003020 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003021 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003022}
3023
3024static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003025memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003026{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003027 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003028 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003029}
3030
3031static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003032memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003033{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003034 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003035 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003036}
3037
3038static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003039memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003040{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003041 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003042 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003043}
3044
3045static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003046memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003047{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003048 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003049 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003050}
3051
3052static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003053memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003054{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003055 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003056 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003057}
3058
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003059static PyObject *
3060memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3061{
3062 CHECK_RELEASED(self);
3063 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3064}
3065
3066static PyObject *
3067memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3068{
3069 CHECK_RELEASED(self);
3070 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3071}
3072
3073static PyObject *
3074memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3075{
3076 CHECK_RELEASED(self);
3077 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3078}
3079
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003080PyDoc_STRVAR(memory_obj_doc,
3081 "The underlying object of the memoryview.");
3082PyDoc_STRVAR(memory_nbytes_doc,
3083 "The amount of space in bytes that the array would use in\n"
3084 " a contiguous representation.");
3085PyDoc_STRVAR(memory_readonly_doc,
3086 "A bool indicating whether the memory is read only.");
3087PyDoc_STRVAR(memory_itemsize_doc,
3088 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003089PyDoc_STRVAR(memory_format_doc,
3090 "A string containing the format (in struct module style)\n"
3091 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003092PyDoc_STRVAR(memory_ndim_doc,
3093 "An integer indicating how many dimensions of a multi-dimensional\n"
3094 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003095PyDoc_STRVAR(memory_shape_doc,
3096 "A tuple of ndim integers giving the shape of the memory\n"
3097 " as an N-dimensional array.");
3098PyDoc_STRVAR(memory_strides_doc,
3099 "A tuple of ndim integers giving the size in bytes to access\n"
3100 " each element for each dimension of the array.");
3101PyDoc_STRVAR(memory_suboffsets_doc,
3102 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003103PyDoc_STRVAR(memory_c_contiguous_doc,
3104 "A bool indicating whether the memory is C contiguous.");
3105PyDoc_STRVAR(memory_f_contiguous_doc,
3106 "A bool indicating whether the memory is Fortran contiguous.");
3107PyDoc_STRVAR(memory_contiguous_doc,
3108 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003109
Stefan Krahbcaf5992014-05-18 00:35:09 +02003110
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003111static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003112 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3113 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003114 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3115 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3116 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3117 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3118 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3119 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3120 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003121 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3122 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3123 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003124 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003125};
3126
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003127PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003128"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003129\n\
3130Release the underlying buffer exposed by the memoryview object.");
3131PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahd08ea702019-02-02 18:57:41 +01003132"tobytes($self, /, order=None)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003133\n\
Stefan Krahd08ea702019-02-02 18:57:41 +01003134Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
3135When order is 'C' or 'F', the data of the original array is converted to C or\n\
3136Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
3137memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
3138views, the data is converted to C first. order=None is the same as order='C'.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003139PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003140"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003141\n\
3142Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003143PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003144"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003145\n\
3146Cast a memoryview to a new format or shape.");
Antoine Pitrou480ab052018-04-14 19:49:21 +02003147PyDoc_STRVAR(memory_toreadonly_doc,
3148"toreadonly($self, /)\n--\n\
3149\n\
3150Return a readonly version of the memoryview.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003151
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003152static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003153 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
Stéphane Wirtel359a2f32019-03-05 16:10:53 +01003154 {"tobytes", (PyCFunction)(void(*)(void))memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07003155 MEMORYVIEW_HEX_METHODDEF
Alexander Belopolskye370c382012-09-03 16:43:55 -04003156 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02003157 {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Antoine Pitrou480ab052018-04-14 19:49:21 +02003158 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003159 {"__enter__", memory_enter, METH_NOARGS, NULL},
3160 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003161 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003162};
3163
3164
3165PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003166 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003167 "memoryview", /* tp_name */
3168 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3169 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003170 (destructor)memory_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003171 0, /* tp_vectorcall_offset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003172 0, /* tp_getattr */
3173 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003174 0, /* tp_as_async */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003175 (reprfunc)memory_repr, /* tp_repr */
3176 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003177 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003178 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003179 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003180 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003181 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003182 PyObject_GenericGetAttr, /* tp_getattro */
3183 0, /* tp_setattro */
3184 &memory_as_buffer, /* tp_as_buffer */
3185 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3186 memory_doc, /* tp_doc */
3187 (traverseproc)memory_traverse, /* tp_traverse */
3188 (inquiry)memory_clear, /* tp_clear */
3189 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003190 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003191 0, /* tp_iter */
3192 0, /* tp_iternext */
3193 memory_methods, /* tp_methods */
3194 0, /* tp_members */
3195 memory_getsetlist, /* tp_getset */
3196 0, /* tp_base */
3197 0, /* tp_dict */
3198 0, /* tp_descr_get */
3199 0, /* tp_descr_set */
3200 0, /* tp_dictoffset */
3201 0, /* tp_init */
3202 0, /* tp_alloc */
3203 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003204};