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