ยปCore Development>Code coverage>Objects/memoryobject.c

Python code coverage for Objects/memoryobject.c

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