Coverage Report

Created: 2022-07-08 09:39

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