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