Coverage Report

Created: 2025-07-11 06:59

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