LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Objects - memoryobject.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 1189 0.0 %
Date: 2012-12-17 Functions: 0 96 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10