diff options
author | Travis E. Oliphant <oliphant@enthought.com> | 2007-08-18 11:21:56 (GMT) |
---|---|---|
committer | Travis E. Oliphant <oliphant@enthought.com> | 2007-08-18 11:21:56 (GMT) |
commit | b99f762f10edb2646a634c2290ecb064bd52e5c7 (patch) | |
tree | e0a354d42dccb18b7b2c99ed2733c135135a50af /Modules | |
parent | 3de862df45480438dc6756103109ea9010d2825e (diff) | |
download | cpython-b99f762f10edb2646a634c2290ecb064bd52e5c7.zip cpython-b99f762f10edb2646a634c2290ecb064bd52e5c7.tar.gz cpython-b99f762f10edb2646a634c2290ecb064bd52e5c7.tar.bz2 |
Merged in py3k-buffer branch to main line. All objects now use the buffer protocol in PEP 3118.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 39 | ||||
-rw-r--r-- | Modules/_sre.c | 44 | ||||
-rw-r--r-- | Modules/arraymodule.c | 117 | ||||
-rw-r--r-- | Modules/mmapmodule.c | 73 |
4 files changed, 138 insertions, 135 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index e6db969..fcb9085 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -739,22 +739,33 @@ CharArray_set_raw(CDataObject *self, PyObject *value) { char *ptr; Py_ssize_t size; + int rel = 0; + PyBuffer view; + if (PyBuffer_Check(value)) { - size = Py_Type(value)->tp_as_buffer->bf_getreadbuffer(value, 0, (void *)&ptr); - if (size < 0) - return -1; + if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) < 0) + return -1; + size = view.len; + ptr = view.buf; + rel = 1; } else if (-1 == PyString_AsStringAndSize(value, &ptr, &size)) { return -1; } if (size > self->b_size) { PyErr_SetString(PyExc_ValueError, "string too long"); - return -1; + goto fail; } memcpy(self->b_ptr, ptr, size); + if (rel) + PyObject_ReleaseBuffer(value, &view); return 0; + fail: + if (rel) + PyObject_ReleaseBuffer(value, &view); + return -1; } static PyObject * @@ -2072,29 +2083,15 @@ static PyMemberDef CData_members[] = { { NULL }, }; -static Py_ssize_t CData_GetBuffer(PyObject *_self, Py_ssize_t seg, void **pptr) +static int CData_GetBuffer(PyObject *_self, PyBuffer *view, int flags) { CDataObject *self = (CDataObject *)_self; - if (seg != 0) { - /* Hm. Must this set an exception? */ - return -1; - } - *pptr = self->b_ptr; - return self->b_size; -} - -static Py_ssize_t CData_GetSegcount(PyObject *_self, Py_ssize_t *lenp) -{ - if (lenp) - *lenp = 1; - return 1; + return PyBuffer_FillInfo(view, self->b_ptr, self->b_size, 0, flags); } static PyBufferProcs CData_as_buffer = { CData_GetBuffer, - CData_GetBuffer, - CData_GetSegcount, - NULL, + NULL, }; /* diff --git a/Modules/_sre.c b/Modules/_sre.c index 012f127..295bc93 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -1672,44 +1672,38 @@ getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize) Py_ssize_t size, bytes; int charsize; void* ptr; - -#if defined(HAVE_UNICODE) - if (PyUnicode_Check(string)) { - /* unicode strings doesn't always support the buffer interface */ - ptr = (void*) PyUnicode_AS_DATA(string); - bytes = PyUnicode_GET_DATA_SIZE(string); - size = PyUnicode_GET_SIZE(string); - charsize = sizeof(Py_UNICODE); - - } else { -#endif + PyBuffer view; /* get pointer to string buffer */ + view.len = -1; buffer = Py_Type(string)->tp_as_buffer; - if (!buffer || !buffer->bf_getreadbuffer || !buffer->bf_getsegcount || - buffer->bf_getsegcount(string, NULL) != 1) { - PyErr_SetString(PyExc_TypeError, "expected string or buffer"); - return NULL; + if (!buffer || !buffer->bf_getbuffer || + (*buffer->bf_getbuffer)(string, &view, PyBUF_SIMPLE) < 0) { + PyErr_SetString(PyExc_TypeError, "expected string or buffer"); + return NULL; } /* determine buffer size */ - bytes = buffer->bf_getreadbuffer(string, 0, &ptr); + bytes = view.len; + ptr = view.buf; + + /* Release the buffer immediately --- possibly dangerous + but doing something else would require some re-factoring + */ + PyObject_ReleaseBuffer(string, &view); + if (bytes < 0) { PyErr_SetString(PyExc_TypeError, "buffer has negative size"); return NULL; } /* determine character size */ -#if PY_VERSION_HEX >= 0x01060000 size = PyObject_Size(string); -#else - size = PyObject_Length(string); -#endif if (PyString_Check(string) || bytes == size) charsize = 1; #if defined(HAVE_UNICODE) - else if (bytes == (Py_ssize_t) (size * sizeof(Py_UNICODE))) + else if (bytes == (Py_ssize_t) (size * sizeof(Py_UNICODE))) charsize = sizeof(Py_UNICODE); #endif else { @@ -1717,13 +1711,13 @@ getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize) return NULL; } -#if defined(HAVE_UNICODE) - } -#endif - *p_length = size; *p_charsize = charsize; + if (ptr == NULL) { + PyErr_SetString(PyExc_ValueError, + "Buffer is NULL"); + } return ptr; } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 8e8dce2..656fc09 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -26,6 +26,7 @@ struct arraydescr { 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 @@ typedef struct arrayobject { 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 @@ array_resize(arrayobject *self, Py_ssize_t newsize) 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 @@ d_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) 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 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr) op->ob_descr = descr; op->allocated = size; op->weakreflist = NULL; + op->ob_exports = 0; return (PyObject *) op; } @@ -1403,10 +1421,10 @@ array_fromunicode(arrayobject *self, PyObject *args) 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) { @@ -1431,7 +1449,7 @@ PyDoc_STRVAR(fromunicode_doc, "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."); @@ -1439,9 +1457,9 @@ append Unicode data to an array of some other type."); 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)); @@ -1451,7 +1469,7 @@ PyDoc_STRVAR(tounicode_doc, "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."); @@ -1542,7 +1560,7 @@ array_repr(arrayobject *a) 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); @@ -1720,40 +1738,56 @@ static PyMappingMethods array_as_mapping = { 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_CHARACTER)) { + PyErr_SetString(PyExc_TypeError, + "Cannot be a character buffer"); + return -1; + } + if ((flags & PyBUF_LOCKDATA)) { + PyErr_SetString(PyExc_BufferError, + "Cannot lock data"); + return -1; + } + if (view==NULL) goto finish; + + view->buf = (void *)self->ob_item; + if (view->buf == NULL) + view->buf = (void *)emptybuf; + 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->shape = NULL; + if ((flags & PyBUF_ND)==PyBUF_ND) { + view->shape = &((Py_Size(self))); + } + view->strides = NULL; + if ((flags & PyBUF_STRIDES)==PyBUF_STRIDES) + view->strides = &(view->itemsize); + view->format = NULL; + view->internal = NULL; + if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { + view->internal = malloc(3); + view->format = view->internal; + view->format[0] = (char)(self->ob_descr->typecode); + view->format[1] = '\0'; + } + + finish: + self->ob_exports++; + return 0; } -static Py_ssize_t -array_buffer_getsegcount(arrayobject *self, Py_ssize_t *lenp) +static void +array_buffer_relbuf(arrayobject *self, PyBuffer *view) { - if ( lenp ) - *lenp = Py_Size(self)*self->ob_descr->itemsize; - return 1; + free(view->internal); + self->ob_exports--; } static PySequenceMethods array_as_sequence = { @@ -1770,10 +1804,8 @@ static PySequenceMethods array_as_sequence = { }; 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 * @@ -1792,7 +1824,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 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; @@ -1900,6 +1932,7 @@ is a single character. The following type codes are defined:\n\ 'H' unsigned integer 2 \n\ 'i' signed integer 2 \n\ 'I' unsigned integer 2 \n\ + 'w' unicode character 4 \n\ 'l' signed integer 4 \n\ 'L' unsigned integer 4 \n\ 'f' floating point 4 \n\ diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 1626d72..16a9dd2 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -75,6 +75,7 @@ typedef struct { char * data; size_t size; size_t pos; + int exports; #ifdef MS_WINDOWS HANDLE map_handle; @@ -119,6 +120,11 @@ mmap_object_dealloc(mmap_object *m_obj) static PyObject * mmap_close_method(mmap_object *self, PyObject *unused) { + if (self->exports > 0) { + PyErr_SetString(PyExc_BufferError, "cannot close "\ + "exported pointers exist"); + return NULL; + } #ifdef MS_WINDOWS /* For each resource we maintain, we need to check the value is valid, and if so, free the resource @@ -277,8 +283,13 @@ is_writeable(mmap_object *self) static int is_resizeable(mmap_object *self) { + if (self->exports > 0) { + PyErr_SetString(PyExc_BufferError, + "mmap can't resize with extant buffers exported."); + return 0; + } if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT)) - return 1; + return 1; PyErr_Format(PyExc_TypeError, "mmap can't resize a readonly or copy-on-write memory map."); return 0; @@ -589,53 +600,21 @@ static struct PyMethodDef mmap_object_methods[] = { /* Functions for treating an mmap'ed file as a buffer */ -static Py_ssize_t -mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr) -{ - CHECK_VALID(-1); - if (index != 0) { - PyErr_SetString(PyExc_SystemError, - "Accessing non-existent mmap segment"); - return -1; - } - *ptr = self->data; - return self->size; -} - -static Py_ssize_t -mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr) -{ - CHECK_VALID(-1); - if (index != 0) { - PyErr_SetString(PyExc_SystemError, - "Accessing non-existent mmap segment"); - return -1; - } - if (!is_writeable(self)) - return -1; - *ptr = self->data; - return self->size; -} - -static Py_ssize_t -mmap_buffer_getsegcount(mmap_object *self, Py_ssize_t *lenp) +static int +mmap_buffer_getbuf(mmap_object *self, PyBuffer *view, int flags) { CHECK_VALID(-1); - if (lenp) - *lenp = self->size; - return 1; + if (PyBuffer_FillInfo(view, self->data, self->size, + (self->access == ACCESS_READ), flags) < 0) + return -1; + self->exports++; + return 0; } -static Py_ssize_t -mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr) +static void +mmap_buffer_releasebuf(mmap_object *self, PyBuffer *view) { - if (index != 0) { - PyErr_SetString(PyExc_SystemError, - "accessing non-existent buffer segment"); - return -1; - } - *ptr = (const char *)self->data; - return self->size; + self->exports--; } static PyObject * @@ -775,10 +754,8 @@ static PySequenceMethods mmap_as_sequence = { }; static PyBufferProcs mmap_as_buffer = { - (readbufferproc)mmap_buffer_getreadbuf, - (writebufferproc)mmap_buffer_getwritebuf, - (segcountproc)mmap_buffer_getsegcount, - (charbufferproc)mmap_buffer_getcharbuffer, + (getbufferproc)mmap_buffer_getbuf, + (releasebufferproc)mmap_buffer_releasebuf, }; static PyTypeObject mmap_object_type = { @@ -900,6 +877,7 @@ new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict) m_obj->data = NULL; m_obj->size = (size_t) map_size; m_obj->pos = (size_t) 0; + m_obj->exports = 0; if (fd == -1) { m_obj->fd = -1; /* Assume the caller wants to map anonymous memory. @@ -1069,6 +1047,7 @@ new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict) /* set the initial position */ m_obj->pos = (size_t) 0; + m_obj->exports = 0; /* set the tag name */ if (tagname != NULL && *tagname != '\0') { m_obj->tagname = PyMem_Malloc(strlen(tagname)+1); |