Coverage Report

Created: 2026-10-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/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
2.42M
{
74
2.42M
    _PyManagedBufferObject *mbuf;
75
76
2.42M
    mbuf = (_PyManagedBufferObject *)
77
2.42M
        PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
78
2.42M
    if (mbuf == NULL)
79
0
        return NULL;
80
2.42M
    mbuf->flags = 0;
81
2.42M
    mbuf->exports = 0;
82
2.42M
    mbuf->master.obj = NULL;
83
2.42M
    _PyObject_GC_TRACK(mbuf);
84
85
2.42M
    return mbuf;
86
2.42M
}
87
88
static PyObject *
89
_PyManagedBuffer_FromObject(PyObject *base, int flags)
90
68.0k
{
91
68.0k
    _PyManagedBufferObject *mbuf;
92
93
68.0k
    mbuf = mbuf_alloc();
94
68.0k
    if (mbuf == NULL)
95
0
        return NULL;
96
97
68.0k
    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
68.0k
    return (PyObject *)mbuf;
104
68.0k
}
105
106
static void
107
mbuf_release(_PyManagedBufferObject *self)
108
4.84M
{
109
4.84M
    if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
110
2.42M
        return;
111
112
2.42M
    self->flags |= _Py_MANAGED_BUFFER_RELEASED;
113
114
    /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
115
2.42M
    _PyObject_GC_UNTRACK(self);
116
2.42M
    PyBuffer_Release(&self->master);
117
2.42M
}
118
119
static void
120
mbuf_dealloc(PyObject *_self)
121
2.42M
{
122
2.42M
    _PyManagedBufferObject *self = (_PyManagedBufferObject *)_self;
123
2.42M
    assert(self->exports == 0);
124
2.42M
    mbuf_release(self);
125
2.42M
    if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
126
0
        PyMem_Free(self->master.format);
127
2.42M
    PyObject_GC_Del(self);
128
2.42M
}
129
130
static int
131
mbuf_traverse(PyObject *_self, visitproc visit, void *arg)
132
732
{
133
732
    _PyManagedBufferObject *self = (_PyManagedBufferObject *)_self;
134
732
    Py_VISIT(self->master.obj);
135
732
    return 0;
136
732
}
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
8.26M
    (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
182
8.26M
     ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
183
184
#define CHECK_RELEASED(mv) \
185
4.41M
    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
3.85M
    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
138k
    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
2.31M
    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
4.01M
#define CHECK_RELEASED_AGAIN(mv) CHECK_RELEASED(mv)
215
30.8k
#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
108
#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
225
226
/* Check for the presence of suboffsets in the first dimension. */
227
4.01M
#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
228
/* Adjust ptr if suboffsets are present. */
229
#define ADJUST_PTR(ptr, suboffsets, dim) \
230
4.01M
    (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
231
232
/* Memoryview buffer properties */
233
1.02M
#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
2.56M
    ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
242
243
/* getbuffer() requests */
244
4.62M
#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
245
4.62M
#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
246
4.62M
#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
247
4.62M
#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
248
2.31M
#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
249
2.31M
#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
250
4.62M
#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
251
2.31M
#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
123k
    (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
30.8k
{
274
30.8k
    assert(dest->ndim > 0 && src->ndim > 0);
275
30.8k
    return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
276
30.8k
            !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
277
30.8k
            dest->strides[dest->ndim-1] == dest->itemsize &&
278
30.8k
            src->strides[src->ndim-1] == src->itemsize);
279
30.8k
}
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
30.8k
{
290
30.8k
    const char *dfmt, *sfmt;
291
292
30.8k
    assert(dest->format && src->format);
293
30.8k
    dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
294
30.8k
    sfmt = src->format[0] == '@' ? src->format+1 : src->format;
295
296
30.8k
    if (strcmp(dfmt, sfmt) != 0 ||
297
30.8k
        dest->itemsize != src->itemsize) {
298
0
        return 0;
299
0
    }
300
301
30.8k
    return 1;
302
30.8k
}
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
30.9k
{
310
30.9k
    int i;
311
312
30.9k
    if (dest->ndim != src->ndim)
313
0
        return 0;
314
315
61.5k
    for (i = 0; i < dest->ndim; i++) {
316
30.9k
        if (dest->shape[i] != src->shape[i])
317
25
            return 0;
318
30.9k
        if (dest->shape[i] == 0)
319
318
            break;
320
30.9k
    }
321
322
30.9k
    return 1;
323
30.9k
}
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
30.8k
{
330
30.8k
    if (!equiv_format(dest, src) ||
331
30.8k
        !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
30.8k
    return 1;
339
30.8k
}
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
30.8k
{
350
30.8k
    if (mem == NULL) { /* contiguous */
351
30.8k
        Py_ssize_t size = shape[0] * itemsize;
352
30.8k
        if (dptr + size < sptr || sptr + size < dptr)
353
30.8k
            memcpy(dptr, sptr, size); /* no overlapping */
354
0
        else
355
0
            memmove(dptr, sptr, size);
356
30.8k
    }
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
30.8k
}
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
30.8k
{
407
30.8k
    CHECK_RELEASED_INT_AGAIN(self);
408
30.8k
    char *mem = NULL;
409
410
30.8k
    assert(dest->ndim == 1);
411
412
30.8k
    if (!equiv_structure(dest, src))
413
0
        return -1;
414
415
30.8k
    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
30.8k
    copy_base(dest->shape, dest->itemsize,
424
30.8k
              dest->buf, dest->strides, dest->suboffsets,
425
30.8k
              src->buf, src->strides, src->suboffsets,
426
30.8k
              mem);
427
428
30.8k
    if (mem)
429
0
        PyMem_Free(mem);
430
431
30.8k
    return 0;
432
30.8k
}
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
2.55M
{
545
2.55M
    dest->obj = src->obj;
546
2.55M
    dest->buf = src->buf;
547
2.55M
    dest->len = src->len;
548
2.55M
    dest->itemsize = src->itemsize;
549
2.55M
    dest->readonly = src->readonly;
550
2.55M
    dest->format = src->format ? src->format : "B";
551
2.55M
    dest->internal = src->internal;
552
2.55M
}
553
554
/* Copy shape and strides. Reconstruct missing values. */
555
static void
556
init_shape_strides(Py_buffer *dest, const Py_buffer *src)
557
2.46M
{
558
2.46M
    Py_ssize_t i;
559
560
2.46M
    if (src->ndim == 0) {
561
0
        dest->shape = NULL;
562
0
        dest->strides = NULL;
563
0
        return;
564
0
    }
565
2.46M
    if (src->ndim == 1) {
566
2.46M
        dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
567
2.46M
        dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
568
2.46M
        return;
569
2.46M
    }
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
2.46M
{
585
2.46M
    Py_ssize_t i;
586
587
2.46M
    if (src->suboffsets == NULL) {
588
2.46M
        dest->suboffsets = NULL;
589
2.46M
        return;
590
2.46M
    }
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
5.48k
{
599
5.48k
    Py_ssize_t i, len;
600
601
5.48k
    len = 1;
602
10.9k
    for (i = 0; i < view->ndim; i++)
603
5.48k
        len *= view->shape[i];
604
5.48k
    len *= view->itemsize;
605
606
5.48k
    view->len = len;
607
5.48k
}
608
609
/* Initialize memoryview buffer properties. */
610
static void
611
init_flags(PyMemoryViewObject *mv)
612
2.56M
{
613
2.56M
    const Py_buffer *view = &mv->view;
614
2.56M
    int flags = 0;
615
616
2.56M
    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
2.56M
    case 1:
622
2.56M
        if (MV_CONTIGUOUS_NDIM1(view))
623
2.56M
            flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
624
2.56M
        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
2.56M
    }
632
633
2.56M
    if (view->suboffsets) {
634
0
        flags |= _Py_MEMORYVIEW_PIL;
635
0
        flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
636
0
    }
637
638
2.56M
    mv->flags = flags;
639
2.56M
}
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
2.55M
{
646
2.55M
    PyMemoryViewObject *mv;
647
648
2.55M
    mv = (PyMemoryViewObject *)
649
2.55M
        PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
650
2.55M
    if (mv == NULL)
651
0
        return NULL;
652
653
2.55M
    mv->mbuf = NULL;
654
2.55M
    mv->hash = -1;
655
2.55M
    mv->flags = 0;
656
2.55M
    mv->exports = 0;
657
2.55M
    mv->view.ndim = ndim;
658
2.55M
    mv->view.shape = mv->ob_array;
659
2.55M
    mv->view.strides = mv->ob_array + ndim;
660
2.55M
    mv->view.suboffsets = mv->ob_array + 2 * ndim;
661
2.55M
    mv->weakreflist = NULL;
662
663
2.55M
    _PyObject_GC_TRACK(mv);
664
2.55M
    return mv;
665
2.55M
}
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
2.46M
{
678
2.46M
    PyMemoryViewObject *mv;
679
2.46M
    Py_buffer *dest;
680
681
2.46M
    if (src == NULL)
682
2.42M
        src = &mbuf->master;
683
684
2.46M
    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
2.46M
    mv = memory_alloc(src->ndim);
692
2.46M
    if (mv == NULL)
693
0
        return NULL;
694
695
2.46M
    dest = &mv->view;
696
2.46M
    init_shared_values(dest, src);
697
2.46M
    init_shape_strides(dest, src);
698
2.46M
    init_suboffsets(dest, src);
699
2.46M
    init_flags(mv);
700
701
2.46M
    mv->mbuf = (_PyManagedBufferObject*)Py_NewRef(mbuf);
702
2.46M
    mbuf->exports++;
703
704
2.46M
    return (PyObject *)mv;
705
2.46M
}
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
97.8k
{
716
97.8k
    PyMemoryViewObject *mv;
717
97.8k
    Py_buffer *dest;
718
719
97.8k
    if (src == NULL)
720
0
        src = &mbuf->master;
721
722
97.8k
    assert(ndim <= PyBUF_MAX_NDIM);
723
724
97.8k
    mv = memory_alloc(ndim);
725
97.8k
    if (mv == NULL)
726
0
        return NULL;
727
728
97.8k
    dest = &mv->view;
729
97.8k
    init_shared_values(dest, src);
730
731
97.8k
    mv->mbuf = (_PyManagedBufferObject*)Py_NewRef(mbuf);
732
97.8k
    mbuf->exports++;
733
734
97.8k
    return (PyObject *)mv;
735
97.8k
}
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
2.35M
{
772
2.35M
    _PyManagedBufferObject *mbuf;
773
2.35M
    PyObject *mv;
774
775
2.35M
    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
2.35M
    mbuf = mbuf_alloc();
782
2.35M
    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
2.35M
    mbuf->master = *info;
788
2.35M
    mbuf->master.obj = NULL;
789
790
2.35M
    mv = mbuf_add_view(mbuf, NULL);
791
2.35M
    Py_DECREF(mbuf);
792
793
2.35M
    return mv;
794
2.35M
}
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
103k
{
803
103k
    _PyManagedBufferObject *mbuf;
804
805
103k
    if (PyMemoryView_Check(v)) {
806
35.1k
        PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
807
35.1k
        CHECK_RELEASED(mv);
808
35.1k
        CHECK_RESTRICTED(mv);
809
35.1k
        return mbuf_add_view(mv->mbuf, &mv->view);
810
35.1k
    }
811
68.0k
    else if (PyObject_CheckBuffer(v)) {
812
68.0k
        PyObject *ret;
813
68.0k
        mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v, flags);
814
68.0k
        if (mbuf == NULL)
815
0
            return NULL;
816
68.0k
        ret = mbuf_add_view(mbuf, NULL);
817
68.0k
        Py_DECREF(mbuf);
818
68.0k
        return ret;
819
68.0k
    }
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
103k
}
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
103k
{
856
103k
    return PyMemoryView_FromObjectAndFlags(v, PyBUF_FULL_RO);
857
103k
}
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
103k
{
1017
103k
    return PyMemoryView_FromObject(object);
1018
103k
}
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
31.0M
{
1051
31.0M
    Py_buffer_full *fb = NULL;
1052
31.0M
    int ret;
1053
1054
31.0M
    assert(order == 'C' || order == 'F' || order == 'A');
1055
1056
31.0M
    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
31.0M
    if (PyBuffer_IsContiguous(src, order)) {
1063
31.0M
        memcpy((char *)buf, src->buf, len);
1064
31.0M
        return 0;
1065
31.0M
    }
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
70.2k
{
1092
#ifdef Py_GIL_DISABLED
1093
    return _Py_atomic_load_ssize_relaxed(&buf->exports);
1094
#else
1095
70.2k
    return buf->exports;
1096
70.2k
#endif
1097
70.2k
}
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
2.62M
{
1111
2.62M
    assert(get_exports(self) == 0);
1112
2.62M
    if (self->flags & _Py_MEMORYVIEW_RELEASED)
1113
70.2k
        return;
1114
1115
2.55M
    self->flags |= _Py_MEMORYVIEW_RELEASED;
1116
2.55M
    assert(self->mbuf->exports > 0);
1117
2.55M
    if (--self->mbuf->exports == 0) {
1118
2.42M
        mbuf_release(self->mbuf);
1119
2.42M
    }
1120
2.55M
}
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
70.2k
{
1132
70.2k
    Py_ssize_t exports = get_exports(self);
1133
70.2k
    if (exports == 0) {
1134
70.2k
        _memory_release(self);
1135
70.2k
        Py_RETURN_NONE;
1136
70.2k
    }
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
2.55M
{
1153
2.55M
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
1154
2.55M
    assert(get_exports(self) == 0);
1155
2.55M
    _PyObject_GC_UNTRACK(self);
1156
2.55M
    _memory_release(self);
1157
2.55M
    Py_CLEAR(self->mbuf);
1158
2.55M
    if (self->weakreflist != NULL)
1159
0
        PyObject_ClearWeakRefs((PyObject *) self);
1160
2.55M
    PyObject_GC_Del(self);
1161
2.55M
}
1162
1163
static int
1164
memory_traverse(PyObject *_self, visitproc visit, void *arg)
1165
780
{
1166
780
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
1167
780
    Py_VISIT(self->mbuf);
1168
780
    return 0;
1169
780
}
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
70.2k
{
1185
70.2k
    CHECK_RELEASED(self);
1186
70.2k
    return Py_NewRef(self);
1187
70.2k
}
1188
1189
/*[clinic input]
1190
memoryview.__exit__
1191
1192
    *exc_info: array
1193
1194
Release the underlying buffer exposed by the memoryview object.
1195
[clinic start generated code]*/
1196
1197
static PyObject *
1198
memoryview___exit___impl(PyMemoryViewObject *self,
1199
                         PyObject * const *exc_info,
1200
                         Py_ssize_t exc_info_length)
1201
/*[clinic end generated code: output=c055c4c69baf495d input=881969146ff4d413]*/
1202
70.2k
{
1203
70.2k
    return memoryview_release_impl(self);
1204
70.2k
}
1205
1206
1207
/****************************************************************************/
1208
/*                         Casting format and shape                         */
1209
/****************************************************************************/
1210
1211
#define IS_BYTE_FORMAT(f) \
1212
97.8k
    (strcmp(f, "b") == 0 || strcmp(f, "B") == 0 || strcmp(f, "c") == 0)
1213
1214
static inline Py_ssize_t
1215
get_native_fmtchar(const char **result, const char *fmt)
1216
195k
{
1217
195k
    Py_ssize_t size = -1;
1218
1219
195k
    if (fmt[0] == '@') fmt++;
1220
1221
195k
    switch (fmt[0]) {
1222
133k
    case 'c': case 'b': case 'B': size = sizeof(char); break;
1223
0
    case 'h': case 'H': size = sizeof(short); break;
1224
62.7k
    case 'i': case 'I': size = sizeof(int); break;
1225
0
    case 'l': case 'L': size = sizeof(long); break;
1226
0
    case 'q': case 'Q': size = sizeof(long long); break;
1227
0
    case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1228
0
    case 'f': size = sizeof(float); break;
1229
0
    case 'd': size = sizeof(double); break;
1230
0
    case 'e': size = sizeof(float) / 2; break;
1231
0
    case '?': size = sizeof(_Bool); break;
1232
0
    case 'P': size = sizeof(void *); break;
1233
0
    case 'Z': {
1234
0
        switch (fmt[1]) {
1235
0
            case 'f': size = 2*sizeof(float); break;
1236
0
            case 'd': size = 2*sizeof(double); break;
1237
0
        }
1238
0
        if (size > 0 && fmt[2] == '\0') {
1239
0
            *result = fmt;
1240
0
            return size;
1241
0
        }
1242
0
        break;
1243
0
    }
1244
195k
    }
1245
1246
195k
    if (size > 0 && fmt[1] == '\0') {
1247
195k
        *result = fmt;
1248
195k
        return size;
1249
195k
    }
1250
1251
0
    return -1;
1252
195k
}
1253
1254
static inline const char *
1255
get_native_fmtstr(const char *fmt)
1256
97.8k
{
1257
97.8k
    int at = 0;
1258
1259
97.8k
    if (fmt[0] == '@') {
1260
0
        at = 1;
1261
0
        fmt++;
1262
0
    }
1263
97.8k
    if (fmt[0] == '\0') {
1264
0
        return NULL;
1265
0
    }
1266
97.8k
    if (fmt[0] == 'Z') {
1267
0
        if (fmt[1] == '\0' || fmt[2] != '\0') {
1268
0
            return NULL;
1269
0
        }
1270
0
    }
1271
97.8k
    else {
1272
97.8k
        if (fmt[1] != '\0') {
1273
0
            return NULL;
1274
0
        }
1275
97.8k
    }
1276
1277
97.8k
#define RETURN(s) do { return at ? "@" s : s; } while (0)
1278
1279
97.8k
    switch (fmt[0]) {
1280
0
    case 'c': RETURN("c");
1281
0
    case 'b': RETURN("b");
1282
35.1k
    case 'B': RETURN("B");
1283
0
    case 'h': RETURN("h");
1284
0
    case 'H': RETURN("H");
1285
0
    case 'i': RETURN("i");
1286
62.7k
    case 'I': RETURN("I");
1287
0
    case 'l': RETURN("l");
1288
0
    case 'L': RETURN("L");
1289
0
    case 'q': RETURN("q");
1290
0
    case 'Q': RETURN("Q");
1291
0
    case 'n': RETURN("n");
1292
0
    case 'N': RETURN("N");
1293
0
    case 'f': RETURN("f");
1294
0
    case 'd': RETURN("d");
1295
0
    case 'e': RETURN("e");
1296
0
    case 'Z': {
1297
0
        switch (fmt[1]) {
1298
0
        case 'f': RETURN("Zf");
1299
0
        case 'd': RETURN("Zd");
1300
0
        }
1301
0
        break;
1302
0
    }
1303
0
    case '?': RETURN("?");
1304
0
    case 'P': RETURN("P");
1305
97.8k
    }
1306
1307
0
    return NULL;
1308
97.8k
}
1309
1310
1311
/* Cast a memoryview's data type to 'format'. The input array must be
1312
   C-contiguous. At least one of input-format, output-format must have
1313
   byte size. The output array is 1-D, with the same byte length as the
1314
   input array. Thus, view->len must be a multiple of the new itemsize. */
1315
static int
1316
cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1317
97.8k
{
1318
97.8k
    Py_buffer *view = &mv->view;
1319
97.8k
    PyObject *asciifmt;
1320
97.8k
    const char *srcfmt, *destfmt;
1321
97.8k
    Py_ssize_t itemsize;
1322
97.8k
    int ret = -1;
1323
1324
97.8k
    assert(view->ndim >= 1);
1325
97.8k
    assert(Py_SIZE(mv) == 3*view->ndim);
1326
97.8k
    assert(view->shape == mv->ob_array);
1327
97.8k
    assert(view->strides == mv->ob_array + view->ndim);
1328
97.8k
    assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1329
1330
97.8k
    asciifmt = PyUnicode_AsASCIIString(format);
1331
97.8k
    if (asciifmt == NULL)
1332
0
        return ret;
1333
1334
97.8k
    itemsize = get_native_fmtchar(&destfmt, PyBytes_AS_STRING(asciifmt));
1335
97.8k
    if (itemsize < 0) {
1336
0
        PyErr_SetString(PyExc_ValueError,
1337
0
            "memoryview: destination format must be a native "
1338
0
            "format prefixed with an optional '@'");
1339
0
        goto out;
1340
0
    }
1341
1342
97.8k
    if ((get_native_fmtchar(&srcfmt, view->format) < 0 ||
1343
97.8k
         !IS_BYTE_FORMAT(srcfmt)) && !IS_BYTE_FORMAT(destfmt)) {
1344
0
        PyErr_SetString(PyExc_TypeError,
1345
0
            "memoryview: cannot cast between two non-byte formats");
1346
0
        goto out;
1347
0
    }
1348
97.8k
    if (view->len % itemsize) {
1349
0
        PyErr_SetString(PyExc_TypeError,
1350
0
            "memoryview: length is not a multiple of itemsize");
1351
0
        goto out;
1352
0
    }
1353
1354
97.8k
    view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
1355
97.8k
    if (view->format == NULL) {
1356
        /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1357
0
        PyErr_SetString(PyExc_RuntimeError,
1358
0
            "memoryview: internal error");
1359
0
        goto out;
1360
0
    }
1361
97.8k
    view->itemsize = itemsize;
1362
1363
97.8k
    view->ndim = 1;
1364
97.8k
    view->shape[0] = view->len / view->itemsize;
1365
97.8k
    view->strides[0] = view->itemsize;
1366
97.8k
    view->suboffsets = NULL;
1367
1368
97.8k
    init_flags(mv);
1369
1370
97.8k
    ret = 0;
1371
1372
97.8k
out:
1373
97.8k
    Py_DECREF(asciifmt);
1374
97.8k
    return ret;
1375
97.8k
}
1376
1377
/* The memoryview must have space for 3*len(seq) elements. */
1378
static Py_ssize_t
1379
copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1380
           Py_ssize_t itemsize)
1381
0
{
1382
0
    Py_ssize_t x, i;
1383
0
    Py_ssize_t len = itemsize;
1384
1385
0
    for (i = 0; i < ndim; i++) {
1386
0
        PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1387
0
        if (!PyLong_Check(tmp)) {
1388
0
            PyErr_SetString(PyExc_TypeError,
1389
0
                "memoryview.cast(): elements of shape must be integers");
1390
0
            return -1;
1391
0
        }
1392
0
        x = PyLong_AsSsize_t(tmp);
1393
0
        if (x == -1 && PyErr_Occurred()) {
1394
0
            return -1;
1395
0
        }
1396
0
        if (x <= 0) {
1397
            /* In general elements of shape may be 0, but not for casting. */
1398
0
            PyErr_Format(PyExc_ValueError,
1399
0
                "memoryview.cast(): elements of shape must be integers > 0");
1400
0
            return -1;
1401
0
        }
1402
0
        if (x > PY_SSIZE_T_MAX / len) {
1403
0
            PyErr_Format(PyExc_ValueError,
1404
0
                "memoryview.cast(): product(shape) > SSIZE_MAX");
1405
0
            return -1;
1406
0
        }
1407
0
        len *= x;
1408
0
        shape[i] = x;
1409
0
    }
1410
1411
0
    return len;
1412
0
}
1413
1414
/* Cast a 1-D array to a new shape. The result array will be C-contiguous
1415
   ('C') or Fortran-contiguous ('F') according to 'order'.  If the result
1416
   array does not have exactly the same byte length as the input array, raise
1417
   TypeError. */
1418
static int
1419
cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim, char order)
1420
0
{
1421
0
    Py_buffer *view = &mv->view;
1422
0
    Py_ssize_t len;
1423
1424
0
    assert(view->ndim == 1); /* ndim from cast_to_1D() */
1425
0
    assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1426
0
    assert(view->shape == mv->ob_array);
1427
0
    assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1428
0
    assert(view->suboffsets == NULL);
1429
1430
0
    view->ndim = ndim;
1431
0
    if (view->ndim == 0) {
1432
0
        view->shape = NULL;
1433
0
        view->strides = NULL;
1434
0
        len = view->itemsize;
1435
0
    }
1436
0
    else {
1437
0
        len = copy_shape(view->shape, shape, ndim, view->itemsize);
1438
0
        if (len < 0)
1439
0
            return -1;
1440
0
        if (order == 'F')
1441
0
            init_fortran_strides_from_shape(view);
1442
0
        else
1443
0
            init_strides_from_shape(view);
1444
0
    }
1445
1446
0
    if (view->len != len) {
1447
0
        PyErr_SetString(PyExc_TypeError,
1448
0
            "memoryview: product(shape) * itemsize != buffer size");
1449
0
        return -1;
1450
0
    }
1451
1452
0
    init_flags(mv);
1453
1454
0
    return 0;
1455
0
}
1456
1457
static int
1458
zero_in_shape(PyMemoryViewObject *mv)
1459
0
{
1460
0
    Py_buffer *view = &mv->view;
1461
0
    Py_ssize_t i;
1462
1463
0
    for (i = 0; i < view->ndim; i++)
1464
0
        if (view->shape[i] == 0)
1465
0
            return 1;
1466
1467
0
    return 0;
1468
0
}
1469
1470
/*
1471
   Cast a copy of 'self' to a different view. The input view must
1472
   be C-contiguous. The function always casts the input view to a
1473
   1-D output according to 'format'. At least one of input-format,
1474
   output-format must have byte size.
1475
1476
   If 'shape' is given, the 1-D view from the previous step will
1477
   be cast to a C-contiguous view with new shape and strides.
1478
1479
   All casts must result in views that will have the exact byte
1480
   size of the original input. Otherwise, an error is raised.
1481
*/
1482
/*[clinic input]
1483
memoryview.cast
1484
1485
    format: unicode
1486
    shape: object = NULL
1487
    *
1488
    order: int(accept={str}) = 'C'
1489
1490
Cast a memoryview to a new format or shape.
1491
1492
With a multidimensional *shape*, *order* selects the result
1493
layout: 'C' for C-contiguous (row-major, the default) or 'F'
1494
for Fortran-contiguous (column-major).
1495
[clinic start generated code]*/
1496
1497
static PyObject *
1498
memoryview_cast_impl(PyMemoryViewObject *self, PyObject *format,
1499
                     PyObject *shape, int order)
1500
/*[clinic end generated code: output=6410d87141f6bb56 input=4a1a2326c59caeb3]*/
1501
97.8k
{
1502
97.8k
    PyMemoryViewObject *mv = NULL;
1503
97.8k
    Py_ssize_t ndim = 1;
1504
1505
97.8k
    CHECK_RELEASED(self);
1506
97.8k
    CHECK_RESTRICTED(self);
1507
1508
97.8k
    if (order != 'C' && order != 'F') {
1509
0
        PyErr_SetString(PyExc_ValueError, "order must be 'C' or 'F'");
1510
0
        return NULL;
1511
0
    }
1512
1513
97.8k
    if (!MV_C_CONTIGUOUS(self->flags)) {
1514
0
        if (shape || !MV_F_CONTIGUOUS(self->flags)) {
1515
0
            PyErr_SetString(PyExc_TypeError,
1516
0
                "memoryview: casts are restricted to contiguous views");
1517
0
            return NULL;
1518
0
        }
1519
0
    }
1520
97.8k
    if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
1521
0
        PyErr_SetString(PyExc_TypeError,
1522
0
            "memoryview: cannot cast view with zeros in shape or strides");
1523
0
        return NULL;
1524
0
    }
1525
97.8k
    if (shape) {
1526
0
        CHECK_LIST_OR_TUPLE(shape)
1527
0
        ndim = PySequence_Fast_GET_SIZE(shape);
1528
0
        if (ndim > PyBUF_MAX_NDIM) {
1529
0
            PyErr_SetString(PyExc_ValueError,
1530
0
                "memoryview: number of dimensions must not exceed "
1531
0
                Py_STRINGIFY(PyBUF_MAX_NDIM));
1532
0
            return NULL;
1533
0
        }
1534
0
        if (self->view.ndim != 1 && ndim != 1) {
1535
0
            PyErr_SetString(PyExc_TypeError,
1536
0
                "memoryview: cast must be 1D -> ND or ND -> 1D");
1537
0
            return NULL;
1538
0
        }
1539
0
    }
1540
1541
97.8k
    mv = (PyMemoryViewObject *)
1542
97.8k
        mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1543
97.8k
    if (mv == NULL)
1544
0
        return NULL;
1545
1546
97.8k
    if (cast_to_1D(mv, format) < 0)
1547
0
        goto error;
1548
97.8k
    if (shape && cast_to_ND(mv, shape, (int)ndim, (char)order) < 0)
1549
0
        goto error;
1550
1551
97.8k
    return (PyObject *)mv;
1552
1553
0
error:
1554
0
    Py_DECREF(mv);
1555
0
    return NULL;
1556
97.8k
}
1557
1558
/*[clinic input]
1559
memoryview.toreadonly
1560
1561
Return a readonly version of the memoryview.
1562
[clinic start generated code]*/
1563
1564
static PyObject *
1565
memoryview_toreadonly_impl(PyMemoryViewObject *self)
1566
/*[clinic end generated code: output=2c7e056f04c99e62 input=dc06d20f19ba236f]*/
1567
0
{
1568
0
    CHECK_RELEASED(self);
1569
0
    CHECK_RESTRICTED(self);
1570
    /* Even if self is already readonly, we still need to create a new
1571
     * object for .release() to work correctly.
1572
     */
1573
0
    self = (PyMemoryViewObject *) mbuf_add_view(self->mbuf, &self->view);
1574
0
    if (self != NULL) {
1575
0
        self->view.readonly = 1;
1576
0
    };
1577
0
    return (PyObject *) self;
1578
0
}
1579
1580
1581
/**************************************************************************/
1582
/*                               getbuffer                                */
1583
/**************************************************************************/
1584
1585
static int
1586
memory_getbuf(PyObject *_self, Py_buffer *view, int flags)
1587
2.31M
{
1588
2.31M
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
1589
2.31M
    Py_buffer *base = &self->view;
1590
2.31M
    int baseflags = self->flags;
1591
1592
2.31M
    CHECK_RELEASED_INT(self);
1593
2.31M
    CHECK_RESTRICTED_INT(self);
1594
1595
    /* start with complete information */
1596
2.31M
    *view = *base;
1597
2.31M
    view->obj = NULL;
1598
1599
2.31M
    if (REQ_WRITABLE(flags) && base->readonly) {
1600
0
        PyErr_SetString(PyExc_BufferError,
1601
0
            "memoryview: underlying buffer is not writable");
1602
0
        return -1;
1603
0
    }
1604
2.31M
    if (!REQ_FORMAT(flags)) {
1605
        /* NULL indicates that the buffer's data type has been cast to 'B'.
1606
           view->itemsize is the _previous_ itemsize. If shape is present,
1607
           the equality product(shape) * itemsize = len still holds at this
1608
           point. The equality calcsize(format) = itemsize does _not_ hold
1609
           from here on! */
1610
924k
        view->format = NULL;
1611
924k
    }
1612
1613
2.31M
    if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1614
0
        PyErr_SetString(PyExc_BufferError,
1615
0
            "memoryview: underlying buffer is not C-contiguous");
1616
0
        return -1;
1617
0
    }
1618
2.31M
    if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1619
0
        PyErr_SetString(PyExc_BufferError,
1620
0
            "memoryview: underlying buffer is not Fortran contiguous");
1621
0
        return -1;
1622
0
    }
1623
2.31M
    if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1624
0
        PyErr_SetString(PyExc_BufferError,
1625
0
            "memoryview: underlying buffer is not contiguous");
1626
0
        return -1;
1627
0
    }
