Kaydet (Commit) 35b7e837 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

Issue #4822: fix messy indentation in memoryobject.c/.h, before we may backport it to trunk.

Reviewed on IRC by Georg Brandl, with assistance by Benjamin Peterson.
üst 771ed761
...@@ -20,53 +20,53 @@ PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base, ...@@ -20,53 +20,53 @@ PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base,
int buffertype, int buffertype,
char fort); char fort);
/* Return a contiguous chunk of memory representing the buffer /* Return a contiguous chunk of memory representing the buffer
from an object in a memory view object. If a copy is made then the from an object in a memory view object. If a copy is made then the
base object for the memory view will be a *new* bytes object. base object for the memory view will be a *new* bytes object.
Otherwise, the base-object will be the object itself and no Otherwise, the base-object will be the object itself and no
data-copying will be done. data-copying will be done.
The buffertype argument can be PyBUF_READ, PyBUF_WRITE, The buffertype argument can be PyBUF_READ, PyBUF_WRITE,
PyBUF_SHADOW to determine whether the returned buffer PyBUF_SHADOW to determine whether the returned buffer
should be READONLY, WRITABLE, or set to update the should be READONLY, WRITABLE, or set to update the
original buffer if a copy must be made. If buffertype is original buffer if a copy must be made. If buffertype is
PyBUF_WRITE and the buffer is not contiguous an error will PyBUF_WRITE and the buffer is not contiguous an error will
be raised. In this circumstance, the user can use be raised. In this circumstance, the user can use
PyBUF_SHADOW to ensure that a a writable temporary PyBUF_SHADOW to ensure that a a writable temporary
contiguous buffer is returned. The contents of this contiguous buffer is returned. The contents of this
contiguous buffer will be copied back into the original contiguous buffer will be copied back into the original
object after the memoryview object is deleted as long as object after the memoryview object is deleted as long as
the original object is writable and allows setting an the original object is writable and allows setting an
exclusive write lock. If this is not allowed by the exclusive write lock. If this is not allowed by the
original object, then a BufferError is raised. original object, then a BufferError is raised.
If the object is multi-dimensional and if fortran is 'F', If the object is multi-dimensional and if fortran is 'F',
the first dimension of the underlying array will vary the the first dimension of the underlying array will vary the
fastest in the buffer. If fortran is 'C', then the last fastest in the buffer. If fortran is 'C', then the last
dimension will vary the fastest (C-style contiguous). If dimension will vary the fastest (C-style contiguous). If
fortran is 'A', then it does not matter and you will get fortran is 'A', then it does not matter and you will get
whatever the object decides is more efficient. whatever the object decides is more efficient.
A new reference is returned that must be DECREF'd when finished. A new reference is returned that must be DECREF'd when finished.
*/ */
PyAPI_FUNC(PyObject *) PyMemoryView_FromObject(PyObject *base); PyAPI_FUNC(PyObject *) PyMemoryView_FromObject(PyObject *base);
PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(Py_buffer *info); PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(Py_buffer *info);
/* create new if bufptr is NULL /* create new if bufptr is NULL
will be a new bytesobject in base */ will be a new bytesobject in base */
/* The struct is declared here so that macros can work, but it shouldn't /* The struct is declared here so that macros can work, but it shouldn't
be considered public. Don't access those fields directly, use the macros be considered public. Don't access those fields directly, use the macros
and functions instead! */ and functions instead! */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *base; PyObject *base;
Py_buffer view; Py_buffer view;
} PyMemoryViewObject; } PyMemoryViewObject;
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -33,21 +33,21 @@ dup_buffer(Py_buffer *dest, Py_buffer *src) ...@@ -33,21 +33,21 @@ dup_buffer(Py_buffer *dest, Py_buffer *src)
static int static int
memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags)
{ {
int res = 0; int res = 0;
/* XXX for whatever reason fixing the flags seems necessary */ /* XXX for whatever reason fixing the flags seems necessary */
if (self->view.readonly) if (self->view.readonly)
flags &= ~PyBUF_WRITABLE; flags &= ~PyBUF_WRITABLE;
if (self->view.obj != NULL) if (self->view.obj != NULL)
res = PyObject_GetBuffer(self->view.obj, view, flags); res = PyObject_GetBuffer(self->view.obj, view, flags);
if (view) if (view)
dup_buffer(view, &self->view); dup_buffer(view, &self->view);
return res; return res;
} }
static void static void
memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view) memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view)
{ {
PyBuffer_Release(view); PyBuffer_Release(view);
} }
PyDoc_STRVAR(memory_doc, PyDoc_STRVAR(memory_doc,
...@@ -58,61 +58,61 @@ Create a new memoryview object which references the given object."); ...@@ -58,61 +58,61 @@ Create a new memoryview object which references the given object.");
PyObject * PyObject *
PyMemoryView_FromBuffer(Py_buffer *info) PyMemoryView_FromBuffer(Py_buffer *info)
{ {
PyMemoryViewObject *mview; PyMemoryViewObject *mview;
mview = (PyMemoryViewObject *) mview = (PyMemoryViewObject *)
PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type); PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type);
if (mview == NULL) if (mview == NULL)
return NULL; return NULL;
mview->base = NULL; mview->base = NULL;
dup_buffer(&mview->view, info); dup_buffer(&mview->view, info);
/* NOTE: mview->view.obj should already have been incref'ed as /* NOTE: mview->view.obj should already have been incref'ed as
part of PyBuffer_FillInfo(). */ part of PyBuffer_FillInfo(). */
_PyObject_GC_TRACK(mview); _PyObject_GC_TRACK(mview);
return (PyObject *)mview; return (PyObject *)mview;
} }
PyObject * PyObject *
PyMemoryView_FromObject(PyObject *base) PyMemoryView_FromObject(PyObject *base)
{ {
PyMemoryViewObject *mview; PyMemoryViewObject *mview;
if (!PyObject_CheckBuffer(base)) { if (!PyObject_CheckBuffer(base)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"cannot make memory view because object does " "cannot make memory view because object does "
"not have the buffer interface"); "not have the buffer interface");
return NULL; return NULL;
} }
mview = (PyMemoryViewObject *) mview = (PyMemoryViewObject *)
PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type); PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type);
if (mview == NULL) if (mview == NULL)
return NULL; return NULL;
mview->base = NULL; mview->base = NULL;
if (PyObject_GetBuffer(base, &(mview->view), PyBUF_FULL_RO) < 0) { if (PyObject_GetBuffer(base, &(mview->view), PyBUF_FULL_RO) < 0) {
Py_DECREF(mview); Py_DECREF(mview);
return NULL; return NULL;
} }
mview->base = base; mview->base = base;
Py_INCREF(base); Py_INCREF(base);
_PyObject_GC_TRACK(mview); _PyObject_GC_TRACK(mview);
return (PyObject *)mview; return (PyObject *)mview;
} }
static PyObject * static PyObject *
memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
{ {
PyObject *obj; PyObject *obj;
static char *kwlist[] = {"object", 0}; static char *kwlist[] = {"object", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
&obj)) { &obj)) {
return NULL; return NULL;
} }
return PyMemoryView_FromObject(obj); return PyMemoryView_FromObject(obj);
} }
...@@ -120,58 +120,58 @@ static void ...@@ -120,58 +120,58 @@ static void
_strided_copy_nd(char *dest, char *src, int nd, Py_ssize_t *shape, _strided_copy_nd(char *dest, char *src, int nd, Py_ssize_t *shape,
Py_ssize_t *strides, Py_ssize_t itemsize, char fort) Py_ssize_t *strides, Py_ssize_t itemsize, char fort)
{ {
int k; int k;
Py_ssize_t outstride; Py_ssize_t outstride;
if (nd==0) { if (nd==0) {
memcpy(dest, src, itemsize); memcpy(dest, src, itemsize);
}
else if (nd == 1) {
for (k = 0; k<shape[0]; k++) {
memcpy(dest, src, itemsize);
dest += itemsize;
src += strides[0];
} }
else if (nd == 1) { }
for (k = 0; k<shape[0]; k++) { else {
memcpy(dest, src, itemsize); if (fort == 'F') {
dest += itemsize; /* Copy first dimension first,
src += strides[0]; 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];
}
} }
else { else {
if (fort == 'F') { /* Copy last dimension first,
/* Copy first dimension first, second-to-last dimension second, etc.
second dimension second, etc... Set up the recursion so that the
Set up the recursive loop backwards so that final first dimension is copied last
dimension is actually copied last. */
*/ outstride = itemsize;
outstride = itemsize; for (k=1; k < nd; k++) {
for (k=1; k<nd-1;k++) { outstride *= shape[k];
outstride *= shape[k]; }
} for (k=0; k<shape[0]; k++) {
for (k=0; k<shape[nd-1]; k++) { _strided_copy_nd(dest, src, nd-1, shape+1,
_strided_copy_nd(dest, src, nd-1, shape, strides+1, itemsize,
strides, itemsize, fort); fort);
dest += outstride; dest += outstride;
src += strides[nd-1]; src += strides[0];
} }
}
else {
/* 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];
}
}
} }
return; }
return;
} }
void _add_one_to_index_F(int nd, Py_ssize_t *index, Py_ssize_t *shape); void _add_one_to_index_F(int nd, Py_ssize_t *index, Py_ssize_t *shape);
...@@ -180,45 +180,45 @@ void _add_one_to_index_C(int nd, Py_ssize_t *index, Py_ssize_t *shape); ...@@ -180,45 +180,45 @@ void _add_one_to_index_C(int nd, Py_ssize_t *index, Py_ssize_t *shape);
static int static int
_indirect_copy_nd(char *dest, Py_buffer *view, char fort) _indirect_copy_nd(char *dest, Py_buffer *view, char fort)
{ {
Py_ssize_t *indices; Py_ssize_t *indices;
int k; int k;
Py_ssize_t elements; Py_ssize_t elements;
char *ptr; char *ptr;
void (*func)(int, Py_ssize_t *, Py_ssize_t *); void (*func)(int, Py_ssize_t *, Py_ssize_t *);
if (view->ndim > PY_SSIZE_T_MAX / sizeof(Py_ssize_t)) { if (view->ndim > PY_SSIZE_T_MAX / sizeof(Py_ssize_t)) {
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
} }
indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view->ndim); indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view->ndim);
if (indices == NULL) { if (indices == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
} }
for (k=0; k<view->ndim;k++) { for (k=0; k<view->ndim;k++) {
indices[k] = 0; indices[k] = 0;
} }
elements = 1; elements = 1;
for (k=0; k<view->ndim; k++) { for (k=0; k<view->ndim; k++) {
elements *= view->shape[k]; elements *= view->shape[k];
} }
if (fort == 'F') { if (fort == 'F') {
func = _add_one_to_index_F; func = _add_one_to_index_F;
} }
else { else {
func = _add_one_to_index_C; func = _add_one_to_index_C;
} }
while (elements--) { while (elements--) {
func(view->ndim, indices, view->shape); func(view->ndim, indices, view->shape);
ptr = PyBuffer_GetPointer(view, indices); ptr = PyBuffer_GetPointer(view, indices);
memcpy(dest, ptr, view->itemsize); memcpy(dest, ptr, view->itemsize);
dest += view->itemsize; dest += view->itemsize;
} }
PyMem_Free(indices); PyMem_Free(indices);
return 0; return 0;
} }
/* /*
...@@ -240,181 +240,181 @@ _indirect_copy_nd(char *dest, Py_buffer *view, char fort) ...@@ -240,181 +240,181 @@ _indirect_copy_nd(char *dest, Py_buffer *view, char fort)
the shadow buffer which can be written to and then the shadow buffer which can be written to and then
will be copied back into the other buffer when the memory will be copied back into the other buffer when the memory
view is de-allocated. While the shadow buffer is view is de-allocated. While the shadow buffer is
being used, it will have an exclusive write lock on being used, it will have an exclusive write lock on
the original buffer. the original buffer.
*/ */
PyObject * PyObject *
PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort) PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char fort)
{ {
PyMemoryViewObject *mem; PyMemoryViewObject *mem;
PyObject *bytes; PyObject *bytes;
Py_buffer *view; Py_buffer *view;
int flags; int flags;
char *dest; char *dest;
if (!PyObject_CheckBuffer(obj)) {
PyErr_SetString(PyExc_TypeError,
"object does not have the buffer interface");
return NULL;
}
mem = PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type); if (!PyObject_CheckBuffer(obj)) {
if (mem == NULL) PyErr_SetString(PyExc_TypeError,
return NULL; "object does not have the buffer interface");
return NULL;
}
view = &mem->view; mem = PyObject_GC_New(PyMemoryViewObject, &PyMemoryView_Type);
flags = PyBUF_FULL_RO; if (mem == NULL)
switch(buffertype) { return NULL;
case PyBUF_WRITE:
flags = PyBUF_FULL;
break;
}
if (PyObject_GetBuffer(obj, view, flags) != 0) { view = &mem->view;
Py_DECREF(mem); flags = PyBUF_FULL_RO;
return NULL; switch(buffertype) {
} case PyBUF_WRITE:
flags = PyBUF_FULL;
break;
}
if (PyBuffer_IsContiguous(view, fort)) { if (PyObject_GetBuffer(obj, view, flags) != 0) {
/* no copy needed */ Py_DECREF(mem);
Py_INCREF(obj); return NULL;
mem->base = obj; }
_PyObject_GC_TRACK(mem);
return (PyObject *)mem; if (PyBuffer_IsContiguous(view, fort)) {
} /* no copy needed */
/* otherwise a copy is needed */ Py_INCREF(obj);
if (buffertype == PyBUF_WRITE) { mem->base = obj;
Py_DECREF(mem); _PyObject_GC_TRACK(mem);
PyErr_SetString(PyExc_BufferError, return (PyObject *)mem;
"writable contiguous buffer requested " }
"for a non-contiguousobject."); /* otherwise a copy is needed */
return NULL; if (buffertype == PyBUF_WRITE) {
} Py_DECREF(mem);
bytes = PyBytes_FromStringAndSize(NULL, view->len); PyErr_SetString(PyExc_BufferError,
if (bytes == NULL) { "writable contiguous buffer requested "
Py_DECREF(mem); "for a non-contiguousobject.");
return NULL; return NULL;
} }
dest = PyBytes_AS_STRING(bytes); bytes = PyBytes_FromStringAndSize(NULL, view->len);
/* different copying strategy depending on whether if (bytes == NULL) {
or not any pointer de-referencing is needed Py_DECREF(mem);
*/ return NULL;
/* strided or in-direct copy */ }
if (view->suboffsets==NULL) { dest = PyBytes_AS_STRING(bytes);
_strided_copy_nd(dest, view->buf, view->ndim, view->shape, /* different copying strategy depending on whether
view->strides, view->itemsize, fort); or not any pointer de-referencing is needed
} */
else { /* strided or in-direct copy */
if (_indirect_copy_nd(dest, view, fort) < 0) { if (view->suboffsets==NULL) {
Py_DECREF(bytes); _strided_copy_nd(dest, view->buf, view->ndim, view->shape,
Py_DECREF(mem); view->strides, view->itemsize, fort);
return NULL; }
} else {
} if (_indirect_copy_nd(dest, view, fort) < 0) {
if (buffertype == PyBUF_SHADOW) { Py_DECREF(bytes);
/* return a shadowed memory-view object */ Py_DECREF(mem);
view->buf = dest; return NULL;
mem->base = PyTuple_Pack(2, obj, bytes);
Py_DECREF(bytes);
if (mem->base == NULL) {
Py_DECREF(mem);
return NULL;
}
} }
else { }
PyBuffer_Release(view); /* XXX ? */ if (buffertype == PyBUF_SHADOW) {
/* steal the reference */ /* return a shadowed memory-view object */
mem->base = bytes; view->buf = dest;
mem->base = PyTuple_Pack(2, obj, bytes);
Py_DECREF(bytes);
if (mem->base == NULL) {
Py_DECREF(mem);
return NULL;
} }
_PyObject_GC_TRACK(mem); }
return (PyObject *)mem; else {
PyBuffer_Release(view); /* XXX ? */
/* steal the reference */
mem->base = bytes;
}
_PyObject_GC_TRACK(mem);
return (PyObject *)mem;
} }
static PyObject * static PyObject *
memory_format_get(PyMemoryViewObject *self) memory_format_get(PyMemoryViewObject *self)
{ {
return PyUnicode_FromString(self->view.format); return PyUnicode_FromString(self->view.format);
} }
static PyObject * static PyObject *
memory_itemsize_get(PyMemoryViewObject *self) memory_itemsize_get(PyMemoryViewObject *self)
{ {
return PyLong_FromSsize_t(self->view.itemsize); return PyLong_FromSsize_t(self->view.itemsize);
} }
static PyObject * static PyObject *
_IntTupleFromSsizet(int len, Py_ssize_t *vals) _IntTupleFromSsizet(int len, Py_ssize_t *vals)
{ {
int i; int i;
PyObject *o; PyObject *o;
PyObject *intTuple; PyObject *intTuple;
if (vals == NULL) { if (vals == NULL) {
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
intTuple = PyTuple_New(len); intTuple = PyTuple_New(len);
if (!intTuple) return NULL; if (!intTuple) return NULL;
for(i=0; i<len; i++) { for(i=0; i<len; i++) {
o = PyLong_FromSsize_t(vals[i]); o = PyLong_FromSsize_t(vals[i]);
if (!o) { if (!o) {
Py_DECREF(intTuple); Py_DECREF(intTuple);
return NULL; return NULL;
} }
PyTuple_SET_ITEM(intTuple, i, o); PyTuple_SET_ITEM(intTuple, i, o);
} }
return intTuple; return intTuple;
} }
static PyObject * static PyObject *
memory_shape_get(PyMemoryViewObject *self) memory_shape_get(PyMemoryViewObject *self)
{ {
return _IntTupleFromSsizet(self->view.ndim, self->view.shape); return _IntTupleFromSsizet(self->view.ndim, self->view.shape);
} }
static PyObject * static PyObject *
memory_strides_get(PyMemoryViewObject *self) memory_strides_get(PyMemoryViewObject *self)
{ {
return _IntTupleFromSsizet(self->view.ndim, self->view.strides); return _IntTupleFromSsizet(self->view.ndim, self->view.strides);
} }
static PyObject * static PyObject *
memory_suboffsets_get(PyMemoryViewObject *self) memory_suboffsets_get(PyMemoryViewObject *self)
{ {
return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets); return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets);
} }
static PyObject * static PyObject *
memory_readonly_get(PyMemoryViewObject *self) memory_readonly_get(PyMemoryViewObject *self)
{ {
return PyBool_FromLong(self->view.readonly); return PyBool_FromLong(self->view.readonly);
} }
static PyObject * static PyObject *
memory_ndim_get(PyMemoryViewObject *self) memory_ndim_get(PyMemoryViewObject *self)
{ {
return PyLong_FromLong(self->view.ndim); return PyLong_FromLong(self->view.ndim);
} }
static PyGetSetDef memory_getsetlist[] ={ static PyGetSetDef memory_getsetlist[] ={
{"format", (getter)memory_format_get, NULL, NULL}, {"format", (getter)memory_format_get, NULL, NULL},
{"itemsize", (getter)memory_itemsize_get, NULL, NULL}, {"itemsize", (getter)memory_itemsize_get, NULL, NULL},
{"shape", (getter)memory_shape_get, NULL, NULL}, {"shape", (getter)memory_shape_get, NULL, NULL},
{"strides", (getter)memory_strides_get, NULL, NULL}, {"strides", (getter)memory_strides_get, NULL, NULL},
{"suboffsets", (getter)memory_suboffsets_get, NULL, NULL}, {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL},
{"readonly", (getter)memory_readonly_get, NULL, NULL}, {"readonly", (getter)memory_readonly_get, NULL, NULL},
{"ndim", (getter)memory_ndim_get, NULL, NULL}, {"ndim", (getter)memory_ndim_get, NULL, NULL},
{NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL},
}; };
static PyObject * static PyObject *
memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs) memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs)
{ {
return PyObject_CallFunctionObjArgs( return PyObject_CallFunctionObjArgs(
(PyObject *) &PyBytes_Type, mem, NULL); (PyObject *) &PyBytes_Type, mem, NULL);
} }
/* TODO: rewrite this function using the struct module to unpack /* TODO: rewrite this function using the struct module to unpack
...@@ -423,59 +423,59 @@ memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs) ...@@ -423,59 +423,59 @@ memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs)
static PyObject * static PyObject *
memory_tolist(PyMemoryViewObject *mem, PyObject *noargs) memory_tolist(PyMemoryViewObject *mem, PyObject *noargs)
{ {
Py_buffer *view = &(mem->view); Py_buffer *view = &(mem->view);
Py_ssize_t i; Py_ssize_t i;
PyObject *res, *item; PyObject *res, *item;
char *buf; char *buf;
if (strcmp(view->format, "B") || view->itemsize != 1) { if (strcmp(view->format, "B") || view->itemsize != 1) {
PyErr_SetString(PyExc_NotImplementedError, PyErr_SetString(PyExc_NotImplementedError,
"tolist() only supports byte views"); "tolist() only supports byte views");
return NULL; return NULL;
} }
if (view->ndim != 1) { if (view->ndim != 1) {
PyErr_SetString(PyExc_NotImplementedError, PyErr_SetString(PyExc_NotImplementedError,
"tolist() only supports one-dimensional objects"); "tolist() only supports one-dimensional objects");
return NULL; return NULL;
} }
res = PyList_New(view->len); res = PyList_New(view->len);
if (res == NULL) if (res == NULL)
return NULL; return NULL;
buf = view->buf; buf = view->buf;
for (i = 0; i < view->len; i++) { for (i = 0; i < view->len; i++) {
item = PyLong_FromUnsignedLong((unsigned char) *buf); item = PyLong_FromUnsignedLong((unsigned char) *buf);
if (item == NULL) { if (item == NULL) {
Py_DECREF(res); Py_DECREF(res);
return NULL; return NULL;
} }
PyList_SET_ITEM(res, i, item); PyList_SET_ITEM(res, i, item);
buf++; buf++;
} }
return res; return res;
} }
static PyMethodDef memory_methods[] = { static PyMethodDef memory_methods[] = {
{"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL}, {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL},
{"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL}, {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static void static void
memory_dealloc(PyMemoryViewObject *self) memory_dealloc(PyMemoryViewObject *self)
{ {
_PyObject_GC_UNTRACK(self); _PyObject_GC_UNTRACK(self);
if (self->view.obj != NULL) { if (self->view.obj != NULL) {
if (self->base && PyTuple_Check(self->base)) { if (self->base && PyTuple_Check(self->base)) {
/* Special case when first element is generic object /* Special case when first element is generic object
with buffer interface and the second element is a with buffer interface and the second element is a
contiguous "shadow" that must be copied back into contiguous "shadow" that must be copied back into
the data areay of the first tuple element before the data areay of the first tuple element before
releasing the buffer on the first element. releasing the buffer on the first element.
*/ */
PyObject_CopyData(PyTuple_GET_ITEM(self->base,0), PyObject_CopyData(PyTuple_GET_ITEM(self->base,0),
PyTuple_GET_ITEM(self->base,1)); PyTuple_GET_ITEM(self->base,1));
/* The view member should have readonly == -1 in /* The view member should have readonly == -1 in
this instance indicating that the memory can this instance indicating that the memory can
...@@ -495,23 +495,23 @@ memory_dealloc(PyMemoryViewObject *self) ...@@ -495,23 +495,23 @@ memory_dealloc(PyMemoryViewObject *self)
static PyObject * static PyObject *
memory_repr(PyMemoryViewObject *self) memory_repr(PyMemoryViewObject *self)
{ {
return PyUnicode_FromFormat("<memory at %p>", self); return PyUnicode_FromFormat("<memory at %p>", self);
} }
static PyObject * static PyObject *
memory_str(PyMemoryViewObject *self) memory_str(PyMemoryViewObject *self)
{ {
Py_buffer view; Py_buffer view;
PyObject *res; PyObject *res;
if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0) if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0)
return NULL; return NULL;
res = PyBytes_FromStringAndSize(NULL, view.len); res = PyBytes_FromStringAndSize(NULL, view.len);
PyBuffer_ToContiguous(PyBytes_AS_STRING(res), &view, view.len, 'C'); PyBuffer_ToContiguous(PyBytes_AS_STRING(res), &view, view.len, 'C');
PyBuffer_Release(&view); PyBuffer_Release(&view);
return res; return res;
} }
/* Sequence methods */ /* Sequence methods */
...@@ -524,10 +524,10 @@ memory_length(PyMemoryViewObject *self) ...@@ -524,10 +524,10 @@ memory_length(PyMemoryViewObject *self)
/* /*
mem[obj] returns a bytes object holding the data for one element if mem[obj] returns a bytes object holding the data for one element if
obj fully indexes the memory view or another memory-view object obj fully indexes the memory view or another memory-view object
if it does not. if it does not.
0-d memory-view objects can be referenced using ... or () but 0-d memory-view objects can be referenced using ... or () but
not with anything else. not with anything else.
*/ */
static PyObject * static PyObject *
memory_subscript(PyMemoryViewObject *self, PyObject *key) memory_subscript(PyMemoryViewObject *self, PyObject *key)
...@@ -536,61 +536,60 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key) ...@@ -536,61 +536,60 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
view = &(self->view); view = &(self->view);
if (view->ndim == 0) { if (view->ndim == 0) {
if (key == Py_Ellipsis || if (key == Py_Ellipsis ||
(PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) { (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) {
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
} }
else { else {
PyErr_SetString(PyExc_IndexError, PyErr_SetString(PyExc_IndexError,
"invalid indexing of 0-dim memory"); "invalid indexing of 0-dim memory");
return NULL; return NULL;
} }
} }
if (PyIndex_Check(key)) { if (PyIndex_Check(key)) {
Py_ssize_t result; Py_ssize_t result;
result = PyNumber_AsSsize_t(key, NULL); result = PyNumber_AsSsize_t(key, NULL);
if (result == -1 && PyErr_Occurred()) if (result == -1 && PyErr_Occurred())
return NULL; return NULL;
if (view->ndim == 1) { if (view->ndim == 1) {
/* Return a bytes object */ /* Return a bytes object */
char *ptr; char *ptr;
ptr = (char *)view->buf; ptr = (char *)view->buf;
if (result < 0) { if (result < 0) {
result += get_shape0(view); result += get_shape0(view);
} }
if ((result < 0) || (result >= get_shape0(view))) { if ((result < 0) || (result >= get_shape0(view))) {
PyErr_SetString(PyExc_IndexError, PyErr_SetString(PyExc_IndexError,
"index out of bounds"); "index out of bounds");
return NULL; return NULL;
} }
if (view->strides == NULL) if (view->strides == NULL)
ptr += view->itemsize * result; ptr += view->itemsize * result;
else else
ptr += view->strides[0] * result; ptr += view->strides[0] * result;
if (view->suboffsets != NULL && if (view->suboffsets != NULL &&
view->suboffsets[0] >= 0) view->suboffsets[0] >= 0) {
{ ptr = *((char **)ptr) + view->suboffsets[0];
ptr = *((char **)ptr) + view->suboffsets[0]; }
} return PyBytes_FromStringAndSize(ptr, view->itemsize);
return PyBytes_FromStringAndSize(ptr, view->itemsize); }
} else {
else { /* Return a new memory-view object */
/* Return a new memory-view object */ Py_buffer newview;
Py_buffer newview; memset(&newview, 0, sizeof(newview));
memset(&newview, 0, sizeof(newview)); /* XXX: This needs to be fixed so it
/* XXX: This needs to be fixed so it actually returns a sub-view
actually returns a sub-view */
*/ return PyMemoryView_FromBuffer(&newview);
return PyMemoryView_FromBuffer(&newview); }
}
} }
else if (PySlice_Check(key)) { else if (PySlice_Check(key)) {
Py_ssize_t start, stop, step, slicelength; Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((PySliceObject*)key, get_shape0(view), if (PySlice_GetIndicesEx((PySliceObject*)key, get_shape0(view),
&start, &stop, &step, &slicelength) < 0) { &start, &stop, &step, &slicelength) < 0) {
return NULL; return NULL;
} }
if (step == 1 && view->ndim == 1) { if (step == 1 && view->ndim == 1) {
...@@ -620,8 +619,8 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key) ...@@ -620,8 +619,8 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
return NULL; return NULL;
} }
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"cannot index memory using \"%.200s\"", "cannot index memory using \"%.200s\"",
key->ob_type->tp_name); key->ob_type->tp_name);
return NULL; return NULL;
} }
...@@ -722,118 +721,118 @@ _error: ...@@ -722,118 +721,118 @@ _error:
static PyObject * static PyObject *
memory_richcompare(PyObject *v, PyObject *w, int op) memory_richcompare(PyObject *v, PyObject *w, int op)
{ {
Py_buffer vv, ww; Py_buffer vv, ww;
int equal = 0; int equal = 0;
PyObject *res; PyObject *res;
vv.obj = NULL; vv.obj = NULL;
ww.obj = NULL; ww.obj = NULL;
if (op != Py_EQ && op != Py_NE) if (op != Py_EQ && op != Py_NE)
goto _notimpl; goto _notimpl;
if (PyObject_GetBuffer(v, &vv, PyBUF_CONTIG_RO) == -1) { if (PyObject_GetBuffer(v, &vv, PyBUF_CONTIG_RO) == -1) {
PyErr_Clear(); PyErr_Clear();
goto _notimpl; goto _notimpl;
} }
if (PyObject_GetBuffer(w, &ww, PyBUF_CONTIG_RO) == -1) { if (PyObject_GetBuffer(w, &ww, PyBUF_CONTIG_RO) == -1) {
PyErr_Clear(); PyErr_Clear();
goto _notimpl; goto _notimpl;
} }
if (vv.itemsize != ww.itemsize || vv.len != ww.len) if (vv.itemsize != ww.itemsize || vv.len != ww.len)
goto _end; goto _end;
equal = !memcmp(vv.buf, ww.buf, vv.len); equal = !memcmp(vv.buf, ww.buf, vv.len);
_end: _end:
PyBuffer_Release(&vv); PyBuffer_Release(&vv);
PyBuffer_Release(&ww); PyBuffer_Release(&ww);
if ((equal && op == Py_EQ) || (!equal && op == Py_NE)) if ((equal && op == Py_EQ) || (!equal && op == Py_NE))
res = Py_True; res = Py_True;
else else
res = Py_False; res = Py_False;
Py_INCREF(res); Py_INCREF(res);
return res; return res;
_notimpl: _notimpl:
PyBuffer_Release(&vv); PyBuffer_Release(&vv);
PyBuffer_Release(&ww); PyBuffer_Release(&ww);
Py_INCREF(Py_NotImplemented); Py_INCREF(Py_NotImplemented);
return Py_NotImplemented; return Py_NotImplemented;
} }
static int static int
memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg) memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg)
{ {
if (self->base != NULL) if (self->base != NULL)
Py_VISIT(self->base); Py_VISIT(self->base);
if (self->view.obj != NULL) if (self->view.obj != NULL)
Py_VISIT(self->view.obj); Py_VISIT(self->view.obj);
return 0; return 0;
} }
static int static int
memory_clear(PyMemoryViewObject *self) memory_clear(PyMemoryViewObject *self)
{ {
Py_CLEAR(self->base); Py_CLEAR(self->base);
PyBuffer_Release(&self->view); PyBuffer_Release(&self->view);
return 0; return 0;
} }
/* As mapping */ /* As mapping */
static PyMappingMethods memory_as_mapping = { static PyMappingMethods memory_as_mapping = {
(lenfunc)memory_length, /*mp_length*/ (lenfunc)memory_length, /* mp_length */
(binaryfunc)memory_subscript, /*mp_subscript*/ (binaryfunc)memory_subscript, /* mp_subscript */
(objobjargproc)memory_ass_sub, /*mp_ass_subscript*/ (objobjargproc)memory_ass_sub, /* mp_ass_subscript */
}; };
/* Buffer methods */ /* Buffer methods */
static PyBufferProcs memory_as_buffer = { static PyBufferProcs memory_as_buffer = {
(getbufferproc)memory_getbuf, /* bf_getbuffer */ (getbufferproc)memory_getbuf, /* bf_getbuffer */
(releasebufferproc)memory_releasebuf, /* bf_releasebuffer */ (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */
}; };
PyTypeObject PyMemoryView_Type = { PyTypeObject PyMemoryView_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
"memoryview", "memoryview",
sizeof(PyMemoryViewObject), sizeof(PyMemoryViewObject),
0, 0,
(destructor)memory_dealloc, /* tp_dealloc */ (destructor)memory_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
(reprfunc)memory_repr, /* tp_repr */ (reprfunc)memory_repr, /* tp_repr */
0, /* tp_as_number */ 0, /* tp_as_number */
0, /* tp_as_sequence */ 0, /* tp_as_sequence */
&memory_as_mapping, /* tp_as_mapping */ &memory_as_mapping, /* tp_as_mapping */
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
(reprfunc)memory_str, /* tp_str */ (reprfunc)memory_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
&memory_as_buffer, /* tp_as_buffer */ &memory_as_buffer, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
memory_doc, /* tp_doc */ memory_doc, /* tp_doc */
(traverseproc)memory_traverse, /* tp_traverse */ (traverseproc)memory_traverse, /* tp_traverse */
(inquiry)memory_clear, /* tp_clear */ (inquiry)memory_clear, /* tp_clear */
memory_richcompare, /* tp_richcompare */ memory_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
memory_methods, /* tp_methods */ memory_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
memory_getsetlist, /* tp_getset */ memory_getsetlist, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
0, /* tp_dictoffset */ 0, /* tp_dictoffset */
0, /* tp_init */ 0, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
memory_new, /* tp_new */ memory_new, /* tp_new */
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment