blob: d328f4d40b7a42c9dacee67c4a40f857acd7c361 [file] [log] [blame]
Stefan Krahee3bac42020-02-24 11:15:26 +01001/*
2 * Memoryview object implementation
3 * --------------------------------
4 *
5 * This implementation is a complete rewrite contributed by Stefan Krah in
6 * Python 3.3. Substantial credit goes to Antoine Pitrou (who had already
7 * fortified and rewritten the previous implementation) and Nick Coghlan
8 * (who came up with the idea of the ManagedBuffer) for analyzing the complex
9 * ownership rules.
10 *
11 */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000012
13#include "Python.h"
Victor Stinnera15e2602020-04-08 02:01:56 +020014#include "pycore_abstract.h" // _PyIndex_Check()
Victor Stinnerbcda8f12018-11-21 22:27:47 +010015#include "pycore_object.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +000016#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +010017#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000018
Gregory P. Smith0c2f9302019-05-29 11:46:58 -070019/*[clinic input]
20class memoryview "PyMemoryViewObject *" "&PyMemoryView_Type"
21[clinic start generated code]*/
22/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2e49d2192835219]*/
23
24#include "clinic/memoryobject.c.h"
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000025
Stefan Krah9a2d99e2012-02-25 12:24:21 +010026/****************************************************************************/
27/* ManagedBuffer Object */
28/****************************************************************************/
29
30/*
31 ManagedBuffer Object:
32 ---------------------
33
34 The purpose of this object is to facilitate the handling of chained
35 memoryviews that have the same underlying exporting object. PEP-3118
36 allows the underlying object to change while a view is exported. This
37 could lead to unexpected results when constructing a new memoryview
38 from an existing memoryview.
39
40 Rather than repeatedly redirecting buffer requests to the original base
41 object, all chained memoryviews use a single buffer snapshot. This
42 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
43
44 Ownership rules:
45 ----------------
46
47 The master buffer inside a managed buffer is filled in by the original
48 base object. shape, strides, suboffsets and format are read-only for
49 all consumers.
50
51 A memoryview's buffer is a private copy of the exporter's buffer. shape,
52 strides and suboffsets belong to the memoryview and are thus writable.
53
54 If a memoryview itself exports several buffers via memory_getbuf(), all
55 buffer copies share shape, strides and suboffsets. In this case, the
56 arrays are NOT writable.
57
58 Reference count assumptions:
59 ----------------------------
60
61 The 'obj' member of a Py_buffer must either be NULL or refer to the
62 exporting base object. In the Python codebase, all getbufferprocs
63 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
64
65 PyBuffer_Release() decrements view.obj (if non-NULL), so the
66 releasebufferprocs must NOT decrement view.obj.
67*/
68
69
Stefan Krah9a2d99e2012-02-25 12:24:21 +010070#define CHECK_MBUF_RELEASED(mbuf) \
71 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
72 PyErr_SetString(PyExc_ValueError, \
73 "operation forbidden on released memoryview object"); \
74 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000075 }
76
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000077
Benjamin Peterson82cce4c2016-09-08 11:56:06 -070078static inline _PyManagedBufferObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +010079mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000080{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010081 _PyManagedBufferObject *mbuf;
82
83 mbuf = (_PyManagedBufferObject *)
84 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
85 if (mbuf == NULL)
86 return NULL;
87 mbuf->flags = 0;
88 mbuf->exports = 0;
89 mbuf->master.obj = NULL;
90 _PyObject_GC_TRACK(mbuf);
91
92 return mbuf;
93}
94
95static PyObject *
96_PyManagedBuffer_FromObject(PyObject *base)
97{
98 _PyManagedBufferObject *mbuf;
99
100 mbuf = mbuf_alloc();
101 if (mbuf == NULL)
102 return NULL;
103
104 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +0100105 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100106 Py_DECREF(mbuf);
107 return NULL;
108 }
109
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100110 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000111}
112
113static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100114mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000115{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100116 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
117 return;
118
119 /* NOTE: at this point self->exports can still be > 0 if this function
120 is called from mbuf_clear() to break up a reference cycle. */
121 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
122
123 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
124 _PyObject_GC_UNTRACK(self);
125 PyBuffer_Release(&self->master);
126}
127
128static void
129mbuf_dealloc(_PyManagedBufferObject *self)
130{
131 assert(self->exports == 0);
132 mbuf_release(self);
133 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
134 PyMem_Free(self->master.format);
135 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000136}
137
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000138static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100139mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000140{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100141 Py_VISIT(self->master.obj);
142 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000143}
144
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100145static int
146mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000147{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100148 assert(self->exports >= 0);
149 mbuf_release(self);
150 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000151}
152
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100153PyTypeObject _PyManagedBuffer_Type = {
154 PyVarObject_HEAD_INIT(&PyType_Type, 0)
155 "managedbuffer",
156 sizeof(_PyManagedBufferObject),
157 0,
158 (destructor)mbuf_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200159 0, /* tp_vectorcall_offset */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100160 0, /* tp_getattr */
161 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200162 0, /* tp_as_async */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100163 0, /* tp_repr */
164 0, /* tp_as_number */
165 0, /* tp_as_sequence */
166 0, /* tp_as_mapping */
167 0, /* tp_hash */
168 0, /* tp_call */
169 0, /* tp_str */
170 PyObject_GenericGetAttr, /* tp_getattro */
171 0, /* tp_setattro */
172 0, /* tp_as_buffer */
173 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
174 0, /* tp_doc */
175 (traverseproc)mbuf_traverse, /* tp_traverse */
176 (inquiry)mbuf_clear /* tp_clear */
177};
178
179
180/****************************************************************************/
181/* MemoryView Object */
182/****************************************************************************/
183
184/* In the process of breaking reference cycles mbuf_release() can be
185 called before memory_release(). */
186#define BASE_INACCESSIBLE(mv) \
187 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
188 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
189
190#define CHECK_RELEASED(mv) \
191 if (BASE_INACCESSIBLE(mv)) { \
192 PyErr_SetString(PyExc_ValueError, \
193 "operation forbidden on released memoryview object"); \
194 return NULL; \
195 }
196
197#define CHECK_RELEASED_INT(mv) \
198 if (BASE_INACCESSIBLE(mv)) { \
199 PyErr_SetString(PyExc_ValueError, \
200 "operation forbidden on released memoryview object"); \
201 return -1; \
202 }
203
204#define CHECK_LIST_OR_TUPLE(v) \
205 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
206 PyErr_SetString(PyExc_TypeError, \
207 #v " must be a list or a tuple"); \
208 return NULL; \
209 }
210
211#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
212
213/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100214#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100215/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100216#define ADJUST_PTR(ptr, suboffsets, dim) \
217 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100218
219/* Memoryview buffer properties */
220#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
221#define MV_F_CONTIGUOUS(flags) \
222 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
223#define MV_ANY_CONTIGUOUS(flags) \
224 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
225
226/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
227#define MV_CONTIGUOUS_NDIM1(view) \
228 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
229
230/* getbuffer() requests */
231#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
232#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
233#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
234#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
235#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
236#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
237#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
238#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
239
240
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100241/**************************************************************************/
242/* Copy memoryview buffers */
243/**************************************************************************/
244
245/* The functions in this section take a source and a destination buffer
246 with the same logical structure: format, itemsize, ndim and shape
247 are identical, with ndim > 0.
248
249 NOTE: All buffers are assumed to have PyBUF_FULL information, which
250 is the case for memoryviews! */
251
252
253/* Assumptions: ndim >= 1. The macro tests for a corner case that should
254 perhaps be explicitly forbidden in the PEP. */
255#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
256 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
257
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700258static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000259last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100260{
261 assert(dest->ndim > 0 && src->ndim > 0);
262 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
263 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
264 dest->strides[dest->ndim-1] == dest->itemsize &&
265 src->strides[src->ndim-1] == src->itemsize);
266}
267
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000268/* This is not a general function for determining format equivalence.
269 It is used in copy_single() and copy_buffer() to weed out non-matching
270 formats. Skipping the '@' character is specifically used in slice
271 assignments, where the lvalue is already known to have a single character
272 format. This is a performance hack that could be rewritten (if properly
273 benchmarked). */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700274static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000275equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100276{
277 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100278
279 assert(dest->format && src->format);
280 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
281 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
282
283 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000284 dest->itemsize != src->itemsize) {
285 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100286 }
287
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000288 return 1;
289}
290
291/* Two shapes are equivalent if they are either equal or identical up
292 to a zero element at the same position. For example, in NumPy arrays
293 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700294static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000295equiv_shape(const Py_buffer *dest, const Py_buffer *src)
296{
297 int i;
298
299 if (dest->ndim != src->ndim)
300 return 0;
301
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100302 for (i = 0; i < dest->ndim; i++) {
303 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000304 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100305 if (dest->shape[i] == 0)
306 break;
307 }
308
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000309 return 1;
310}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100311
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000312/* Check that the logical structure of the destination and source buffers
313 is identical. */
314static int
315equiv_structure(const Py_buffer *dest, const Py_buffer *src)
316{
317 if (!equiv_format(dest, src) ||
318 !equiv_shape(dest, src)) {
319 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100320 "memoryview assignment: lvalue and rvalue have different "
321 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000322 return 0;
323 }
324
325 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100326}
327
328/* Base case for recursive multi-dimensional copying. Contiguous arrays are
329 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
330 sizeof(mem) == shape[0] * itemsize. */
331static void
332copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
333 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
334 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
335 char *mem)
336{
337 if (mem == NULL) { /* contiguous */
338 Py_ssize_t size = shape[0] * itemsize;
339 if (dptr + size < sptr || sptr + size < dptr)
340 memcpy(dptr, sptr, size); /* no overlapping */
341 else
342 memmove(dptr, sptr, size);
343 }
344 else {
345 char *p;
346 Py_ssize_t i;
347 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100348 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100349 memcpy(p, xsptr, itemsize);
350 }
351 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100352 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100353 memcpy(xdptr, p, itemsize);
354 }
355 }
356
357}
358
359/* Recursively copy a source buffer to a destination buffer. The two buffers
360 have the same ndim, shape and itemsize. */
361static void
362copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
363 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
364 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
365 char *mem)
366{
367 Py_ssize_t i;
368
369 assert(ndim >= 1);
370
371 if (ndim == 1) {
372 copy_base(shape, itemsize,
373 dptr, dstrides, dsuboffsets,
374 sptr, sstrides, ssuboffsets,
375 mem);
376 return;
377 }
378
379 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100380 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
381 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100382
383 copy_rec(shape+1, ndim-1, itemsize,
384 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
385 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
386 mem);
387 }
388}
389
390/* Faster copying of one-dimensional arrays. */
391static int
392copy_single(Py_buffer *dest, Py_buffer *src)
393{
394 char *mem = NULL;
395
396 assert(dest->ndim == 1);
397
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000398 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100399 return -1;
400
401 if (!last_dim_is_contiguous(dest, src)) {
402 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
403 if (mem == NULL) {
404 PyErr_NoMemory();
405 return -1;
406 }
407 }
408
409 copy_base(dest->shape, dest->itemsize,
410 dest->buf, dest->strides, dest->suboffsets,
411 src->buf, src->strides, src->suboffsets,
412 mem);
413
414 if (mem)
415 PyMem_Free(mem);
416
417 return 0;
418}
419
420/* Recursively copy src to dest. Both buffers must have the same basic
421 structure. Copying is atomic, the function never fails with a partial
422 copy. */
423static int
424copy_buffer(Py_buffer *dest, Py_buffer *src)
425{
426 char *mem = NULL;
427
428 assert(dest->ndim > 0);
429
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000430 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100431 return -1;
432
433 if (!last_dim_is_contiguous(dest, src)) {
434 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
435 if (mem == NULL) {
436 PyErr_NoMemory();
437 return -1;
438 }
439 }
440
441 copy_rec(dest->shape, dest->ndim, dest->itemsize,
442 dest->buf, dest->strides, dest->suboffsets,
443 src->buf, src->strides, src->suboffsets,
444 mem);
445
446 if (mem)
447 PyMem_Free(mem);
448
449 return 0;
450}
451
452/* Initialize strides for a C-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700453static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100454init_strides_from_shape(Py_buffer *view)
455{
456 Py_ssize_t i;
457
458 assert(view->ndim > 0);
459
460 view->strides[view->ndim-1] = view->itemsize;
461 for (i = view->ndim-2; i >= 0; i--)
462 view->strides[i] = view->strides[i+1] * view->shape[i+1];
463}
464
465/* Initialize strides for a Fortran-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700466static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100467init_fortran_strides_from_shape(Py_buffer *view)
468{
469 Py_ssize_t i;
470
471 assert(view->ndim > 0);
472
473 view->strides[0] = view->itemsize;
474 for (i = 1; i < view->ndim; i++)
475 view->strides[i] = view->strides[i-1] * view->shape[i-1];
476}
477
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200478/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
479 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100480 len(mem) == src->len. */
481static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200482buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100483{
484 Py_buffer dest;
485 Py_ssize_t *strides;
486 int ret;
487
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200488 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100489 assert(src->shape != NULL);
490 assert(src->strides != NULL);
491
492 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
493 if (strides == NULL) {
494 PyErr_NoMemory();
495 return -1;
496 }
497
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200498 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100499 dest = *src;
500 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200501 /* shape is constant and shared: the logical representation of the
502 array is unaltered. */
503
504 /* The physical representation determined by strides (and possibly
505 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100506 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200507 if (order == 'C' || order == 'A') {
508 init_strides_from_shape(&dest);
509 }
510 else {
511 init_fortran_strides_from_shape(&dest);
512 }
513
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100514 dest.suboffsets = NULL;
515
516 ret = copy_buffer(&dest, src);
517
518 PyMem_Free(strides);
519 return ret;
520}
521
522
523/****************************************************************************/
524/* Constructors */
525/****************************************************************************/
526
527/* Initialize values that are shared with the managed buffer. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700528static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100529init_shared_values(Py_buffer *dest, const Py_buffer *src)
530{
531 dest->obj = src->obj;
532 dest->buf = src->buf;
533 dest->len = src->len;
534 dest->itemsize = src->itemsize;
535 dest->readonly = src->readonly;
536 dest->format = src->format ? src->format : "B";
537 dest->internal = src->internal;
538}
539
540/* Copy shape and strides. Reconstruct missing values. */
541static void
542init_shape_strides(Py_buffer *dest, const Py_buffer *src)
543{
544 Py_ssize_t i;
545
546 if (src->ndim == 0) {
547 dest->shape = NULL;
548 dest->strides = NULL;
549 return;
550 }
551 if (src->ndim == 1) {
552 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
553 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
554 return;
555 }
556
557 for (i = 0; i < src->ndim; i++)
558 dest->shape[i] = src->shape[i];
559 if (src->strides) {
560 for (i = 0; i < src->ndim; i++)
561 dest->strides[i] = src->strides[i];
562 }
563 else {
564 init_strides_from_shape(dest);
565 }
566}
567
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700568static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100569init_suboffsets(Py_buffer *dest, const Py_buffer *src)
570{
571 Py_ssize_t i;
572
573 if (src->suboffsets == NULL) {
574 dest->suboffsets = NULL;
575 return;
576 }
577 for (i = 0; i < src->ndim; i++)
578 dest->suboffsets[i] = src->suboffsets[i];
579}
580
581/* len = product(shape) * itemsize */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700582static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100583init_len(Py_buffer *view)
584{
585 Py_ssize_t i, len;
586
587 len = 1;
588 for (i = 0; i < view->ndim; i++)
589 len *= view->shape[i];
590 len *= view->itemsize;
591
592 view->len = len;
593}
594
595/* Initialize memoryview buffer properties. */
596static void
597init_flags(PyMemoryViewObject *mv)
598{
599 const Py_buffer *view = &mv->view;
600 int flags = 0;
601
602 switch (view->ndim) {
603 case 0:
604 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
605 _Py_MEMORYVIEW_FORTRAN);
606 break;
607 case 1:
608 if (MV_CONTIGUOUS_NDIM1(view))
609 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
610 break;
611 default:
612 if (PyBuffer_IsContiguous(view, 'C'))
613 flags |= _Py_MEMORYVIEW_C;
614 if (PyBuffer_IsContiguous(view, 'F'))
615 flags |= _Py_MEMORYVIEW_FORTRAN;
616 break;
617 }
618
619 if (view->suboffsets) {
620 flags |= _Py_MEMORYVIEW_PIL;
621 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
622 }
623
624 mv->flags = flags;
625}
626
627/* Allocate a new memoryview and perform basic initialization. New memoryviews
628 are exclusively created through the mbuf_add functions. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700629static inline PyMemoryViewObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100630memory_alloc(int ndim)
631{
632 PyMemoryViewObject *mv;
633
634 mv = (PyMemoryViewObject *)
635 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
636 if (mv == NULL)
637 return NULL;
638
639 mv->mbuf = NULL;
640 mv->hash = -1;
641 mv->flags = 0;
642 mv->exports = 0;
643 mv->view.ndim = ndim;
644 mv->view.shape = mv->ob_array;
645 mv->view.strides = mv->ob_array + ndim;
646 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100647 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100648
649 _PyObject_GC_TRACK(mv);
650 return mv;
651}
652
653/*
654 Return a new memoryview that is registered with mbuf. If src is NULL,
655 use mbuf->master as the underlying buffer. Otherwise, use src.
656
657 The new memoryview has full buffer information: shape and strides
658 are always present, suboffsets as needed. Arrays are copied to
659 the memoryview's ob_array field.
660 */
661static PyObject *
662mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
663{
664 PyMemoryViewObject *mv;
665 Py_buffer *dest;
666
667 if (src == NULL)
668 src = &mbuf->master;
669
670 if (src->ndim > PyBUF_MAX_NDIM) {
671 PyErr_SetString(PyExc_ValueError,
672 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200673 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100674 return NULL;
675 }
676
677 mv = memory_alloc(src->ndim);
678 if (mv == NULL)
679 return NULL;
680
681 dest = &mv->view;
682 init_shared_values(dest, src);
683 init_shape_strides(dest, src);
684 init_suboffsets(dest, src);
685 init_flags(mv);
686
687 mv->mbuf = mbuf;
688 Py_INCREF(mbuf);
689 mbuf->exports++;
690
691 return (PyObject *)mv;
692}
693
694/* Register an incomplete view: shape, strides, suboffsets and flags still
695 need to be initialized. Use 'ndim' instead of src->ndim to determine the
696 size of the memoryview's ob_array.
697
698 Assumption: ndim <= PyBUF_MAX_NDIM. */
699static PyObject *
700mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
701 int ndim)
702{
703 PyMemoryViewObject *mv;
704 Py_buffer *dest;
705
706 if (src == NULL)
707 src = &mbuf->master;
708
709 assert(ndim <= PyBUF_MAX_NDIM);
710
711 mv = memory_alloc(ndim);
712 if (mv == NULL)
713 return NULL;
714
715 dest = &mv->view;
716 init_shared_values(dest, src);
717
718 mv->mbuf = mbuf;
719 Py_INCREF(mbuf);
720 mbuf->exports++;
721
722 return (PyObject *)mv;
723}
724
725/* Expose a raw memory area as a view of contiguous bytes. flags can be
726 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
727 The memoryview has complete buffer information. */
728PyObject *
729PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
730{
731 _PyManagedBufferObject *mbuf;
732 PyObject *mv;
733 int readonly;
734
735 assert(mem != NULL);
736 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
737
738 mbuf = mbuf_alloc();
739 if (mbuf == NULL)
740 return NULL;
741
742 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
743 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
744 PyBUF_FULL_RO);
745
746 mv = mbuf_add_view(mbuf, NULL);
747 Py_DECREF(mbuf);
748
749 return mv;
750}
751
752/* Create a memoryview from a given Py_buffer. For simple byte views,
753 PyMemoryView_FromMemory() should be used instead.
754 This function is the only entry point that can create a master buffer
755 without full information. Because of this fact init_shape_strides()
756 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000757PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000758PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000759{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100760 _PyManagedBufferObject *mbuf;
761 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000762
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000763 if (info->buf == NULL) {
764 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100765 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000766 return NULL;
767 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100768
769 mbuf = mbuf_alloc();
770 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000771 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100772
773 /* info->obj is either NULL or a borrowed reference. This reference
774 should not be decremented in PyBuffer_Release(). */
775 mbuf->master = *info;
776 mbuf->master.obj = NULL;
777
778 mv = mbuf_add_view(mbuf, NULL);
779 Py_DECREF(mbuf);
780
781 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000782}
783
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100784/* Create a memoryview from an object that implements the buffer protocol.
785 If the object is a memoryview, the new memoryview must be registered
786 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000787PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100788PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000789{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100790 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000791
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100792 if (PyMemoryView_Check(v)) {
793 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
794 CHECK_RELEASED(mv);
795 return mbuf_add_view(mv->mbuf, &mv->view);
796 }
797 else if (PyObject_CheckBuffer(v)) {
798 PyObject *ret;
799 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
800 if (mbuf == NULL)
801 return NULL;
802 ret = mbuf_add_view(mbuf, NULL);
803 Py_DECREF(mbuf);
804 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000805 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000806
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100807 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400808 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100809 Py_TYPE(v)->tp_name);
810 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000811}
812
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100813/* Copy the format string from a base object that might vanish. */
814static int
815mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
816{
817 if (fmt != NULL) {
818 char *cp = PyMem_Malloc(strlen(fmt)+1);
819 if (cp == NULL) {
820 PyErr_NoMemory();
821 return -1;
822 }
823 mbuf->master.format = strcpy(cp, fmt);
824 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
825 }
826
827 return 0;
828}
829
830/*
831 Return a memoryview that is based on a contiguous copy of src.
832 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
833
834 Ownership rules:
835 1) As usual, the returned memoryview has a private copy
836 of src->shape, src->strides and src->suboffsets.
837 2) src->format is copied to the master buffer and released
838 in mbuf_dealloc(). The releasebufferproc of the bytes
839 object is NULL, so it does not matter that mbuf_release()
840 passes the altered format pointer to PyBuffer_Release().
841*/
842static PyObject *
843memory_from_contiguous_copy(Py_buffer *src, char order)
844{
845 _PyManagedBufferObject *mbuf;
846 PyMemoryViewObject *mv;
847 PyObject *bytes;
848 Py_buffer *dest;
849 int i;
850
851 assert(src->ndim > 0);
852 assert(src->shape != NULL);
853
854 bytes = PyBytes_FromStringAndSize(NULL, src->len);
855 if (bytes == NULL)
856 return NULL;
857
858 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
859 Py_DECREF(bytes);
860 if (mbuf == NULL)
861 return NULL;
862
863 if (mbuf_copy_format(mbuf, src->format) < 0) {
864 Py_DECREF(mbuf);
865 return NULL;
866 }
867
868 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
869 Py_DECREF(mbuf);
870 if (mv == NULL)
871 return NULL;
872
873 dest = &mv->view;
874
875 /* shared values are initialized correctly except for itemsize */
876 dest->itemsize = src->itemsize;
877
878 /* shape and strides */
879 for (i = 0; i < src->ndim; i++) {
880 dest->shape[i] = src->shape[i];
881 }
882 if (order == 'C' || order == 'A') {
883 init_strides_from_shape(dest);
884 }
885 else {
886 init_fortran_strides_from_shape(dest);
887 }
888 /* suboffsets */
889 dest->suboffsets = NULL;
890
891 /* flags */
892 init_flags(mv);
893
894 if (copy_buffer(dest, src) < 0) {
895 Py_DECREF(mv);
896 return NULL;
897 }
898
899 return (PyObject *)mv;
900}
901
902/*
903 Return a new memoryview object based on a contiguous exporter with
904 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
905 The logical structure of the input and output buffers is the same
906 (i.e. tolist(input) == tolist(output)), but the physical layout in
907 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200908
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100909 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
910 otherwise it may be writable or read-only.
911
912 If the exporter is already contiguous with the desired target order,
913 the memoryview will be directly based on the exporter.
914
915 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
916 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
917 'F'ortran order otherwise.
918*/
919PyObject *
920PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
921{
922 PyMemoryViewObject *mv;
923 PyObject *ret;
924 Py_buffer *view;
925
926 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
927 assert(order == 'C' || order == 'F' || order == 'A');
928
929 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
930 if (mv == NULL)
931 return NULL;
932
933 view = &mv->view;
934 if (buffertype == PyBUF_WRITE && view->readonly) {
935 PyErr_SetString(PyExc_BufferError,
936 "underlying buffer is not writable");
937 Py_DECREF(mv);
938 return NULL;
939 }
940
941 if (PyBuffer_IsContiguous(view, order))
942 return (PyObject *)mv;
943
944 if (buffertype == PyBUF_WRITE) {
945 PyErr_SetString(PyExc_BufferError,
946 "writable contiguous buffer requested "
947 "for a non-contiguous object.");
948 Py_DECREF(mv);
949 return NULL;
950 }
951
952 ret = memory_from_contiguous_copy(view, order);
953 Py_DECREF(mv);
954 return ret;
955}
956
957
Serhiy Storchaka80a50362020-07-18 11:12:05 +0300958/*[clinic input]
959@classmethod
960memoryview.__new__
961
962 object: object
963
964Create a new memoryview object which references the given object.
965[clinic start generated code]*/
966
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000967static PyObject *
Serhiy Storchaka80a50362020-07-18 11:12:05 +0300968memoryview_impl(PyTypeObject *type, PyObject *object)
969/*[clinic end generated code: output=7de78e184ed66db8 input=f04429eb0bdf8c6e]*/
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000970{
Serhiy Storchaka80a50362020-07-18 11:12:05 +0300971 return PyMemoryView_FromObject(object);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000972}
973
974
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100975/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200976/* Previously in abstract.c */
977/****************************************************************************/
978
979typedef struct {
980 Py_buffer view;
981 Py_ssize_t array[1];
982} Py_buffer_full;
983
984int
985PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
986{
987 Py_buffer_full *fb = NULL;
988 int ret;
989
990 assert(order == 'C' || order == 'F' || order == 'A');
991
992 if (len != src->len) {
993 PyErr_SetString(PyExc_ValueError,
994 "PyBuffer_ToContiguous: len != view->len");
995 return -1;
996 }
997
998 if (PyBuffer_IsContiguous(src, order)) {
999 memcpy((char *)buf, src->buf, len);
1000 return 0;
1001 }
1002
1003 /* buffer_to_contiguous() assumes PyBUF_FULL */
1004 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
1005 if (fb == NULL) {
1006 PyErr_NoMemory();
1007 return -1;
1008 }
1009 fb->view.ndim = src->ndim;
1010 fb->view.shape = fb->array;
1011 fb->view.strides = fb->array + src->ndim;
1012 fb->view.suboffsets = fb->array + 2 * src->ndim;
1013
1014 init_shared_values(&fb->view, src);
1015 init_shape_strides(&fb->view, src);
1016 init_suboffsets(&fb->view, src);
1017
1018 src = &fb->view;
1019
1020 ret = buffer_to_contiguous(buf, src, order);
1021 PyMem_Free(fb);
1022 return ret;
1023}
1024
1025
1026/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001027/* Release/GC management */
1028/****************************************************************************/
1029
1030/* Inform the managed buffer that this particular memoryview will not access
1031 the underlying buffer again. If no other memoryviews are registered with
1032 the managed buffer, the underlying buffer is released instantly and
1033 marked as inaccessible for both the memoryview and the managed buffer.
1034
1035 This function fails if the memoryview itself has exported buffers. */
1036static int
1037_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001038{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001039 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1040 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001041
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001042 if (self->exports == 0) {
1043 self->flags |= _Py_MEMORYVIEW_RELEASED;
1044 assert(self->mbuf->exports > 0);
1045 if (--self->mbuf->exports == 0)
1046 mbuf_release(self->mbuf);
1047 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001048 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001049 if (self->exports > 0) {
1050 PyErr_Format(PyExc_BufferError,
1051 "memoryview has %zd exported buffer%s", self->exports,
1052 self->exports==1 ? "" : "s");
1053 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001054 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001055
Victor Stinner47ee8a62020-01-27 22:37:44 +01001056 PyErr_SetString(PyExc_SystemError,
1057 "_memory_release(): negative export count");
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001058 return -1;
1059}
1060
Serhiy Storchaka80a50362020-07-18 11:12:05 +03001061/*[clinic input]
1062memoryview.release
1063
1064Release the underlying buffer exposed by the memoryview object.
1065[clinic start generated code]*/
1066
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001067static PyObject *
Serhiy Storchaka80a50362020-07-18 11:12:05 +03001068memoryview_release_impl(PyMemoryViewObject *self)
1069/*[clinic end generated code: output=d0b7e3ba95b7fcb9 input=bc71d1d51f4a52f0]*/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001070{
1071 if (_memory_release(self) < 0)
1072 return NULL;
1073 Py_RETURN_NONE;
1074}
1075
1076static void
1077memory_dealloc(PyMemoryViewObject *self)
1078{
1079 assert(self->exports == 0);
1080 _PyObject_GC_UNTRACK(self);
1081 (void)_memory_release(self);
1082 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001083 if (self->weakreflist != NULL)
1084 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001085 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001086}
1087
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001088static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001089memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001090{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001091 Py_VISIT(self->mbuf);
1092 return 0;
1093}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001094
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001095static int
1096memory_clear(PyMemoryViewObject *self)
1097{
1098 (void)_memory_release(self);
1099 Py_CLEAR(self->mbuf);
1100 return 0;
1101}
1102
1103static PyObject *
1104memory_enter(PyObject *self, PyObject *args)
1105{
1106 CHECK_RELEASED(self);
1107 Py_INCREF(self);
1108 return self;
1109}
1110
1111static PyObject *
1112memory_exit(PyObject *self, PyObject *args)
1113{
Serhiy Storchaka80a50362020-07-18 11:12:05 +03001114 return memoryview_release_impl((PyMemoryViewObject *)self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001115}
1116
1117
1118/****************************************************************************/
1119/* Casting format and shape */
1120/****************************************************************************/
1121
1122#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1123
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001124static inline Py_ssize_t
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001125get_native_fmtchar(char *result, const char *fmt)
1126{
1127 Py_ssize_t size = -1;
1128
1129 if (fmt[0] == '@') fmt++;
1130
1131 switch (fmt[0]) {
1132 case 'c': case 'b': case 'B': size = sizeof(char); break;
1133 case 'h': case 'H': size = sizeof(short); break;
1134 case 'i': case 'I': size = sizeof(int); break;
1135 case 'l': case 'L': size = sizeof(long); break;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001136 case 'q': case 'Q': size = sizeof(long long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001137 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1138 case 'f': size = sizeof(float); break;
1139 case 'd': size = sizeof(double); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001140 case '?': size = sizeof(_Bool); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001141 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001142 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001143
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001144 if (size > 0 && fmt[1] == '\0') {
1145 *result = fmt[0];
1146 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001147 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001148
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001149 return -1;
1150}
1151
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001152static inline const char *
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001153get_native_fmtstr(const char *fmt)
1154{
1155 int at = 0;
1156
1157 if (fmt[0] == '@') {
1158 at = 1;
1159 fmt++;
1160 }
1161 if (fmt[0] == '\0' || fmt[1] != '\0') {
1162 return NULL;
1163 }
1164
1165#define RETURN(s) do { return at ? "@" s : s; } while (0)
1166
1167 switch (fmt[0]) {
1168 case 'c': RETURN("c");
1169 case 'b': RETURN("b");
1170 case 'B': RETURN("B");
1171 case 'h': RETURN("h");
1172 case 'H': RETURN("H");
1173 case 'i': RETURN("i");
1174 case 'I': RETURN("I");
1175 case 'l': RETURN("l");
1176 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001177 case 'q': RETURN("q");
1178 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001179 case 'n': RETURN("n");
1180 case 'N': RETURN("N");
1181 case 'f': RETURN("f");
1182 case 'd': RETURN("d");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001183 case '?': RETURN("?");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001184 case 'P': RETURN("P");
1185 }
1186
1187 return NULL;
1188}
1189
1190
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001191/* Cast a memoryview's data type to 'format'. The input array must be
1192 C-contiguous. At least one of input-format, output-format must have
1193 byte size. The output array is 1-D, with the same byte length as the
1194 input array. Thus, view->len must be a multiple of the new itemsize. */
1195static int
1196cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1197{
1198 Py_buffer *view = &mv->view;
1199 PyObject *asciifmt;
1200 char srcchar, destchar;
1201 Py_ssize_t itemsize;
1202 int ret = -1;
1203
1204 assert(view->ndim >= 1);
1205 assert(Py_SIZE(mv) == 3*view->ndim);
1206 assert(view->shape == mv->ob_array);
1207 assert(view->strides == mv->ob_array + view->ndim);
1208 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1209
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001210 asciifmt = PyUnicode_AsASCIIString(format);
1211 if (asciifmt == NULL)
1212 return ret;
1213
1214 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1215 if (itemsize < 0) {
1216 PyErr_SetString(PyExc_ValueError,
1217 "memoryview: destination format must be a native single "
1218 "character format prefixed with an optional '@'");
1219 goto out;
1220 }
1221
Stefan Krah0c515952015-08-08 13:38:10 +02001222 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1223 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001224 PyErr_SetString(PyExc_TypeError,
1225 "memoryview: cannot cast between two non-byte formats");
1226 goto out;
1227 }
1228 if (view->len % itemsize) {
1229 PyErr_SetString(PyExc_TypeError,
1230 "memoryview: length is not a multiple of itemsize");
1231 goto out;
1232 }
1233
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001234 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001235 if (view->format == NULL) {
1236 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1237 PyErr_SetString(PyExc_RuntimeError,
1238 "memoryview: internal error");
1239 goto out;
1240 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001241 view->itemsize = itemsize;
1242
1243 view->ndim = 1;
1244 view->shape[0] = view->len / view->itemsize;
1245 view->strides[0] = view->itemsize;
1246 view->suboffsets = NULL;
1247
1248 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001249
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001250 ret = 0;
1251
1252out:
1253 Py_DECREF(asciifmt);
1254 return ret;
1255}
1256
1257/* The memoryview must have space for 3*len(seq) elements. */
1258static Py_ssize_t
1259copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1260 Py_ssize_t itemsize)
1261{
1262 Py_ssize_t x, i;
1263 Py_ssize_t len = itemsize;
1264
1265 for (i = 0; i < ndim; i++) {
1266 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1267 if (!PyLong_Check(tmp)) {
1268 PyErr_SetString(PyExc_TypeError,
1269 "memoryview.cast(): elements of shape must be integers");
1270 return -1;
1271 }
1272 x = PyLong_AsSsize_t(tmp);
1273 if (x == -1 && PyErr_Occurred()) {
1274 return -1;
1275 }
1276 if (x <= 0) {
1277 /* In general elements of shape may be 0, but not for casting. */
1278 PyErr_Format(PyExc_ValueError,
1279 "memoryview.cast(): elements of shape must be integers > 0");
1280 return -1;
1281 }
1282 if (x > PY_SSIZE_T_MAX / len) {
1283 PyErr_Format(PyExc_ValueError,
1284 "memoryview.cast(): product(shape) > SSIZE_MAX");
1285 return -1;
1286 }
1287 len *= x;
1288 shape[i] = x;
1289 }
1290
1291 return len;
1292}
1293
1294/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1295 If the result array does not have exactly the same byte length as the
1296 input array, raise ValueError. */
1297static int
1298cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1299{
1300 Py_buffer *view = &mv->view;
1301 Py_ssize_t len;
1302
1303 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1304 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1305 assert(view->shape == mv->ob_array);
1306 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1307 assert(view->suboffsets == NULL);
1308
1309 view->ndim = ndim;
1310 if (view->ndim == 0) {
1311 view->shape = NULL;
1312 view->strides = NULL;
1313 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001314 }
1315 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001316 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1317 if (len < 0)
1318 return -1;
1319 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001320 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001321
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001322 if (view->len != len) {
1323 PyErr_SetString(PyExc_TypeError,
1324 "memoryview: product(shape) * itemsize != buffer size");
1325 return -1;
1326 }
1327
1328 init_flags(mv);
1329
1330 return 0;
1331}
1332
1333static int
1334zero_in_shape(PyMemoryViewObject *mv)
1335{
1336 Py_buffer *view = &mv->view;
1337 Py_ssize_t i;
1338
1339 for (i = 0; i < view->ndim; i++)
1340 if (view->shape[i] == 0)
1341 return 1;
1342
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001343 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001344}
1345
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001346/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001347 Cast a copy of 'self' to a different view. The input view must
1348 be C-contiguous. The function always casts the input view to a
1349 1-D output according to 'format'. At least one of input-format,
1350 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001351
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001352 If 'shape' is given, the 1-D view from the previous step will
1353 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001354
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001355 All casts must result in views that will have the exact byte
1356 size of the original input. Otherwise, an error is raised.
1357*/
Serhiy Storchaka80a50362020-07-18 11:12:05 +03001358/*[clinic input]
1359memoryview.cast
1360
1361 format: unicode
1362 shape: object = NULL
1363
1364Cast a memoryview to a new format or shape.
1365[clinic start generated code]*/
1366
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001367static PyObject *
Serhiy Storchaka80a50362020-07-18 11:12:05 +03001368memoryview_cast_impl(PyMemoryViewObject *self, PyObject *format,
1369 PyObject *shape)
1370/*[clinic end generated code: output=bae520b3a389cbab input=138936cc9041b1a3]*/
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001371{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001372 PyMemoryViewObject *mv = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001373 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001374
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001375 CHECK_RELEASED(self);
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
Serhiy Storchaka80a50362020-07-18 11:12:05 +03001420/*[clinic input]
1421memoryview.toreadonly
1422
1423Return a readonly version of the memoryview.
1424[clinic start generated code]*/
1425
Antoine Pitrou480ab052018-04-14 19:49:21 +02001426static PyObject *
Serhiy Storchaka80a50362020-07-18 11:12:05 +03001427memoryview_toreadonly_impl(PyMemoryViewObject *self)
1428/*[clinic end generated code: output=2c7e056f04c99e62 input=dc06d20f19ba236f]*/
Antoine Pitrou480ab052018-04-14 19:49:21 +02001429{
1430 CHECK_RELEASED(self);
1431 /* Even if self is already readonly, we still need to create a new
1432 * object for .release() to work correctly.
1433 */
1434 self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1435 if (self != NULL) {
1436 self->view.readonly = 1;
1437 };
1438 return (PyObject *) self;
1439}
1440
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001441
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001442/**************************************************************************/
1443/* getbuffer */
1444/**************************************************************************/
1445
1446static int
1447memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1448{
1449 Py_buffer *base = &self->view;
1450 int baseflags = self->flags;
1451
1452 CHECK_RELEASED_INT(self);
1453
1454 /* start with complete information */
1455 *view = *base;
1456 view->obj = NULL;
1457
1458 if (REQ_WRITABLE(flags) && base->readonly) {
1459 PyErr_SetString(PyExc_BufferError,
1460 "memoryview: underlying buffer is not writable");
1461 return -1;
1462 }
1463 if (!REQ_FORMAT(flags)) {
1464 /* NULL indicates that the buffer's data type has been cast to 'B'.
1465 view->itemsize is the _previous_ itemsize. If shape is present,
1466 the equality product(shape) * itemsize = len still holds at this
1467 point. The equality calcsize(format) = itemsize does _not_ hold
1468 from here on! */
1469 view->format = NULL;
1470 }
1471
1472 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1473 PyErr_SetString(PyExc_BufferError,
1474 "memoryview: underlying buffer is not C-contiguous");
1475 return -1;
1476 }
1477 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1478 PyErr_SetString(PyExc_BufferError,
1479 "memoryview: underlying buffer is not Fortran contiguous");
1480 return -1;
1481 }
1482 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1483 PyErr_SetString(PyExc_BufferError,
1484 "memoryview: underlying buffer is not contiguous");
1485 return -1;
1486 }
1487 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1488 PyErr_SetString(PyExc_BufferError,
1489 "memoryview: underlying buffer requires suboffsets");
1490 return -1;
1491 }
1492 if (!REQ_STRIDES(flags)) {
1493 if (!MV_C_CONTIGUOUS(baseflags)) {
1494 PyErr_SetString(PyExc_BufferError,
1495 "memoryview: underlying buffer is not C-contiguous");
1496 return -1;
1497 }
1498 view->strides = NULL;
1499 }
1500 if (!REQ_SHAPE(flags)) {
1501 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1502 so base->buf = ndbuf->data. */
1503 if (view->format != NULL) {
1504 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1505 not make sense. */
1506 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001507 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001508 "is present");
1509 return -1;
1510 }
1511 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1512 do _not_ hold from here on! */
1513 view->ndim = 1;
1514 view->shape = NULL;
1515 }
1516
1517
1518 view->obj = (PyObject *)self;
1519 Py_INCREF(view->obj);
1520 self->exports++;
1521
1522 return 0;
1523}
1524
1525static void
1526memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1527{
1528 self->exports--;
1529 return;
1530 /* PyBuffer_Release() decrements view->obj after this function returns. */
1531}
1532
1533/* Buffer methods */
1534static PyBufferProcs memory_as_buffer = {
1535 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1536 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1537};
1538
1539
1540/****************************************************************************/
1541/* Optimized pack/unpack for all native format specifiers */
1542/****************************************************************************/
1543
1544/*
1545 Fix exceptions:
1546 1) Include format string in the error message.
1547 2) OverflowError -> ValueError.
1548 3) The error message from PyNumber_Index() is not ideal.
1549*/
1550static int
1551type_error_int(const char *fmt)
1552{
1553 PyErr_Format(PyExc_TypeError,
1554 "memoryview: invalid type for format '%s'", fmt);
1555 return -1;
1556}
1557
1558static int
1559value_error_int(const char *fmt)
1560{
1561 PyErr_Format(PyExc_ValueError,
1562 "memoryview: invalid value for format '%s'", fmt);
1563 return -1;
1564}
1565
1566static int
1567fix_error_int(const char *fmt)
1568{
1569 assert(PyErr_Occurred());
1570 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1571 PyErr_Clear();
1572 return type_error_int(fmt);
1573 }
1574 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1575 PyErr_ExceptionMatches(PyExc_ValueError)) {
1576 PyErr_Clear();
1577 return value_error_int(fmt);
1578 }
1579
1580 return -1;
1581}
1582
1583/* Accept integer objects or objects with an __index__() method. */
1584static long
1585pylong_as_ld(PyObject *item)
1586{
1587 PyObject *tmp;
1588 long ld;
1589
Serhiy Storchaka5f4b229d2020-05-28 10:33:45 +03001590 tmp = _PyNumber_Index(item);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001591 if (tmp == NULL)
1592 return -1;
1593
1594 ld = PyLong_AsLong(tmp);
1595 Py_DECREF(tmp);
1596 return ld;
1597}
1598
1599static unsigned long
1600pylong_as_lu(PyObject *item)
1601{
1602 PyObject *tmp;
1603 unsigned long lu;
1604
Serhiy Storchaka5f4b229d2020-05-28 10:33:45 +03001605 tmp = _PyNumber_Index(item);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001606 if (tmp == NULL)
1607 return (unsigned long)-1;
1608
1609 lu = PyLong_AsUnsignedLong(tmp);
1610 Py_DECREF(tmp);
1611 return lu;
1612}
1613
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001614static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001615pylong_as_lld(PyObject *item)
1616{
1617 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001618 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001619
Serhiy Storchaka5f4b229d2020-05-28 10:33:45 +03001620 tmp = _PyNumber_Index(item);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001621 if (tmp == NULL)
1622 return -1;
1623
1624 lld = PyLong_AsLongLong(tmp);
1625 Py_DECREF(tmp);
1626 return lld;
1627}
1628
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001629static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001630pylong_as_llu(PyObject *item)
1631{
1632 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001633 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001634
Serhiy Storchaka5f4b229d2020-05-28 10:33:45 +03001635 tmp = _PyNumber_Index(item);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001636 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001637 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001638
1639 llu = PyLong_AsUnsignedLongLong(tmp);
1640 Py_DECREF(tmp);
1641 return llu;
1642}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001643
1644static Py_ssize_t
1645pylong_as_zd(PyObject *item)
1646{
1647 PyObject *tmp;
1648 Py_ssize_t zd;
1649
Serhiy Storchaka5f4b229d2020-05-28 10:33:45 +03001650 tmp = _PyNumber_Index(item);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001651 if (tmp == NULL)
1652 return -1;
1653
1654 zd = PyLong_AsSsize_t(tmp);
1655 Py_DECREF(tmp);
1656 return zd;
1657}
1658
1659static size_t
1660pylong_as_zu(PyObject *item)
1661{
1662 PyObject *tmp;
1663 size_t zu;
1664
Serhiy Storchaka5f4b229d2020-05-28 10:33:45 +03001665 tmp = _PyNumber_Index(item);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001666 if (tmp == NULL)
1667 return (size_t)-1;
1668
1669 zu = PyLong_AsSize_t(tmp);
1670 Py_DECREF(tmp);
1671 return zu;
1672}
1673
1674/* Timings with the ndarray from _testbuffer.c indicate that using the
1675 struct module is around 15x slower than the two functions below. */
1676
1677#define UNPACK_SINGLE(dest, ptr, type) \
1678 do { \
1679 type x; \
1680 memcpy((char *)&x, ptr, sizeof x); \
1681 dest = x; \
1682 } while (0)
1683
1684/* Unpack a single item. 'fmt' can be any native format character in struct
1685 module syntax. This function is very sensitive to small changes. With this
1686 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001687static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001688unpack_single(const char *ptr, const char *fmt)
1689{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001690 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001691 unsigned long lu;
1692 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001693 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001694 long ld;
1695 Py_ssize_t zd;
1696 double d;
1697 unsigned char uc;
1698 void *p;
1699
1700 switch (fmt[0]) {
1701
1702 /* signed integers and fast path for 'B' */
Andy Lestere6be9b52020-02-11 20:28:35 -06001703 case 'B': uc = *((const unsigned char *)ptr); goto convert_uc;
1704 case 'b': ld = *((const signed char *)ptr); goto convert_ld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001705 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1706 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1707 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1708
1709 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001710 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001711
1712 /* unsigned integers */
1713 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1714 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1715 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1716
1717 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001718 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1719 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001720
1721 /* ssize_t and size_t */
1722 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1723 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1724
1725 /* floats */
1726 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1727 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1728
1729 /* bytes object */
1730 case 'c': goto convert_bytes;
1731
1732 /* pointer */
1733 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1734
1735 /* default */
1736 default: goto err_format;
1737 }
1738
1739convert_uc:
1740 /* PyLong_FromUnsignedLong() is slower */
1741 return PyLong_FromLong(uc);
1742convert_ld:
1743 return PyLong_FromLong(ld);
1744convert_lu:
1745 return PyLong_FromUnsignedLong(lu);
1746convert_lld:
1747 return PyLong_FromLongLong(lld);
1748convert_llu:
1749 return PyLong_FromUnsignedLongLong(llu);
1750convert_zd:
1751 return PyLong_FromSsize_t(zd);
1752convert_zu:
1753 return PyLong_FromSize_t(zu);
1754convert_double:
1755 return PyFloat_FromDouble(d);
1756convert_bool:
1757 return PyBool_FromLong(ld);
1758convert_bytes:
1759 return PyBytes_FromStringAndSize(ptr, 1);
1760convert_pointer:
1761 return PyLong_FromVoidPtr(p);
1762err_format:
1763 PyErr_Format(PyExc_NotImplementedError,
1764 "memoryview: format %s not supported", fmt);
1765 return NULL;
1766}
1767
1768#define PACK_SINGLE(ptr, src, type) \
1769 do { \
1770 type x; \
1771 x = (type)src; \
1772 memcpy(ptr, (char *)&x, sizeof x); \
1773 } while (0)
1774
1775/* Pack a single item. 'fmt' can be any native format character in
1776 struct module syntax. */
1777static int
1778pack_single(char *ptr, PyObject *item, const char *fmt)
1779{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001780 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001781 unsigned long lu;
1782 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001783 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001784 long ld;
1785 Py_ssize_t zd;
1786 double d;
1787 void *p;
1788
1789 switch (fmt[0]) {
1790 /* signed integers */
1791 case 'b': case 'h': case 'i': case 'l':
1792 ld = pylong_as_ld(item);
1793 if (ld == -1 && PyErr_Occurred())
1794 goto err_occurred;
1795 switch (fmt[0]) {
1796 case 'b':
1797 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1798 *((signed char *)ptr) = (signed char)ld; break;
1799 case 'h':
1800 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1801 PACK_SINGLE(ptr, ld, short); break;
1802 case 'i':
1803 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1804 PACK_SINGLE(ptr, ld, int); break;
1805 default: /* 'l' */
1806 PACK_SINGLE(ptr, ld, long); break;
1807 }
1808 break;
1809
1810 /* unsigned integers */
1811 case 'B': case 'H': case 'I': case 'L':
1812 lu = pylong_as_lu(item);
1813 if (lu == (unsigned long)-1 && PyErr_Occurred())
1814 goto err_occurred;
1815 switch (fmt[0]) {
1816 case 'B':
1817 if (lu > UCHAR_MAX) goto err_range;
1818 *((unsigned char *)ptr) = (unsigned char)lu; break;
1819 case 'H':
1820 if (lu > USHRT_MAX) goto err_range;
1821 PACK_SINGLE(ptr, lu, unsigned short); break;
1822 case 'I':
1823 if (lu > UINT_MAX) goto err_range;
1824 PACK_SINGLE(ptr, lu, unsigned int); break;
1825 default: /* 'L' */
1826 PACK_SINGLE(ptr, lu, unsigned long); break;
1827 }
1828 break;
1829
1830 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001831 case 'q':
1832 lld = pylong_as_lld(item);
1833 if (lld == -1 && PyErr_Occurred())
1834 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001835 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001836 break;
1837 case 'Q':
1838 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001839 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001840 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001841 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001842 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001843
1844 /* ssize_t and size_t */
1845 case 'n':
1846 zd = pylong_as_zd(item);
1847 if (zd == -1 && PyErr_Occurred())
1848 goto err_occurred;
1849 PACK_SINGLE(ptr, zd, Py_ssize_t);
1850 break;
1851 case 'N':
1852 zu = pylong_as_zu(item);
1853 if (zu == (size_t)-1 && PyErr_Occurred())
1854 goto err_occurred;
1855 PACK_SINGLE(ptr, zu, size_t);
1856 break;
1857
1858 /* floats */
1859 case 'f': case 'd':
1860 d = PyFloat_AsDouble(item);
1861 if (d == -1.0 && PyErr_Occurred())
1862 goto err_occurred;
1863 if (fmt[0] == 'f') {
1864 PACK_SINGLE(ptr, d, float);
1865 }
1866 else {
1867 PACK_SINGLE(ptr, d, double);
1868 }
1869 break;
1870
1871 /* bool */
1872 case '?':
1873 ld = PyObject_IsTrue(item);
1874 if (ld < 0)
1875 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001876 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001877 break;
1878
1879 /* bytes object */
1880 case 'c':
1881 if (!PyBytes_Check(item))
1882 return type_error_int(fmt);
1883 if (PyBytes_GET_SIZE(item) != 1)
1884 return value_error_int(fmt);
1885 *ptr = PyBytes_AS_STRING(item)[0];
1886 break;
1887
1888 /* pointer */
1889 case 'P':
1890 p = PyLong_AsVoidPtr(item);
1891 if (p == NULL && PyErr_Occurred())
1892 goto err_occurred;
1893 PACK_SINGLE(ptr, p, void *);
1894 break;
1895
1896 /* default */
1897 default: goto err_format;
1898 }
1899
1900 return 0;
1901
1902err_occurred:
1903 return fix_error_int(fmt);
1904err_range:
1905 return value_error_int(fmt);
1906err_format:
1907 PyErr_Format(PyExc_NotImplementedError,
1908 "memoryview: format %s not supported", fmt);
1909 return -1;
1910}
1911
1912
1913/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001914/* unpack using the struct module */
1915/****************************************************************************/
1916
1917/* For reasonable performance it is necessary to cache all objects required
1918 for unpacking. An unpacker can handle the format passed to unpack_from().
1919 Invariant: All pointer fields of the struct should either be NULL or valid
1920 pointers. */
1921struct unpacker {
1922 PyObject *unpack_from; /* Struct.unpack_from(format) */
1923 PyObject *mview; /* cached memoryview */
1924 char *item; /* buffer for mview */
1925 Py_ssize_t itemsize; /* len(item) */
1926};
1927
1928static struct unpacker *
1929unpacker_new(void)
1930{
1931 struct unpacker *x = PyMem_Malloc(sizeof *x);
1932
1933 if (x == NULL) {
1934 PyErr_NoMemory();
1935 return NULL;
1936 }
1937
1938 x->unpack_from = NULL;
1939 x->mview = NULL;
1940 x->item = NULL;
1941 x->itemsize = 0;
1942
1943 return x;
1944}
1945
1946static void
1947unpacker_free(struct unpacker *x)
1948{
1949 if (x) {
1950 Py_XDECREF(x->unpack_from);
1951 Py_XDECREF(x->mview);
1952 PyMem_Free(x->item);
1953 PyMem_Free(x);
1954 }
1955}
1956
1957/* Return a new unpacker for the given format. */
1958static struct unpacker *
1959struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1960{
1961 PyObject *structmodule; /* XXX cache these two */
1962 PyObject *Struct = NULL; /* XXX in globals? */
1963 PyObject *structobj = NULL;
1964 PyObject *format = NULL;
1965 struct unpacker *x = NULL;
1966
1967 structmodule = PyImport_ImportModule("struct");
1968 if (structmodule == NULL)
1969 return NULL;
1970
1971 Struct = PyObject_GetAttrString(structmodule, "Struct");
1972 Py_DECREF(structmodule);
1973 if (Struct == NULL)
1974 return NULL;
1975
1976 x = unpacker_new();
1977 if (x == NULL)
1978 goto error;
1979
1980 format = PyBytes_FromString(fmt);
1981 if (format == NULL)
1982 goto error;
1983
Petr Viktorinffd97532020-02-11 17:46:57 +01001984 structobj = PyObject_CallOneArg(Struct, format);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001985 if (structobj == NULL)
1986 goto error;
1987
1988 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1989 if (x->unpack_from == NULL)
1990 goto error;
1991
1992 x->item = PyMem_Malloc(itemsize);
1993 if (x->item == NULL) {
1994 PyErr_NoMemory();
1995 goto error;
1996 }
1997 x->itemsize = itemsize;
1998
1999 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
2000 if (x->mview == NULL)
2001 goto error;
2002
2003
2004out:
2005 Py_XDECREF(Struct);
2006 Py_XDECREF(format);
2007 Py_XDECREF(structobj);
2008 return x;
2009
2010error:
2011 unpacker_free(x);
2012 x = NULL;
2013 goto out;
2014}
2015
2016/* unpack a single item */
2017static PyObject *
2018struct_unpack_single(const char *ptr, struct unpacker *x)
2019{
2020 PyObject *v;
2021
2022 memcpy(x->item, ptr, x->itemsize);
Petr Viktorinffd97532020-02-11 17:46:57 +01002023 v = PyObject_CallOneArg(x->unpack_from, x->mview);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002024 if (v == NULL)
2025 return NULL;
2026
2027 if (PyTuple_GET_SIZE(v) == 1) {
2028 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2029 Py_INCREF(tmp);
2030 Py_DECREF(v);
2031 return tmp;
2032 }
2033
2034 return v;
2035}
2036
2037
2038/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002039/* Representations */
2040/****************************************************************************/
2041
2042/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002043static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002044adjust_fmt(const Py_buffer *view)
2045{
2046 const char *fmt;
2047
2048 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2049 if (fmt[0] && fmt[1] == '\0')
2050 return fmt;
2051
2052 PyErr_Format(PyExc_NotImplementedError,
2053 "memoryview: unsupported format %s", view->format);
2054 return NULL;
2055}
2056
2057/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2058static PyObject *
2059tolist_base(const char *ptr, const Py_ssize_t *shape,
2060 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2061 const char *fmt)
2062{
2063 PyObject *lst, *item;
2064 Py_ssize_t i;
2065
2066 lst = PyList_New(shape[0]);
2067 if (lst == NULL)
2068 return NULL;
2069
2070 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002071 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002072 item = unpack_single(xptr, fmt);
2073 if (item == NULL) {
2074 Py_DECREF(lst);
2075 return NULL;
2076 }
2077 PyList_SET_ITEM(lst, i, item);
2078 }
2079
2080 return lst;
2081}
2082
2083/* Unpack a multi-dimensional array into a nested list.
2084 Assumption: ndim >= 1. */
2085static PyObject *
2086tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2087 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2088 const char *fmt)
2089{
2090 PyObject *lst, *item;
2091 Py_ssize_t i;
2092
2093 assert(ndim >= 1);
2094 assert(shape != NULL);
2095 assert(strides != NULL);
2096
2097 if (ndim == 1)
2098 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2099
2100 lst = PyList_New(shape[0]);
2101 if (lst == NULL)
2102 return NULL;
2103
2104 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002105 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002106 item = tolist_rec(xptr, ndim-1, shape+1,
2107 strides+1, suboffsets ? suboffsets+1 : NULL,
2108 fmt);
2109 if (item == NULL) {
2110 Py_DECREF(lst);
2111 return NULL;
2112 }
2113 PyList_SET_ITEM(lst, i, item);
2114 }
2115
2116 return lst;
2117}
2118
2119/* Return a list representation of the memoryview. Currently only buffers
2120 with native format strings are supported. */
Serhiy Storchaka80a50362020-07-18 11:12:05 +03002121/*[clinic input]
2122memoryview.tolist
2123
2124Return the data in the buffer as a list of elements.
2125[clinic start generated code]*/
2126
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002127static PyObject *
Serhiy Storchaka80a50362020-07-18 11:12:05 +03002128memoryview_tolist_impl(PyMemoryViewObject *self)
2129/*[clinic end generated code: output=a6cda89214fd5a1b input=21e7d0c1860b211a]*/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002130{
Serhiy Storchaka80a50362020-07-18 11:12:05 +03002131 const Py_buffer *view = &self->view;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002132 const char *fmt;
2133
Serhiy Storchaka80a50362020-07-18 11:12:05 +03002134 CHECK_RELEASED(self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002135
2136 fmt = adjust_fmt(view);
2137 if (fmt == NULL)
2138 return NULL;
2139 if (view->ndim == 0) {
2140 return unpack_single(view->buf, fmt);
2141 }
2142 else if (view->ndim == 1) {
2143 return tolist_base(view->buf, view->shape,
2144 view->strides, view->suboffsets,
2145 fmt);
2146 }
2147 else {
2148 return tolist_rec(view->buf, view->ndim, view->shape,
2149 view->strides, view->suboffsets,
2150 fmt);
2151 }
2152}
2153
Serhiy Storchaka80a50362020-07-18 11:12:05 +03002154/*[clinic input]
2155memoryview.tobytes
2156
2157 order: str(accept={str, NoneType}, c_default="NULL") = 'C'
2158
2159Return the data in the buffer as a byte string.
2160
2161Order can be {'C', 'F', 'A'}. When order is 'C' or 'F', the data of the
2162original array is converted to C or Fortran order. For contiguous views,
2163'A' returns an exact copy of the physical memory. In particular, in-memory
2164Fortran order is preserved. For non-contiguous views, the data is converted
2165to C first. order=None is the same as order='C'.
2166[clinic start generated code]*/
2167
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002168static PyObject *
Serhiy Storchaka80a50362020-07-18 11:12:05 +03002169memoryview_tobytes_impl(PyMemoryViewObject *self, const char *order)
2170/*[clinic end generated code: output=1288b62560a32a23 input=0efa3ddaeda573a8]*/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002171{
2172 Py_buffer *src = VIEW_ADDR(self);
Stefan Krahd08ea702019-02-02 18:57:41 +01002173 char ord = 'C';
2174 PyObject *bytes;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002175
2176 CHECK_RELEASED(self);
2177
Stefan Krahd08ea702019-02-02 18:57:41 +01002178 if (order) {
2179 if (strcmp(order, "F") == 0) {
2180 ord = 'F';
2181 }
2182 else if (strcmp(order, "A") == 0) {
2183 ord = 'A';
2184 }
2185 else if (strcmp(order, "C") != 0) {
2186 PyErr_SetString(PyExc_ValueError,
2187 "order must be 'C', 'F' or 'A'");
2188 return NULL;
2189 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002190 }
2191
2192 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2193 if (bytes == NULL)
2194 return NULL;
2195
Stefan Krahd08ea702019-02-02 18:57:41 +01002196 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, ord) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002197 Py_DECREF(bytes);
2198 return NULL;
2199 }
2200
2201 return bytes;
2202}
2203
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002204/*[clinic input]
2205memoryview.hex
2206
2207 sep: object = NULL
2208 An optional single character or byte to separate hex bytes.
2209 bytes_per_sep: int = 1
2210 How many bytes between separators. Positive values count from the
2211 right, negative values count from the left.
2212
2213Return the data in the buffer as a str of hexadecimal numbers.
2214
2215Example:
2216>>> value = memoryview(b'\xb9\x01\xef')
2217>>> value.hex()
2218'b901ef'
2219>>> value.hex(':')
2220'b9:01:ef'
2221>>> value.hex(':', 2)
2222'b9:01ef'
2223>>> value.hex(':', -2)
2224'b901:ef'
2225[clinic start generated code]*/
2226
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002227static PyObject *
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002228memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
2229 int bytes_per_sep)
2230/*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002231{
2232 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002233 PyObject *bytes;
2234 PyObject *ret;
2235
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002236 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002237
2238 if (MV_C_CONTIGUOUS(self->flags)) {
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002239 return _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002240 }
2241
Stefan Krahd08ea702019-02-02 18:57:41 +01002242 bytes = PyBytes_FromStringAndSize(NULL, src->len);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002243 if (bytes == NULL)
2244 return NULL;
2245
Stefan Krahd08ea702019-02-02 18:57:41 +01002246 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, 'C') < 0) {
2247 Py_DECREF(bytes);
2248 return NULL;
2249 }
2250
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002251 ret = _Py_strhex_with_sep(
2252 PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes),
2253 sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002254 Py_DECREF(bytes);
2255
2256 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002257}
2258
2259static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002260memory_repr(PyMemoryViewObject *self)
2261{
2262 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2263 return PyUnicode_FromFormat("<released memory at %p>", self);
2264 else
2265 return PyUnicode_FromFormat("<memory at %p>", self);
2266}
2267
2268
2269/**************************************************************************/
2270/* Indexing and slicing */
2271/**************************************************************************/
2272
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002273static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002274lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002275{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002276 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002277
2278 assert(view->shape);
2279 assert(view->strides);
2280
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002281 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002282 if (index < 0) {
2283 index += nitems;
2284 }
2285 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002286 PyErr_Format(PyExc_IndexError,
2287 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002288 return NULL;
2289 }
2290
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002291 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002292
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002293 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002294
2295 return ptr;
2296}
2297
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002298/* Get the pointer to the item at index. */
2299static char *
2300ptr_from_index(Py_buffer *view, Py_ssize_t index)
2301{
2302 char *ptr = (char *)view->buf;
2303 return lookup_dimension(view, ptr, 0, index);
2304}
2305
2306/* Get the pointer to the item at tuple. */
2307static char *
2308ptr_from_tuple(Py_buffer *view, PyObject *tup)
2309{
2310 char *ptr = (char *)view->buf;
2311 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2312
2313 if (nindices > view->ndim) {
2314 PyErr_Format(PyExc_TypeError,
2315 "cannot index %zd-dimension view with %zd-element tuple",
2316 view->ndim, nindices);
2317 return NULL;
2318 }
2319
2320 for (dim = 0; dim < nindices; dim++) {
2321 Py_ssize_t index;
2322 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2323 PyExc_IndexError);
2324 if (index == -1 && PyErr_Occurred())
2325 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002326 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002327 if (ptr == NULL)
2328 return NULL;
2329 }
2330 return ptr;
2331}
2332
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002333/* Return the item at index. In a one-dimensional view, this is an object
2334 with the type specified by view->format. Otherwise, the item is a sub-view.
2335 The function is used in memory_subscript() and memory_as_sequence. */
2336static PyObject *
2337memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2338{
2339 Py_buffer *view = &(self->view);
2340 const char *fmt;
2341
2342 CHECK_RELEASED(self);
2343
2344 fmt = adjust_fmt(view);
2345 if (fmt == NULL)
2346 return NULL;
2347
2348 if (view->ndim == 0) {
2349 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2350 return NULL;
2351 }
2352 if (view->ndim == 1) {
2353 char *ptr = ptr_from_index(view, index);
2354 if (ptr == NULL)
2355 return NULL;
2356 return unpack_single(ptr, fmt);
2357 }
2358
2359 PyErr_SetString(PyExc_NotImplementedError,
2360 "multi-dimensional sub-views are not implemented");
2361 return NULL;
2362}
2363
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002364/* Return the item at position *key* (a tuple of indices). */
2365static PyObject *
2366memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2367{
2368 Py_buffer *view = &(self->view);
2369 const char *fmt;
2370 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2371 char *ptr;
2372
2373 CHECK_RELEASED(self);
2374
2375 fmt = adjust_fmt(view);
2376 if (fmt == NULL)
2377 return NULL;
2378
2379 if (nindices < view->ndim) {
2380 PyErr_SetString(PyExc_NotImplementedError,
2381 "sub-views are not implemented");
2382 return NULL;
2383 }
2384 ptr = ptr_from_tuple(view, tup);
2385 if (ptr == NULL)
2386 return NULL;
2387 return unpack_single(ptr, fmt);
2388}
2389
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002390static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002391init_slice(Py_buffer *base, PyObject *key, int dim)
2392{
2393 Py_ssize_t start, stop, step, slicelength;
2394
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002395 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002396 return -1;
2397 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002398 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002399
2400
2401 if (base->suboffsets == NULL || dim == 0) {
2402 adjust_buf:
2403 base->buf = (char *)base->buf + base->strides[dim] * start;
2404 }
2405 else {
2406 Py_ssize_t n = dim-1;
2407 while (n >= 0 && base->suboffsets[n] < 0)
2408 n--;
2409 if (n < 0)
2410 goto adjust_buf; /* all suboffsets are negative */
2411 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2412 }
2413 base->shape[dim] = slicelength;
2414 base->strides[dim] = base->strides[dim] * step;
2415
2416 return 0;
2417}
2418
2419static int
2420is_multislice(PyObject *key)
2421{
2422 Py_ssize_t size, i;
2423
2424 if (!PyTuple_Check(key))
2425 return 0;
2426 size = PyTuple_GET_SIZE(key);
2427 if (size == 0)
2428 return 0;
2429
2430 for (i = 0; i < size; i++) {
2431 PyObject *x = PyTuple_GET_ITEM(key, i);
2432 if (!PySlice_Check(x))
2433 return 0;
2434 }
2435 return 1;
2436}
2437
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002438static Py_ssize_t
2439is_multiindex(PyObject *key)
2440{
2441 Py_ssize_t size, i;
2442
2443 if (!PyTuple_Check(key))
2444 return 0;
2445 size = PyTuple_GET_SIZE(key);
2446 for (i = 0; i < size; i++) {
2447 PyObject *x = PyTuple_GET_ITEM(key, i);
Victor Stinnera15e2602020-04-08 02:01:56 +02002448 if (!_PyIndex_Check(x)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002449 return 0;
Victor Stinnera15e2602020-04-08 02:01:56 +02002450 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002451 }
2452 return 1;
2453}
2454
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002455/* mv[obj] returns an object holding the data for one element if obj
2456 fully indexes the memoryview or another memoryview object if it
2457 does not.
2458
2459 0-d memoryview objects can be referenced using mv[...] or mv[()]
2460 but not with anything else. */
2461static PyObject *
2462memory_subscript(PyMemoryViewObject *self, PyObject *key)
2463{
2464 Py_buffer *view;
2465 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002466
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002467 CHECK_RELEASED(self);
2468
2469 if (view->ndim == 0) {
2470 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2471 const char *fmt = adjust_fmt(view);
2472 if (fmt == NULL)
2473 return NULL;
2474 return unpack_single(view->buf, fmt);
2475 }
2476 else if (key == Py_Ellipsis) {
2477 Py_INCREF(self);
2478 return (PyObject *)self;
2479 }
2480 else {
2481 PyErr_SetString(PyExc_TypeError,
2482 "invalid indexing of 0-dim memory");
2483 return NULL;
2484 }
2485 }
2486
Victor Stinnera15e2602020-04-08 02:01:56 +02002487 if (_PyIndex_Check(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002488 Py_ssize_t index;
2489 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2490 if (index == -1 && PyErr_Occurred())
2491 return NULL;
2492 return memory_item(self, index);
2493 }
2494 else if (PySlice_Check(key)) {
2495 PyMemoryViewObject *sliced;
2496
2497 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2498 if (sliced == NULL)
2499 return NULL;
2500
2501 if (init_slice(&sliced->view, key, 0) < 0) {
2502 Py_DECREF(sliced);
2503 return NULL;
2504 }
2505 init_len(&sliced->view);
2506 init_flags(sliced);
2507
2508 return (PyObject *)sliced;
2509 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002510 else if (is_multiindex(key)) {
2511 return memory_item_multi(self, key);
2512 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002513 else if (is_multislice(key)) {
2514 PyErr_SetString(PyExc_NotImplementedError,
2515 "multi-dimensional slicing is not implemented");
2516 return NULL;
2517 }
2518
2519 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2520 return NULL;
2521}
2522
2523static int
2524memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2525{
2526 Py_buffer *view = &(self->view);
2527 Py_buffer src;
2528 const char *fmt;
2529 char *ptr;
2530
2531 CHECK_RELEASED_INT(self);
2532
2533 fmt = adjust_fmt(view);
2534 if (fmt == NULL)
2535 return -1;
2536
2537 if (view->readonly) {
2538 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2539 return -1;
2540 }
2541 if (value == NULL) {
2542 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2543 return -1;
2544 }
2545 if (view->ndim == 0) {
2546 if (key == Py_Ellipsis ||
2547 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2548 ptr = (char *)view->buf;
2549 return pack_single(ptr, value, fmt);
2550 }
2551 else {
2552 PyErr_SetString(PyExc_TypeError,
2553 "invalid indexing of 0-dim memory");
2554 return -1;
2555 }
2556 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002557
Victor Stinnera15e2602020-04-08 02:01:56 +02002558 if (_PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002559 Py_ssize_t index;
2560 if (1 < view->ndim) {
2561 PyErr_SetString(PyExc_NotImplementedError,
2562 "sub-views are not implemented");
2563 return -1;
2564 }
2565 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002566 if (index == -1 && PyErr_Occurred())
2567 return -1;
2568 ptr = ptr_from_index(view, index);
2569 if (ptr == NULL)
2570 return -1;
2571 return pack_single(ptr, value, fmt);
2572 }
2573 /* one-dimensional: fast path */
2574 if (PySlice_Check(key) && view->ndim == 1) {
2575 Py_buffer dest; /* sliced view */
2576 Py_ssize_t arrays[3];
2577 int ret = -1;
2578
2579 /* rvalue must be an exporter */
2580 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2581 return ret;
2582
2583 dest = *view;
2584 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2585 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2586 if (view->suboffsets) {
2587 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2588 }
2589
2590 if (init_slice(&dest, key, 0) < 0)
2591 goto end_block;
2592 dest.len = dest.shape[0] * dest.itemsize;
2593
2594 ret = copy_single(&dest, &src);
2595
2596 end_block:
2597 PyBuffer_Release(&src);
2598 return ret;
2599 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002600 if (is_multiindex(key)) {
2601 char *ptr;
2602 if (PyTuple_GET_SIZE(key) < view->ndim) {
2603 PyErr_SetString(PyExc_NotImplementedError,
2604 "sub-views are not implemented");
2605 return -1;
2606 }
2607 ptr = ptr_from_tuple(view, key);
2608 if (ptr == NULL)
2609 return -1;
2610 return pack_single(ptr, value, fmt);
2611 }
2612 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002613 /* Call memory_subscript() to produce a sliced lvalue, then copy
2614 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2615 PyErr_SetString(PyExc_NotImplementedError,
2616 "memoryview slice assignments are currently restricted "
2617 "to ndim = 1");
2618 return -1;
2619 }
2620
2621 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2622 return -1;
2623}
2624
2625static Py_ssize_t
2626memory_length(PyMemoryViewObject *self)
2627{
2628 CHECK_RELEASED_INT(self);
2629 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2630}
2631
2632/* As mapping */
2633static PyMappingMethods memory_as_mapping = {
2634 (lenfunc)memory_length, /* mp_length */
2635 (binaryfunc)memory_subscript, /* mp_subscript */
2636 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2637};
2638
2639/* As sequence */
2640static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002641 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002642 0, /* sq_concat */
2643 0, /* sq_repeat */
2644 (ssizeargfunc)memory_item, /* sq_item */
2645};
2646
2647
2648/**************************************************************************/
2649/* Comparisons */
2650/**************************************************************************/
2651
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002652#define MV_COMPARE_EX -1 /* exception */
2653#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2654
2655/* Translate a StructError to "not equal". Preserve other exceptions. */
2656static int
2657fix_struct_error_int(void)
2658{
2659 assert(PyErr_Occurred());
2660 /* XXX Cannot get at StructError directly? */
2661 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2662 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2663 return MV_COMPARE_EX;
2664 }
2665 /* StructError: invalid or unknown format -> not equal */
2666 PyErr_Clear();
2667 return 0;
2668}
2669
2670/* Unpack and compare single items of p and q using the struct module. */
2671static int
2672struct_unpack_cmp(const char *p, const char *q,
2673 struct unpacker *unpack_p, struct unpacker *unpack_q)
2674{
2675 PyObject *v, *w;
2676 int ret;
2677
2678 /* At this point any exception from the struct module should not be
2679 StructError, since both formats have been accepted already. */
2680 v = struct_unpack_single(p, unpack_p);
2681 if (v == NULL)
2682 return MV_COMPARE_EX;
2683
2684 w = struct_unpack_single(q, unpack_q);
2685 if (w == NULL) {
2686 Py_DECREF(v);
2687 return MV_COMPARE_EX;
2688 }
2689
2690 /* MV_COMPARE_EX == -1: exceptions are preserved */
2691 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2692 Py_DECREF(v);
2693 Py_DECREF(w);
2694
2695 return ret;
2696}
2697
2698/* Unpack and compare single items of p and q. If both p and q have the same
2699 single element native format, the comparison uses a fast path (gcc creates
2700 a jump table and converts memcpy into simple assignments on x86/x64).
2701
2702 Otherwise, the comparison is delegated to the struct module, which is
2703 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002704#define CMP_SINGLE(p, q, type) \
2705 do { \
2706 type x; \
2707 type y; \
2708 memcpy((char *)&x, p, sizeof x); \
2709 memcpy((char *)&y, q, sizeof y); \
2710 equal = (x == y); \
2711 } while (0)
2712
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002713static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002714unpack_cmp(const char *p, const char *q, char fmt,
2715 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002716{
2717 int equal;
2718
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002719 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002720
2721 /* signed integers and fast path for 'B' */
Andy Lestere6be9b52020-02-11 20:28:35 -06002722 case 'B': return *((const unsigned char *)p) == *((const unsigned char *)q);
2723 case 'b': return *((const signed char *)p) == *((const signed char *)q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002724 case 'h': CMP_SINGLE(p, q, short); return equal;
2725 case 'i': CMP_SINGLE(p, q, int); return equal;
2726 case 'l': CMP_SINGLE(p, q, long); return equal;
2727
2728 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002729 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002730
2731 /* unsigned integers */
2732 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2733 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2734 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2735
2736 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002737 case 'q': CMP_SINGLE(p, q, long long); return equal;
2738 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002739
2740 /* ssize_t and size_t */
2741 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2742 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2743
2744 /* floats */
2745 /* XXX DBL_EPSILON? */
2746 case 'f': CMP_SINGLE(p, q, float); return equal;
2747 case 'd': CMP_SINGLE(p, q, double); return equal;
2748
2749 /* bytes object */
2750 case 'c': return *p == *q;
2751
2752 /* pointer */
2753 case 'P': CMP_SINGLE(p, q, void *); return equal;
2754
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002755 /* use the struct module */
2756 case '_':
2757 assert(unpack_p);
2758 assert(unpack_q);
2759 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002760 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002761
2762 /* NOT REACHED */
2763 PyErr_SetString(PyExc_RuntimeError,
2764 "memoryview: internal error in richcompare");
2765 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002766}
2767
2768/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2769static int
2770cmp_base(const char *p, const char *q, 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 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002779 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2780 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002781 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002782 if (equal <= 0)
2783 return equal;
2784 }
2785
2786 return 1;
2787}
2788
2789/* Recursively compare two multi-dimensional arrays that have the same
2790 logical structure. Assumption: ndim >= 1. */
2791static int
2792cmp_rec(const char *p, const char *q,
2793 Py_ssize_t ndim, const Py_ssize_t *shape,
2794 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2795 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002796 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002797{
2798 Py_ssize_t i;
2799 int equal;
2800
2801 assert(ndim >= 1);
2802 assert(shape != NULL);
2803 assert(pstrides != NULL);
2804 assert(qstrides != NULL);
2805
2806 if (ndim == 1) {
2807 return cmp_base(p, q, shape,
2808 pstrides, psuboffsets,
2809 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002810 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002811 }
2812
2813 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002814 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2815 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002816 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2817 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2818 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002819 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002820 if (equal <= 0)
2821 return equal;
2822 }
2823
2824 return 1;
2825}
2826
2827static PyObject *
2828memory_richcompare(PyObject *v, PyObject *w, int op)
2829{
2830 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002831 Py_buffer wbuf, *vv;
2832 Py_buffer *ww = NULL;
2833 struct unpacker *unpack_v = NULL;
2834 struct unpacker *unpack_w = NULL;
2835 char vfmt, wfmt;
2836 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002837
2838 if (op != Py_EQ && op != Py_NE)
2839 goto result; /* Py_NotImplemented */
2840
2841 assert(PyMemoryView_Check(v));
2842 if (BASE_INACCESSIBLE(v)) {
2843 equal = (v == w);
2844 goto result;
2845 }
2846 vv = VIEW_ADDR(v);
2847
2848 if (PyMemoryView_Check(w)) {
2849 if (BASE_INACCESSIBLE(w)) {
2850 equal = (v == w);
2851 goto result;
2852 }
2853 ww = VIEW_ADDR(w);
2854 }
2855 else {
2856 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2857 PyErr_Clear();
2858 goto result; /* Py_NotImplemented */
2859 }
2860 ww = &wbuf;
2861 }
2862
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002863 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002864 PyErr_Clear();
2865 equal = 0;
2866 goto result;
2867 }
2868
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002869 /* Use fast unpacking for identical primitive C type formats. */
2870 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2871 vfmt = '_';
2872 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2873 wfmt = '_';
2874 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2875 /* Use struct module unpacking. NOTE: Even for equal format strings,
2876 memcmp() cannot be used for item comparison since it would give
2877 incorrect results in the case of NaNs or uninitialized padding
2878 bytes. */
2879 vfmt = '_';
2880 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2881 if (unpack_v == NULL) {
2882 equal = fix_struct_error_int();
2883 goto result;
2884 }
2885 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2886 if (unpack_w == NULL) {
2887 equal = fix_struct_error_int();
2888 goto result;
2889 }
2890 }
2891
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002892 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002893 equal = unpack_cmp(vv->buf, ww->buf,
2894 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002895 }
2896 else if (vv->ndim == 1) {
2897 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2898 vv->strides, vv->suboffsets,
2899 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002900 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002901 }
2902 else {
2903 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2904 vv->strides, vv->suboffsets,
2905 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002906 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002907 }
2908
2909result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002910 if (equal < 0) {
2911 if (equal == MV_COMPARE_NOT_IMPL)
2912 res = Py_NotImplemented;
2913 else /* exception */
2914 res = NULL;
2915 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002916 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2917 res = Py_True;
2918 else
2919 res = Py_False;
2920
2921 if (ww == &wbuf)
2922 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002923
2924 unpacker_free(unpack_v);
2925 unpacker_free(unpack_w);
2926
2927 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002928 return res;
2929}
2930
2931/**************************************************************************/
2932/* Hash */
2933/**************************************************************************/
2934
2935static Py_hash_t
2936memory_hash(PyMemoryViewObject *self)
2937{
2938 if (self->hash == -1) {
2939 Py_buffer *view = &self->view;
2940 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002941 Py_ssize_t ret;
2942 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002943
2944 CHECK_RELEASED_INT(self);
2945
2946 if (!view->readonly) {
2947 PyErr_SetString(PyExc_ValueError,
2948 "cannot hash writable memoryview object");
2949 return -1;
2950 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002951 ret = get_native_fmtchar(&fmt, view->format);
2952 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2953 PyErr_SetString(PyExc_ValueError,
2954 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2955 return -1;
2956 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002957 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2958 /* Keep the original error message */
2959 return -1;
2960 }
2961
2962 if (!MV_C_CONTIGUOUS(self->flags)) {
2963 mem = PyMem_Malloc(view->len);
2964 if (mem == NULL) {
2965 PyErr_NoMemory();
2966 return -1;
2967 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002968 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002969 PyMem_Free(mem);
2970 return -1;
2971 }
2972 }
2973
2974 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002975 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002976
2977 if (mem != view->buf)
2978 PyMem_Free(mem);
2979 }
2980
2981 return self->hash;
2982}
2983
2984
2985/**************************************************************************/
2986/* getters */
2987/**************************************************************************/
2988
2989static PyObject *
2990_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2991{
2992 int i;
2993 PyObject *o;
2994 PyObject *intTuple;
2995
2996 if (vals == NULL)
2997 return PyTuple_New(0);
2998
2999 intTuple = PyTuple_New(len);
3000 if (!intTuple)
3001 return NULL;
3002 for (i=0; i<len; i++) {
3003 o = PyLong_FromSsize_t(vals[i]);
3004 if (!o) {
3005 Py_DECREF(intTuple);
3006 return NULL;
3007 }
3008 PyTuple_SET_ITEM(intTuple, i, o);
3009 }
3010 return intTuple;
3011}
3012
3013static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003014memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003015{
3016 Py_buffer *view = &self->view;
3017
3018 CHECK_RELEASED(self);
3019 if (view->obj == NULL) {
3020 Py_RETURN_NONE;
3021 }
3022 Py_INCREF(view->obj);
3023 return view->obj;
3024}
3025
3026static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003027memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003028{
3029 CHECK_RELEASED(self);
3030 return PyLong_FromSsize_t(self->view.len);
3031}
3032
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003033static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003034memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003035{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003036 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003037 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003038}
3039
3040static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003041memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003042{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003043 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003044 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003045}
3046
3047static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003048memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003049{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003050 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003051 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003052}
3053
3054static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003055memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003056{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003057 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003058 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003059}
3060
3061static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003062memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003063{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003064 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003065 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003066}
3067
3068static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003069memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003070{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003071 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003072 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003073}
3074
3075static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003076memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003077{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003078 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003079 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003080}
3081
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003082static PyObject *
3083memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3084{
3085 CHECK_RELEASED(self);
3086 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3087}
3088
3089static PyObject *
3090memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3091{
3092 CHECK_RELEASED(self);
3093 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3094}
3095
3096static PyObject *
3097memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3098{
3099 CHECK_RELEASED(self);
3100 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3101}
3102
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003103PyDoc_STRVAR(memory_obj_doc,
3104 "The underlying object of the memoryview.");
3105PyDoc_STRVAR(memory_nbytes_doc,
3106 "The amount of space in bytes that the array would use in\n"
3107 " a contiguous representation.");
3108PyDoc_STRVAR(memory_readonly_doc,
3109 "A bool indicating whether the memory is read only.");
3110PyDoc_STRVAR(memory_itemsize_doc,
3111 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003112PyDoc_STRVAR(memory_format_doc,
3113 "A string containing the format (in struct module style)\n"
3114 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003115PyDoc_STRVAR(memory_ndim_doc,
3116 "An integer indicating how many dimensions of a multi-dimensional\n"
3117 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003118PyDoc_STRVAR(memory_shape_doc,
3119 "A tuple of ndim integers giving the shape of the memory\n"
3120 " as an N-dimensional array.");
3121PyDoc_STRVAR(memory_strides_doc,
3122 "A tuple of ndim integers giving the size in bytes to access\n"
3123 " each element for each dimension of the array.");
3124PyDoc_STRVAR(memory_suboffsets_doc,
3125 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003126PyDoc_STRVAR(memory_c_contiguous_doc,
3127 "A bool indicating whether the memory is C contiguous.");
3128PyDoc_STRVAR(memory_f_contiguous_doc,
3129 "A bool indicating whether the memory is Fortran contiguous.");
3130PyDoc_STRVAR(memory_contiguous_doc,
3131 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003132
Stefan Krahbcaf5992014-05-18 00:35:09 +02003133
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003134static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003135 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3136 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003137 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3138 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3139 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3140 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3141 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3142 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3143 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003144 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3145 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3146 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003147 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003148};
3149
3150
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003151static PyMethodDef memory_methods[] = {
Serhiy Storchaka80a50362020-07-18 11:12:05 +03003152 MEMORYVIEW_RELEASE_METHODDEF
3153 MEMORYVIEW_TOBYTES_METHODDEF
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07003154 MEMORYVIEW_HEX_METHODDEF
Serhiy Storchaka80a50362020-07-18 11:12:05 +03003155 MEMORYVIEW_TOLIST_METHODDEF
3156 MEMORYVIEW_CAST_METHODDEF
3157 MEMORYVIEW_TOREADONLY_METHODDEF
Stefan Krahe4c07992012-07-28 14:10:02 +02003158 {"__enter__", memory_enter, METH_NOARGS, NULL},
3159 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003160 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003161};
3162
dxfloresb0ac5d72020-09-08 08:28:45 +01003163/**************************************************************************/
3164/* Memoryview Iterator */
3165/**************************************************************************/
3166
3167static PyTypeObject PyMemoryIter_Type;
3168
3169typedef struct {
3170 PyObject_HEAD
3171 Py_ssize_t it_index;
3172 PyMemoryViewObject *it_seq; // Set to NULL when iterator is exhausted
3173 Py_ssize_t it_length;
3174 const char *it_fmt;
3175} memoryiterobject;
3176
3177static void
3178memoryiter_dealloc(memoryiterobject *it)
3179{
3180 _PyObject_GC_UNTRACK(it);
3181 Py_XDECREF(it->it_seq);
3182 PyObject_GC_Del(it);
3183}
3184
3185static int
3186memoryiter_traverse(memoryiterobject *it, visitproc visit, void *arg)
3187{
3188 Py_VISIT(it->it_seq);
3189 return 0;
3190}
3191
3192static PyObject *
3193memoryiter_next(memoryiterobject *it)
3194{
3195 PyMemoryViewObject *seq;
3196 seq = it->it_seq;
3197 if (seq == NULL) {
3198 return NULL;
3199 }
3200
3201 if (it->it_index < it->it_length) {
3202 CHECK_RELEASED(seq);
3203 Py_buffer *view = &(seq->view);
3204 char *ptr = (char *)seq->view.buf;
3205
3206 ptr += view->strides[0] * it->it_index++;
3207 ptr = ADJUST_PTR(ptr, view->suboffsets, 0);
3208 if (ptr == NULL) {
3209 return NULL;
3210 }
3211 return unpack_single(ptr, it->it_fmt);
3212 }
3213
3214 it->it_seq = NULL;
3215 Py_DECREF(seq);
3216 return NULL;
3217}
3218
3219static PyObject *
3220memory_iter(PyObject *seq)
3221{
3222 if (!PyMemoryView_Check(seq)) {
3223 PyErr_BadInternalCall();
3224 return NULL;
3225 }
3226 PyMemoryViewObject *obj = (PyMemoryViewObject *)seq;
3227 int ndims = obj->view.ndim;
3228 if (ndims == 0) {
3229 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
3230 return NULL;
3231 }
3232 if (ndims != 1) {
3233 PyErr_SetString(PyExc_NotImplementedError,
3234 "multi-dimensional sub-views are not implemented");
3235 return NULL;
3236 }
3237
3238 const char *fmt = adjust_fmt(&obj->view);
3239 if (fmt == NULL) {
3240 return NULL;
3241 }
3242
3243 memoryiterobject *it;
3244 it = PyObject_GC_New(memoryiterobject, &PyMemoryIter_Type);
3245 if (it == NULL) {
3246 return NULL;
3247 }
3248 it->it_fmt = fmt;
3249 it->it_length = memory_length(obj);
3250 it->it_index = 0;
3251 Py_INCREF(seq);
3252 it->it_seq = obj;
3253 _PyObject_GC_TRACK(it);
3254 return (PyObject *)it;
3255}
3256
3257static PyTypeObject PyMemoryIter_Type = {
3258 PyVarObject_HEAD_INIT(&PyType_Type, 0)
3259 .tp_name = "memory_iterator",
3260 .tp_basicsize = sizeof(memoryiterobject),
3261 // methods
3262 .tp_dealloc = (destructor)memoryiter_dealloc,
3263 .tp_getattro = PyObject_GenericGetAttr,
3264 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
3265 .tp_traverse = (traverseproc)memoryiter_traverse,
3266 .tp_iter = PyObject_SelfIter,
3267 .tp_iternext = (iternextfunc)memoryiter_next,
3268};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003269
3270PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003271 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003272 "memoryview", /* tp_name */
3273 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3274 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003275 (destructor)memory_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003276 0, /* tp_vectorcall_offset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003277 0, /* tp_getattr */
3278 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003279 0, /* tp_as_async */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003280 (reprfunc)memory_repr, /* tp_repr */
3281 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003282 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003283 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003284 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003285 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003286 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003287 PyObject_GenericGetAttr, /* tp_getattro */
3288 0, /* tp_setattro */
3289 &memory_as_buffer, /* tp_as_buffer */
3290 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Serhiy Storchaka80a50362020-07-18 11:12:05 +03003291 memoryview__doc__, /* tp_doc */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003292 (traverseproc)memory_traverse, /* tp_traverse */
3293 (inquiry)memory_clear, /* tp_clear */
3294 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003295 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
dxfloresb0ac5d72020-09-08 08:28:45 +01003296 memory_iter, /* tp_iter */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003297 0, /* tp_iternext */
3298 memory_methods, /* tp_methods */
3299 0, /* tp_members */
3300 memory_getsetlist, /* tp_getset */
3301 0, /* tp_base */
3302 0, /* tp_dict */
3303 0, /* tp_descr_get */
3304 0, /* tp_descr_set */
3305 0, /* tp_dictoffset */
3306 0, /* tp_init */
3307 0, /* tp_alloc */
Serhiy Storchaka80a50362020-07-18 11:12:05 +03003308 memoryview, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003309};