1628
2.31M
    if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1629
0
        PyErr_SetString(PyExc_BufferError,
1630
0
            "memoryview: underlying buffer requires suboffsets");
1631
0
        return -1;
1632
0
    }
1633
2.31M
    if (!REQ_STRIDES(flags)) {
1634
924k
        if (!MV_C_CONTIGUOUS(baseflags)) {
1635
0
            PyErr_SetString(PyExc_BufferError,
1636
0
                "memoryview: underlying buffer is not C-contiguous");
1637
0
            return -1;
1638
0
        }
1639
924k
        view->strides = NULL;
1640
924k
    }
1641
2.31M
    if (!REQ_SHAPE(flags)) {
1642
        /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1643
           so base->buf = ndbuf->data. */
1644
924k
        if (view->format != NULL) {
1645
            /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1646
               not make sense. */
1647
0
            PyErr_Format(PyExc_BufferError,
1648
0
                "memoryview: cannot cast to unsigned bytes if the format flag "
1649
0
                "is present");
1650
0
            return -1;
1651
0
        }
1652
        /* product(shape) * itemsize = len and calcsize(format) = itemsize
1653
           do _not_ hold from here on! */
1654
924k
        view->ndim = 1;
1655
924k
        view->shape = NULL;
1656
924k
    }
