Coverage Report

Created: 2026-07-16 07:04

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