[Python-3000-checkins] r56785 - in python/branches/py3k-buffer: Include/abstract.h Include/object.h Objects/abstract.c Objects/bufferobject.c
travis.oliphant
python-3000-checkins at python.org
Tue Aug 7 04:59:28 CEST 2007
Author: travis.oliphant
Date: Tue Aug 7 04:59:27 2007
New Revision: 56785
Modified:
python/branches/py3k-buffer/Include/abstract.h
python/branches/py3k-buffer/Include/object.h
python/branches/py3k-buffer/Objects/abstract.c
python/branches/py3k-buffer/Objects/bufferobject.c
Log:
Basic buffer interface and C-API completed. Still need to adapt objects.
Modified: python/branches/py3k-buffer/Include/abstract.h
==============================================================================
--- python/branches/py3k-buffer/Include/abstract.h (original)
+++ python/branches/py3k-buffer/Include/abstract.h Tue Aug 7 04:59:27 2007
@@ -534,8 +534,10 @@
*/
/* new buffer API */
-
- PyAPI_FUNC(int) PyObject_CheckBuffer(PyObject *obj);
+
+#define PyObject_CheckBuffer(obj) \
+ (((obj)->tp_as_buffer != NULL) && \
+ ((obj)->tp_as_buffer->bf_getbuffer != NULL))
/* Return 1 if the getbuffer function is available, otherwise
return 0 */
@@ -549,14 +551,23 @@
success
*/
+
PyAPI_FUNC(int) PyObject_ReleaseBuffer(PyObject *obj, PyBuffer *view);
- /* C-API version of the releasebuffer function call. It checks
- to make sure the object has the required function pointer and
- issues the call. Returns 0 on success and -1 (with an error
- raised) on failure. This function always succeeds (as a NO-OP)
- if there is no releasebuffer function for the object so that
- it can always be called when the consumer is done with the buffer
+
+ /* C-API version of the releasebuffer function call. It
+ checks to make sure the object has the required function
+ pointer and issues the call. The obj must have the buffer
+ interface or this function will cause a segfault (i.e. it
+ is assumed to be called only after a corresponding
+ getbuffer which already verified the existence of the
+ tp_as_buffer pointer).
+
+ Returns 0 on success and -1 (with an error raised) on
+ failure. This function always succeeds (as a NO-OP) if
+ there is no releasebuffer function for the object so that
+ it can always be called when the consumer is done with the
+ buffer
*/
PyAPI_FUNC(int) PyBuffer_SizeFromFormat(const char *);
@@ -610,14 +621,18 @@
*/
+ PyAPI_FUNC(int) PyObject_CopyData(PyObject *dest, PyObject *src);
+
+ /* Copy the data from the src buffer to the buffer of destination
+ */
+
PyAPI_FUNC(int) PyBuffer_IsContiguous(PyBuffer *view, char fortran);
- PyAPI_FUNC(int) PyBuffer_IsAligned(PyBuffer *view);
- PyAPI_FUNC(int) PyBuffer_FillContiguousStrides(int *ndims,
+ PyAPI_FUNC(void) PyBuffer_FillContiguousStrides(int *ndims,
Py_ssize_t *shape,
- int itemsize,
Py_ssize_t *strides,
+ int itemsize,
char fortran);
/* Fill the strides array with byte-strides of a contiguous
Modified: python/branches/py3k-buffer/Include/object.h
==============================================================================
--- python/branches/py3k-buffer/Include/object.h (original)
+++ python/branches/py3k-buffer/Include/object.h Tue Aug 7 04:59:27 2007
@@ -163,21 +163,20 @@
#define PyBUF_REQ_WRITEABLE 0x0001
#define PyBUF_REQ_LOCKDATA 0x0002
#define PyBUF_REQ_FORMAT 0x0004
-#define PyBUF_REQ_ALIGNED (0x0008 | PyBUF_REQ_FORMAT)
-#define PyBUF_ALW_ND 0x0010
-#define PyBUF_ALW_STRIDES (0x0020 | PyBUF_ALW_ND)
-#define PyBUF_REQ_C_CONTIGUOUS (0x0040 | PyBUF_ALW_STRIDES)
-#define PyBUF_REQ_F_CONTIGUOUS (0x0080 | PyBUF_ALW_STRIDES)
-#define PyBUF_REQ_ANY_CONTIGUOUS (0x0200 | PyBUF_ALW_STRIDES)
-#define PyBUF_ALW_INDIRECT (0x0400 | PyBUF_ALW_STRIDES)
-
-#define PyBUF_CONTIG (PyBUF_ALW_ND | PyBUF_REQ_WRITEABLE | PyBUF_REQ_ALIGNED)
-#define PyBUF_CONTIG_RO (PyBUF_ALW_ND | PyBUF_REQ_ALIGNED)
-#define PyBUF_CONTIG_LCK (PyBUF_ALW_ND | PyBUF_REQ_LOCKDATA | PyBUF_REQ_ALIGNED)
-
-#define PyBUF_STRIDED (PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE | PyBUF_REQ_ALIGNED)
-#define PyBUF_STRIDED_RO (PyBUF_ALW_STRIDES | PyBUF_REQ_ALIGNED)
-#define PyBUF_STRIDED_LCK (PyBUF_ALW_STRIDES | PyBUF_REQ_LOCKDATA | PyBUF_REQ_ALIGNED)
+#define PyBUF_ALW_ND 0x0008
+#define PyBUF_ALW_STRIDES (0x0010 | PyBUF_ALW_ND)
+#define PyBUF_REQ_C_CONTIGUOUS (0x0020 | PyBUF_ALW_STRIDES)
+#define PyBUF_REQ_F_CONTIGUOUS (0x0040 | PyBUF_ALW_STRIDES)
+#define PyBUF_REQ_ANY_CONTIGUOUS (0x0080 | PyBUF_ALW_STRIDES)
+#define PyBUF_ALW_INDIRECT (0x0200 | PyBUF_ALW_STRIDES)
+
+#define PyBUF_CONTIG (PyBUF_ALW_ND | PyBUF_REQ_WRITEABLE)
+#define PyBUF_CONTIG_RO (PyBUF_ALW_ND)
+#define PyBUF_CONTIG_LCK (PyBUF_ALW_ND | PyBUF_REQ_LOCKDATA)
+
+#define PyBUF_STRIDED (PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE)
+#define PyBUF_STRIDED_RO (PyBUF_ALW_STRIDES)
+#define PyBUF_STRIDED_LCK (PyBUF_ALW_STRIDES | PyBUF_REQ_LOCKDATA)
#define PyBUF_RECORDS (PyBUF_ALW_STRIDES | PyBUF_REQ_WRITEABLE | PyBUF_REQ_FORMAT)
#define PyBUF_RECORDS_RO (PyBUF_ALW_STRIDES | PyBUF_REQ_FORMAT)
Modified: python/branches/py3k-buffer/Objects/abstract.c
==============================================================================
--- python/branches/py3k-buffer/Objects/abstract.c (original)
+++ python/branches/py3k-buffer/Objects/abstract.c Tue Aug 7 04:59:27 2007
@@ -223,42 +223,46 @@
PyBufferProcs *pb;
char *pp;
Py_ssize_t len;
+ PyBuffer view;
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error();
return -1;
}
pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL ||
- pb->bf_getcharbuffer == NULL ||
- pb->bf_getsegcount == NULL) {
+ if (pb == NULL || pb->bf_getbuffer == NULL) {
PyErr_SetString(PyExc_TypeError,
- "expected a character buffer object");
+ "expected an object with the buffer interface");
return -1;
}
- if ((*pb->bf_getsegcount)(obj,NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "expected a single-segment buffer object");
- return -1;
- }
- len = (*pb->bf_getcharbuffer)(obj, 0, &pp);
- if (len < 0)
- return -1;
- *buffer = pp;
- *buffer_len = len;
+ if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
+
+ *buffer = view.buf;
+ *buffer_len = view.len;
+ if (pb->bf_releasebuffer != NULL ||
+ ((*pb->bf_releasebuffer)(obj, &view) != 0)) {
+ return -1;
+ }
return 0;
}
int
PyObject_CheckReadBuffer(PyObject *obj)
{
- PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
+ PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
if (pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL ||
- (*pb->bf_getsegcount)(obj, NULL) != 1)
- return 0;
+ pb->bf_getbuffer == NULL)
+ return 0;
+ if ((*pb->bf_getbuffer)(obj, NULL, PyBUF_SIMPLE) == -1) {
+ PyErr_Clear();
+ return 0;
+ }
+ if (*pb->bf_releasebuffer != NULL ||
+ ((*pb->bf_releasebuffer)(obj, NULL) != 0)) {
+ PyErr_Clear();
+ return 0;
+ }
return 1;
}
@@ -267,8 +271,8 @@
Py_ssize_t *buffer_len)
{
PyBufferProcs *pb;
- void *pp;
Py_ssize_t len;
+ PyBuffer view;
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error();
@@ -276,22 +280,20 @@
}
pb = obj->ob_type->tp_as_buffer;
if (pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected a readable buffer object");
- return -1;
- }
- if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
+ pb->bf_getbuffer == NULL)
PyErr_SetString(PyExc_TypeError,
- "expected a single-segment buffer object");
+ "expected an object with a buffer interface");
return -1;
}
- len = (*pb->bf_getreadbuffer)(obj, 0, &pp);
- if (len < 0)
- return -1;
- *buffer = pp;
- *buffer_len = len;
+
+ if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
+
+ *buffer = view.buf;
+ *buffer_len = view.len;
+ if (pb->bf_releasebuffer != NULL ||
+ ((*pb->bf_releasebuffer)(obj, &view) != 0)) {
+ return -1;
+ }
return 0;
}
@@ -300,8 +302,8 @@
Py_ssize_t *buffer_len)
{
PyBufferProcs *pb;
- void*pp;
Py_ssize_t len;
+ PyBuffer view;
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error();
@@ -309,25 +311,504 @@
}
pb = obj->ob_type->tp_as_buffer;
if (pb == NULL ||
- pb->bf_getwritebuffer == NULL ||
- pb->bf_getsegcount == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected a writeable buffer object");
- return -1;
- }
- if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "expected a single-segment buffer object");
+ pb->bf_getbuffer == NULL ||
+ ((*pb->bf_getbuffer)(obj, &view, PyBUF_REQ_WRITEABLE) != 0))
+ PyErr_SetString(PyExc_TypeError,
+ "expected an object with a writeable buffer interface");
return -1;
}
- len = (*pb->bf_getwritebuffer)(obj,0,&pp);
- if (len < 0)
- return -1;
- *buffer = pp;
- *buffer_len = len;
+
+ *buffer = view.buf;
+ *buffer_len = view.len;
+ if (pb->bf_releasebuffer != NULL ||
+ ((*pb->bf_releasebuffer)(obj, &view) != 0)) {
+ return -1;
+ }
return 0;
}
+/* Buffer C-API for Python 3.0 */
+
+int
+PyObject_GetBuffer(PyObject *obj, PyBuffer *view, int flags)
+{
+ if !PyObject_CheckBuffer(obj) {
+ PyErr_SetString(PyExc_TypeError,
+ "object does not have the buffer interface");
+ return -1;
+ }
+ return (*(obj->tp_as_buffer->bf_getbuffer))(obj, view, flags);
+}
+
+int
+PyObject_ReleaseBuffer(PyObject *obj, PyBuffer *view)
+{
+ if (obj->tp_as_buffer != NULL &&
+ obj->tp_as_buffer->bf_releasebuffer != NULL) {
+ return (*(obj->tp_as_buffer->bf_releasebuffer))(obj, view);
+ }
+ return 0;
+}
+
+
+static int
+_IsFortranContiguous(PyBuffer *view);
+{
+ Py_ssize_t sd, dim;
+ int i;
+
+ if (view->nd == 0) return 1;
+ if (view->strides == NULL) return (view->nd == 1);
+
+ sd = view->itemsize;
+ if (view->nd == 1) return (view->shape[0] == 1 ||
+ sd == view->strides[0]);
+ for (i=0; i<view->nd; i++) {
+ dim = view->shape[i];
+ if (dim == 0) return 1;
+ if (view->strides[i] != sd) return 0;
+ sd *= dim;
+ }
+ return 1;
+}
+
+static int
+_IsCContiguous(PyBuffer *view);
+{
+ Py_ssize_t sd, dim;
+ int i;
+
+ if (view->nd == 0) return 1;
+ if (view->strides == NULL) return 1;
+
+ sd = view->itemsize;
+ if (view->nd == 1) return (view->shape[0] == 1 ||
+ sd == view->strides[0]);
+ for (i=view->nd-1; i>=0; i--) {
+ dim = view->shape[i];
+ if (dim == 0) return 1;
+ if (view->strides[i] != sd) return 0;
+ sd *= dim;
+ }
+ return 1;
+}
+
+int
+PyBuffer_IsContiguous(PyBuffer *view, char fort)
+{
+
+ if (view->suboffsets != NULL) return 0;
+
+ if (fort == 'C')
+ return _IsCContiguous(view);
+ else if (fort == 'F')
+ return _IsFortranContiguous(view);
+ else if (fort == 'A')
+ return (_IsCContiguous(view) || _IsFortranContiguous(view));
+ return 0;
+}
+
+static void
+_strided_copy_nd(char *dest, char *src, int nd, Py_ssize_t *shape,
+ Py_ssize_t *strides, int itemsize, char fort)
+{
+ int k;
+ Py_ssize_t outstride;
+ char *ptr;
+
+ 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];
+ }
+ }
+ 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, suboffsets, itemsize, fort);
+ dest += outstride;
+ src += strides[nd-1];
+ }
+ }
+
+ 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, suboffsets+1, itemsize,
+ fort);
+ dest += outstride;
+ src += strides[0];
+ }
+ }
+ }
+ return;
+}
+
+static void
+_add_one_to_index_F(int nd, Py_ssize_t *index, Py_ssize_t *shape)
+{
+ int k;
+
+ for (k=0; k<nd; k++) {
+ if (index[k] < shape[k]-1) {
+ index[k]++;
+ break;
+ }
+ else {
+ index[k] = 0;
+ }
+ }
+}
+
+static void
+_add_one_to_index_C(int nd, Py_ssize_t *index, Py_ssize_t *shape)
+{
+ int k;
+
+ for (k=nd-1; k>=0; k--) {
+ if (index[k] < shape[k]-1) {
+ index[k]++;
+ break;
+ }
+ else {
+ index[k] = 0;
+ }
+ }
+}
+
+static void*
+get_item_pointer(PyBuffer *view, Py_ssize_t *indices)
+{
+ char* pointer;
+ int i;
+ pointer = (char *)view->buf;
+ for (i = 0; i < view->ndim; i++) {
+ pointer += view->strides[i]*indices[i];
+ if ((view->suboffsets != NULL) && (view->suboffsets[i] >= 0)) {
+ pointer = *((char**)pointer) + view->suboffsets[i];
+ }
+ }
+ return (void*)pointer;
+}
+
+
+static int
+_indirect_copy_nd(char *dest, PyBuffer *view, char fort)
+{
+ Py_ssize_t *indices;
+ int k;
+ Py_ssize_t elements;
+ char *ptr;
+ void (*func)(int, Py_ssize_t *, Py_ssize_t *);
+
+
+ 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;
+ }
+
+ elements = 1;
+ for (k=0; k<view->ndim; k++) {
+ elements *= view->shape[k];
+ }
+ if (fort == 'F') {
+ func = _add_one_to_index_F;
+ }
+ else {
+ func = _add_one_to_index_C;
+ }
+ while (elements--) {
+ func(view->ndim, indices, view->shape);
+ ptr = get_item_pointer(view, indices);
+ memcpy(dest, ptr, view->itemsize);
+ dest += itemsize;
+ }
+
+ PyMem_Free(indices);
+ return 0;
+}
+
+/* Get a the data from an object as a contiguous chunk of memory even
+ if it means copying it into a separate memory area.
+
+ Make sure PyMem_Free is called on *buf if a copy is made.
+ */
+int
+PyObject_GetContiguous(PyObject *obj, void **buf, Py_ssize_t *len,
+ char **format, int writeable, char fort)
+{
+ PyBuffer view;
+ getbufferproc func;
+ int flags;
+
+ if !PyObject_CheckBuffer(obj) {
+ PyErr_SetString(PyExc_TypeError,
+ "object does not have the buffer interface");
+ return -1;
+ }
+ func = obj->tp_as_buffer->bf_getbuffer;
+
+ flags = (writeable ? PyBUF_FULL : PyBUF_FULL_RO);
+ if (PyObject_GetBuffer(obj, &view, flags) != 0) return -1;
+
+ *len = view.len;
+ *format = view.format;
+ if (PyBuffer_IsContiguous(&view, fort)) {
+ /* no copy needed */
+ *buf = view.buf;
+ PyObject_ReleaseBuffer(obj, &view);
+ return -1;
+ }
+ /* otherwise a copy is needed */
+ *buf = PyMem_Malloc(*len);
+ if (*buf == NULL) {
+ PyObject_ReleaseBuffer(obj, &view);
+ return -1;
+ }
+ /* different copying strategy depending on whether
+ or not any pointer de-referencing is needed
+ */
+ /* strided or in-direct copy */
+ if (suboffsets==NULL) {
+ _strided_copy_nd(*buf, view.buf, view.ndim,
+ view.shape, view.strides,
+ view.itemsize, fort);
+ }
+ else {
+ if (_indirect_copy_nd(*buf, &view, fort) < 0) {
+ PyMem_Free(*buf);
+ PyObject_ReleaseBuffer(obj, &view);
+ return -1;
+ }
+ }
+ if (PyObject_ReleaseBuffer(obj, &view) < 0) return -1;
+ return 1;
+}
+
+int
+PyObject_CopyToObject(PyObject *obj, void *buf, Py_ssize_t len,
+ char fort);
+{
+ PyBuffer view;
+ getbufferproc func;
+ int k;
+ void (*addone)(int, Py_ssize_t *, Py_ssize_t *);
+ Py_ssize_t *indices, elements;
+ char *src;
+
+ if !PyObject_CheckBuffer(obj) {
+ PyErr_SetString(PyExc_TypeError,
+ "object does not have the buffer interface");
+ return -1;
+ }
+ func = obj->tp_as_buffer->bf_getbuffer;
+
+ if (PyObject_GetBuffer(obj, &view, PyBUF_FULL) != 0) return -1;
+
+ if (len > view.len) {
+ PyErr_SetString(PyExc_BufferError,
+ "object is too small to receive data");
+ PyObject_ReleaseBuffer(obj, &view);
+ return -1;
+ }
+
+ if (PyBuffer_IsContiguous(&view, fort)) {
+ /* simplest copy is all that is needed */
+ memcpy(view.buf, buf, len);
+ return PyObject_ReleaseBuffer(obj, &view);
+ }
+
+ /* Otherwise a more elaborate scheme is needed */
+
+ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view->ndim);
+ if (indices == NULL) {
+ PyErr_NoMemory();
+ PyObject_ReleaseBuffer(obj, &view);
+ return -1;
+ }
+ for (k=0; k<view->ndim;k++) {
+ indices[k] = 0;
+ }
+
+ elements = 1;
+ for (k=0; k<view->ndim; k++) {
+ elements *= view->shape[k];
+ }
+ if (fort == 'F') {
+ addone = _add_one_to_index_F;
+ }
+ else {
+ addone = _add_one_to_index_C;
+ }
+ src = buf;
+ while (elements--) {
+ addone(view->ndim, indices, view->shape);
+ ptr = get_item_pointer(view, indices);
+ memcpy(ptr, src, view->itemsize);
+ src += itemsize;
+ }
+
+ PyMem_Free(indices);
+ return PyObject_ReleaseBuffer(obj, &view);
+}
+
+
+int PyObject_CopyData(PyObject *dest, PyObject *src) {
+
+ PyBuffer view_dest, view_src;
+ getbufferproc func;
+ int k;
+ Py_ssize_t *indices, elements;
+ char *dptr, *sptr;
+
+ if !PyObject_CheckBuffer(dest) {
+ PyErr_SetString(PyExc_TypeError,
+ "destination does not have the buffer interface");
+ return -1;
+ }
+ if !PyObject_CheckBuffer(src) {
+ PyErr_SetString(PyExc_TypeError,
+ "source does not have the buffer interface");
+ return -1;
+ }
+
+ func = dest->tp_as_buffer->bf_getbuffer;
+ if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1;
+
+ func = src->tp_as_buffer->bf_getbuffer;
+ if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) return -1;
+
+ if (view_dest.len < view_src.len) {
+ PyErr_SetString(PyExc_BufferError,
+ "destination is too small to receive data from source");
+ PyObject_ReleaseBuffer(dest, &view_dest);
+ PyObject_ReleaseBuffer(src, &view_src);
+ return -1;
+ }
+
+ if ((PyBuffer_IsContiguous(&view_dest, 'C') &&
+ PyBuffer_IsContiguous(&src_dest, 'C')) ||
+ (PyBuffer_IsContiguous(&view_dest, 'F') &&
+ PyBuffer_IsContiguous(&src_dest, 'F'))) {
+ /* simplest copy is all that is needed */
+ memcpy(view_dest.buf, view_src.buf, view_src.len);
+ if (PyObject_ReleaseBuffer(dest, &view_dest) < 0 ||
+ PyObject_ReleaseBuffer(src, &view_src) < 0)
+ return -1;
+ return 0;
+ }
+
+ /* Otherwise a more elaborate copy scheme is needed */
+
+ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view->ndim);
+ if (indices == NULL) {
+ PyErr_NoMemory();
+ PyObject_ReleaseBuffer(dest, &view_dest);
+ PyObject_ReleaseBuffer(src, &view_src);
+ return -1;
+ }
+ for (k=0; k<view->ndim;k++) {
+ indices[k] = 0;
+ }
+ elements = 1;
+ for (k=0; k<view->ndim; k++) {
+ elements *= view->shape[k];
+ }
+ src = buf;
+ while (elements--) {
+ _add_one_to_index_C(view->ndim, indices, view->shape);
+ dptr = get_item_pointer(view_dest, indices);
+ sptr = get_item_pointer(view_src, indices);
+ memcpy(dptr, sptr, view->itemsize);
+ src += itemsize;
+ }
+ PyMem_Free(indices);
+ if (PyObject_ReleaseBuffer(dest, &view_dest) < 0 ||
+ PyObject_ReleaseBuffer(src, &view_src) < 0)
+ return -1;
+ return 0;
+}
+
+static void
+PyBuffer_FillContiguousStrides(int *nd, Py_ssize_t *shape,
+ Py_ssize_t *strides, int itemsize,
+ char fort)
+{
+ int k;
+ Py_ssize_t sd;
+
+ sd = itemsize;
+ if (fort == 'F') {
+ for (k=0; k<nd; k++) {
+ strides[k] = sd;
+ sd *= shape[k];
+ }
+ }
+ else {
+ for (k=nd-1; k>=0; k--) {
+ strides[k] = sd;
+ sd *= shape[k];
+ }
+ }
+ return;
+}
+
+static int
+PyBuffer_FillInfo(PyBuffer *view, void *buf, Py_ssize_t len,
+ int readonly, int flags)
+{
+ if ((flags & PyBUF_REQ_LOCKDATA) == PyBUF_REQ_LOCKDATA && readonly != -1) {
+ PyErr_SetString(PyExc_BufferError, "Cannot make this object read-only.");
+ return -1;
+ }
+ view->buf = buf;
+ view->len = len;
+ view->readonly = readonly;
+ view->format = NULL;
+ if ((flags & PyBUF_REQ_FORMAT) == PyBUF_REQ_FORMAT)
+ view->format = "B";
+ view->ndim = 1;
+ if ((flags & PyBUF_ALW_ND) == PyBUF_ALW_ND)
+ view->shape = &(view->len);
+ else
+ view->shape = NULL;
+ view->itemsize = 1;
+ if ((flags & PyBUF_ALW_STRIDES) == PyBUF_ALW_STRIDES)
+ view->strides = &(view->itemsize);
+ else
+ view->strides = NULL;
+ view->suboffsets = NULL;
+ view->internal = NULL;
+ return 0;
+}
+
/* Operations on numbers */
int
Modified: python/branches/py3k-buffer/Objects/bufferobject.c
==============================================================================
--- python/branches/py3k-buffer/Objects/bufferobject.c (original)
+++ python/branches/py3k-buffer/Objects/bufferobject.c Tue Aug 7 04:59:27 2007
@@ -152,10 +152,8 @@
PyBufferProcs *pb = base->ob_type->tp_as_buffer;
if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_SetString(PyExc_TypeError, "buffer object expected");
+ pb->bf_getbuffer == NULL) {
+ PyErr_SetString(PyExc_TypeError, "buffer object expected");
return NULL;
}
@@ -168,9 +166,7 @@
PyBufferProcs *pb = base->ob_type->tp_as_buffer;
if ( pb == NULL ||
- pb->bf_getwritebuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
+ pb->bf_getbuffer == NULL) {
PyErr_SetString(PyExc_TypeError, "buffer object expected");
return NULL;
}
@@ -629,69 +625,6 @@
/* Buffer methods */
-static Py_ssize_t
-buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
-{
- Py_ssize_t size;
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, pp, &size, READ_BUFFER))
- return -1;
- return size;
-}
-
-static Py_ssize_t
-buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
-{
- Py_ssize_t size;
-
- if ( self->b_readonly )
- {
- PyErr_SetString(PyExc_TypeError, "buffer is read-only");
- return -1;
- }
-
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, pp, &size, WRITE_BUFFER))
- return -1;
- return size;
-}
-
-static Py_ssize_t
-buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return -1;
- if (lenp)
- *lenp = size;
- return 1;
-}
-
-static Py_ssize_t
-buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
-{
- void *ptr;
- Py_ssize_t size;
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
- return -1;
- *pp = (const char *)ptr;
- return size;
-}
-
static PySequenceMethods buffer_as_sequence = {
(lenfunc)buffer_length, /*sq_length*/
(binaryfunc)buffer_concat, /*sq_concat*/
@@ -703,10 +636,8 @@
};
static PyBufferProcs buffer_as_buffer = {
- (readbufferproc)buffer_getreadbuf,
- (writebufferproc)buffer_getwritebuf,
- (segcountproc)buffer_getsegcount,
- (charbufferproc)buffer_getcharbuf,
+ (getbufferproc)buffer_getbuf,
+ (releasebufferproc)buffer_releasebuf,
};
PyTypeObject PyBuffer_Type = {
More information about the Python-3000-checkins
mailing list