blob: 906d1cef69b1f404d6670642f8bdb6efa17408d9 [file] [log] [blame]
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001/* Memoryview object implementation */
2
3#include "Python.h"
Victor Stinnerbcda8f12018-11-21 22:27:47 +01004#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01005#include "pycore_pymem.h"
6#include "pycore_pystate.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +00007#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +01008#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00009
Gregory P. Smith0c2f9302019-05-29 11:46:58 -070010/*[clinic input]
11class memoryview "PyMemoryViewObject *" "&PyMemoryView_Type"
12[clinic start generated code]*/
13/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2e49d2192835219]*/
14
15#include "clinic/memoryobject.c.h"
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000016
Stefan Krah9a2d99e2012-02-25 12:24:21 +010017/****************************************************************************/
18/* ManagedBuffer Object */
19/****************************************************************************/
20
21/*
22 ManagedBuffer Object:
23 ---------------------
24
25 The purpose of this object is to facilitate the handling of chained
26 memoryviews that have the same underlying exporting object. PEP-3118
27 allows the underlying object to change while a view is exported. This
28 could lead to unexpected results when constructing a new memoryview
29 from an existing memoryview.
30
31 Rather than repeatedly redirecting buffer requests to the original base
32 object, all chained memoryviews use a single buffer snapshot. This
33 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
34
35 Ownership rules:
36 ----------------
37
38 The master buffer inside a managed buffer is filled in by the original
39 base object. shape, strides, suboffsets and format are read-only for
40 all consumers.
41
42 A memoryview's buffer is a private copy of the exporter's buffer. shape,
43 strides and suboffsets belong to the memoryview and are thus writable.
44
45 If a memoryview itself exports several buffers via memory_getbuf(), all
46 buffer copies share shape, strides and suboffsets. In this case, the
47 arrays are NOT writable.
48
49 Reference count assumptions:
50 ----------------------------
51
52 The 'obj' member of a Py_buffer must either be NULL or refer to the
53 exporting base object. In the Python codebase, all getbufferprocs
54 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
55
56 PyBuffer_Release() decrements view.obj (if non-NULL), so the
57 releasebufferprocs must NOT decrement view.obj.
58*/
59
60
Stefan Krah9a2d99e2012-02-25 12:24:21 +010061#define CHECK_MBUF_RELEASED(mbuf) \
62 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
63 PyErr_SetString(PyExc_ValueError, \
64 "operation forbidden on released memoryview object"); \
65 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000066 }
67
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000068
Benjamin Peterson82cce4c2016-09-08 11:56:06 -070069static inline _PyManagedBufferObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +010070mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000071{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010072 _PyManagedBufferObject *mbuf;
73
74 mbuf = (_PyManagedBufferObject *)
75 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
76 if (mbuf == NULL)
77 return NULL;
78 mbuf->flags = 0;
79 mbuf->exports = 0;
80 mbuf->master.obj = NULL;
81 _PyObject_GC_TRACK(mbuf);
82
83 return mbuf;
84}
85
86static PyObject *
87_PyManagedBuffer_FromObject(PyObject *base)
88{
89 _PyManagedBufferObject *mbuf;
90
91 mbuf = mbuf_alloc();
92 if (mbuf == NULL)
93 return NULL;
94
95 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +010096 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +010097 Py_DECREF(mbuf);
98 return NULL;
99 }
100
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100101 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000102}
103
104static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100105mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +0000106{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100107 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
108 return;
109
110 /* NOTE: at this point self->exports can still be > 0 if this function
111 is called from mbuf_clear() to break up a reference cycle. */
112 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
113
114 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
115 _PyObject_GC_UNTRACK(self);
116 PyBuffer_Release(&self->master);
117}
118
119static void
120mbuf_dealloc(_PyManagedBufferObject *self)
121{
122 assert(self->exports == 0);
123 mbuf_release(self);
124 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
125 PyMem_Free(self->master.format);
126 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000127}
128
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000129static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100130mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000131{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100132 Py_VISIT(self->master.obj);
133 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000134}
135
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100136static int
137mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000138{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100139 assert(self->exports >= 0);
140 mbuf_release(self);
141 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000142}
143
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100144PyTypeObject _PyManagedBuffer_Type = {
145 PyVarObject_HEAD_INIT(&PyType_Type, 0)
146 "managedbuffer",
147 sizeof(_PyManagedBufferObject),
148 0,
149 (destructor)mbuf_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200150 0, /* tp_vectorcall_offset */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100151 0, /* tp_getattr */
152 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200153 0, /* tp_as_async */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100154 0, /* tp_repr */
155 0, /* tp_as_number */
156 0, /* tp_as_sequence */
157 0, /* tp_as_mapping */
158 0, /* tp_hash */
159 0, /* tp_call */
160 0, /* tp_str */
161 PyObject_GenericGetAttr, /* tp_getattro */
162 0, /* tp_setattro */
163 0, /* tp_as_buffer */
164 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
165 0, /* tp_doc */
166 (traverseproc)mbuf_traverse, /* tp_traverse */
167 (inquiry)mbuf_clear /* tp_clear */
168};
169
170
171/****************************************************************************/
172/* MemoryView Object */
173/****************************************************************************/
174
175/* In the process of breaking reference cycles mbuf_release() can be
176 called before memory_release(). */
177#define BASE_INACCESSIBLE(mv) \
178 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
179 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
180
181#define CHECK_RELEASED(mv) \
182 if (BASE_INACCESSIBLE(mv)) { \
183 PyErr_SetString(PyExc_ValueError, \
184 "operation forbidden on released memoryview object"); \
185 return NULL; \
186 }
187
188#define CHECK_RELEASED_INT(mv) \
189 if (BASE_INACCESSIBLE(mv)) { \
190 PyErr_SetString(PyExc_ValueError, \
191 "operation forbidden on released memoryview object"); \
192 return -1; \
193 }
194
195#define CHECK_LIST_OR_TUPLE(v) \
196 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
197 PyErr_SetString(PyExc_TypeError, \
198 #v " must be a list or a tuple"); \
199 return NULL; \
200 }
201
202#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
203
204/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100205#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100206/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100207#define ADJUST_PTR(ptr, suboffsets, dim) \
208 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100209
210/* Memoryview buffer properties */
211#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
212#define MV_F_CONTIGUOUS(flags) \
213 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
214#define MV_ANY_CONTIGUOUS(flags) \
215 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
216
217/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
218#define MV_CONTIGUOUS_NDIM1(view) \
219 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
220
221/* getbuffer() requests */
222#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
223#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
224#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
225#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
226#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
227#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
228#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
229#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
230
231
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000232PyDoc_STRVAR(memory_doc,
Stefan Krah195319e2016-12-30 12:23:35 +0100233"memoryview(object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000234\n\
235Create a new memoryview object which references the given object.");
236
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100237
238/**************************************************************************/
239/* Copy memoryview buffers */
240/**************************************************************************/
241
242/* The functions in this section take a source and a destination buffer
243 with the same logical structure: format, itemsize, ndim and shape
244 are identical, with ndim > 0.
245
246 NOTE: All buffers are assumed to have PyBUF_FULL information, which
247 is the case for memoryviews! */
248
249
250/* Assumptions: ndim >= 1. The macro tests for a corner case that should
251 perhaps be explicitly forbidden in the PEP. */
252#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
253 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
254
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700255static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000256last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100257{
258 assert(dest->ndim > 0 && src->ndim > 0);
259 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
260 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
261 dest->strides[dest->ndim-1] == dest->itemsize &&
262 src->strides[src->ndim-1] == src->itemsize);
263}
264
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000265/* This is not a general function for determining format equivalence.
266 It is used in copy_single() and copy_buffer() to weed out non-matching
267 formats. Skipping the '@' character is specifically used in slice
268 assignments, where the lvalue is already known to have a single character
269 format. This is a performance hack that could be rewritten (if properly
270 benchmarked). */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700271static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000272equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100273{
274 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100275
276 assert(dest->format && src->format);
277 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
278 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
279
280 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000281 dest->itemsize != src->itemsize) {
282 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100283 }
284
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000285 return 1;
286}
287
288/* Two shapes are equivalent if they are either equal or identical up
289 to a zero element at the same position. For example, in NumPy arrays
290 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700291static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000292equiv_shape(const Py_buffer *dest, const Py_buffer *src)
293{
294 int i;
295
296 if (dest->ndim != src->ndim)
297 return 0;
298
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100299 for (i = 0; i < dest->ndim; i++) {
300 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000301 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100302 if (dest->shape[i] == 0)
303 break;
304 }
305
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000306 return 1;
307}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100308
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000309/* Check that the logical structure of the destination and source buffers
310 is identical. */
311static int
312equiv_structure(const Py_buffer *dest, const Py_buffer *src)
313{
314 if (!equiv_format(dest, src) ||
315 !equiv_shape(dest, src)) {
316 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100317 "memoryview assignment: lvalue and rvalue have different "
318 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000319 return 0;
320 }
321
322 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100323}
324
325/* Base case for recursive multi-dimensional copying. Contiguous arrays are
326 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
327 sizeof(mem) == shape[0] * itemsize. */
328static void
329copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
330 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
331 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
332 char *mem)
333{
334 if (mem == NULL) { /* contiguous */
335 Py_ssize_t size = shape[0] * itemsize;
336 if (dptr + size < sptr || sptr + size < dptr)
337 memcpy(dptr, sptr, size); /* no overlapping */
338 else
339 memmove(dptr, sptr, size);
340 }
341 else {
342 char *p;
343 Py_ssize_t i;
344 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100345 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100346 memcpy(p, xsptr, itemsize);
347 }
348 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100349 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100350 memcpy(xdptr, p, itemsize);
351 }
352 }
353
354}
355
356/* Recursively copy a source buffer to a destination buffer. The two buffers
357 have the same ndim, shape and itemsize. */
358static void
359copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
360 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
361 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
362 char *mem)
363{
364 Py_ssize_t i;
365
366 assert(ndim >= 1);
367
368 if (ndim == 1) {
369 copy_base(shape, itemsize,
370 dptr, dstrides, dsuboffsets,
371 sptr, sstrides, ssuboffsets,
372 mem);
373 return;
374 }
375
376 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100377 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
378 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100379
380 copy_rec(shape+1, ndim-1, itemsize,
381 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
382 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
383 mem);
384 }
385}
386
387/* Faster copying of one-dimensional arrays. */
388static int
389copy_single(Py_buffer *dest, Py_buffer *src)
390{
391 char *mem = NULL;
392
393 assert(dest->ndim == 1);
394
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000395 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100396 return -1;
397
398 if (!last_dim_is_contiguous(dest, src)) {
399 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
400 if (mem == NULL) {
401 PyErr_NoMemory();
402 return -1;
403 }
404 }
405
406 copy_base(dest->shape, dest->itemsize,
407 dest->buf, dest->strides, dest->suboffsets,
408 src->buf, src->strides, src->suboffsets,
409 mem);
410
411 if (mem)
412 PyMem_Free(mem);
413
414 return 0;
415}
416
417/* Recursively copy src to dest. Both buffers must have the same basic
418 structure. Copying is atomic, the function never fails with a partial
419 copy. */
420static int
421copy_buffer(Py_buffer *dest, Py_buffer *src)
422{
423 char *mem = NULL;
424
425 assert(dest->ndim > 0);
426
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000427 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100428 return -1;
429
430 if (!last_dim_is_contiguous(dest, src)) {
431 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
432 if (mem == NULL) {
433 PyErr_NoMemory();
434 return -1;
435 }
436 }
437
438 copy_rec(dest->shape, dest->ndim, dest->itemsize,
439 dest->buf, dest->strides, dest->suboffsets,
440 src->buf, src->strides, src->suboffsets,
441 mem);
442
443 if (mem)
444 PyMem_Free(mem);
445
446 return 0;
447}
448
449/* Initialize strides for a C-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700450static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100451init_strides_from_shape(Py_buffer *view)
452{
453 Py_ssize_t i;
454
455 assert(view->ndim > 0);
456
457 view->strides[view->ndim-1] = view->itemsize;
458 for (i = view->ndim-2; i >= 0; i--)
459 view->strides[i] = view->strides[i+1] * view->shape[i+1];
460}
461
462/* Initialize strides for a Fortran-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700463static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100464init_fortran_strides_from_shape(Py_buffer *view)
465{
466 Py_ssize_t i;
467
468 assert(view->ndim > 0);
469
470 view->strides[0] = view->itemsize;
471 for (i = 1; i < view->ndim; i++)
472 view->strides[i] = view->strides[i-1] * view->shape[i-1];
473}
474
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200475/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
476 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100477 len(mem) == src->len. */
478static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200479buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100480{
481 Py_buffer dest;
482 Py_ssize_t *strides;
483 int ret;
484
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200485 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100486 assert(src->shape != NULL);
487 assert(src->strides != NULL);
488
489 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
490 if (strides == NULL) {
491 PyErr_NoMemory();
492 return -1;
493 }
494
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200495 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100496 dest = *src;
497 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200498 /* shape is constant and shared: the logical representation of the
499 array is unaltered. */
500
501 /* The physical representation determined by strides (and possibly
502 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100503 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200504 if (order == 'C' || order == 'A') {
505 init_strides_from_shape(&dest);
506 }
507 else {
508 init_fortran_strides_from_shape(&dest);
509 }
510
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100511 dest.suboffsets = NULL;
512
513 ret = copy_buffer(&dest, src);
514
515 PyMem_Free(strides);
516 return ret;
517}
518
519
520/****************************************************************************/
521/* Constructors */
522/****************************************************************************/
523
524/* Initialize values that are shared with the managed buffer. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700525static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100526init_shared_values(Py_buffer *dest, const Py_buffer *src)
527{
528 dest->obj = src->obj;
529 dest->buf = src->buf;
530 dest->len = src->len;
531 dest->itemsize = src->itemsize;
532 dest->readonly = src->readonly;
533 dest->format = src->format ? src->format : "B";
534 dest->internal = src->internal;
535}
536
537/* Copy shape and strides. Reconstruct missing values. */
538static void
539init_shape_strides(Py_buffer *dest, const Py_buffer *src)
540{
541 Py_ssize_t i;
542
543 if (src->ndim == 0) {
544 dest->shape = NULL;
545 dest->strides = NULL;
546 return;
547 }
548 if (src->ndim == 1) {
549 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
550 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
551 return;
552 }
553
554 for (i = 0; i < src->ndim; i++)
555 dest->shape[i] = src->shape[i];
556 if (src->strides) {
557 for (i = 0; i < src->ndim; i++)
558 dest->strides[i] = src->strides[i];
559 }
560 else {
561 init_strides_from_shape(dest);
562 }
563}
564
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700565static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100566init_suboffsets(Py_buffer *dest, const Py_buffer *src)
567{
568 Py_ssize_t i;
569
570 if (src->suboffsets == NULL) {
571 dest->suboffsets = NULL;
572 return;
573 }
574 for (i = 0; i < src->ndim; i++)
575 dest->suboffsets[i] = src->suboffsets[i];
576}
577
578/* len = product(shape) * itemsize */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700579static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100580init_len(Py_buffer *view)
581{
582 Py_ssize_t i, len;
583
584 len = 1;
585 for (i = 0; i < view->ndim; i++)
586 len *= view->shape[i];
587 len *= view->itemsize;
588
589 view->len = len;
590}
591
592/* Initialize memoryview buffer properties. */
593static void
594init_flags(PyMemoryViewObject *mv)
595{
596 const Py_buffer *view = &mv->view;
597 int flags = 0;
598
599 switch (view->ndim) {
600 case 0:
601 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
602 _Py_MEMORYVIEW_FORTRAN);
603 break;
604 case 1:
605 if (MV_CONTIGUOUS_NDIM1(view))
606 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
607 break;
608 default:
609 if (PyBuffer_IsContiguous(view, 'C'))
610 flags |= _Py_MEMORYVIEW_C;
611 if (PyBuffer_IsContiguous(view, 'F'))
612 flags |= _Py_MEMORYVIEW_FORTRAN;
613 break;
614 }
615
616 if (view->suboffsets) {
617 flags |= _Py_MEMORYVIEW_PIL;
618 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
619 }
620
621 mv->flags = flags;
622}
623
624/* Allocate a new memoryview and perform basic initialization. New memoryviews
625 are exclusively created through the mbuf_add functions. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700626static inline PyMemoryViewObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100627memory_alloc(int ndim)
628{
629 PyMemoryViewObject *mv;
630
631 mv = (PyMemoryViewObject *)
632 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
633 if (mv == NULL)
634 return NULL;
635
636 mv->mbuf = NULL;
637 mv->hash = -1;
638 mv->flags = 0;
639 mv->exports = 0;
640 mv->view.ndim = ndim;
641 mv->view.shape = mv->ob_array;
642 mv->view.strides = mv->ob_array + ndim;
643 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100644 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100645
646 _PyObject_GC_TRACK(mv);
647 return mv;
648}
649
650/*
651 Return a new memoryview that is registered with mbuf. If src is NULL,
652 use mbuf->master as the underlying buffer. Otherwise, use src.
653
654 The new memoryview has full buffer information: shape and strides
655 are always present, suboffsets as needed. Arrays are copied to
656 the memoryview's ob_array field.
657 */
658static PyObject *
659mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
660{
661 PyMemoryViewObject *mv;
662 Py_buffer *dest;
663
664 if (src == NULL)
665 src = &mbuf->master;
666
667 if (src->ndim > PyBUF_MAX_NDIM) {
668 PyErr_SetString(PyExc_ValueError,
669 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200670 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100671 return NULL;
672 }
673
674 mv = memory_alloc(src->ndim);
675 if (mv == NULL)
676 return NULL;
677
678 dest = &mv->view;
679 init_shared_values(dest, src);
680 init_shape_strides(dest, src);
681 init_suboffsets(dest, src);
682 init_flags(mv);
683
684 mv->mbuf = mbuf;
685 Py_INCREF(mbuf);
686 mbuf->exports++;
687
688 return (PyObject *)mv;
689}
690
691/* Register an incomplete view: shape, strides, suboffsets and flags still
692 need to be initialized. Use 'ndim' instead of src->ndim to determine the
693 size of the memoryview's ob_array.
694
695 Assumption: ndim <= PyBUF_MAX_NDIM. */
696static PyObject *
697mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
698 int ndim)
699{
700 PyMemoryViewObject *mv;
701 Py_buffer *dest;
702
703 if (src == NULL)
704 src = &mbuf->master;
705
706 assert(ndim <= PyBUF_MAX_NDIM);
707
708 mv = memory_alloc(ndim);
709 if (mv == NULL)
710 return NULL;
711
712 dest = &mv->view;
713 init_shared_values(dest, src);
714
715 mv->mbuf = mbuf;
716 Py_INCREF(mbuf);
717 mbuf->exports++;
718
719 return (PyObject *)mv;
720}
721
722/* Expose a raw memory area as a view of contiguous bytes. flags can be
723 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
724 The memoryview has complete buffer information. */
725PyObject *
726PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
727{
728 _PyManagedBufferObject *mbuf;
729 PyObject *mv;
730 int readonly;
731
732 assert(mem != NULL);
733 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
734
735 mbuf = mbuf_alloc();
736 if (mbuf == NULL)
737 return NULL;
738
739 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
740 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
741 PyBUF_FULL_RO);
742
743 mv = mbuf_add_view(mbuf, NULL);
744 Py_DECREF(mbuf);
745
746 return mv;
747}
748
749/* Create a memoryview from a given Py_buffer. For simple byte views,
750 PyMemoryView_FromMemory() should be used instead.
751 This function is the only entry point that can create a master buffer
752 without full information. Because of this fact init_shape_strides()
753 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000754PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000755PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000756{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100757 _PyManagedBufferObject *mbuf;
758 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000759
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000760 if (info->buf == NULL) {
761 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100762 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000763 return NULL;
764 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100765
766 mbuf = mbuf_alloc();
767 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000768 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100769
770 /* info->obj is either NULL or a borrowed reference. This reference
771 should not be decremented in PyBuffer_Release(). */
772 mbuf->master = *info;
773 mbuf->master.obj = NULL;
774
775 mv = mbuf_add_view(mbuf, NULL);
776 Py_DECREF(mbuf);
777
778 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000779}
780
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100781/* Create a memoryview from an object that implements the buffer protocol.
782 If the object is a memoryview, the new memoryview must be registered
783 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000784PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100785PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000786{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100787 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000788
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100789 if (PyMemoryView_Check(v)) {
790 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
791 CHECK_RELEASED(mv);
792 return mbuf_add_view(mv->mbuf, &mv->view);
793 }
794 else if (PyObject_CheckBuffer(v)) {
795 PyObject *ret;
796 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
797 if (mbuf == NULL)
798 return NULL;
799 ret = mbuf_add_view(mbuf, NULL);
800 Py_DECREF(mbuf);
801 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000802 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000803
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100804 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400805 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100806 Py_TYPE(v)->tp_name);
807 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000808}
809
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100810/* Copy the format string from a base object that might vanish. */
811static int
812mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
813{
814 if (fmt != NULL) {
815 char *cp = PyMem_Malloc(strlen(fmt)+1);
816 if (cp == NULL) {
817 PyErr_NoMemory();
818 return -1;
819 }
820 mbuf->master.format = strcpy(cp, fmt);
821 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
822 }
823
824 return 0;
825}
826
827/*
828 Return a memoryview that is based on a contiguous copy of src.
829 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
830
831 Ownership rules:
832 1) As usual, the returned memoryview has a private copy
833 of src->shape, src->strides and src->suboffsets.
834 2) src->format is copied to the master buffer and released
835 in mbuf_dealloc(). The releasebufferproc of the bytes
836 object is NULL, so it does not matter that mbuf_release()
837 passes the altered format pointer to PyBuffer_Release().
838*/
839static PyObject *
840memory_from_contiguous_copy(Py_buffer *src, char order)
841{
842 _PyManagedBufferObject *mbuf;
843 PyMemoryViewObject *mv;
844 PyObject *bytes;
845 Py_buffer *dest;
846 int i;
847
848 assert(src->ndim > 0);
849 assert(src->shape != NULL);
850
851 bytes = PyBytes_FromStringAndSize(NULL, src->len);
852 if (bytes == NULL)
853 return NULL;
854
855 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
856 Py_DECREF(bytes);
857 if (mbuf == NULL)
858 return NULL;
859
860 if (mbuf_copy_format(mbuf, src->format) < 0) {
861 Py_DECREF(mbuf);
862 return NULL;
863 }
864
865 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
866 Py_DECREF(mbuf);
867 if (mv == NULL)
868 return NULL;
869
870 dest = &mv->view;
871
872 /* shared values are initialized correctly except for itemsize */
873 dest->itemsize = src->itemsize;
874
875 /* shape and strides */
876 for (i = 0; i < src->ndim; i++) {
877 dest->shape[i] = src->shape[i];
878 }
879 if (order == 'C' || order == 'A') {
880 init_strides_from_shape(dest);
881 }
882 else {
883 init_fortran_strides_from_shape(dest);
884 }
885 /* suboffsets */
886 dest->suboffsets = NULL;
887
888 /* flags */
889 init_flags(mv);
890
891 if (copy_buffer(dest, src) < 0) {
892 Py_DECREF(mv);
893 return NULL;
894 }
895
896 return (PyObject *)mv;
897}
898
899/*
900 Return a new memoryview object based on a contiguous exporter with
901 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
902 The logical structure of the input and output buffers is the same
903 (i.e. tolist(input) == tolist(output)), but the physical layout in
904 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200905
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100906 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
907 otherwise it may be writable or read-only.
908
909 If the exporter is already contiguous with the desired target order,
910 the memoryview will be directly based on the exporter.
911
912 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
913 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
914 'F'ortran order otherwise.
915*/
916PyObject *
917PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
918{
919 PyMemoryViewObject *mv;
920 PyObject *ret;
921 Py_buffer *view;
922
923 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
924 assert(order == 'C' || order == 'F' || order == 'A');
925
926 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
927 if (mv == NULL)
928 return NULL;
929
930 view = &mv->view;
931 if (buffertype == PyBUF_WRITE && view->readonly) {
932 PyErr_SetString(PyExc_BufferError,
933 "underlying buffer is not writable");
934 Py_DECREF(mv);
935 return NULL;
936 }
937
938 if (PyBuffer_IsContiguous(view, order))
939 return (PyObject *)mv;
940
941 if (buffertype == PyBUF_WRITE) {
942 PyErr_SetString(PyExc_BufferError,
943 "writable contiguous buffer requested "
944 "for a non-contiguous object.");
945 Py_DECREF(mv);
946 return NULL;
947 }
948
949 ret = memory_from_contiguous_copy(view, order);
950 Py_DECREF(mv);
951 return ret;
952}
953
954
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000955static PyObject *
956memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
957{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000958 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100959 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000960
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000961 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
962 &obj)) {
963 return NULL;
964 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000965
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000966 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000967}
968
969
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100970/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200971/* Previously in abstract.c */
972/****************************************************************************/
973
974typedef struct {
975 Py_buffer view;
976 Py_ssize_t array[1];
977} Py_buffer_full;
978
979int
980PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
981{
982 Py_buffer_full *fb = NULL;
983 int ret;
984
985 assert(order == 'C' || order == 'F' || order == 'A');
986
987 if (len != src->len) {
988 PyErr_SetString(PyExc_ValueError,
989 "PyBuffer_ToContiguous: len != view->len");
990 return -1;
991 }
992
993 if (PyBuffer_IsContiguous(src, order)) {
994 memcpy((char *)buf, src->buf, len);
995 return 0;
996 }
997
998 /* buffer_to_contiguous() assumes PyBUF_FULL */
999 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
1000 if (fb == NULL) {
1001 PyErr_NoMemory();
1002 return -1;
1003 }
1004 fb->view.ndim = src->ndim;
1005 fb->view.shape = fb->array;
1006 fb->view.strides = fb->array + src->ndim;
1007 fb->view.suboffsets = fb->array + 2 * src->ndim;
1008
1009 init_shared_values(&fb->view, src);
1010 init_shape_strides(&fb->view, src);
1011 init_suboffsets(&fb->view, src);
1012
1013 src = &fb->view;
1014
1015 ret = buffer_to_contiguous(buf, src, order);
1016 PyMem_Free(fb);
1017 return ret;
1018}
1019
1020
1021/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001022/* Release/GC management */
1023/****************************************************************************/
1024
1025/* Inform the managed buffer that this particular memoryview will not access
1026 the underlying buffer again. If no other memoryviews are registered with
1027 the managed buffer, the underlying buffer is released instantly and
1028 marked as inaccessible for both the memoryview and the managed buffer.
1029
1030 This function fails if the memoryview itself has exported buffers. */
1031static int
1032_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001033{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001034 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1035 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001036
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001037 if (self->exports == 0) {
1038 self->flags |= _Py_MEMORYVIEW_RELEASED;
1039 assert(self->mbuf->exports > 0);
1040 if (--self->mbuf->exports == 0)
1041 mbuf_release(self->mbuf);
1042 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001043 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001044 if (self->exports > 0) {
1045 PyErr_Format(PyExc_BufferError,
1046 "memoryview has %zd exported buffer%s", self->exports,
1047 self->exports==1 ? "" : "s");
1048 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001049 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001050
Victor Stinner47ee8a62020-01-27 22:37:44 +01001051 PyErr_SetString(PyExc_SystemError,
1052 "_memory_release(): negative export count");
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001053 return -1;
1054}
1055
1056static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001057memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001058{
1059 if (_memory_release(self) < 0)
1060 return NULL;
1061 Py_RETURN_NONE;
1062}
1063
1064static void
1065memory_dealloc(PyMemoryViewObject *self)
1066{
1067 assert(self->exports == 0);
1068 _PyObject_GC_UNTRACK(self);
1069 (void)_memory_release(self);
1070 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001071 if (self->weakreflist != NULL)
1072 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001073 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001074}
1075
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001076static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001077memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001078{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001079 Py_VISIT(self->mbuf);
1080 return 0;
1081}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001082
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001083static int
1084memory_clear(PyMemoryViewObject *self)
1085{
1086 (void)_memory_release(self);
1087 Py_CLEAR(self->mbuf);
1088 return 0;
1089}
1090
1091static PyObject *
1092memory_enter(PyObject *self, PyObject *args)
1093{
1094 CHECK_RELEASED(self);
1095 Py_INCREF(self);
1096 return self;
1097}
1098
1099static PyObject *
1100memory_exit(PyObject *self, PyObject *args)
1101{
Stefan Krahe4c07992012-07-28 14:10:02 +02001102 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001103}
1104
1105
1106/****************************************************************************/
1107/* Casting format and shape */
1108/****************************************************************************/
1109
1110#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1111
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001112static inline Py_ssize_t
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001113get_native_fmtchar(char *result, const char *fmt)
1114{
1115 Py_ssize_t size = -1;
1116
1117 if (fmt[0] == '@') fmt++;
1118
1119 switch (fmt[0]) {
1120 case 'c': case 'b': case 'B': size = sizeof(char); break;
1121 case 'h': case 'H': size = sizeof(short); break;
1122 case 'i': case 'I': size = sizeof(int); break;
1123 case 'l': case 'L': size = sizeof(long); break;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001124 case 'q': case 'Q': size = sizeof(long long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001125 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1126 case 'f': size = sizeof(float); break;
1127 case 'd': size = sizeof(double); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001128 case '?': size = sizeof(_Bool); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001129 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001130 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001131
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001132 if (size > 0 && fmt[1] == '\0') {
1133 *result = fmt[0];
1134 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001135 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001136
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001137 return -1;
1138}
1139
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001140static inline const char *
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001141get_native_fmtstr(const char *fmt)
1142{
1143 int at = 0;
1144
1145 if (fmt[0] == '@') {
1146 at = 1;
1147 fmt++;
1148 }
1149 if (fmt[0] == '\0' || fmt[1] != '\0') {
1150 return NULL;
1151 }
1152
1153#define RETURN(s) do { return at ? "@" s : s; } while (0)
1154
1155 switch (fmt[0]) {
1156 case 'c': RETURN("c");
1157 case 'b': RETURN("b");
1158 case 'B': RETURN("B");
1159 case 'h': RETURN("h");
1160 case 'H': RETURN("H");
1161 case 'i': RETURN("i");
1162 case 'I': RETURN("I");
1163 case 'l': RETURN("l");
1164 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001165 case 'q': RETURN("q");
1166 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001167 case 'n': RETURN("n");
1168 case 'N': RETURN("N");
1169 case 'f': RETURN("f");
1170 case 'd': RETURN("d");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001171 case '?': RETURN("?");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001172 case 'P': RETURN("P");
1173 }
1174
1175 return NULL;
1176}
1177
1178
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001179/* Cast a memoryview's data type to 'format'. The input array must be
1180 C-contiguous. At least one of input-format, output-format must have
1181 byte size. The output array is 1-D, with the same byte length as the
1182 input array. Thus, view->len must be a multiple of the new itemsize. */
1183static int
1184cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1185{
1186 Py_buffer *view = &mv->view;
1187 PyObject *asciifmt;
1188 char srcchar, destchar;
1189 Py_ssize_t itemsize;
1190 int ret = -1;
1191
1192 assert(view->ndim >= 1);
1193 assert(Py_SIZE(mv) == 3*view->ndim);
1194 assert(view->shape == mv->ob_array);
1195 assert(view->strides == mv->ob_array + view->ndim);
1196 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1197
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001198 asciifmt = PyUnicode_AsASCIIString(format);
1199 if (asciifmt == NULL)
1200 return ret;
1201
1202 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1203 if (itemsize < 0) {
1204 PyErr_SetString(PyExc_ValueError,
1205 "memoryview: destination format must be a native single "
1206 "character format prefixed with an optional '@'");
1207 goto out;
1208 }
1209
Stefan Krah0c515952015-08-08 13:38:10 +02001210 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1211 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001212 PyErr_SetString(PyExc_TypeError,
1213 "memoryview: cannot cast between two non-byte formats");
1214 goto out;
1215 }
1216 if (view->len % itemsize) {
1217 PyErr_SetString(PyExc_TypeError,
1218 "memoryview: length is not a multiple of itemsize");
1219 goto out;
1220 }
1221
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001222 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001223 if (view->format == NULL) {
1224 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1225 PyErr_SetString(PyExc_RuntimeError,
1226 "memoryview: internal error");
1227 goto out;
1228 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001229 view->itemsize = itemsize;
1230
1231 view->ndim = 1;
1232 view->shape[0] = view->len / view->itemsize;
1233 view->strides[0] = view->itemsize;
1234 view->suboffsets = NULL;
1235
1236 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001237
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001238 ret = 0;
1239
1240out:
1241 Py_DECREF(asciifmt);
1242 return ret;
1243}
1244
1245/* The memoryview must have space for 3*len(seq) elements. */
1246static Py_ssize_t
1247copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1248 Py_ssize_t itemsize)
1249{
1250 Py_ssize_t x, i;
1251 Py_ssize_t len = itemsize;
1252
1253 for (i = 0; i < ndim; i++) {
1254 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1255 if (!PyLong_Check(tmp)) {
1256 PyErr_SetString(PyExc_TypeError,
1257 "memoryview.cast(): elements of shape must be integers");
1258 return -1;
1259 }
1260 x = PyLong_AsSsize_t(tmp);
1261 if (x == -1 && PyErr_Occurred()) {
1262 return -1;
1263 }
1264 if (x <= 0) {
1265 /* In general elements of shape may be 0, but not for casting. */
1266 PyErr_Format(PyExc_ValueError,
1267 "memoryview.cast(): elements of shape must be integers > 0");
1268 return -1;
1269 }
1270 if (x > PY_SSIZE_T_MAX / len) {
1271 PyErr_Format(PyExc_ValueError,
1272 "memoryview.cast(): product(shape) > SSIZE_MAX");
1273 return -1;
1274 }
1275 len *= x;
1276 shape[i] = x;
1277 }
1278
1279 return len;
1280}
1281
1282/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1283 If the result array does not have exactly the same byte length as the
1284 input array, raise ValueError. */
1285static int
1286cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1287{
1288 Py_buffer *view = &mv->view;
1289 Py_ssize_t len;
1290
1291 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1292 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1293 assert(view->shape == mv->ob_array);
1294 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1295 assert(view->suboffsets == NULL);
1296
1297 view->ndim = ndim;
1298 if (view->ndim == 0) {
1299 view->shape = NULL;
1300 view->strides = NULL;
1301 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001302 }
1303 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001304 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1305 if (len < 0)
1306 return -1;
1307 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001308 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001309
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001310 if (view->len != len) {
1311 PyErr_SetString(PyExc_TypeError,
1312 "memoryview: product(shape) * itemsize != buffer size");
1313 return -1;
1314 }
1315
1316 init_flags(mv);
1317
1318 return 0;
1319}
1320
1321static int
1322zero_in_shape(PyMemoryViewObject *mv)
1323{
1324 Py_buffer *view = &mv->view;
1325 Py_ssize_t i;
1326
1327 for (i = 0; i < view->ndim; i++)
1328 if (view->shape[i] == 0)
1329 return 1;
1330
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001331 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001332}
1333
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001334/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001335 Cast a copy of 'self' to a different view. The input view must
1336 be C-contiguous. The function always casts the input view to a
1337 1-D output according to 'format'. At least one of input-format,
1338 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001339
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001340 If 'shape' is given, the 1-D view from the previous step will
1341 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001342
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001343 All casts must result in views that will have the exact byte
1344 size of the original input. Otherwise, an error is raised.
1345*/
1346static PyObject *
1347memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001348{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001349 static char *kwlist[] = {"format", "shape", NULL};
1350 PyMemoryViewObject *mv = NULL;
1351 PyObject *shape = NULL;
1352 PyObject *format;
1353 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001354
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001355 CHECK_RELEASED(self);
1356
1357 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1358 &format, &shape)) {
1359 return NULL;
1360 }
1361 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001362 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001363 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001364 return NULL;
1365 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001366 if (!MV_C_CONTIGUOUS(self->flags)) {
1367 PyErr_SetString(PyExc_TypeError,
1368 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001369 return NULL;
1370 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001371 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001372 PyErr_SetString(PyExc_TypeError,
1373 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001374 return NULL;
1375 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001376 if (shape) {
1377 CHECK_LIST_OR_TUPLE(shape)
1378 ndim = PySequence_Fast_GET_SIZE(shape);
1379 if (ndim > PyBUF_MAX_NDIM) {
1380 PyErr_SetString(PyExc_ValueError,
1381 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001382 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001383 return NULL;
1384 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001385 if (self->view.ndim != 1 && ndim != 1) {
1386 PyErr_SetString(PyExc_TypeError,
1387 "memoryview: cast must be 1D -> ND or ND -> 1D");
1388 return NULL;
1389 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001390 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001391
1392 mv = (PyMemoryViewObject *)
1393 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1394 if (mv == NULL)
1395 return NULL;
1396
1397 if (cast_to_1D(mv, format) < 0)
1398 goto error;
1399 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1400 goto error;
1401
1402 return (PyObject *)mv;
1403
1404error:
1405 Py_DECREF(mv);
1406 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001407}
1408
Antoine Pitrou480ab052018-04-14 19:49:21 +02001409static PyObject *
1410memory_toreadonly(PyMemoryViewObject *self, PyObject *noargs)
1411{
1412 CHECK_RELEASED(self);
1413 /* Even if self is already readonly, we still need to create a new
1414 * object for .release() to work correctly.
1415 */
1416 self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1417 if (self != NULL) {
1418 self->view.readonly = 1;
1419 };
1420 return (PyObject *) self;
1421}
1422
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001423
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001424/**************************************************************************/
1425/* getbuffer */
1426/**************************************************************************/
1427
1428static int
1429memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1430{
1431 Py_buffer *base = &self->view;
1432 int baseflags = self->flags;
1433
1434 CHECK_RELEASED_INT(self);
1435
1436 /* start with complete information */
1437 *view = *base;
1438 view->obj = NULL;
1439
1440 if (REQ_WRITABLE(flags) && base->readonly) {
1441 PyErr_SetString(PyExc_BufferError,
1442 "memoryview: underlying buffer is not writable");
1443 return -1;
1444 }
1445 if (!REQ_FORMAT(flags)) {
1446 /* NULL indicates that the buffer's data type has been cast to 'B'.
1447 view->itemsize is the _previous_ itemsize. If shape is present,
1448 the equality product(shape) * itemsize = len still holds at this
1449 point. The equality calcsize(format) = itemsize does _not_ hold
1450 from here on! */
1451 view->format = NULL;
1452 }
1453
1454 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1455 PyErr_SetString(PyExc_BufferError,
1456 "memoryview: underlying buffer is not C-contiguous");
1457 return -1;
1458 }
1459 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1460 PyErr_SetString(PyExc_BufferError,
1461 "memoryview: underlying buffer is not Fortran contiguous");
1462 return -1;
1463 }
1464 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1465 PyErr_SetString(PyExc_BufferError,
1466 "memoryview: underlying buffer is not contiguous");
1467 return -1;
1468 }
1469 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1470 PyErr_SetString(PyExc_BufferError,
1471 "memoryview: underlying buffer requires suboffsets");
1472 return -1;
1473 }
1474 if (!REQ_STRIDES(flags)) {
1475 if (!MV_C_CONTIGUOUS(baseflags)) {
1476 PyErr_SetString(PyExc_BufferError,
1477 "memoryview: underlying buffer is not C-contiguous");
1478 return -1;
1479 }
1480 view->strides = NULL;
1481 }
1482 if (!REQ_SHAPE(flags)) {
1483 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1484 so base->buf = ndbuf->data. */
1485 if (view->format != NULL) {
1486 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1487 not make sense. */
1488 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001489 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001490 "is present");
1491 return -1;
1492 }
1493 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1494 do _not_ hold from here on! */
1495 view->ndim = 1;
1496 view->shape = NULL;
1497 }
1498
1499
1500 view->obj = (PyObject *)self;
1501 Py_INCREF(view->obj);
1502 self->exports++;
1503
1504 return 0;
1505}
1506
1507static void
1508memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1509{
1510 self->exports--;
1511 return;
1512 /* PyBuffer_Release() decrements view->obj after this function returns. */
1513}
1514
1515/* Buffer methods */
1516static PyBufferProcs memory_as_buffer = {
1517 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1518 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1519};
1520
1521
1522/****************************************************************************/
1523/* Optimized pack/unpack for all native format specifiers */
1524/****************************************************************************/
1525
1526/*
1527 Fix exceptions:
1528 1) Include format string in the error message.
1529 2) OverflowError -> ValueError.
1530 3) The error message from PyNumber_Index() is not ideal.
1531*/
1532static int
1533type_error_int(const char *fmt)
1534{
1535 PyErr_Format(PyExc_TypeError,
1536 "memoryview: invalid type for format '%s'", fmt);
1537 return -1;
1538}
1539
1540static int
1541value_error_int(const char *fmt)
1542{
1543 PyErr_Format(PyExc_ValueError,
1544 "memoryview: invalid value for format '%s'", fmt);
1545 return -1;
1546}
1547
1548static int
1549fix_error_int(const char *fmt)
1550{
1551 assert(PyErr_Occurred());
1552 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1553 PyErr_Clear();
1554 return type_error_int(fmt);
1555 }
1556 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1557 PyErr_ExceptionMatches(PyExc_ValueError)) {
1558 PyErr_Clear();
1559 return value_error_int(fmt);
1560 }
1561
1562 return -1;
1563}
1564
1565/* Accept integer objects or objects with an __index__() method. */
1566static long
1567pylong_as_ld(PyObject *item)
1568{
1569 PyObject *tmp;
1570 long ld;
1571
1572 tmp = PyNumber_Index(item);
1573 if (tmp == NULL)
1574 return -1;
1575
1576 ld = PyLong_AsLong(tmp);
1577 Py_DECREF(tmp);
1578 return ld;
1579}
1580
1581static unsigned long
1582pylong_as_lu(PyObject *item)
1583{
1584 PyObject *tmp;
1585 unsigned long lu;
1586
1587 tmp = PyNumber_Index(item);
1588 if (tmp == NULL)
1589 return (unsigned long)-1;
1590
1591 lu = PyLong_AsUnsignedLong(tmp);
1592 Py_DECREF(tmp);
1593 return lu;
1594}
1595
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001596static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001597pylong_as_lld(PyObject *item)
1598{
1599 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001600 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001601
1602 tmp = PyNumber_Index(item);
1603 if (tmp == NULL)
1604 return -1;
1605
1606 lld = PyLong_AsLongLong(tmp);
1607 Py_DECREF(tmp);
1608 return lld;
1609}
1610
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001611static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001612pylong_as_llu(PyObject *item)
1613{
1614 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001615 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001616
1617 tmp = PyNumber_Index(item);
1618 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001619 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001620
1621 llu = PyLong_AsUnsignedLongLong(tmp);
1622 Py_DECREF(tmp);
1623 return llu;
1624}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001625
1626static Py_ssize_t
1627pylong_as_zd(PyObject *item)
1628{
1629 PyObject *tmp;
1630 Py_ssize_t zd;
1631
1632 tmp = PyNumber_Index(item);
1633 if (tmp == NULL)
1634 return -1;
1635
1636 zd = PyLong_AsSsize_t(tmp);
1637 Py_DECREF(tmp);
1638 return zd;
1639}
1640
1641static size_t
1642pylong_as_zu(PyObject *item)
1643{
1644 PyObject *tmp;
1645 size_t zu;
1646
1647 tmp = PyNumber_Index(item);
1648 if (tmp == NULL)
1649 return (size_t)-1;
1650
1651 zu = PyLong_AsSize_t(tmp);
1652 Py_DECREF(tmp);
1653 return zu;
1654}
1655
1656/* Timings with the ndarray from _testbuffer.c indicate that using the
1657 struct module is around 15x slower than the two functions below. */
1658
1659#define UNPACK_SINGLE(dest, ptr, type) \
1660 do { \
1661 type x; \
1662 memcpy((char *)&x, ptr, sizeof x); \
1663 dest = x; \
1664 } while (0)
1665
1666/* Unpack a single item. 'fmt' can be any native format character in struct
1667 module syntax. This function is very sensitive to small changes. With this
1668 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001669static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001670unpack_single(const char *ptr, const char *fmt)
1671{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001672 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001673 unsigned long lu;
1674 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001675 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001676 long ld;
1677 Py_ssize_t zd;
1678 double d;
1679 unsigned char uc;
1680 void *p;
1681
1682 switch (fmt[0]) {
1683
1684 /* signed integers and fast path for 'B' */
1685 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1686 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1687 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1688 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1689 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1690
1691 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001692 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001693
1694 /* unsigned integers */
1695 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1696 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1697 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1698
1699 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001700 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1701 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001702
1703 /* ssize_t and size_t */
1704 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1705 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1706
1707 /* floats */
1708 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1709 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1710
1711 /* bytes object */
1712 case 'c': goto convert_bytes;
1713
1714 /* pointer */
1715 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1716
1717 /* default */
1718 default: goto err_format;
1719 }
1720
1721convert_uc:
1722 /* PyLong_FromUnsignedLong() is slower */
1723 return PyLong_FromLong(uc);
1724convert_ld:
1725 return PyLong_FromLong(ld);
1726convert_lu:
1727 return PyLong_FromUnsignedLong(lu);
1728convert_lld:
1729 return PyLong_FromLongLong(lld);
1730convert_llu:
1731 return PyLong_FromUnsignedLongLong(llu);
1732convert_zd:
1733 return PyLong_FromSsize_t(zd);
1734convert_zu:
1735 return PyLong_FromSize_t(zu);
1736convert_double:
1737 return PyFloat_FromDouble(d);
1738convert_bool:
1739 return PyBool_FromLong(ld);
1740convert_bytes:
1741 return PyBytes_FromStringAndSize(ptr, 1);
1742convert_pointer:
1743 return PyLong_FromVoidPtr(p);
1744err_format:
1745 PyErr_Format(PyExc_NotImplementedError,
1746 "memoryview: format %s not supported", fmt);
1747 return NULL;
1748}
1749
1750#define PACK_SINGLE(ptr, src, type) \
1751 do { \
1752 type x; \
1753 x = (type)src; \
1754 memcpy(ptr, (char *)&x, sizeof x); \
1755 } while (0)
1756
1757/* Pack a single item. 'fmt' can be any native format character in
1758 struct module syntax. */
1759static int
1760pack_single(char *ptr, PyObject *item, const char *fmt)
1761{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001762 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001763 unsigned long lu;
1764 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001765 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001766 long ld;
1767 Py_ssize_t zd;
1768 double d;
1769 void *p;
1770
1771 switch (fmt[0]) {
1772 /* signed integers */
1773 case 'b': case 'h': case 'i': case 'l':
1774 ld = pylong_as_ld(item);
1775 if (ld == -1 && PyErr_Occurred())
1776 goto err_occurred;
1777 switch (fmt[0]) {
1778 case 'b':
1779 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1780 *((signed char *)ptr) = (signed char)ld; break;
1781 case 'h':
1782 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1783 PACK_SINGLE(ptr, ld, short); break;
1784 case 'i':
1785 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1786 PACK_SINGLE(ptr, ld, int); break;
1787 default: /* 'l' */
1788 PACK_SINGLE(ptr, ld, long); break;
1789 }
1790 break;
1791
1792 /* unsigned integers */
1793 case 'B': case 'H': case 'I': case 'L':
1794 lu = pylong_as_lu(item);
1795 if (lu == (unsigned long)-1 && PyErr_Occurred())
1796 goto err_occurred;
1797 switch (fmt[0]) {
1798 case 'B':
1799 if (lu > UCHAR_MAX) goto err_range;
1800 *((unsigned char *)ptr) = (unsigned char)lu; break;
1801 case 'H':
1802 if (lu > USHRT_MAX) goto err_range;
1803 PACK_SINGLE(ptr, lu, unsigned short); break;
1804 case 'I':
1805 if (lu > UINT_MAX) goto err_range;
1806 PACK_SINGLE(ptr, lu, unsigned int); break;
1807 default: /* 'L' */
1808 PACK_SINGLE(ptr, lu, unsigned long); break;
1809 }
1810 break;
1811
1812 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001813 case 'q':
1814 lld = pylong_as_lld(item);
1815 if (lld == -1 && PyErr_Occurred())
1816 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001817 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001818 break;
1819 case 'Q':
1820 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001821 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001822 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001823 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001824 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001825
1826 /* ssize_t and size_t */
1827 case 'n':
1828 zd = pylong_as_zd(item);
1829 if (zd == -1 && PyErr_Occurred())
1830 goto err_occurred;
1831 PACK_SINGLE(ptr, zd, Py_ssize_t);
1832 break;
1833 case 'N':
1834 zu = pylong_as_zu(item);
1835 if (zu == (size_t)-1 && PyErr_Occurred())
1836 goto err_occurred;
1837 PACK_SINGLE(ptr, zu, size_t);
1838 break;
1839
1840 /* floats */
1841 case 'f': case 'd':
1842 d = PyFloat_AsDouble(item);
1843 if (d == -1.0 && PyErr_Occurred())
1844 goto err_occurred;
1845 if (fmt[0] == 'f') {
1846 PACK_SINGLE(ptr, d, float);
1847 }
1848 else {
1849 PACK_SINGLE(ptr, d, double);
1850 }
1851 break;
1852
1853 /* bool */
1854 case '?':
1855 ld = PyObject_IsTrue(item);
1856 if (ld < 0)
1857 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001858 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001859 break;
1860
1861 /* bytes object */
1862 case 'c':
1863 if (!PyBytes_Check(item))
1864 return type_error_int(fmt);
1865 if (PyBytes_GET_SIZE(item) != 1)
1866 return value_error_int(fmt);
1867 *ptr = PyBytes_AS_STRING(item)[0];
1868 break;
1869
1870 /* pointer */
1871 case 'P':
1872 p = PyLong_AsVoidPtr(item);
1873 if (p == NULL && PyErr_Occurred())
1874 goto err_occurred;
1875 PACK_SINGLE(ptr, p, void *);
1876 break;
1877
1878 /* default */
1879 default: goto err_format;
1880 }
1881
1882 return 0;
1883
1884err_occurred:
1885 return fix_error_int(fmt);
1886err_range:
1887 return value_error_int(fmt);
1888err_format:
1889 PyErr_Format(PyExc_NotImplementedError,
1890 "memoryview: format %s not supported", fmt);
1891 return -1;
1892}
1893
1894
1895/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001896/* unpack using the struct module */
1897/****************************************************************************/
1898
1899/* For reasonable performance it is necessary to cache all objects required
1900 for unpacking. An unpacker can handle the format passed to unpack_from().
1901 Invariant: All pointer fields of the struct should either be NULL or valid
1902 pointers. */
1903struct unpacker {
1904 PyObject *unpack_from; /* Struct.unpack_from(format) */
1905 PyObject *mview; /* cached memoryview */
1906 char *item; /* buffer for mview */
1907 Py_ssize_t itemsize; /* len(item) */
1908};
1909
1910static struct unpacker *
1911unpacker_new(void)
1912{
1913 struct unpacker *x = PyMem_Malloc(sizeof *x);
1914
1915 if (x == NULL) {
1916 PyErr_NoMemory();
1917 return NULL;
1918 }
1919
1920 x->unpack_from = NULL;
1921 x->mview = NULL;
1922 x->item = NULL;
1923 x->itemsize = 0;
1924
1925 return x;
1926}
1927
1928static void
1929unpacker_free(struct unpacker *x)
1930{
1931 if (x) {
1932 Py_XDECREF(x->unpack_from);
1933 Py_XDECREF(x->mview);
1934 PyMem_Free(x->item);
1935 PyMem_Free(x);
1936 }
1937}
1938
1939/* Return a new unpacker for the given format. */
1940static struct unpacker *
1941struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1942{
1943 PyObject *structmodule; /* XXX cache these two */
1944 PyObject *Struct = NULL; /* XXX in globals? */
1945 PyObject *structobj = NULL;
1946 PyObject *format = NULL;
1947 struct unpacker *x = NULL;
1948
1949 structmodule = PyImport_ImportModule("struct");
1950 if (structmodule == NULL)
1951 return NULL;
1952
1953 Struct = PyObject_GetAttrString(structmodule, "Struct");
1954 Py_DECREF(structmodule);
1955 if (Struct == NULL)
1956 return NULL;
1957
1958 x = unpacker_new();
1959 if (x == NULL)
1960 goto error;
1961
1962 format = PyBytes_FromString(fmt);
1963 if (format == NULL)
1964 goto error;
1965
Petr Viktorinffd97532020-02-11 17:46:57 +01001966 structobj = PyObject_CallOneArg(Struct, format);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001967 if (structobj == NULL)
1968 goto error;
1969
1970 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1971 if (x->unpack_from == NULL)
1972 goto error;
1973
1974 x->item = PyMem_Malloc(itemsize);
1975 if (x->item == NULL) {
1976 PyErr_NoMemory();
1977 goto error;
1978 }
1979 x->itemsize = itemsize;
1980
1981 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1982 if (x->mview == NULL)
1983 goto error;
1984
1985
1986out:
1987 Py_XDECREF(Struct);
1988 Py_XDECREF(format);
1989 Py_XDECREF(structobj);
1990 return x;
1991
1992error:
1993 unpacker_free(x);
1994 x = NULL;
1995 goto out;
1996}
1997
1998/* unpack a single item */
1999static PyObject *
2000struct_unpack_single(const char *ptr, struct unpacker *x)
2001{
2002 PyObject *v;
2003
2004 memcpy(x->item, ptr, x->itemsize);
Petr Viktorinffd97532020-02-11 17:46:57 +01002005 v = PyObject_CallOneArg(x->unpack_from, x->mview);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002006 if (v == NULL)
2007 return NULL;
2008
2009 if (PyTuple_GET_SIZE(v) == 1) {
2010 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2011 Py_INCREF(tmp);
2012 Py_DECREF(v);
2013 return tmp;
2014 }
2015
2016 return v;
2017}
2018
2019
2020/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002021/* Representations */
2022/****************************************************************************/
2023
2024/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002025static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002026adjust_fmt(const Py_buffer *view)
2027{
2028 const char *fmt;
2029
2030 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2031 if (fmt[0] && fmt[1] == '\0')
2032 return fmt;
2033
2034 PyErr_Format(PyExc_NotImplementedError,
2035 "memoryview: unsupported format %s", view->format);
2036 return NULL;
2037}
2038
2039/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2040static PyObject *
2041tolist_base(const char *ptr, const Py_ssize_t *shape,
2042 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2043 const char *fmt)
2044{
2045 PyObject *lst, *item;
2046 Py_ssize_t i;
2047
2048 lst = PyList_New(shape[0]);
2049 if (lst == NULL)
2050 return NULL;
2051
2052 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002053 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002054 item = unpack_single(xptr, fmt);
2055 if (item == NULL) {
2056 Py_DECREF(lst);
2057 return NULL;
2058 }
2059 PyList_SET_ITEM(lst, i, item);
2060 }
2061
2062 return lst;
2063}
2064
2065/* Unpack a multi-dimensional array into a nested list.
2066 Assumption: ndim >= 1. */
2067static PyObject *
2068tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2069 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2070 const char *fmt)
2071{
2072 PyObject *lst, *item;
2073 Py_ssize_t i;
2074
2075 assert(ndim >= 1);
2076 assert(shape != NULL);
2077 assert(strides != NULL);
2078
2079 if (ndim == 1)
2080 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2081
2082 lst = PyList_New(shape[0]);
2083 if (lst == NULL)
2084 return NULL;
2085
2086 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002087 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002088 item = tolist_rec(xptr, ndim-1, shape+1,
2089 strides+1, suboffsets ? suboffsets+1 : NULL,
2090 fmt);
2091 if (item == NULL) {
2092 Py_DECREF(lst);
2093 return NULL;
2094 }
2095 PyList_SET_ITEM(lst, i, item);
2096 }
2097
2098 return lst;
2099}
2100
2101/* Return a list representation of the memoryview. Currently only buffers
2102 with native format strings are supported. */
2103static PyObject *
2104memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2105{
2106 const Py_buffer *view = &(mv->view);
2107 const char *fmt;
2108
2109 CHECK_RELEASED(mv);
2110
2111 fmt = adjust_fmt(view);
2112 if (fmt == NULL)
2113 return NULL;
2114 if (view->ndim == 0) {
2115 return unpack_single(view->buf, fmt);
2116 }
2117 else if (view->ndim == 1) {
2118 return tolist_base(view->buf, view->shape,
2119 view->strides, view->suboffsets,
2120 fmt);
2121 }
2122 else {
2123 return tolist_rec(view->buf, view->ndim, view->shape,
2124 view->strides, view->suboffsets,
2125 fmt);
2126 }
2127}
2128
2129static PyObject *
Stefan Krahd08ea702019-02-02 18:57:41 +01002130memory_tobytes(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002131{
Stefan Krahd08ea702019-02-02 18:57:41 +01002132 static char *kwlist[] = {"order", NULL};
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002133 Py_buffer *src = VIEW_ADDR(self);
Stefan Krahd08ea702019-02-02 18:57:41 +01002134 char *order = NULL;
2135 char ord = 'C';
2136 PyObject *bytes;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002137
2138 CHECK_RELEASED(self);
2139
Stefan Krahd08ea702019-02-02 18:57:41 +01002140 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z", kwlist, &order)) {
2141 return NULL;
2142 }
2143
2144 if (order) {
2145 if (strcmp(order, "F") == 0) {
2146 ord = 'F';
2147 }
2148 else if (strcmp(order, "A") == 0) {
2149 ord = 'A';
2150 }
2151 else if (strcmp(order, "C") != 0) {
2152 PyErr_SetString(PyExc_ValueError,
2153 "order must be 'C', 'F' or 'A'");
2154 return NULL;
2155 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002156 }
2157
2158 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2159 if (bytes == NULL)
2160 return NULL;
2161
Stefan Krahd08ea702019-02-02 18:57:41 +01002162 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, ord) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002163 Py_DECREF(bytes);
2164 return NULL;
2165 }
2166
2167 return bytes;
2168}
2169
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002170/*[clinic input]
2171memoryview.hex
2172
2173 sep: object = NULL
2174 An optional single character or byte to separate hex bytes.
2175 bytes_per_sep: int = 1
2176 How many bytes between separators. Positive values count from the
2177 right, negative values count from the left.
2178
2179Return the data in the buffer as a str of hexadecimal numbers.
2180
2181Example:
2182>>> value = memoryview(b'\xb9\x01\xef')
2183>>> value.hex()
2184'b901ef'
2185>>> value.hex(':')
2186'b9:01:ef'
2187>>> value.hex(':', 2)
2188'b9:01ef'
2189>>> value.hex(':', -2)
2190'b901:ef'
2191[clinic start generated code]*/
2192
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002193static PyObject *
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002194memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
2195 int bytes_per_sep)
2196/*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002197{
2198 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002199 PyObject *bytes;
2200 PyObject *ret;
2201
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002202 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002203
2204 if (MV_C_CONTIGUOUS(self->flags)) {
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002205 return _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002206 }
2207
Stefan Krahd08ea702019-02-02 18:57:41 +01002208 bytes = PyBytes_FromStringAndSize(NULL, src->len);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002209 if (bytes == NULL)
2210 return NULL;
2211
Stefan Krahd08ea702019-02-02 18:57:41 +01002212 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, 'C') < 0) {
2213 Py_DECREF(bytes);
2214 return NULL;
2215 }
2216
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07002217 ret = _Py_strhex_with_sep(
2218 PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes),
2219 sep, bytes_per_sep);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002220 Py_DECREF(bytes);
2221
2222 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002223}
2224
2225static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002226memory_repr(PyMemoryViewObject *self)
2227{
2228 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2229 return PyUnicode_FromFormat("<released memory at %p>", self);
2230 else
2231 return PyUnicode_FromFormat("<memory at %p>", self);
2232}
2233
2234
2235/**************************************************************************/
2236/* Indexing and slicing */
2237/**************************************************************************/
2238
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002239static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002240lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002241{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002242 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002243
2244 assert(view->shape);
2245 assert(view->strides);
2246
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002247 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002248 if (index < 0) {
2249 index += nitems;
2250 }
2251 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002252 PyErr_Format(PyExc_IndexError,
2253 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002254 return NULL;
2255 }
2256
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002257 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002258
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002259 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002260
2261 return ptr;
2262}
2263
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002264/* Get the pointer to the item at index. */
2265static char *
2266ptr_from_index(Py_buffer *view, Py_ssize_t index)
2267{
2268 char *ptr = (char *)view->buf;
2269 return lookup_dimension(view, ptr, 0, index);
2270}
2271
2272/* Get the pointer to the item at tuple. */
2273static char *
2274ptr_from_tuple(Py_buffer *view, PyObject *tup)
2275{
2276 char *ptr = (char *)view->buf;
2277 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2278
2279 if (nindices > view->ndim) {
2280 PyErr_Format(PyExc_TypeError,
2281 "cannot index %zd-dimension view with %zd-element tuple",
2282 view->ndim, nindices);
2283 return NULL;
2284 }
2285
2286 for (dim = 0; dim < nindices; dim++) {
2287 Py_ssize_t index;
2288 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2289 PyExc_IndexError);
2290 if (index == -1 && PyErr_Occurred())
2291 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002292 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002293 if (ptr == NULL)
2294 return NULL;
2295 }
2296 return ptr;
2297}
2298
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002299/* Return the item at index. In a one-dimensional view, this is an object
2300 with the type specified by view->format. Otherwise, the item is a sub-view.
2301 The function is used in memory_subscript() and memory_as_sequence. */
2302static PyObject *
2303memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2304{
2305 Py_buffer *view = &(self->view);
2306 const char *fmt;
2307
2308 CHECK_RELEASED(self);
2309
2310 fmt = adjust_fmt(view);
2311 if (fmt == NULL)
2312 return NULL;
2313
2314 if (view->ndim == 0) {
2315 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2316 return NULL;
2317 }
2318 if (view->ndim == 1) {
2319 char *ptr = ptr_from_index(view, index);
2320 if (ptr == NULL)
2321 return NULL;
2322 return unpack_single(ptr, fmt);
2323 }
2324
2325 PyErr_SetString(PyExc_NotImplementedError,
2326 "multi-dimensional sub-views are not implemented");
2327 return NULL;
2328}
2329
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002330/* Return the item at position *key* (a tuple of indices). */
2331static PyObject *
2332memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2333{
2334 Py_buffer *view = &(self->view);
2335 const char *fmt;
2336 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2337 char *ptr;
2338
2339 CHECK_RELEASED(self);
2340
2341 fmt = adjust_fmt(view);
2342 if (fmt == NULL)
2343 return NULL;
2344
2345 if (nindices < view->ndim) {
2346 PyErr_SetString(PyExc_NotImplementedError,
2347 "sub-views are not implemented");
2348 return NULL;
2349 }
2350 ptr = ptr_from_tuple(view, tup);
2351 if (ptr == NULL)
2352 return NULL;
2353 return unpack_single(ptr, fmt);
2354}
2355
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002356static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002357init_slice(Py_buffer *base, PyObject *key, int dim)
2358{
2359 Py_ssize_t start, stop, step, slicelength;
2360
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002361 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002362 return -1;
2363 }
Serhiy Storchakab879fe82017-04-08 09:53:51 +03002364 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002365
2366
2367 if (base->suboffsets == NULL || dim == 0) {
2368 adjust_buf:
2369 base->buf = (char *)base->buf + base->strides[dim] * start;
2370 }
2371 else {
2372 Py_ssize_t n = dim-1;
2373 while (n >= 0 && base->suboffsets[n] < 0)
2374 n--;
2375 if (n < 0)
2376 goto adjust_buf; /* all suboffsets are negative */
2377 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2378 }
2379 base->shape[dim] = slicelength;
2380 base->strides[dim] = base->strides[dim] * step;
2381
2382 return 0;
2383}
2384
2385static int
2386is_multislice(PyObject *key)
2387{
2388 Py_ssize_t size, i;
2389
2390 if (!PyTuple_Check(key))
2391 return 0;
2392 size = PyTuple_GET_SIZE(key);
2393 if (size == 0)
2394 return 0;
2395
2396 for (i = 0; i < size; i++) {
2397 PyObject *x = PyTuple_GET_ITEM(key, i);
2398 if (!PySlice_Check(x))
2399 return 0;
2400 }
2401 return 1;
2402}
2403
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002404static Py_ssize_t
2405is_multiindex(PyObject *key)
2406{
2407 Py_ssize_t size, i;
2408
2409 if (!PyTuple_Check(key))
2410 return 0;
2411 size = PyTuple_GET_SIZE(key);
2412 for (i = 0; i < size; i++) {
2413 PyObject *x = PyTuple_GET_ITEM(key, i);
2414 if (!PyIndex_Check(x))
2415 return 0;
2416 }
2417 return 1;
2418}
2419
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002420/* mv[obj] returns an object holding the data for one element if obj
2421 fully indexes the memoryview or another memoryview object if it
2422 does not.
2423
2424 0-d memoryview objects can be referenced using mv[...] or mv[()]
2425 but not with anything else. */
2426static PyObject *
2427memory_subscript(PyMemoryViewObject *self, PyObject *key)
2428{
2429 Py_buffer *view;
2430 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002431
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002432 CHECK_RELEASED(self);
2433
2434 if (view->ndim == 0) {
2435 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2436 const char *fmt = adjust_fmt(view);
2437 if (fmt == NULL)
2438 return NULL;
2439 return unpack_single(view->buf, fmt);
2440 }
2441 else if (key == Py_Ellipsis) {
2442 Py_INCREF(self);
2443 return (PyObject *)self;
2444 }
2445 else {
2446 PyErr_SetString(PyExc_TypeError,
2447 "invalid indexing of 0-dim memory");
2448 return NULL;
2449 }
2450 }
2451
2452 if (PyIndex_Check(key)) {
2453 Py_ssize_t index;
2454 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2455 if (index == -1 && PyErr_Occurred())
2456 return NULL;
2457 return memory_item(self, index);
2458 }
2459 else if (PySlice_Check(key)) {
2460 PyMemoryViewObject *sliced;
2461
2462 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2463 if (sliced == NULL)
2464 return NULL;
2465
2466 if (init_slice(&sliced->view, key, 0) < 0) {
2467 Py_DECREF(sliced);
2468 return NULL;
2469 }
2470 init_len(&sliced->view);
2471 init_flags(sliced);
2472
2473 return (PyObject *)sliced;
2474 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002475 else if (is_multiindex(key)) {
2476 return memory_item_multi(self, key);
2477 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002478 else if (is_multislice(key)) {
2479 PyErr_SetString(PyExc_NotImplementedError,
2480 "multi-dimensional slicing is not implemented");
2481 return NULL;
2482 }
2483
2484 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2485 return NULL;
2486}
2487
2488static int
2489memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2490{
2491 Py_buffer *view = &(self->view);
2492 Py_buffer src;
2493 const char *fmt;
2494 char *ptr;
2495
2496 CHECK_RELEASED_INT(self);
2497
2498 fmt = adjust_fmt(view);
2499 if (fmt == NULL)
2500 return -1;
2501
2502 if (view->readonly) {
2503 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2504 return -1;
2505 }
2506 if (value == NULL) {
2507 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2508 return -1;
2509 }
2510 if (view->ndim == 0) {
2511 if (key == Py_Ellipsis ||
2512 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2513 ptr = (char *)view->buf;
2514 return pack_single(ptr, value, fmt);
2515 }
2516 else {
2517 PyErr_SetString(PyExc_TypeError,
2518 "invalid indexing of 0-dim memory");
2519 return -1;
2520 }
2521 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002522
2523 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002524 Py_ssize_t index;
2525 if (1 < view->ndim) {
2526 PyErr_SetString(PyExc_NotImplementedError,
2527 "sub-views are not implemented");
2528 return -1;
2529 }
2530 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002531 if (index == -1 && PyErr_Occurred())
2532 return -1;
2533 ptr = ptr_from_index(view, index);
2534 if (ptr == NULL)
2535 return -1;
2536 return pack_single(ptr, value, fmt);
2537 }
2538 /* one-dimensional: fast path */
2539 if (PySlice_Check(key) && view->ndim == 1) {
2540 Py_buffer dest; /* sliced view */
2541 Py_ssize_t arrays[3];
2542 int ret = -1;
2543
2544 /* rvalue must be an exporter */
2545 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2546 return ret;
2547
2548 dest = *view;
2549 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2550 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2551 if (view->suboffsets) {
2552 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2553 }
2554
2555 if (init_slice(&dest, key, 0) < 0)
2556 goto end_block;
2557 dest.len = dest.shape[0] * dest.itemsize;
2558
2559 ret = copy_single(&dest, &src);
2560
2561 end_block:
2562 PyBuffer_Release(&src);
2563 return ret;
2564 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002565 if (is_multiindex(key)) {
2566 char *ptr;
2567 if (PyTuple_GET_SIZE(key) < view->ndim) {
2568 PyErr_SetString(PyExc_NotImplementedError,
2569 "sub-views are not implemented");
2570 return -1;
2571 }
2572 ptr = ptr_from_tuple(view, key);
2573 if (ptr == NULL)
2574 return -1;
2575 return pack_single(ptr, value, fmt);
2576 }
2577 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002578 /* Call memory_subscript() to produce a sliced lvalue, then copy
2579 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2580 PyErr_SetString(PyExc_NotImplementedError,
2581 "memoryview slice assignments are currently restricted "
2582 "to ndim = 1");
2583 return -1;
2584 }
2585
2586 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2587 return -1;
2588}
2589
2590static Py_ssize_t
2591memory_length(PyMemoryViewObject *self)
2592{
2593 CHECK_RELEASED_INT(self);
2594 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2595}
2596
2597/* As mapping */
2598static PyMappingMethods memory_as_mapping = {
2599 (lenfunc)memory_length, /* mp_length */
2600 (binaryfunc)memory_subscript, /* mp_subscript */
2601 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2602};
2603
2604/* As sequence */
2605static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002606 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002607 0, /* sq_concat */
2608 0, /* sq_repeat */
2609 (ssizeargfunc)memory_item, /* sq_item */
2610};
2611
2612
2613/**************************************************************************/
2614/* Comparisons */
2615/**************************************************************************/
2616
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002617#define MV_COMPARE_EX -1 /* exception */
2618#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2619
2620/* Translate a StructError to "not equal". Preserve other exceptions. */
2621static int
2622fix_struct_error_int(void)
2623{
2624 assert(PyErr_Occurred());
2625 /* XXX Cannot get at StructError directly? */
2626 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2627 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2628 return MV_COMPARE_EX;
2629 }
2630 /* StructError: invalid or unknown format -> not equal */
2631 PyErr_Clear();
2632 return 0;
2633}
2634
2635/* Unpack and compare single items of p and q using the struct module. */
2636static int
2637struct_unpack_cmp(const char *p, const char *q,
2638 struct unpacker *unpack_p, struct unpacker *unpack_q)
2639{
2640 PyObject *v, *w;
2641 int ret;
2642
2643 /* At this point any exception from the struct module should not be
2644 StructError, since both formats have been accepted already. */
2645 v = struct_unpack_single(p, unpack_p);
2646 if (v == NULL)
2647 return MV_COMPARE_EX;
2648
2649 w = struct_unpack_single(q, unpack_q);
2650 if (w == NULL) {
2651 Py_DECREF(v);
2652 return MV_COMPARE_EX;
2653 }
2654
2655 /* MV_COMPARE_EX == -1: exceptions are preserved */
2656 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2657 Py_DECREF(v);
2658 Py_DECREF(w);
2659
2660 return ret;
2661}
2662
2663/* Unpack and compare single items of p and q. If both p and q have the same
2664 single element native format, the comparison uses a fast path (gcc creates
2665 a jump table and converts memcpy into simple assignments on x86/x64).
2666
2667 Otherwise, the comparison is delegated to the struct module, which is
2668 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002669#define CMP_SINGLE(p, q, type) \
2670 do { \
2671 type x; \
2672 type y; \
2673 memcpy((char *)&x, p, sizeof x); \
2674 memcpy((char *)&y, q, sizeof y); \
2675 equal = (x == y); \
2676 } while (0)
2677
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002678static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002679unpack_cmp(const char *p, const char *q, char fmt,
2680 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002681{
2682 int equal;
2683
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002684 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002685
2686 /* signed integers and fast path for 'B' */
2687 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2688 case 'b': return *((signed char *)p) == *((signed char *)q);
2689 case 'h': CMP_SINGLE(p, q, short); return equal;
2690 case 'i': CMP_SINGLE(p, q, int); return equal;
2691 case 'l': CMP_SINGLE(p, q, long); return equal;
2692
2693 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002694 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002695
2696 /* unsigned integers */
2697 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2698 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2699 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2700
2701 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002702 case 'q': CMP_SINGLE(p, q, long long); return equal;
2703 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002704
2705 /* ssize_t and size_t */
2706 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2707 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2708
2709 /* floats */
2710 /* XXX DBL_EPSILON? */
2711 case 'f': CMP_SINGLE(p, q, float); return equal;
2712 case 'd': CMP_SINGLE(p, q, double); return equal;
2713
2714 /* bytes object */
2715 case 'c': return *p == *q;
2716
2717 /* pointer */
2718 case 'P': CMP_SINGLE(p, q, void *); return equal;
2719
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002720 /* use the struct module */
2721 case '_':
2722 assert(unpack_p);
2723 assert(unpack_q);
2724 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002725 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002726
2727 /* NOT REACHED */
2728 PyErr_SetString(PyExc_RuntimeError,
2729 "memoryview: internal error in richcompare");
2730 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002731}
2732
2733/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2734static int
2735cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2736 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2737 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002738 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002739{
2740 Py_ssize_t i;
2741 int equal;
2742
2743 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002744 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2745 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002746 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002747 if (equal <= 0)
2748 return equal;
2749 }
2750
2751 return 1;
2752}
2753
2754/* Recursively compare two multi-dimensional arrays that have the same
2755 logical structure. Assumption: ndim >= 1. */
2756static int
2757cmp_rec(const char *p, const char *q,
2758 Py_ssize_t ndim, const Py_ssize_t *shape,
2759 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2760 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002761 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002762{
2763 Py_ssize_t i;
2764 int equal;
2765
2766 assert(ndim >= 1);
2767 assert(shape != NULL);
2768 assert(pstrides != NULL);
2769 assert(qstrides != NULL);
2770
2771 if (ndim == 1) {
2772 return cmp_base(p, q, shape,
2773 pstrides, psuboffsets,
2774 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002775 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002776 }
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);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002781 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2782 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2783 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002784 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002785 if (equal <= 0)
2786 return equal;
2787 }
2788
2789 return 1;
2790}
2791
2792static PyObject *
2793memory_richcompare(PyObject *v, PyObject *w, int op)
2794{
2795 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002796 Py_buffer wbuf, *vv;
2797 Py_buffer *ww = NULL;
2798 struct unpacker *unpack_v = NULL;
2799 struct unpacker *unpack_w = NULL;
2800 char vfmt, wfmt;
2801 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002802
2803 if (op != Py_EQ && op != Py_NE)
2804 goto result; /* Py_NotImplemented */
2805
2806 assert(PyMemoryView_Check(v));
2807 if (BASE_INACCESSIBLE(v)) {
2808 equal = (v == w);
2809 goto result;
2810 }
2811 vv = VIEW_ADDR(v);
2812
2813 if (PyMemoryView_Check(w)) {
2814 if (BASE_INACCESSIBLE(w)) {
2815 equal = (v == w);
2816 goto result;
2817 }
2818 ww = VIEW_ADDR(w);
2819 }
2820 else {
2821 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2822 PyErr_Clear();
2823 goto result; /* Py_NotImplemented */
2824 }
2825 ww = &wbuf;
2826 }
2827
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002828 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002829 PyErr_Clear();
2830 equal = 0;
2831 goto result;
2832 }
2833
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002834 /* Use fast unpacking for identical primitive C type formats. */
2835 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2836 vfmt = '_';
2837 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2838 wfmt = '_';
2839 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2840 /* Use struct module unpacking. NOTE: Even for equal format strings,
2841 memcmp() cannot be used for item comparison since it would give
2842 incorrect results in the case of NaNs or uninitialized padding
2843 bytes. */
2844 vfmt = '_';
2845 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2846 if (unpack_v == NULL) {
2847 equal = fix_struct_error_int();
2848 goto result;
2849 }
2850 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2851 if (unpack_w == NULL) {
2852 equal = fix_struct_error_int();
2853 goto result;
2854 }
2855 }
2856
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002857 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002858 equal = unpack_cmp(vv->buf, ww->buf,
2859 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002860 }
2861 else if (vv->ndim == 1) {
2862 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2863 vv->strides, vv->suboffsets,
2864 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002865 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002866 }
2867 else {
2868 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2869 vv->strides, vv->suboffsets,
2870 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002871 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002872 }
2873
2874result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002875 if (equal < 0) {
2876 if (equal == MV_COMPARE_NOT_IMPL)
2877 res = Py_NotImplemented;
2878 else /* exception */
2879 res = NULL;
2880 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002881 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2882 res = Py_True;
2883 else
2884 res = Py_False;
2885
2886 if (ww == &wbuf)
2887 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002888
2889 unpacker_free(unpack_v);
2890 unpacker_free(unpack_w);
2891
2892 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002893 return res;
2894}
2895
2896/**************************************************************************/
2897/* Hash */
2898/**************************************************************************/
2899
2900static Py_hash_t
2901memory_hash(PyMemoryViewObject *self)
2902{
2903 if (self->hash == -1) {
2904 Py_buffer *view = &self->view;
2905 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002906 Py_ssize_t ret;
2907 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002908
2909 CHECK_RELEASED_INT(self);
2910
2911 if (!view->readonly) {
2912 PyErr_SetString(PyExc_ValueError,
2913 "cannot hash writable memoryview object");
2914 return -1;
2915 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002916 ret = get_native_fmtchar(&fmt, view->format);
2917 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2918 PyErr_SetString(PyExc_ValueError,
2919 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2920 return -1;
2921 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002922 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2923 /* Keep the original error message */
2924 return -1;
2925 }
2926
2927 if (!MV_C_CONTIGUOUS(self->flags)) {
2928 mem = PyMem_Malloc(view->len);
2929 if (mem == NULL) {
2930 PyErr_NoMemory();
2931 return -1;
2932 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002933 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002934 PyMem_Free(mem);
2935 return -1;
2936 }
2937 }
2938
2939 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002940 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002941
2942 if (mem != view->buf)
2943 PyMem_Free(mem);
2944 }
2945
2946 return self->hash;
2947}
2948
2949
2950/**************************************************************************/
2951/* getters */
2952/**************************************************************************/
2953
2954static PyObject *
2955_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2956{
2957 int i;
2958 PyObject *o;
2959 PyObject *intTuple;
2960
2961 if (vals == NULL)
2962 return PyTuple_New(0);
2963
2964 intTuple = PyTuple_New(len);
2965 if (!intTuple)
2966 return NULL;
2967 for (i=0; i<len; i++) {
2968 o = PyLong_FromSsize_t(vals[i]);
2969 if (!o) {
2970 Py_DECREF(intTuple);
2971 return NULL;
2972 }
2973 PyTuple_SET_ITEM(intTuple, i, o);
2974 }
2975 return intTuple;
2976}
2977
2978static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002979memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002980{
2981 Py_buffer *view = &self->view;
2982
2983 CHECK_RELEASED(self);
2984 if (view->obj == NULL) {
2985 Py_RETURN_NONE;
2986 }
2987 Py_INCREF(view->obj);
2988 return view->obj;
2989}
2990
2991static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002992memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002993{
2994 CHECK_RELEASED(self);
2995 return PyLong_FromSsize_t(self->view.len);
2996}
2997
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002998static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02002999memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003000{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003001 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003002 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003003}
3004
3005static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003006memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003007{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003008 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003009 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003010}
3011
3012static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003013memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003014{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003015 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003016 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003017}
3018
3019static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003020memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003021{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003022 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003023 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003024}
3025
3026static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003027memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003028{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003029 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003030 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003031}
3032
3033static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003034memory_readonly_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 PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003038}
3039
3040static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02003041memory_ndim_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_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003045}
3046
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003047static PyObject *
3048memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3049{
3050 CHECK_RELEASED(self);
3051 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3052}
3053
3054static PyObject *
3055memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3056{
3057 CHECK_RELEASED(self);
3058 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3059}
3060
3061static PyObject *
3062memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3063{
3064 CHECK_RELEASED(self);
3065 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3066}
3067
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003068PyDoc_STRVAR(memory_obj_doc,
3069 "The underlying object of the memoryview.");
3070PyDoc_STRVAR(memory_nbytes_doc,
3071 "The amount of space in bytes that the array would use in\n"
3072 " a contiguous representation.");
3073PyDoc_STRVAR(memory_readonly_doc,
3074 "A bool indicating whether the memory is read only.");
3075PyDoc_STRVAR(memory_itemsize_doc,
3076 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003077PyDoc_STRVAR(memory_format_doc,
3078 "A string containing the format (in struct module style)\n"
3079 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003080PyDoc_STRVAR(memory_ndim_doc,
3081 "An integer indicating how many dimensions of a multi-dimensional\n"
3082 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003083PyDoc_STRVAR(memory_shape_doc,
3084 "A tuple of ndim integers giving the shape of the memory\n"
3085 " as an N-dimensional array.");
3086PyDoc_STRVAR(memory_strides_doc,
3087 "A tuple of ndim integers giving the size in bytes to access\n"
3088 " each element for each dimension of the array.");
3089PyDoc_STRVAR(memory_suboffsets_doc,
3090 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003091PyDoc_STRVAR(memory_c_contiguous_doc,
3092 "A bool indicating whether the memory is C contiguous.");
3093PyDoc_STRVAR(memory_f_contiguous_doc,
3094 "A bool indicating whether the memory is Fortran contiguous.");
3095PyDoc_STRVAR(memory_contiguous_doc,
3096 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003097
Stefan Krahbcaf5992014-05-18 00:35:09 +02003098
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003099static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003100 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3101 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003102 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3103 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3104 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3105 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3106 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3107 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3108 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003109 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3110 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3111 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003112 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003113};
3114
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003115PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003116"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003117\n\
3118Release the underlying buffer exposed by the memoryview object.");
3119PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahd08ea702019-02-02 18:57:41 +01003120"tobytes($self, /, order=None)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003121\n\
Stefan Krahd08ea702019-02-02 18:57:41 +01003122Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
3123When order is 'C' or 'F', the data of the original array is converted to C or\n\
3124Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
3125memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
3126views, the data is converted to C first. order=None is the same as order='C'.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003127PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003128"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003129\n\
3130Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003131PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003132"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003133\n\
3134Cast a memoryview to a new format or shape.");
Antoine Pitrou480ab052018-04-14 19:49:21 +02003135PyDoc_STRVAR(memory_toreadonly_doc,
3136"toreadonly($self, /)\n--\n\
3137\n\
3138Return a readonly version of the memoryview.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003139
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003140static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003141 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
Stéphane Wirtel359a2f32019-03-05 16:10:53 +01003142 {"tobytes", (PyCFunction)(void(*)(void))memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
Gregory P. Smith0c2f9302019-05-29 11:46:58 -07003143 MEMORYVIEW_HEX_METHODDEF
Alexander Belopolskye370c382012-09-03 16:43:55 -04003144 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02003145 {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Antoine Pitrou480ab052018-04-14 19:49:21 +02003146 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003147 {"__enter__", memory_enter, METH_NOARGS, NULL},
3148 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003149 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003150};
3151
3152
3153PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003154 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003155 "memoryview", /* tp_name */
3156 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3157 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003158 (destructor)memory_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003159 0, /* tp_vectorcall_offset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003160 0, /* tp_getattr */
3161 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02003162 0, /* tp_as_async */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003163 (reprfunc)memory_repr, /* tp_repr */
3164 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003165 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003166 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003167 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003168 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003169 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003170 PyObject_GenericGetAttr, /* tp_getattro */
3171 0, /* tp_setattro */
3172 &memory_as_buffer, /* tp_as_buffer */
3173 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3174 memory_doc, /* tp_doc */
3175 (traverseproc)memory_traverse, /* tp_traverse */
3176 (inquiry)memory_clear, /* tp_clear */
3177 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003178 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003179 0, /* tp_iter */
3180 0, /* tp_iternext */
3181 memory_methods, /* tp_methods */
3182 0, /* tp_members */
3183 memory_getsetlist, /* tp_getset */
3184 0, /* tp_base */
3185 0, /* tp_dict */
3186 0, /* tp_descr_get */
3187 0, /* tp_descr_set */
3188 0, /* tp_dictoffset */
3189 0, /* tp_init */
3190 0, /* tp_alloc */
3191 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003192};