| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Memoryview object implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  | #define IS_RELEASED(memobj) \
 | 
					
						
							|  |  |  |     (((PyMemoryViewObject *) memobj)->view.buf == NULL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CHECK_RELEASED(memobj) \
 | 
					
						
							|  |  |  |     if (IS_RELEASED(memobj)) { \ | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, \ | 
					
						
							|  |  |  |                         "operation forbidden on released memoryview object"); \ | 
					
						
							|  |  |  |         return NULL; \ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CHECK_RELEASED_INT(memobj) \
 | 
					
						
							|  |  |  |     if (IS_RELEASED(memobj)) { \ | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, \ | 
					
						
							|  |  |  |                         "operation forbidden on released memoryview object"); \ | 
					
						
							|  |  |  |         return -1; \ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							|  |  |  | get_shape0(Py_buffer *buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (buf->shape != NULL) | 
					
						
							|  |  |  |         return buf->shape[0]; | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |     if (buf->ndim == 0) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |         "exported buffer does not have any shape information associated " | 
					
						
							|  |  |  |         "to it"); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | dup_buffer(Py_buffer *dest, Py_buffer *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     *dest = *src; | 
					
						
							|  |  |  |     if (src->ndim == 1 && src->shape != NULL) { | 
					
						
							|  |  |  |         dest->shape = &(dest->smalltable[0]); | 
					
						
							|  |  |  |         dest->shape[0] = get_shape0(src); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (src->ndim == 1 && src->strides != NULL) { | 
					
						
							|  |  |  |         dest->strides = &(dest->smalltable[1]); | 
					
						
							|  |  |  |         dest->strides[0] = src->strides[0]; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2007-09-23 02:00:13 +00:00
										 |  |  | memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     int res = 0; | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED_INT(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (self->view.obj != NULL) | 
					
						
							|  |  |  |         res = PyObject_GetBuffer(self->view.obj, view, flags); | 
					
						
							|  |  |  |     if (view) | 
					
						
							|  |  |  |         dup_buffer(view, &self->view); | 
					
						
							|  |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view) | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyBuffer_Release(view); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(memory_doc, | 
					
						
							|  |  |  | "memoryview(object)\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Create a new memoryview object which references the given object."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2008-08-19 18:22:14 +00:00
										 |  |  | PyMemoryView_FromBuffer(Py_buffer *info) | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyMemoryViewObject *mview; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-24 20:50:49 +00:00
										 |  |  |     if (info->buf == NULL) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |             "cannot make memory view from a buffer with a NULL data pointer"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     mview = (PyMemoryViewObject *) | 
					
						
							|  |  |  |         PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type); | 
					
						
							|  |  |  |     if (mview == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     dup_buffer(&mview->view, info); | 
					
						
							|  |  |  |     /* NOTE: mview->view.obj should already have been incref'ed as
 | 
					
						
							|  |  |  |        part of PyBuffer_FillInfo(). */ | 
					
						
							|  |  |  |     _PyObject_GC_TRACK(mview); | 
					
						
							|  |  |  |     return (PyObject *)mview; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyMemoryView_FromObject(PyObject *base) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyMemoryViewObject *mview; | 
					
						
							| 
									
										
										
										
											2010-02-02 22:47:00 +00:00
										 |  |  |     Py_buffer view; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (!PyObject_CheckBuffer(base)) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |             "cannot make memory view because object does " | 
					
						
							|  |  |  |             "not have the buffer interface"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 22:47:00 +00:00
										 |  |  |     if (PyObject_GetBuffer(base, &view, PyBUF_FULL_RO) < 0) | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 22:47:00 +00:00
										 |  |  |     mview = (PyMemoryViewObject *)PyMemoryView_FromBuffer(&view); | 
					
						
							|  |  |  |     if (mview == NULL) { | 
					
						
							|  |  |  |         PyBuffer_Release(&view); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return (PyObject *)mview; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyObject *obj; | 
					
						
							|  |  |  |     static char *kwlist[] = {"object", 0}; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist, | 
					
						
							|  |  |  |                                      &obj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-11-08 02:28:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return PyMemoryView_FromObject(obj); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | _strided_copy_nd(char *dest, char *src, int nd, Py_ssize_t *shape, | 
					
						
							| 
									
										
										
										
											2007-10-26 06:44:10 +00:00
										 |  |  |                  Py_ssize_t *strides, Py_ssize_t itemsize, char fort) | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     int k; | 
					
						
							|  |  |  |     Py_ssize_t outstride; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (nd==0) { | 
					
						
							|  |  |  |         memcpy(dest, src, itemsize); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (nd == 1) { | 
					
						
							|  |  |  |         for (k = 0; k<shape[0]; k++) { | 
					
						
							|  |  |  |             memcpy(dest, src, itemsize); | 
					
						
							|  |  |  |             dest += itemsize; | 
					
						
							|  |  |  |             src += strides[0]; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (fort == 'F') { | 
					
						
							|  |  |  |             /* Copy first dimension first,
 | 
					
						
							|  |  |  |                second dimension second, etc... | 
					
						
							|  |  |  |                Set up the recursive loop backwards so that final | 
					
						
							|  |  |  |                dimension is actually copied last. | 
					
						
							|  |  |  |             */ | 
					
						
							|  |  |  |             outstride = itemsize; | 
					
						
							|  |  |  |             for (k=1; k<nd-1;k++) { | 
					
						
							|  |  |  |                 outstride *= shape[k]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             for (k=0; k<shape[nd-1]; k++) { | 
					
						
							|  |  |  |                 _strided_copy_nd(dest, src, nd-1, shape, | 
					
						
							|  |  |  |                                  strides, itemsize, fort); | 
					
						
							|  |  |  |                 dest += outstride; | 
					
						
							|  |  |  |                 src += strides[nd-1]; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |         else { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |             /* Copy last dimension first,
 | 
					
						
							|  |  |  |                second-to-last dimension second, etc. | 
					
						
							|  |  |  |                Set up the recursion so that the | 
					
						
							|  |  |  |                first dimension is copied last | 
					
						
							|  |  |  |             */ | 
					
						
							|  |  |  |             outstride = itemsize; | 
					
						
							|  |  |  |             for (k=1; k < nd; k++) { | 
					
						
							|  |  |  |                 outstride *= shape[k]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             for (k=0; k<shape[0]; k++) { | 
					
						
							|  |  |  |                 _strided_copy_nd(dest, src, nd-1, shape+1, | 
					
						
							|  |  |  |                                  strides+1, itemsize, | 
					
						
							|  |  |  |                                  fort); | 
					
						
							|  |  |  |                 dest += outstride; | 
					
						
							|  |  |  |                 src += strides[0]; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2007-09-23 02:00:13 +00:00
										 |  |  | _indirect_copy_nd(char *dest, Py_buffer *view, char fort) | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     Py_ssize_t *indices; | 
					
						
							|  |  |  |     int k; | 
					
						
							|  |  |  |     Py_ssize_t elements; | 
					
						
							|  |  |  |     char *ptr; | 
					
						
							| 
									
										
										
										
											2010-09-01 21:14:46 +00:00
										 |  |  |     void (*func)(int, Py_ssize_t *, const Py_ssize_t *); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (view->ndim > PY_SSIZE_T_MAX / sizeof(Py_ssize_t)) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view->ndim); | 
					
						
							|  |  |  |     if (indices == NULL) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (k=0; k<view->ndim;k++) { | 
					
						
							|  |  |  |         indices[k] = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     elements = 1; | 
					
						
							|  |  |  |     for (k=0; k<view->ndim; k++) { | 
					
						
							|  |  |  |         elements *= view->shape[k]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (fort == 'F') { | 
					
						
							| 
									
										
										
										
											2010-09-01 12:58:21 +00:00
										 |  |  |         func = _Py_add_one_to_index_F; | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2010-09-01 12:58:21 +00:00
										 |  |  |         func = _Py_add_one_to_index_C; | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     while (elements--) { | 
					
						
							|  |  |  |         func(view->ndim, indices, view->shape); | 
					
						
							|  |  |  |         ptr = PyBuffer_GetPointer(view, indices); | 
					
						
							|  |  |  |         memcpy(dest, ptr, view->itemsize); | 
					
						
							|  |  |  |         dest += view->itemsize; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyMem_Free(indices); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |    Get a the data from an object as a contiguous chunk of memory (in | 
					
						
							|  |  |  |    either 'C' or 'F'ortran order) even if it means copying it into a | 
					
						
							|  |  |  |    separate memory area. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Returns a new reference to a Memory view object.  If no copy is needed, | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  |    the memory view object points to the original memory and holds a | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |    lock on the original.  If a copy is needed, then the memory view object | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  |    points to a brand-new Bytes object (and holds a memory lock on it). | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    buffertype | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    PyBUF_READ  buffer only needs to be read-only | 
					
						
							| 
									
										
										
										
											2007-09-17 17:55:36 +00:00
										 |  |  |    PyBUF_WRITE buffer needs to be writable (give error if not contiguous) | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  |    PyBUF_SHADOW buffer needs to be writable so shadow it with | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |                 a contiguous buffer if it is not. The view will point to | 
					
						
							|  |  |  |                 the shadow buffer which can be written to and then | 
					
						
							|  |  |  |                 will be copied back into the other buffer when the memory | 
					
						
							| 
									
										
										
										
											2008-08-02 21:02:48 +00:00
										 |  |  |                 view is de-allocated.  While the shadow buffer is | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |                 being used, it will have an exclusive write lock on | 
					
						
							|  |  |  |                 the original buffer. | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyMemoryViewObject *mem; | 
					
						
							|  |  |  |     PyObject *bytes; | 
					
						
							|  |  |  |     Py_buffer *view; | 
					
						
							|  |  |  |     int flags; | 
					
						
							|  |  |  |     char *dest; | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (!PyObject_CheckBuffer(obj)) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2009-08-04 20:29:27 +00:00
										 |  |  |                         "object does not support the buffer interface"); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     mem = PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type); | 
					
						
							|  |  |  |     if (mem == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     view = &mem->view; | 
					
						
							|  |  |  |     flags = PyBUF_FULL_RO; | 
					
						
							|  |  |  |     switch(buffertype) { | 
					
						
							|  |  |  |     case PyBUF_WRITE: | 
					
						
							|  |  |  |         flags = PyBUF_FULL; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (PyObject_GetBuffer(obj, view, flags) != 0) { | 
					
						
							|  |  |  |         Py_DECREF(mem); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyBuffer_IsContiguous(view, fort)) { | 
					
						
							|  |  |  |         /* no copy needed */ | 
					
						
							|  |  |  |         _PyObject_GC_TRACK(mem); | 
					
						
							|  |  |  |         return (PyObject *)mem; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* otherwise a copy is needed */ | 
					
						
							|  |  |  |     if (buffertype == PyBUF_WRITE) { | 
					
						
							|  |  |  |         Py_DECREF(mem); | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_BufferError, | 
					
						
							|  |  |  |                         "writable contiguous buffer requested " | 
					
						
							|  |  |  |                         "for a non-contiguousobject."); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     bytes = PyBytes_FromStringAndSize(NULL, view->len); | 
					
						
							|  |  |  |     if (bytes == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(mem); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     dest = PyBytes_AS_STRING(bytes); | 
					
						
							|  |  |  |     /* different copying strategy depending on whether
 | 
					
						
							|  |  |  |        or not any pointer de-referencing is needed | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     /* strided or in-direct copy */ | 
					
						
							|  |  |  |     if (view->suboffsets==NULL) { | 
					
						
							|  |  |  |         _strided_copy_nd(dest, view->buf, view->ndim, view->shape, | 
					
						
							|  |  |  |                          view->strides, view->itemsize, fort); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (_indirect_copy_nd(dest, view, fort) < 0) { | 
					
						
							|  |  |  |             Py_DECREF(bytes); | 
					
						
							|  |  |  |             Py_DECREF(mem); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |         PyBuffer_Release(view);  /* XXX ? */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     _PyObject_GC_TRACK(mem); | 
					
						
							|  |  |  |     return (PyObject *)mem; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_format_get(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return PyUnicode_FromString(self->view.format); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_itemsize_get(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return PyLong_FromSsize_t(self->view.itemsize); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _IntTupleFromSsizet(int len, Py_ssize_t *vals) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     int i; | 
					
						
							|  |  |  |     PyObject *o; | 
					
						
							|  |  |  |     PyObject *intTuple; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (vals == NULL) { | 
					
						
							|  |  |  |         Py_INCREF(Py_None); | 
					
						
							|  |  |  |         return Py_None; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     intTuple = PyTuple_New(len); | 
					
						
							| 
									
										
										
										
											2010-11-03 23:11:10 +00:00
										 |  |  |     if (!intTuple) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     for (i=0; i<len; i++) { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |         o = PyLong_FromSsize_t(vals[i]); | 
					
						
							|  |  |  |         if (!o) { | 
					
						
							|  |  |  |             Py_DECREF(intTuple); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyTuple_SET_ITEM(intTuple, i, o); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return intTuple; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_shape_get(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return _IntTupleFromSsizet(self->view.ndim, self->view.shape); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_strides_get(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return _IntTupleFromSsizet(self->view.ndim, self->view.strides); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_suboffsets_get(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_readonly_get(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return PyBool_FromLong(self->view.readonly); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_ndim_get(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return PyLong_FromLong(self->view.ndim); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | static PyGetSetDef memory_getsetlist[] ={ | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     {"format",                (getter)memory_format_get,      NULL, NULL}, | 
					
						
							|  |  |  |     {"itemsize",        (getter)memory_itemsize_get,    NULL, NULL}, | 
					
						
							|  |  |  |     {"shape",           (getter)memory_shape_get,       NULL, NULL}, | 
					
						
							|  |  |  |     {"strides",         (getter)memory_strides_get,     NULL, NULL}, | 
					
						
							|  |  |  |     {"suboffsets",      (getter)memory_suboffsets_get,  NULL, NULL}, | 
					
						
							|  |  |  |     {"readonly",        (getter)memory_readonly_get,    NULL, NULL}, | 
					
						
							|  |  |  |     {"ndim",            (getter)memory_ndim_get,        NULL, NULL}, | 
					
						
							|  |  |  |     {NULL, NULL, NULL, NULL}, | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2007-08-19 04:23:20 +00:00
										 |  |  | memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs) | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(mem); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     return PyObject_CallFunctionObjArgs( | 
					
						
							|  |  |  |             (PyObject *) &PyBytes_Type, mem, NULL); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  | /* TODO: rewrite this function using the struct module to unpack
 | 
					
						
							|  |  |  |    each buffer item */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2007-08-19 04:23:20 +00:00
										 |  |  | memory_tolist(PyMemoryViewObject *mem, PyObject *noargs) | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     Py_buffer *view = &(mem->view); | 
					
						
							|  |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  |     PyObject *res, *item; | 
					
						
							|  |  |  |     char *buf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(mem); | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (strcmp(view->format, "B") || view->itemsize != 1) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_NotImplementedError,  | 
					
						
							|  |  |  |                 "tolist() only supports byte views"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (view->ndim != 1) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_NotImplementedError,  | 
					
						
							|  |  |  |                 "tolist() only supports one-dimensional objects"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     res = PyList_New(view->len); | 
					
						
							|  |  |  |     if (res == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     buf = view->buf; | 
					
						
							|  |  |  |     for (i = 0; i < view->len; i++) { | 
					
						
							|  |  |  |         item = PyLong_FromUnsignedLong((unsigned char) *buf); | 
					
						
							|  |  |  |         if (item == NULL) { | 
					
						
							|  |  |  |             Py_DECREF(res); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyList_SET_ITEM(res, i, item); | 
					
						
							|  |  |  |         buf++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  | do_release(PyMemoryViewObject *self) | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (self->view.obj != NULL) { | 
					
						
							| 
									
										
										
										
											2010-11-04 20:30:33 +00:00
										 |  |  |         PyBuffer_Release(&(self->view)); | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     self->view.obj = NULL; | 
					
						
							|  |  |  |     self->view.buf = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_enter(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     CHECK_RELEASED(self); | 
					
						
							|  |  |  |     Py_INCREF(self); | 
					
						
							|  |  |  |     return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_exit(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     do_release((PyMemoryViewObject *) self); | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef memory_methods[] = { | 
					
						
							|  |  |  |     {"release", memory_exit, METH_NOARGS}, | 
					
						
							|  |  |  |     {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL}, | 
					
						
							|  |  |  |     {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL}, | 
					
						
							|  |  |  |     {"__enter__", memory_enter, METH_NOARGS}, | 
					
						
							|  |  |  |     {"__exit__", memory_exit, METH_VARARGS}, | 
					
						
							|  |  |  |     {NULL,          NULL}           /* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | memory_dealloc(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _PyObject_GC_UNTRACK(self); | 
					
						
							|  |  |  |     do_release(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |     PyObject_GC_Del(self); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_repr(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     if (IS_RELEASED(self)) | 
					
						
							|  |  |  |         return PyUnicode_FromFormat("<released memory at %p>", self); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return PyUnicode_FromFormat("<memory at %p>", self); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Sequence methods */ | 
					
						
							|  |  |  | static Py_ssize_t | 
					
						
							|  |  |  | memory_length(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED_INT(self); | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |     return get_shape0(&self->view); | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-23 20:38:54 +00:00
										 |  |  | /* Alternate version of memory_subcript that only accepts indices.
 | 
					
						
							|  |  |  |    Used by PySeqIter_New(). | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | memory_item(PyMemoryViewObject *self, Py_ssize_t result) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_buffer *view = &(self->view); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2009-06-23 20:38:54 +00:00
										 |  |  |     if (view->ndim == 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_IndexError, | 
					
						
							|  |  |  |                         "invalid indexing of 0-dim memory"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (view->ndim == 1) { | 
					
						
							|  |  |  |         /* Return a bytes object */ | 
					
						
							|  |  |  |         char *ptr; | 
					
						
							|  |  |  |         ptr = (char *)view->buf; | 
					
						
							|  |  |  |         if (result < 0) { | 
					
						
							|  |  |  |             result += get_shape0(view); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ((result < 0) || (result >= get_shape0(view))) { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_IndexError, | 
					
						
							|  |  |  |                                 "index out of bounds"); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (view->strides == NULL) | 
					
						
							|  |  |  |             ptr += view->itemsize * result; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             ptr += view->strides[0] * result; | 
					
						
							|  |  |  |         if (view->suboffsets != NULL && | 
					
						
							|  |  |  |             view->suboffsets[0] >= 0) { | 
					
						
							|  |  |  |             ptr = *((char **)ptr) + view->suboffsets[0]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return PyBytes_FromStringAndSize(ptr, view->itemsize); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         /* Return a new memory-view object */ | 
					
						
							|  |  |  |         Py_buffer newview; | 
					
						
							|  |  |  |         memset(&newview, 0, sizeof(newview)); | 
					
						
							|  |  |  |         /* XXX:  This needs to be fixed so it actually returns a sub-view */ | 
					
						
							|  |  |  |         return PyMemoryView_FromBuffer(&newview); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-09-23 02:00:13 +00:00
										 |  |  |   mem[obj] returns a bytes object holding the data for one element if | 
					
						
							|  |  |  |            obj fully indexes the memory view or another memory-view object | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |            if it does not. | 
					
						
							| 
									
										
										
										
											2007-09-25 22:10:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |            0-d memory-view objects can be referenced using ... or () but | 
					
						
							|  |  |  |            not with anything else. | 
					
						
							| 
									
										
										
										
											2007-09-23 02:00:13 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | memory_subscript(PyMemoryViewObject *self, PyObject *key) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |     Py_buffer *view; | 
					
						
							|  |  |  |     view = &(self->view); | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED(self); | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |     if (view->ndim == 0) { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |         if (key == Py_Ellipsis || | 
					
						
							|  |  |  |             (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) { | 
					
						
							|  |  |  |             Py_INCREF(self); | 
					
						
							|  |  |  |             return (PyObject *)self; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_IndexError, | 
					
						
							|  |  |  |                                 "invalid indexing of 0-dim memory"); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (PyIndex_Check(key)) { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |         Py_ssize_t result; | 
					
						
							|  |  |  |         result = PyNumber_AsSsize_t(key, NULL); | 
					
						
							|  |  |  |         if (result == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							| 
									
										
										
										
											2009-06-23 20:38:54 +00:00
										 |  |  |         return memory_item(self, result); | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (PySlice_Check(key)) { | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |         Py_ssize_t start, stop, step, slicelength; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |         if (PySlice_GetIndicesEx(key, get_shape0(view), | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |                                  &start, &stop, &step, &slicelength) < 0) { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |         if (step == 1 && view->ndim == 1) { | 
					
						
							|  |  |  |             Py_buffer newview; | 
					
						
							|  |  |  |             void *newbuf = (char *) view->buf | 
					
						
							|  |  |  |                                     + start * view->itemsize; | 
					
						
							|  |  |  |             int newflags = view->readonly | 
					
						
							|  |  |  |                     ? PyBUF_CONTIG_RO : PyBUF_CONTIG; | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2009-01-03 16:59:18 +00:00
										 |  |  |             /* XXX There should be an API to create a subbuffer */ | 
					
						
							|  |  |  |             if (view->obj != NULL) { | 
					
						
							|  |  |  |                 if (PyObject_GetBuffer(view->obj, &newview, newflags) == -1) | 
					
						
							|  |  |  |                     return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 newview = *view; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             newview.buf = newbuf; | 
					
						
							|  |  |  |             newview.len = slicelength * newview.itemsize; | 
					
						
							|  |  |  |             newview.format = view->format; | 
					
						
							|  |  |  |             newview.shape = &(newview.smalltable[0]); | 
					
						
							|  |  |  |             newview.shape[0] = slicelength; | 
					
						
							|  |  |  |             newview.strides = &(newview.itemsize); | 
					
						
							|  |  |  |             return PyMemoryView_FromBuffer(&newview); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyErr_SetNone(PyExc_NotImplementedError); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |         "cannot index memory using \"%.200s\"",  | 
					
						
							|  |  |  |         key->ob_type->tp_name); | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-12 23:27:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Need to support assigning memory if we can */ | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-11 12:12:00 +00:00
										 |  |  |     Py_ssize_t start, len, bytelen; | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  |     Py_buffer srcview; | 
					
						
							|  |  |  |     Py_buffer *view = &(self->view); | 
					
						
							|  |  |  |     char *srcbuf, *destbuf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     CHECK_RELEASED_INT(self); | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  |     if (view->readonly) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |             "cannot modify read-only memory"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-09-01 21:14:16 +00:00
										 |  |  |     if (value == NULL) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                         "cannot delete memory"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  |     if (view->ndim != 1) { | 
					
						
							|  |  |  |         PyErr_SetNone(PyExc_NotImplementedError); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyIndex_Check(key)) { | 
					
						
							|  |  |  |         start = PyNumber_AsSsize_t(key, NULL); | 
					
						
							|  |  |  |         if (start == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         if (start < 0) { | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |             start += get_shape0(view); | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |         if ((start < 0) || (start >= get_shape0(view))) { | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  |             PyErr_SetString(PyExc_IndexError, | 
					
						
							|  |  |  |                             "index out of bounds"); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         len = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PySlice_Check(key)) { | 
					
						
							|  |  |  |         Py_ssize_t stop, step; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 20:14:31 +00:00
										 |  |  |         if (PySlice_GetIndicesEx(key, get_shape0(view), | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  |                          &start, &stop, &step, &len) < 0) { | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (step != 1) { | 
					
						
							|  |  |  |             PyErr_SetNone(PyExc_NotImplementedError); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |             "cannot index memory using \"%.200s\"",  | 
					
						
							|  |  |  |             key->ob_type->tp_name); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyObject_GetBuffer(value, &srcview, PyBUF_CONTIG_RO) == -1) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* XXX should we allow assignment of different item sizes
 | 
					
						
							|  |  |  |        as long as the byte length is the same? | 
					
						
							|  |  |  |        (e.g. assign 2 shorts to a 4-byte slice) */ | 
					
						
							|  |  |  |     if (srcview.itemsize != view->itemsize) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |             "mismatching item sizes for \"%.200s\" and \"%.200s\"",  | 
					
						
							|  |  |  |             view->obj->ob_type->tp_name, srcview.obj->ob_type->tp_name); | 
					
						
							|  |  |  |         goto _error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-07 20:14:49 +00:00
										 |  |  |     bytelen = len * view->itemsize; | 
					
						
							|  |  |  |     if (bytelen != srcview.len) { | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  |         PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |             "cannot modify size of memoryview object"); | 
					
						
							|  |  |  |         goto _error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Do the actual copy */ | 
					
						
							|  |  |  |     destbuf = (char *) view->buf + start * view->itemsize; | 
					
						
							|  |  |  |     srcbuf = (char *) srcview.buf; | 
					
						
							|  |  |  |     if (destbuf + bytelen < srcbuf || srcbuf + bytelen < destbuf) | 
					
						
							|  |  |  |         /* No overlapping */ | 
					
						
							|  |  |  |         memcpy(destbuf, srcbuf, bytelen); | 
					
						
							| 
									
										
										
										
											2010-07-11 12:12:00 +00:00
										 |  |  |     else | 
					
						
							|  |  |  |         memmove(destbuf, srcbuf, bytelen); | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     PyBuffer_Release(&srcview); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _error: | 
					
						
							|  |  |  |     PyBuffer_Release(&srcview); | 
					
						
							|  |  |  |     return -1; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | memory_richcompare(PyObject *v, PyObject *w, int op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     Py_buffer vv, ww; | 
					
						
							|  |  |  |     int equal = 0; | 
					
						
							|  |  |  |     PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vv.obj = NULL; | 
					
						
							|  |  |  |     ww.obj = NULL; | 
					
						
							|  |  |  |     if (op != Py_EQ && op != Py_NE) | 
					
						
							|  |  |  |         goto _notimpl; | 
					
						
							| 
									
										
										
										
											2010-09-09 12:59:39 +00:00
										 |  |  |     if ((PyMemoryView_Check(v) && IS_RELEASED(v)) || | 
					
						
							|  |  |  |         (PyMemoryView_Check(w) && IS_RELEASED(w))) { | 
					
						
							|  |  |  |         equal = (v == w); | 
					
						
							|  |  |  |         goto _end; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (PyObject_GetBuffer(v, &vv, PyBUF_CONTIG_RO) == -1) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto _notimpl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyObject_GetBuffer(w, &ww, PyBUF_CONTIG_RO) == -1) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto _notimpl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (vv.itemsize != ww.itemsize || vv.len != ww.len) | 
					
						
							|  |  |  |         goto _end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     equal = !memcmp(vv.buf, ww.buf, vv.len); | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | _end: | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyBuffer_Release(&vv); | 
					
						
							|  |  |  |     PyBuffer_Release(&ww); | 
					
						
							|  |  |  |     if ((equal && op == Py_EQ) || (!equal && op == Py_NE)) | 
					
						
							|  |  |  |         res = Py_True; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         res = Py_False; | 
					
						
							|  |  |  |     Py_INCREF(res); | 
					
						
							|  |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | _notimpl: | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyBuffer_Release(&vv); | 
					
						
							|  |  |  |     PyBuffer_Release(&ww); | 
					
						
							| 
									
										
										
										
											2011-08-10 20:28:54 -05:00
										 |  |  |     Py_RETURN_NOTIMPLEMENTED; | 
					
						
							| 
									
										
										
										
											2008-08-19 22:09:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-01 15:10:14 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     if (self->view.obj != NULL) | 
					
						
							|  |  |  |         Py_VISIT(self->view.obj); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2008-09-01 15:10:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | memory_clear(PyMemoryViewObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyBuffer_Release(&self->view); | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2008-09-01 15:10:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | /* As mapping */ | 
					
						
							|  |  |  | static PyMappingMethods memory_as_mapping = { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     (lenfunc)memory_length,               /* mp_length */ | 
					
						
							|  |  |  |     (binaryfunc)memory_subscript,         /* mp_subscript */ | 
					
						
							|  |  |  |     (objobjargproc)memory_ass_sub,        /* mp_ass_subscript */ | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-23 20:38:54 +00:00
										 |  |  | static PySequenceMethods memory_as_sequence = { | 
					
						
							| 
									
										
										
										
											2010-08-11 17:31:17 +00:00
										 |  |  |         0,                                  /* sq_length */ | 
					
						
							|  |  |  |         0,                                  /* sq_concat */ | 
					
						
							|  |  |  |         0,                                  /* sq_repeat */ | 
					
						
							|  |  |  |         (ssizeargfunc)memory_item,          /* sq_item */ | 
					
						
							| 
									
										
										
										
											2009-06-23 20:38:54 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Buffer methods */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyBufferProcs memory_as_buffer = { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     (getbufferproc)memory_getbuf,         /* bf_getbuffer */ | 
					
						
							|  |  |  |     (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */ | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject PyMemoryView_Type = { | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							|  |  |  |     "memoryview", | 
					
						
							|  |  |  |     sizeof(PyMemoryViewObject), | 
					
						
							|  |  |  |     0, | 
					
						
							|  |  |  |     (destructor)memory_dealloc,               /* tp_dealloc */ | 
					
						
							|  |  |  |     0,                                        /* tp_print */ | 
					
						
							|  |  |  |     0,                                        /* tp_getattr */ | 
					
						
							|  |  |  |     0,                                        /* tp_setattr */ | 
					
						
							| 
									
										
										
										
											2009-02-02 20:36:42 +00:00
										 |  |  |     0,                                        /* tp_reserved */ | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     (reprfunc)memory_repr,                    /* tp_repr */ | 
					
						
							|  |  |  |     0,                                        /* tp_as_number */ | 
					
						
							| 
									
										
										
										
											2009-06-23 20:38:54 +00:00
										 |  |  |     &memory_as_sequence,                      /* tp_as_sequence */ | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     &memory_as_mapping,                       /* tp_as_mapping */ | 
					
						
							|  |  |  |     0,                                        /* tp_hash */ | 
					
						
							|  |  |  |     0,                                        /* tp_call */ | 
					
						
							| 
									
										
										
										
											2009-02-08 15:00:52 +00:00
										 |  |  |     0,                                        /* tp_str */ | 
					
						
							| 
									
										
										
										
											2009-01-03 19:20:36 +00:00
										 |  |  |     PyObject_GenericGetAttr,                  /* tp_getattro */ | 
					
						
							|  |  |  |     0,                                        /* tp_setattro */ | 
					
						
							|  |  |  |     &memory_as_buffer,                        /* tp_as_buffer */ | 
					
						
							|  |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  /* tp_flags */ | 
					
						
							|  |  |  |     memory_doc,                               /* tp_doc */ | 
					
						
							|  |  |  |     (traverseproc)memory_traverse,            /* tp_traverse */ | 
					
						
							|  |  |  |     (inquiry)memory_clear,                    /* tp_clear */ | 
					
						
							|  |  |  |     memory_richcompare,                       /* tp_richcompare */ | 
					
						
							|  |  |  |     0,                                        /* tp_weaklistoffset */ | 
					
						
							|  |  |  |     0,                                        /* tp_iter */ | 
					
						
							|  |  |  |     0,                                        /* tp_iternext */ | 
					
						
							|  |  |  |     memory_methods,                           /* tp_methods */ | 
					
						
							|  |  |  |     0,                                        /* tp_members */ | 
					
						
							|  |  |  |     memory_getsetlist,                        /* tp_getset */ | 
					
						
							|  |  |  |     0,                                        /* tp_base */ | 
					
						
							|  |  |  |     0,                                        /* tp_dict */ | 
					
						
							|  |  |  |     0,                                        /* tp_descr_get */ | 
					
						
							|  |  |  |     0,                                        /* tp_descr_set */ | 
					
						
							|  |  |  |     0,                                        /* tp_dictoffset */ | 
					
						
							|  |  |  |     0,                                        /* tp_init */ | 
					
						
							|  |  |  |     0,                                        /* tp_alloc */ | 
					
						
							|  |  |  |     memory_new,                               /* tp_new */ | 
					
						
							| 
									
										
										
										
											2007-08-18 11:21:56 +00:00
										 |  |  | }; |