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