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