blob: b1798a2073d108cff67a2f5453971b68b50aa1c0 [file] [log] [blame]
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001/* Memoryview object implementation */
2
3#include "Python.h"
Gregory P. Smith8cb65692015-04-25 23:22:26 +00004#include "pystrhex.h"
Stefan Krah9a2d99e2012-02-25 12:24:21 +01005#include <stddef.h>
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00006
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00007
Stefan Krah9a2d99e2012-02-25 12:24:21 +01008/****************************************************************************/
9/* ManagedBuffer Object */
10/****************************************************************************/
11
12/*
13 ManagedBuffer Object:
14 ---------------------
15
16 The purpose of this object is to facilitate the handling of chained
17 memoryviews that have the same underlying exporting object. PEP-3118
18 allows the underlying object to change while a view is exported. This
19 could lead to unexpected results when constructing a new memoryview
20 from an existing memoryview.
21
22 Rather than repeatedly redirecting buffer requests to the original base
23 object, all chained memoryviews use a single buffer snapshot. This
24 snapshot is generated by the constructor _PyManagedBuffer_FromObject().
25
26 Ownership rules:
27 ----------------
28
29 The master buffer inside a managed buffer is filled in by the original
30 base object. shape, strides, suboffsets and format are read-only for
31 all consumers.
32
33 A memoryview's buffer is a private copy of the exporter's buffer. shape,
34 strides and suboffsets belong to the memoryview and are thus writable.
35
36 If a memoryview itself exports several buffers via memory_getbuf(), all
37 buffer copies share shape, strides and suboffsets. In this case, the
38 arrays are NOT writable.
39
40 Reference count assumptions:
41 ----------------------------
42
43 The 'obj' member of a Py_buffer must either be NULL or refer to the
44 exporting base object. In the Python codebase, all getbufferprocs
45 return a new reference to view.obj (example: bytes_buffer_getbuffer()).
46
47 PyBuffer_Release() decrements view.obj (if non-NULL), so the
48 releasebufferprocs must NOT decrement view.obj.
49*/
50
51
Stefan Krah9a2d99e2012-02-25 12:24:21 +010052#define CHECK_MBUF_RELEASED(mbuf) \
53 if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
54 PyErr_SetString(PyExc_ValueError, \
55 "operation forbidden on released memoryview object"); \
56 return NULL; \
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000057 }
58
Antoine Pitrou6e6cc832010-09-09 12:59:39 +000059
Benjamin Peterson82cce4c2016-09-08 11:56:06 -070060static inline _PyManagedBufferObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +010061mbuf_alloc(void)
Antoine Pitroubc420402008-12-07 20:14:49 +000062{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010063 _PyManagedBufferObject *mbuf;
64
65 mbuf = (_PyManagedBufferObject *)
66 PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type);
67 if (mbuf == NULL)
68 return NULL;
69 mbuf->flags = 0;
70 mbuf->exports = 0;
71 mbuf->master.obj = NULL;
72 _PyObject_GC_TRACK(mbuf);
73
74 return mbuf;
75}
76
77static PyObject *
78_PyManagedBuffer_FromObject(PyObject *base)
79{
80 _PyManagedBufferObject *mbuf;
81
82 mbuf = mbuf_alloc();
83 if (mbuf == NULL)
84 return NULL;
85
86 if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) {
Stefan Krah1649c1b2012-03-05 17:45:17 +010087 mbuf->master.obj = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +010088 Py_DECREF(mbuf);
89 return NULL;
90 }
91
Stefan Krah9a2d99e2012-02-25 12:24:21 +010092 return (PyObject *)mbuf;
Antoine Pitrouc3b39242009-01-03 16:59:18 +000093}
94
95static void
Stefan Krah9a2d99e2012-02-25 12:24:21 +010096mbuf_release(_PyManagedBufferObject *self)
Antoine Pitrouc3b39242009-01-03 16:59:18 +000097{
Stefan Krah9a2d99e2012-02-25 12:24:21 +010098 if (self->flags&_Py_MANAGED_BUFFER_RELEASED)
99 return;
100
101 /* NOTE: at this point self->exports can still be > 0 if this function
102 is called from mbuf_clear() to break up a reference cycle. */
103 self->flags |= _Py_MANAGED_BUFFER_RELEASED;
104
105 /* PyBuffer_Release() decrements master->obj and sets it to NULL. */
106 _PyObject_GC_UNTRACK(self);
107 PyBuffer_Release(&self->master);
108}
109
110static void
111mbuf_dealloc(_PyManagedBufferObject *self)
112{
113 assert(self->exports == 0);
114 mbuf_release(self);
115 if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT)
116 PyMem_Free(self->master.format);
117 PyObject_GC_Del(self);
Antoine Pitroubc420402008-12-07 20:14:49 +0000118}
119
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000120static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100121mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000122{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100123 Py_VISIT(self->master.obj);
124 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000125}
126
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100127static int
128mbuf_clear(_PyManagedBufferObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000129{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100130 assert(self->exports >= 0);
131 mbuf_release(self);
132 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000133}
134
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100135PyTypeObject _PyManagedBuffer_Type = {
136 PyVarObject_HEAD_INIT(&PyType_Type, 0)
137 "managedbuffer",
138 sizeof(_PyManagedBufferObject),
139 0,
140 (destructor)mbuf_dealloc, /* tp_dealloc */
141 0, /* tp_print */
142 0, /* tp_getattr */
143 0, /* tp_setattr */
144 0, /* tp_reserved */
145 0, /* tp_repr */
146 0, /* tp_as_number */
147 0, /* tp_as_sequence */
148 0, /* tp_as_mapping */
149 0, /* tp_hash */
150 0, /* tp_call */
151 0, /* tp_str */
152 PyObject_GenericGetAttr, /* tp_getattro */
153 0, /* tp_setattro */
154 0, /* tp_as_buffer */
155 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
156 0, /* tp_doc */
157 (traverseproc)mbuf_traverse, /* tp_traverse */
158 (inquiry)mbuf_clear /* tp_clear */
159};
160
161
162/****************************************************************************/
163/* MemoryView Object */
164/****************************************************************************/
165
166/* In the process of breaking reference cycles mbuf_release() can be
167 called before memory_release(). */
168#define BASE_INACCESSIBLE(mv) \
169 (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \
170 ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED)
171
172#define CHECK_RELEASED(mv) \
173 if (BASE_INACCESSIBLE(mv)) { \
174 PyErr_SetString(PyExc_ValueError, \
175 "operation forbidden on released memoryview object"); \
176 return NULL; \
177 }
178
179#define CHECK_RELEASED_INT(mv) \
180 if (BASE_INACCESSIBLE(mv)) { \
181 PyErr_SetString(PyExc_ValueError, \
182 "operation forbidden on released memoryview object"); \
183 return -1; \
184 }
185
186#define CHECK_LIST_OR_TUPLE(v) \
187 if (!PyList_Check(v) && !PyTuple_Check(v)) { \
188 PyErr_SetString(PyExc_TypeError, \
189 #v " must be a list or a tuple"); \
190 return NULL; \
191 }
192
193#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view)
194
195/* Check for the presence of suboffsets in the first dimension. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100196#define HAVE_PTR(suboffsets, dim) (suboffsets && suboffsets[dim] >= 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100197/* Adjust ptr if suboffsets are present. */
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100198#define ADJUST_PTR(ptr, suboffsets, dim) \
199 (HAVE_PTR(suboffsets, dim) ? *((char**)ptr) + suboffsets[dim] : ptr)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100200
201/* Memoryview buffer properties */
202#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C))
203#define MV_F_CONTIGUOUS(flags) \
204 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN))
205#define MV_ANY_CONTIGUOUS(flags) \
206 (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN))
207
208/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */
209#define MV_CONTIGUOUS_NDIM1(view) \
210 ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize)
211
212/* getbuffer() requests */
213#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT)
214#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS)
215#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)
216#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS)
217#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES)
218#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND)
219#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE)
220#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
221
222
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000223PyDoc_STRVAR(memory_doc,
Stefan Krah195319e2016-12-30 12:23:35 +0100224"memoryview(object)\n--\n\
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000225\n\
226Create a new memoryview object which references the given object.");
227
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100228
229/**************************************************************************/
230/* Copy memoryview buffers */
231/**************************************************************************/
232
233/* The functions in this section take a source and a destination buffer
234 with the same logical structure: format, itemsize, ndim and shape
235 are identical, with ndim > 0.
236
237 NOTE: All buffers are assumed to have PyBUF_FULL information, which
238 is the case for memoryviews! */
239
240
241/* Assumptions: ndim >= 1. The macro tests for a corner case that should
242 perhaps be explicitly forbidden in the PEP. */
243#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
244 (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
245
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700246static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000247last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100248{
249 assert(dest->ndim > 0 && src->ndim > 0);
250 return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) &&
251 !HAVE_SUBOFFSETS_IN_LAST_DIM(src) &&
252 dest->strides[dest->ndim-1] == dest->itemsize &&
253 src->strides[src->ndim-1] == src->itemsize);
254}
255
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000256/* This is not a general function for determining format equivalence.
257 It is used in copy_single() and copy_buffer() to weed out non-matching
258 formats. Skipping the '@' character is specifically used in slice
259 assignments, where the lvalue is already known to have a single character
260 format. This is a performance hack that could be rewritten (if properly
261 benchmarked). */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700262static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000263equiv_format(const Py_buffer *dest, const Py_buffer *src)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100264{
265 const char *dfmt, *sfmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100266
267 assert(dest->format && src->format);
268 dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format;
269 sfmt = src->format[0] == '@' ? src->format+1 : src->format;
270
271 if (strcmp(dfmt, sfmt) != 0 ||
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000272 dest->itemsize != src->itemsize) {
273 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100274 }
275
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000276 return 1;
277}
278
279/* Two shapes are equivalent if they are either equal or identical up
280 to a zero element at the same position. For example, in NumPy arrays
281 the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700282static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000283equiv_shape(const Py_buffer *dest, const Py_buffer *src)
284{
285 int i;
286
287 if (dest->ndim != src->ndim)
288 return 0;
289
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100290 for (i = 0; i < dest->ndim; i++) {
291 if (dest->shape[i] != src->shape[i])
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000292 return 0;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100293 if (dest->shape[i] == 0)
294 break;
295 }
296
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000297 return 1;
298}
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100299
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000300/* Check that the logical structure of the destination and source buffers
301 is identical. */
302static int
303equiv_structure(const Py_buffer *dest, const Py_buffer *src)
304{
305 if (!equiv_format(dest, src) ||
306 !equiv_shape(dest, src)) {
307 PyErr_SetString(PyExc_ValueError,
Stefan Krah674a42b2013-02-19 13:44:49 +0100308 "memoryview assignment: lvalue and rvalue have different "
309 "structures");
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000310 return 0;
311 }
312
313 return 1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100314}
315
316/* Base case for recursive multi-dimensional copying. Contiguous arrays are
317 copied with very little overhead. Assumptions: ndim == 1, mem == NULL or
318 sizeof(mem) == shape[0] * itemsize. */
319static void
320copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize,
321 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
322 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
323 char *mem)
324{
325 if (mem == NULL) { /* contiguous */
326 Py_ssize_t size = shape[0] * itemsize;
327 if (dptr + size < sptr || sptr + size < dptr)
328 memcpy(dptr, sptr, size); /* no overlapping */
329 else
330 memmove(dptr, sptr, size);
331 }
332 else {
333 char *p;
334 Py_ssize_t i;
335 for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100336 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100337 memcpy(p, xsptr, itemsize);
338 }
339 for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100340 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100341 memcpy(xdptr, p, itemsize);
342 }
343 }
344
345}
346
347/* Recursively copy a source buffer to a destination buffer. The two buffers
348 have the same ndim, shape and itemsize. */
349static void
350copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize,
351 char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets,
352 char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets,
353 char *mem)
354{
355 Py_ssize_t i;
356
357 assert(ndim >= 1);
358
359 if (ndim == 1) {
360 copy_base(shape, itemsize,
361 dptr, dstrides, dsuboffsets,
362 sptr, sstrides, ssuboffsets,
363 mem);
364 return;
365 }
366
367 for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +0100368 char *xdptr = ADJUST_PTR(dptr, dsuboffsets, 0);
369 char *xsptr = ADJUST_PTR(sptr, ssuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100370
371 copy_rec(shape+1, ndim-1, itemsize,
372 xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL,
373 xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL,
374 mem);
375 }
376}
377
378/* Faster copying of one-dimensional arrays. */
379static int
380copy_single(Py_buffer *dest, Py_buffer *src)
381{
382 char *mem = NULL;
383
384 assert(dest->ndim == 1);
385
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000386 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100387 return -1;
388
389 if (!last_dim_is_contiguous(dest, src)) {
390 mem = PyMem_Malloc(dest->shape[0] * dest->itemsize);
391 if (mem == NULL) {
392 PyErr_NoMemory();
393 return -1;
394 }
395 }
396
397 copy_base(dest->shape, dest->itemsize,
398 dest->buf, dest->strides, dest->suboffsets,
399 src->buf, src->strides, src->suboffsets,
400 mem);
401
402 if (mem)
403 PyMem_Free(mem);
404
405 return 0;
406}
407
408/* Recursively copy src to dest. Both buffers must have the same basic
409 structure. Copying is atomic, the function never fails with a partial
410 copy. */
411static int
412copy_buffer(Py_buffer *dest, Py_buffer *src)
413{
414 char *mem = NULL;
415
416 assert(dest->ndim > 0);
417
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000418 if (!equiv_structure(dest, src))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100419 return -1;
420
421 if (!last_dim_is_contiguous(dest, src)) {
422 mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize);
423 if (mem == NULL) {
424 PyErr_NoMemory();
425 return -1;
426 }
427 }
428
429 copy_rec(dest->shape, dest->ndim, dest->itemsize,
430 dest->buf, dest->strides, dest->suboffsets,
431 src->buf, src->strides, src->suboffsets,
432 mem);
433
434 if (mem)
435 PyMem_Free(mem);
436
437 return 0;
438}
439
440/* Initialize strides for a C-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700441static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100442init_strides_from_shape(Py_buffer *view)
443{
444 Py_ssize_t i;
445
446 assert(view->ndim > 0);
447
448 view->strides[view->ndim-1] = view->itemsize;
449 for (i = view->ndim-2; i >= 0; i--)
450 view->strides[i] = view->strides[i+1] * view->shape[i+1];
451}
452
453/* Initialize strides for a Fortran-contiguous array. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700454static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100455init_fortran_strides_from_shape(Py_buffer *view)
456{
457 Py_ssize_t i;
458
459 assert(view->ndim > 0);
460
461 view->strides[0] = view->itemsize;
462 for (i = 1; i < view->ndim; i++)
463 view->strides[i] = view->strides[i-1] * view->shape[i-1];
464}
465
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200466/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran)
467 or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100468 len(mem) == src->len. */
469static int
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200470buffer_to_contiguous(char *mem, Py_buffer *src, char order)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100471{
472 Py_buffer dest;
473 Py_ssize_t *strides;
474 int ret;
475
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200476 assert(src->ndim >= 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100477 assert(src->shape != NULL);
478 assert(src->strides != NULL);
479
480 strides = PyMem_Malloc(src->ndim * (sizeof *src->strides));
481 if (strides == NULL) {
482 PyErr_NoMemory();
483 return -1;
484 }
485
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200486 /* initialize dest */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100487 dest = *src;
488 dest.buf = mem;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200489 /* shape is constant and shared: the logical representation of the
490 array is unaltered. */
491
492 /* The physical representation determined by strides (and possibly
493 suboffsets) may change. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100494 dest.strides = strides;
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200495 if (order == 'C' || order == 'A') {
496 init_strides_from_shape(&dest);
497 }
498 else {
499 init_fortran_strides_from_shape(&dest);
500 }
501
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100502 dest.suboffsets = NULL;
503
504 ret = copy_buffer(&dest, src);
505
506 PyMem_Free(strides);
507 return ret;
508}
509
510
511/****************************************************************************/
512/* Constructors */
513/****************************************************************************/
514
515/* Initialize values that are shared with the managed buffer. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700516static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100517init_shared_values(Py_buffer *dest, const Py_buffer *src)
518{
519 dest->obj = src->obj;
520 dest->buf = src->buf;
521 dest->len = src->len;
522 dest->itemsize = src->itemsize;
523 dest->readonly = src->readonly;
524 dest->format = src->format ? src->format : "B";
525 dest->internal = src->internal;
526}
527
528/* Copy shape and strides. Reconstruct missing values. */
529static void
530init_shape_strides(Py_buffer *dest, const Py_buffer *src)
531{
532 Py_ssize_t i;
533
534 if (src->ndim == 0) {
535 dest->shape = NULL;
536 dest->strides = NULL;
537 return;
538 }
539 if (src->ndim == 1) {
540 dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize;
541 dest->strides[0] = src->strides ? src->strides[0] : src->itemsize;
542 return;
543 }
544
545 for (i = 0; i < src->ndim; i++)
546 dest->shape[i] = src->shape[i];
547 if (src->strides) {
548 for (i = 0; i < src->ndim; i++)
549 dest->strides[i] = src->strides[i];
550 }
551 else {
552 init_strides_from_shape(dest);
553 }
554}
555
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700556static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100557init_suboffsets(Py_buffer *dest, const Py_buffer *src)
558{
559 Py_ssize_t i;
560
561 if (src->suboffsets == NULL) {
562 dest->suboffsets = NULL;
563 return;
564 }
565 for (i = 0; i < src->ndim; i++)
566 dest->suboffsets[i] = src->suboffsets[i];
567}
568
569/* len = product(shape) * itemsize */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700570static inline void
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100571init_len(Py_buffer *view)
572{
573 Py_ssize_t i, len;
574
575 len = 1;
576 for (i = 0; i < view->ndim; i++)
577 len *= view->shape[i];
578 len *= view->itemsize;
579
580 view->len = len;
581}
582
583/* Initialize memoryview buffer properties. */
584static void
585init_flags(PyMemoryViewObject *mv)
586{
587 const Py_buffer *view = &mv->view;
588 int flags = 0;
589
590 switch (view->ndim) {
591 case 0:
592 flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|
593 _Py_MEMORYVIEW_FORTRAN);
594 break;
595 case 1:
596 if (MV_CONTIGUOUS_NDIM1(view))
597 flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
598 break;
599 default:
600 if (PyBuffer_IsContiguous(view, 'C'))
601 flags |= _Py_MEMORYVIEW_C;
602 if (PyBuffer_IsContiguous(view, 'F'))
603 flags |= _Py_MEMORYVIEW_FORTRAN;
604 break;
605 }
606
607 if (view->suboffsets) {
608 flags |= _Py_MEMORYVIEW_PIL;
609 flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN);
610 }
611
612 mv->flags = flags;
613}
614
615/* Allocate a new memoryview and perform basic initialization. New memoryviews
616 are exclusively created through the mbuf_add functions. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -0700617static inline PyMemoryViewObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100618memory_alloc(int ndim)
619{
620 PyMemoryViewObject *mv;
621
622 mv = (PyMemoryViewObject *)
623 PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim);
624 if (mv == NULL)
625 return NULL;
626
627 mv->mbuf = NULL;
628 mv->hash = -1;
629 mv->flags = 0;
630 mv->exports = 0;
631 mv->view.ndim = ndim;
632 mv->view.shape = mv->ob_array;
633 mv->view.strides = mv->ob_array + ndim;
634 mv->view.suboffsets = mv->ob_array + 2 * ndim;
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +0100635 mv->weakreflist = NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100636
637 _PyObject_GC_TRACK(mv);
638 return mv;
639}
640
641/*
642 Return a new memoryview that is registered with mbuf. If src is NULL,
643 use mbuf->master as the underlying buffer. Otherwise, use src.
644
645 The new memoryview has full buffer information: shape and strides
646 are always present, suboffsets as needed. Arrays are copied to
647 the memoryview's ob_array field.
648 */
649static PyObject *
650mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
651{
652 PyMemoryViewObject *mv;
653 Py_buffer *dest;
654
655 if (src == NULL)
656 src = &mbuf->master;
657
658 if (src->ndim > PyBUF_MAX_NDIM) {
659 PyErr_SetString(PyExc_ValueError,
660 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +0200661 Py_STRINGIFY(PyBUF_MAX_NDIM));
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100662 return NULL;
663 }
664
665 mv = memory_alloc(src->ndim);
666 if (mv == NULL)
667 return NULL;
668
669 dest = &mv->view;
670 init_shared_values(dest, src);
671 init_shape_strides(dest, src);
672 init_suboffsets(dest, src);
673 init_flags(mv);
674
675 mv->mbuf = mbuf;
676 Py_INCREF(mbuf);
677 mbuf->exports++;
678
679 return (PyObject *)mv;
680}
681
682/* Register an incomplete view: shape, strides, suboffsets and flags still
683 need to be initialized. Use 'ndim' instead of src->ndim to determine the
684 size of the memoryview's ob_array.
685
686 Assumption: ndim <= PyBUF_MAX_NDIM. */
687static PyObject *
688mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
689 int ndim)
690{
691 PyMemoryViewObject *mv;
692 Py_buffer *dest;
693
694 if (src == NULL)
695 src = &mbuf->master;
696
697 assert(ndim <= PyBUF_MAX_NDIM);
698
699 mv = memory_alloc(ndim);
700 if (mv == NULL)
701 return NULL;
702
703 dest = &mv->view;
704 init_shared_values(dest, src);
705
706 mv->mbuf = mbuf;
707 Py_INCREF(mbuf);
708 mbuf->exports++;
709
710 return (PyObject *)mv;
711}
712
713/* Expose a raw memory area as a view of contiguous bytes. flags can be
714 PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes).
715 The memoryview has complete buffer information. */
716PyObject *
717PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags)
718{
719 _PyManagedBufferObject *mbuf;
720 PyObject *mv;
721 int readonly;
722
723 assert(mem != NULL);
724 assert(flags == PyBUF_READ || flags == PyBUF_WRITE);
725
726 mbuf = mbuf_alloc();
727 if (mbuf == NULL)
728 return NULL;
729
730 readonly = (flags == PyBUF_WRITE) ? 0 : 1;
731 (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly,
732 PyBUF_FULL_RO);
733
734 mv = mbuf_add_view(mbuf, NULL);
735 Py_DECREF(mbuf);
736
737 return mv;
738}
739
740/* Create a memoryview from a given Py_buffer. For simple byte views,
741 PyMemoryView_FromMemory() should be used instead.
742 This function is the only entry point that can create a master buffer
743 without full information. Because of this fact init_shape_strides()
744 must be able to reconstruct missing values. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000745PyObject *
Antoine Pitrouee58fa42008-08-19 18:22:14 +0000746PyMemoryView_FromBuffer(Py_buffer *info)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000747{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100748 _PyManagedBufferObject *mbuf;
749 PyObject *mv;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000750
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000751 if (info->buf == NULL) {
752 PyErr_SetString(PyExc_ValueError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100753 "PyMemoryView_FromBuffer(): info->buf must not be NULL");
Antoine Pitrou5bffa792011-02-24 20:50:49 +0000754 return NULL;
755 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100756
757 mbuf = mbuf_alloc();
758 if (mbuf == NULL)
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000759 return NULL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100760
761 /* info->obj is either NULL or a borrowed reference. This reference
762 should not be decremented in PyBuffer_Release(). */
763 mbuf->master = *info;
764 mbuf->master.obj = NULL;
765
766 mv = mbuf_add_view(mbuf, NULL);
767 Py_DECREF(mbuf);
768
769 return mv;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000770}
771
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100772/* Create a memoryview from an object that implements the buffer protocol.
773 If the object is a memoryview, the new memoryview must be registered
774 with the same managed buffer. Otherwise, a new managed buffer is created. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000775PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100776PyMemoryView_FromObject(PyObject *v)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000777{
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100778 _PyManagedBufferObject *mbuf;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000779
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100780 if (PyMemoryView_Check(v)) {
781 PyMemoryViewObject *mv = (PyMemoryViewObject *)v;
782 CHECK_RELEASED(mv);
783 return mbuf_add_view(mv->mbuf, &mv->view);
784 }
785 else if (PyObject_CheckBuffer(v)) {
786 PyObject *ret;
787 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v);
788 if (mbuf == NULL)
789 return NULL;
790 ret = mbuf_add_view(mbuf, NULL);
791 Py_DECREF(mbuf);
792 return ret;
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000793 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +0000794
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100795 PyErr_Format(PyExc_TypeError,
R David Murray861470c2014-10-05 11:47:01 -0400796 "memoryview: a bytes-like object is required, not '%.200s'",
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100797 Py_TYPE(v)->tp_name);
798 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000799}
800
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100801/* Copy the format string from a base object that might vanish. */
802static int
803mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt)
804{
805 if (fmt != NULL) {
806 char *cp = PyMem_Malloc(strlen(fmt)+1);
807 if (cp == NULL) {
808 PyErr_NoMemory();
809 return -1;
810 }
811 mbuf->master.format = strcpy(cp, fmt);
812 mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT;
813 }
814
815 return 0;
816}
817
818/*
819 Return a memoryview that is based on a contiguous copy of src.
820 Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0.
821
822 Ownership rules:
823 1) As usual, the returned memoryview has a private copy
824 of src->shape, src->strides and src->suboffsets.
825 2) src->format is copied to the master buffer and released
826 in mbuf_dealloc(). The releasebufferproc of the bytes
827 object is NULL, so it does not matter that mbuf_release()
828 passes the altered format pointer to PyBuffer_Release().
829*/
830static PyObject *
831memory_from_contiguous_copy(Py_buffer *src, char order)
832{
833 _PyManagedBufferObject *mbuf;
834 PyMemoryViewObject *mv;
835 PyObject *bytes;
836 Py_buffer *dest;
837 int i;
838
839 assert(src->ndim > 0);
840 assert(src->shape != NULL);
841
842 bytes = PyBytes_FromStringAndSize(NULL, src->len);
843 if (bytes == NULL)
844 return NULL;
845
846 mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes);
847 Py_DECREF(bytes);
848 if (mbuf == NULL)
849 return NULL;
850
851 if (mbuf_copy_format(mbuf, src->format) < 0) {
852 Py_DECREF(mbuf);
853 return NULL;
854 }
855
856 mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim);
857 Py_DECREF(mbuf);
858 if (mv == NULL)
859 return NULL;
860
861 dest = &mv->view;
862
863 /* shared values are initialized correctly except for itemsize */
864 dest->itemsize = src->itemsize;
865
866 /* shape and strides */
867 for (i = 0; i < src->ndim; i++) {
868 dest->shape[i] = src->shape[i];
869 }
870 if (order == 'C' || order == 'A') {
871 init_strides_from_shape(dest);
872 }
873 else {
874 init_fortran_strides_from_shape(dest);
875 }
876 /* suboffsets */
877 dest->suboffsets = NULL;
878
879 /* flags */
880 init_flags(mv);
881
882 if (copy_buffer(dest, src) < 0) {
883 Py_DECREF(mv);
884 return NULL;
885 }
886
887 return (PyObject *)mv;
888}
889
890/*
891 Return a new memoryview object based on a contiguous exporter with
892 buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}.
893 The logical structure of the input and output buffers is the same
894 (i.e. tolist(input) == tolist(output)), but the physical layout in
895 memory can be explicitly chosen.
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200896
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100897 As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable,
898 otherwise it may be writable or read-only.
899
900 If the exporter is already contiguous with the desired target order,
901 the memoryview will be directly based on the exporter.
902
903 Otherwise, if the buffertype is PyBUF_READ, the memoryview will be
904 based on a new bytes object. If order={'C', 'A'ny}, use 'C' order,
905 'F'ortran order otherwise.
906*/
907PyObject *
908PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
909{
910 PyMemoryViewObject *mv;
911 PyObject *ret;
912 Py_buffer *view;
913
914 assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE);
915 assert(order == 'C' || order == 'F' || order == 'A');
916
917 mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj);
918 if (mv == NULL)
919 return NULL;
920
921 view = &mv->view;
922 if (buffertype == PyBUF_WRITE && view->readonly) {
923 PyErr_SetString(PyExc_BufferError,
924 "underlying buffer is not writable");
925 Py_DECREF(mv);
926 return NULL;
927 }
928
929 if (PyBuffer_IsContiguous(view, order))
930 return (PyObject *)mv;
931
932 if (buffertype == PyBUF_WRITE) {
933 PyErr_SetString(PyExc_BufferError,
934 "writable contiguous buffer requested "
935 "for a non-contiguous object.");
936 Py_DECREF(mv);
937 return NULL;
938 }
939
940 ret = memory_from_contiguous_copy(view, order);
941 Py_DECREF(mv);
942 return ret;
943}
944
945
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000946static PyObject *
947memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
948{
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000949 PyObject *obj;
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100950 static char *kwlist[] = {"object", NULL};
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000951
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000952 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
953 &obj)) {
954 return NULL;
955 }
Christian Heimes7b6fc8e2007-11-08 02:28:11 +0000956
Antoine Pitrou35b7e832009-01-03 19:20:36 +0000957 return PyMemoryView_FromObject(obj);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000958}
959
960
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100961/****************************************************************************/
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200962/* Previously in abstract.c */
963/****************************************************************************/
964
965typedef struct {
966 Py_buffer view;
967 Py_ssize_t array[1];
968} Py_buffer_full;
969
970int
971PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
972{
973 Py_buffer_full *fb = NULL;
974 int ret;
975
976 assert(order == 'C' || order == 'F' || order == 'A');
977
978 if (len != src->len) {
979 PyErr_SetString(PyExc_ValueError,
980 "PyBuffer_ToContiguous: len != view->len");
981 return -1;
982 }
983
984 if (PyBuffer_IsContiguous(src, order)) {
985 memcpy((char *)buf, src->buf, len);
986 return 0;
987 }
988
989 /* buffer_to_contiguous() assumes PyBUF_FULL */
990 fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array));
991 if (fb == NULL) {
992 PyErr_NoMemory();
993 return -1;
994 }
995 fb->view.ndim = src->ndim;
996 fb->view.shape = fb->array;
997 fb->view.strides = fb->array + src->ndim;
998 fb->view.suboffsets = fb->array + 2 * src->ndim;
999
1000 init_shared_values(&fb->view, src);
1001 init_shape_strides(&fb->view, src);
1002 init_suboffsets(&fb->view, src);
1003
1004 src = &fb->view;
1005
1006 ret = buffer_to_contiguous(buf, src, order);
1007 PyMem_Free(fb);
1008 return ret;
1009}
1010
1011
1012/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001013/* Release/GC management */
1014/****************************************************************************/
1015
1016/* Inform the managed buffer that this particular memoryview will not access
1017 the underlying buffer again. If no other memoryviews are registered with
1018 the managed buffer, the underlying buffer is released instantly and
1019 marked as inaccessible for both the memoryview and the managed buffer.
1020
1021 This function fails if the memoryview itself has exported buffers. */
1022static int
1023_memory_release(PyMemoryViewObject *self)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001024{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001025 if (self->flags & _Py_MEMORYVIEW_RELEASED)
1026 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001027
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001028 if (self->exports == 0) {
1029 self->flags |= _Py_MEMORYVIEW_RELEASED;
1030 assert(self->mbuf->exports > 0);
1031 if (--self->mbuf->exports == 0)
1032 mbuf_release(self->mbuf);
1033 return 0;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001034 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001035 if (self->exports > 0) {
1036 PyErr_Format(PyExc_BufferError,
1037 "memoryview has %zd exported buffer%s", self->exports,
1038 self->exports==1 ? "" : "s");
1039 return -1;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001040 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001041
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001042 Py_FatalError("_memory_release(): negative export count");
1043 return -1;
1044}
1045
1046static PyObject *
Stefan Krahe4c07992012-07-28 14:10:02 +02001047memory_release(PyMemoryViewObject *self, PyObject *noargs)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001048{
1049 if (_memory_release(self) < 0)
1050 return NULL;
1051 Py_RETURN_NONE;
1052}
1053
1054static void
1055memory_dealloc(PyMemoryViewObject *self)
1056{
1057 assert(self->exports == 0);
1058 _PyObject_GC_UNTRACK(self);
1059 (void)_memory_release(self);
1060 Py_CLEAR(self->mbuf);
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01001061 if (self->weakreflist != NULL)
1062 PyObject_ClearWeakRefs((PyObject *) self);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001063 PyObject_GC_Del(self);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001064}
1065
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001066static int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001067memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001068{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001069 Py_VISIT(self->mbuf);
1070 return 0;
1071}
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001072
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001073static int
1074memory_clear(PyMemoryViewObject *self)
1075{
1076 (void)_memory_release(self);
1077 Py_CLEAR(self->mbuf);
1078 return 0;
1079}
1080
1081static PyObject *
1082memory_enter(PyObject *self, PyObject *args)
1083{
1084 CHECK_RELEASED(self);
1085 Py_INCREF(self);
1086 return self;
1087}
1088
1089static PyObject *
1090memory_exit(PyObject *self, PyObject *args)
1091{
Stefan Krahe4c07992012-07-28 14:10:02 +02001092 return memory_release((PyMemoryViewObject *)self, NULL);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001093}
1094
1095
1096/****************************************************************************/
1097/* Casting format and shape */
1098/****************************************************************************/
1099
1100#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
1101
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001102static inline Py_ssize_t
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001103get_native_fmtchar(char *result, const char *fmt)
1104{
1105 Py_ssize_t size = -1;
1106
1107 if (fmt[0] == '@') fmt++;
1108
1109 switch (fmt[0]) {
1110 case 'c': case 'b': case 'B': size = sizeof(char); break;
1111 case 'h': case 'H': size = sizeof(short); break;
1112 case 'i': case 'I': size = sizeof(int); break;
1113 case 'l': case 'L': size = sizeof(long); break;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001114 case 'q': case 'Q': size = sizeof(long long); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001115 case 'n': case 'N': size = sizeof(Py_ssize_t); break;
1116 case 'f': size = sizeof(float); break;
1117 case 'd': size = sizeof(double); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001118 case '?': size = sizeof(_Bool); break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001119 case 'P': size = sizeof(void *); break;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001120 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001121
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001122 if (size > 0 && fmt[1] == '\0') {
1123 *result = fmt[0];
1124 return size;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001125 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001126
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001127 return -1;
1128}
1129
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001130static inline const char *
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001131get_native_fmtstr(const char *fmt)
1132{
1133 int at = 0;
1134
1135 if (fmt[0] == '@') {
1136 at = 1;
1137 fmt++;
1138 }
1139 if (fmt[0] == '\0' || fmt[1] != '\0') {
1140 return NULL;
1141 }
1142
1143#define RETURN(s) do { return at ? "@" s : s; } while (0)
1144
1145 switch (fmt[0]) {
1146 case 'c': RETURN("c");
1147 case 'b': RETURN("b");
1148 case 'B': RETURN("B");
1149 case 'h': RETURN("h");
1150 case 'H': RETURN("H");
1151 case 'i': RETURN("i");
1152 case 'I': RETURN("I");
1153 case 'l': RETURN("l");
1154 case 'L': RETURN("L");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001155 case 'q': RETURN("q");
1156 case 'Q': RETURN("Q");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001157 case 'n': RETURN("n");
1158 case 'N': RETURN("N");
1159 case 'f': RETURN("f");
1160 case 'd': RETURN("d");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001161 case '?': RETURN("?");
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001162 case 'P': RETURN("P");
1163 }
1164
1165 return NULL;
1166}
1167
1168
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001169/* Cast a memoryview's data type to 'format'. The input array must be
1170 C-contiguous. At least one of input-format, output-format must have
1171 byte size. The output array is 1-D, with the same byte length as the
1172 input array. Thus, view->len must be a multiple of the new itemsize. */
1173static int
1174cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
1175{
1176 Py_buffer *view = &mv->view;
1177 PyObject *asciifmt;
1178 char srcchar, destchar;
1179 Py_ssize_t itemsize;
1180 int ret = -1;
1181
1182 assert(view->ndim >= 1);
1183 assert(Py_SIZE(mv) == 3*view->ndim);
1184 assert(view->shape == mv->ob_array);
1185 assert(view->strides == mv->ob_array + view->ndim);
1186 assert(view->suboffsets == mv->ob_array + 2*view->ndim);
1187
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001188 asciifmt = PyUnicode_AsASCIIString(format);
1189 if (asciifmt == NULL)
1190 return ret;
1191
1192 itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt));
1193 if (itemsize < 0) {
1194 PyErr_SetString(PyExc_ValueError,
1195 "memoryview: destination format must be a native single "
1196 "character format prefixed with an optional '@'");
1197 goto out;
1198 }
1199
Stefan Krah0c515952015-08-08 13:38:10 +02001200 if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
1201 !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001202 PyErr_SetString(PyExc_TypeError,
1203 "memoryview: cannot cast between two non-byte formats");
1204 goto out;
1205 }
1206 if (view->len % itemsize) {
1207 PyErr_SetString(PyExc_TypeError,
1208 "memoryview: length is not a multiple of itemsize");
1209 goto out;
1210 }
1211
Serhiy Storchakaef1585e2015-12-25 20:01:53 +02001212 view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
Stefan Krahfa5d6a52015-01-29 14:27:23 +01001213 if (view->format == NULL) {
1214 /* NOT_REACHED: get_native_fmtchar() already validates the format. */
1215 PyErr_SetString(PyExc_RuntimeError,
1216 "memoryview: internal error");
1217 goto out;
1218 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001219 view->itemsize = itemsize;
1220
1221 view->ndim = 1;
1222 view->shape[0] = view->len / view->itemsize;
1223 view->strides[0] = view->itemsize;
1224 view->suboffsets = NULL;
1225
1226 init_flags(mv);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02001227
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001228 ret = 0;
1229
1230out:
1231 Py_DECREF(asciifmt);
1232 return ret;
1233}
1234
1235/* The memoryview must have space for 3*len(seq) elements. */
1236static Py_ssize_t
1237copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim,
1238 Py_ssize_t itemsize)
1239{
1240 Py_ssize_t x, i;
1241 Py_ssize_t len = itemsize;
1242
1243 for (i = 0; i < ndim; i++) {
1244 PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i);
1245 if (!PyLong_Check(tmp)) {
1246 PyErr_SetString(PyExc_TypeError,
1247 "memoryview.cast(): elements of shape must be integers");
1248 return -1;
1249 }
1250 x = PyLong_AsSsize_t(tmp);
1251 if (x == -1 && PyErr_Occurred()) {
1252 return -1;
1253 }
1254 if (x <= 0) {
1255 /* In general elements of shape may be 0, but not for casting. */
1256 PyErr_Format(PyExc_ValueError,
1257 "memoryview.cast(): elements of shape must be integers > 0");
1258 return -1;
1259 }
1260 if (x > PY_SSIZE_T_MAX / len) {
1261 PyErr_Format(PyExc_ValueError,
1262 "memoryview.cast(): product(shape) > SSIZE_MAX");
1263 return -1;
1264 }
1265 len *= x;
1266 shape[i] = x;
1267 }
1268
1269 return len;
1270}
1271
1272/* Cast a 1-D array to a new shape. The result array will be C-contiguous.
1273 If the result array does not have exactly the same byte length as the
1274 input array, raise ValueError. */
1275static int
1276cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim)
1277{
1278 Py_buffer *view = &mv->view;
1279 Py_ssize_t len;
1280
1281 assert(view->ndim == 1); /* ndim from cast_to_1D() */
1282 assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */
1283 assert(view->shape == mv->ob_array);
1284 assert(view->strides == mv->ob_array + (ndim==0?1:ndim));
1285 assert(view->suboffsets == NULL);
1286
1287 view->ndim = ndim;
1288 if (view->ndim == 0) {
1289 view->shape = NULL;
1290 view->strides = NULL;
1291 len = view->itemsize;
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001292 }
1293 else {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001294 len = copy_shape(view->shape, shape, ndim, view->itemsize);
1295 if (len < 0)
1296 return -1;
1297 init_strides_from_shape(view);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001298 }
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001299
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001300 if (view->len != len) {
1301 PyErr_SetString(PyExc_TypeError,
1302 "memoryview: product(shape) * itemsize != buffer size");
1303 return -1;
1304 }
1305
1306 init_flags(mv);
1307
1308 return 0;
1309}
1310
1311static int
1312zero_in_shape(PyMemoryViewObject *mv)
1313{
1314 Py_buffer *view = &mv->view;
1315 Py_ssize_t i;
1316
1317 for (i = 0; i < view->ndim; i++)
1318 if (view->shape[i] == 0)
1319 return 1;
1320
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001321 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001322}
1323
Guido van Rossum5dde61d2007-09-25 22:10:05 +00001324/*
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001325 Cast a copy of 'self' to a different view. The input view must
1326 be C-contiguous. The function always casts the input view to a
1327 1-D output according to 'format'. At least one of input-format,
1328 output-format must have byte size.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001329
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001330 If 'shape' is given, the 1-D view from the previous step will
1331 be cast to a C-contiguous view with new shape and strides.
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001332
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001333 All casts must result in views that will have the exact byte
1334 size of the original input. Otherwise, an error is raised.
1335*/
1336static PyObject *
1337memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001338{
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001339 static char *kwlist[] = {"format", "shape", NULL};
1340 PyMemoryViewObject *mv = NULL;
1341 PyObject *shape = NULL;
1342 PyObject *format;
1343 Py_ssize_t ndim = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001344
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001345 CHECK_RELEASED(self);
1346
1347 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
1348 &format, &shape)) {
1349 return NULL;
1350 }
1351 if (!PyUnicode_Check(format)) {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001352 PyErr_SetString(PyExc_TypeError,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001353 "memoryview: format argument must be a string");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001354 return NULL;
1355 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001356 if (!MV_C_CONTIGUOUS(self->flags)) {
1357 PyErr_SetString(PyExc_TypeError,
1358 "memoryview: casts are restricted to C-contiguous views");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001359 return NULL;
1360 }
Antoine Pitrou60b18342013-10-03 19:55:41 +02001361 if ((shape || self->view.ndim != 1) && zero_in_shape(self)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001362 PyErr_SetString(PyExc_TypeError,
1363 "memoryview: cannot cast view with zeros in shape or strides");
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001364 return NULL;
1365 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001366 if (shape) {
1367 CHECK_LIST_OR_TUPLE(shape)
1368 ndim = PySequence_Fast_GET_SIZE(shape);
1369 if (ndim > PyBUF_MAX_NDIM) {
1370 PyErr_SetString(PyExc_ValueError,
1371 "memoryview: number of dimensions must not exceed "
Victor Stinner45e8e2f2014-05-14 17:24:35 +02001372 Py_STRINGIFY(PyBUF_MAX_NDIM));
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001373 return NULL;
1374 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001375 if (self->view.ndim != 1 && ndim != 1) {
1376 PyErr_SetString(PyExc_TypeError,
1377 "memoryview: cast must be 1D -> ND or ND -> 1D");
1378 return NULL;
1379 }
Antoine Pitrou35b7e832009-01-03 19:20:36 +00001380 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001381
1382 mv = (PyMemoryViewObject *)
1383 mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim);
1384 if (mv == NULL)
1385 return NULL;
1386
1387 if (cast_to_1D(mv, format) < 0)
1388 goto error;
1389 if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
1390 goto error;
1391
1392 return (PyObject *)mv;
1393
1394error:
1395 Py_DECREF(mv);
1396 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00001397}
1398
1399
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001400/**************************************************************************/
1401/* getbuffer */
1402/**************************************************************************/
1403
1404static int
1405memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
1406{
1407 Py_buffer *base = &self->view;
1408 int baseflags = self->flags;
1409
1410 CHECK_RELEASED_INT(self);
1411
1412 /* start with complete information */
1413 *view = *base;
1414 view->obj = NULL;
1415
1416 if (REQ_WRITABLE(flags) && base->readonly) {
1417 PyErr_SetString(PyExc_BufferError,
1418 "memoryview: underlying buffer is not writable");
1419 return -1;
1420 }
1421 if (!REQ_FORMAT(flags)) {
1422 /* NULL indicates that the buffer's data type has been cast to 'B'.
1423 view->itemsize is the _previous_ itemsize. If shape is present,
1424 the equality product(shape) * itemsize = len still holds at this
1425 point. The equality calcsize(format) = itemsize does _not_ hold
1426 from here on! */
1427 view->format = NULL;
1428 }
1429
1430 if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) {
1431 PyErr_SetString(PyExc_BufferError,
1432 "memoryview: underlying buffer is not C-contiguous");
1433 return -1;
1434 }
1435 if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) {
1436 PyErr_SetString(PyExc_BufferError,
1437 "memoryview: underlying buffer is not Fortran contiguous");
1438 return -1;
1439 }
1440 if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) {
1441 PyErr_SetString(PyExc_BufferError,
1442 "memoryview: underlying buffer is not contiguous");
1443 return -1;
1444 }
1445 if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) {
1446 PyErr_SetString(PyExc_BufferError,
1447 "memoryview: underlying buffer requires suboffsets");
1448 return -1;
1449 }
1450 if (!REQ_STRIDES(flags)) {
1451 if (!MV_C_CONTIGUOUS(baseflags)) {
1452 PyErr_SetString(PyExc_BufferError,
1453 "memoryview: underlying buffer is not C-contiguous");
1454 return -1;
1455 }
1456 view->strides = NULL;
1457 }
1458 if (!REQ_SHAPE(flags)) {
1459 /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous,
1460 so base->buf = ndbuf->data. */
1461 if (view->format != NULL) {
1462 /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do
1463 not make sense. */
1464 PyErr_Format(PyExc_BufferError,
Stefan Krah674a42b2013-02-19 13:44:49 +01001465 "memoryview: cannot cast to unsigned bytes if the format flag "
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001466 "is present");
1467 return -1;
1468 }
1469 /* product(shape) * itemsize = len and calcsize(format) = itemsize
1470 do _not_ hold from here on! */
1471 view->ndim = 1;
1472 view->shape = NULL;
1473 }
1474
1475
1476 view->obj = (PyObject *)self;
1477 Py_INCREF(view->obj);
1478 self->exports++;
1479
1480 return 0;
1481}
1482
1483static void
1484memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
1485{
1486 self->exports--;
1487 return;
1488 /* PyBuffer_Release() decrements view->obj after this function returns. */
1489}
1490
1491/* Buffer methods */
1492static PyBufferProcs memory_as_buffer = {
1493 (getbufferproc)memory_getbuf, /* bf_getbuffer */
1494 (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
1495};
1496
1497
1498/****************************************************************************/
1499/* Optimized pack/unpack for all native format specifiers */
1500/****************************************************************************/
1501
1502/*
1503 Fix exceptions:
1504 1) Include format string in the error message.
1505 2) OverflowError -> ValueError.
1506 3) The error message from PyNumber_Index() is not ideal.
1507*/
1508static int
1509type_error_int(const char *fmt)
1510{
1511 PyErr_Format(PyExc_TypeError,
1512 "memoryview: invalid type for format '%s'", fmt);
1513 return -1;
1514}
1515
1516static int
1517value_error_int(const char *fmt)
1518{
1519 PyErr_Format(PyExc_ValueError,
1520 "memoryview: invalid value for format '%s'", fmt);
1521 return -1;
1522}
1523
1524static int
1525fix_error_int(const char *fmt)
1526{
1527 assert(PyErr_Occurred());
1528 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1529 PyErr_Clear();
1530 return type_error_int(fmt);
1531 }
1532 else if (PyErr_ExceptionMatches(PyExc_OverflowError) ||
1533 PyErr_ExceptionMatches(PyExc_ValueError)) {
1534 PyErr_Clear();
1535 return value_error_int(fmt);
1536 }
1537
1538 return -1;
1539}
1540
1541/* Accept integer objects or objects with an __index__() method. */
1542static long
1543pylong_as_ld(PyObject *item)
1544{
1545 PyObject *tmp;
1546 long ld;
1547
1548 tmp = PyNumber_Index(item);
1549 if (tmp == NULL)
1550 return -1;
1551
1552 ld = PyLong_AsLong(tmp);
1553 Py_DECREF(tmp);
1554 return ld;
1555}
1556
1557static unsigned long
1558pylong_as_lu(PyObject *item)
1559{
1560 PyObject *tmp;
1561 unsigned long lu;
1562
1563 tmp = PyNumber_Index(item);
1564 if (tmp == NULL)
1565 return (unsigned long)-1;
1566
1567 lu = PyLong_AsUnsignedLong(tmp);
1568 Py_DECREF(tmp);
1569 return lu;
1570}
1571
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001572static long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001573pylong_as_lld(PyObject *item)
1574{
1575 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001576 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001577
1578 tmp = PyNumber_Index(item);
1579 if (tmp == NULL)
1580 return -1;
1581
1582 lld = PyLong_AsLongLong(tmp);
1583 Py_DECREF(tmp);
1584 return lld;
1585}
1586
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001587static unsigned long long
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001588pylong_as_llu(PyObject *item)
1589{
1590 PyObject *tmp;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001591 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001592
1593 tmp = PyNumber_Index(item);
1594 if (tmp == NULL)
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001595 return (unsigned long long)-1;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001596
1597 llu = PyLong_AsUnsignedLongLong(tmp);
1598 Py_DECREF(tmp);
1599 return llu;
1600}
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001601
1602static Py_ssize_t
1603pylong_as_zd(PyObject *item)
1604{
1605 PyObject *tmp;
1606 Py_ssize_t zd;
1607
1608 tmp = PyNumber_Index(item);
1609 if (tmp == NULL)
1610 return -1;
1611
1612 zd = PyLong_AsSsize_t(tmp);
1613 Py_DECREF(tmp);
1614 return zd;
1615}
1616
1617static size_t
1618pylong_as_zu(PyObject *item)
1619{
1620 PyObject *tmp;
1621 size_t zu;
1622
1623 tmp = PyNumber_Index(item);
1624 if (tmp == NULL)
1625 return (size_t)-1;
1626
1627 zu = PyLong_AsSize_t(tmp);
1628 Py_DECREF(tmp);
1629 return zu;
1630}
1631
1632/* Timings with the ndarray from _testbuffer.c indicate that using the
1633 struct module is around 15x slower than the two functions below. */
1634
1635#define UNPACK_SINGLE(dest, ptr, type) \
1636 do { \
1637 type x; \
1638 memcpy((char *)&x, ptr, sizeof x); \
1639 dest = x; \
1640 } while (0)
1641
1642/* Unpack a single item. 'fmt' can be any native format character in struct
1643 module syntax. This function is very sensitive to small changes. With this
1644 layout gcc automatically generates a fast jump table. */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07001645static inline PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001646unpack_single(const char *ptr, const char *fmt)
1647{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001648 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001649 unsigned long lu;
1650 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001651 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001652 long ld;
1653 Py_ssize_t zd;
1654 double d;
1655 unsigned char uc;
1656 void *p;
1657
1658 switch (fmt[0]) {
1659
1660 /* signed integers and fast path for 'B' */
1661 case 'B': uc = *((unsigned char *)ptr); goto convert_uc;
1662 case 'b': ld = *((signed char *)ptr); goto convert_ld;
1663 case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld;
1664 case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld;
1665 case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
1666
1667 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001668 case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001669
1670 /* unsigned integers */
1671 case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
1672 case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu;
1673 case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
1674
1675 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001676 case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
1677 case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001678
1679 /* ssize_t and size_t */
1680 case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
1681 case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu;
1682
1683 /* floats */
1684 case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
1685 case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1686
1687 /* bytes object */
1688 case 'c': goto convert_bytes;
1689
1690 /* pointer */
1691 case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer;
1692
1693 /* default */
1694 default: goto err_format;
1695 }
1696
1697convert_uc:
1698 /* PyLong_FromUnsignedLong() is slower */
1699 return PyLong_FromLong(uc);
1700convert_ld:
1701 return PyLong_FromLong(ld);
1702convert_lu:
1703 return PyLong_FromUnsignedLong(lu);
1704convert_lld:
1705 return PyLong_FromLongLong(lld);
1706convert_llu:
1707 return PyLong_FromUnsignedLongLong(llu);
1708convert_zd:
1709 return PyLong_FromSsize_t(zd);
1710convert_zu:
1711 return PyLong_FromSize_t(zu);
1712convert_double:
1713 return PyFloat_FromDouble(d);
1714convert_bool:
1715 return PyBool_FromLong(ld);
1716convert_bytes:
1717 return PyBytes_FromStringAndSize(ptr, 1);
1718convert_pointer:
1719 return PyLong_FromVoidPtr(p);
1720err_format:
1721 PyErr_Format(PyExc_NotImplementedError,
1722 "memoryview: format %s not supported", fmt);
1723 return NULL;
1724}
1725
1726#define PACK_SINGLE(ptr, src, type) \
1727 do { \
1728 type x; \
1729 x = (type)src; \
1730 memcpy(ptr, (char *)&x, sizeof x); \
1731 } while (0)
1732
1733/* Pack a single item. 'fmt' can be any native format character in
1734 struct module syntax. */
1735static int
1736pack_single(char *ptr, PyObject *item, const char *fmt)
1737{
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001738 unsigned long long llu;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001739 unsigned long lu;
1740 size_t zu;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001741 long long lld;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001742 long ld;
1743 Py_ssize_t zd;
1744 double d;
1745 void *p;
1746
1747 switch (fmt[0]) {
1748 /* signed integers */
1749 case 'b': case 'h': case 'i': case 'l':
1750 ld = pylong_as_ld(item);
1751 if (ld == -1 && PyErr_Occurred())
1752 goto err_occurred;
1753 switch (fmt[0]) {
1754 case 'b':
1755 if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range;
1756 *((signed char *)ptr) = (signed char)ld; break;
1757 case 'h':
1758 if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range;
1759 PACK_SINGLE(ptr, ld, short); break;
1760 case 'i':
1761 if (ld < INT_MIN || ld > INT_MAX) goto err_range;
1762 PACK_SINGLE(ptr, ld, int); break;
1763 default: /* 'l' */
1764 PACK_SINGLE(ptr, ld, long); break;
1765 }
1766 break;
1767
1768 /* unsigned integers */
1769 case 'B': case 'H': case 'I': case 'L':
1770 lu = pylong_as_lu(item);
1771 if (lu == (unsigned long)-1 && PyErr_Occurred())
1772 goto err_occurred;
1773 switch (fmt[0]) {
1774 case 'B':
1775 if (lu > UCHAR_MAX) goto err_range;
1776 *((unsigned char *)ptr) = (unsigned char)lu; break;
1777 case 'H':
1778 if (lu > USHRT_MAX) goto err_range;
1779 PACK_SINGLE(ptr, lu, unsigned short); break;
1780 case 'I':
1781 if (lu > UINT_MAX) goto err_range;
1782 PACK_SINGLE(ptr, lu, unsigned int); break;
1783 default: /* 'L' */
1784 PACK_SINGLE(ptr, lu, unsigned long); break;
1785 }
1786 break;
1787
1788 /* native 64-bit */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001789 case 'q':
1790 lld = pylong_as_lld(item);
1791 if (lld == -1 && PyErr_Occurred())
1792 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001793 PACK_SINGLE(ptr, lld, long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001794 break;
1795 case 'Q':
1796 llu = pylong_as_llu(item);
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001797 if (llu == (unsigned long long)-1 && PyErr_Occurred())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001798 goto err_occurred;
Benjamin Petersonaf580df2016-09-06 10:46:49 -07001799 PACK_SINGLE(ptr, llu, unsigned long long);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001800 break;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001801
1802 /* ssize_t and size_t */
1803 case 'n':
1804 zd = pylong_as_zd(item);
1805 if (zd == -1 && PyErr_Occurred())
1806 goto err_occurred;
1807 PACK_SINGLE(ptr, zd, Py_ssize_t);
1808 break;
1809 case 'N':
1810 zu = pylong_as_zu(item);
1811 if (zu == (size_t)-1 && PyErr_Occurred())
1812 goto err_occurred;
1813 PACK_SINGLE(ptr, zu, size_t);
1814 break;
1815
1816 /* floats */
1817 case 'f': case 'd':
1818 d = PyFloat_AsDouble(item);
1819 if (d == -1.0 && PyErr_Occurred())
1820 goto err_occurred;
1821 if (fmt[0] == 'f') {
1822 PACK_SINGLE(ptr, d, float);
1823 }
1824 else {
1825 PACK_SINGLE(ptr, d, double);
1826 }
1827 break;
1828
1829 /* bool */
1830 case '?':
1831 ld = PyObject_IsTrue(item);
1832 if (ld < 0)
1833 return -1; /* preserve original error */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001834 PACK_SINGLE(ptr, ld, _Bool);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001835 break;
1836
1837 /* bytes object */
1838 case 'c':
1839 if (!PyBytes_Check(item))
1840 return type_error_int(fmt);
1841 if (PyBytes_GET_SIZE(item) != 1)
1842 return value_error_int(fmt);
1843 *ptr = PyBytes_AS_STRING(item)[0];
1844 break;
1845
1846 /* pointer */
1847 case 'P':
1848 p = PyLong_AsVoidPtr(item);
1849 if (p == NULL && PyErr_Occurred())
1850 goto err_occurred;
1851 PACK_SINGLE(ptr, p, void *);
1852 break;
1853
1854 /* default */
1855 default: goto err_format;
1856 }
1857
1858 return 0;
1859
1860err_occurred:
1861 return fix_error_int(fmt);
1862err_range:
1863 return value_error_int(fmt);
1864err_format:
1865 PyErr_Format(PyExc_NotImplementedError,
1866 "memoryview: format %s not supported", fmt);
1867 return -1;
1868}
1869
1870
1871/****************************************************************************/
Nick Coghlan06e1ab02012-08-25 17:59:50 +10001872/* unpack using the struct module */
1873/****************************************************************************/
1874
1875/* For reasonable performance it is necessary to cache all objects required
1876 for unpacking. An unpacker can handle the format passed to unpack_from().
1877 Invariant: All pointer fields of the struct should either be NULL or valid
1878 pointers. */
1879struct unpacker {
1880 PyObject *unpack_from; /* Struct.unpack_from(format) */
1881 PyObject *mview; /* cached memoryview */
1882 char *item; /* buffer for mview */
1883 Py_ssize_t itemsize; /* len(item) */
1884};
1885
1886static struct unpacker *
1887unpacker_new(void)
1888{
1889 struct unpacker *x = PyMem_Malloc(sizeof *x);
1890
1891 if (x == NULL) {
1892 PyErr_NoMemory();
1893 return NULL;
1894 }
1895
1896 x->unpack_from = NULL;
1897 x->mview = NULL;
1898 x->item = NULL;
1899 x->itemsize = 0;
1900
1901 return x;
1902}
1903
1904static void
1905unpacker_free(struct unpacker *x)
1906{
1907 if (x) {
1908 Py_XDECREF(x->unpack_from);
1909 Py_XDECREF(x->mview);
1910 PyMem_Free(x->item);
1911 PyMem_Free(x);
1912 }
1913}
1914
1915/* Return a new unpacker for the given format. */
1916static struct unpacker *
1917struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
1918{
1919 PyObject *structmodule; /* XXX cache these two */
1920 PyObject *Struct = NULL; /* XXX in globals? */
1921 PyObject *structobj = NULL;
1922 PyObject *format = NULL;
1923 struct unpacker *x = NULL;
1924
1925 structmodule = PyImport_ImportModule("struct");
1926 if (structmodule == NULL)
1927 return NULL;
1928
1929 Struct = PyObject_GetAttrString(structmodule, "Struct");
1930 Py_DECREF(structmodule);
1931 if (Struct == NULL)
1932 return NULL;
1933
1934 x = unpacker_new();
1935 if (x == NULL)
1936 goto error;
1937
1938 format = PyBytes_FromString(fmt);
1939 if (format == NULL)
1940 goto error;
1941
1942 structobj = PyObject_CallFunctionObjArgs(Struct, format, NULL);
1943 if (structobj == NULL)
1944 goto error;
1945
1946 x->unpack_from = PyObject_GetAttrString(structobj, "unpack_from");
1947 if (x->unpack_from == NULL)
1948 goto error;
1949
1950 x->item = PyMem_Malloc(itemsize);
1951 if (x->item == NULL) {
1952 PyErr_NoMemory();
1953 goto error;
1954 }
1955 x->itemsize = itemsize;
1956
1957 x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE);
1958 if (x->mview == NULL)
1959 goto error;
1960
1961
1962out:
1963 Py_XDECREF(Struct);
1964 Py_XDECREF(format);
1965 Py_XDECREF(structobj);
1966 return x;
1967
1968error:
1969 unpacker_free(x);
1970 x = NULL;
1971 goto out;
1972}
1973
1974/* unpack a single item */
1975static PyObject *
1976struct_unpack_single(const char *ptr, struct unpacker *x)
1977{
1978 PyObject *v;
1979
1980 memcpy(x->item, ptr, x->itemsize);
1981 v = PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL);
1982 if (v == NULL)
1983 return NULL;
1984
1985 if (PyTuple_GET_SIZE(v) == 1) {
1986 PyObject *tmp = PyTuple_GET_ITEM(v, 0);
1987 Py_INCREF(tmp);
1988 Py_DECREF(v);
1989 return tmp;
1990 }
1991
1992 return v;
1993}
1994
1995
1996/****************************************************************************/
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001997/* Representations */
1998/****************************************************************************/
1999
2000/* allow explicit form of native format */
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002001static inline const char *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002002adjust_fmt(const Py_buffer *view)
2003{
2004 const char *fmt;
2005
2006 fmt = (view->format[0] == '@') ? view->format+1 : view->format;
2007 if (fmt[0] && fmt[1] == '\0')
2008 return fmt;
2009
2010 PyErr_Format(PyExc_NotImplementedError,
2011 "memoryview: unsupported format %s", view->format);
2012 return NULL;
2013}
2014
2015/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */
2016static PyObject *
2017tolist_base(const char *ptr, const Py_ssize_t *shape,
2018 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2019 const char *fmt)
2020{
2021 PyObject *lst, *item;
2022 Py_ssize_t i;
2023
2024 lst = PyList_New(shape[0]);
2025 if (lst == NULL)
2026 return NULL;
2027
2028 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002029 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002030 item = unpack_single(xptr, fmt);
2031 if (item == NULL) {
2032 Py_DECREF(lst);
2033 return NULL;
2034 }
2035 PyList_SET_ITEM(lst, i, item);
2036 }
2037
2038 return lst;
2039}
2040
2041/* Unpack a multi-dimensional array into a nested list.
2042 Assumption: ndim >= 1. */
2043static PyObject *
2044tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape,
2045 const Py_ssize_t *strides, const Py_ssize_t *suboffsets,
2046 const char *fmt)
2047{
2048 PyObject *lst, *item;
2049 Py_ssize_t i;
2050
2051 assert(ndim >= 1);
2052 assert(shape != NULL);
2053 assert(strides != NULL);
2054
2055 if (ndim == 1)
2056 return tolist_base(ptr, shape, strides, suboffsets, fmt);
2057
2058 lst = PyList_New(shape[0]);
2059 if (lst == NULL)
2060 return NULL;
2061
2062 for (i = 0; i < shape[0]; ptr+=strides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002063 const char *xptr = ADJUST_PTR(ptr, suboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002064 item = tolist_rec(xptr, ndim-1, shape+1,
2065 strides+1, suboffsets ? suboffsets+1 : NULL,
2066 fmt);
2067 if (item == NULL) {
2068 Py_DECREF(lst);
2069 return NULL;
2070 }
2071 PyList_SET_ITEM(lst, i, item);
2072 }
2073
2074 return lst;
2075}
2076
2077/* Return a list representation of the memoryview. Currently only buffers
2078 with native format strings are supported. */
2079static PyObject *
2080memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
2081{
2082 const Py_buffer *view = &(mv->view);
2083 const char *fmt;
2084
2085 CHECK_RELEASED(mv);
2086
2087 fmt = adjust_fmt(view);
2088 if (fmt == NULL)
2089 return NULL;
2090 if (view->ndim == 0) {
2091 return unpack_single(view->buf, fmt);
2092 }
2093 else if (view->ndim == 1) {
2094 return tolist_base(view->buf, view->shape,
2095 view->strides, view->suboffsets,
2096 fmt);
2097 }
2098 else {
2099 return tolist_rec(view->buf, view->ndim, view->shape,
2100 view->strides, view->suboffsets,
2101 fmt);
2102 }
2103}
2104
2105static PyObject *
2106memory_tobytes(PyMemoryViewObject *self, PyObject *dummy)
2107{
2108 Py_buffer *src = VIEW_ADDR(self);
2109 PyObject *bytes = NULL;
2110
2111 CHECK_RELEASED(self);
2112
2113 if (MV_C_CONTIGUOUS(self->flags)) {
2114 return PyBytes_FromStringAndSize(src->buf, src->len);
2115 }
2116
2117 bytes = PyBytes_FromStringAndSize(NULL, src->len);
2118 if (bytes == NULL)
2119 return NULL;
2120
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002121 if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002122 Py_DECREF(bytes);
2123 return NULL;
2124 }
2125
2126 return bytes;
2127}
2128
2129static PyObject *
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002130memory_hex(PyMemoryViewObject *self, PyObject *dummy)
2131{
2132 Py_buffer *src = VIEW_ADDR(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002133 PyObject *bytes;
2134 PyObject *ret;
2135
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002136 CHECK_RELEASED(self);
Stefan Krah0ce5b6e2015-11-10 18:17:22 +01002137
2138 if (MV_C_CONTIGUOUS(self->flags)) {
2139 return _Py_strhex(src->buf, src->len);
2140 }
2141
2142 bytes = memory_tobytes(self, dummy);
2143 if (bytes == NULL)
2144 return NULL;
2145
2146 ret = _Py_strhex(PyBytes_AS_STRING(bytes), Py_SIZE(bytes));
2147 Py_DECREF(bytes);
2148
2149 return ret;
Gregory P. Smith8cb65692015-04-25 23:22:26 +00002150}
2151
2152static PyObject *
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002153memory_repr(PyMemoryViewObject *self)
2154{
2155 if (self->flags & _Py_MEMORYVIEW_RELEASED)
2156 return PyUnicode_FromFormat("<released memory at %p>", self);
2157 else
2158 return PyUnicode_FromFormat("<memory at %p>", self);
2159}
2160
2161
2162/**************************************************************************/
2163/* Indexing and slicing */
2164/**************************************************************************/
2165
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002166static char *
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002167lookup_dimension(Py_buffer *view, char *ptr, int dim, Py_ssize_t index)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002168{
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002169 Py_ssize_t nitems; /* items in the given dimension */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002170
2171 assert(view->shape);
2172 assert(view->strides);
2173
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002174 nitems = view->shape[dim];
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002175 if (index < 0) {
2176 index += nitems;
2177 }
2178 if (index < 0 || index >= nitems) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002179 PyErr_Format(PyExc_IndexError,
2180 "index out of bounds on dimension %d", dim + 1);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002181 return NULL;
2182 }
2183
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002184 ptr += view->strides[dim] * index;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002185
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002186 ptr = ADJUST_PTR(ptr, view->suboffsets, dim);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002187
2188 return ptr;
2189}
2190
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002191/* Get the pointer to the item at index. */
2192static char *
2193ptr_from_index(Py_buffer *view, Py_ssize_t index)
2194{
2195 char *ptr = (char *)view->buf;
2196 return lookup_dimension(view, ptr, 0, index);
2197}
2198
2199/* Get the pointer to the item at tuple. */
2200static char *
2201ptr_from_tuple(Py_buffer *view, PyObject *tup)
2202{
2203 char *ptr = (char *)view->buf;
2204 Py_ssize_t dim, nindices = PyTuple_GET_SIZE(tup);
2205
2206 if (nindices > view->ndim) {
2207 PyErr_Format(PyExc_TypeError,
2208 "cannot index %zd-dimension view with %zd-element tuple",
2209 view->ndim, nindices);
2210 return NULL;
2211 }
2212
2213 for (dim = 0; dim < nindices; dim++) {
2214 Py_ssize_t index;
2215 index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, dim),
2216 PyExc_IndexError);
2217 if (index == -1 && PyErr_Occurred())
2218 return NULL;
Stefan Krah7c3f3852015-11-10 18:35:19 +01002219 ptr = lookup_dimension(view, ptr, (int)dim, index);
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002220 if (ptr == NULL)
2221 return NULL;
2222 }
2223 return ptr;
2224}
2225
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002226/* Return the item at index. In a one-dimensional view, this is an object
2227 with the type specified by view->format. Otherwise, the item is a sub-view.
2228 The function is used in memory_subscript() and memory_as_sequence. */
2229static PyObject *
2230memory_item(PyMemoryViewObject *self, Py_ssize_t index)
2231{
2232 Py_buffer *view = &(self->view);
2233 const char *fmt;
2234
2235 CHECK_RELEASED(self);
2236
2237 fmt = adjust_fmt(view);
2238 if (fmt == NULL)
2239 return NULL;
2240
2241 if (view->ndim == 0) {
2242 PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory");
2243 return NULL;
2244 }
2245 if (view->ndim == 1) {
2246 char *ptr = ptr_from_index(view, index);
2247 if (ptr == NULL)
2248 return NULL;
2249 return unpack_single(ptr, fmt);
2250 }
2251
2252 PyErr_SetString(PyExc_NotImplementedError,
2253 "multi-dimensional sub-views are not implemented");
2254 return NULL;
2255}
2256
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002257/* Return the item at position *key* (a tuple of indices). */
2258static PyObject *
2259memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
2260{
2261 Py_buffer *view = &(self->view);
2262 const char *fmt;
2263 Py_ssize_t nindices = PyTuple_GET_SIZE(tup);
2264 char *ptr;
2265
2266 CHECK_RELEASED(self);
2267
2268 fmt = adjust_fmt(view);
2269 if (fmt == NULL)
2270 return NULL;
2271
2272 if (nindices < view->ndim) {
2273 PyErr_SetString(PyExc_NotImplementedError,
2274 "sub-views are not implemented");
2275 return NULL;
2276 }
2277 ptr = ptr_from_tuple(view, tup);
2278 if (ptr == NULL)
2279 return NULL;
2280 return unpack_single(ptr, fmt);
2281}
2282
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002283static inline int
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002284init_slice(Py_buffer *base, PyObject *key, int dim)
2285{
2286 Py_ssize_t start, stop, step, slicelength;
2287
2288 if (PySlice_GetIndicesEx(key, base->shape[dim],
2289 &start, &stop, &step, &slicelength) < 0) {
2290 return -1;
2291 }
2292
2293
2294 if (base->suboffsets == NULL || dim == 0) {
2295 adjust_buf:
2296 base->buf = (char *)base->buf + base->strides[dim] * start;
2297 }
2298 else {
2299 Py_ssize_t n = dim-1;
2300 while (n >= 0 && base->suboffsets[n] < 0)
2301 n--;
2302 if (n < 0)
2303 goto adjust_buf; /* all suboffsets are negative */
2304 base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start;
2305 }
2306 base->shape[dim] = slicelength;
2307 base->strides[dim] = base->strides[dim] * step;
2308
2309 return 0;
2310}
2311
2312static int
2313is_multislice(PyObject *key)
2314{
2315 Py_ssize_t size, i;
2316
2317 if (!PyTuple_Check(key))
2318 return 0;
2319 size = PyTuple_GET_SIZE(key);
2320 if (size == 0)
2321 return 0;
2322
2323 for (i = 0; i < size; i++) {
2324 PyObject *x = PyTuple_GET_ITEM(key, i);
2325 if (!PySlice_Check(x))
2326 return 0;
2327 }
2328 return 1;
2329}
2330
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002331static Py_ssize_t
2332is_multiindex(PyObject *key)
2333{
2334 Py_ssize_t size, i;
2335
2336 if (!PyTuple_Check(key))
2337 return 0;
2338 size = PyTuple_GET_SIZE(key);
2339 for (i = 0; i < size; i++) {
2340 PyObject *x = PyTuple_GET_ITEM(key, i);
2341 if (!PyIndex_Check(x))
2342 return 0;
2343 }
2344 return 1;
2345}
2346
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002347/* mv[obj] returns an object holding the data for one element if obj
2348 fully indexes the memoryview or another memoryview object if it
2349 does not.
2350
2351 0-d memoryview objects can be referenced using mv[...] or mv[()]
2352 but not with anything else. */
2353static PyObject *
2354memory_subscript(PyMemoryViewObject *self, PyObject *key)
2355{
2356 Py_buffer *view;
2357 view = &(self->view);
Serhiy Storchaka009b8112015-03-18 21:53:15 +02002358
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002359 CHECK_RELEASED(self);
2360
2361 if (view->ndim == 0) {
2362 if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) {
2363 const char *fmt = adjust_fmt(view);
2364 if (fmt == NULL)
2365 return NULL;
2366 return unpack_single(view->buf, fmt);
2367 }
2368 else if (key == Py_Ellipsis) {
2369 Py_INCREF(self);
2370 return (PyObject *)self;
2371 }
2372 else {
2373 PyErr_SetString(PyExc_TypeError,
2374 "invalid indexing of 0-dim memory");
2375 return NULL;
2376 }
2377 }
2378
2379 if (PyIndex_Check(key)) {
2380 Py_ssize_t index;
2381 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
2382 if (index == -1 && PyErr_Occurred())
2383 return NULL;
2384 return memory_item(self, index);
2385 }
2386 else if (PySlice_Check(key)) {
2387 PyMemoryViewObject *sliced;
2388
2389 sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view);
2390 if (sliced == NULL)
2391 return NULL;
2392
2393 if (init_slice(&sliced->view, key, 0) < 0) {
2394 Py_DECREF(sliced);
2395 return NULL;
2396 }
2397 init_len(&sliced->view);
2398 init_flags(sliced);
2399
2400 return (PyObject *)sliced;
2401 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002402 else if (is_multiindex(key)) {
2403 return memory_item_multi(self, key);
2404 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002405 else if (is_multislice(key)) {
2406 PyErr_SetString(PyExc_NotImplementedError,
2407 "multi-dimensional slicing is not implemented");
2408 return NULL;
2409 }
2410
2411 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2412 return NULL;
2413}
2414
2415static int
2416memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
2417{
2418 Py_buffer *view = &(self->view);
2419 Py_buffer src;
2420 const char *fmt;
2421 char *ptr;
2422
2423 CHECK_RELEASED_INT(self);
2424
2425 fmt = adjust_fmt(view);
2426 if (fmt == NULL)
2427 return -1;
2428
2429 if (view->readonly) {
2430 PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory");
2431 return -1;
2432 }
2433 if (value == NULL) {
2434 PyErr_SetString(PyExc_TypeError, "cannot delete memory");
2435 return -1;
2436 }
2437 if (view->ndim == 0) {
2438 if (key == Py_Ellipsis ||
2439 (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
2440 ptr = (char *)view->buf;
2441 return pack_single(ptr, value, fmt);
2442 }
2443 else {
2444 PyErr_SetString(PyExc_TypeError,
2445 "invalid indexing of 0-dim memory");
2446 return -1;
2447 }
2448 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002449
2450 if (PyIndex_Check(key)) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002451 Py_ssize_t index;
2452 if (1 < view->ndim) {
2453 PyErr_SetString(PyExc_NotImplementedError,
2454 "sub-views are not implemented");
2455 return -1;
2456 }
2457 index = PyNumber_AsSsize_t(key, PyExc_IndexError);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002458 if (index == -1 && PyErr_Occurred())
2459 return -1;
2460 ptr = ptr_from_index(view, index);
2461 if (ptr == NULL)
2462 return -1;
2463 return pack_single(ptr, value, fmt);
2464 }
2465 /* one-dimensional: fast path */
2466 if (PySlice_Check(key) && view->ndim == 1) {
2467 Py_buffer dest; /* sliced view */
2468 Py_ssize_t arrays[3];
2469 int ret = -1;
2470
2471 /* rvalue must be an exporter */
2472 if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0)
2473 return ret;
2474
2475 dest = *view;
2476 dest.shape = &arrays[0]; dest.shape[0] = view->shape[0];
2477 dest.strides = &arrays[1]; dest.strides[0] = view->strides[0];
2478 if (view->suboffsets) {
2479 dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0];
2480 }
2481
2482 if (init_slice(&dest, key, 0) < 0)
2483 goto end_block;
2484 dest.len = dest.shape[0] * dest.itemsize;
2485
2486 ret = copy_single(&dest, &src);
2487
2488 end_block:
2489 PyBuffer_Release(&src);
2490 return ret;
2491 }
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002492 if (is_multiindex(key)) {
2493 char *ptr;
2494 if (PyTuple_GET_SIZE(key) < view->ndim) {
2495 PyErr_SetString(PyExc_NotImplementedError,
2496 "sub-views are not implemented");
2497 return -1;
2498 }
2499 ptr = ptr_from_tuple(view, key);
2500 if (ptr == NULL)
2501 return -1;
2502 return pack_single(ptr, value, fmt);
2503 }
2504 if (PySlice_Check(key) || is_multislice(key)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002505 /* Call memory_subscript() to produce a sliced lvalue, then copy
2506 rvalue into lvalue. This is already implemented in _testbuffer.c. */
2507 PyErr_SetString(PyExc_NotImplementedError,
2508 "memoryview slice assignments are currently restricted "
2509 "to ndim = 1");
2510 return -1;
2511 }
2512
2513 PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key");
2514 return -1;
2515}
2516
2517static Py_ssize_t
2518memory_length(PyMemoryViewObject *self)
2519{
2520 CHECK_RELEASED_INT(self);
2521 return self->view.ndim == 0 ? 1 : self->view.shape[0];
2522}
2523
2524/* As mapping */
2525static PyMappingMethods memory_as_mapping = {
2526 (lenfunc)memory_length, /* mp_length */
2527 (binaryfunc)memory_subscript, /* mp_subscript */
2528 (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
2529};
2530
2531/* As sequence */
2532static PySequenceMethods memory_as_sequence = {
Nick Coghlana0f169c2013-10-02 22:06:54 +10002533 (lenfunc)memory_length, /* sq_length */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002534 0, /* sq_concat */
2535 0, /* sq_repeat */
2536 (ssizeargfunc)memory_item, /* sq_item */
2537};
2538
2539
2540/**************************************************************************/
2541/* Comparisons */
2542/**************************************************************************/
2543
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002544#define MV_COMPARE_EX -1 /* exception */
2545#define MV_COMPARE_NOT_IMPL -2 /* not implemented */
2546
2547/* Translate a StructError to "not equal". Preserve other exceptions. */
2548static int
2549fix_struct_error_int(void)
2550{
2551 assert(PyErr_Occurred());
2552 /* XXX Cannot get at StructError directly? */
2553 if (PyErr_ExceptionMatches(PyExc_ImportError) ||
2554 PyErr_ExceptionMatches(PyExc_MemoryError)) {
2555 return MV_COMPARE_EX;
2556 }
2557 /* StructError: invalid or unknown format -> not equal */
2558 PyErr_Clear();
2559 return 0;
2560}
2561
2562/* Unpack and compare single items of p and q using the struct module. */
2563static int
2564struct_unpack_cmp(const char *p, const char *q,
2565 struct unpacker *unpack_p, struct unpacker *unpack_q)
2566{
2567 PyObject *v, *w;
2568 int ret;
2569
2570 /* At this point any exception from the struct module should not be
2571 StructError, since both formats have been accepted already. */
2572 v = struct_unpack_single(p, unpack_p);
2573 if (v == NULL)
2574 return MV_COMPARE_EX;
2575
2576 w = struct_unpack_single(q, unpack_q);
2577 if (w == NULL) {
2578 Py_DECREF(v);
2579 return MV_COMPARE_EX;
2580 }
2581
2582 /* MV_COMPARE_EX == -1: exceptions are preserved */
2583 ret = PyObject_RichCompareBool(v, w, Py_EQ);
2584 Py_DECREF(v);
2585 Py_DECREF(w);
2586
2587 return ret;
2588}
2589
2590/* Unpack and compare single items of p and q. If both p and q have the same
2591 single element native format, the comparison uses a fast path (gcc creates
2592 a jump table and converts memcpy into simple assignments on x86/x64).
2593
2594 Otherwise, the comparison is delegated to the struct module, which is
2595 30-60x slower. */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002596#define CMP_SINGLE(p, q, type) \
2597 do { \
2598 type x; \
2599 type y; \
2600 memcpy((char *)&x, p, sizeof x); \
2601 memcpy((char *)&y, q, sizeof y); \
2602 equal = (x == y); \
2603 } while (0)
2604
Benjamin Peterson82cce4c2016-09-08 11:56:06 -07002605static inline int
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002606unpack_cmp(const char *p, const char *q, char fmt,
2607 struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002608{
2609 int equal;
2610
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002611 switch (fmt) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002612
2613 /* signed integers and fast path for 'B' */
2614 case 'B': return *((unsigned char *)p) == *((unsigned char *)q);
2615 case 'b': return *((signed char *)p) == *((signed char *)q);
2616 case 'h': CMP_SINGLE(p, q, short); return equal;
2617 case 'i': CMP_SINGLE(p, q, int); return equal;
2618 case 'l': CMP_SINGLE(p, q, long); return equal;
2619
2620 /* boolean */
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002621 case '?': CMP_SINGLE(p, q, _Bool); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002622
2623 /* unsigned integers */
2624 case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
2625 case 'I': CMP_SINGLE(p, q, unsigned int); return equal;
2626 case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
2627
2628 /* native 64-bit */
Benjamin Petersonaf580df2016-09-06 10:46:49 -07002629 case 'q': CMP_SINGLE(p, q, long long); return equal;
2630 case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002631
2632 /* ssize_t and size_t */
2633 case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
2634 case 'N': CMP_SINGLE(p, q, size_t); return equal;
2635
2636 /* floats */
2637 /* XXX DBL_EPSILON? */
2638 case 'f': CMP_SINGLE(p, q, float); return equal;
2639 case 'd': CMP_SINGLE(p, q, double); return equal;
2640
2641 /* bytes object */
2642 case 'c': return *p == *q;
2643
2644 /* pointer */
2645 case 'P': CMP_SINGLE(p, q, void *); return equal;
2646
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002647 /* use the struct module */
2648 case '_':
2649 assert(unpack_p);
2650 assert(unpack_q);
2651 return struct_unpack_cmp(p, q, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002652 }
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002653
2654 /* NOT REACHED */
2655 PyErr_SetString(PyExc_RuntimeError,
2656 "memoryview: internal error in richcompare");
2657 return MV_COMPARE_EX;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002658}
2659
2660/* Base case for recursive array comparisons. Assumption: ndim == 1. */
2661static int
2662cmp_base(const char *p, const char *q, const Py_ssize_t *shape,
2663 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2664 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002665 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002666{
2667 Py_ssize_t i;
2668 int equal;
2669
2670 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002671 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2672 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002673 equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002674 if (equal <= 0)
2675 return equal;
2676 }
2677
2678 return 1;
2679}
2680
2681/* Recursively compare two multi-dimensional arrays that have the same
2682 logical structure. Assumption: ndim >= 1. */
2683static int
2684cmp_rec(const char *p, const char *q,
2685 Py_ssize_t ndim, const Py_ssize_t *shape,
2686 const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets,
2687 const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002688 char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002689{
2690 Py_ssize_t i;
2691 int equal;
2692
2693 assert(ndim >= 1);
2694 assert(shape != NULL);
2695 assert(pstrides != NULL);
2696 assert(qstrides != NULL);
2697
2698 if (ndim == 1) {
2699 return cmp_base(p, q, shape,
2700 pstrides, psuboffsets,
2701 qstrides, qsuboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002702 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002703 }
2704
2705 for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) {
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002706 const char *xp = ADJUST_PTR(p, psuboffsets, 0);
2707 const char *xq = ADJUST_PTR(q, qsuboffsets, 0);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002708 equal = cmp_rec(xp, xq, ndim-1, shape+1,
2709 pstrides+1, psuboffsets ? psuboffsets+1 : NULL,
2710 qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002711 fmt, unpack_p, unpack_q);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002712 if (equal <= 0)
2713 return equal;
2714 }
2715
2716 return 1;
2717}
2718
2719static PyObject *
2720memory_richcompare(PyObject *v, PyObject *w, int op)
2721{
2722 PyObject *res;
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002723 Py_buffer wbuf, *vv;
2724 Py_buffer *ww = NULL;
2725 struct unpacker *unpack_v = NULL;
2726 struct unpacker *unpack_w = NULL;
2727 char vfmt, wfmt;
2728 int equal = MV_COMPARE_NOT_IMPL;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002729
2730 if (op != Py_EQ && op != Py_NE)
2731 goto result; /* Py_NotImplemented */
2732
2733 assert(PyMemoryView_Check(v));
2734 if (BASE_INACCESSIBLE(v)) {
2735 equal = (v == w);
2736 goto result;
2737 }
2738 vv = VIEW_ADDR(v);
2739
2740 if (PyMemoryView_Check(w)) {
2741 if (BASE_INACCESSIBLE(w)) {
2742 equal = (v == w);
2743 goto result;
2744 }
2745 ww = VIEW_ADDR(w);
2746 }
2747 else {
2748 if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) {
2749 PyErr_Clear();
2750 goto result; /* Py_NotImplemented */
2751 }
2752 ww = &wbuf;
2753 }
2754
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002755 if (!equiv_shape(vv, ww)) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002756 PyErr_Clear();
2757 equal = 0;
2758 goto result;
2759 }
2760
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002761 /* Use fast unpacking for identical primitive C type formats. */
2762 if (get_native_fmtchar(&vfmt, vv->format) < 0)
2763 vfmt = '_';
2764 if (get_native_fmtchar(&wfmt, ww->format) < 0)
2765 wfmt = '_';
2766 if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) {
2767 /* Use struct module unpacking. NOTE: Even for equal format strings,
2768 memcmp() cannot be used for item comparison since it would give
2769 incorrect results in the case of NaNs or uninitialized padding
2770 bytes. */
2771 vfmt = '_';
2772 unpack_v = struct_get_unpacker(vv->format, vv->itemsize);
2773 if (unpack_v == NULL) {
2774 equal = fix_struct_error_int();
2775 goto result;
2776 }
2777 unpack_w = struct_get_unpacker(ww->format, ww->itemsize);
2778 if (unpack_w == NULL) {
2779 equal = fix_struct_error_int();
2780 goto result;
2781 }
2782 }
2783
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002784 if (vv->ndim == 0) {
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002785 equal = unpack_cmp(vv->buf, ww->buf,
2786 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002787 }
2788 else if (vv->ndim == 1) {
2789 equal = cmp_base(vv->buf, ww->buf, vv->shape,
2790 vv->strides, vv->suboffsets,
2791 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002792 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002793 }
2794 else {
2795 equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape,
2796 vv->strides, vv->suboffsets,
2797 ww->strides, ww->suboffsets,
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002798 vfmt, unpack_v, unpack_w);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002799 }
2800
2801result:
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002802 if (equal < 0) {
2803 if (equal == MV_COMPARE_NOT_IMPL)
2804 res = Py_NotImplemented;
2805 else /* exception */
2806 res = NULL;
2807 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002808 else if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
2809 res = Py_True;
2810 else
2811 res = Py_False;
2812
2813 if (ww == &wbuf)
2814 PyBuffer_Release(ww);
Nick Coghlan06e1ab02012-08-25 17:59:50 +10002815
2816 unpacker_free(unpack_v);
2817 unpacker_free(unpack_w);
2818
2819 Py_XINCREF(res);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002820 return res;
2821}
2822
2823/**************************************************************************/
2824/* Hash */
2825/**************************************************************************/
2826
2827static Py_hash_t
2828memory_hash(PyMemoryViewObject *self)
2829{
2830 if (self->hash == -1) {
2831 Py_buffer *view = &self->view;
2832 char *mem = view->buf;
Stefan Krah4af77a02012-11-02 17:49:22 +01002833 Py_ssize_t ret;
2834 char fmt;
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002835
2836 CHECK_RELEASED_INT(self);
2837
2838 if (!view->readonly) {
2839 PyErr_SetString(PyExc_ValueError,
2840 "cannot hash writable memoryview object");
2841 return -1;
2842 }
Stefan Krah4af77a02012-11-02 17:49:22 +01002843 ret = get_native_fmtchar(&fmt, view->format);
2844 if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2845 PyErr_SetString(PyExc_ValueError,
2846 "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2847 return -1;
2848 }
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002849 if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
2850 /* Keep the original error message */
2851 return -1;
2852 }
2853
2854 if (!MV_C_CONTIGUOUS(self->flags)) {
2855 mem = PyMem_Malloc(view->len);
2856 if (mem == NULL) {
2857 PyErr_NoMemory();
2858 return -1;
2859 }
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002860 if (buffer_to_contiguous(mem, view, 'C') < 0) {
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002861 PyMem_Free(mem);
2862 return -1;
2863 }
2864 }
2865
2866 /* Can't fail */
Christian Heimes985ecdc2013-11-20 11:46:18 +01002867 self->hash = _Py_HashBytes(mem, view->len);
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002868
2869 if (mem != view->buf)
2870 PyMem_Free(mem);
2871 }
2872
2873 return self->hash;
2874}
2875
2876
2877/**************************************************************************/
2878/* getters */
2879/**************************************************************************/
2880
2881static PyObject *
2882_IntTupleFromSsizet(int len, Py_ssize_t *vals)
2883{
2884 int i;
2885 PyObject *o;
2886 PyObject *intTuple;
2887
2888 if (vals == NULL)
2889 return PyTuple_New(0);
2890
2891 intTuple = PyTuple_New(len);
2892 if (!intTuple)
2893 return NULL;
2894 for (i=0; i<len; i++) {
2895 o = PyLong_FromSsize_t(vals[i]);
2896 if (!o) {
2897 Py_DECREF(intTuple);
2898 return NULL;
2899 }
2900 PyTuple_SET_ITEM(intTuple, i, o);
2901 }
2902 return intTuple;
2903}
2904
2905static PyObject *
2906memory_obj_get(PyMemoryViewObject *self)
2907{
2908 Py_buffer *view = &self->view;
2909
2910 CHECK_RELEASED(self);
2911 if (view->obj == NULL) {
2912 Py_RETURN_NONE;
2913 }
2914 Py_INCREF(view->obj);
2915 return view->obj;
2916}
2917
2918static PyObject *
2919memory_nbytes_get(PyMemoryViewObject *self)
2920{
2921 CHECK_RELEASED(self);
2922 return PyLong_FromSsize_t(self->view.len);
2923}
2924
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002925static PyObject *
2926memory_format_get(PyMemoryViewObject *self)
2927{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002928 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002929 return PyUnicode_FromString(self->view.format);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002930}
2931
2932static PyObject *
2933memory_itemsize_get(PyMemoryViewObject *self)
2934{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002935 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002936 return PyLong_FromSsize_t(self->view.itemsize);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002937}
2938
2939static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002940memory_shape_get(PyMemoryViewObject *self)
2941{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002942 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002943 return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002944}
2945
2946static PyObject *
2947memory_strides_get(PyMemoryViewObject *self)
2948{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002949 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002950 return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002951}
2952
2953static PyObject *
2954memory_suboffsets_get(PyMemoryViewObject *self)
2955{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002956 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002957 return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002958}
2959
2960static PyObject *
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002961memory_readonly_get(PyMemoryViewObject *self)
2962{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002963 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002964 return PyBool_FromLong(self->view.readonly);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002965}
2966
2967static PyObject *
2968memory_ndim_get(PyMemoryViewObject *self)
2969{
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00002970 CHECK_RELEASED(self);
Antoine Pitrou35b7e832009-01-03 19:20:36 +00002971 return PyLong_FromLong(self->view.ndim);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00002972}
2973
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002974static PyObject *
2975memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2976{
2977 CHECK_RELEASED(self);
2978 return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags));
2979}
2980
2981static PyObject *
2982memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2983{
2984 CHECK_RELEASED(self);
2985 return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags));
2986}
2987
2988static PyObject *
2989memory_contiguous(PyMemoryViewObject *self, PyObject *dummy)
2990{
2991 CHECK_RELEASED(self);
2992 return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags));
2993}
2994
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04002995PyDoc_STRVAR(memory_obj_doc,
2996 "The underlying object of the memoryview.");
2997PyDoc_STRVAR(memory_nbytes_doc,
2998 "The amount of space in bytes that the array would use in\n"
2999 " a contiguous representation.");
3000PyDoc_STRVAR(memory_readonly_doc,
3001 "A bool indicating whether the memory is read only.");
3002PyDoc_STRVAR(memory_itemsize_doc,
3003 "The size in bytes of each element of the memoryview.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003004PyDoc_STRVAR(memory_format_doc,
3005 "A string containing the format (in struct module style)\n"
3006 " for each element in the view.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003007PyDoc_STRVAR(memory_ndim_doc,
3008 "An integer indicating how many dimensions of a multi-dimensional\n"
3009 " array the memory represents.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003010PyDoc_STRVAR(memory_shape_doc,
3011 "A tuple of ndim integers giving the shape of the memory\n"
3012 " as an N-dimensional array.");
3013PyDoc_STRVAR(memory_strides_doc,
3014 "A tuple of ndim integers giving the size in bytes to access\n"
3015 " each element for each dimension of the array.");
3016PyDoc_STRVAR(memory_suboffsets_doc,
3017 "A tuple of integers used internally for PIL-style arrays.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003018PyDoc_STRVAR(memory_c_contiguous_doc,
3019 "A bool indicating whether the memory is C contiguous.");
3020PyDoc_STRVAR(memory_f_contiguous_doc,
3021 "A bool indicating whether the memory is Fortran contiguous.");
3022PyDoc_STRVAR(memory_contiguous_doc,
3023 "A bool indicating whether the memory is contiguous.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003024
Stefan Krahbcaf5992014-05-18 00:35:09 +02003025
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003026static PyGetSetDef memory_getsetlist[] = {
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003027 {"obj", (getter)memory_obj_get, NULL, memory_obj_doc},
3028 {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003029 {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc},
3030 {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc},
3031 {"format", (getter)memory_format_get, NULL, memory_format_doc},
3032 {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc},
3033 {"shape", (getter)memory_shape_get, NULL, memory_shape_doc},
3034 {"strides", (getter)memory_strides_get, NULL, memory_strides_doc},
3035 {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003036 {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
3037 {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
3038 {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003039 {NULL, NULL, NULL, NULL},
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003040};
3041
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003042PyDoc_STRVAR(memory_release_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003043"release($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003044\n\
3045Release the underlying buffer exposed by the memoryview object.");
3046PyDoc_STRVAR(memory_tobytes_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003047"tobytes($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003048\n\
3049Return the data in the buffer as a byte string.");
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003050PyDoc_STRVAR(memory_hex_doc,
3051"hex($self, /)\n--\n\
3052\n\
3053Return the data in the buffer as a string of hexadecimal numbers.");
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003054PyDoc_STRVAR(memory_tolist_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003055"tolist($self, /)\n--\n\
Alexander Belopolsky397e5c92012-09-03 16:29:11 -04003056\n\
3057Return the data in the buffer as a list of elements.");
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003058PyDoc_STRVAR(memory_cast_doc,
Stefan Krahbcaf5992014-05-18 00:35:09 +02003059"cast($self, /, format, *, shape)\n--\n\
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003060\n\
3061Cast a memoryview to a new format or shape.");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003062
Antoine Pitrou6e6cc832010-09-09 12:59:39 +00003063static PyMethodDef memory_methods[] = {
Alexander Belopolskye370c382012-09-03 16:43:55 -04003064 {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
3065 {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
Gregory P. Smith8cb65692015-04-25 23:22:26 +00003066 {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
Alexander Belopolskye370c382012-09-03 16:43:55 -04003067 {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
Alexander Belopolskyf73c69e2012-09-03 16:51:01 -04003068 {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
Stefan Krahe4c07992012-07-28 14:10:02 +02003069 {"__enter__", memory_enter, METH_NOARGS, NULL},
3070 {"__exit__", memory_exit, METH_VARARGS, NULL},
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003071 {NULL, NULL}
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003072};
3073
3074
3075PyTypeObject PyMemoryView_Type = {
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003076 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003077 "memoryview", /* tp_name */
3078 offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */
3079 sizeof(Py_ssize_t), /* tp_itemsize */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003080 (destructor)memory_dealloc, /* tp_dealloc */
3081 0, /* tp_print */
3082 0, /* tp_getattr */
3083 0, /* tp_setattr */
Mark Dickinsone94c6792009-02-02 20:36:42 +00003084 0, /* tp_reserved */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003085 (reprfunc)memory_repr, /* tp_repr */
3086 0, /* tp_as_number */
Raymond Hettinger159eac92009-06-23 20:38:54 +00003087 &memory_as_sequence, /* tp_as_sequence */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003088 &memory_as_mapping, /* tp_as_mapping */
Antoine Pitrouce4a9da2011-11-21 20:46:33 +01003089 (hashfunc)memory_hash, /* tp_hash */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003090 0, /* tp_call */
Benjamin Peterson87618552009-02-08 15:00:52 +00003091 0, /* tp_str */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003092 PyObject_GenericGetAttr, /* tp_getattro */
3093 0, /* tp_setattro */
3094 &memory_as_buffer, /* tp_as_buffer */
3095 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
3096 memory_doc, /* tp_doc */
3097 (traverseproc)memory_traverse, /* tp_traverse */
3098 (inquiry)memory_clear, /* tp_clear */
3099 memory_richcompare, /* tp_richcompare */
Richard Oudkerk3e0a1eb2012-05-28 21:35:09 +01003100 offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */
Antoine Pitrou35b7e832009-01-03 19:20:36 +00003101 0, /* tp_iter */
3102 0, /* tp_iternext */
3103 memory_methods, /* tp_methods */
3104 0, /* tp_members */
3105 memory_getsetlist, /* tp_getset */
3106 0, /* tp_base */
3107 0, /* tp_dict */
3108 0, /* tp_descr_get */
3109 0, /* tp_descr_set */
3110 0, /* tp_dictoffset */
3111 0, /* tp_init */
3112 0, /* tp_alloc */
3113 memory_new, /* tp_new */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +00003114};