1657
1658
1659
2.31M
    view->obj = Py_NewRef(self);
1660
2.31M
    FT_ATOMIC_ADD_SSIZE(self->exports, 1);
1661
1662
2.31M
    return 0;
1663
2.31M
}
1664
1665
static void
1666
memory_releasebuf(PyObject *_self, Py_buffer *view)
1667
2.31M
{
1668
2.31M
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
1669
2.31M
    FT_ATOMIC_ADD_SSIZE(self->exports, -1);
1670
2.31M
    return;
1671
    /* PyBuffer_Release() decrements view->obj after this function returns. */
1672
2.31M
}
1673
1674
/* Buffer methods */
1675
static PyBufferProcs memory_as_buffer = {
1676
    memory_getbuf,         /* bf_getbuffer */
1677
    memory_releasebuf,                    /* bf_releasebuffer */
1678
};
1679
1680
1681
/****************************************************************************/
1682
/*           Optimized pack/unpack for all native format specifiers         */
1683
/****************************************************************************/
1684
1685
/*
1686
  Fix exceptions:
1687
     1) Include format string in the error message.
1688
     2) OverflowError -> ValueError.
1689
     3) The error message from PyNumber_Index() is not ideal.
1690
*/
1691
static int
1692
type_error_int(const char *fmt)
1693
0
{
1694
0
    PyErr_Format(PyExc_TypeError,
1695
0
        "memoryview: invalid type for format '%s'", fmt);
1696
0
    return -1;
1697
0
}
1698
1699
static int
1700
value_error_int(const char *fmt)
1701
0
{
1702
0
    PyErr_Format(PyExc_ValueError,
1703
0
        "memoryview: invalid value for format '%s'", fmt);
1704
0
    return -1;
1705
0
}
1706
1707
static int
1708
fix_error_int(const char *fmt)
1709
0
{
1710
0
    assert(PyErr_Occurred());
1711
0
    if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1712
0
        PyErr_Clear();
1713
0
        return type_error_int(fmt);
1714
0
    }
1715
0
    else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1716
0
             PyErr_ExceptionMatches(PyExc_ValueError)) {
1717
0
        PyErr_Clear();
1718
0
        return value_error_int(fmt);
1719
0
    }
1720
1721
0
    return -1;
1722
0
}
1723
1724
// UNPACK_TO_BOOL: Return 0 if PTR represents "false", and 1 otherwise.
1725
static const _Bool bool_false = 0;
1726
0
#define UNPACK_TO_BOOL(PTR) (memcmp((PTR), &bool_false, sizeof(_Bool)) != 0)
1727
1728
/* Accept integer objects or objects with an __index__() method. */
1729
static long
1730
pylong_as_ld(PyObject *item)
1731
0
{
1732
0
    PyObject *tmp;
1733
0
    long ld;
1734
1735
0
    tmp = _PyNumber_Index(item);
1736
0
    if (tmp == NULL)
1737
0
        return -1;
1738
1739
0
    ld = PyLong_AsLong(tmp);
1740
0
    Py_DECREF(tmp);
1741
0
    return ld;
1742
0
}
1743
1744
static unsigned long
1745
pylong_as_lu(PyObject *item)
1746
0
{
1747
0
    PyObject *tmp;
1748
0
    unsigned long lu;
1749
1750
0
    tmp = _PyNumber_Index(item);
1751
0
    if (tmp == NULL)
1752
0
        return (unsigned long)-1;
1753
1754
0
    lu = PyLong_AsUnsignedLong(tmp);
1755
0
    Py_DECREF(tmp);
1756
0
    return lu;
1757
0
}
1758
1759
static long long
1760
pylong_as_lld(PyObject *item)
1761
0
{
1762
0
    PyObject *tmp;
1763
0
    long long lld;
1764
1765
0
    tmp = _PyNumber_Index(item);
1766
0
    if (tmp == NULL)
1767
0
        return -1;
1768
1769
0
    lld = PyLong_AsLongLong(tmp);
1770
0
    Py_DECREF(tmp);
1771
0
    return lld;
1772
0
}
1773
1774
static unsigned long long
1775
pylong_as_llu(PyObject *item)
1776
0
{
1777
0
    PyObject *tmp;
1778
0
    unsigned long long llu;
1779
1780
0
    tmp = _PyNumber_Index(item);
1781
0
    if (tmp == NULL)
1782
0
        return (unsigned long long)-1;
1783
1784
0
    llu = PyLong_AsUnsignedLongLong(tmp);
1785
0
    Py_DECREF(tmp);
1786
0
    return llu;
1787
0
}
1788
1789
static Py_ssize_t
1790
pylong_as_zd(PyObject *item)
1791
0
{
1792
0
    PyObject *tmp;
1793
0
    Py_ssize_t zd;
1794
1795
0
    tmp = _PyNumber_Index(item);
1796
0
    if (tmp == NULL)
1797
0
        return -1;
1798
1799
0
    zd = PyLong_AsSsize_t(tmp);
1800
0
    Py_DECREF(tmp);
1801
0
    return zd;
1802
0
}
1803
1804
static size_t
1805
pylong_as_zu(PyObject *item)
1806
0
{
1807
0
    PyObject *tmp;
1808
0
    size_t zu;
1809
1810
0
    tmp = _PyNumber_Index(item);
1811
0
    if (tmp == NULL)
1812
0
        return (size_t)-1;
1813
1814
0
    zu = PyLong_AsSize_t(tmp);
1815
0
    Py_DECREF(tmp);
1816
0
    return zu;
1817
0
}
1818
1819
/* Timings with the ndarray from _testbuffer.c indicate that using the
1820
   struct module is around 15x slower than the two functions below. */
1821
1822
#define UNPACK_SINGLE(dest, ptr, type) \
1823
4.01M
    do {                                   \
1824
4.01M
        type x;                            \
1825
4.01M
        memcpy((char *)&x, ptr, sizeof x); \
1826
4.01M
        dest = x;                          \
1827
4.01M
    } while (0)
1828
1829
/* Unpack a single item. 'fmt' can be any native format in struct
1830
   module syntax. This function is very sensitive to small changes. With this
1831
   layout gcc automatically generates a fast jump table. */
1832
static inline PyObject *
1833
unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt)
1834
4.01M
{
1835
4.01M
    unsigned long long llu;
1836
4.01M
    unsigned long lu;
1837
4.01M
    size_t zu;
1838
4.01M
    long long lld;
1839
4.01M
    long ld;
1840
4.01M
    Py_ssize_t zd;
1841
4.01M
    double d[2];
1842
4.01M
    unsigned char uc;
1843
4.01M
    void *p;
1844
1845
4.01M
    CHECK_RELEASED_AGAIN(self);
1846
1847
4.01M
#if PY_LITTLE_ENDIAN
1848
4.01M
    int endian = 1;
1849
#else
1850
    int endian = 0;
1851
#endif
1852
1853
4.01M
    switch (fmt[0]) {
1854
1855
    /* signed integers and fast path for 'B' */
1856
0
    case 'B': uc = *((const unsigned char *)ptr); goto convert_uc;
1857
0
    case 'b': ld =   *((const signed char *)ptr); goto convert_ld;
1858
0
    case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1859
0
    case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1860
0
    case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1861
1862
    /* boolean */
1863
0
    case '?': ld = UNPACK_TO_BOOL(ptr); goto convert_bool;
1864
1865
    /* unsigned integers */
1866
0
    case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1867
4.01M
    case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1868
0
    case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1869
1870
    /* native 64-bit */
1871
0
    case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1872
0
    case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
1873
1874
    /* ssize_t and size_t */
1875
0
    case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1876
0
    case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1877
1878
    /* floats */
1879
0
    case 'f': UNPACK_SINGLE(d[0], ptr, float); goto convert_double;
1880
0
    case 'd': UNPACK_SINGLE(d[0], ptr, double); goto convert_double;
1881
0
    case 'e': d[0] = PyFloat_Unpack2(ptr, endian); goto convert_double;
1882
1883
    /* complexes */
1884
0
    case 'Z': {
1885
0
        switch (fmt[1]) {
1886
0
        case 'f':
1887
0
            d[0] = PyFloat_Unpack4(ptr, endian);
1888
0
            d[1] = PyFloat_Unpack4(ptr + sizeof(float), endian);
1889
0
            goto convert_double_complex;
1890
1891
0
        case 'd':
1892
0
            d[0] = PyFloat_Unpack8(ptr, endian);
1893
0
            d[1] = PyFloat_Unpack8(ptr + sizeof(double), endian);
1894
0
            goto convert_double_complex;
1895
1896
0
        default: goto err_format;
1897
0
        }
1898
0
        break;
1899
0
    }
1900
1901
    /* bytes object */
1902
0
    case 'c': goto convert_bytes;
1903
1904
    /* pointer */
1905
0
    case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1906
1907
    /* default */
1908
0
    default: goto err_format;
1909
4.01M
    }
1910
1911
0
convert_uc:
1912
    /* PyLong_FromUnsignedLong() is slower */
1913
0
    return PyLong_FromLong(uc);
1914
0
convert_ld:
1915
0
    return PyLong_FromLong(ld);
1916
4.01M
convert_lu:
1917
4.01M
    return PyLong_FromUnsignedLong(lu);
1918
0
convert_lld:
1919
0
    return PyLong_FromLongLong(lld);
1920
0
convert_llu:
1921
0
    return PyLong_FromUnsignedLongLong(llu);
1922
0
convert_zd:
1923
0
    return PyLong_FromSsize_t(zd);
1924
0
convert_zu:
1925
0
    return PyLong_FromSize_t(zu);
1926
0
convert_double:
1927
0
    return PyFloat_FromDouble(d[0]);
1928
0
convert_double_complex:
1929
0
    return PyComplex_FromDoubles(d[0], d[1]);
1930
0
convert_bool:
1931
0
    return PyBool_FromLong(ld);
1932
0
convert_bytes:
1933
0
    return PyBytes_FromStringAndSize(ptr, 1);
1934
0
convert_pointer:
1935
0
    return PyLong_FromVoidPtr(p);
1936
0
err_format:
1937
0
    PyErr_Format(PyExc_NotImplementedError,
1938
0
        "memoryview: format %s not supported", fmt);
1939
0
    return NULL;
1940
4.01M
}
1941
1942
#define PACK_SINGLE(ptr, src, type) \
1943
0
    do {                                     \
1944
0
        type x;                              \
1945
0
        x = (type)src;                       \
1946
0
        memcpy(ptr, (char *)&x, sizeof x);   \
1947
0
    } while (0)
