1 /*
2 * Memoryview object implementation
3 * --------------------------------
4 *
5 * This implementation is a complete rewrite contributed by Stefan Krah in
6 * Python 3.3. Substantial credit goes to Antoine Pitrou (who had already
7 * fortified and rewritten the previous implementation) and Nick Coghlan
8 * (who came up with the idea of the ManagedBuffer) for analyzing the complex
9 * ownership rules.
10 *
11 */
12
13 #include "Python.h"
14 #include "pycore_object.h"
15 #include "pycore_pymem.h"
16 #include "pycore_pystate.h"
17 #include "pystrhex.h"
18 #include <stddef.h>
19
20 /*[clinic input]
21 class memoryview "PyMemoryViewObject *" "&PyMemoryView_Type"
22 [clinic start generated code]*/
23 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2e49d2192835219]*/
24
25 #include "clinic/memoryobject.c.h"
26
27 /****************************************************************************/
28 /* ManagedBuffer Object */
29 /****************************************************************************/
30
31 /*
32 ManagedBuffer Object:
33 ---------------------
34
35 The purpose of this object is to facilitate the handling of chained
36 memoryviews that have the same underlying exporting object. PEP-3118
37 allows the underlying object to change while a view is exported. This
38 could lead to unexpected results when constructing a new memoryview
39 from an existing memoryview.
40
41 Rather than repeatedly redirecting buffer requests to the original base
42 object, all chained memoryviews use a single buffer snapshot. This
43 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
44
45 Ownership rules:
46 ----------------
47
48 The master buffer inside a managed buffer is filled in by the original
49 base object. shape, strides, suboffsets and format are read-only for
50 all consumers.
51
52 A memoryview's buffer is a private copy of the exporter's buffer. shape,
53 strides and suboffsets belong to the memoryview and are thus writable.
54
55 If a memoryview itself exports several buffers via memory_getbuf(), all
56 buffer copies share shape, strides and suboffsets. In this case, the
57 arrays are NOT writable.
58
59 Reference count assumptions:
60 ----------------------------
61
62 The 'obj' member of a Py_buffer must either be NULL or refer to the
63 exporting base object. In the Python codebase, all getbufferprocs
64 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
65
66 PyBuffer_Release() decrements view.obj (if non-NULL), so the
67 releasebufferprocs must NOT decrement view.obj.
68 */
69
70
71 #define CHECK_MBUF_RELEASED(mbuf) \
72 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
73 PyErr_SetString(PyExc_ValueError, \
74 "operation forbidden on released memoryview object"); \
75 return NULL; \
76 }
77
78
79 static inline _PyManagedBufferObject *
mbuf_alloc(void)80 mbuf_alloc(void)
81 {
82 _PyManagedBufferObject *mbuf;
83
84 mbuf = (_PyManagedBufferObject *)
85 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
86 if (mbuf == NULL)
87 return NULL;
88 mbuf->flags = 0;
89 mbuf->exports = 0;
90 mbuf->master.obj = NULL;
91 _PyObject_GC_TRACK(mbuf);
92
93 return mbuf;
94 }
95
96 static PyObject *
_PyManagedBuffer_FromObject(PyObject * base)97 _PyManagedBuffer_FromObject(PyObject *base)
98 {
99 _PyManagedBufferObject *mbuf;
100
101 mbuf = mbuf_alloc();
102 if (mbuf == NULL)
103 return NULL;
104
105 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
106 mbuf->master.obj = NULL;
107 Py_DECREF(mbuf);
108 return NULL;
109 }
110
111 return (PyObject *)mbuf;
112 }
113
114 static void
mbuf_release(_PyManagedBufferObject * self)115 mbuf_release(_PyManagedBufferObject *self)
116 {
117 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
118 return;
119
120 /* NOTE: at this point self->exports can still be > 0 if this function
121 is called from mbuf_clear() to break up a reference cycle. */
122 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
123
124 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
125 _PyObject_GC_UNTRACK(self);
126 PyBuffer_Release(&self->master);
127 }
128
129 static void
mbuf_dealloc(_PyManagedBufferObject * self)130 mbuf_dealloc(_PyManagedBufferObject *self)
131 {
132 assert(self->exports == 0);
133 mbuf_release(self);
134 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
135 PyMem_Free(self->master.format);
136 PyObject_GC_Del(self);
137 }
138
139 static int
mbuf_traverse(_PyManagedBufferObject * self,visitproc visit,void * arg)140 mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
141 {
142 Py_VISIT(self->master.obj);
143 return 0;
144 }
145
146 static int
mbuf_clear(_PyManagedBufferObject * self)147 mbuf_clear(_PyManagedBufferObject *self)
148 {
149 assert(self->exports >= 0);
150 mbuf_release(self);
151 return 0;
152 }
153
154 PyTypeObject _PyManagedBuffer_Type = {
155 PyVarObject_HEAD_INIT(&PyType_Type, 0)
156 "managedbuffer",
157 sizeof(_PyManagedBufferObject),
158 0,
159 (destructor)mbuf_dealloc, /* tp_dealloc */
160 0, /* tp_vectorcall_offset */
161 0, /* tp_getattr */
162 0, /* tp_setattr */
163 0, /* tp_as_async */
164 0, /* tp_repr */
165 0, /* tp_as_number */
166 0, /* tp_as_sequence */
167 0, /* tp_as_mapping */
168 0, /* tp_hash */
169 0, /* tp_call */
170 0, /* tp_str */
171 PyObject_GenericGetAttr, /* tp_getattro */
172 0, /* tp_setattro */
173 0, /* tp_as_buffer */
174 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
175 0, /* tp_doc */
176 (traverseproc)mbuf_traverse, /* tp_traverse */
177 (inquiry)mbuf_clear /* tp_clear */
178 };
179
180
181 /****************************************************************************/
182 /* MemoryView Object */
183 /****************************************************************************/
184
185 /* In the process of breaking reference cycles mbuf_release() can be
186 called before memory_release(). */
187 #define BASE_INACCESSIBLE(mv) \
188 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
189 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
190
191 #define CHECK_RELEASED(mv) \
192 if (BASE_INACCESSIBLE(mv)) { \
193 PyErr_SetString(PyExc_ValueError, \
194 "operation forbidden on released memoryview object"); \
195 return NULL; \
196 }
197
198 #define CHECK_RELEASED_INT(mv) \
199 if (BASE_INACCESSIBLE(mv)) { \
200 PyErr_SetString(PyExc_ValueError, \
201 "operation forbidden on released memoryview object"); \
202 return -1; \
203 }
204
205 #define CHECK_LIST_OR_TUPLE(v) \
206 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
207 PyErr_SetString(PyExc_TypeError, \
208 #v " must be a list or a tuple"); \
209 return NULL; \
210 }
211
212 #define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
213
214 /* Check for the presence of suboffsets in the first dimension. */
215 #define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
216 /* Adjust ptr if suboffsets are present. */
217 #define ADJUST_PTR(ptr, suboffsets, dim) \
218 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
219
220 /* Memoryview buffer properties */
221 #define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
222 #define MV_F_CONTIGUOUS(flags) \
223 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
224 #define MV_ANY_CONTIGUOUS(flags) \
225 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
226
227 /* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
228 #define MV_CONTIGUOUS_NDIM1(view) \
229 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
230
231 /* getbuffer() requests */
232 #define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
233 #define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
234 #define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
235 #define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
236 #define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
237 #define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
238 #define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
239 #define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
240
241
242 PyDoc_STRVAR(memory_doc,
243 "memoryview(object)\n--\n\
244 \n\
245 Create a new memoryview object which references the given object.");
246
247
248 /**************************************************************************/
249 /* Copy memoryview buffers */
250 /**************************************************************************/
251
252 /* The functions in this section take a source and a destination buffer
253 with the same logical structure: format, itemsize, ndim and shape
254 are identical, with ndim > 0.
255
256 NOTE: All buffers are assumed to have PyBUF_FULL information, which
257 is the case for memoryviews! */
258
259
260 /* Assumptions: ndim >= 1. The macro tests for a corner case that should
261 perhaps be explicitly forbidden in the PEP. */
262 #define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
263 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
264
265 static inline int
last_dim_is_contiguous(const Py_buffer * dest,const Py_buffer * src)266 last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
267 {
268 assert(dest->ndim > 0 && src->ndim > 0);
269 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
270 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
271 dest->strides[dest->ndim-1] == dest->itemsize &&
272 src->strides[src->ndim-1] == src->itemsize);
273 }
274
275 /* This is not a general function for determining format equivalence.
276 It is used in copy_single() and copy_buffer() to weed out non-matching
277 formats. Skipping the '@' character is specifically used in slice
278 assignments, where the lvalue is already known to have a single character
279 format. This is a performance hack that could be rewritten (if properly
280 benchmarked). */
281 static inline int
equiv_format(const Py_buffer * dest,const Py_buffer * src)282 equiv_format(const Py_buffer *dest, const Py_buffer *src)
283 {
284 const char *dfmt, *sfmt;
285
286 assert(dest->format && src->format);
287 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
288 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
289
290 if (strcmp(dfmt, sfmt) != 0 ||
291 dest->itemsize != src->itemsize) {
292 return 0;
293 }
294
295 return 1;
296 }
297
298 /* Two shapes are equivalent if they are either equal or identical up
299 to a zero element at the same position. For example, in NumPy arrays
300 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
301 static inline int
equiv_shape(const Py_buffer * dest,const Py_buffer * src)302 equiv_shape(const Py_buffer *dest, const Py_buffer *src)
303 {
304 int i;
305
306 if (dest->ndim != src->ndim)
307 return 0;
308
309 for (i = 0; i < dest->ndim; i++) {
310 if (dest->shape[i] != src->shape[i])
311 return 0;
312 if (dest->shape[i] == 0)
313 break;
314 }
315
316 return 1;
317 }
318
319 /* Check that the logical structure of the destination and source buffers
320 is identical. */
321 static int
equiv_structure(const Py_buffer * dest,const Py_buffer * src)322 equiv_structure(const Py_buffer *dest, const Py_buffer *src)
323 {
324 if (!equiv_format(dest, src) ||
325 !equiv_shape(dest, src)) {
326 PyErr_SetString(PyExc_ValueError,
327 "memoryview assignment: lvalue and rvalue have different "
328 "structures");
329 return 0;
330 }
331
332 return 1;
333 }
334
335 /* Base case for recursive multi-dimensional copying. Contiguous arrays are
336 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
337 sizeof(mem) == shape[0] * itemsize. */
338 static void
copy_base(const Py_ssize_t * shape,Py_ssize_t itemsize,char * dptr,const Py_ssize_t * dstrides,const Py_ssize_t * dsuboffsets,char * sptr,const Py_ssize_t * sstrides,const Py_ssize_t * ssuboffsets,char * mem)339 copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
340 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
341 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
342 char *mem)
343 {
344 if (mem == NULL) { /* contiguous */
345 Py_ssize_t size = shape[0] * itemsize;
346 if (dptr + size < sptr || sptr + size < dptr)
347 memcpy(dptr, sptr, size); /* no overlapping */
348 else
349 memmove(dptr, sptr, size);
350 }
351 else {
352 char *p;
353 Py_ssize_t i;
354 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
355 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
356 memcpy(p, xsptr, itemsize);
357 }
358 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
359 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
360 memcpy(xdptr, p, itemsize);
361 }
362 }
363
364 }
365
366 /* Recursively copy a source buffer to a destination buffer. The two buffers
367 have the same ndim, shape and itemsize. */
368 static void
copy_rec(const Py_ssize_t * shape,Py_ssize_t ndim,Py_ssize_t itemsize,char * dptr,const Py_ssize_t * dstrides,const Py_ssize_t * dsuboffsets,char * sptr,const Py_ssize_t * sstrides,const Py_ssize_t * ssuboffsets,char * mem)369 copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
370 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
371 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
372 char *mem)
373 {
374 Py_ssize_t i;
375
376 assert(ndim >= 1);
377
378 if (ndim == 1) {
379 copy_base(shape, itemsize,
380 dptr, dstrides, dsuboffsets,
381 sptr, sstrides, ssuboffsets,
382 mem);
383 return;
384 }
385
386 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
387 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
388 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
389
390 copy_rec(shape+1, ndim-1, itemsize,
391 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
392 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
393 mem);
394 }
395 }
396
397 /* Faster copying of one-dimensional arrays. */
398 static int
copy_single(Py_buffer * dest,Py_buffer * src)399 copy_single(Py_buffer *dest, Py_buffer *src)
400 {
401 char *mem = NULL;
402
403 assert(dest->ndim == 1);
404
405 if (!equiv_structure(dest, src))
406 return -1;
407
408 if (!last_dim_is_contiguous(dest, src)) {
409 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
410 if (mem == NULL) {
411 PyErr_NoMemory();
412 return -1;
413 }
414 }
415
416 copy_base(dest->shape, dest->itemsize,
417 dest->buf, dest->strides, dest->suboffsets,
418 src->buf, src->strides, src->suboffsets,
419 mem);
420
421 if (mem)
422 PyMem_Free(mem);
423
424 return 0;
425 }
426
427 /* Recursively copy src to dest. Both buffers must have the same basic
428 structure. Copying is atomic, the function never fails with a partial
429 copy. */
430 static int
copy_buffer(Py_buffer * dest,Py_buffer * src)431 copy_buffer(Py_buffer *dest, Py_buffer *src)
432 {
433 char *mem = NULL;
434
435 assert(dest->ndim > 0);
436
437 if (!equiv_structure(dest, src))
438 return -1;
439
440 if (!last_dim_is_contiguous(dest, src)) {
441 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
442 if (mem == NULL) {
443 PyErr_NoMemory();
444 return -1;
445 }
446 }
447
448 copy_rec(dest->shape, dest->ndim, dest->itemsize,
449 dest->buf, dest->strides, dest->suboffsets,
450 src->buf, src->strides, src->suboffsets,
451 mem);
452
453 if (mem)
454 PyMem_Free(mem);
455
456 return 0;
457 }
458
459 /* Initialize strides for a C-contiguous array. */
460 static inline void
init_strides_from_shape(Py_buffer * view)461 init_strides_from_shape(Py_buffer *view)
462 {
463 Py_ssize_t i;
464
465 assert(view->ndim > 0);
466
467 view->strides[view->ndim-1] = view->itemsize;
468 for (i = view->ndim-2; i >= 0; i--)
469 view->strides[i] = view->strides[i+1] * view->shape[i+1];
470 }
471
472 /* Initialize strides for a Fortran-contiguous array. */
473 static inline void
init_fortran_strides_from_shape(Py_buffer * view)474 init_fortran_strides_from_shape(Py_buffer *view)
475 {
476 Py_ssize_t i;
477
478 assert(view->ndim > 0);
479
480 view->strides[0] = view->itemsize;
481 for (i = 1; i < view->ndim; i++)
482 view->strides[i] = view->strides[i-1] * view->shape[i-1];
483 }
484
485 /* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
486 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
487 len(mem) == src->len. */
488 static int
buffer_to_contiguous(char * mem,Py_buffer * src,char order)489 buffer_to_contiguous(char *mem, Py_buffer *src, char order)
490 {
491 Py_buffer dest;
492 Py_ssize_t *strides;
493 int ret;
494
495 assert(src->ndim >= 1);
496 assert(src->shape != NULL);
497 assert(src->strides != NULL);
498
499 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
500 if (strides == NULL) {
501 PyErr_NoMemory();
502 return -1;
503 }
504
505 /* initialize dest */
506 dest = *src;
507 dest.buf = mem;
508 /* shape is constant and shared: the logical representation of the
509 array is unaltered. */
510
511 /* The physical representation determined by strides (and possibly
512 suboffsets) may change. */
513 dest.strides = strides;
514 if (order == 'C' || order == 'A') {
515 init_strides_from_shape(&dest);
516 }
517 else {
518 init_fortran_strides_from_shape(&dest);
519 }
520
521 dest.suboffsets = NULL;
522
523 ret = copy_buffer(&dest, src);
524
525 PyMem_Free(strides);
526 return ret;
527 }
528
529
530 /****************************************************************************/
531 /* Constructors */
532 /****************************************************************************/
533
534 /* Initialize values that are shared with the managed buffer. */
535 static inline void
init_shared_values(Py_buffer * dest,const Py_buffer * src)536 init_shared_values(Py_buffer *dest, const Py_buffer *src)
537 {
538 dest->obj = src->obj;
539 dest->buf = src->buf;
540 dest->len = src->len;
541 dest->itemsize = src->itemsize;
542 dest->readonly = src->readonly;
543 dest->format = src->format ? src->format : "B";
544 dest->internal = src->internal;
545 }
546
547 /* Copy shape and strides. Reconstruct missing values. */
548 static void
init_shape_strides(Py_buffer * dest,const Py_buffer * src)549 init_shape_strides(Py_buffer *dest, const Py_buffer *src)
550 {
551 Py_ssize_t i;
552
553 if (src->ndim == 0) {
554 dest->shape = NULL;
555 dest->strides = NULL;
556 return;
557 }
558 if (src->ndim == 1) {
559 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
560 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
561 return;
562 }
563
564 for (i = 0; i < src->ndim; i++)
565 dest->shape[i] = src->shape[i];
566 if (src->strides) {
567 for (i = 0; i < src->ndim; i++)
568 dest->strides[i] = src->strides[i];
569 }
570 else {
571 init_strides_from_shape(dest);
572 }
573 }
574
575 static inline void
init_suboffsets(Py_buffer * dest,const Py_buffer * src)576 init_suboffsets(Py_buffer *dest, const Py_buffer *src)
577 {
578 Py_ssize_t i;
579
580 if (src->suboffsets == NULL) {
581 dest->suboffsets = NULL;
582 return;
583 }
584 for (i = 0; i < src->ndim; i++)
585 dest->suboffsets[i] = src->suboffsets[i];
586 }
587
588 /* len = product(shape) * itemsize */
589 static inline void
init_len(Py_buffer * view)590 init_len(Py_buffer *view)
591 {
592 Py_ssize_t i, len;
593
594 len = 1;
595 for (i = 0; i < view->ndim; i++)
596 len *= view->shape[i];
597 len *= view->itemsize;
598
599 view->len = len;
600 }
601
602 /* Initialize memoryview buffer properties. */
603 static void
init_flags(PyMemoryViewObject * mv)604 init_flags(PyMemoryViewObject *mv)
605 {
606 const Py_buffer *view = &mv->view;
607 int flags = 0;
608
609 switch (view->ndim) {
610 case 0:
611 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
612 _Py_MEMORYVIEW_FORTRAN);
613 break;
614 case 1:
615 if (MV_CONTIGUOUS_NDIM1(view))
616 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
617 break;
618 default:
619 if (PyBuffer_IsContiguous(view, 'C'))
620 flags |= _Py_MEMORYVIEW_C;
621 if (PyBuffer_IsContiguous(view, 'F'))
622 flags |= _Py_MEMORYVIEW_FORTRAN;
623 break;
624 }
625
626 if (view->suboffsets) {
627 flags |= _Py_MEMORYVIEW_PIL;
628 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
629 }
630
631 mv->flags = flags;
632 }
633
634 /* Allocate a new memoryview and perform basic initialization. New memoryviews
635 are exclusively created through the mbuf_add functions. */
636 static inline PyMemoryViewObject *
memory_alloc(int ndim)637 memory_alloc(int ndim)
638 {
639 PyMemoryViewObject *mv;
640
641 mv = (PyMemoryViewObject *)
642 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
643 if (mv == NULL)
644 return NULL;
645
646 mv->mbuf = NULL;
647 mv->hash = -1;
648 mv->flags = 0;
649 mv->exports = 0;
650 mv->view.ndim = ndim;
651 mv->view.shape = mv->ob_array;
652 mv->view.strides = mv->ob_array + ndim;
653 mv->view.suboffsets = mv->ob_array + 2 * ndim;
654 mv->weakreflist = NULL;
655
656 _PyObject_GC_TRACK(mv);
657 return mv;
658 }
659
660 /*
661 Return a new memoryview that is registered with mbuf. If src is NULL,
662 use mbuf->master as the underlying buffer. Otherwise, use src.
663
664 The new memoryview has full buffer information: shape and strides
665 are always present, suboffsets as needed. Arrays are copied to
666 the memoryview's ob_array field.
667 */
668 static PyObject *
mbuf_add_view(_PyManagedBufferObject * mbuf,const Py_buffer * src)669 mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
670 {
671 PyMemoryViewObject *mv;
672 Py_buffer *dest;
673
674 if (src == NULL)
675 src = &mbuf->master;
676
677 if (src->ndim > PyBUF_MAX_NDIM) {
678 PyErr_SetString(PyExc_ValueError,
679 "memoryview: number of dimensions must not exceed "
680 Py_STRINGIFY(PyBUF_MAX_NDIM));
681 return NULL;
682 }
683
684 mv = memory_alloc(src->ndim);
685 if (mv == NULL)
686 return NULL;
687
688 dest = &mv->view;
689 init_shared_values(dest, src);
690 init_shape_strides(dest, src);
691 init_suboffsets(dest, src);
692 init_flags(mv);
693
694 mv->mbuf = mbuf;
695 Py_INCREF(mbuf);
696 mbuf->exports++;
697
698 return (PyObject *)mv;
699 }
700
701 /* Register an incomplete view: shape, strides, suboffsets and flags still
702 need to be initialized. Use 'ndim' instead of src->ndim to determine the
703 size of the memoryview's ob_array.
704
705 Assumption: ndim <= PyBUF_MAX_NDIM. */
706 static PyObject *
mbuf_add_incomplete_view(_PyManagedBufferObject * mbuf,const Py_buffer * src,int ndim)707 mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
708 int ndim)
709 {
710 PyMemoryViewObject *mv;
711 Py_buffer *dest;
712
713 if (src == NULL)
714 src = &mbuf->master;
715
716 assert(ndim <= PyBUF_MAX_NDIM);
717
718 mv = memory_alloc(ndim);
719 if (mv == NULL)
720 return NULL;
721
722 dest = &mv->view;
723 init_shared_values(dest, src);
724
725 mv->mbuf = mbuf;
726 Py_INCREF(mbuf);
727 mbuf->exports++;
728
729 return (PyObject *)mv;
730 }
731
732 /* Expose a raw memory area as a view of contiguous bytes. flags can be
733 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
734 The memoryview has complete buffer information. */
735 PyObject *
PyMemoryView_FromMemory(char * mem,Py_ssize_t size,int flags)736 PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
737 {
738 _PyManagedBufferObject *mbuf;
739 PyObject *mv;
740 int readonly;
741
742 assert(mem != NULL);
743 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
744
745 mbuf = mbuf_alloc();
746 if (mbuf == NULL)
747 return NULL;
748
749 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
750 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
751 PyBUF_FULL_RO);
752
753 mv = mbuf_add_view(mbuf, NULL);
754 Py_DECREF(mbuf);
755
756 return mv;
757 }
758
759 /* Create a memoryview from a given Py_buffer. For simple byte views,
760 PyMemoryView_FromMemory() should be used instead.
761 This function is the only entry point that can create a master buffer
762 without full information. Because of this fact init_shape_strides()
763 must be able to reconstruct missing values. */
764 PyObject *
PyMemoryView_FromBuffer(Py_buffer * info)765 PyMemoryView_FromBuffer(Py_buffer *info)
766 {
767 _PyManagedBufferObject *mbuf;
768 PyObject *mv;
769
770 if (info->buf == NULL) {
771 PyErr_SetString(PyExc_ValueError,
772 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
773 return NULL;
774 }
775
776 mbuf = mbuf_alloc();
777 if (mbuf == NULL)
778 return NULL;
779
780 /* info->obj is either NULL or a borrowed reference. This reference
781 should not be decremented in PyBuffer_Release(). */
782 mbuf->master = *info;
783 mbuf->master.obj = NULL;
784
785 mv = mbuf_add_view(mbuf, NULL);
786 Py_DECREF(mbuf);
787
788 return mv;
789 }
790
791 /* Create a memoryview from an object that implements the buffer protocol.
792 If the object is a memoryview, the new memoryview must be registered
793 with the same managed buffer. Otherwise, a new managed buffer is created. */
794 PyObject *
PyMemoryView_FromObject(PyObject * v)795 PyMemoryView_FromObject(PyObject *v)
796 {
797 _PyManagedBufferObject *mbuf;
798
799 if (PyMemoryView_Check(v)) {
800 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
801 CHECK_RELEASED(mv);
802 return mbuf_add_view(mv->mbuf, &mv->view);
803 }
804 else if (PyObject_CheckBuffer(v)) {
805 PyObject *ret;
806 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
807 if (mbuf == NULL)
808 return NULL;
809 ret = mbuf_add_view(mbuf, NULL);
810 Py_DECREF(mbuf);
811 return ret;
812 }
813
814 PyErr_Format(PyExc_TypeError,
815 "memoryview: a bytes-like object is required, not '%.200s'",
816 Py_TYPE(v)->tp_name);
817 return NULL;
818 }
819
820 /* Copy the format string from a base object that might vanish. */
821 static int
mbuf_copy_format(_PyManagedBufferObject * mbuf,const char * fmt)822 mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
823 {
824 if (fmt != NULL) {
825 char *cp = PyMem_Malloc(strlen(fmt)+1);
826 if (cp == NULL) {
827 PyErr_NoMemory();
828 return -1;
829 }
830 mbuf->master.format = strcpy(cp, fmt);
831 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
832 }
833
834 return 0;
835 }
836
837 /*
838 Return a memoryview that is based on a contiguous copy of src.
839 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
840
841 Ownership rules:
842 1) As usual, the returned memoryview has a private copy
843 of src->shape, src->strides and src->suboffsets.
844 2) src->format is copied to the master buffer and released
845 in mbuf_dealloc(). The releasebufferproc of the bytes
846 object is NULL, so it does not matter that mbuf_release()
847 passes the altered format pointer to PyBuffer_Release().
848 */
849 static PyObject *
memory_from_contiguous_copy(Py_buffer * src,char order)850 memory_from_contiguous_copy(Py_buffer *src, char order)
851 {
852 _PyManagedBufferObject *mbuf;
853 PyMemoryViewObject *mv;
854 PyObject *bytes;
855 Py_buffer *dest;
856 int i;
857
858 assert(src->ndim > 0);
859 assert(src->shape != NULL);
860
861 bytes = PyBytes_FromStringAndSize(NULL, src->len);
862 if (bytes == NULL)
863 return NULL;
864
865 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
866 Py_DECREF(bytes);
867 if (mbuf == NULL)
868 return NULL;
869
870 if (mbuf_copy_format(mbuf, src->format) < 0) {
871 Py_DECREF(mbuf);
872 return NULL;
873 }
874
875 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
876 Py_DECREF(mbuf);
877 if (mv == NULL)
878 return NULL;
879
880 dest = &mv->view;
881
882 /* shared values are initialized correctly except for itemsize */
883 dest->itemsize = src->itemsize;
884
885 /* shape and strides */
886 for (i = 0; i < src->ndim; i++) {
887 dest->shape[i] = src->shape[i];
888 }
889 if (order == 'C' || order == 'A') {
890 init_strides_from_shape(dest);
891 }
892 else {
893 init_fortran_strides_from_shape(dest);
894 }
895 /* suboffsets */
896 dest->suboffsets = NULL;
897
898 /* flags */
899 init_flags(mv);
900
901 if (copy_buffer(dest, src) < 0) {
902 Py_DECREF(mv);
903 return NULL;
904 }
905
906 return (PyObject *)mv;
907 }
908
909 /*
910 Return a new memoryview object based on a contiguous exporter with
911 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
912 The logical structure of the input and output buffers is the same
913 (i.e. tolist(input) == tolist(output)), but the physical layout in
914 memory can be explicitly chosen.
915
916 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
917 otherwise it may be writable or read-only.
918
919 If the exporter is already contiguous with the desired target order,
920 the memoryview will be directly based on the exporter.
921
922 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
923 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
924 'F'ortran order otherwise.
925 */
926 PyObject *
PyMemoryView_GetContiguous(PyObject * obj,int buffertype,char order)927 PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
928 {
929 PyMemoryViewObject *mv;
930 PyObject *ret;
931 Py_buffer *view;
932
933 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
934 assert(order == 'C' || order == 'F' || order == 'A');
935
936 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
937 if (mv == NULL)
938 return NULL;
939
940 view = &mv->view;
941 if (buffertype == PyBUF_WRITE && view->readonly) {
942 PyErr_SetString(PyExc_BufferError,
943 "underlying buffer is not writable");
944 Py_DECREF(mv);
945 return NULL;
946 }
947
948 if (PyBuffer_IsContiguous(view, order))
949 return (PyObject *)mv;
950
951 if (buffertype == PyBUF_WRITE) {
952 PyErr_SetString(PyExc_BufferError,
953 "writable contiguous buffer requested "
954 "for a non-contiguous object.");
955 Py_DECREF(mv);
956 return NULL;
957 }
958
959 ret = memory_from_contiguous_copy(view, order);
960 Py_DECREF(mv);
961 return ret;
962 }
963
964
965 static PyObject *
memory_new(PyTypeObject * subtype,PyObject * args,PyObject * kwds)966 memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
967 {
968 PyObject *obj;
969 static char *kwlist[] = {"object", NULL};
970
971 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
972 &obj)) {
973 return NULL;
974 }
975
976 return PyMemoryView_FromObject(obj);
977 }
978
979
980 /****************************************************************************/
981 /* Previously in abstract.c */
982 /****************************************************************************/
983
984 typedef struct {
985 Py_buffer view;
986 Py_ssize_t array[1];
987 } Py_buffer_full;
988
989 int
PyBuffer_ToContiguous(void * buf,Py_buffer * src,Py_ssize_t len,char order)990 PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
991 {
992 Py_buffer_full *fb = NULL;
993 int ret;
994
995 assert(order == 'C' || order == 'F' || order == 'A');
996
997 if (len != src->len) {
998 PyErr_SetString(PyExc_ValueError,
999 "PyBuffer_ToContiguous: len != view->len");
1000 return -1;
1001 }
1002
1003 if (PyBuffer_IsContiguous(src, order)) {
1004 memcpy((char *)buf, src->buf, len);
1005 return 0;
1006 }
1007
1008 /* buffer_to_contiguous() assumes PyBUF_FULL */
1009 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
1010 if (fb == NULL) {
1011 PyErr_NoMemory();
1012 return -1;
1013 }
1014 fb->view.ndim = src->ndim;
1015 fb->view.shape = fb->array;
1016 fb->view.strides = fb->array + src->ndim;
1017 fb->view.suboffsets = fb->array + 2 * src->ndim;
1018
1019 init_shared_values(&fb->view, src);
1020 init_shape_strides(&fb->view, src);
1021 init_suboffsets(&fb->view, src);
1022
1023 src = &fb->view;
1024
1025 ret = buffer_to_contiguous(buf, src, order);
1026 PyMem_Free(fb);
1027 return ret;
1028 }
1029
1030
1031 /****************************************************************************/
1032 /* Release/GC management */
1033 /****************************************************************************/
1034
1035 /* Inform the managed buffer that this particular memoryview will not access
1036 the underlying buffer again. If no other memoryviews are registered with
1037 the managed buffer, the underlying buffer is released instantly and
1038 marked as inaccessible for both the memoryview and the managed buffer.
1039
1040 This function fails if the memoryview itself has exported buffers. */
1041 static int
_memory_release(PyMemoryViewObject * self)1042 _memory_release(PyMemoryViewObject *self)
1043 {
1044 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1045 return 0;
1046
1047 if (self->exports == 0) {
1048 self->flags |= _Py_MEMORYVIEW_RELEASED;
1049 assert(self->mbuf->exports > 0);
1050 if (--self->mbuf->exports == 0)
1051 mbuf_release(self->mbuf);
1052 return 0;
1053 }
1054 if (self->exports > 0) {
1055 PyErr_Format(PyExc_BufferError,
1056 "memoryview has %zd exported buffer%s", self->exports,
1057 self->exports==1 ? "" : "s");
1058 return -1;
1059 }
1060
1061 Py_FatalError("_memory_release(): negative export count");
1062 return -1;
1063 }
1064
1065 static PyObject *
memory_release(PyMemoryViewObject * self,PyObject * noargs)1066 memory_release(PyMemoryViewObject *self, PyObject *noargs)
1067 {
1068 if (_memory_release(self) < 0)
1069 return NULL;
1070 Py_RETURN_NONE;
1071 }
1072
1073 static void
memory_dealloc(PyMemoryViewObject * self)1074 memory_dealloc(PyMemoryViewObject *self)
1075 {
1076 assert(self->exports == 0);
1077 _PyObject_GC_UNTRACK(self);
1078 (void)_memory_release(self);
1079 Py_CLEAR(self->mbuf);
1080 if (self->weakreflist != NULL)
1081 PyObject_ClearWeakRefs((PyObject *) self);
1082 PyObject_GC_Del(self);
1083 }
1084
1085 static int
memory_traverse(PyMemoryViewObject * self,visitproc visit,void * arg)1086 memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
1087 {
1088 Py_VISIT(self->mbuf);
1089 return 0;
1090 }
1091
1092 static int
memory_clear(PyMemoryViewObject * self)1093 memory_clear(PyMemoryViewObject *self)
1094 {
1095 (void)_memory_release(self);
1096 Py_CLEAR(self->mbuf);
1097 return 0;
1098 }
1099
1100 static PyObject *
memory_enter(PyObject * self,PyObject * args)1101 memory_enter(PyObject *self, PyObject *args)
1102 {
1103 CHECK_RELEASED(self);
1104 Py_INCREF(self);
1105 return self;
1106 }
1107
1108 static PyObject *
memory_exit(PyObject * self,PyObject * args)1109 memory_exit(PyObject *self, PyObject *args)
1110 {
1111 return memory_release((PyMemoryViewObject *)self, NULL);
1112 }
1113
1114
1115 /****************************************************************************/
1116 /* Casting format and shape */
1117 /****************************************************************************/
1118
1119 #define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1120
1121 static inline Py_ssize_t
get_native_fmtchar(char * result,const char * fmt)1122 get_native_fmtchar(char *result, const char *fmt)
1123 {
1124 Py_ssize_t size = -1;
1125
1126 if (fmt[0] == '@') fmt++;
1127
1128 switch (fmt[0]) {
1129 case 'c': case 'b': case 'B': size = sizeof(char); break;
1130 case 'h': case 'H': size = sizeof(short); break;
1131 case 'i': case 'I': size = sizeof(int); break;
1132 case 'l': case 'L': size = sizeof(long); break;
1133 case 'q': case 'Q': size = sizeof(long long); break;
1134 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1135 case 'f': size = sizeof(float); break;
1136 case 'd': size = sizeof(double); break;
1137 case '?': size = sizeof(_Bool); break;
1138 case 'P': size = sizeof(void *); break;
1139 }
1140
1141 if (size > 0 && fmt[1] == '\0') {
1142 *result = fmt[0];
1143 return size;
1144 }
1145
1146 return -1;
1147 }
1148
1149 static inline const char *
get_native_fmtstr(const char * fmt)1150 get_native_fmtstr(const char *fmt)
1151 {
1152 int at = 0;
1153
1154 if (fmt[0] == '@') {
1155 at = 1;
1156 fmt++;
1157 }
1158 if (fmt[0] == '\0' || fmt[1] != '\0') {
1159 return NULL;
1160 }
1161
1162 #define RETURN(s) do { return at ? "@" s : s; } while (0)
1163
1164 switch (fmt[0]) {
1165 case 'c': RETURN("c");
1166 case 'b': RETURN("b");
1167 case 'B': RETURN("B");
1168 case 'h': RETURN("h");
1169 case 'H': RETURN("H");
1170 case 'i': RETURN("i");
1171 case 'I': RETURN("I");
1172 case 'l': RETURN("l");
1173 case 'L': RETURN("L");
1174 case 'q': RETURN("q");
1175 case 'Q': RETURN("Q");
1176 case 'n': RETURN("n");
1177 case 'N': RETURN("N");
1178 case 'f': RETURN("f");
1179 case 'd': RETURN("d");
1180 case '?': RETURN("?");
1181 case 'P': RETURN("P");
1182 }
1183
1184 return NULL;
1185 }
1186
1187
1188 /* Cast a memoryview's data type to 'format'. The input array must be
1189 C-contiguous. At least one of input-format, output-format must have
1190 byte size. The output array is 1-D, with the same byte length as the
1191 input array. Thus, view->len must be a multiple of the new itemsize. */
1192 static int
cast_to_1D(PyMemoryViewObject * mv,PyObject * format)1193 cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1194 {
1195 Py_buffer *view = &mv->view;
1196 PyObject *asciifmt;
1197 char srcchar, destchar;
1198 Py_ssize_t itemsize;
1199 int ret = -1;
1200
1201 assert(view->ndim >= 1);
1202 assert(Py_SIZE(mv) == 3*view->ndim);
1203 assert(view->shape == mv->ob_array);
1204 assert(view->strides == mv->ob_array + view->ndim);
1205 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1206
1207 asciifmt = PyUnicode_AsASCIIString(format);
1208 if (asciifmt == NULL)
1209 return ret;
1210
1211 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1212 if (itemsize < 0) {
1213 PyErr_SetString(PyExc_ValueError,
1214 "memoryview: destination format must be a native single "
1215 "character format prefixed with an optional '@'");
1216 goto out;
1217 }
1218
1219 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1220 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
1221 PyErr_SetString(PyExc_TypeError,
1222 "memoryview: cannot cast between two non-byte formats");
1223 goto out;
1224 }
1225 if (view->len % itemsize) {
1226 PyErr_SetString(PyExc_TypeError,
1227 "memoryview: length is not a multiple of itemsize");
1228 goto out;
1229 }
1230
1231 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
1232 if (view->format == NULL) {
1233 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1234 PyErr_SetString(PyExc_RuntimeError,
1235 "memoryview: internal error");
1236 goto out;
1237 }
1238 view->itemsize = itemsize;
1239
1240 view->ndim = 1;
1241 view->shape[0] = view->len / view->itemsize;
1242 view->strides[0] = view->itemsize;
1243 view->suboffsets = NULL;
1244
1245 init_flags(mv);
1246
1247 ret = 0;
1248
1249 out:
1250 Py_DECREF(asciifmt);
1251 return ret;
1252 }
1253
1254 /* The memoryview must have space for 3*len(seq) elements. */
1255 static Py_ssize_t
copy_shape(Py_ssize_t * shape,const PyObject * seq,Py_ssize_t ndim,Py_ssize_t itemsize)1256 copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1257 Py_ssize_t itemsize)
1258 {
1259 Py_ssize_t x, i;
1260 Py_ssize_t len = itemsize;
1261
1262 for (i = 0; i < ndim; i++) {
1263 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1264 if (!PyLong_Check(tmp)) {
1265 PyErr_SetString(PyExc_TypeError,
1266 "memoryview.cast(): elements of shape must be integers");
1267 return -1;
1268 }
1269 x = PyLong_AsSsize_t(tmp);
1270 if (x == -1 && PyErr_Occurred()) {
1271 return -1;
1272 }
1273 if (x <= 0) {
1274 /* In general elements of shape may be 0, but not for casting. */
1275 PyErr_Format(PyExc_ValueError,
1276 "memoryview.cast(): elements of shape must be integers > 0");
1277 return -1;
1278 }
1279 if (x > PY_SSIZE_T_MAX / len) {
1280 PyErr_Format(PyExc_ValueError,
1281 "memoryview.cast(): product(shape) > SSIZE_MAX");
1282 return -1;
1283 }
1284 len *= x;
1285 shape[i] = x;
1286 }
1287
1288 return len;
1289 }
1290
1291 /* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1292 If the result array does not have exactly the same byte length as the
1293 input array, raise ValueError. */
1294 static int
cast_to_ND(PyMemoryViewObject * mv,const PyObject * shape,int ndim)1295 cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1296 {
1297 Py_buffer *view = &mv->view;
1298 Py_ssize_t len;
1299
1300 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1301 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1302 assert(view->shape == mv->ob_array);
1303 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1304 assert(view->suboffsets == NULL);
1305
1306 view->ndim = ndim;
1307 if (view->ndim == 0) {
1308 view->shape = NULL;
1309 view->strides = NULL;
1310 len = view->itemsize;
1311 }
1312 else {
1313 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1314 if (len < 0)
1315 return -1;
1316 init_strides_from_shape(view);
1317 }
1318
1319 if (view->len != len) {
1320 PyErr_SetString(PyExc_TypeError,
1321 "memoryview: product(shape) * itemsize != buffer size");
1322 return -1;
1323 }
1324
1325 init_flags(mv);
1326
1327 return 0;
1328 }
1329
1330 static int
zero_in_shape(PyMemoryViewObject * mv)1331 zero_in_shape(PyMemoryViewObject *mv)
1332 {
1333 Py_buffer *view = &mv->view;
1334 Py_ssize_t i;
1335
1336 for (i = 0; i < view->ndim; i++)
1337 if (view->shape[i] == 0)
1338 return 1;
1339
1340 return 0;
1341 }
1342
1343 /*
1344 Cast a copy of 'self' to a different view. The input view must
1345 be C-contiguous. The function always casts the input view to a
1346 1-D output according to 'format'. At least one of input-format,
1347 output-format must have byte size.
1348
1349 If 'shape' is given, the 1-D view from the previous step will
1350 be cast to a C-contiguous view with new shape and strides.
1351
1352 All casts must result in views that will have the exact byte
1353 size of the original input. Otherwise, an error is raised.
1354 */
1355 static PyObject *
memory_cast(PyMemoryViewObject * self,PyObject * args,PyObject * kwds)1356 memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
1357 {
1358 static char *kwlist[] = {"format", "shape", NULL};
1359 PyMemoryViewObject *mv = NULL;
1360 PyObject *shape = NULL;
1361 PyObject *format;
1362 Py_ssize_t ndim = 1;
1363
1364 CHECK_RELEASED(self);
1365
1366 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1367 &format, &shape)) {
1368 return NULL;
1369 }
1370 if (!PyUnicode_Check(format)) {
1371 PyErr_SetString(PyExc_TypeError,
1372 "memoryview: format argument must be a string");
1373 return NULL;
1374 }
1375 if (!MV_C_CONTIGUOUS(self->flags)) {
1376 PyErr_SetString(PyExc_TypeError,
1377 "memoryview: casts are restricted to C-contiguous views");
1378 return NULL;
1379 }
1380 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
1381 PyErr_SetString(PyExc_TypeError,
1382 "memoryview: cannot cast view with zeros in shape or strides");
1383 return NULL;
1384 }
1385 if (shape) {
1386 CHECK_LIST_OR_TUPLE(shape)
1387 ndim = PySequence_Fast_GET_SIZE(shape);
1388 if (ndim > PyBUF_MAX_NDIM) {
1389 PyErr_SetString(PyExc_ValueError,
1390 "memoryview: number of dimensions must not exceed "
1391 Py_STRINGIFY(PyBUF_MAX_NDIM));
1392 return NULL;
1393 }
1394 if (self->view.ndim != 1 && ndim != 1) {
1395 PyErr_SetString(PyExc_TypeError,
1396 "memoryview: cast must be 1D -> ND or ND -> 1D");
1397 return NULL;
1398 }
1399 }
1400
1401 mv = (PyMemoryViewObject *)
1402 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1403 if (mv == NULL)
1404 return NULL;
1405
1406 if (cast_to_1D(mv, format) < 0)
1407 goto error;
1408 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1409 goto error;
1410
1411 return (PyObject *)mv;
1412
1413 error:
1414 Py_DECREF(mv);
1415 return NULL;
1416 }
1417
1418 static PyObject *
memory_toreadonly(PyMemoryViewObject * self,PyObject * noargs)1419 memory_toreadonly(PyMemoryViewObject *self, PyObject *noargs)
1420 {
1421 CHECK_RELEASED(self);
1422 /* Even if self is already readonly, we still need to create a new
1423 * object for .release() to work correctly.
1424 */
1425 self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1426 if (self != NULL) {
1427 self->view.readonly = 1;
1428 };
1429 return (PyObject *) self;
1430 }
1431
1432
1433 /**************************************************************************/
1434 /* getbuffer */
1435 /**************************************************************************/
1436
1437 static int
memory_getbuf(PyMemoryViewObject * self,Py_buffer * view,int flags)1438 memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1439 {
1440 Py_buffer *base = &self->view;
1441 int baseflags = self->flags;
1442
1443 CHECK_RELEASED_INT(self);
1444
1445 /* start with complete information */
1446 *view = *base;
1447 view->obj = NULL;
1448
1449 if (REQ_WRITABLE(flags) && base->readonly) {
1450 PyErr_SetString(PyExc_BufferError,
1451 "memoryview: underlying buffer is not writable");
1452 return -1;
1453 }
1454 if (!REQ_FORMAT(flags)) {
1455 /* NULL indicates that the buffer's data type has been cast to 'B'.
1456 view->itemsize is the _previous_ itemsize. If shape is present,
1457 the equality product(shape) * itemsize = len still holds at this
1458 point. The equality calcsize(format) = itemsize does _not_ hold
1459 from here on! */
1460 view->format = NULL;
1461 }
1462
1463 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1464 PyErr_SetString(PyExc_BufferError,
1465 "memoryview: underlying buffer is not C-contiguous");
1466 return -1;
1467 }
1468 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1469 PyErr_SetString(PyExc_BufferError,
1470 "memoryview: underlying buffer is not Fortran contiguous");
1471 return -1;
1472 }
1473 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1474 PyErr_SetString(PyExc_BufferError,
1475 "memoryview: underlying buffer is not contiguous");
1476 return -1;
1477 }
1478 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1479 PyErr_SetString(PyExc_BufferError,
1480 "memoryview: underlying buffer requires suboffsets");
1481 return -1;
1482 }
1483 if (!REQ_STRIDES(flags)) {
1484 if (!MV_C_CONTIGUOUS(baseflags)) {
1485 PyErr_SetString(PyExc_BufferError,
1486 "memoryview: underlying buffer is not C-contiguous");
1487 return -1;
1488 }
1489 view->strides = NULL;
1490 }
1491 if (!REQ_SHAPE(flags)) {
1492 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1493 so base->buf = ndbuf->data. */
1494 if (view->format != NULL) {
1495 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1496 not make sense. */
1497 PyErr_Format(PyExc_BufferError,
1498 "memoryview: cannot cast to unsigned bytes if the format flag "
1499 "is present");
1500 return -1;
1501 }
1502 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1503 do _not_ hold from here on! */
1504 view->ndim = 1;
1505 view->shape = NULL;
1506 }
1507
1508
1509 view->obj = (PyObject *)self;
1510 Py_INCREF(view->obj);
1511 self->exports++;
1512
1513 return 0;
1514 }
1515
1516 static void
memory_releasebuf(PyMemoryViewObject * self,Py_buffer * view)1517 memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1518 {
1519 self->exports--;
1520 return;
1521 /* PyBuffer_Release() decrements view->obj after this function returns. */
1522 }
1523
1524 /* Buffer methods */
1525 static PyBufferProcs memory_as_buffer = {
1526 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1527 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1528 };
1529
1530
1531 /****************************************************************************/
1532 /* Optimized pack/unpack for all native format specifiers */
1533 /****************************************************************************/
1534
1535 /*
1536 Fix exceptions:
1537 1) Include format string in the error message.
1538 2) OverflowError -> ValueError.
1539 3) The error message from PyNumber_Index() is not ideal.
1540 */
1541 static int
type_error_int(const char * fmt)1542 type_error_int(const char *fmt)
1543 {
1544 PyErr_Format(PyExc_TypeError,
1545 "memoryview: invalid type for format '%s'", fmt);
1546 return -1;
1547 }
1548
1549 static int
value_error_int(const char * fmt)1550 value_error_int(const char *fmt)
1551 {
1552 PyErr_Format(PyExc_ValueError,
1553 "memoryview: invalid value for format '%s'", fmt);
1554 return -1;
1555 }
1556
1557 static int
fix_error_int(const char * fmt)1558 fix_error_int(const char *fmt)
1559 {
1560 assert(PyErr_Occurred());
1561 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1562 PyErr_Clear();
1563 return type_error_int(fmt);
1564 }
1565 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1566 PyErr_ExceptionMatches(PyExc_ValueError)) {
1567 PyErr_Clear();
1568 return value_error_int(fmt);
1569 }
1570
1571 return -1;
1572 }
1573
1574 /* Accept integer objects or objects with an __index__() method. */
1575 static long
pylong_as_ld(PyObject * item)1576 pylong_as_ld(PyObject *item)
1577 {
1578 PyObject *tmp;
1579 long ld;
1580
1581 tmp = PyNumber_Index(item);
1582 if (tmp == NULL)
1583 return -1;
1584
1585 ld = PyLong_AsLong(tmp);
1586 Py_DECREF(tmp);
1587 return ld;
1588 }
1589
1590 static unsigned long
pylong_as_lu(PyObject * item)1591 pylong_as_lu(PyObject *item)
1592 {
1593 PyObject *tmp;
1594 unsigned long lu;
1595
1596 tmp = PyNumber_Index(item);
1597 if (tmp == NULL)
1598 return (unsigned long)-1;
1599
1600 lu = PyLong_AsUnsignedLong(tmp);
1601 Py_DECREF(tmp);
1602 return lu;
1603 }
1604
1605 static long long
pylong_as_lld(PyObject * item)1606 pylong_as_lld(PyObject *item)
1607 {
1608 PyObject *tmp;
1609 long long lld;
1610
1611 tmp = PyNumber_Index(item);
1612 if (tmp == NULL)
1613 return -1;
1614
1615 lld = PyLong_AsLongLong(tmp);
1616 Py_DECREF(tmp);
1617 return lld;
1618 }
1619
1620 static unsigned long long
pylong_as_llu(PyObject * item)1621 pylong_as_llu(PyObject *item)
1622 {
1623 PyObject *tmp;
1624 unsigned long long llu;
1625
1626 tmp = PyNumber_Index(item);
1627 if (tmp == NULL)
1628 return (unsigned long long)-1;
1629
1630 llu = PyLong_AsUnsignedLongLong(tmp);
1631 Py_DECREF(tmp);
1632 return llu;
1633 }
1634
1635 static Py_ssize_t
pylong_as_zd(PyObject * item)1636 pylong_as_zd(PyObject *item)
1637 {
1638 PyObject *tmp;
1639 Py_ssize_t zd;
1640
1641 tmp = PyNumber_Index(item);
1642 if (tmp == NULL)
1643 return -1;
1644
1645 zd = PyLong_AsSsize_t(tmp);
1646 Py_DECREF(tmp);
1647 return zd;
1648 }
1649
1650 static size_t
pylong_as_zu(PyObject * item)1651 pylong_as_zu(PyObject *item)
1652 {
1653 PyObject *tmp;
1654 size_t zu;
1655
1656 tmp = PyNumber_Index(item);
1657 if (tmp == NULL)
1658 return (size_t)-1;
1659
1660 zu = PyLong_AsSize_t(tmp);
1661 Py_DECREF(tmp);
1662 return zu;
1663 }
1664
1665 /* Timings with the ndarray from _testbuffer.c indicate that using the
1666 struct module is around 15x slower than the two functions below. */
1667
1668 #define UNPACK_SINGLE(dest, ptr, type) \
1669 do { \
1670 type x; \
1671 memcpy((char *)&x, ptr, sizeof x); \
1672 dest = x; \
1673 } while (0)
1674
1675 /* Unpack a single item. 'fmt' can be any native format character in struct
1676 module syntax. This function is very sensitive to small changes. With this
1677 layout gcc automatically generates a fast jump table. */
1678 static inline PyObject *
unpack_single(const char * ptr,const char * fmt)1679 unpack_single(const char *ptr, const char *fmt)
1680 {
1681 unsigned long long llu;
1682 unsigned long lu;
1683 size_t zu;
1684 long long lld;
1685 long ld;
1686 Py_ssize_t zd;
1687 double d;
1688 unsigned char uc;
1689 void *p;
1690
1691 switch (fmt[0]) {
1692
1693 /* signed integers and fast path for 'B' */
1694 case 'B': uc = *((const unsigned char *)ptr); goto convert_uc;
1695 case 'b': ld = *((const signed char *)ptr); goto convert_ld;
1696 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1697 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1698 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1699
1700 /* boolean */
1701 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
1702
1703 /* unsigned integers */
1704 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1705 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1706 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1707
1708 /* native 64-bit */
1709 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1710 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
1711
1712 /* ssize_t and size_t */
1713 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1714 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1715
1716 /* floats */
1717 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1718 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1719
1720 /* bytes object */
1721 case 'c': goto convert_bytes;
1722
1723 /* pointer */
1724 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1725
1726 /* default */
1727 default: goto err_format;
1728 }
1729
1730 convert_uc:
1731 /* PyLong_FromUnsignedLong() is slower */
1732 return PyLong_FromLong(uc);
1733 convert_ld:
1734 return PyLong_FromLong(ld);
1735 convert_lu:
1736 return PyLong_FromUnsignedLong(lu);
1737 convert_lld:
1738 return PyLong_FromLongLong(lld);
1739 convert_llu:
1740 return PyLong_FromUnsignedLongLong(llu);
1741 convert_zd:
1742 return PyLong_FromSsize_t(zd);
1743 convert_zu:
1744 return PyLong_FromSize_t(zu);
1745 convert_double:
1746 return PyFloat_FromDouble(d);
1747 convert_bool:
1748 return PyBool_FromLong(ld);
1749 convert_bytes:
1750 return PyBytes_FromStringAndSize(ptr, 1);
1751 convert_pointer:
1752 return PyLong_FromVoidPtr(p);
1753 err_format:
1754 PyErr_Format(PyExc_NotImplementedError,
1755 "memoryview: format %s not supported", fmt);
1756 return NULL;
1757 }
1758
1759 #define PACK_SINGLE(ptr, src, type) \
1760 do { \
1761 type x; \
1762 x = (type)src; \
1763 memcpy(ptr, (char *)&x, sizeof x); \
1764 } while (0)
1765
1766 /* Pack a single item. 'fmt' can be any native format character in
1767 struct module syntax. */
1768 static int
pack_single(char * ptr,PyObject * item,const char * fmt)1769 pack_single(char *ptr, PyObject *item, const char *fmt)
1770 {
1771 unsigned long long llu;
1772 unsigned long lu;
1773 size_t zu;
1774 long long lld;
1775 long ld;
1776 Py_ssize_t zd;
1777 double d;
1778 void *p;
1779
1780 switch (fmt[0]) {
1781 /* signed integers */
1782 case 'b': case 'h': case 'i': case 'l':
1783 ld = pylong_as_ld(item);
1784 if (ld == -1 && PyErr_Occurred())
1785 goto err_occurred;
1786 switch (fmt[0]) {
1787 case 'b':
1788 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1789 *((signed char *)ptr) = (signed char)ld; break;
1790 case 'h':
1791 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1792 PACK_SINGLE(ptr, ld, short); break;
1793 case 'i':
1794 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1795 PACK_SINGLE(ptr, ld, int); break;
1796 default: /* 'l' */
1797 PACK_SINGLE(ptr, ld, long); break;
1798 }
1799 break;
1800
1801 /* unsigned integers */
1802 case 'B': case 'H': case 'I': case 'L':
1803 lu = pylong_as_lu(item);
1804 if (lu == (unsigned long)-1 && PyErr_Occurred())
1805 goto err_occurred;
1806 switch (fmt[0]) {
1807 case 'B':
1808 if (lu > UCHAR_MAX) goto err_range;
1809 *((unsigned char *)ptr) = (unsigned char)lu; break;
1810 case 'H':
1811 if (lu > USHRT_MAX) goto err_range;
1812 PACK_SINGLE(ptr, lu, unsigned short); break;
1813 case 'I':
1814 if (lu > UINT_MAX) goto err_range;
1815 PACK_SINGLE(ptr, lu, unsigned int); break;
1816 default: /* 'L' */
1817 PACK_SINGLE(ptr, lu, unsigned long); break;
1818 }
1819 break;
1820
1821 /* native 64-bit */
1822 case 'q':
1823 lld = pylong_as_lld(item);
1824 if (lld == -1 && PyErr_Occurred())
1825 goto err_occurred;
1826 PACK_SINGLE(ptr, lld, long long);
1827 break;
1828 case 'Q':
1829 llu = pylong_as_llu(item);
1830 if (llu == (unsigned long long)-1 && PyErr_Occurred())
1831 goto err_occurred;
1832 PACK_SINGLE(ptr, llu, unsigned long long);
1833 break;
1834
1835 /* ssize_t and size_t */
1836 case 'n':
1837 zd = pylong_as_zd(item);
1838 if (zd == -1 && PyErr_Occurred())
1839 goto err_occurred;
1840 PACK_SINGLE(ptr, zd, Py_ssize_t);
1841 break;
1842 case 'N':
1843 zu = pylong_as_zu(item);
1844 if (zu == (size_t)-1 && PyErr_Occurred())
1845 goto err_occurred;
1846 PACK_SINGLE(ptr, zu, size_t);
1847 break;
1848
1849 /* floats */
1850 case 'f': case 'd':
1851 d = PyFloat_AsDouble(item);
1852 if (d == -1.0 && PyErr_Occurred())
1853 goto err_occurred;
1854 if (fmt[0] == 'f') {
1855 PACK_SINGLE(ptr, d, float);
1856 }
1857 else {
1858 PACK_SINGLE(ptr, d, double);
1859 }
1860 break;
1861
1862 /* bool */
1863 case '?':
1864 ld = PyObject_IsTrue(item);
1865 if (ld < 0)
1866 return -1; /* preserve original error */
1867 PACK_SINGLE(ptr, ld, _Bool);
1868 break;
1869
1870 /* bytes object */
1871 case 'c':
1872 if (!PyBytes_Check(item))
1873 return type_error_int(fmt);
1874 if (PyBytes_GET_SIZE(item) != 1)
1875 return value_error_int(fmt);
1876 *ptr = PyBytes_AS_STRING(item)[0];
1877 break;
1878
1879 /* pointer */
1880 case 'P':
1881 p = PyLong_AsVoidPtr(item);
1882 if (p == NULL && PyErr_Occurred())
1883 goto err_occurred;
1884 PACK_SINGLE(ptr, p, void *);
1885 break;
1886
1887 /* default */
1888 default: goto err_format;
1889 }
1890
1891 return 0;
1892
1893 err_occurred:
1894 return fix_error_int(fmt);
1895 err_range:
1896 return value_error_int(fmt);
1897 err_format:
1898 PyErr_Format(PyExc_NotImplementedError,
1899 "memoryview: format %s not supported", fmt);
1900 return -1;
1901 }
1902
1903
1904 /****************************************************************************/
1905 /* unpack using the struct module */
1906 /****************************************************************************/
1907
1908 /* For reasonable performance it is necessary to cache all objects required
1909 for unpacking. An unpacker can handle the format passed to unpack_from().
1910 Invariant: All pointer fields of the struct should either be NULL or valid
1911 pointers. */
1912 struct unpacker {
1913 PyObject *unpack_from; /* Struct.unpack_from(format) */
1914 PyObject *mview; /* cached memoryview */
1915 char *item; /* buffer for mview */
1916 Py_ssize_t itemsize; /* len(item) */
1917 };
1918
1919 static struct unpacker *
unpacker_new(void)1920 unpacker_new(void)
1921 {
1922 struct unpacker *x = PyMem_Malloc(sizeof *x);
1923
1924 if (x == NULL) {
1925 PyErr_NoMemory();
1926 return NULL;
1927 }
1928
1929 x->unpack_from = NULL;
1930 x->mview = NULL;
1931 x->item = NULL;
1932 x->itemsize = 0;
1933
1934 return x;
1935 }
1936
1937 static void
unpacker_free(struct unpacker * x)1938 unpacker_free(struct unpacker *x)
1939 {
1940 if (x) {
1941 Py_XDECREF(x->unpack_from);
1942 Py_XDECREF(x->mview);
1943 PyMem_Free(x->item);
1944 PyMem_Free(x);
1945 }
1946 }
1947
1948 /* Return a new unpacker for the given format. */
1949 static struct unpacker *
struct_get_unpacker(const char * fmt,Py_ssize_t itemsize)1950 struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1951 {
1952 PyObject *structmodule; /* XXX cache these two */
1953 PyObject *Struct = NULL; /* XXX in globals? */
1954 PyObject *structobj = NULL;
1955 PyObject *format = NULL;
1956 struct unpacker *x = NULL;
1957
1958 structmodule = PyImport_ImportModule("struct");
1959 if (structmodule == NULL)
1960 return NULL;
1961
1962 Struct = PyObject_GetAttrString(structmodule, "Struct");
1963 Py_DECREF(structmodule);
1964 if (Struct == NULL)
1965 return NULL;
1966
1967 x = unpacker_new();
1968 if (x == NULL)
1969 goto error;
1970
1971 format = PyBytes_FromString(fmt);
1972 if (format == NULL)
1973 goto error;
1974
1975 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1976 if (structobj == NULL)
1977 goto error;
1978
1979 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1980 if (x->unpack_from == NULL)
1981 goto error;
1982
1983 x->item = PyMem_Malloc(itemsize);
1984 if (x->item == NULL) {
1985 PyErr_NoMemory();
1986 goto error;
1987 }
1988 x->itemsize = itemsize;
1989
1990 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1991 if (x->mview == NULL)
1992 goto error;
1993
1994
1995 out:
1996 Py_XDECREF(Struct);
1997 Py_XDECREF(format);
1998 Py_XDECREF(structobj);
1999 return x;
2000
2001 error:
2002 unpacker_free(x);
2003 x = NULL;
2004 goto out;
2005 }
2006
2007 /* unpack a single item */
2008 static PyObject *
struct_unpack_single(const char * ptr,struct unpacker * x)2009 struct_unpack_single(const char *ptr, struct unpacker *x)
2010 {
2011 PyObject *v;
2012
2013 memcpy(x->item, ptr, x->itemsize);
2014 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
2015 if (v == NULL)
2016 return NULL;
2017
2018 if (PyTuple_GET_SIZE(v) == 1) {
2019 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
2020 Py_INCREF(tmp);
2021 Py_DECREF(v);
2022 return tmp;
2023 }
2024
2025 return v;
2026 }
2027
2028
2029 /****************************************************************************/
2030 /* Representations */
2031 /****************************************************************************/
2032
2033 /* allow explicit form of native format */
2034 static inline const char *
adjust_fmt(const Py_buffer * view)2035 adjust_fmt(const Py_buffer *view)
2036 {
2037 const char *fmt;
2038
2039 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2040 if (fmt[0] && fmt[1] == '\0')
2041 return fmt;
2042
2043 PyErr_Format(PyExc_NotImplementedError,
2044 "memoryview: unsupported format %s", view->format);
2045 return NULL;
2046 }
2047
2048 /* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2049 static PyObject *
tolist_base(const char * ptr,const Py_ssize_t * shape,const Py_ssize_t * strides,const Py_ssize_t * suboffsets,const char * fmt)2050 tolist_base(const char *ptr, const Py_ssize_t *shape,
2051 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2052 const char *fmt)
2053 {
2054 PyObject *lst, *item;
2055 Py_ssize_t i;
2056
2057 lst = PyList_New(shape[0]);
2058 if (lst == NULL)
2059 return NULL;
2060
2061 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
2062 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
2063 item = unpack_single(xptr, fmt);
2064 if (item == NULL) {
2065 Py_DECREF(lst);
2066 return NULL;
2067 }
2068 PyList_SET_ITEM(lst, i, item);
2069 }
2070
2071 return lst;
2072 }
2073
2074 /* Unpack a multi-dimensional array into a nested list.
2075 Assumption: ndim >= 1. */
2076 static PyObject *
tolist_rec(const char * ptr,Py_ssize_t ndim,const Py_ssize_t * shape,const Py_ssize_t * strides,const Py_ssize_t * suboffsets,const char * fmt)2077 tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2078 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2079 const char *fmt)
2080 {
2081 PyObject *lst, *item;
2082 Py_ssize_t i;
2083
2084 assert(ndim >= 1);
2085 assert(shape != NULL);
2086 assert(strides != NULL);
2087
2088 if (ndim == 1)
2089 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2090
2091 lst = PyList_New(shape[0]);
2092 if (lst == NULL)
2093 return NULL;
2094
2095 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
2096 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
2097 item = tolist_rec(xptr, ndim-1, shape+1,
2098 strides+1, suboffsets ? suboffsets+1 : NULL,
2099 fmt);
2100 if (item == NULL) {
2101 Py_DECREF(lst);
2102 return NULL;
2103 }
2104 PyList_SET_ITEM(lst, i, item);
2105 }
2106
2107 return lst;
2108 }
2109
2110 /* Return a list representation of the memoryview. Currently only buffers
2111 with native format strings are supported. */
2112 static PyObject *
memory_tolist(PyMemoryViewObject * mv,PyObject * noargs)2113 memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2114 {
2115 const Py_buffer *view = &(mv->view);
2116 const char *fmt;
2117
2118 CHECK_RELEASED(mv);
2119
2120 fmt = adjust_fmt(view);
2121 if (fmt == NULL)
2122 return NULL;
2123 if (view->ndim == 0) {
2124 return unpack_single(view->buf, fmt);
2125 }
2126 else if (view->ndim == 1) {
2127 return tolist_base(view->buf, view->shape,
2128 view->strides, view->suboffsets,
2129 fmt);
2130 }
2131 else {
2132 return tolist_rec(view->buf, view->ndim, view->shape,
2133 view->strides, view->suboffsets,
2134 fmt);
2135 }
2136 }
2137
2138 static PyObject *
memory_tobytes(PyMemoryViewObject * self,PyObject * args,PyObject * kwds)2139 memory_tobytes(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
2140 {
2141 static char *kwlist[] = {"order", NULL};
2142 Py_buffer *src = VIEW_ADDR(self);
2143 char *order = NULL;
2144 char ord = 'C';
2145 PyObject *bytes;
2146
2147 CHECK_RELEASED(self);
2148
2149 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z", kwlist, &order)) {
2150 return NULL;
2151 }
2152
2153 if (order) {
2154 if (strcmp(order, "F") == 0) {
2155 ord = 'F';
2156 }
2157 else if (strcmp(order, "A") == 0) {
2158 ord = 'A';
2159 }
2160 else if (strcmp(order, "C") != 0) {
2161 PyErr_SetString(PyExc_ValueError,
2162 "order must be 'C', 'F' or 'A'");
2163 return NULL;
2164 }
2165 }
2166
2167 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2168 if (bytes == NULL)
2169 return NULL;
2170
2171 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, ord) < 0) {
2172 Py_DECREF(bytes);
2173 return NULL;
2174 }
2175
2176 return bytes;
2177 }
2178
2179 /*[clinic input]
2180 memoryview.hex
2181
2182 sep: object = NULL
2183 An optional single character or byte to separate hex bytes.
2184 bytes_per_sep: int = 1
2185 How many bytes between separators. Positive values count from the
2186 right, negative values count from the left.
2187
2188 Return the data in the buffer as a str of hexadecimal numbers.
2189
2190 Example:
2191 >>> value = memoryview(b'\xb9\x01\xef')
2192 >>> value.hex()
2193 'b901ef'
2194 >>> value.hex(':')
2195 'b9:01:ef'
2196 >>> value.hex(':', 2)
2197 'b9:01ef'
2198 >>> value.hex(':', -2)
2199 'b901:ef'
2200 [clinic start generated code]*/
2201
2202 static PyObject *
memoryview_hex_impl(PyMemoryViewObject * self,PyObject * sep,int bytes_per_sep)2203 memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
2204 int bytes_per_sep)
2205 /*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/
2206 {
2207 Py_buffer *src = VIEW_ADDR(self);
2208 PyObject *bytes;
2209 PyObject *ret;
2210
2211 CHECK_RELEASED(self);
2212
2213 if (MV_C_CONTIGUOUS(self->flags)) {
2214 return _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
2215 }
2216
2217 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2218 if (bytes == NULL)
2219 return NULL;
2220
2221 if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, 'C') < 0) {
2222 Py_DECREF(bytes);
2223 return NULL;
2224 }
2225
2226 ret = _Py_strhex_with_sep(
2227 PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes),
2228 sep, bytes_per_sep);
2229 Py_DECREF(bytes);
2230
2231 return ret;
2232 }
2233
2234 static PyObject *
memory_repr(PyMemoryViewObject * self)2235 memory_repr(PyMemoryViewObject *self)
2236 {
2237 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2238 return PyUnicode_FromFormat("<released memory at %p>", self);
2239 else
2240 return PyUnicode_FromFormat("<memory at %p>", self);
2241 }
2242
2243
2244 /**************************************************************************/
2245 /* Indexing and slicing */
2246 /**************************************************************************/
2247
2248 static char *
lookup_dimension(Py_buffer * view,char * ptr,int dim,Py_ssize_t index)2249 lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
2250 {
2251 Py_ssize_t nitems; /* items in the given dimension */
2252
2253 assert(view->shape);
2254 assert(view->strides);
2255
2256 nitems = view->shape[dim];
2257 if (index < 0) {
2258 index += nitems;
2259 }
2260 if (index < 0 || index >= nitems) {
2261 PyErr_Format(PyExc_IndexError,
2262 "index out of bounds on dimension %d", dim + 1);
2263 return NULL;
2264 }
2265
2266 ptr += view->strides[dim] * index;
2267
2268 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
2269
2270 return ptr;
2271 }
2272
2273 /* Get the pointer to the item at index. */
2274 static char *
ptr_from_index(Py_buffer * view,Py_ssize_t index)2275 ptr_from_index(Py_buffer *view, Py_ssize_t index)
2276 {
2277 char *ptr = (char *)view->buf;
2278 return lookup_dimension(view, ptr, 0, index);
2279 }
2280
2281 /* Get the pointer to the item at tuple. */
2282 static char *
ptr_from_tuple(Py_buffer * view,PyObject * tup)2283 ptr_from_tuple(Py_buffer *view, PyObject *tup)
2284 {
2285 char *ptr = (char *)view->buf;
2286 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2287
2288 if (nindices > view->ndim) {
2289 PyErr_Format(PyExc_TypeError,
2290 "cannot index %zd-dimension view with %zd-element tuple",
2291 view->ndim, nindices);
2292 return NULL;
2293 }
2294
2295 for (dim = 0; dim < nindices; dim++) {
2296 Py_ssize_t index;
2297 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2298 PyExc_IndexError);
2299 if (index == -1 && PyErr_Occurred())
2300 return NULL;
2301 ptr = lookup_dimension(view, ptr, (int)dim, index);
2302 if (ptr == NULL)
2303 return NULL;
2304 }
2305 return ptr;
2306 }
2307
2308 /* Return the item at index. In a one-dimensional view, this is an object
2309 with the type specified by view->format. Otherwise, the item is a sub-view.
2310 The function is used in memory_subscript() and memory_as_sequence. */
2311 static PyObject *
memory_item(PyMemoryViewObject * self,Py_ssize_t index)2312 memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2313 {
2314 Py_buffer *view = &(self->view);
2315 const char *fmt;
2316
2317 CHECK_RELEASED(self);
2318
2319 fmt = adjust_fmt(view);
2320 if (fmt == NULL)
2321 return NULL;
2322
2323 if (view->ndim == 0) {
2324 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2325 return NULL;
2326 }
2327 if (view->ndim == 1) {
2328 char *ptr = ptr_from_index(view, index);
2329 if (ptr == NULL)
2330 return NULL;
2331 return unpack_single(ptr, fmt);
2332 }
2333
2334 PyErr_SetString(PyExc_NotImplementedError,
2335 "multi-dimensional sub-views are not implemented");
2336 return NULL;
2337 }
2338
2339 /* Return the item at position *key* (a tuple of indices). */
2340 static PyObject *
memory_item_multi(PyMemoryViewObject * self,PyObject * tup)2341 memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2342 {
2343 Py_buffer *view = &(self->view);
2344 const char *fmt;
2345 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2346 char *ptr;
2347
2348 CHECK_RELEASED(self);
2349
2350 fmt = adjust_fmt(view);
2351 if (fmt == NULL)
2352 return NULL;
2353
2354 if (nindices < view->ndim) {
2355 PyErr_SetString(PyExc_NotImplementedError,
2356 "sub-views are not implemented");
2357 return NULL;
2358 }
2359 ptr = ptr_from_tuple(view, tup);
2360 if (ptr == NULL)
2361 return NULL;
2362 return unpack_single(ptr, fmt);
2363 }
2364
2365 static inline int
init_slice(Py_buffer * base,PyObject * key,int dim)2366 init_slice(Py_buffer *base, PyObject *key, int dim)
2367 {
2368 Py_ssize_t start, stop, step, slicelength;
2369
2370 if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
2371 return -1;
2372 }
2373 slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
2374
2375
2376 if (base->suboffsets == NULL || dim == 0) {
2377 adjust_buf:
2378 base->buf = (char *)base->buf + base->strides[dim] * start;
2379 }
2380 else {
2381 Py_ssize_t n = dim-1;
2382 while (n >= 0 && base->suboffsets[n] < 0)
2383 n--;
2384 if (n < 0)
2385 goto adjust_buf; /* all suboffsets are negative */
2386 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2387 }
2388 base->shape[dim] = slicelength;
2389 base->strides[dim] = base->strides[dim] * step;
2390
2391 return 0;
2392 }
2393
2394 static int
is_multislice(PyObject * key)2395 is_multislice(PyObject *key)
2396 {
2397 Py_ssize_t size, i;
2398
2399 if (!PyTuple_Check(key))
2400 return 0;
2401 size = PyTuple_GET_SIZE(key);
2402 if (size == 0)
2403 return 0;
2404
2405 for (i = 0; i < size; i++) {
2406 PyObject *x = PyTuple_GET_ITEM(key, i);
2407 if (!PySlice_Check(x))
2408 return 0;
2409 }
2410 return 1;
2411 }
2412
2413 static Py_ssize_t
is_multiindex(PyObject * key)2414 is_multiindex(PyObject *key)
2415 {
2416 Py_ssize_t size, i;
2417
2418 if (!PyTuple_Check(key))
2419 return 0;
2420 size = PyTuple_GET_SIZE(key);
2421 for (i = 0; i < size; i++) {
2422 PyObject *x = PyTuple_GET_ITEM(key, i);
2423 if (!PyIndex_Check(x))
2424 return 0;
2425 }
2426 return 1;
2427 }
2428
2429 /* mv[obj] returns an object holding the data for one element if obj
2430 fully indexes the memoryview or another memoryview object if it
2431 does not.
2432
2433 0-d memoryview objects can be referenced using mv[...] or mv[()]
2434 but not with anything else. */
2435 static PyObject *
memory_subscript(PyMemoryViewObject * self,PyObject * key)2436 memory_subscript(PyMemoryViewObject *self, PyObject *key)
2437 {
2438 Py_buffer *view;
2439 view = &(self->view);
2440
2441 CHECK_RELEASED(self);
2442
2443 if (view->ndim == 0) {
2444 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2445 const char *fmt = adjust_fmt(view);
2446 if (fmt == NULL)
2447 return NULL;
2448 return unpack_single(view->buf, fmt);
2449 }
2450 else if (key == Py_Ellipsis) {
2451 Py_INCREF(self);
2452 return (PyObject *)self;
2453 }
2454 else {
2455 PyErr_SetString(PyExc_TypeError,
2456 "invalid indexing of 0-dim memory");
2457 return NULL;
2458 }
2459 }
2460
2461 if (PyIndex_Check(key)) {
2462 Py_ssize_t index;
2463 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2464 if (index == -1 && PyErr_Occurred())
2465 return NULL;
2466 return memory_item(self, index);
2467 }
2468 else if (PySlice_Check(key)) {
2469 PyMemoryViewObject *sliced;
2470
2471 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2472 if (sliced == NULL)
2473 return NULL;
2474
2475 if (init_slice(&sliced->view, key, 0) < 0) {
2476 Py_DECREF(sliced);
2477 return NULL;
2478 }
2479 init_len(&sliced->view);
2480 init_flags(sliced);
2481
2482 return (PyObject *)sliced;
2483 }
2484 else if (is_multiindex(key)) {
2485 return memory_item_multi(self, key);
2486 }
2487 else if (is_multislice(key)) {
2488 PyErr_SetString(PyExc_NotImplementedError,
2489 "multi-dimensional slicing is not implemented");
2490 return NULL;
2491 }
2492
2493 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2494 return NULL;
2495 }
2496
2497 static int
memory_ass_sub(PyMemoryViewObject * self,PyObject * key,PyObject * value)2498 memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2499 {
2500 Py_buffer *view = &(self->view);
2501 Py_buffer src;
2502 const char *fmt;
2503 char *ptr;
2504
2505 CHECK_RELEASED_INT(self);
2506
2507 fmt = adjust_fmt(view);
2508 if (fmt == NULL)
2509 return -1;
2510
2511 if (view->readonly) {
2512 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2513 return -1;
2514 }
2515 if (value == NULL) {
2516 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2517 return -1;
2518 }
2519 if (view->ndim == 0) {
2520 if (key == Py_Ellipsis ||
2521 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2522 ptr = (char *)view->buf;
2523 return pack_single(ptr, value, fmt);
2524 }
2525 else {
2526 PyErr_SetString(PyExc_TypeError,
2527 "invalid indexing of 0-dim memory");
2528 return -1;
2529 }
2530 }
2531
2532 if (PyIndex_Check(key)) {
2533 Py_ssize_t index;
2534 if (1 < view->ndim) {
2535 PyErr_SetString(PyExc_NotImplementedError,
2536 "sub-views are not implemented");
2537 return -1;
2538 }
2539 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2540 if (index == -1 && PyErr_Occurred())
2541 return -1;
2542 ptr = ptr_from_index(view, index);
2543 if (ptr == NULL)
2544 return -1;
2545 return pack_single(ptr, value, fmt);
2546 }
2547 /* one-dimensional: fast path */
2548 if (PySlice_Check(key) && view->ndim == 1) {
2549 Py_buffer dest; /* sliced view */
2550 Py_ssize_t arrays[3];
2551 int ret = -1;
2552
2553 /* rvalue must be an exporter */
2554 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2555 return ret;
2556
2557 dest = *view;
2558 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2559 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2560 if (view->suboffsets) {
2561 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2562 }
2563
2564 if (init_slice(&dest, key, 0) < 0)
2565 goto end_block;
2566 dest.len = dest.shape[0] * dest.itemsize;
2567
2568 ret = copy_single(&dest, &src);
2569
2570 end_block:
2571 PyBuffer_Release(&src);
2572 return ret;
2573 }
2574 if (is_multiindex(key)) {
2575 char *ptr;
2576 if (PyTuple_GET_SIZE(key) < view->ndim) {
2577 PyErr_SetString(PyExc_NotImplementedError,
2578 "sub-views are not implemented");
2579 return -1;
2580 }
2581 ptr = ptr_from_tuple(view, key);
2582 if (ptr == NULL)
2583 return -1;
2584 return pack_single(ptr, value, fmt);
2585 }
2586 if (PySlice_Check(key) || is_multislice(key)) {
2587 /* Call memory_subscript() to produce a sliced lvalue, then copy
2588 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2589 PyErr_SetString(PyExc_NotImplementedError,
2590 "memoryview slice assignments are currently restricted "
2591 "to ndim = 1");
2592 return -1;
2593 }
2594
2595 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2596 return -1;
2597 }
2598
2599 static Py_ssize_t
memory_length(PyMemoryViewObject * self)2600 memory_length(PyMemoryViewObject *self)
2601 {
2602 CHECK_RELEASED_INT(self);
2603 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2604 }
2605
2606 /* As mapping */
2607 static PyMappingMethods memory_as_mapping = {
2608 (lenfunc)memory_length, /* mp_length */
2609 (binaryfunc)memory_subscript, /* mp_subscript */
2610 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2611 };
2612
2613 /* As sequence */
2614 static PySequenceMethods memory_as_sequence = {
2615 (lenfunc)memory_length, /* sq_length */
2616 0, /* sq_concat */
2617 0, /* sq_repeat */
2618 (ssizeargfunc)memory_item, /* sq_item */
2619 };
2620
2621
2622 /**************************************************************************/
2623 /* Comparisons */
2624 /**************************************************************************/
2625
2626 #define MV_COMPARE_EX -1 /* exception */
2627 #define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2628
2629 /* Translate a StructError to "not equal". Preserve other exceptions. */
2630 static int
fix_struct_error_int(void)2631 fix_struct_error_int(void)
2632 {
2633 assert(PyErr_Occurred());
2634 /* XXX Cannot get at StructError directly? */
2635 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2636 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2637 return MV_COMPARE_EX;
2638 }
2639 /* StructError: invalid or unknown format -> not equal */
2640 PyErr_Clear();
2641 return 0;
2642 }
2643
2644 /* Unpack and compare single items of p and q using the struct module. */
2645 static int
struct_unpack_cmp(const char * p,const char * q,struct unpacker * unpack_p,struct unpacker * unpack_q)2646 struct_unpack_cmp(const char *p, const char *q,
2647 struct unpacker *unpack_p, struct unpacker *unpack_q)
2648 {
2649 PyObject *v, *w;
2650 int ret;
2651
2652 /* At this point any exception from the struct module should not be
2653 StructError, since both formats have been accepted already. */
2654 v = struct_unpack_single(p, unpack_p);
2655 if (v == NULL)
2656 return MV_COMPARE_EX;
2657
2658 w = struct_unpack_single(q, unpack_q);
2659 if (w == NULL) {
2660 Py_DECREF(v);
2661 return MV_COMPARE_EX;
2662 }
2663
2664 /* MV_COMPARE_EX == -1: exceptions are preserved */
2665 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2666 Py_DECREF(v);
2667 Py_DECREF(w);
2668
2669 return ret;
2670 }
2671
2672 /* Unpack and compare single items of p and q. If both p and q have the same
2673 single element native format, the comparison uses a fast path (gcc creates
2674 a jump table and converts memcpy into simple assignments on x86/x64).
2675
2676 Otherwise, the comparison is delegated to the struct module, which is
2677 30-60x slower. */
2678 #define CMP_SINGLE(p, q, type) \
2679 do { \
2680 type x; \
2681 type y; \
2682 memcpy((char *)&x, p, sizeof x); \
2683 memcpy((char *)&y, q, sizeof y); \
2684 equal = (x == y); \
2685 } while (0)
2686
2687 static inline int
unpack_cmp(const char * p,const char * q,char fmt,struct unpacker * unpack_p,struct unpacker * unpack_q)2688 unpack_cmp(const char *p, const char *q, char fmt,
2689 struct unpacker *unpack_p, struct unpacker *unpack_q)
2690 {
2691 int equal;
2692
2693 switch (fmt) {
2694
2695 /* signed integers and fast path for 'B' */
2696 case 'B': return *((const unsigned char *)p) == *((const unsigned char *)q);
2697 case 'b': return *((const signed char *)p) == *((const signed char *)q);
2698 case 'h': CMP_SINGLE(p, q, short); return equal;
2699 case 'i': CMP_SINGLE(p, q, int); return equal;
2700 case 'l': CMP_SINGLE(p, q, long); return equal;
2701
2702 /* boolean */
2703 case '?': CMP_SINGLE(p, q, _Bool); return equal;
2704
2705 /* unsigned integers */
2706 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2707 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2708 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2709
2710 /* native 64-bit */
2711 case 'q': CMP_SINGLE(p, q, long long); return equal;
2712 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
2713
2714 /* ssize_t and size_t */
2715 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2716 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2717
2718 /* floats */
2719 /* XXX DBL_EPSILON? */
2720 case 'f': CMP_SINGLE(p, q, float); return equal;
2721 case 'd': CMP_SINGLE(p, q, double); return equal;
2722
2723 /* bytes object */
2724 case 'c': return *p == *q;
2725
2726 /* pointer */
2727 case 'P': CMP_SINGLE(p, q, void *); return equal;
2728
2729 /* use the struct module */
2730 case '_':
2731 assert(unpack_p);
2732 assert(unpack_q);
2733 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
2734 }
2735
2736 /* NOT REACHED */
2737 PyErr_SetString(PyExc_RuntimeError,
2738 "memoryview: internal error in richcompare");
2739 return MV_COMPARE_EX;
2740 }
2741
2742 /* Base case for recursive array comparisons. Assumption: ndim == 1. */
2743 static int
cmp_base(const char * p,const char * q,const Py_ssize_t * shape,const Py_ssize_t * pstrides,const Py_ssize_t * psuboffsets,const Py_ssize_t * qstrides,const Py_ssize_t * qsuboffsets,char fmt,struct unpacker * unpack_p,struct unpacker * unpack_q)2744 cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2745 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2746 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
2747 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
2748 {
2749 Py_ssize_t i;
2750 int equal;
2751
2752 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
2753 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2754 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
2755 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
2756 if (equal <= 0)
2757 return equal;
2758 }
2759
2760 return 1;
2761 }
2762
2763 /* Recursively compare two multi-dimensional arrays that have the same
2764 logical structure. Assumption: ndim >= 1. */
2765 static int
cmp_rec(const char * p,const char * q,Py_ssize_t ndim,const Py_ssize_t * shape,const Py_ssize_t * pstrides,const Py_ssize_t * psuboffsets,const Py_ssize_t * qstrides,const Py_ssize_t * qsuboffsets,char fmt,struct unpacker * unpack_p,struct unpacker * unpack_q)2766 cmp_rec(const char *p, const char *q,
2767 Py_ssize_t ndim, const Py_ssize_t *shape,
2768 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2769 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
2770 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
2771 {
2772 Py_ssize_t i;
2773 int equal;
2774
2775 assert(ndim >= 1);
2776 assert(shape != NULL);
2777 assert(pstrides != NULL);
2778 assert(qstrides != NULL);
2779
2780 if (ndim == 1) {
2781 return cmp_base(p, q, shape,
2782 pstrides, psuboffsets,
2783 qstrides, qsuboffsets,
2784 fmt, unpack_p, unpack_q);
2785 }
2786
2787 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
2788 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2789 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
2790 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2791 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2792 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
2793 fmt, unpack_p, unpack_q);
2794 if (equal <= 0)
2795 return equal;
2796 }
2797
2798 return 1;
2799 }
2800
2801 static PyObject *
memory_richcompare(PyObject * v,PyObject * w,int op)2802 memory_richcompare(PyObject *v, PyObject *w, int op)
2803 {
2804 PyObject *res;
2805 Py_buffer wbuf, *vv;
2806 Py_buffer *ww = NULL;
2807 struct unpacker *unpack_v = NULL;
2808 struct unpacker *unpack_w = NULL;
2809 char vfmt, wfmt;
2810 int equal = MV_COMPARE_NOT_IMPL;
2811
2812 if (op != Py_EQ && op != Py_NE)
2813 goto result; /* Py_NotImplemented */
2814
2815 assert(PyMemoryView_Check(v));
2816 if (BASE_INACCESSIBLE(v)) {
2817 equal = (v == w);
2818 goto result;
2819 }
2820 vv = VIEW_ADDR(v);
2821
2822 if (PyMemoryView_Check(w)) {
2823 if (BASE_INACCESSIBLE(w)) {
2824 equal = (v == w);
2825 goto result;
2826 }
2827 ww = VIEW_ADDR(w);
2828 }
2829 else {
2830 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2831 PyErr_Clear();
2832 goto result; /* Py_NotImplemented */
2833 }
2834 ww = &wbuf;
2835 }
2836
2837 if (!equiv_shape(vv, ww)) {
2838 PyErr_Clear();
2839 equal = 0;
2840 goto result;
2841 }
2842
2843 /* Use fast unpacking for identical primitive C type formats. */
2844 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2845 vfmt = '_';
2846 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2847 wfmt = '_';
2848 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2849 /* Use struct module unpacking. NOTE: Even for equal format strings,
2850 memcmp() cannot be used for item comparison since it would give
2851 incorrect results in the case of NaNs or uninitialized padding
2852 bytes. */
2853 vfmt = '_';
2854 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2855 if (unpack_v == NULL) {
2856 equal = fix_struct_error_int();
2857 goto result;
2858 }
2859 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2860 if (unpack_w == NULL) {
2861 equal = fix_struct_error_int();
2862 goto result;
2863 }
2864 }
2865
2866 if (vv->ndim == 0) {
2867 equal = unpack_cmp(vv->buf, ww->buf,
2868 vfmt, unpack_v, unpack_w);
2869 }
2870 else if (vv->ndim == 1) {
2871 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2872 vv->strides, vv->suboffsets,
2873 ww->strides, ww->suboffsets,
2874 vfmt, unpack_v, unpack_w);
2875 }
2876 else {
2877 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2878 vv->strides, vv->suboffsets,
2879 ww->strides, ww->suboffsets,
2880 vfmt, unpack_v, unpack_w);
2881 }
2882
2883 result:
2884 if (equal < 0) {
2885 if (equal == MV_COMPARE_NOT_IMPL)
2886 res = Py_NotImplemented;
2887 else /* exception */
2888 res = NULL;
2889 }
2890 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2891 res = Py_True;
2892 else
2893 res = Py_False;
2894
2895 if (ww == &wbuf)
2896 PyBuffer_Release(ww);
2897
2898 unpacker_free(unpack_v);
2899 unpacker_free(unpack_w);
2900
2901 Py_XINCREF(res);
2902 return res;
2903 }
2904
2905 /**************************************************************************/
2906 /* Hash */
2907 /**************************************************************************/
2908
2909 static Py_hash_t
memory_hash(PyMemoryViewObject * self)2910 memory_hash(PyMemoryViewObject *self)
2911 {
2912 if (self->hash == -1) {
2913 Py_buffer *view = &self->view;
2914 char *mem = view->buf;
2915 Py_ssize_t ret;
2916 char fmt;
2917
2918 CHECK_RELEASED_INT(self);
2919
2920 if (!view->readonly) {
2921 PyErr_SetString(PyExc_ValueError,
2922 "cannot hash writable memoryview object");
2923 return -1;
2924 }
2925 ret = get_native_fmtchar(&fmt, view->format);
2926 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2927 PyErr_SetString(PyExc_ValueError,
2928 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2929 return -1;
2930 }
2931 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2932 /* Keep the original error message */
2933 return -1;
2934 }
2935
2936 if (!MV_C_CONTIGUOUS(self->flags)) {
2937 mem = PyMem_Malloc(view->len);
2938 if (mem == NULL) {
2939 PyErr_NoMemory();
2940 return -1;
2941 }
2942 if (buffer_to_contiguous(mem, view, 'C') < 0) {
2943 PyMem_Free(mem);
2944 return -1;
2945 }
2946 }
2947
2948 /* Can't fail */
2949 self->hash = _Py_HashBytes(mem, view->len);
2950
2951 if (mem != view->buf)
2952 PyMem_Free(mem);
2953 }
2954
2955 return self->hash;
2956 }
2957
2958
2959 /**************************************************************************/
2960 /* getters */
2961 /**************************************************************************/
2962
2963 static PyObject *
_IntTupleFromSsizet(int len,Py_ssize_t * vals)2964 _IntTupleFromSsizet(int len, Py_ssize_t *vals)
2965 {
2966 int i;
2967 PyObject *o;
2968 PyObject *intTuple;
2969
2970 if (vals == NULL)
2971 return PyTuple_New(0);
2972
2973 intTuple = PyTuple_New(len);
2974 if (!intTuple)
2975 return NULL;
2976 for (i=0; i<len; i++) {
2977 o = PyLong_FromSsize_t(vals[i]);
2978 if (!o) {
2979 Py_DECREF(intTuple);
2980 return NULL;
2981 }
2982 PyTuple_SET_ITEM(intTuple, i, o);
2983 }
2984 return intTuple;
2985 }
2986
2987 static PyObject *
memory_obj_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))2988 memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
2989 {
2990 Py_buffer *view = &self->view;
2991
2992 CHECK_RELEASED(self);
2993 if (view->obj == NULL) {
2994 Py_RETURN_NONE;
2995 }
2996 Py_INCREF(view->obj);
2997 return view->obj;
2998 }
2999
3000 static PyObject *
memory_nbytes_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3001 memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3002 {
3003 CHECK_RELEASED(self);
3004 return PyLong_FromSsize_t(self->view.len);
3005 }
3006
3007 static PyObject *
memory_format_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3008 memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3009 {
3010 CHECK_RELEASED(self);
3011 return PyUnicode_FromString(self->view.format);
3012 }
3013
3014 static PyObject *
memory_itemsize_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3015 memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3016 {
3017 CHECK_RELEASED(self);
3018 return PyLong_FromSsize_t(self->view.itemsize);
3019 }
3020
3021 static PyObject *
memory_shape_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3022 memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3023 {
3024 CHECK_RELEASED(self);
3025 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
3026 }
3027
3028 static PyObject *
memory_strides_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3029 memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3030 {
3031 CHECK_RELEASED(self);
3032 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
3033 }
3034
3035 static PyObject *
memory_suboffsets_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3036 memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3037 {
3038 CHECK_RELEASED(self);
3039 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
3040 }
3041
3042 static PyObject *
memory_readonly_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3043 memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3044 {
3045 CHECK_RELEASED(self);
3046 return PyBool_FromLong(self->view.readonly);
3047 }
3048
3049 static PyObject *
memory_ndim_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3050 memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3051 {
3052 CHECK_RELEASED(self);
3053 return PyLong_FromLong(self->view.ndim);
3054 }
3055
3056 static PyObject *
memory_c_contiguous(PyMemoryViewObject * self,PyObject * dummy)3057 memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3058 {
3059 CHECK_RELEASED(self);
3060 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3061 }
3062
3063 static PyObject *
memory_f_contiguous(PyMemoryViewObject * self,PyObject * dummy)3064 memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3065 {
3066 CHECK_RELEASED(self);
3067 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3068 }
3069
3070 static PyObject *
memory_contiguous(PyMemoryViewObject * self,PyObject * dummy)3071 memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3072 {
3073 CHECK_RELEASED(self);
3074 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3075 }
3076
3077 PyDoc_STRVAR(memory_obj_doc,
3078 "The underlying object of the memoryview.");
3079 PyDoc_STRVAR(memory_nbytes_doc,
3080 "The amount of space in bytes that the array would use in\n"
3081 " a contiguous representation.");
3082 PyDoc_STRVAR(memory_readonly_doc,
3083 "A bool indicating whether the memory is read only.");
3084 PyDoc_STRVAR(memory_itemsize_doc,
3085 "The size in bytes of each element of the memoryview.");
3086 PyDoc_STRVAR(memory_format_doc,
3087 "A string containing the format (in struct module style)\n"
3088 " for each element in the view.");
3089 PyDoc_STRVAR(memory_ndim_doc,
3090 "An integer indicating how many dimensions of a multi-dimensional\n"
3091 " array the memory represents.");
3092 PyDoc_STRVAR(memory_shape_doc,
3093 "A tuple of ndim integers giving the shape of the memory\n"
3094 " as an N-dimensional array.");
3095 PyDoc_STRVAR(memory_strides_doc,
3096 "A tuple of ndim integers giving the size in bytes to access\n"
3097 " each element for each dimension of the array.");
3098 PyDoc_STRVAR(memory_suboffsets_doc,
3099 "A tuple of integers used internally for PIL-style arrays.");
3100 PyDoc_STRVAR(memory_c_contiguous_doc,
3101 "A bool indicating whether the memory is C contiguous.");
3102 PyDoc_STRVAR(memory_f_contiguous_doc,
3103 "A bool indicating whether the memory is Fortran contiguous.");
3104 PyDoc_STRVAR(memory_contiguous_doc,
3105 "A bool indicating whether the memory is contiguous.");
3106
3107
3108 static PyGetSetDef memory_getsetlist[] = {
3109 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3110 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
3111 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3112 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3113 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3114 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3115 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3116 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3117 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
3118 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3119 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3120 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
3121 {NULL, NULL, NULL, NULL},
3122 };
3123
3124 PyDoc_STRVAR(memory_release_doc,
3125 "release($self, /)\n--\n\
3126 \n\
3127 Release the underlying buffer exposed by the memoryview object.");
3128 PyDoc_STRVAR(memory_tobytes_doc,
3129 "tobytes($self, /, order=None)\n--\n\
3130 \n\
3131 Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
3132 When order is 'C' or 'F', the data of the original array is converted to C or\n\
3133 Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
3134 memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
3135 views, the data is converted to C first. order=None is the same as order='C'.");
3136 PyDoc_STRVAR(memory_tolist_doc,
3137 "tolist($self, /)\n--\n\
3138 \n\
3139 Return the data in the buffer as a list of elements.");
3140 PyDoc_STRVAR(memory_cast_doc,
3141 "cast($self, /, format, *, shape)\n--\n\
3142 \n\
3143 Cast a memoryview to a new format or shape.");
3144 PyDoc_STRVAR(memory_toreadonly_doc,
3145 "toreadonly($self, /)\n--\n\
3146 \n\
3147 Return a readonly version of the memoryview.");
3148
3149 static PyMethodDef memory_methods[] = {
3150 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3151 {"tobytes", (PyCFunction)(void(*)(void))memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
3152 MEMORYVIEW_HEX_METHODDEF
3153 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
3154 {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
3155 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
3156 {"__enter__", memory_enter, METH_NOARGS, NULL},
3157 {"__exit__", memory_exit, METH_VARARGS, NULL},
3158 {NULL, NULL}
3159 };
3160
3161
3162 PyTypeObject PyMemoryView_Type = {
3163 PyVarObject_HEAD_INIT(&PyType_Type, 0)
3164 "memoryview", /* tp_name */
3165 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3166 sizeof(Py_ssize_t), /* tp_itemsize */
3167 (destructor)memory_dealloc, /* tp_dealloc */
3168 0, /* tp_vectorcall_offset */
3169 0, /* tp_getattr */
3170 0, /* tp_setattr */
3171 0, /* tp_as_async */
3172 (reprfunc)memory_repr, /* tp_repr */
3173 0, /* tp_as_number */
3174 &memory_as_sequence, /* tp_as_sequence */
3175 &memory_as_mapping, /* tp_as_mapping */
3176 (hashfunc)memory_hash, /* tp_hash */
3177 0, /* tp_call */
3178 0, /* tp_str */
3179 PyObject_GenericGetAttr, /* tp_getattro */
3180 0, /* tp_setattro */
3181 &memory_as_buffer, /* tp_as_buffer */
3182 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3183 memory_doc, /* tp_doc */
3184 (traverseproc)memory_traverse, /* tp_traverse */
3185 (inquiry)memory_clear, /* tp_clear */
3186 memory_richcompare, /* tp_richcompare */
3187 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
3188 0, /* tp_iter */
3189 0, /* tp_iternext */
3190 memory_methods, /* tp_methods */
3191 0, /* tp_members */
3192 memory_getsetlist, /* tp_getset */
3193 0, /* tp_base */
3194 0, /* tp_dict */
3195 0, /* tp_descr_get */
3196 0, /* tp_descr_set */
3197 0, /* tp_dictoffset */
3198 0, /* tp_init */
3199 0, /* tp_alloc */
3200 memory_new, /* tp_new */
3201 };
3202