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