1948
1949
/* Pack a single item. 'fmt' can be any native format in
1950
   struct module syntax. */
1951
static int
1952
pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt)
1953
0
{
1954
0
    unsigned long long llu;
1955
0
    unsigned long lu;
1956
0
    size_t zu;
1957
0
    long long lld;
1958
0
    long ld;
1959
0
    Py_ssize_t zd;
1960
0
    double d;
1961
0
    Py_complex c;
1962
0
    void *p;
1963
1964
0
#if PY_LITTLE_ENDIAN
1965
0
    int endian = 1;
1966
#else
1967
    int endian = 0;
1968
#endif
1969
0
    switch (fmt[0]) {
1970
    /* signed integers */
1971
0
    case 'b': case 'h': case 'i': case 'l':
1972
0
        ld = pylong_as_ld(item);
1973
0
        if (ld == -1 && PyErr_Occurred())
1974
0
            goto err_occurred;
1975
0
        CHECK_RELEASED_INT_AGAIN(self);
1976
0
        switch (fmt[0]) {
1977
0
        case 'b':
1978
0
            if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1979
0
            *((signed char *)ptr) = (signed char)ld; break;
1980
0
        case 'h':
1981
0
            if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1982
0
            PACK_SINGLE(ptr, ld, short); break;
1983
0
        case 'i':
1984
0
            if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1985
0
            PACK_SINGLE(ptr, ld, int); break;
1986
0
        default: /* 'l' */
1987
0
            PACK_SINGLE(ptr, ld, long); break;
1988
0
        }
1989
0
        break;
1990
1991
    /* unsigned integers */
1992
0
    case 'B': case 'H': case 'I': case 'L':
1993
0
        lu = pylong_as_lu(item);
1994
0
        if (lu == (unsigned long)-1 && PyErr_Occurred())
1995
0
            goto err_occurred;
1996
0
        CHECK_RELEASED_INT_AGAIN(self);
1997
0
        switch (fmt[0]) {
1998
0
        case 'B':
1999
0
            if (lu > UCHAR_MAX) goto err_range;
2000
0
            *((unsigned char *)ptr) = (unsigned char)lu; break;
2001
0
        case 'H':
2002
0
            if (lu > USHRT_MAX) goto err_range;
2003
0
            PACK_SINGLE(ptr, lu, unsigned short); break;
2004
0
        case 'I':
2005
0
            if (lu > UINT_MAX) goto err_range;
2006
0
            PACK_SINGLE(ptr, lu, unsigned int); break;
2007
0
        default: /* 'L' */
2008
0
            PACK_SINGLE(ptr, lu, unsigned long); break;
2009
0
        }
2010
0
        break;
2011
2012
    /* native 64-bit */
2013
0
    case 'q':
2014
0
        lld = pylong_as_lld(item);
2015
0
        if (lld == -1 && PyErr_Occurred())
2016
0
            goto err_occurred;
2017
0
        CHECK_RELEASED_INT_AGAIN(self);
2018
0
        PACK_SINGLE(ptr, lld, long long);
2019
0
        break;
2020
0
    case 'Q':
2021
0
        llu = pylong_as_llu(item);
2022
0
        if (llu == (unsigned long long)-1 && PyErr_Occurred())
2023
0
            goto err_occurred;
2024
0
        CHECK_RELEASED_INT_AGAIN(self);
2025
0
        PACK_SINGLE(ptr, llu, unsigned long long);
2026
0
        break;
2027
2028
    /* ssize_t and size_t */
2029
0
    case 'n':
2030
0
        zd = pylong_as_zd(item);
2031
0
        if (zd == -1 && PyErr_Occurred())
2032
0
            goto err_occurred;
2033
0
        CHECK_RELEASED_INT_AGAIN(self);
2034
0
        PACK_SINGLE(ptr, zd, Py_ssize_t);
2035
0
        break;
2036
0
    case 'N':
2037
0
        zu = pylong_as_zu(item);
2038
0
        if (zu == (size_t)-1 && PyErr_Occurred())
2039
0
            goto err_occurred;
2040
0
        CHECK_RELEASED_INT_AGAIN(self);
2041
0
        PACK_SINGLE(ptr, zu, size_t);
2042
0
        break;
2043
2044
    /* floats */
2045
0
    case 'f': case 'd': case 'e':
2046
0
        d = PyFloat_AsDouble(item);
2047
0
        if (d == -1.0 && PyErr_Occurred())
2048
0
            goto err_occurred;
2049
0
        CHECK_RELEASED_INT_AGAIN(self);
2050
0
        if (fmt[0] == 'f') {
2051
0
            if (PyFloat_Pack4(d, ptr, endian) < 0) {
2052
0
                goto err_occurred;
2053
0
            }
2054
0
        }
2055
0
        else if (fmt[0] == 'd') {
2056
0
            PACK_SINGLE(ptr, d, double);
2057
0
        }
2058
0
        else {
2059
0
            if (PyFloat_Pack2(d, ptr, endian) < 0) {
2060
0
                goto err_occurred;
2061
0
            }
2062
0
        }
2063
0
        break;
2064
2065
    /* complexes */
2066
0
    case 'Z': {
2067
0
        switch (fmt[1]) {
2068
0
        case 'f': case 'd':
2069
0
            c = PyComplex_AsCComplex(item);
2070
0
            if (c.real == -1.0 && PyErr_Occurred()) {
2071
0
                goto err_occurred;
2072
0
            }
2073
0
            CHECK_RELEASED_INT_AGAIN(self);
2074
0
            if (fmt[1] == 'd') {
2075
0
                double x[2] = {c.real, c.imag};
2076
2077
0
                memcpy(ptr, &x, sizeof(x));
2078
0
            }
2079
0
            else {
2080
0
                char tmp[8];
2081
2082
0
                if (PyFloat_Pack4(c.real, tmp, endian) < 0) {
2083
0
                    goto err_occurred;
2084
0
                }
2085
0
                if (PyFloat_Pack4(c.imag, tmp + 4, endian) < 0) {
2086
0
                    goto err_occurred;
2087
0
                }
2088
0
                memcpy(ptr, tmp, 8);
2089
0
            }
2090
0
            break;
2091
2092
0
        default: goto err_format;
2093
0
        }
2094
0
        break;
2095
0
    }
2096
2097
    /* bool */
2098
0
    case '?':
2099
0
        ld = PyObject_IsTrue(item);
2100
0
        if (ld < 0)
2101
0
            return -1; /* preserve original error */
2102
0
        CHECK_RELEASED_INT_AGAIN(self);
2103
0
        PACK_SINGLE(ptr, ld, _Bool);
2104
0
        break;
2105
2106
    /* bytes object */
2107
0
    case 'c':
2108
0
        if (!PyBytes_Check(item))
2109
0
            return type_error_int(fmt);
2110
0
        if (PyBytes_GET_SIZE(item) != 1)
2111
0
            return value_error_int(fmt);
2112
0
        *ptr = PyBytes_AS_STRING(item)[0];
2113
0
        break;
2114
2115
    /* pointer */
2116
0
    case 'P':
2117
0
        p = PyLong_AsVoidPtr(item);
2118
0
        if (p == NULL && PyErr_Occurred())
2119
0
            goto err_occurred;
2120
0
        CHECK_RELEASED_INT_AGAIN(self);
2121
0
        PACK_SINGLE(ptr, p, void *);
2122
0
        break;
2123
2124
    /* default */
2125
0
    default: goto err_format;
2126
0
    }
2127
2128
0
    return 0;
2129
2130
0
err_occurred:
2131
0
    return fix_error_int(fmt);
2132
0
err_range:
2133
0
    return value_error_int(fmt);
2134
0
err_format:
2135
0
    PyErr_Format(PyExc_NotImplementedError,
2136
0
        "memoryview: format %s not supported", fmt);
2137
0
    return -1;
2138
0
}
2139
2140
2141
/****************************************************************************/
2142
/*                       unpack using the struct module                     */
2143
/****************************************************************************/
2144
2145
/* For reasonable performance it is necessary to cache all objects required
2146
   for unpacking. An unpacker can handle the format passed to unpack_from().
2147
   Invariant: All pointer fields of the struct should either be NULL or valid
2148
   pointers. */
2149
struct unpacker {
2150
    PyObject *unpack_from; /* Struct.unpack_from(format) */
2151
    PyObject *mview;       /* cached memoryview */
2152
    char *item;            /* buffer for mview */
2153
    Py_ssize_t itemsize;   /* len(item) */
2154
};
2155
2156
static struct unpacker *
2157
unpacker_new(void)
2158
0
{
2159
0
    struct unpacker *x = PyMem_Malloc(sizeof *x);
2160
2161
0
    if (x == NULL) {
2162
0
        PyErr_NoMemory();
2163
0
        return NULL;
2164
0
    }
2165
2166
0
    x->unpack_from = NULL;
2167
0
    x->mview = NULL;
2168
0
    x->item = NULL;
2169
0
    x->itemsize = 0;
2170
2171
0
    return x;
2172
0
}
2173
2174
static void
2175
unpacker_free(struct unpacker *x)
2176
216
{
2177
216
    if (x) {
2178
0
        Py_XDECREF(x->unpack_from);
2179
0
        Py_XDECREF(x->mview);
2180
0
        PyMem_Free(x->item);
2181
0
        PyMem_Free(x);
2182
0
    }
2183
216
}
2184
2185
/* Return a new unpacker for the given format. */
2186
static struct unpacker *
2187
struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
2188
0
{
2189
0
    PyObject *Struct = NULL;    /* XXX cache it in globals? */
2190
0
    PyObject *structobj = NULL;
2191
0
    PyObject *format = NULL;
2192
0
    struct unpacker *x = NULL;
2193
2194
0
    Struct = PyImport_ImportModuleAttrString("struct", "Struct");
2195
0
    if (Struct == NULL)
2196
0
        return NULL;
2197
2198
0
    x = unpacker_new();
2199
0
    if (x == NULL)
2200
0
        goto error;
2201
2202
0
    format = PyBytes_FromString(fmt);
2203
0
    if (format == NULL)
2204
0
        goto error;
2205
2206
0
    structobj = PyObject_CallOneArg(Struct, format);
2207
0
    if (structobj == NULL)
2208
0
        goto error;
2209
2210
0
    x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
2211
0
    if (x->unpack_from == NULL)
2212
0
        goto error;
2213
2214
0
    x->item = PyMem_Malloc(itemsize);
2215
0
    if (x->item == NULL) {
2216
0
        PyErr_NoMemory();
2217
0
        goto error;
2218
0
    }
2219
0
    x->itemsize = itemsize;
2220
2221
0
    x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
2222
0
    if (x->mview == NULL)
2223
0
        goto error;
2224
2225
2226
0
out:
2227
0
    Py_XDECREF(Struct);
2228
0
    Py_XDECREF(format);
2229
0
    Py_XDECREF(structobj);
2230
0
    return x;
2231
2232
0
error:
2233
0
    unpacker_free(x);
2234
0
    x = NULL;
2235
0
    goto out;
2236
0
}
2237
2238
/* unpack a single item */
2239
static PyObject *
2240
struct_unpack_single(const char *ptr, struct unpacker *x)
2241
0
{
2242
0
    PyObject *v;
2243
2244
0
    memcpy(x->item, ptr, x->itemsize);
2245
0
    v = PyObject_CallOneArg(x->unpack_from, x->mview);
2246
0
    if (v == NULL)
2247
0
        return NULL;
2248
2249
0
    if (PyTuple_GET_SIZE(v) == 1) {
2250
0
        PyObject *res = Py_NewRef(PyTuple_GET_ITEM(v, 0));
2251
0
        Py_DECREF(v);
2252
0
        return res;
2253
0
    }
2254
2255
0
    return v;
2256
0
}
2257
2258
2259
/****************************************************************************/
2260
/*                              Representations                             */
2261
/****************************************************************************/
2262
2263
/* allow explicit form of native format */
2264
static inline const char *
2265
adjust_fmt(const Py_buffer *view)
2266
93.5k
{
2267
93.5k
    const char *fmt;
2268
2269
93.5k
    fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2270
93.5k
    if (fmt[0] == 'Z' && fmt[1] && fmt[2] == '\0')
2271
0
        return fmt;
2272
93.5k
    if (fmt[0] && fmt[1] == '\0')
2273
93.5k
        return fmt;
2274
2275
0
    PyErr_Format(PyExc_NotImplementedError,
2276
0
        "memoryview: unsupported format %s", view->format);
2277
0
    return NULL;
2278
93.5k
}
2279
2280
/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2281
static PyObject *
2282
tolist_base(PyMemoryViewObject *self, const char *ptr, const Py_ssize_t *shape,
2283
            const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2284
            const char *fmt)
2285
62.7k
{
2286
62.7k
    PyObject *lst, *item;
2287
62.7k
    Py_ssize_t i;
2288
2289
62.7k
    lst = PyList_New(shape[0]);
2290
62.7k
    if (lst == NULL)
2291
0
        return NULL;
2292
2293
4.07M
    for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
2294
4.01M
        const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
2295
4.01M
        item = unpack_single(self, xptr, fmt);
2296
4.01M
        if (item == NULL) {
2297
0
            Py_DECREF(lst);
2298
0
            return NULL;
2299
0
        }
2300
4.01M
        PyList_SET_ITEM(lst, i, item);
2301
4.01M
    }
