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_abstract.h" // _PyIndex_Check()
15 #include "pycore_object.h"
16 #include "pystrhex.h"
17 #include <stddef.h>
18
19 /*[clinic input]
20 class memoryview "PyMemoryViewObject *" "&PyMemoryView_Type"
21 [clinic start generated code]*/
22 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2e49d2192835219]*/
23
24 #include "clinic/memoryobject.c.h"
25
26 /****************************************************************************/
27 /* ManagedBuffer Object */
28 /****************************************************************************/
29
30 /*
31 ManagedBuffer Object:
32 ---------------------
33
34 The purpose of this object is to facilitate the handling of chained
35 memoryviews that have the same underlying exporting object. PEP-3118
36 allows the underlying object to change while a view is exported. This
37 could lead to unexpected results when constructing a new memoryview
38 from an existing memoryview.
39
40 Rather than repeatedly redirecting buffer requests to the original base
41 object, all chained memoryviews use a single buffer snapshot. This
42 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
43
44 Ownership rules:
45 ----------------
46
47 The master buffer inside a managed buffer is filled in by the original
48 base object. shape, strides, suboffsets and format are read-only for
49 all consumers.
50
51 A memoryview's buffer is a private copy of the exporter's buffer. shape,
52 strides and suboffsets belong to the memoryview and are thus writable.
53
54 If a memoryview itself exports several buffers via memory_getbuf(), all
55 buffer copies share shape, strides and suboffsets. In this case, the
56 arrays are NOT writable.
57
58 Reference count assumptions:
59 ----------------------------
60
61 The 'obj' member of a Py_buffer must either be NULL or refer to the
62 exporting base object. In the Python codebase, all getbufferprocs
63 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
64
65 PyBuffer_Release() decrements view.obj (if non-NULL), so the
66 releasebufferprocs must NOT decrement view.obj.
67 */
68
69
70 #define CHECK_MBUF_RELEASED(mbuf) \
71 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
72 PyErr_SetString(PyExc_ValueError, \
73 "operation forbidden on released memoryview object"); \
74 return NULL; \
75 }
76
77
78 static inline _PyManagedBufferObject *
mbuf_alloc(void)79 mbuf_alloc(void)
80 {
81 _PyManagedBufferObject *mbuf;
82
83 mbuf = (_PyManagedBufferObject *)
84 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
85 if (mbuf == NULL)
86 return NULL;
87 mbuf->flags = 0;
88 mbuf->exports = 0;
89 mbuf->master.obj = NULL;
90 _PyObject_GC_TRACK(mbuf);
91
92 return mbuf;
93 }
94
95 static PyObject *
_PyManagedBuffer_FromObject(PyObject * base)96 _PyManagedBuffer_FromObject(PyObject *base)
97 {
98 _PyManagedBufferObject *mbuf;
99
100 mbuf = mbuf_alloc();
101 if (mbuf == NULL)
102 return NULL;
103
104 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
105 mbuf->master.obj = NULL;
106 Py_DECREF(mbuf);
107 return NULL;
108 }
109
110 return (PyObject *)mbuf;
111 }
112
113 static void
mbuf_release(_PyManagedBufferObject * self)114 mbuf_release(_PyManagedBufferObject *self)
115 {
116 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
117 return;
118
119 /* NOTE: at this point self->exports can still be > 0 if this function
120 is called from mbuf_clear() to break up a reference cycle. */
121 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
122
123 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
124 _PyObject_GC_UNTRACK(self);
125 PyBuffer_Release(&self->master);
126 }
127
128 static void
mbuf_dealloc(_PyManagedBufferObject * self)129 mbuf_dealloc(_PyManagedBufferObject *self)
130 {
131 assert(self->exports == 0);
132 mbuf_release(self);
133 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
134 PyMem_Free(self->master.format);
135 PyObject_GC_Del(self);
136 }
137
138 static int
mbuf_traverse(_PyManagedBufferObject * self,visitproc visit,void * arg)139 mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
140 {
141 Py_VISIT(self->master.obj);
142 return 0;
143 }
144
145 static int
mbuf_clear(_PyManagedBufferObject * self)146 mbuf_clear(_PyManagedBufferObject *self)
147 {
148 assert(self->exports >= 0);
149 mbuf_release(self);
150 return 0;
151 }
152
153 PyTypeObject _PyManagedBuffer_Type = {
154 PyVarObject_HEAD_INIT(&PyType_Type, 0)
155 "managedbuffer",
156 sizeof(_PyManagedBufferObject),
157 0,
158 (destructor)mbuf_dealloc, /* tp_dealloc */
159 0, /* tp_vectorcall_offset */
160 0, /* tp_getattr */
161 0, /* tp_setattr */
162 0, /* tp_as_async */
163 0, /* tp_repr */
164 0, /* tp_as_number */
165 0, /* tp_as_sequence */
166 0, /* tp_as_mapping */
167 0, /* tp_hash */
168 0, /* tp_call */
169 0, /* tp_str */
170 PyObject_GenericGetAttr, /* tp_getattro */
171 0, /* tp_setattro */
172 0, /* tp_as_buffer */
173 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
174 0, /* tp_doc */
175 (traverseproc)mbuf_traverse, /* tp_traverse */
176 (inquiry)mbuf_clear /* tp_clear */
177 };
178
179
180 /****************************************************************************/
181 /* MemoryView Object */
182 /****************************************************************************/
183
184 /* In the process of breaking reference cycles mbuf_release() can be
185 called before memory_release(). */
186 #define BASE_INACCESSIBLE(mv) \
187 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
188 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
189
190 #define CHECK_RELEASED(mv) \
191 if (BASE_INACCESSIBLE(mv)) { \
192 PyErr_SetString(PyExc_ValueError, \
193 "operation forbidden on released memoryview object"); \
194 return NULL; \
195 }
196
197 #define CHECK_RELEASED_INT(mv) \
198 if (BASE_INACCESSIBLE(mv)) { \
199 PyErr_SetString(PyExc_ValueError, \
200 "operation forbidden on released memoryview object"); \
201 return -1; \
202 }
203
204 #define CHECK_LIST_OR_TUPLE(v) \
205 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
206 PyErr_SetString(PyExc_TypeError, \
207 #v " must be a list or a tuple"); \
208 return NULL; \
209 }
210
211 #define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
212
213 /* Check for the presence of suboffsets in the first dimension. */
214 #define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
215 /* Adjust ptr if suboffsets are present. */
216 #define ADJUST_PTR(ptr, suboffsets, dim) \
217 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
218
219 /* Memoryview buffer properties */
220 #define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
221 #define MV_F_CONTIGUOUS(flags) \
222 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
223 #define MV_ANY_CONTIGUOUS(flags) \
224 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
225
226 /* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
227 #define MV_CONTIGUOUS_NDIM1(view) \
228 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
229
230 /* getbuffer() requests */
231 #define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
232 #define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
233 #define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
234 #define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
235 #define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
236 #define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
237 #define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
238 #define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
239
240
241 PyDoc_STRVAR(memory_doc,
242 "memoryview(object)\n--\n\
243 \n\
244 Create a new memoryview object which references the given object.");
245
246
247 /**************************************************************************/
248 /* Copy memoryview buffers */
249 /**************************************************************************/
250
251 /* The functions in this section take a source and a destination buffer
252 with the same logical structure: format, itemsize, ndim and shape
253 are identical, with ndim > 0.
254
255 NOTE: All buffers are assumed to have PyBUF_FULL information, which
256 is the case for memoryviews! */
257
258
259 /* Assumptions: ndim >= 1. The macro tests for a corner case that should
260 perhaps be explicitly forbidden in the PEP. */
261 #define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
262 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
263
264 static inline int
last_dim_is_contiguous(const Py_buffer * dest,const Py_buffer * src)265 last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
266 {
267 assert(dest->ndim > 0 && src->ndim > 0);
268 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
269 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
270 dest->strides[dest->ndim-1] == dest->itemsize &&
271 src->strides[src->ndim-1] == src->itemsize);
272 }
273
274 /* This is not a general function for determining format equivalence.
275 It is used in copy_single() and copy_buffer() to weed out non-matching
276 formats. Skipping the '@' character is specifically used in slice
277 assignments, where the lvalue is already known to have a single character
278 format. This is a performance hack that could be rewritten (if properly
279 benchmarked). */
280 static inline int
equiv_format(const Py_buffer * dest,const Py_buffer * src)281 equiv_format(const Py_buffer *dest, const Py_buffer *src)
282 {
283 const char *dfmt, *sfmt;
284
285 assert(dest->format && src->format);
286 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
287 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
288
289 if (strcmp(dfmt, sfmt) != 0 ||
290 dest->itemsize != src->itemsize) {
291 return 0;
292 }
293
294 return 1;
295 }
296
297 /* Two shapes are equivalent if they are either equal or identical up
298 to a zero element at the same position. For example, in NumPy arrays
299 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
300 static inline int
equiv_shape(const Py_buffer * dest,const Py_buffer * src)301 equiv_shape(const Py_buffer *dest, const Py_buffer *src)
302 {
303 int i;
304
305 if (dest->ndim != src->ndim)
306 return 0;
307
308 for (i = 0; i < dest->ndim; i++) {
309 if (dest->shape[i] != src->shape[i])
310 return 0;
311 if (dest->shape[i] == 0)
312 break;
313 }
314
315 return 1;
316 }
317
318 /* Check that the logical structure of the destination and source buffers
319 is identical. */
320 static int
equiv_structure(const Py_buffer * dest,const Py_buffer * src)321 equiv_structure(const Py_buffer *dest, const Py_buffer *src)
322 {
323 if (!equiv_format(dest, src) ||
324 !equiv_shape(dest, src)) {
325 PyErr_SetString(PyExc_ValueError,
326 "memoryview assignment: lvalue and rvalue have different "
327 "structures");
328 return 0;
329 }
330
331 return 1;
332 }
333
334 /* Base case for recursive multi-dimensional copying. Contiguous arrays are
335 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
336 sizeof(mem) == shape[0] * itemsize. */
337 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)338 copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
339 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
340 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
341 char *mem)
342 {
343 if (mem == NULL) { /* contiguous */
344 Py_ssize_t size = shape[0] * itemsize;
345 if (dptr + size < sptr || sptr + size < dptr)
346 memcpy(dptr, sptr, size); /* no overlapping */
347 else
348 memmove(dptr, sptr, size);
349 }
350 else {
351 char *p;
352 Py_ssize_t i;
353 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
354 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
355 memcpy(p, xsptr, itemsize);
356 }
357 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
358 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
359 memcpy(xdptr, p, itemsize);
360 }
361 }
362
363 }
364
365 /* Recursively copy a source buffer to a destination buffer. The two buffers
366 have the same ndim, shape and itemsize. */
367 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)368 copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
369 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
370 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
371 char *mem)
372 {
373 Py_ssize_t i;
374
375 assert(ndim >= 1);
376
377 if (ndim == 1) {
378 copy_base(shape, itemsize,
379 dptr, dstrides, dsuboffsets,
380 sptr, sstrides, ssuboffsets,
381 mem);
382 return;
383 }
384
385 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
386 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
387 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
388
389 copy_rec(shape+1, ndim-1, itemsize,
390 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
391 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
392 mem);
393 }
394 }
395
396 /* Faster copying of one-dimensional arrays. */
397 static int
copy_single(Py_buffer * dest,Py_buffer * src)398 copy_single(Py_buffer *dest, Py_buffer *src)
399 {
400 char *mem = NULL;
401
402 assert(dest->ndim == 1);
403
404 if (!equiv_structure(dest, src))
405 return -1;
406
407 if (!last_dim_is_contiguous(dest, src)) {
408 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
409 if (mem == NULL) {
410 PyErr_NoMemory();
411 return -1;
412 }
413 }
414
415 copy_base(dest->shape, dest->itemsize,
416 dest->buf, dest->strides, dest->suboffsets,
417 src->buf, src->strides, src->suboffsets,
418 mem);
419
420 if (mem)
421 PyMem_Free(mem);
422
423 return 0;
424 }
425
426 /* Recursively copy src to dest. Both buffers must have the same basic
427 structure. Copying is atomic, the function never fails with a partial
428 copy. */
429 static int
copy_buffer(Py_buffer * dest,Py_buffer * src)430 copy_buffer(Py_buffer *dest, Py_buffer *src)
431 {
432 char *mem = NULL;
433
434 assert(dest->ndim > 0);
435
436 if (!equiv_structure(dest, src))
437 return -1;
438
439 if (!last_dim_is_contiguous(dest, src)) {
440 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
441 if (mem == NULL) {
442 PyErr_NoMemory();
443 return -1;
444 }
445 }
446
447 copy_rec(dest->shape, dest->ndim, dest->itemsize,
448 dest->buf, dest->strides, dest->suboffsets,
449 src->buf, src->strides, src->suboffsets,
450 mem);
451
452 if (mem)
453 PyMem_Free(mem);
454
455 return 0;
456 }
457
458 /* Initialize strides for a C-contiguous array. */
459 static inline void
init_strides_from_shape(Py_buffer * view)460 init_strides_from_shape(Py_buffer *view)
461 {
462 Py_ssize_t i;
463
464 assert(view->ndim > 0);
465
466 view->strides[view->ndim-1] = view->itemsize;
467 for (i = view->ndim-2; i >= 0; i--)
468 view->strides[i] = view->strides[i+1] * view->shape[i+1];
469 }
470
471 /* Initialize strides for a Fortran-contiguous array. */
472 static inline void
init_fortran_strides_from_shape(Py_buffer * view)473 init_fortran_strides_from_shape(Py_buffer *view)
474 {
475 Py_ssize_t i;
476
477 assert(view->ndim > 0);
478
479 view->strides[0] = view->itemsize;
480 for (i = 1; i < view->ndim; i++)
481 view->strides[i] = view->strides[i-1] * view->shape[i-1];
482 }
483
484 /* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
485 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
486 len(mem) == src->len. */
487 static int
buffer_to_contiguous(char * mem,Py_buffer * src,char order)488 buffer_to_contiguous(char *mem, Py_buffer *src, char order)
489 {
490 Py_buffer dest;
491 Py_ssize_t *strides;
492 int ret;
493
494 assert(src->ndim >= 1);
495 assert(src->shape != NULL);
496 assert(src->strides != NULL);
497
498 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
499 if (strides == NULL) {
500 PyErr_NoMemory();
501 return -1;
502 }
503
504 /* initialize dest */
505 dest = *src;
506 dest.buf = mem;
507 /* shape is constant and shared: the logical representation of the
508 array is unaltered. */
509
510 /* The physical representation determined by strides (and possibly
511 suboffsets) may change. */
512 dest.strides = strides;
513 if (order == 'C' || order == 'A') {
514 init_strides_from_shape(&dest);
515 }
516 else {
517 init_fortran_strides_from_shape(&dest);
518 }
519
520 dest.suboffsets = NULL;
521
522 ret = copy_buffer(&dest, src);
523
524 PyMem_Free(strides);
525 return ret;
526 }
527
528
529 /****************************************************************************/
530 /* Constructors */
531 /****************************************************************************/
532
533 /* Initialize values that are shared with the managed buffer. */
534 static inline void
init_shared_values(Py_buffer * dest,const Py_buffer * src)535 init_shared_values(Py_buffer *dest, const Py_buffer *src)
536 {
537 dest->obj = src->obj;
538 dest->buf = src->buf;
539 dest->len = src->len;
540 dest->itemsize = src->itemsize;
541 dest->readonly = src->readonly;
542 dest->format = src->format ? src->format : "B";
543 dest->internal = src->internal;
544 }
545
546 /* Copy shape and strides. Reconstruct missing values. */
547 static void
init_shape_strides(Py_buffer * dest,const Py_buffer * src)548 init_shape_strides(Py_buffer *dest, const Py_buffer *src)
549 {
550 Py_ssize_t i;
551
552 if (src->ndim == 0) {
553 dest->shape = NULL;
554 dest->strides = NULL;
555 return;
556 }
557 if (src->ndim == 1) {
558 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
559 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
560 return;
561 }
562
563 for (i = 0; i < src->ndim; i++)
564 dest->shape[i] = src->shape[i];
565 if (src->strides) {
566 for (i = 0; i < src->ndim; i++)
567 dest->strides[i] = src->strides[i];
568 }
569 else {
570 init_strides_from_shape(dest);
571 }
572 }
573
574 static inline void
init_suboffsets(Py_buffer * dest,const Py_buffer * src)575 init_suboffsets(Py_buffer *dest, const Py_buffer *src)
576 {
577 Py_ssize_t i;
578
579 if (src->suboffsets == NULL) {
580 dest->suboffsets = NULL;
581 return;
582 }
583 for (i = 0; i < src->ndim; i++)
584 dest->suboffsets[i] = src->suboffsets[i];
585 }
586
587 /* len = product(shape) * itemsize */
588 static inline void
init_len(Py_buffer * view)589 init_len(Py_buffer *view)
590 {
591 Py_ssize_t i, len;
592
593 len = 1;
594 for (i = 0; i < view->ndim; i++)
595 len *= view->shape[i];
596 len *= view->itemsize;
597
598 view->len = len;
599 }
600
601 /* Initialize memoryview buffer properties. */
602 static void
init_flags(PyMemoryViewObject * mv)603 init_flags(PyMemoryViewObject *mv)
604 {
605 const Py_buffer *view = &mv->view;
606 int flags = 0;
607
608 switch (view->ndim) {
609 case 0:
610 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
611 _Py_MEMORYVIEW_FORTRAN);
612 break;
613 case 1:
614 if (MV_CONTIGUOUS_NDIM1(view))
615 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
616 break;
617 default:
618 if (PyBuffer_IsContiguous(view, 'C'))
619 flags |= _Py_MEMORYVIEW_C;
620 if (PyBuffer_IsContiguous(view, 'F'))
621 flags |= _Py_MEMORYVIEW_FORTRAN;
622 break;
623 }
624
625 if (view->suboffsets) {
626 flags |= _Py_MEMORYVIEW_PIL;
627 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
628 }
629
630 mv->flags = flags;
631 }
632
633 /* Allocate a new memoryview and perform basic initialization. New memoryviews
634 are exclusively created through the mbuf_add functions. */
635 static inline PyMemoryViewObject *
memory_alloc(int ndim)636 memory_alloc(int ndim)
637 {
638 PyMemoryViewObject *mv;
639
640 mv = (PyMemoryViewObject *)
641 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
642 if (mv == NULL)
643 return NULL;
644
645 mv->mbuf = NULL;
646 mv->hash = -1;
647 mv->flags = 0;
648 mv->exports = 0;
649 mv->view.ndim = ndim;
650 mv->view.shape = mv->ob_array;
651 mv->view.strides = mv->ob_array + ndim;
652 mv->view.suboffsets = mv->ob_array + 2 * ndim;
653 mv->weakreflist = NULL;
654
655 _PyObject_GC_TRACK(mv);
656 return mv;
657 }
658
659 /*
660 Return a new memoryview that is registered with mbuf. If src is NULL,
661 use mbuf->master as the underlying buffer. Otherwise, use src.
662
663 The new memoryview has full buffer information: shape and strides
664 are always present, suboffsets as needed. Arrays are copied to
665 the memoryview's ob_array field.
666 */
667 static PyObject *
mbuf_add_view(_PyManagedBufferObject * mbuf,const Py_buffer * src)668 mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
669 {
670 PyMemoryViewObject *mv;
671 Py_buffer *dest;
672
673 if (src == NULL)
674 src = &mbuf->master;
675
676 if (src->ndim > PyBUF_MAX_NDIM) {
677 PyErr_SetString(PyExc_ValueError,
678 "memoryview: number of dimensions must not exceed "
679 Py_STRINGIFY(PyBUF_MAX_NDIM));
680 return NULL;
681 }
682
683 mv = memory_alloc(src->ndim);
684 if (mv == NULL)
685 return NULL;
686
687 dest = &mv->view;
688 init_shared_values(dest, src);
689 init_shape_strides(dest, src);
690 init_suboffsets(dest, src);
691 init_flags(mv);
692
693 mv->mbuf = mbuf;
694 Py_INCREF(mbuf);
695 mbuf->exports++;
696
697 return (PyObject *)mv;
698 }
699
700 /* Register an incomplete view: shape, strides, suboffsets and flags still
701 need to be initialized. Use 'ndim' instead of src->ndim to determine the
702 size of the memoryview's ob_array.
703
704 Assumption: ndim <= PyBUF_MAX_NDIM. */
705 static PyObject *
mbuf_add_incomplete_view(_PyManagedBufferObject * mbuf,const Py_buffer * src,int ndim)706 mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
707 int ndim)
708 {
709 PyMemoryViewObject *mv;
710 Py_buffer *dest;
711
712 if (src == NULL)
713 src = &mbuf->master;
714
715 assert(ndim <= PyBUF_MAX_NDIM);
716
717 mv = memory_alloc(ndim);
718 if (mv == NULL)
719 return NULL;
720
721 dest = &mv->view;
722 init_shared_values(dest, src);
723
724 mv->mbuf = mbuf;
725 Py_INCREF(mbuf);
726 mbuf->exports++;
727
728 return (PyObject *)mv;
729 }
730
731 /* Expose a raw memory area as a view of contiguous bytes. flags can be
732 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
733 The memoryview has complete buffer information. */
734 PyObject *
PyMemoryView_FromMemory(char * mem,Py_ssize_t size,int flags)735 PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
736 {
737 _PyManagedBufferObject *mbuf;
738 PyObject *mv;
739 int readonly;
740
741 assert(mem != NULL);
742 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
743
744 mbuf = mbuf_alloc();
745 if (mbuf == NULL)
746 return NULL;
747
748 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
749 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
750 PyBUF_FULL_RO);
751
752 mv = mbuf_add_view(mbuf, NULL);
753 Py_DECREF(mbuf);
754
755 return mv;
756 }
757
758 /* Create a memoryview from a given Py_buffer. For simple byte views,
759 PyMemoryView_FromMemory() should be used instead.
760 This function is the only entry point that can create a master buffer
761 without full information. Because of this fact init_shape_strides()
762 must be able to reconstruct missing values. */
763 PyObject *
PyMemoryView_FromBuffer(Py_buffer * info)764 PyMemoryView_FromBuffer(Py_buffer *info)
765 {
766 _PyManagedBufferObject *mbuf;
767 PyObject *mv;
768
769 if (info->buf == NULL) {
770 PyErr_SetString(PyExc_ValueError,
771 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
772 return NULL;
773 }
774
775 mbuf = mbuf_alloc();
776 if (mbuf == NULL)
777 return NULL;
778
779 /* info->obj is either NULL or a borrowed reference. This reference
780 should not be decremented in PyBuffer_Release(). */
781 mbuf->master = *info;
782 mbuf->master.obj = NULL;
783
784 mv = mbuf_add_view(mbuf, NULL);
785 Py_DECREF(mbuf);
786
787 return mv;
788 }
789
790 /* Create a memoryview from an object that implements the buffer protocol.
791 If the object is a memoryview, the new memoryview must be registered
792 with the same managed buffer. Otherwise, a new managed buffer is created. */
793 PyObject *
PyMemoryView_FromObject(PyObject * v)794 PyMemoryView_FromObject(PyObject *v)
795 {
796 _PyManagedBufferObject *mbuf;
797
798 if (PyMemoryView_Check(v)) {
799 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
800 CHECK_RELEASED(mv);
801 return mbuf_add_view(mv->mbuf, &mv->view);
802 }
803 else if (PyObject_CheckBuffer(v)) {
804 PyObject *ret;
805 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
806 if (mbuf == NULL)
807 return NULL;
808 ret = mbuf_add_view(mbuf, NULL);
809 Py_DECREF(mbuf);
810 return ret;
811 }
812
813 PyErr_Format(PyExc_TypeError,
814 "memoryview: a bytes-like object is required, not '%.200s'",
815 Py_TYPE(v)->tp_name);
816 return NULL;
817 }
818
819 /* Copy the format string from a base object that might vanish. */
820 static int
mbuf_copy_format(_PyManagedBufferObject * mbuf,const char * fmt)821 mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
822 {
823 if (fmt != NULL) {
824 char *cp = PyMem_Malloc(strlen(fmt)+1);
825 if (cp == NULL) {
826 PyErr_NoMemory();
827 return -1;
828 }
829 mbuf->master.format = strcpy(cp, fmt);
830 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
831 }
832
833 return 0;
834 }
835
836 /*
837 Return a memoryview that is based on a contiguous copy of src.
838 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
839
840 Ownership rules:
841 1) As usual, the returned memoryview has a private copy
842 of src->shape, src->strides and src->suboffsets.
843 2) src->format is copied to the master buffer and released
844 in mbuf_dealloc(). The releasebufferproc of the bytes
845 object is NULL, so it does not matter that mbuf_release()
846 passes the altered format pointer to PyBuffer_Release().
847 */
848 static PyObject *
memory_from_contiguous_copy(Py_buffer * src,char order)849 memory_from_contiguous_copy(Py_buffer *src, char order)
850 {
851 _PyManagedBufferObject *mbuf;
852 PyMemoryViewObject *mv;
853 PyObject *bytes;
854 Py_buffer *dest;
855 int i;
856
857 assert(src->ndim > 0);
858 assert(src->shape != NULL);
859
860 bytes = PyBytes_FromStringAndSize(NULL, src->len);
861 if (bytes == NULL)
862 return NULL;
863
864 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
865 Py_DECREF(bytes);
866 if (mbuf == NULL)
867 return NULL;
868
869 if (mbuf_copy_format(mbuf, src->format) < 0) {
870 Py_DECREF(mbuf);
871 return NULL;
872 }
873
874 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
875 Py_DECREF(mbuf);
876 if (mv == NULL)
877 return NULL;
878
879 dest = &mv->view;
880
881 /* shared values are initialized correctly except for itemsize */
882 dest->itemsize = src->itemsize;
883
884 /* shape and strides */
885 for (i = 0; i < src->ndim; i++) {
886 dest->shape[i] = src->shape[i];
887 }
888 if (order == 'C' || order == 'A') {
889 init_strides_from_shape(dest);
890 }
891 else {
892 init_fortran_strides_from_shape(dest);
893 }
894 /* suboffsets */
895 dest->suboffsets = NULL;
896
897 /* flags */
898 init_flags(mv);
899
900 if (copy_buffer(dest, src) < 0) {
901 Py_DECREF(mv);
902 return NULL;
903 }
904
905 return (PyObject *)mv;
906 }
907
908 /*
909 Return a new memoryview object based on a contiguous exporter with
910 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
911 The logical structure of the input and output buffers is the same
912 (i.e. tolist(input) == tolist(output)), but the physical layout in
913 memory can be explicitly chosen.
914
915 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
916 otherwise it may be writable or read-only.
917
918 If the exporter is already contiguous with the desired target order,
919 the memoryview will be directly based on the exporter.
920
921 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
922 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
923 'F'ortran order otherwise.
924 */
925 PyObject *
PyMemoryView_GetContiguous(PyObject * obj,int buffertype,char order)926 PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
927 {
928 PyMemoryViewObject *mv;
929 PyObject *ret;
930 Py_buffer *view;
931
932 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
933 assert(order == 'C' || order == 'F' || order == 'A');
934
935 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
936 if (mv == NULL)
937 return NULL;
938
939 view = &mv->view;
940 if (buffertype == PyBUF_WRITE && view->readonly) {
941 PyErr_SetString(PyExc_BufferError,
942 "underlying buffer is not writable");
943 Py_DECREF(mv);
944 return NULL;
945 }
946
947 if (PyBuffer_IsContiguous(view, order))
948 return (PyObject *)mv;
949
950 if (buffertype == PyBUF_WRITE) {
951 PyErr_SetString(PyExc_BufferError,
952 "writable contiguous buffer requested "
953 "for a non-contiguous object.");
954 Py_DECREF(mv);
955 return NULL;
956 }
957
958 ret = memory_from_contiguous_copy(view, order);
959 Py_DECREF(mv);
960 return ret;
961 }
962
963
964 static PyObject *
memory_new(PyTypeObject * subtype,PyObject * args,PyObject * kwds)965 memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
966 {
967 PyObject *obj;
968 static char *kwlist[] = {"object", NULL};
969
970 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
971 &obj)) {
972 return NULL;
973 }
974
975 return PyMemoryView_FromObject(obj);
976 }
977
978
979 /****************************************************************************/
980 /* Previously in abstract.c */
981 /****************************************************************************/
982
983 typedef struct {
984 Py_buffer view;
985 Py_ssize_t array[1];
986 } Py_buffer_full;
987
988 int
PyBuffer_ToContiguous(void * buf,Py_buffer * src,Py_ssize_t len,char order)989 PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
990 {
991 Py_buffer_full *fb = NULL;
992 int ret;
993
994 assert(order == 'C' || order == 'F' || order == 'A');
995
996 if (len != src->len) {
997 PyErr_SetString(PyExc_ValueError,
998 "PyBuffer_ToContiguous: len != view->len");
999 return -1;
1000 }
1001
1002 if (PyBuffer_IsContiguous(src, order)) {
1003 memcpy((char *)buf, src->buf, len);
1004 return 0;
1005 }
1006
1007 /* buffer_to_contiguous() assumes PyBUF_FULL */
1008 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
1009 if (fb == NULL) {
1010 PyErr_NoMemory();
1011 return -1;
1012 }
1013 fb->view.ndim = src->ndim;
1014 fb->view.shape = fb->array;
1015 fb->view.strides = fb->array + src->ndim;
1016 fb->view.suboffsets = fb->array + 2 * src->ndim;
1017
1018 init_shared_values(&fb->view, src);
1019 init_shape_strides(&fb->view, src);
1020 init_suboffsets(&fb->view, src);
1021
1022 src = &fb->view;
1023
1024 ret = buffer_to_contiguous(buf, src, order);
1025 PyMem_Free(fb);
1026 return ret;
1027 }
1028
1029
1030 /****************************************************************************/
1031 /* Release/GC management */
1032 /****************************************************************************/
1033
1034 /* Inform the managed buffer that this particular memoryview will not access
1035 the underlying buffer again. If no other memoryviews are registered with
1036 the managed buffer, the underlying buffer is released instantly and
1037 marked as inaccessible for both the memoryview and the managed buffer.
1038
1039 This function fails if the memoryview itself has exported buffers. */
1040 static int
_memory_release(PyMemoryViewObject * self)1041 _memory_release(PyMemoryViewObject *self)
1042 {
1043 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1044 return 0;
1045
1046 if (self->exports == 0) {
1047 self->flags |= _Py_MEMORYVIEW_RELEASED;
1048 assert(self->mbuf->exports > 0);
1049 if (--self->mbuf->exports == 0)
1050 mbuf_release(self->mbuf);
1051 return 0;
1052 }
1053 if (self->exports > 0) {
1054 PyErr_Format(PyExc_BufferError,
1055 "memoryview has %zd exported buffer%s", self->exports,
1056 self->exports==1 ? "" : "s");
1057 return -1;
1058 }
1059
1060 PyErr_SetString(PyExc_SystemError,
1061 "_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_CallOneArg(Struct, format);
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_CallOneArg(x->unpack_from, x->mview);
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 }
2427 return 1;
2428 }
2429
2430 /* mv[obj] returns an object holding the data for one element if obj
2431 fully indexes the memoryview or another memoryview object if it
2432 does not.
2433
2434 0-d memoryview objects can be referenced using mv[...] or mv[()]
2435 but not with anything else. */
2436 static PyObject *
memory_subscript(PyMemoryViewObject * self,PyObject * key)2437 memory_subscript(PyMemoryViewObject *self, PyObject *key)
2438 {
2439 Py_buffer *view;
2440 view = &(self->view);
2441
2442 CHECK_RELEASED(self);
2443
2444 if (view->ndim == 0) {
2445 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2446 const char *fmt = adjust_fmt(view);
2447 if (fmt == NULL)
2448 return NULL;
2449 return unpack_single(view->buf, fmt);
2450 }
2451 else if (key == Py_Ellipsis) {
2452 Py_INCREF(self);
2453 return (PyObject *)self;
2454 }
2455 else {
2456 PyErr_SetString(PyExc_TypeError,
2457 "invalid indexing of 0-dim memory");
2458 return NULL;
2459 }
2460 }
2461
2462 if (_PyIndex_Check(key)) {
2463 Py_ssize_t index;
2464 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2465 if (index == -1 && PyErr_Occurred())
2466 return NULL;
2467 return memory_item(self, index);
2468 }
2469 else if (PySlice_Check(key)) {
2470 PyMemoryViewObject *sliced;
2471
2472 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2473 if (sliced == NULL)
2474 return NULL;
2475
2476 if (init_slice(&sliced->view, key, 0) < 0) {
2477 Py_DECREF(sliced);
2478 return NULL;
2479 }
2480 init_len(&sliced->view);
2481 init_flags(sliced);
2482
2483 return (PyObject *)sliced;
2484 }
2485 else if (is_multiindex(key)) {
2486 return memory_item_multi(self, key);
2487 }
2488 else if (is_multislice(key)) {
2489 PyErr_SetString(PyExc_NotImplementedError,
2490 "multi-dimensional slicing is not implemented");
2491 return NULL;
2492 }
2493
2494 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2495 return NULL;
2496 }
2497
2498 static int
memory_ass_sub(PyMemoryViewObject * self,PyObject * key,PyObject * value)2499 memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2500 {
2501 Py_buffer *view = &(self->view);
2502 Py_buffer src;
2503 const char *fmt;
2504 char *ptr;
2505
2506 CHECK_RELEASED_INT(self);
2507
2508 fmt = adjust_fmt(view);
2509 if (fmt == NULL)
2510 return -1;
2511
2512 if (view->readonly) {
2513 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2514 return -1;
2515 }
2516 if (value == NULL) {
2517 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2518 return -1;
2519 }
2520 if (view->ndim == 0) {
2521 if (key == Py_Ellipsis ||
2522 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2523 ptr = (char *)view->buf;
2524 return pack_single(ptr, value, fmt);
2525 }
2526 else {
2527 PyErr_SetString(PyExc_TypeError,
2528 "invalid indexing of 0-dim memory");
2529 return -1;
2530 }
2531 }
2532
2533 if (_PyIndex_Check(key)) {
2534 Py_ssize_t index;
2535 if (1 < view->ndim) {
2536 PyErr_SetString(PyExc_NotImplementedError,
2537 "sub-views are not implemented");
2538 return -1;
2539 }
2540 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2541 if (index == -1 && PyErr_Occurred())
2542 return -1;
2543 ptr = ptr_from_index(view, index);
2544 if (ptr == NULL)
2545 return -1;
2546 return pack_single(ptr, value, fmt);
2547 }
2548 /* one-dimensional: fast path */
2549 if (PySlice_Check(key) && view->ndim == 1) {
2550 Py_buffer dest; /* sliced view */
2551 Py_ssize_t arrays[3];
2552 int ret = -1;
2553
2554 /* rvalue must be an exporter */
2555 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2556 return ret;
2557
2558 dest = *view;
2559 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2560 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2561 if (view->suboffsets) {
2562 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2563 }
2564
2565 if (init_slice(&dest, key, 0) < 0)
2566 goto end_block;
2567 dest.len = dest.shape[0] * dest.itemsize;
2568
2569 ret = copy_single(&dest, &src);
2570
2571 end_block:
2572 PyBuffer_Release(&src);
2573 return ret;
2574 }
2575 if (is_multiindex(key)) {
2576 char *ptr;
2577 if (PyTuple_GET_SIZE(key) < view->ndim) {
2578 PyErr_SetString(PyExc_NotImplementedError,
2579 "sub-views are not implemented");
2580 return -1;
2581 }
2582 ptr = ptr_from_tuple(view, key);
2583 if (ptr == NULL)
2584 return -1;
2585 return pack_single(ptr, value, fmt);
2586 }
2587 if (PySlice_Check(key) || is_multislice(key)) {
2588 /* Call memory_subscript() to produce a sliced lvalue, then copy
2589 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2590 PyErr_SetString(PyExc_NotImplementedError,
2591 "memoryview slice assignments are currently restricted "
2592 "to ndim = 1");
2593 return -1;
2594 }
2595
2596 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2597 return -1;
2598 }
2599
2600 static Py_ssize_t
memory_length(PyMemoryViewObject * self)2601 memory_length(PyMemoryViewObject *self)
2602 {
2603 CHECK_RELEASED_INT(self);
2604 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2605 }
2606
2607 /* As mapping */
2608 static PyMappingMethods memory_as_mapping = {
2609 (lenfunc)memory_length, /* mp_length */
2610 (binaryfunc)memory_subscript, /* mp_subscript */
2611 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2612 };
2613
2614 /* As sequence */
2615 static PySequenceMethods memory_as_sequence = {
2616 (lenfunc)memory_length, /* sq_length */
2617 0, /* sq_concat */
2618 0, /* sq_repeat */
2619 (ssizeargfunc)memory_item, /* sq_item */
2620 };
2621
2622
2623 /**************************************************************************/
2624 /* Comparisons */
2625 /**************************************************************************/
2626
2627 #define MV_COMPARE_EX -1 /* exception */
2628 #define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2629
2630 /* Translate a StructError to "not equal". Preserve other exceptions. */
2631 static int
fix_struct_error_int(void)2632 fix_struct_error_int(void)
2633 {
2634 assert(PyErr_Occurred());
2635 /* XXX Cannot get at StructError directly? */
2636 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2637 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2638 return MV_COMPARE_EX;
2639 }
2640 /* StructError: invalid or unknown format -> not equal */
2641 PyErr_Clear();
2642 return 0;
2643 }
2644
2645 /* Unpack and compare single items of p and q using the struct module. */
2646 static int
struct_unpack_cmp(const char * p,const char * q,struct unpacker * unpack_p,struct unpacker * unpack_q)2647 struct_unpack_cmp(const char *p, const char *q,
2648 struct unpacker *unpack_p, struct unpacker *unpack_q)
2649 {
2650 PyObject *v, *w;
2651 int ret;
2652
2653 /* At this point any exception from the struct module should not be
2654 StructError, since both formats have been accepted already. */
2655 v = struct_unpack_single(p, unpack_p);
2656 if (v == NULL)
2657 return MV_COMPARE_EX;
2658
2659 w = struct_unpack_single(q, unpack_q);
2660 if (w == NULL) {
2661 Py_DECREF(v);
2662 return MV_COMPARE_EX;
2663 }
2664
2665 /* MV_COMPARE_EX == -1: exceptions are preserved */
2666 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2667 Py_DECREF(v);
2668 Py_DECREF(w);
2669
2670 return ret;
2671 }
2672
2673 /* Unpack and compare single items of p and q. If both p and q have the same
2674 single element native format, the comparison uses a fast path (gcc creates
2675 a jump table and converts memcpy into simple assignments on x86/x64).
2676
2677 Otherwise, the comparison is delegated to the struct module, which is
2678 30-60x slower. */
2679 #define CMP_SINGLE(p, q, type) \
2680 do { \
2681 type x; \
2682 type y; \
2683 memcpy((char *)&x, p, sizeof x); \
2684 memcpy((char *)&y, q, sizeof y); \
2685 equal = (x == y); \
2686 } while (0)
2687
2688 static inline int
unpack_cmp(const char * p,const char * q,char fmt,struct unpacker * unpack_p,struct unpacker * unpack_q)2689 unpack_cmp(const char *p, const char *q, char fmt,
2690 struct unpacker *unpack_p, struct unpacker *unpack_q)
2691 {
2692 int equal;
2693
2694 switch (fmt) {
2695
2696 /* signed integers and fast path for 'B' */
2697 case 'B': return *((const unsigned char *)p) == *((const unsigned char *)q);
2698 case 'b': return *((const signed char *)p) == *((const signed char *)q);
2699 case 'h': CMP_SINGLE(p, q, short); return equal;
2700 case 'i': CMP_SINGLE(p, q, int); return equal;
2701 case 'l': CMP_SINGLE(p, q, long); return equal;
2702
2703 /* boolean */
2704 case '?': CMP_SINGLE(p, q, _Bool); return equal;
2705
2706 /* unsigned integers */
2707 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2708 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2709 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2710
2711 /* native 64-bit */
2712 case 'q': CMP_SINGLE(p, q, long long); return equal;
2713 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
2714
2715 /* ssize_t and size_t */
2716 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2717 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2718
2719 /* floats */
2720 /* XXX DBL_EPSILON? */
2721 case 'f': CMP_SINGLE(p, q, float); return equal;
2722 case 'd': CMP_SINGLE(p, q, double); return equal;
2723
2724 /* bytes object */
2725 case 'c': return *p == *q;
2726
2727 /* pointer */
2728 case 'P': CMP_SINGLE(p, q, void *); return equal;
2729
2730 /* use the struct module */
2731 case '_':
2732 assert(unpack_p);
2733 assert(unpack_q);
2734 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
2735 }
2736
2737 /* NOT REACHED */
2738 PyErr_SetString(PyExc_RuntimeError,
2739 "memoryview: internal error in richcompare");
2740 return MV_COMPARE_EX;
2741 }
2742
2743 /* Base case for recursive array comparisons. Assumption: ndim == 1. */
2744 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)2745 cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2746 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2747 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
2748 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
2749 {
2750 Py_ssize_t i;
2751 int equal;
2752
2753 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
2754 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2755 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
2756 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
2757 if (equal <= 0)
2758 return equal;
2759 }
2760
2761 return 1;
2762 }
2763
2764 /* Recursively compare two multi-dimensional arrays that have the same
2765 logical structure. Assumption: ndim >= 1. */
2766 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)2767 cmp_rec(const char *p, const char *q,
2768 Py_ssize_t ndim, const Py_ssize_t *shape,
2769 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2770 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
2771 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
2772 {
2773 Py_ssize_t i;
2774 int equal;
2775
2776 assert(ndim >= 1);
2777 assert(shape != NULL);
2778 assert(pstrides != NULL);
2779 assert(qstrides != NULL);
2780
2781 if (ndim == 1) {
2782 return cmp_base(p, q, shape,
2783 pstrides, psuboffsets,
2784 qstrides, qsuboffsets,
2785 fmt, unpack_p, unpack_q);
2786 }
2787
2788 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
2789 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2790 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
2791 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2792 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2793 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
2794 fmt, unpack_p, unpack_q);
2795 if (equal <= 0)
2796 return equal;
2797 }
2798
2799 return 1;
2800 }
2801
2802 static PyObject *
memory_richcompare(PyObject * v,PyObject * w,int op)2803 memory_richcompare(PyObject *v, PyObject *w, int op)
2804 {
2805 PyObject *res;
2806 Py_buffer wbuf, *vv;
2807 Py_buffer *ww = NULL;
2808 struct unpacker *unpack_v = NULL;
2809 struct unpacker *unpack_w = NULL;
2810 char vfmt, wfmt;
2811 int equal = MV_COMPARE_NOT_IMPL;
2812
2813 if (op != Py_EQ && op != Py_NE)
2814 goto result; /* Py_NotImplemented */
2815
2816 assert(PyMemoryView_Check(v));
2817 if (BASE_INACCESSIBLE(v)) {
2818 equal = (v == w);
2819 goto result;
2820 }
2821 vv = VIEW_ADDR(v);
2822
2823 if (PyMemoryView_Check(w)) {
2824 if (BASE_INACCESSIBLE(w)) {
2825 equal = (v == w);
2826 goto result;
2827 }
2828 ww = VIEW_ADDR(w);
2829 }
2830 else {
2831 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2832 PyErr_Clear();
2833 goto result; /* Py_NotImplemented */
2834 }
2835 ww = &wbuf;
2836 }
2837
2838 if (!equiv_shape(vv, ww)) {
2839 PyErr_Clear();
2840 equal = 0;
2841 goto result;
2842 }
2843
2844 /* Use fast unpacking for identical primitive C type formats. */
2845 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2846 vfmt = '_';
2847 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2848 wfmt = '_';
2849 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2850 /* Use struct module unpacking. NOTE: Even for equal format strings,
2851 memcmp() cannot be used for item comparison since it would give
2852 incorrect results in the case of NaNs or uninitialized padding
2853 bytes. */
2854 vfmt = '_';
2855 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2856 if (unpack_v == NULL) {
2857 equal = fix_struct_error_int();
2858 goto result;
2859 }
2860 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2861 if (unpack_w == NULL) {
2862 equal = fix_struct_error_int();
2863 goto result;
2864 }
2865 }
2866
2867 if (vv->ndim == 0) {
2868 equal = unpack_cmp(vv->buf, ww->buf,
2869 vfmt, unpack_v, unpack_w);
2870 }
2871 else if (vv->ndim == 1) {
2872 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2873 vv->strides, vv->suboffsets,
2874 ww->strides, ww->suboffsets,
2875 vfmt, unpack_v, unpack_w);
2876 }
2877 else {
2878 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2879 vv->strides, vv->suboffsets,
2880 ww->strides, ww->suboffsets,
2881 vfmt, unpack_v, unpack_w);
2882 }
2883
2884 result:
2885 if (equal < 0) {
2886 if (equal == MV_COMPARE_NOT_IMPL)
2887 res = Py_NotImplemented;
2888 else /* exception */
2889 res = NULL;
2890 }
2891 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2892 res = Py_True;
2893 else
2894 res = Py_False;
2895
2896 if (ww == &wbuf)
2897 PyBuffer_Release(ww);
2898
2899 unpacker_free(unpack_v);
2900 unpacker_free(unpack_w);
2901
2902 Py_XINCREF(res);
2903 return res;
2904 }
2905
2906 /**************************************************************************/
2907 /* Hash */
2908 /**************************************************************************/
2909
2910 static Py_hash_t
memory_hash(PyMemoryViewObject * self)2911 memory_hash(PyMemoryViewObject *self)
2912 {
2913 if (self->hash == -1) {
2914 Py_buffer *view = &self->view;
2915 char *mem = view->buf;
2916 Py_ssize_t ret;
2917 char fmt;
2918
2919 CHECK_RELEASED_INT(self);
2920
2921 if (!view->readonly) {
2922 PyErr_SetString(PyExc_ValueError,
2923 "cannot hash writable memoryview object");
2924 return -1;
2925 }
2926 ret = get_native_fmtchar(&fmt, view->format);
2927 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2928 PyErr_SetString(PyExc_ValueError,
2929 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2930 return -1;
2931 }
2932 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2933 /* Keep the original error message */
2934 return -1;
2935 }
2936
2937 if (!MV_C_CONTIGUOUS(self->flags)) {
2938 mem = PyMem_Malloc(view->len);
2939 if (mem == NULL) {
2940 PyErr_NoMemory();
2941 return -1;
2942 }
2943 if (buffer_to_contiguous(mem, view, 'C') < 0) {
2944 PyMem_Free(mem);
2945 return -1;
2946 }
2947 }
2948
2949 /* Can't fail */
2950 self->hash = _Py_HashBytes(mem, view->len);
2951
2952 if (mem != view->buf)
2953 PyMem_Free(mem);
2954 }
2955
2956 return self->hash;
2957 }
2958
2959
2960 /**************************************************************************/
2961 /* getters */
2962 /**************************************************************************/
2963
2964 static PyObject *
_IntTupleFromSsizet(int len,Py_ssize_t * vals)2965 _IntTupleFromSsizet(int len, Py_ssize_t *vals)
2966 {
2967 int i;
2968 PyObject *o;
2969 PyObject *intTuple;
2970
2971 if (vals == NULL)
2972 return PyTuple_New(0);
2973
2974 intTuple = PyTuple_New(len);
2975 if (!intTuple)
2976 return NULL;
2977 for (i=0; i<len; i++) {
2978 o = PyLong_FromSsize_t(vals[i]);
2979 if (!o) {
2980 Py_DECREF(intTuple);
2981 return NULL;
2982 }
2983 PyTuple_SET_ITEM(intTuple, i, o);
2984 }
2985 return intTuple;
2986 }
2987
2988 static PyObject *
memory_obj_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))2989 memory_obj_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
2990 {
2991 Py_buffer *view = &self->view;
2992
2993 CHECK_RELEASED(self);
2994 if (view->obj == NULL) {
2995 Py_RETURN_NONE;
2996 }
2997 Py_INCREF(view->obj);
2998 return view->obj;
2999 }
3000
3001 static PyObject *
memory_nbytes_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3002 memory_nbytes_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3003 {
3004 CHECK_RELEASED(self);
3005 return PyLong_FromSsize_t(self->view.len);
3006 }
3007
3008 static PyObject *
memory_format_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3009 memory_format_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3010 {
3011 CHECK_RELEASED(self);
3012 return PyUnicode_FromString(self->view.format);
3013 }
3014
3015 static PyObject *
memory_itemsize_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3016 memory_itemsize_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3017 {
3018 CHECK_RELEASED(self);
3019 return PyLong_FromSsize_t(self->view.itemsize);
3020 }
3021
3022 static PyObject *
memory_shape_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3023 memory_shape_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3024 {
3025 CHECK_RELEASED(self);
3026 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
3027 }
3028
3029 static PyObject *
memory_strides_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3030 memory_strides_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3031 {
3032 CHECK_RELEASED(self);
3033 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
3034 }
3035
3036 static PyObject *
memory_suboffsets_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3037 memory_suboffsets_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3038 {
3039 CHECK_RELEASED(self);
3040 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
3041 }
3042
3043 static PyObject *
memory_readonly_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3044 memory_readonly_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3045 {
3046 CHECK_RELEASED(self);
3047 return PyBool_FromLong(self->view.readonly);
3048 }
3049
3050 static PyObject *
memory_ndim_get(PyMemoryViewObject * self,void * Py_UNUSED (ignored))3051 memory_ndim_get(PyMemoryViewObject *self, void *Py_UNUSED(ignored))
3052 {
3053 CHECK_RELEASED(self);
3054 return PyLong_FromLong(self->view.ndim);
3055 }
3056
3057 static PyObject *
memory_c_contiguous(PyMemoryViewObject * self,PyObject * dummy)3058 memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3059 {
3060 CHECK_RELEASED(self);
3061 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3062 }
3063
3064 static PyObject *
memory_f_contiguous(PyMemoryViewObject * self,PyObject * dummy)3065 memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3066 {
3067 CHECK_RELEASED(self);
3068 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3069 }
3070
3071 static PyObject *
memory_contiguous(PyMemoryViewObject * self,PyObject * dummy)3072 memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
3073 {
3074 CHECK_RELEASED(self);
3075 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3076 }
3077
3078 PyDoc_STRVAR(memory_obj_doc,
3079 "The underlying object of the memoryview.");
3080 PyDoc_STRVAR(memory_nbytes_doc,
3081 "The amount of space in bytes that the array would use in\n"
3082 " a contiguous representation.");
3083 PyDoc_STRVAR(memory_readonly_doc,
3084 "A bool indicating whether the memory is read only.");
3085 PyDoc_STRVAR(memory_itemsize_doc,
3086 "The size in bytes of each element of the memoryview.");
3087 PyDoc_STRVAR(memory_format_doc,
3088 "A string containing the format (in struct module style)\n"
3089 " for each element in the view.");
3090 PyDoc_STRVAR(memory_ndim_doc,
3091 "An integer indicating how many dimensions of a multi-dimensional\n"
3092 " array the memory represents.");
3093 PyDoc_STRVAR(memory_shape_doc,
3094 "A tuple of ndim integers giving the shape of the memory\n"
3095 " as an N-dimensional array.");
3096 PyDoc_STRVAR(memory_strides_doc,
3097 "A tuple of ndim integers giving the size in bytes to access\n"
3098 " each element for each dimension of the array.");
3099 PyDoc_STRVAR(memory_suboffsets_doc,
3100 "A tuple of integers used internally for PIL-style arrays.");
3101 PyDoc_STRVAR(memory_c_contiguous_doc,
3102 "A bool indicating whether the memory is C contiguous.");
3103 PyDoc_STRVAR(memory_f_contiguous_doc,
3104 "A bool indicating whether the memory is Fortran contiguous.");
3105 PyDoc_STRVAR(memory_contiguous_doc,
3106 "A bool indicating whether the memory is contiguous.");
3107
3108
3109 static PyGetSetDef memory_getsetlist[] = {
3110 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3111 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
3112 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3113 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3114 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3115 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3116 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3117 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3118 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
3119 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3120 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3121 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
3122 {NULL, NULL, NULL, NULL},
3123 };
3124
3125 PyDoc_STRVAR(memory_release_doc,
3126 "release($self, /)\n--\n\
3127 \n\
3128 Release the underlying buffer exposed by the memoryview object.");
3129 PyDoc_STRVAR(memory_tobytes_doc,
3130 "tobytes($self, /, order=None)\n--\n\
3131 \n\
3132 Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
3133 When order is 'C' or 'F', the data of the original array is converted to C or\n\
3134 Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
3135 memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
3136 views, the data is converted to C first. order=None is the same as order='C'.");
3137 PyDoc_STRVAR(memory_tolist_doc,
3138 "tolist($self, /)\n--\n\
3139 \n\
3140 Return the data in the buffer as a list of elements.");
3141 PyDoc_STRVAR(memory_cast_doc,
3142 "cast($self, /, format, *, shape)\n--\n\
3143 \n\
3144 Cast a memoryview to a new format or shape.");
3145 PyDoc_STRVAR(memory_toreadonly_doc,
3146 "toreadonly($self, /)\n--\n\
3147 \n\
3148 Return a readonly version of the memoryview.");
3149
3150 static PyMethodDef memory_methods[] = {
3151 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3152 {"tobytes", (PyCFunction)(void(*)(void))memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
3153 MEMORYVIEW_HEX_METHODDEF
3154 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
3155 {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
3156 {"toreadonly", (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
3157 {"__enter__", memory_enter, METH_NOARGS, NULL},
3158 {"__exit__", memory_exit, METH_VARARGS, NULL},
3159 {NULL, NULL}
3160 };
3161
3162
3163 PyTypeObject PyMemoryView_Type = {
3164 PyVarObject_HEAD_INIT(&PyType_Type, 0)
3165 "memoryview", /* tp_name */
3166 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3167 sizeof(Py_ssize_t), /* tp_itemsize */
3168 (destructor)memory_dealloc, /* tp_dealloc */
3169 0, /* tp_vectorcall_offset */
3170 0, /* tp_getattr */
3171 0, /* tp_setattr */
3172 0, /* tp_as_async */
3173 (reprfunc)memory_repr, /* tp_repr */
3174 0, /* tp_as_number */
3175 &memory_as_sequence, /* tp_as_sequence */
3176 &memory_as_mapping, /* tp_as_mapping */
3177 (hashfunc)memory_hash, /* tp_hash */
3178 0, /* tp_call */
3179 0, /* tp_str */
3180 PyObject_GenericGetAttr, /* tp_getattro */
3181 0, /* tp_setattro */
3182 &memory_as_buffer, /* tp_as_buffer */
3183 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3184 memory_doc, /* tp_doc */
3185 (traverseproc)memory_traverse, /* tp_traverse */
3186 (inquiry)memory_clear, /* tp_clear */
3187 memory_richcompare, /* tp_richcompare */
3188 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
3189 0, /* tp_iter */
3190 0, /* tp_iternext */
3191 memory_methods, /* tp_methods */
3192 0, /* tp_members */
3193 memory_getsetlist, /* tp_getset */
3194 0, /* tp_base */
3195 0, /* tp_dict */
3196 0, /* tp_descr_get */
3197 0, /* tp_descr_set */
3198 0, /* tp_dictoffset */
3199 0, /* tp_init */
3200 0, /* tp_alloc */
3201 memory_new, /* tp_new */
3202 };
3203