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