2302
2303
62.7k
    return lst;
2304
62.7k
}
2305
2306
/* Unpack a multi-dimensional array into a nested list.
2307
   Assumption: ndim >= 1. */
2308
static PyObject *
2309
tolist_rec(PyMemoryViewObject *self, const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2310
           const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2311
           const char *fmt)
2312
0
{
2313
0
    PyObject *lst, *item;
2314
0
    Py_ssize_t i;
2315
2316
0
    assert(ndim >= 1);
2317
0
    assert(shape != NULL);
2318
0
    assert(strides != NULL);
2319
2320
0
    if (ndim == 1)
2321
0
        return tolist_base(self, ptr, shape, strides, suboffsets, fmt);
2322
2323
0
    lst = PyList_New(shape[0]);
2324
0
    if (lst == NULL)
2325
0
        return NULL;
2326
2327
0
    for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
2328
0
        const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
2329
0
        item = tolist_rec(self, xptr, ndim-1, shape+1,
2330
0
                          strides+1, suboffsets ? suboffsets+1 : NULL,
2331
0
                          fmt);
2332
0
        if (item == NULL) {
2333
0
            Py_DECREF(lst);
2334
0
            return NULL;
2335
0
        }
2336
0
        PyList_SET_ITEM(lst, i, item);
2337
0
    }
2338
2339
0
    return lst;
2340
0
}
2341
2342
/* Return a list representation of the memoryview. Currently only buffers
2343
   with native format strings are supported. */
2344
/*[clinic input]
2345
memoryview.tolist
2346
2347
Return the data in the buffer as a list of elements.
2348
[clinic start generated code]*/
2349
2350
static PyObject *
2351
memoryview_tolist_impl(PyMemoryViewObject *self)
2352
/*[clinic end generated code: output=a6cda89214fd5a1b input=21e7d0c1860b211a]*/
2353
62.7k
{
2354
62.7k
    const Py_buffer *view = &self->view;
2355
62.7k
    const char *fmt;
2356
2357
62.7k
    CHECK_RELEASED(self);
2358
2359
62.7k
    fmt = adjust_fmt(view);
2360
62.7k
    if (fmt == NULL)
2361
0
        return NULL;
2362
62.7k
    if (view->ndim == 0) {
2363
0
        return unpack_single(self, view->buf, fmt);
2364
0
    }
2365
62.7k
    else if (view->ndim == 1) {
2366
62.7k
        return tolist_base(self, view->buf, view->shape,
2367
62.7k
                           view->strides, view->suboffsets,
2368
62.7k
                           fmt);
2369
62.7k
    }
2370
0
    else {
2371
0
        return tolist_rec(self, view->buf, view->ndim, view->shape,
2372
0
                          view->strides, view->suboffsets,
2373
0
                          fmt);
2374
0
    }
2375
62.7k
}
2376
2377
/*[clinic input]
2378
memoryview.tobytes
2379
2380
    order: str(accept={str, NoneType}, c_default="NULL") = 'C'
2381
2382
Return the data in the buffer as a byte string.
2383
2384
Order can be {'C', 'F', 'A'}.  When order is 'C' or 'F', the data of
2385
the original array is converted to C or Fortran order.  For
2386
contiguous views, 'A' returns an exact copy of the physical memory.
2387
In particular, in-memory Fortran order is preserved.  For
2388
non-contiguous views, the data is converted to C first.  order=None
2389
is the same as order='C'.
2390
[clinic start generated code]*/
2391
2392
static PyObject *
2393
memoryview_tobytes_impl(PyMemoryViewObject *self, const char *order)
2394
/*[clinic end generated code: output=1288b62560a32a23 input=119c70aa91791dc8]*/
2395
0
{
2396
0
    Py_buffer *src = VIEW_ADDR(self);
2397
0
    char ord = 'C';
2398
2399
0
    CHECK_RELEASED(self);
2400
2401
0
    if (order) {
2402
0
        if (strcmp(order, "F") == 0) {
2403
0
            ord = 'F';
2404
0
        }
2405
0
        else if (strcmp(order, "A") == 0) {
2406
0
            ord = 'A';
2407
0
        }
2408
0
        else if (strcmp(order, "C") != 0) {
2409
0
            PyErr_SetString(PyExc_ValueError,
2410
0
                "order must be 'C', 'F' or 'A'");
2411
0
            return NULL;
2412
0
        }
2413
0
    }
2414
2415
0
    PyBytesWriter *writer = PyBytesWriter_Create(src->len);
2416
0
    if (writer == NULL) {
2417
0
        return NULL;
2418
0
    }
2419
2420
0
    if (PyBuffer_ToContiguous(PyBytesWriter_GetData(writer),
2421
0
                              src, src->len, ord) < 0) {
2422
0
        PyBytesWriter_Discard(writer);
2423
0
        return NULL;
2424
0
    }
2425
2426
0
    return PyBytesWriter_Finish(writer);
2427
0
}
2428
2429
/*[clinic input]
2430
memoryview.hex
2431
2432
    sep: object = NULL
2433
        An optional single character or byte to separate hex bytes.
2434
    bytes_per_sep: Py_ssize_t = 1
2435
        How many bytes between separators.  Positive values count from
2436
        the right, negative values count from the left.
2437
2438
Return the data in the buffer as a str of hexadecimal numbers.
2439
2440
Example:
2441
>>> value = memoryview(b'\xb9\x01\xef')
2442
>>> value.hex()
2443
'b901ef'
2444
>>> value.hex(':')
2445
'b9:01:ef'
2446
>>> value.hex(':', 2)
2447
'b9:01ef'
2448
>>> value.hex(':', -2)
2449
'b901:ef'
2450
[clinic start generated code]*/
2451
2452
static PyObject *
2453
memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep,
2454
                    Py_ssize_t bytes_per_sep)
2455
/*[clinic end generated code: output=c9bb00c7a8e86056 input=3f1c5d08906e3b70]*/
2456
0
{
2457
0
    Py_buffer *src = VIEW_ADDR(self);
2458
2459
0
    CHECK_RELEASED(self);
2460
2461
0
    if (MV_C_CONTIGUOUS(self->flags)) {
2462
        // Prevent 'self' from being freed if computing len(sep) mutates 'self'
2463
        // in _Py_strhex_with_sep().
2464
        // See: https://github.com/python/cpython/issues/143195.
2465
0
        FT_ATOMIC_ADD_SSIZE(self->exports, 1);
2466
0
        PyObject *ret = _Py_strhex_with_sep(src->buf, src->len, sep, bytes_per_sep);
2467
0
        FT_ATOMIC_ADD_SSIZE(self->exports, -1);
2468
0
        return ret;
2469
0
    }
2470
2471
0
    char *buffer = PyMem_Malloc(src->len);
2472
0
    if (buffer == NULL) {
2473
0
        PyErr_NoMemory();
2474
0
        return NULL;
2475
0
    }
2476
2477
0
    if (PyBuffer_ToContiguous(buffer, src, src->len, 'C') < 0) {
2478
0
        PyMem_Free(buffer);
2479
0
        return NULL;
2480
0
    }
2481
2482
0
    PyObject *ret = _Py_strhex_with_sep(buffer, src->len, sep, bytes_per_sep);
2483
0
    PyMem_Free(buffer);
2484
2485
0
    return ret;
2486
0
}
2487
2488
static PyObject *
2489
memory_repr(PyObject *_self)
2490
0
{
2491
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
2492
0
    if (self->flags & _Py_MEMORYVIEW_RELEASED)
2493
0
        return PyUnicode_FromFormat("<released memory at %p>", self);
2494
0
    else
2495
0
        return PyUnicode_FromFormat("<memory at %p>", self);
2496
0
}
2497
2498
2499
/**************************************************************************/
2500
/*                          Indexing and slicing                          */
2501
/**************************************************************************/
2502
2503
static char *
2504
lookup_dimension(const Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
2505
0
{
2506
0
    Py_ssize_t nitems; /* items in the given dimension */
2507
2508
0
    assert(view->shape);
2509
0
    assert(view->strides);
2510
2511
0
    nitems = view->shape[dim];
2512
0
    if (index < 0) {
2513
0
        index += nitems;
2514
0
    }
2515
0
    if (index < 0 || index >= nitems) {
2516
0
        PyErr_Format(PyExc_IndexError,
2517
0
                     "index out of bounds on dimension %d", dim + 1);
2518
0
        return NULL;
2519
0
    }
2520
2521
0
    ptr += view->strides[dim] * index;
2522
2523
0
    ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
2524
2525
0
    return ptr;
2526
0
}
2527
2528
/* Get the pointer to the item at index. */
2529
static char *
2530
ptr_from_index(const Py_buffer *view, Py_ssize_t index)
2531
0
{
2532
0
    char *ptr = (char *)view->buf;
2533
0
    return lookup_dimension(view, ptr, 0, index);
2534
0
}
2535
2536
/* Get the pointer to the item at tuple. */
2537
static char *
2538
ptr_from_tuple(const Py_buffer *view, PyObject *tup)
2539
0
{
2540
0
    char *ptr = (char *)view->buf;
2541
0
    Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2542
2543
0
    if (nindices > view->ndim) {
2544
0
        PyErr_Format(PyExc_TypeError,
2545
0
                     "cannot index %d-dimension view with %zd-element tuple",
2546
0
                     view->ndim, nindices);
2547
0
        return NULL;
2548
0
    }
2549
2550
0
    for (dim = 0; dim < nindices; dim++) {
2551
0
        Py_ssize_t index;
2552
0
        index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2553
0
                                   PyExc_IndexError);
2554
0
        if (index == -1 && PyErr_Occurred())
2555
0
            return NULL;
2556
0
        ptr = lookup_dimension(view, ptr, (int)dim, index);
2557
0
        if (ptr == NULL)
2558
0
            return NULL;
2559
0
    }
2560
0
    return ptr;
2561
0
}
2562
2563
/* Return the item at index. In a one-dimensional view, this is an object
2564
   with the type specified by view->format. Otherwise, the item is a sub-view.
2565
   The function is used in memory_subscript() and memory_as_sequence. */
2566
static PyObject *
2567
memory_item(PyObject *_self, Py_ssize_t index)
2568
0
{
2569
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
2570
0
    Py_buffer *view = &(self->view);
2571
0
    const char *fmt;
2572
2573
0
    CHECK_RELEASED(self);
2574
2575
0
    fmt = adjust_fmt(view);
2576
0
    if (fmt == NULL)
2577
0
        return NULL;
2578
2579
0
    if (view->ndim == 0) {
2580
0
        PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2581
0
        return NULL;
2582
0
    }
2583
0
    if (view->ndim == 1) {
2584
0
        char *ptr = ptr_from_index(view, index);
2585
0
        if (ptr == NULL)
2586
0
            return NULL;
2587
0
        return unpack_single(self, ptr, fmt);
2588
0
    }
2589
2590
0
    PyErr_SetString(PyExc_NotImplementedError,
2591
0
        "multi-dimensional sub-views are not implemented");
2592
0
    return NULL;
2593
0
}
2594
2595
/* Return the item at position *key* (a tuple of indices). */
2596
static PyObject *
2597
memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2598
0
{
2599
0
    Py_buffer *view = &(self->view);
2600
0
    const char *fmt;
2601
0
    Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2602
0
    char *ptr;
2603
2604
0
    CHECK_RELEASED(self);
2605
2606
0
    fmt = adjust_fmt(view);
2607
0
    if (fmt == NULL)
2608
0
        return NULL;
2609
2610
0
    if (nindices < view->ndim) {
2611
0
        PyErr_SetString(PyExc_NotImplementedError,
2612
0
                        "sub-views are not implemented");
2613
0
        return NULL;
2614
0
    }
2615
0
    ptr = ptr_from_tuple(view, tup);
2616
0
    if (ptr == NULL)
2617
0
        return NULL;
2618
0
    return unpack_single(self, ptr, fmt);
2619
0
}
2620
2621
static inline int
2622
init_slice(Py_buffer *base, PyObject *key, int dim)
2623
36.3k
{
2624
36.3k
    Py_ssize_t start, stop, step, slicelength;
2625
2626
36.3k
    if (PySlice_Unpack(key, &start, &stop, &step) < 0) {
2627
0
        return -1;
2628
0
    }
2629
36.3k
    slicelength = PySlice_AdjustIndices(base->shape[dim], &start, &stop, step);
2630
2631
2632
36.3k
    if (base->suboffsets == NULL || dim == 0) {
2633
36.3k
    adjust_buf:
2634
36.3k
        base->buf = (char *)base->buf + base->strides[dim] * start;
2635
36.3k
    }
2636
0
    else {
2637
0
        Py_ssize_t n = dim-1;
2638
0
        while (n >= 0 && base->suboffsets[n] < 0)
2639
0
            n--;
2640
0
        if (n < 0)
2641
0
            goto adjust_buf; /* all suboffsets are negative */
2642
0
        base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2643
0
    }
2644
36.3k
    base->shape[dim] = slicelength;
2645
36.3k
    base->strides[dim] = base->strides[dim] * step;
2646
2647
36.3k
    return 0;
2648
36.3k
}
2649
2650
static int
2651
is_multislice(PyObject *key)
2652
0
{
2653
0
    Py_ssize_t size, i;
2654
2655
0
    if (!PyTuple_Check(key))
2656
0
        return 0;
2657
0
    size = PyTuple_GET_SIZE(key);
2658
0
    if (size == 0)
2659
0
        return 0;
2660
2661
0
    for (i = 0; i < size; i++) {
2662
0
        PyObject *x = PyTuple_GET_ITEM(key, i);
2663
0
        if (!PySlice_Check(x))
2664
0
            return 0;
2665
0
    }
2666
0
    return 1;
2667
0
}
2668
2669
static Py_ssize_t
2670
is_multiindex(PyObject *key)
2671
0
{
2672
0
    Py_ssize_t size, i;
2673
2674
0
    if (!PyTuple_Check(key))
2675
0
        return 0;
2676
0
    size = PyTuple_GET_SIZE(key);
2677
0
    for (i = 0; i < size; i++) {
2678
0
        PyObject *x = PyTuple_GET_ITEM(key, i);
2679
0
        if (!_PyIndex_Check(x)) {
2680
0
            return 0;
2681
0
        }
2682
0
    }
2683
0
    return 1;
2684
0
}
2685
2686
/* mv[obj] returns an object holding the data for one element if obj
2687
   fully indexes the memoryview or another memoryview object if it
2688
   does not.
2689
2690
   0-d memoryview objects can be referenced using mv[...] or mv[()]
2691
   but not with anything else. */
