[Python-3000-checkins] r56792 - in python/branches/py3k-buffer: Include/bytesobject.h Include/object.h Modules/arraymodule.c Objects/abstract.c Objects/bufferobject.c Objects/bytesobject.c Objects/stringobject.c Objects/unicodeobject.c
travis.oliphant
python-3000-checkins at python.org
Tue Aug 7 07:43:49 CEST 2007
Author: travis.oliphant
Date: Tue Aug 7 07:43:49 2007
New Revision: 56792
Modified:
python/branches/py3k-buffer/Include/bytesobject.h
python/branches/py3k-buffer/Include/object.h
python/branches/py3k-buffer/Modules/arraymodule.c
python/branches/py3k-buffer/Objects/abstract.c
python/branches/py3k-buffer/Objects/bufferobject.c
python/branches/py3k-buffer/Objects/bytesobject.c
python/branches/py3k-buffer/Objects/stringobject.c
python/branches/py3k-buffer/Objects/unicodeobject.c
Log:
Update more objects to use new buffer interface.
Modified: python/branches/py3k-buffer/Include/bytesobject.h
==============================================================================
--- python/branches/py3k-buffer/Include/bytesobject.h (original)
+++ python/branches/py3k-buffer/Include/bytesobject.h Tue Aug 7 07:43:49 2007
@@ -21,6 +21,7 @@
/* Object layout */
typedef struct {
PyObject_VAR_HEAD
+ int ob_exports; /* how many buffer exports */
Py_ssize_t ob_alloc; /* How many bytes allocated */
char *ob_bytes;
} PyBytesObject;
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 07:43:49 2007
@@ -156,7 +156,7 @@
} PyBuffer;
typedef int (*getbufferproc)(PyObject *, PyBuffer *, int);
-typedef int (*releasebufferproc)(PyObject *, PyBuffer *);
+typedef void (*releasebufferproc)(PyObject *, PyBuffer *);
/* Flags for getting buffers */
#define PyBUF_SIMPLE 0
@@ -265,6 +265,7 @@
typedef struct {
getbufferproc bf_getbuffer;
releasebufferproc bf_releasebuffer;
+ inquiry bf_multisegment;
} PyBufferProcs;
typedef void (*freefunc)(void *);
Modified: python/branches/py3k-buffer/Modules/arraymodule.c
==============================================================================
--- python/branches/py3k-buffer/Modules/arraymodule.c (original)
+++ python/branches/py3k-buffer/Modules/arraymodule.c Tue Aug 7 07:43:49 2007
@@ -26,6 +26,7 @@
int itemsize;
PyObject * (*getitem)(struct arrayobject *, Py_ssize_t);
int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
+ const char *formats;
};
typedef struct arrayobject {
@@ -34,10 +35,19 @@
Py_ssize_t allocated;
struct arraydescr *ob_descr;
PyObject *weakreflist; /* List of weak references */
+ int ob_exports; /* Number of exported buffers */
} arrayobject;
static PyTypeObject Arraytype;
+#ifdef Py_UNICODE_WIDE
+#define PyArr_UNI 'w'
+static const char *PyArr_UNISTR = "w";
+#else
+#define PyArr_UNI 'u'
+static const char *PyArr_UNISTR = "u";
+#endif
+
#define array_Check(op) PyObject_TypeCheck(op, &Arraytype)
#define array_CheckExact(op) (Py_Type(op) == &Arraytype)
@@ -59,6 +69,12 @@
return 0;
}
+ if (self->ob_exports > 0) {
+ PyErr_SetString(PyExc_BufferError,
+ "cannot resize an array that is exporting data");
+ return -1;
+ }
+
/* This over-allocates proportional to the array size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
@@ -370,11 +386,12 @@
return 0;
}
+
/* Description of types */
static struct arraydescr descriptors[] = {
{'b', sizeof(char), b_getitem, b_setitem},
{'B', sizeof(char), BB_getitem, BB_setitem},
- {'u', sizeof(Py_UNICODE), u_getitem, u_setitem},
+ {PyArr_UNI, sizeof(Py_UNICODE), u_getitem, u_setitem},
{'h', sizeof(short), h_getitem, h_setitem},
{'H', sizeof(short), HH_getitem, HH_setitem},
{'i', sizeof(int), i_getitem, i_setitem},
@@ -424,6 +441,7 @@
op->ob_descr = descr;
op->allocated = size;
op->weakreflist = NULL;
+ op->ob_exports = 0;
return (PyObject *) op;
}
@@ -1402,10 +1420,10 @@
if (!PyArg_ParseTuple(args, "u#:fromunicode", &ustr, &n))
return NULL;
- if (self->ob_descr->typecode != 'u') {
+ if (self->ob_descr->typecode != PyARR_UNI) {
PyErr_SetString(PyExc_ValueError,
"fromunicode() may only be called on "
- "type 'u' arrays");
+ "unicode type arrays");
return NULL;
}
if (n > 0) {
@@ -1430,7 +1448,7 @@
"fromunicode(ustr)\n\
\n\
Extends this array with data from the unicode string ustr.\n\
-The array must be a type 'u' array; otherwise a ValueError\n\
+The array must be a unicode type array; otherwise a ValueError\n\
is raised. Use array.fromstring(ustr.decode(...)) to\n\
append Unicode data to an array of some other type.");
@@ -1438,9 +1456,9 @@
static PyObject *
array_tounicode(arrayobject *self, PyObject *unused)
{
- if (self->ob_descr->typecode != 'u') {
+ if (self->ob_descr->typecode != PyArr_UNI) {
PyErr_SetString(PyExc_ValueError,
- "tounicode() may only be called on type 'u' arrays");
+ "tounicode() may only be called on unicode type arrays");
return NULL;
}
return PyUnicode_FromUnicode((Py_UNICODE *) self->ob_item, Py_Size(self));
@@ -1450,7 +1468,7 @@
"tounicode() -> unicode\n\
\n\
Convert the array to a unicode string. The array must be\n\
-a type 'u' array; otherwise a ValueError is raised. Use\n\
+a unicode type array; otherwise a ValueError is raised. Use\n\
array.tostring().decode() to obtain a unicode string from\n\
an array of some other type.");
@@ -1541,7 +1559,7 @@
if (len == 0) {
return PyUnicode_FromFormat("array('%c')", typecode);
}
- if (typecode == 'u')
+ if (typecode == PyArr_UNI)
v = array_tounicode(a, NULL);
else
v = array_tolist(a, NULL);
@@ -1719,40 +1737,46 @@
static const void *emptybuf = "";
-static Py_ssize_t
-array_buffer_getreadbuf(arrayobject *self, Py_ssize_t index, const void **ptr)
-{
- if ( index != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "Accessing non-existent array segment");
- return -1;
- }
- *ptr = (void *)self->ob_item;
- if (*ptr == NULL)
- *ptr = emptybuf;
- return Py_Size(self)*self->ob_descr->itemsize;
-}
-
-static Py_ssize_t
-array_buffer_getwritebuf(arrayobject *self, Py_ssize_t index, const void **ptr)
+static int
+array_buffer_getbuf(arrayobject *self, PyBuffer *view, int flags)
{
- if ( index != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "Accessing non-existent array segment");
- return -1;
- }
- *ptr = (void *)self->ob_item;
- if (*ptr == NULL)
- *ptr = emptybuf;
- return Py_Size(self)*self->ob_descr->itemsize;
+ if ((flags & PyBUF_REQ_LOCKDATA)) {
+ PyErr_SetString(PyExc_BufferError,
+ "Cannot lock data");
+ return -1;
+ }
+ view->buf = (void *)self->ob_item;
+ view->len = Py_Size(self)*self->ob_descr->itemsize;
+ view->readonly = 0;
+ view->ndim = 1;
+ view->itemsize = self->ob_descr->itemsize;
+ view->suboffsets = NULL;
+ view->internal = NULL;
+ if ((flags & PyBUF_ALW_ND)==PyBUF_ALW_ND) {
+ view->shape = &(Py_Size(self));
+ }
+ else
+ view->shape = NULL;
+ if ((flags & PyBUF_ALW_STRIDES)==PyBUF_ALW_STRIDES)
+ view->strides = &(view->itemsize);
+ else
+ view->strides = NULL;
+ if ((flags & PyBUF_REQ_FORMAT) == PyBUF_REQ_FORMAT) {
+ view->format = malloc(2);
+ view->format[0] = (char)self->ob_descr->typecode;
+ view->format[1] = '\0';
+ }
+ else
+ view->format = NULL;
+ self->ob_exports++;
+ return 0;
}
-static Py_ssize_t
-array_buffer_getsegcount(arrayobject *self, Py_ssize_t *lenp)
+static int
+array_buffer_relbuf(arrayobject *self, PyBuffer *view)
{
- if ( lenp )
- *lenp = Py_Size(self)*self->ob_descr->itemsize;
- return 1;
+ free(view->format);
+ self->ob_exports--;
}
static PySequenceMethods array_as_sequence = {
@@ -1769,10 +1793,8 @@
};
static PyBufferProcs array_as_buffer = {
- (readbufferproc)array_buffer_getreadbuf,
- (writebufferproc)array_buffer_getwritebuf,
- (segcountproc)array_buffer_getsegcount,
- NULL,
+ (getbufferproc)array_buffer_getbuf,
+ (releasebufferproc)array_buffer_relbuf
};
static PyObject *
@@ -1791,7 +1813,7 @@
if (!(initial == NULL || PyList_Check(initial)
|| PyBytes_Check(initial)
|| PyString_Check(initial) || PyTuple_Check(initial)
- || (c == 'u' && PyUnicode_Check(initial)))) {
+ || (c == PyArr_UNI && PyUnicode_Check(initial)))) {
it = PyObject_GetIter(initial);
if (it == NULL)
return NULL;
@@ -1899,6 +1921,7 @@
'H' unsigned integer 2 \n\
'i' signed integer 2 \n\
'I' unsigned integer 2 \n\
+ 'w' unicode character 4
'l' signed integer 4 \n\
'L' unsigned integer 4 \n\
'f' floating point 4 \n\
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 07:43:49 2007
@@ -217,8 +217,8 @@
int
PyObject_AsCharBuffer(PyObject *obj,
- const char **buffer,
- Py_ssize_t *buffer_len)
+ const char **buffer,
+ Py_ssize_t *buffer_len)
{
PyBufferProcs *pb;
char *pp;
@@ -230,7 +230,7 @@
return -1;
}
pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL || pb->bf_getbuffer == NULL) {
+ if (pb == NULL || pb->bf_getbuffer == NULL)
PyErr_SetString(PyExc_TypeError,
"expected an object with the buffer interface");
return -1;
@@ -340,14 +340,13 @@
return (*(obj->tp_as_buffer->bf_getbuffer))(obj, view, flags);
}
-int
+void
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);
+ (*(obj->tp_as_buffer->bf_releasebuffer))(obj, view);
}
- return 0;
}
@@ -608,7 +607,7 @@
return -1;
}
}
- if (PyObject_ReleaseBuffer(obj, &view) < 0) return -1;
+ PyObject_ReleaseBuffer(obj, &view);
return 1;
}
@@ -642,7 +641,8 @@
if (PyBuffer_IsContiguous(&view, fort)) {
/* simplest copy is all that is needed */
memcpy(view.buf, buf, len);
- return PyObject_ReleaseBuffer(obj, &view);
+ PyObject_ReleaseBuffer(obj, &view);
+ return 0;
}
/* Otherwise a more elaborate scheme is needed */
@@ -676,7 +676,8 @@
}
PyMem_Free(indices);
- return PyObject_ReleaseBuffer(obj, &view);
+ PyObject_ReleaseBuffer(obj, &view);
+ return 0;
}
@@ -719,9 +720,8 @@
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;
+ PyObject_ReleaseBuffer(dest, &view_dest);
+ PyObject_ReleaseBuffer(src, &view_src);
return 0;
}
@@ -750,9 +750,8 @@
src += itemsize;
}
PyMem_Free(indices);
- if (PyObject_ReleaseBuffer(dest, &view_dest) < 0 ||
- PyObject_ReleaseBuffer(src, &view_src) < 0)
- return -1;
+ PyObject_ReleaseBuffer(dest, &view_dest);
+ PyObject_ReleaseBuffer(src, &view_src);
return 0;
}
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 07:43:49 2007
@@ -15,80 +15,58 @@
} PyBufferObject;
-enum buffer_t {
- READ_BUFFER,
- WRITE_BUFFER,
- CHAR_BUFFER,
- ANY_BUFFER
-};
-
static int
-get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
- enum buffer_t buffer_type)
+get_buf(PyBufferObject *self, PyBuffer *view)
{
if (self->b_base == NULL) {
- assert (ptr != NULL);
- *ptr = self->b_ptr;
- *size = self->b_size;
+ view->buf = self->b_ptr;
+ view->len = self->b_size;
}
else {
Py_ssize_t count, offset;
- readbufferproc proc = 0;
PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
- if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return 0;
- }
- if ((buffer_type == READ_BUFFER) ||
- ((buffer_type == ANY_BUFFER) && self->b_readonly))
- proc = bp->bf_getreadbuffer;
- else if ((buffer_type == WRITE_BUFFER) ||
- (buffer_type == ANY_BUFFER))
- proc = (readbufferproc)bp->bf_getwritebuffer;
- else if (buffer_type == CHAR_BUFFER) {
- proc = (readbufferproc)bp->bf_getcharbuffer;
- }
- if (!proc) {
- char *buffer_type_name;
- switch (buffer_type) {
- case READ_BUFFER:
- buffer_type_name = "read";
- break;
- case WRITE_BUFFER:
- buffer_type_name = "write";
- break;
- case CHAR_BUFFER:
- buffer_type_name = "char";
- break;
- default:
- buffer_type_name = "no";
- break;
- }
- PyErr_Format(PyExc_TypeError,
- "%s buffer type not available",
- buffer_type_name);
- return 0;
- }
- if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
- return 0;
+ PyBuffer view;
+ if ((*bp->bf_getbuffer)(self->b_base, view, PyBUF_SIMPLE) < 0) return 0;
+ count = view->len;
/* apply constraints to the start/end */
if (self->b_offset > count)
offset = count;
else
offset = self->b_offset;
- *(char **)ptr = *(char **)ptr + offset;
+ view->buf = (char*)view->buf + offset;
if (self->b_size == Py_END_OF_BUFFER)
- *size = count;
+ view->len = count;
else
- *size = self->b_size;
- if (offset + *size > count)
- *size = count - offset;
+ view->len = self->b_size;
+ if (offset + view->len > count)
+ view->len = count - offset;
}
return 1;
}
+static int
+buffer_getbuf(PyBufferObject *self, PyBuffer *view, int flags)
+{
+ if (!get_buf(self, view))
+ return -1;
+ return PyBuffer_FillInfo(view, view.buf, view.len, view.readonly, flags);
+}
+
+
+static int
+buffer_releasebuf(PyBufferObject *self, PyBuffer *view)
+{
+ /* No-op if there is no self->b_base */
+ if (self->b_base != NULL) {
+ PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
+ if (bp->releasebuffer != NULL) {
+ return (*bp->releasebuffer)(self->b_base, view);
+ }
+ }
+ return 0;
+}
+
static PyObject *
buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
int readonly)
@@ -248,12 +226,12 @@
}
static int
-get_bufx(PyObject *obj, void **ptr, Py_ssize_t *size)
+get_bufx(PyObject *obj, PyBuffer *view)
{
PyBufferProcs *bp;
if (PyBuffer_Check(obj)) {
- if (!get_buf((PyBufferObject *)obj, ptr, size, ANY_BUFFER)) {
+ if (!get_buf((PyBufferObject *)obj, view)) {
PyErr_Clear();
return 0;
}
@@ -262,17 +240,11 @@
}
bp = obj->ob_type->tp_as_buffer;
if (bp == NULL ||
- bp->bf_getreadbuffer == NULL ||
- bp->bf_getsegcount == NULL)
- return 0;
- if ((*bp->bf_getsegcount)(obj, NULL) != 1)
+ bp->bf_getbuffer == NULL)
return 0;
- *size = (*bp->bf_getreadbuffer)(obj, 0, ptr);
- if (*size < 0) {
- PyErr_Clear();
+ if ((*bp->bf_getbuffer)(obj, view, PyBUF_SIMPLE) < 0)
return 0;
- }
- return 1;
+ return 1;
}
static PyObject *
@@ -281,12 +253,15 @@
void *p1, *p2;
Py_ssize_t len1, len2, min_len;
int cmp, ok;
+ PyBuffer v1, v2;
ok = 1;
- if (!get_bufx(self, &p1, &len1))
+ if (!get_bufx(self, &v1))
ok = 0;
- if (!get_bufx(other, &p2, &len2))
+ if (!get_bufx(other, &v2)) {
+ if (ok) PyObject_ReleaseBuffer(self, v1);
ok = 0;
+ }
if (!ok) {
/* If we can't get the buffers,
== and != are still defined
@@ -301,11 +276,17 @@
Py_INCREF(result);
return result;
}
+ len1 = v1.len;
+ len2 = v2.len;
+ p1 = v1.buf;
+ p2 = v2.buf;
min_len = (len1 < len2) ? len1 : len2;
cmp = memcmp(p1, p2, min_len);
if (cmp == 0)
cmp = (len1 < len2) ? -1 :
(len1 > len2) ? 1 : 0;
+ PyObject_ReleaseBuffer(self, v1);
+ PyObject_ReleaseBuffer(other, v2);
return Py_CmpToRich(op, cmp);
}
@@ -335,6 +316,7 @@
{
void *ptr;
Py_ssize_t size;
+ PyBuffer view;
register Py_ssize_t len;
register unsigned char *p;
register long x;
@@ -350,34 +332,40 @@
* be to call tp_hash on the underlying object and see if it raises
* an error. */
if ( !self->b_readonly )
- {
- PyErr_SetString(PyExc_TypeError,
- "writable buffers are not hashable");
- return -1;
- }
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
+ if (!get_buf(self, &view))
+ return -1;
+ if (!(view.readonly)) {
+ PyErr_SetString(PyExc_TypeError,
+ "writable buffers are not hashable");
+ PyObject_ReleaseBuffer(self, view);
return -1;
- p = (unsigned char *) ptr;
- len = size;
+ }
+
+ p = (unsigned char *) view.buf;
+ len = view.len;
x = *p << 7;
while (--len >= 0)
x = (1000003*x) ^ *p++;
- x ^= size;
+ x ^= view.len;
if (x == -1)
x = -2;
self->b_hash = x;
+ PyObject_ReleaseBuffer(self, view);
return x;
}
static PyObject *
buffer_str(PyBufferObject *self)
{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
+ PyBuffer view;
+ PyObject *res;
+
+ if (!get_buf(self, &view))
return NULL;
- return PyString_FromStringAndSize((const char *)ptr, size);
+ res = PyString_FromStringAndSize((const char *)view.buf, view.len);
+ PyObject_ReleaseBuffer(self, view);
+ return res;
}
/* Sequence methods */
@@ -385,71 +373,58 @@
static Py_ssize_t
buffer_length(PyBufferObject *self)
{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
+ PyBuffer view;
+
+ if (!get_buf(self, &view))
return -1;
- return size;
+ PyObject_ReleaseBuffer(self, view);
+ return view.len;
}
static PyObject *
buffer_concat(PyBufferObject *self, PyObject *other)
{
PyBufferProcs *pb = other->ob_type->tp_as_buffer;
- void *ptr1, *ptr2;
char *p;
- PyObject *ob;
- Py_ssize_t size, count;
+ PyObject *ob, *ret=NULL;
+ PyBuffer view, view2;
if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
+ pb->bf_getbuffer == NULL)
{
PyErr_BadArgument();
return NULL;
}
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return NULL;
- }
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
+ if (!get_buf(self, &view))
return NULL;
/* optimize special case */
/* XXX bad idea type-wise */
- if ( size == 0 )
- {
- Py_INCREF(other);
- return other;
- }
-
- if (PyUnicode_Check(other)) {
- /* XXX HACK */
- if ( (count = (*pb->bf_getcharbuffer)(other, 0,
- (char **)&ptr2)) < 0 )
- return NULL;
- }
- else {
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return NULL;
- }
-
- /* XXX Should return a bytes object, really */
- ob = PyString_FromStringAndSize(NULL, size + count);
- if ( ob == NULL )
- return NULL;
- p = PyString_AS_STRING(ob);
- memcpy(p, ptr1, size);
- memcpy(p + size, ptr2, count);
-
- /* there is an extra byte in the string object, so this is safe */
- p[size + count] = '\0';
-
- return ob;
+ if ( view.len == 0 ) {
+ PyObject_ReleaseBuffer(self, view);
+ Py_INCREF(other);
+ return other;
+ }
+
+ if (PyObject_GetBuffer(self, view2, PyBUF_SIMPLE) < 0) {
+ PyObject_ReleaseBuffer(self, view);
+ return NULL;
+ }
+
+ ob = PyBytes_FromStringAndSize(NULL, view.len+view2.len);
+ if ( ob == NULL ) {
+ PyObject_ReleaseBuffer(self, view);
+ PyObject_ReleaseBuffer(other, view2);
+ return NULL;
+ }
+ p = PyBytes_AS_STRING(ob);
+ memcpy(p, view.buf, view.len);
+ memcpy(p + view.len, view2.buf, view2.len);
+
+ PyObject_ReleaseBuffer(self, view);
+ PyObject_ReleaseBuffer(other, view2);
+ return ob;
}
static PyObject *
@@ -459,48 +434,49 @@
register char *p;
void *ptr;
Py_ssize_t size;
+ PyBuffer view;
if ( count < 0 )
count = 0;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
+ if (!get_buf(self, &view))
return NULL;
- ob = PyString_FromStringAndSize(NULL, size * count);
+ ob = PyBytes_FromStringAndSize(NULL, view.len * count);
if ( ob == NULL )
return NULL;
- p = PyString_AS_STRING(ob);
+ p = PyBytes_AS_STRING(ob);
while ( count-- )
{
- memcpy(p, ptr, size);
- p += size;
+ memcpy(p, view.buf, view.len);
+ p += view.len;
}
- /* there is an extra byte in the string object, so this is safe */
- *p = '\0';
-
+ PyObject_ReleaseBuffer(self, view);
return ob;
}
static PyObject *
buffer_item(PyBufferObject *self, Py_ssize_t idx)
{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
+ PyBuffer view;
+ PyObject *ob;
+
+ if (!get_buf(self, &view))
return NULL;
- if ( idx < 0 || idx >= size ) {
+ if ( idx < 0 || idx >= view.len ) {
PyErr_SetString(PyExc_IndexError, "buffer index out of range");
return NULL;
}
- return PyString_FromStringAndSize((char *)ptr + idx, 1);
+ ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
+ PyObject_ReleaseBuffer(self, view);
+ return ob;
}
static PyObject *
buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
+ PyBuffer view;
+ if (!get_buf(self, &view))
return NULL;
if ( left < 0 )
left = 0;
@@ -510,28 +486,29 @@
right = size;
if ( right < left )
right = left;
- return PyString_FromStringAndSize((char *)ptr + left,
- right - left);
+ ob = PyBytes_FromStringAndSize((char *)view.buf + left,
+ right - left);
+ PyObject_ReleaseBuffer(self, view);
+ return ob;
}
static int
buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
{
PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t size;
- Py_ssize_t count;
+ PyBuffer view, view2;
- if ( self->b_readonly ) {
+ if (!get_buf(self, &view))
+ return -1;
+
+ if ( self->b_readonly || view.readonly ) {
PyErr_SetString(PyExc_TypeError,
"buffer is read-only");
+ PyObject_ReleaseBuffer(self, view);
return -1;
}
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
- return -1;
-
- if (idx < 0 || idx >= size) {
+ if (idx < 0 || idx >= view.len) {
PyErr_SetString(PyExc_IndexError,
"buffer assignment index out of range");
return -1;
@@ -539,29 +516,27 @@
pb = other ? other->ob_type->tp_as_buffer : NULL;
if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
+ pb->bf_getbuffer == NULL) {
PyErr_BadArgument();
+ PyObject_ReleaseBuffer(self, view);
return -1;
}
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return -1;
- }
-
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return -1;
- if ( count != 1 ) {
+
+ if (PyObject_GetBuffer(other, &view2, PyBUF_SIMPLE) < 0) {
+ PyObject_ReleaseBuffer(self, view);
+ return -1;
+ }
+ if ( view.len != 1 ) {
+ PyObject_ReleaseBuffer(self, view);
+ PyObject_ReleaseBuffer(other, view2);
PyErr_SetString(PyExc_TypeError,
"right operand must be a single byte");
return -1;
}
- ((char *)ptr1)[idx] = *(char *)ptr2;
+ ((char *)(view.buf))[idx] = *((char *)(view2.buf));
+ PyObject_ReleaseBuffer(self, view);
+ PyObject_ReleaseBuffer(other, view2);
return 0;
}
@@ -569,36 +544,30 @@
buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
{
PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t size;
+ PyBuffer v1, v2;
Py_ssize_t slice_len;
- Py_ssize_t count;
-
- if ( self->b_readonly ) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is read-only");
- return -1;
- }
pb = other ? other->ob_type->tp_as_buffer : NULL;
if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
+ pb->bf_getbuffer == NULL)
{
PyErr_BadArgument();
return -1;
}
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
+ if (!get_buf(self, &v1))
+ return -1;
+
+ if ( self->b_readonly || v1.readonly) {
PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
+ "buffer is read-only");
+ PyObject_ReleaseBuffer(self, v1);
return -1;
}
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
- return -1;
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return -1;
+
+ if ((*pb->bf_getbuffer)(other, &v2, PyBUF_SIMPLE) < 0) {
+ PyObject_ReleaseBuffer(self, v1);
+ return -1;
+ }
if ( left < 0 )
left = 0;
@@ -610,7 +579,7 @@
right = size;
slice_len = right - left;
- if ( count != slice_len ) {
+ if ( v2.len != slice_len ) {
PyErr_SetString(
PyExc_TypeError,
"right operand length must match slice length");
@@ -618,8 +587,10 @@
}
if ( slice_len )
- memcpy((char *)ptr1 + left, ptr2, slice_len);
+ memcpy((char *)v1.buf + left, v2.buf, slice_len);
+ PyObject_ReleaseBuffer(self, v1);
+ PyObject_ReleaseBuffer(other, v2);
return 0;
}
Modified: python/branches/py3k-buffer/Objects/bytesobject.c
==============================================================================
--- python/branches/py3k-buffer/Objects/bytesobject.c (original)
+++ python/branches/py3k-buffer/Objects/bytesobject.c Tue Aug 7 07:43:49 2007
@@ -26,6 +26,7 @@
return 0;
nullbytes->ob_bytes = NULL;
Py_Size(nullbytes) = nullbytes->ob_alloc = 0;
+ nullbytes->ob_exports = 0;
return 1;
}
@@ -48,22 +49,33 @@
return 1;
}
+static int
+bytes_getbuffer(PyBytesObject *obj, PyBuffer *view, int flags)
+{
+ int ret;
+ ret = PyBuffer_FillInfo(view, obj->ob_bytes, Py_Size(obj), 0, flags);
+ if (ret >= 0) {
+ obj->ob_exports++;
+ }
+ return ret;
+}
+
+static void
+bytes_releasebuffer(PyBytesObject *obj, PyBuffer *view)
+{
+ obj->ob_exports--;
+}
+
Py_ssize_t
-_getbuffer(PyObject *obj, void **ptr)
+_getbuffer(PyObject *obj, PyBuffer *view)
{
PyBufferProcs *buffer = Py_Type(obj)->tp_as_buffer;
if (buffer == NULL ||
PyUnicode_Check(obj) ||
- buffer->bf_getreadbuffer == NULL ||
- buffer->bf_getsegcount == NULL ||
- buffer->bf_getsegcount(obj, NULL) != 1)
- {
- *ptr = NULL;
- return -1;
- }
+ buffer->bf_getbuffer == NULL) return -1;
- return buffer->bf_getreadbuffer(obj, 0, ptr);
+ return buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE);
}
/* Direct API functions */
@@ -104,6 +116,7 @@
}
Py_Size(new) = size;
new->ob_alloc = alloc;
+ new->ob_exports = 0;
return (PyObject *)new;
}
@@ -155,6 +168,12 @@
alloc = size + 1;
}
+ if (((PyBytesObject *)self)->ob_exports > 0) {
+ PyErr_SetString(PyExc_BufferError,
+ "Existing exports of data: object cannot be re-sized");
+ return -1;
+ }
+
sval = PyMem_Realloc(((PyBytesObject *)self)->ob_bytes, alloc);
if (sval == NULL) {
PyErr_NoMemory();
@@ -172,27 +191,38 @@
PyObject *
PyBytes_Concat(PyObject *a, PyObject *b)
{
- Py_ssize_t asize, bsize, size;
- void *aptr, *bptr;
+ Py_ssize_t size;
+ PyBuffer va, vb;
PyBytesObject *result;
- asize = _getbuffer(a, &aptr);
- bsize = _getbuffer(b, &bptr);
- if (asize < 0 || bsize < 0) {
- PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
- Py_Type(a)->tp_name, Py_Type(b)->tp_name);
- return NULL;
+ va.len = -1;
+ vb.len = -1;
+ if (_getbuffer(a, &va) < 0 ||
+ _getbuffer(b, &vb) < 0) {
+ if (va.len != -1)
+ PyObject_ReleaseBuffer(a, &va);
+ if (vb.len != -1)
+ PyObject_ReleaseBuffer(b, &vb);
+ PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
+ Py_Type(a)->tp_name, Py_Type(b)->tp_name);
+ return NULL;
}
- size = asize + bsize;
- if (size < 0)
- return PyErr_NoMemory();
+ size = va.len + vb.len;
+ if (size < 0) {
+ PyObject_ReleaseBuffer(a, &va);
+ PyObject_ReleaseBuffer(b, &vb);
+ return PyErr_NoMemory();
+ }
result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, size);
if (result != NULL) {
- memcpy(result->ob_bytes, aptr, asize);
- memcpy(result->ob_bytes + asize, bptr, bsize);
+ memcpy(result->ob_bytes, va.buf, va.len);
+ memcpy(result->ob_bytes + va.len, vb.buf, vb.len);
}
+
+ PyObject_ReleaseBuffer(a, &va);
+ PyObject_ReleaseBuffer(b, &vb);
return (PyObject *)result;
}
@@ -213,30 +243,31 @@
static PyObject *
bytes_iconcat(PyBytesObject *self, PyObject *other)
{
- void *optr;
- Py_ssize_t osize;
Py_ssize_t mysize;
Py_ssize_t size;
+ PyBuffer vo;
- /* XXX What if other == self? */
- osize = _getbuffer(other, &optr);
- if (osize < 0) {
- PyErr_Format(PyExc_TypeError,
- "can't concat bytes to %.100s", Py_Type(other)->tp_name);
- return NULL;
+ if (_getbuffer(other, &vo) < 0) {
+ PyErr_Format(PyExc_TypeError,
+ "can't concat bytes to %.100s", Py_Type(self)->tp_name);
+ return NULL;
}
mysize = Py_Size(self);
- size = mysize + osize;
- if (size < 0)
- return PyErr_NoMemory();
+ size = mysize + vo.len;
+ if (size < 0) {
+ PyObject_ReleaseBuffer(other, &vo);
+ return PyErr_NoMemory();
+ }
if (size < self->ob_alloc) {
- Py_Size(self) = size;
- self->ob_bytes[Py_Size(self)] = '\0'; /* Trailing null byte */
+ Py_Size(self) = size;
+ self->ob_bytes[Py_Size(self)] = '\0'; /* Trailing null byte */
}
- else if (PyBytes_Resize((PyObject *)self, size) < 0)
- return NULL;
- memcpy(self->ob_bytes + mysize, optr, osize);
+ else if (PyBytes_Resize((PyObject *)self, size) < 0) {
+ PyObject_ReleaseBuffer(other, &vo);
+ return NULL;
+ }
+ memcpy(self->ob_bytes + mysize, vo.buf, vo.len);
Py_INCREF(self);
return (PyObject *)self;
}
@@ -409,9 +440,12 @@
{
Py_ssize_t avail, needed;
void *bytes;
+ PyBuffer vbytes;
+ int res = 0;
+ vbytes.len = -1;
if (values == (PyObject *)self) {
- /* Make a copy an call this function recursively */
+ /* Make a copy and call this function recursively */
int err;
values = PyBytes_FromObject(values);
if (values == NULL)
@@ -426,13 +460,14 @@
needed = 0;
}
else {
- needed = _getbuffer(values, &bytes);
- if (needed < 0) {
- PyErr_Format(PyExc_TypeError,
- "can't set bytes slice from %.100s",
- Py_Type(values)->tp_name);
- return -1;
- }
+ if (_getbuffer(values, &vbytes) < 0) {
+ PyErr_Format(PyExc_TypeError,
+ "can't set bytes slice from %.100s",
+ Py_Type(values)->tp_name);
+ return -1;
+ }
+ needed = vbytes.len;
+ bytes = vbytes.buf;
}
if (lo < 0)
@@ -458,8 +493,10 @@
Py_Size(self) - hi);
}
if (PyBytes_Resize((PyObject *)self,
- Py_Size(self) + needed - avail) < 0)
- return -1;
+ Py_Size(self) + needed - avail) < 0) {
+ res = -1;
+ goto finish;
+ }
if (avail < needed) {
/*
0 lo hi old_size
@@ -475,7 +512,11 @@
if (needed > 0)
memcpy(self->ob_bytes + lo, bytes, needed);
- return 0;
+
+ finish:
+ if (vbytes.len != -1)
+ PyObject_ReleaseBuffer(values, &vbytes);
+ return res;
}
static int
@@ -743,7 +784,8 @@
}
return 0;
}
-
+
+ /* XXX -> Use the modern buffer interface */
if (PyObject_CheckReadBuffer(arg)) {
const void *bytes;
Py_ssize_t size;
@@ -945,8 +987,12 @@
}
static Py_ssize_t
-bytes_getbuffer(PyBytesObject *self, Py_ssize_t index, const void **ptr)
+bytes_getbuffer(PyBytesObject *self, PyBuffer *view, int flags)
{
+ PyBuffer_FillInfo(view, ptr,
+ if (self->ob_bytes == NULL) {
+ }
+
if (index != 0) {
PyErr_SetString(PyExc_SystemError,
"accessing non-existent bytes segment");
@@ -959,15 +1005,6 @@
return Py_Size(self);
}
-static Py_ssize_t
-bytes_getsegcount(PyStringObject *self, Py_ssize_t *lenp)
-{
- if (lenp)
- *lenp = Py_Size(self);
- return 1;
-}
-
-
/* -------------------------------------------------------------------- */
/* Methods */
@@ -1018,6 +1055,7 @@
sub = PyBytes_AS_STRING(subobj);
sub_len = PyBytes_GET_SIZE(subobj);
}
+ /* XXX --> use the modern buffer interface */
else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))
/* XXX - the "expected a character buffer object" is pretty
confusing for a non-expert. remap to something else ? */
@@ -1075,6 +1113,7 @@
sub = PyBytes_AS_STRING(sub_obj);
sub_len = PyBytes_GET_SIZE(sub_obj);
}
+ /* XXX --> use the modern buffer interface */
else if (PyObject_AsCharBuffer(sub_obj, &sub, &sub_len))
return NULL;
@@ -1162,6 +1201,7 @@
sub = PyBytes_AS_STRING(substr);
slen = PyBytes_GET_SIZE(substr);
}
+ /* XXX --> Use the modern buffer interface */
else if (PyObject_AsCharBuffer(substr, &sub, &slen))
return -1;
str = PyBytes_AS_STRING(self);
@@ -1297,6 +1337,7 @@
table1 = PyBytes_AS_STRING(tableobj);
tablen = PyBytes_GET_SIZE(tableobj);
}
+ /* XXX -> Use the modern buffer interface */
else if (PyObject_AsCharBuffer(tableobj, &table1, &tablen))
return NULL;
@@ -1311,6 +1352,7 @@
del_table = PyBytes_AS_STRING(delobj);
dellen = PyBytes_GET_SIZE(delobj);
}
+ /* XXX -> use the modern buffer interface */
else if (PyObject_AsCharBuffer(delobj, &del_table, &dellen))
return NULL;
}
@@ -1984,6 +2026,7 @@
from_s = PyBytes_AS_STRING(from);
from_len = PyBytes_GET_SIZE(from);
}
+ /* XXX -> use the modern buffer interface */
else if (PyObject_AsCharBuffer(from, &from_s, &from_len))
return NULL;
@@ -1991,6 +2034,7 @@
to_s = PyBytes_AS_STRING(to);
to_len = PyBytes_GET_SIZE(to);
}
+ /* XXX -> use the modern buffer interface */
else if (PyObject_AsCharBuffer(to, &to_s, &to_len))
return NULL;
@@ -2104,6 +2148,7 @@
sub = PyBytes_AS_STRING(subobj);
n = PyBytes_GET_SIZE(subobj);
}
+ /* XXX -> use the modern buffer interface */
else if (PyObject_AsCharBuffer(subobj, &sub, &n))
return NULL;
@@ -2261,6 +2306,7 @@
sub = PyBytes_AS_STRING(subobj);
n = PyBytes_GET_SIZE(subobj);
}
+ /* XXX -> Use the modern buffer interface */
else if (PyObject_AsCharBuffer(subobj, &sub, &n))
return NULL;
@@ -2751,12 +2797,8 @@
};
static PyBufferProcs bytes_as_buffer = {
- (readbufferproc)bytes_getbuffer,
- (writebufferproc)bytes_getbuffer,
- (segcountproc)bytes_getsegcount,
- /* XXX Bytes are not characters! But we need to implement
- bf_getcharbuffer() so we can be used as 't#' argument to codecs. */
- (charbufferproc)bytes_getbuffer,
+ (getbufferproc)bytes_getbuffer,
+ (releasebufferproc)bytes_releasebuffer,
};
static PyMethodDef
Modified: python/branches/py3k-buffer/Objects/stringobject.c
==============================================================================
--- python/branches/py3k-buffer/Objects/stringobject.c (original)
+++ python/branches/py3k-buffer/Objects/stringobject.c Tue Aug 7 07:43:49 2007
@@ -1236,44 +1236,10 @@
}
}
-static Py_ssize_t
-string_buffer_getreadbuf(PyStringObject *self, Py_ssize_t index, const void **ptr)
-{
- if ( index != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent string segment");
- return -1;
- }
- *ptr = (void *)self->ob_sval;
- return Py_Size(self);
-}
-
-static Py_ssize_t
-string_buffer_getwritebuf(PyStringObject *self, Py_ssize_t index, const void **ptr)
-{
- PyErr_SetString(PyExc_TypeError,
- "Cannot use string as modifiable buffer");
- return -1;
-}
-
-static Py_ssize_t
-string_buffer_getsegcount(PyStringObject *self, Py_ssize_t *lenp)
-{
- if ( lenp )
- *lenp = Py_Size(self);
- return 1;
-}
-
-static Py_ssize_t
-string_buffer_getcharbuf(PyStringObject *self, Py_ssize_t index, const char **ptr)
+static int
+string_buffer_getbuffer(PyStringObject *self, PyBuffer *view, int flags)
{
- if ( index != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent string segment");
- return -1;
- }
- *ptr = self->ob_sval;
- return Py_Size(self);
+ return PyBuffer_FillInfo(view, (void *)self->ob_sval, Py_Size(self), 1, flags);
}
static PySequenceMethods string_as_sequence = {
@@ -1294,10 +1260,8 @@
};
static PyBufferProcs string_as_buffer = {
- (readbufferproc)string_buffer_getreadbuf,
- (writebufferproc)string_buffer_getwritebuf,
- (segcountproc)string_buffer_getsegcount,
- (charbufferproc)string_buffer_getcharbuf,
+ (getbufferproc)string_buffer_getbuffer,
+ NULL,
};
Modified: python/branches/py3k-buffer/Objects/unicodeobject.c
==============================================================================
--- python/branches/py3k-buffer/Objects/unicodeobject.c (original)
+++ python/branches/py3k-buffer/Objects/unicodeobject.c Tue Aug 7 07:43:49 2007
@@ -7788,56 +7788,16 @@
(objobjargproc)0, /* mp_ass_subscript */
};
-static Py_ssize_t
-unicode_buffer_getreadbuf(PyUnicodeObject *self,
- Py_ssize_t index,
- const void **ptr)
-{
- if (index != 0) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent unicode segment");
- return -1;
- }
- *ptr = (void *) self->str;
- return PyUnicode_GET_DATA_SIZE(self);
-}
-
-static Py_ssize_t
-unicode_buffer_getwritebuf(PyUnicodeObject *self, Py_ssize_t index,
- const void **ptr)
-{
- PyErr_SetString(PyExc_TypeError,
- "cannot use unicode as modifiable buffer");
- return -1;
-}
static int
-unicode_buffer_getsegcount(PyUnicodeObject *self,
- Py_ssize_t *lenp)
+unicode_buffer_getbuffer(PyUnicodeObject *self, PyBuffer *view, int flags)
{
- if (lenp)
- *lenp = PyUnicode_GET_DATA_SIZE(self);
- return 1;
+ int res;
+
+ return PyBuffer_FillInfo(view, (void *)self->str, PyUnicode_GET_DATA_SIZE(self),
+ 1, flags);
}
-static Py_ssize_t
-unicode_buffer_getcharbuf(PyUnicodeObject *self,
- Py_ssize_t index,
- const void **ptr)
-{
- PyObject *str;
-
- if (index != 0) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent unicode segment");
- return -1;
- }
- str = _PyUnicode_AsDefaultEncodedString((PyObject *)self, NULL);
- if (str == NULL)
- return -1;
- *ptr = (void *) PyString_AS_STRING(str);
- return PyString_GET_SIZE(str);
-}
/* Helpers for PyUnicode_Format() */
@@ -8533,10 +8493,8 @@
}
static PyBufferProcs unicode_as_buffer = {
- (readbufferproc) unicode_buffer_getreadbuf,
- (writebufferproc) unicode_buffer_getwritebuf,
- (segcountproc) unicode_buffer_getsegcount,
- (charbufferproc) unicode_buffer_getcharbuf,
+ (getbufferproc) unicode_buffer_getbuffer,
+ NULL,
};
static PyObject *
More information about the Python-3000-checkins
mailing list