2692
static PyObject *
2693
memory_subscript(PyObject *_self, PyObject *key)
2694
5.48k
{
2695
5.48k
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
2696
5.48k
    Py_buffer *view;
2697
5.48k
    view = &(self->view);
2698
2699
5.48k
    CHECK_RELEASED(self);
2700
2701
5.48k
    if (view->ndim == 0) {
2702
0
        if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2703
0
            const char *fmt = adjust_fmt(view);
2704
0
            if (fmt == NULL)
2705
0
                return NULL;
2706
0
            return unpack_single(self, view->buf, fmt);
2707
0
        }
2708
0
        else if (key == Py_Ellipsis) {
2709
0
            return Py_NewRef(self);
2710
0
        }
2711
0
        else {
2712
0
            PyErr_SetString(PyExc_TypeError,
2713
0
                "invalid indexing of 0-dim memory");
2714
0
            return NULL;
2715
0
        }
2716
0
    }
2717
2718
5.48k
    if (_PyIndex_Check(key)) {
2719
0
        Py_ssize_t index;
2720
0
        index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2721
0
        if (index == -1 && PyErr_Occurred())
2722
0
            return NULL;
2723
0
        return memory_item((PyObject *)self, index);
2724
0
    }
2725
5.48k
    else if (PySlice_Check(key)) {
2726
5.48k
        CHECK_RESTRICTED(self);
2727
5.48k
        PyMemoryViewObject *sliced;
2728
2729
5.48k
        sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2730
5.48k
        if (sliced == NULL)
2731
0
            return NULL;
2732
2733
5.48k
        if (init_slice(&sliced->view, key, 0) < 0) {
2734
0
            Py_DECREF(sliced);
2735
0
            return NULL;
2736
0
        }
2737
5.48k
        init_len(&sliced->view);
2738
5.48k
        init_flags(sliced);
2739
2740
5.48k
        return (PyObject *)sliced;
2741
5.48k
    }
2742
0
    else if (is_multiindex(key)) {
2743
0
        return memory_item_multi(self, key);
2744
0
    }
2745
0
    else if (is_multislice(key)) {
2746
0
        PyErr_SetString(PyExc_NotImplementedError,
2747
0
            "multi-dimensional slicing is not implemented");
2748
0
        return NULL;
2749
0
    }
2750
2751
0
    PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2752
0
    return NULL;
2753
5.48k
}
2754
2755
static int
2756
memory_ass_sub(PyObject *_self, PyObject *key, PyObject *value)
2757
30.8k
{
2758
30.8k
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
2759
30.8k
    Py_buffer *view = &(self->view);
2760
30.8k
    Py_buffer src;
2761
30.8k
    const char *fmt;
2762
30.8k
    char *ptr;
2763
2764
30.8k
    CHECK_RELEASED_INT(self);
2765
2766
30.8k
    fmt = adjust_fmt(view);
2767
30.8k
    if (fmt == NULL)
2768
0
        return -1;
2769
2770
30.8k
    if (view->readonly) {
2771
0
        PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2772
0
        return -1;
2773
0
    }
2774
30.8k
    if (value == NULL) {
2775
0
        PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2776
0
        return -1;
2777
0
    }
2778
30.8k
    if (view->ndim == 0) {
2779
0
        if (key == Py_Ellipsis ||
2780
0
            (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2781
0
            ptr = (char *)view->buf;
2782
0
            return pack_single(self, ptr, value, fmt);
2783
0
        }
2784
0
        else {
2785
0
            PyErr_SetString(PyExc_TypeError,
2786
0
                "invalid indexing of 0-dim memory");
2787
0
            return -1;
2788
0
        }
2789
0
    }
2790
2791
30.8k
    if (_PyIndex_Check(key)) {
2792
0
        Py_ssize_t index;
2793
0
        if (1 < view->ndim) {
2794
0
            PyErr_SetString(PyExc_NotImplementedError,
2795
0
                            "sub-views are not implemented");
2796
0
            return -1;
2797
0
        }
2798
0
        index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2799
0
        if (index == -1 && PyErr_Occurred())
2800
0
            return -1;
2801
0
        ptr = ptr_from_index(view, index);
2802
0
        if (ptr == NULL)
2803
0
            return -1;
2804
0
        return pack_single(self, ptr, value, fmt);
2805
0
    }
2806
    /* one-dimensional: fast path */
2807
30.8k
    if (PySlice_Check(key) && view->ndim == 1) {
2808
30.8k
        Py_buffer dest; /* sliced view */
2809
30.8k
        Py_ssize_t arrays[3];
2810
30.8k
        int ret = -1;
2811
2812
        /* rvalue must be an exporter */
2813
30.8k
        if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2814
0
            return ret;
2815
2816
30.8k
        dest = *view;
2817
30.8k
        dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2818
30.8k
        dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2819
30.8k
        if (view->suboffsets) {
2820
0
            dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2821
0
        }
2822
2823
30.8k
        if (init_slice(&dest, key, 0) < 0)
2824
0
            goto end_block;
2825
30.8k
        dest.len = dest.shape[0] * dest.itemsize;
2826
2827
30.8k
        ret = copy_single(self, &dest, &src);
2828
2829
30.8k
    end_block:
2830
30.8k
        PyBuffer_Release(&src);
2831
30.8k
        return ret;
2832
30.8k
    }
2833
0
    if (is_multiindex(key)) {
2834
0
        char *ptr;
2835
0
        if (PyTuple_GET_SIZE(key) < view->ndim) {
2836
0
            PyErr_SetString(PyExc_NotImplementedError,
2837
0
                            "sub-views are not implemented");
2838
0
            return -1;
2839
0
        }
2840
0
        ptr = ptr_from_tuple(view, key);
2841
0
        if (ptr == NULL)
2842
0
            return -1;
2843
0
        return pack_single(self, ptr, value, fmt);
2844
0
    }
2845
0
    if (PySlice_Check(key) || is_multislice(key)) {
2846
        /* Call memory_subscript() to produce a sliced lvalue, then copy
2847
           rvalue into lvalue. This is already implemented in _testbuffer.c. */
2848
0
        PyErr_SetString(PyExc_NotImplementedError,
2849
0
            "memoryview slice assignments are currently restricted "
2850
0
            "to ndim = 1");
2851
0
        return -1;
2852
0
    }
2853
2854
0
    PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2855
0
    return -1;
2856
0
}
2857
2858
static Py_ssize_t
2859
memory_length(PyObject *_self)
2860
1.48M
{
2861
1.48M
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
2862
1.48M
    CHECK_RELEASED_INT(self);
2863
1.48M
    if (self->view.ndim == 0) {
2864
0
        PyErr_SetString(PyExc_TypeError, "0-dim memory has no length");
2865
0
        return -1;
2866
0
    }
2867
1.48M
    return self->view.shape[0];
2868
1.48M
}
2869
2870
/* As mapping */
2871
static PyMappingMethods memory_as_mapping = {
2872
    memory_length,                        /* mp_length */
2873
    memory_subscript,                     /* mp_subscript */
2874
    memory_ass_sub,                       /* mp_ass_subscript */
2875
};
2876
2877
/* As sequence */
2878
static PySequenceMethods memory_as_sequence = {
2879
        memory_length,                    /* sq_length */
2880
        0,                                /* sq_concat */
2881
        0,                                /* sq_repeat */
2882
        memory_item,                      /* sq_item */
2883
};
2884
2885
2886
/****************************************************************************/
2887
/*                              Counting                                    */
2888
/****************************************************************************/
2889
2890
/*[clinic input]
2891
memoryview.count
2892
2893
    value: object
2894
    /
2895
2896
Count the number of occurrences of a value.
2897
[clinic start generated code]*/
2898
2899
static PyObject *
2900
memoryview_count_impl(PyMemoryViewObject *self, PyObject *value)
2901
/*[clinic end generated code: output=a15cb19311985063 input=e3036ce1ed7d1823]*/
2902
0
{
2903
0
    PyObject *iter = PyObject_GetIter(_PyObject_CAST(self));
2904
0
    if (iter == NULL) {
2905
0
        return NULL;
2906
0
    }
2907
2908
0
    Py_ssize_t count = 0;
2909
0
    PyObject *item = NULL;
2910
0
    while (PyIter_NextItem(iter, &item)) {
2911
0
        if (item == NULL) {
2912
0
            Py_DECREF(iter);
2913
0
            return NULL;
2914
0
        }
2915
0
        if (item == value) {
2916
0
            Py_DECREF(item);
2917
0
            count++;  // no overflow since count <= len(mv) <= PY_SSIZE_T_MAX
2918
0
            continue;
2919
0
        }
2920
0
        int contained = PyObject_RichCompareBool(item, value, Py_EQ);
2921
0
        Py_DECREF(item);
2922
0
        if (contained > 0) { // more likely than 'contained < 0'
2923
0
            count++;  // no overflow since count <= len(mv) <= PY_SSIZE_T_MAX
2924
0
        }
2925
0
        else if (contained < 0) {
2926
0
            Py_DECREF(iter);
2927
0
            return NULL;
2928
0
        }
2929
0
    }
2930
0
    Py_DECREF(iter);
2931
0
    return PyLong_FromSsize_t(count);
2932
0
}
2933
2934
2935
/**************************************************************************/
2936
/*                             Lookup                                     */
2937
/**************************************************************************/
2938
2939
/*[clinic input]
2940
memoryview.index
2941
2942
    value: object
2943
    start: slice_index(accept={int}) = 0
2944
    stop: slice_index(accept={int}, c_default="PY_SSIZE_T_MAX") = sys.maxsize
2945
    /
2946
2947
Return the index of the first occurrence of a value.
2948
2949
Raises ValueError if the value is not present.
2950
[clinic start generated code]*/
2951
2952
static PyObject *
2953
memoryview_index_impl(PyMemoryViewObject *self, PyObject *value,
2954
                      Py_ssize_t start, Py_ssize_t stop)
2955
/*[clinic end generated code: output=e0185e3819e549df input=0697a0165bf90b5a]*/
2956
0
{
2957
0
    const Py_buffer *view = &self->view;
2958
0
    CHECK_RELEASED(self);
2959
2960
0
    if (view->ndim == 0) {
2961
0
        PyErr_SetString(PyExc_TypeError, "invalid lookup on 0-dim memory");
2962
0
        return NULL;
2963
0
    }
2964
2965
0
    if (view->ndim == 1) {
2966
0
        Py_ssize_t n = view->shape[0];
2967
2968
0
        if (start < 0) {
2969
0
            start = Py_MAX(start + n, 0);
2970
0
        }
2971
2972
0
        if (stop < 0) {
2973
0
            stop = Py_MAX(stop + n, 0);
2974
0
        }
2975
2976
0
        stop = Py_MIN(stop, n);
2977
0
        assert(stop >= 0);
2978
0
        assert(stop <= n);
2979
2980
0
        start = Py_MIN(start, stop);
2981
0
        assert(0 <= start);
2982
0
        assert(start <= stop);
2983
2984
0
        PyObject *obj = _PyObject_CAST(self);
2985
0
        for (Py_ssize_t index = start; index < stop; index++) {
2986
            // Note: while memoryviews can be mutated during iterations
2987
            // when calling the == operator, their shape cannot. As such,
2988
            // it is safe to assume that the index remains valid for the
2989
            // entire loop.
2990
0
            assert(index < n);
2991
2992
0
            PyObject *item = memory_item(obj, index);
2993
0
            if (item == NULL) {
2994
0
                return NULL;
2995
0
            }
2996
0
            if (item == value) {
2997
0
                Py_DECREF(item);
2998
0
                return PyLong_FromSsize_t(index);
2999
0
            }
3000
0
            int contained = PyObject_RichCompareBool(item, value, Py_EQ);
3001
0
            Py_DECREF(item);
3002
0
            if (contained > 0) {  // more likely than 'contained < 0'
3003
0
                return PyLong_FromSsize_t(index);
3004
0
            }
3005
0
            else if (contained < 0) {
3006
0
                return NULL;
3007
0
            }
3008
0
        }
3009
3010
0
        PyErr_SetString(PyExc_ValueError, "memoryview.index(x): x not found");
3011
0
        return NULL;
3012
0
    }
3013
3014
0
    PyErr_SetString(PyExc_NotImplementedError,
3015
0
                    "multi-dimensional lookup is not implemented");
3016
0
    return NULL;
3017
3018
0
}
3019
3020
3021
/**************************************************************************/
3022
/*                             Comparisons                                */
3023
/**************************************************************************/
3024
3025
0
#define MV_COMPARE_EX -1       /* exception */
3026
108
#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
3027
3028
/* Translate a StructError to "not equal". Preserve other exceptions. */
3029
static int
3030
fix_struct_error_int(void)
3031
0
{
3032
0
    assert(PyErr_Occurred());
3033
    /* XXX Cannot get at StructError directly? */
3034
0
    if (PyErr_ExceptionMatches(PyExc_ImportError) ||
3035
0
        PyErr_ExceptionMatches(PyExc_MemoryError)) {
3036
0
        return MV_COMPARE_EX;
3037
0
    }
3038
    /* StructError: invalid or unknown format -> not equal */
3039
0
    PyErr_Clear();
3040
0
    return 0;
3041
0
}
3042
3043
/* Unpack and compare single items of p and q using the struct module. */
3044
static int
3045
struct_unpack_cmp(const char *p, const char *q,
3046
                  struct unpacker *unpack_p, struct unpacker *unpack_q)
3047
0
{
3048
0
    PyObject *v, *w;
3049
0
    int ret;
3050
3051
    /* At this point any exception from the struct module should not be
3052
       StructError, since both formats have been accepted already. */
3053
0
    v = struct_unpack_single(p, unpack_p);
3054
0
    if (v == NULL)
3055
0
        return MV_COMPARE_EX;
3056
3057
0
    w = struct_unpack_single(q, unpack_q);
3058
0
    if (w == NULL) {
3059
0
        Py_DECREF(v);
3060
0
        return MV_COMPARE_EX;
3061
0
    }
3062
3063
    /* MV_COMPARE_EX == -1: exceptions are preserved */
3064
0
    ret = PyObject_RichCompareBool(v, w, Py_EQ);
3065
0
    Py_DECREF(v);
3066
0
    Py_DECREF(w);
3067
3068
0
    return ret;
3069
0
}
3070
3071
/* Unpack and compare single items of p and q. If both p and q have the same
3072
   single element native format, the comparison uses a fast path (gcc creates
3073
   a jump table and converts memcpy into simple assignments on x86/x64).
3074
3075
   Otherwise, the comparison is delegated to the struct module, which is
3076
   30-60x slower. */
3077
#define CMP_SINGLE(p, q, type) \
3078
0
    do {                                 \
3079
0
        type x;                          \
3080
0
        type y;                          \
3081
0
        memcpy((char *)&x, p, sizeof x); \
3082
0
        memcpy((char *)&y, q, sizeof y); \
3083
0
        equal = (x == y);                \
3084
0
    } while (0)
3085
3086
static inline int
3087
unpack_cmp(const char *p, const char *q, const char *fmt,
3088
           struct unpacker *unpack_p, struct unpacker *unpack_q)
3089
88
{
3090
88
    int equal;
3091
3092
88
    switch (fmt[0]) {
3093
3094
    /* signed integers and fast path for 'B' */
3095
88
    case 'B': return *((const unsigned char *)p) == *((const unsigned char *)q);
3096
0
    case 'b': return *((const signed char *)p) == *((const signed char *)q);
3097
0
    case 'h': CMP_SINGLE(p, q, short); return equal;
3098
0
    case 'i': CMP_SINGLE(p, q, int); return equal;
3099
0
    case 'l': CMP_SINGLE(p, q, long); return equal;
3100
3101
    /* boolean */
3102
0
    case '?': return UNPACK_TO_BOOL(p) == UNPACK_TO_BOOL(q);
3103
3104
    /* unsigned integers */
3105
0
    case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
3106
0
    case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
3107
0
    case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
3108
3109
    /* native 64-bit */
3110
0
    case 'q': CMP_SINGLE(p, q, long long); return equal;
3111
0
    case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
3112
3113
    /* ssize_t and size_t */
3114
0
    case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
3115
0
    case 'N': CMP_SINGLE(p, q, size_t); return equal;
3116
3117
    /* floats */
3118
    /* XXX DBL_EPSILON? */
3119
0
    case 'f': CMP_SINGLE(p, q, float); return equal;
3120
0
    case 'd': CMP_SINGLE(p, q, double); return equal;
3121
0
    case 'e': {
3122
0
#if PY_LITTLE_ENDIAN
3123
0
        int endian = 1;
3124
#else
3125
        int endian = 0;
3126
#endif
3127
        /* Note: PyFloat_Unpack2 should never fail */
3128
0
        double u = PyFloat_Unpack2(p, endian);
3129
0
        double v = PyFloat_Unpack2(q, endian);
3130
0
        return (u == v);
3131
0
    }
3132
3133
    /* complexes */
3134
0
    case 'Z': {
3135
0
        switch (fmt[1]) {
3136
0
        case 'f':
3137
0
        {
3138
0
             float x[2], y[2];
3139
3140
0
             memcpy(&x, p, sizeof(x));
3141
0
             memcpy(&y, q, sizeof(y));
3142
0
             return (x[0] == y[0]) && (x[1] == y[1]);
3143
0
        }
3144
0
        case 'd':
3145
0
        {
3146
0
             double x[2], y[2];
3147
3148
0
             memcpy(&x, p, sizeof(x));
3149
0
             memcpy(&y, q, sizeof(y));
3150
0
             return (x[0] == y[0]) && (x[1] == y[1]);
3151
0
        }
3152
0
        }
3153
0
        break;
3154
0
    }
3155
3156
    /* bytes object */
3157
0
    case 'c': return *p == *q;
3158
3159
    /* pointer */
3160
0
    case 'P': CMP_SINGLE(p, q, void *); return equal;
3161
3162
    /* use the struct module */
3163
0
    case '_':
3164
0
        assert(unpack_p);
3165
0
        assert(unpack_q);
3166
0
        return struct_unpack_cmp(p, q, unpack_p, unpack_q);
3167
88
    }
3168
3169
    /* NOT REACHED */
3170
0
    PyErr_SetString(PyExc_RuntimeError,
3171
0
        "memoryview: internal error in richcompare");
3172
0
    return MV_COMPARE_EX;
3173
88
}
3174
3175
/* Base case for recursive array comparisons. Assumption: ndim == 1. */
3176
static int
3177
cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
3178
         const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
3179
         const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
3180
         const char *fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
3181
83
{
3182
83
    Py_ssize_t i;
3183
83
    int equal;
3184
3185
89
    for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
3186
88
        const char *xp = ADJUST_PTR(p, psuboffsets, 0);
3187
88
        const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
3188
88
        equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
3189
88
        if (equal <= 0)
3190
82
            return equal;
3191
88
    }
3192
3193
1
    return 1;
3194
83
}
3195
3196
/* Recursively compare two multi-dimensional arrays that have the same
3197
   logical structure. Assumption: ndim >= 1. */
3198
static int
3199
cmp_rec(const char *p, const char *q,
3200
        Py_ssize_t ndim, const Py_ssize_t *shape,
3201
        const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
3202
        const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
3203
        const char *fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
3204
0
{
3205
0
    Py_ssize_t i;
3206
0
    int equal;
3207
3208
0
    assert(ndim >= 1);
3209
0
    assert(shape != NULL);
3210
0
    assert(pstrides != NULL);
3211
0
    assert(qstrides != NULL);
3212
3213
0
    if (ndim == 1) {
3214
0
        return cmp_base(p, q, shape,
3215
0
                        pstrides, psuboffsets,
3216
0
                        qstrides, qsuboffsets,
3217
0
                        fmt, unpack_p, unpack_q);
3218
0
    }
3219
3220
0
    for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
3221
0
        const char *xp = ADJUST_PTR(p, psuboffsets, 0);
3222
0
        const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
3223
0
        equal = cmp_rec(xp, xq, ndim-1, shape+1,
3224
0
                        pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
3225
0
                        qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
3226
0
                        fmt, unpack_p, unpack_q);
3227
0
        if (equal <= 0)
3228
0
            return equal;
3229
0
    }
3230
3231
0
    return 1;
3232
0
}
3233
3234
static PyObject *
3235
memory_richcompare(PyObject *v, PyObject *w, int op)
3236
108
{
3237
108
    PyObject *res;
3238
108
    Py_buffer wbuf, *vv;
3239
108
    Py_buffer *ww = NULL;
3240
108
    struct unpacker *unpack_v = NULL;
3241
108
    struct unpacker *unpack_w = NULL;
3242
108
    const char *vfmt, *wfmt;
3243
108
    int equal = MV_COMPARE_NOT_IMPL;
3244
3245
108
    if (op != Py_EQ && op != Py_NE)
3246
0
        goto result; /* Py_NotImplemented */
3247
3248
108
    assert(PyMemoryView_Check(v));
3249
108
    if (BASE_INACCESSIBLE(v)) {
3250
0
        equal = (v == w);
3251
0
        goto result;
3252
0
    }
3253
108
    vv = VIEW_ADDR(v);
3254
3255
    // For formats supported by the struct module a memoryview is equal to
3256
    // itself: there is no need to compare individual values.
3257
    // This is not true for float values since they can be NaN, and NaN
3258
    // is not equal to itself.  So only use this optimization on format known to
3259
    // not use floats.
3260
108
    if (v == w) {
3261
0
        const char *format = vv->format;
3262
0
        if (format != NULL) {
3263
0
            if (*format == '@') {
3264
0
                format++;
3265
0
            }
3266
            // Include only formats known by struct, exclude float formats
3267
            // "d" (double), "f" (float) and "e" (16-bit float).
3268
            // Do not optimize "P" format.
3269
0
            if (format[0] != 0
3270
0
                && strchr("bBchHiIlLnNqQ?", format[0]) != NULL
3271
0
                && format[1] == 0)
3272
0
            {
3273
0
                equal = 1;
3274
0
                goto result;
3275
0
            }
3276
0
        }
3277
0
    }
3278
3279
108
    if (PyMemoryView_Check(w)) {
3280
0
        if (BASE_INACCESSIBLE(w)) {
3281
0
            equal = (v == w);
3282
0
            goto result;
3283
0
        }
3284
0
        ww = VIEW_ADDR(w);
3285
0
    }
3286
108
    else {
3287
108
        if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
3288
0
            PyErr_Clear();
3289
0
            goto result; /* Py_NotImplemented */
3290
0
        }
3291
108
        ww = &wbuf;
3292
108
    }
3293
3294
108
    if (!equiv_shape(vv, ww)) {
3295
25
        PyErr_Clear();
3296
25
        equal = 0;
3297
25
        goto result;
3298
25
    }
3299
3300
    /* Use fast unpacking for identical primitive C type formats. */
3301
83
    if (get_native_fmtchar(&vfmt, vv->format) < 0)
3302
0
        vfmt = "_";
3303
83
    if (get_native_fmtchar(&wfmt, ww->format) < 0)
3304
0
        wfmt = "_";
3305
83
    if (strcmp(vfmt, "_") == 0 || strcmp(wfmt, "_") == 0 || strcmp(vfmt, wfmt) != 0) {
3306
        /* Use struct module unpacking. NOTE: Even for equal format strings,
3307
           memcmp() cannot be used for item comparison since it would give
3308
           incorrect results in the case of NaNs or uninitialized padding
3309
           bytes. */
3310
0
        vfmt = "_";
3311
0
        unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
3312
0
        if (unpack_v == NULL) {
3313
0
            equal = fix_struct_error_int();
3314
0
            goto result;
3315
0
        }
3316
0
        unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
3317
0
        if (unpack_w == NULL) {
3318
0
            equal = fix_struct_error_int();
3319
0
            goto result;
3320
0
        }
3321
0
    }
3322
3323
83
    if (vv->ndim == 0) {
3324
0
        equal = unpack_cmp(vv->buf, ww->buf,
3325
0
                           vfmt, unpack_v, unpack_w);
3326
0
    }
3327
83
    else if (vv->ndim == 1) {
3328
83
        equal = cmp_base(vv->buf, ww->buf, vv->shape,
3329
83
                         vv->strides, vv->suboffsets,
3330
83
                         ww->strides, ww->suboffsets,
3331
83
                         vfmt, unpack_v, unpack_w);
3332
83
    }
3333
0
    else {
3334
0
        equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
3335
0
                        vv->strides, vv->suboffsets,
3336
0
                        ww->strides, ww->suboffsets,
3337
0
                        vfmt, unpack_v, unpack_w);
3338
0
    }
3339
3340
108
result:
3341
108
    if (equal < 0) {
3342
0
        if (equal == MV_COMPARE_NOT_IMPL)
3343
0
            res = Py_NotImplemented;
3344
0
        else /* exception */
3345
0
            res = NULL;
3346
0
    }
3347
108
    else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
3348
1
        res = Py_True;
3349
107
    else
3350
107
        res = Py_False;
3351
3352
108
    if (ww == &wbuf)
3353
108
        PyBuffer_Release(ww);
3354
3355
108
    unpacker_free(unpack_v);
3356
108
    unpacker_free(unpack_w);
3357
3358
108
    return Py_XNewRef(res);
3359
83
}
3360
3361
/**************************************************************************/
3362
/*                                Hash                                    */
3363
/**************************************************************************/
3364
3365
static Py_hash_t
3366
memory_hash(PyObject *_self)
3367
0
{
3368
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3369
0
    if (self->hash == -1) {
3370
0
        Py_buffer *view = &self->view;
3371
0
        char *mem = view->buf;
3372
0
        Py_ssize_t ret;
3373
0
        const char *fmt;
3374
3375
0
        CHECK_RELEASED_INT(self);
3376
3377
0
        if (!view->readonly) {
3378
0
            PyErr_SetString(PyExc_ValueError,
3379
0
                "cannot hash writable memoryview object");
3380
0
            return -1;
3381
0
        }
3382
0
        ret = get_native_fmtchar(&fmt, view->format);
3383
0
        if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
3384
0
            PyErr_SetString(PyExc_ValueError,
3385
0
                "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
3386
0
            return -1;
3387
0
        }
3388
0
        if (view->obj != NULL) {
3389
            // Prevent 'self' from being freed when computing the item's hash.
3390
            // See https://github.com/python/cpython/issues/142664.
3391
0
            FT_ATOMIC_ADD_SSIZE(self->exports, 1);
3392
0
            Py_hash_t h = PyObject_Hash(view->obj);
3393
0
            FT_ATOMIC_ADD_SSIZE(self->exports, -1);
3394
0
            if (h == -1) {
3395
                /* Keep the original error message */
3396
0
                return -1;
3397
0
            }
3398
0
        }
3399
3400
0
        if (!MV_C_CONTIGUOUS(self->flags)) {
3401
0
            mem = PyMem_Malloc(view->len);
3402
0
            if (mem == NULL) {
3403
0
                PyErr_NoMemory();
3404
0
                return -1;
3405
0
            }
3406
0
            if (buffer_to_contiguous(mem, view, 'C') < 0) {
3407
0
                PyMem_Free(mem);
3408
0
                return -1;
3409
0
            }
3410
0
        }
3411
3412
        /* Can't fail */
3413
0
        self->hash = Py_HashBuffer(mem, view->len);
3414
3415
0
        if (mem != view->buf)
3416
0
            PyMem_Free(mem);
3417
0
    }
3418
3419
0
    return self->hash;
3420
0
}
3421
3422
3423
/**************************************************************************/
3424
/*                                 getters                                */
3425
/**************************************************************************/
3426
3427
static PyObject *
3428
_IntTupleFromSsizet(int len, Py_ssize_t *vals)
3429
0
{
3430
0
    int i;
3431
0
    PyObject *o;
3432
0
    PyObject *intTuple;
3433
3434
0
    if (vals == NULL)
3435
0
        return PyTuple_New(0);
3436
3437
0
    intTuple = PyTuple_New(len);
3438
0
    if (!intTuple)
3439
0
        return NULL;
3440
0
    for (i=0; i<len; i++) {
3441
0
        o = PyLong_FromSsize_t(vals[i]);
3442
0
        if (!o) {
3443
0
            Py_DECREF(intTuple);
3444
0
            return NULL;
3445
0
        }
3446
0
        PyTuple_SET_ITEM(intTuple, i, o);
3447
0
    }
3448
0
    return intTuple;
3449
0
}
3450
3451
static PyObject *
3452
memory_obj_get(PyObject *_self, void *Py_UNUSED(ignored))
3453
0
{
3454
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3455
0
    Py_buffer *view = &self->view;
3456
3457
0
    CHECK_RELEASED(self);
3458
0
    if (view->obj == NULL) {
3459
0
        Py_RETURN_NONE;
3460
0
    }
3461
0
    return Py_NewRef(view->obj);
3462
0
}
3463
3464
static PyObject *
3465
memory_nbytes_get(PyObject *_self, void *Py_UNUSED(ignored))
3466
5
{
3467
5
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3468
5
    CHECK_RELEASED(self);
3469
5
    return PyLong_FromSsize_t(self->view.len);
3470
5
}
3471
3472
static PyObject *
3473
memory_format_get(PyObject *_self, void *Py_UNUSED(ignored))
3474
0
{
3475
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3476
0
    CHECK_RELEASED(self);
3477
0
    return PyUnicode_FromString(self->view.format);
3478
0
}
3479
3480
static PyObject *
3481
memory_itemsize_get(PyObject *_self, void *Py_UNUSED(ignored))
3482
125k
{
3483
125k
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3484
125k
    CHECK_RELEASED(self);
3485
125k
    return PyLong_FromSsize_t(self->view.itemsize);
3486
125k
}
3487
3488
static PyObject *
3489
memory_shape_get(PyObject *_self, void *Py_UNUSED(ignored))
3490
0
{
3491
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3492
0
    CHECK_RELEASED(self);
3493
0
    return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
3494
0
}
3495
3496
static PyObject *
3497
memory_strides_get(PyObject *_self, void *Py_UNUSED(ignored))
3498
0
{
3499
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3500
0
    CHECK_RELEASED(self);
3501
0
    return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
3502
0
}
3503
3504
static PyObject *
3505
memory_suboffsets_get(PyObject *_self, void *Py_UNUSED(ignored))
3506
0
{
3507
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3508
0
    CHECK_RELEASED(self);
3509
0
    return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
3510
0
}
3511
3512
static PyObject *
3513
memory_readonly_get(PyObject *_self, void *Py_UNUSED(ignored))
3514
0
{
3515
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3516
0
    CHECK_RELEASED(self);
3517
0
    return PyBool_FromLong(self->view.readonly);
3518
0
}
3519
3520
static PyObject *
3521
memory_ndim_get(PyObject *_self, void *Py_UNUSED(ignored))
3522
0
{
3523
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3524
0
    CHECK_RELEASED(self);
3525
0
    return PyLong_FromLong(self->view.ndim);
3526
0
}
3527
3528
static PyObject *
3529
memory_c_contiguous(PyObject *_self, void *Py_UNUSED(ignored))
3530
0
{
3531
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3532
0
    CHECK_RELEASED(self);
3533
0
    return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
3534
0
}
3535
3536
static PyObject *
3537
memory_f_contiguous(PyObject *_self, void *Py_UNUSED(ignored))
3538
0
{
3539
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3540
0
    CHECK_RELEASED(self);
3541
0
    return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
3542
0
}
3543
3544
static PyObject *
3545
memory_contiguous(PyObject *_self, void *Py_UNUSED(ignored))
3546
0
{
3547
0
    PyMemoryViewObject *self = (PyMemoryViewObject *)_self;
3548
0
    CHECK_RELEASED(self);
3549
0
    return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
3550
0
}
3551
3552
PyDoc_STRVAR(memory_obj_doc,
3553
             "The underlying object of the memoryview.");
3554
PyDoc_STRVAR(memory_nbytes_doc,
3555
             "The amount of space in bytes that the array would use in\n"
3556
             " a contiguous representation.");
3557
PyDoc_STRVAR(memory_readonly_doc,
3558
             "A bool indicating whether the memory is read only.");
3559
PyDoc_STRVAR(memory_itemsize_doc,
3560
             "The size in bytes of each element of the memoryview.");
3561
PyDoc_STRVAR(memory_format_doc,
3562
             "A string containing the format (in struct module style)\n"
3563
             " for each element in the view.");
3564
PyDoc_STRVAR(memory_ndim_doc,
3565
             "An integer indicating how many dimensions of a multi-dimensional\n"
3566
             " array the memory represents.");
3567
PyDoc_STRVAR(memory_shape_doc,
3568
             "A tuple of ndim integers giving the shape of the memory\n"
3569
             " as an N-dimensional array.");
3570
PyDoc_STRVAR(memory_strides_doc,
3571
             "A tuple of ndim integers giving the size in bytes to access\n"
3572
             " each element for each dimension of the array.");
3573
PyDoc_STRVAR(memory_suboffsets_doc,
3574
             "A tuple of integers used internally for PIL-style arrays.");
3575
PyDoc_STRVAR(memory_c_contiguous_doc,
3576
             "A bool indicating whether the memory is C contiguous.");
3577
PyDoc_STRVAR(memory_f_contiguous_doc,
3578
             "A bool indicating whether the memory is Fortran contiguous.");
3579
PyDoc_STRVAR(memory_contiguous_doc,
3580
             "A bool indicating whether the memory is contiguous.");
3581
static PyGetSetDef memory_getsetlist[] = {
3582
    {"obj",             memory_obj_get,        NULL, memory_obj_doc},
3583
    {"nbytes",          memory_nbytes_get,     NULL, memory_nbytes_doc},
3584
    {"readonly",        memory_readonly_get,   NULL, memory_readonly_doc},
3585
    {"itemsize",        memory_itemsize_get,   NULL, memory_itemsize_doc},
3586
    {"format",          memory_format_get,     NULL, memory_format_doc},
3587
    {"ndim",            memory_ndim_get,       NULL, memory_ndim_doc},
3588
    {"shape",           memory_shape_get,      NULL, memory_shape_doc},
3589
    {"strides",         memory_strides_get,    NULL, memory_strides_doc},
3590
    {"suboffsets",      memory_suboffsets_get, NULL, memory_suboffsets_doc},
3591
    {"c_contiguous",    memory_c_contiguous,   NULL, memory_c_contiguous_doc},
3592
    {"f_contiguous",    memory_f_contiguous,   NULL, memory_f_contiguous_doc},
3593
    {"contiguous",      memory_contiguous,     NULL, memory_contiguous_doc},
3594
    {NULL, NULL, NULL, NULL},
3595
};
3596
3597
3598
static PyMethodDef memory_methods[] = {
3599
    MEMORYVIEW_RELEASE_METHODDEF
3600
    MEMORYVIEW_TOBYTES_METHODDEF
3601
    MEMORYVIEW_HEX_METHODDEF
3602
    MEMORYVIEW_TOLIST_METHODDEF
3603
    MEMORYVIEW_CAST_METHODDEF
3604
    MEMORYVIEW_TOREADONLY_METHODDEF
3605
    MEMORYVIEW__FROM_FLAGS_METHODDEF
3606
    MEMORYVIEW_COUNT_METHODDEF
3607
    MEMORYVIEW_INDEX_METHODDEF
3608
    {"__enter__",   memory_enter, METH_NOARGS, NULL},
3609
    MEMORYVIEW___EXIT___METHODDEF
3610
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS,
3611
     PyDoc_STR("memoryviews are generic over the type of their underlying data")},
3612
    {NULL,          NULL}
3613
};
3614
3615
/**************************************************************************/
3616
/*                          Memoryview Iterator                           */
3617
/**************************************************************************/
3618
3619
PyTypeObject _PyMemoryIter_Type;
3620
3621
typedef struct {
3622
    PyObject_HEAD
3623
    Py_ssize_t it_index;
3624
    PyMemoryViewObject *it_seq; // Set to NULL when iterator is exhausted
3625
    Py_ssize_t it_length;
3626
    const char *it_fmt;
3627
} memoryiterobject;
3628
3629
static void
3630
memoryiter_dealloc(PyObject *self)
3631
0
{
3632
0
    memoryiterobject *it = (memoryiterobject *)self;
3633
0
    _PyObject_GC_UNTRACK(it);
3634
0
    Py_XDECREF(it->it_seq);
3635
0
    PyObject_GC_Del(it);
3636
0
}
3637
3638
static int
3639
memoryiter_traverse(PyObject *self, visitproc visit, void *arg)
3640
0
{
3641
0
    memoryiterobject *it = (memoryiterobject *)self;
3642
0
    Py_VISIT(it->it_seq);
3643
0
    return 0;
3644
0
}
3645
3646
static PyObject *
3647
memoryiter_next(PyObject *self)
3648
0
{
3649
0
    memoryiterobject *it = (memoryiterobject *)self;
3650
0
    PyMemoryViewObject *seq;
3651
0
    seq = it->it_seq;
3652
0
    if (seq == NULL) {
3653
0
        return NULL;
3654
0
    }
3655
3656
0
    if (it->it_index < it->it_length) {
3657
0
        CHECK_RELEASED(seq);
3658
0
        Py_buffer *view = &(seq->view);
3659
0
        char *ptr = (char *)seq->view.buf;
3660
3661
0
        ptr += view->strides[0] * it->it_index++;
3662
0
        ptr = ADJUST_PTR(ptr, view->suboffsets, 0);
3663
0
        if (ptr == NULL) {
3664
0
            return NULL;
3665
0
        }
3666
0
        return unpack_single(seq, ptr, it->it_fmt);
3667
0
    }
3668
3669
0
    it->it_seq = NULL;
3670
0
    Py_DECREF(seq);
3671
0
    return NULL;
3672
0
}
3673
3674
static PyObject *
3675
memory_iter(PyObject *seq)
3676
0
{
3677
0
    if (!PyMemoryView_Check(seq)) {
3678
0
        PyErr_BadInternalCall();
3679
0
        return NULL;
3680
0
    }
3681
0
    CHECK_RELEASED(seq);
3682
0
    PyMemoryViewObject *obj = (PyMemoryViewObject *)seq;
3683
0
    int ndims = obj->view.ndim;
3684
0
    if (ndims == 0) {
3685
0
        PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
3686
0
        return NULL;
3687
0
    }
3688
0
    if (ndims != 1) {
3689
0
        PyErr_SetString(PyExc_NotImplementedError,
3690
0
            "multi-dimensional sub-views are not implemented");
3691
0
        return NULL;
3692
0
    }
3693
3694
0
    const char *fmt = adjust_fmt(&obj->view);
3695
0
    if (fmt == NULL) {
3696
0
        return NULL;
3697
0
    }
3698
3699
0
    memoryiterobject *it;
3700
0
    it = PyObject_GC_New(memoryiterobject, &_PyMemoryIter_Type);
3701
0
    if (it == NULL) {
3702
0
        return NULL;
3703
0
    }
3704
0
    it->it_fmt = fmt;
3705
0
    it->it_length = memory_length((PyObject *)obj);
3706
0
    it->it_index = 0;
3707
0
    it->it_seq = (PyMemoryViewObject*)Py_NewRef(obj);
3708
0
    _PyObject_GC_TRACK(it);
3709
0
    return (PyObject *)it;
3710
0
}
3711
3712
PyTypeObject _PyMemoryIter_Type = {
3713
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
3714
    .tp_name = "memory_iterator",
3715
    .tp_basicsize = sizeof(memoryiterobject),
3716
    // methods
3717
    .tp_dealloc = memoryiter_dealloc,
3718
    .tp_getattro = PyObject_GenericGetAttr,
3719
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
3720
    .tp_traverse = memoryiter_traverse,
3721
    .tp_iter = PyObject_SelfIter,
3722
    .tp_iternext = memoryiter_next,
3723
};
3724
3725
PyTypeObject PyMemoryView_Type = {
3726
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
3727
    "memoryview",                             /* tp_name */
3728
    offsetof(PyMemoryViewObject, ob_array),   /* tp_basicsize */
3729
    sizeof(Py_ssize_t),                       /* tp_itemsize */
3730
    memory_dealloc,                           /* tp_dealloc */
3731
    0,                                        /* tp_vectorcall_offset */
3732
    0,                                        /* tp_getattr */
3733
    0,                                        /* tp_setattr */
3734
    0,                                        /* tp_as_async */
3735
    memory_repr,                              /* tp_repr */
3736
    0,                                        /* tp_as_number */
3737
    &memory_as_sequence,                      /* tp_as_sequence */
3738
    &memory_as_mapping,                       /* tp_as_mapping */
3739
    memory_hash,                              /* tp_hash */
3740
    0,                                        /* tp_call */
3741
    0,                                        /* tp_str */
3742
    PyObject_GenericGetAttr,                  /* tp_getattro */
3743
    0,                                        /* tp_setattro */
3744
    &memory_as_buffer,                        /* tp_as_buffer */
3745
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
3746
       Py_TPFLAGS_SEQUENCE,                   /* tp_flags */
3747
    memoryview__doc__,                        /* tp_doc */
3748
    memory_traverse,                          /* tp_traverse */
3749
    memory_clear,                             /* tp_clear */
3750
    memory_richcompare,                       /* tp_richcompare */
3751
    offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
3752
    memory_iter,                              /* tp_iter */
3753
    0,                                        /* tp_iternext */
3754
    memory_methods,                           /* tp_methods */
3755
    0,                                        /* tp_members */
3756
    memory_getsetlist,                        /* tp_getset */
3757
    0,                                        /* tp_base */
3758
    0,                                        /* tp_dict */
3759
    0,                                        /* tp_descr_get */
3760
    0,                                        /* tp_descr_set */
3761
    0,                                        /* tp_dictoffset */
3762
    0,                                        /* tp_init */
3763
    0,                                        /* tp_alloc */
3764
    memoryview,                               /* tp_new */
3765
};