Mercurial > cpython-lru_cache-weakref
diff Objects/bufferobject.c @ 38676:5bc7272b81e5 legacy-trunk
Buffer objects would return the read or write buffer for a wrapped object when
the char buffer was requested. Now it actually returns the char buffer if
available or raises a TypeError if it isn't (as is raised for the other buffer
types if they are not present but requested).
Not a backport candidate since it does change semantics of the buffer object
(although it could be argued this is enough of a bug to bother backporting).
| author | Brett Cannon <bcannon@gmail.com> |
|---|---|
| date | Thu, 08 Jun 2006 17:00:45 +0000 |
| parents | aeee85b6a5dd |
| children | 72e37ada4170 |
line wrap: on
line diff
--- a/Objects/bufferobject.c Thu Jun 08 16:23:04 2006 +0000 +++ b/Objects/bufferobject.c Thu Jun 08 17:00:45 2006 +0000 @@ -15,8 +15,16 @@ } PyBufferObject; +enum buffer_t { + READBUFFER, + WRITEBUFFER, + CHARBUFFER, + ANY_BUFFER, +}; + static int -get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size) +get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size, + enum buffer_t buffer_type) { if (self->b_base == NULL) { assert (ptr != NULL); @@ -32,10 +40,42 @@ "single-segment buffer object expected"); return 0; } - if (self->b_readonly) - proc = bp->bf_getreadbuffer; - else - proc = (readbufferproc)bp->bf_getwritebuffer; + if ((buffer_type == READBUFFER) || + ((buffer_type == ANY_BUFFER) && self->b_readonly)) + proc = bp->bf_getreadbuffer; + else if ((buffer_type == WRITEBUFFER) || + (buffer_type == ANY_BUFFER)) + proc = (readbufferproc)bp->bf_getwritebuffer; + else if (buffer_type == CHARBUFFER) { + if (!PyType_HasFeature(self->ob_type, + Py_TPFLAGS_HAVE_GETCHARBUFFER)) { + PyErr_SetString(PyExc_TypeError, + "Py_TPFLAGS_HAVE_GETCHARBUFFER needed"); + return 0; + } + proc = (readbufferproc)bp->bf_getcharbuffer; + } + if (!proc) { + char *buffer_type_name; + switch (buffer_type) { + case READBUFFER: + buffer_type_name = "read"; + break; + case WRITEBUFFER: + buffer_type_name = "write"; + break; + case CHARBUFFER: + 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; /* apply constraints to the start/end */ @@ -224,9 +264,9 @@ Py_ssize_t len_self, len_other, min_len; int cmp; - if (!get_buf(self, &p1, &len_self)) + if (!get_buf(self, &p1, &len_self, ANY_BUFFER)) return -1; - if (!get_buf(other, &p2, &len_other)) + if (!get_buf(other, &p2, &len_other, ANY_BUFFER)) return -1; min_len = (len_self < len_other) ? len_self : len_other; if (min_len > 0) { @@ -284,7 +324,7 @@ return -1; } - if (!get_buf(self, &ptr, &size)) + if (!get_buf(self, &ptr, &size, ANY_BUFFER)) return -1; p = (unsigned char *) ptr; len = size; @@ -303,7 +343,7 @@ { void *ptr; Py_ssize_t size; - if (!get_buf(self, &ptr, &size)) + if (!get_buf(self, &ptr, &size, ANY_BUFFER)) return NULL; return PyString_FromStringAndSize((const char *)ptr, size); } @@ -315,7 +355,7 @@ { void *ptr; Py_ssize_t size; - if (!get_buf(self, &ptr, &size)) + if (!get_buf(self, &ptr, &size, ANY_BUFFER)) return -1; return size; } @@ -344,7 +384,7 @@ return NULL; } - if (!get_buf(self, &ptr1, &size)) + if (!get_buf(self, &ptr1, &size, ANY_BUFFER)) return NULL; /* optimize special case */ @@ -380,7 +420,7 @@ if ( count < 0 ) count = 0; - if (!get_buf(self, &ptr, &size)) + if (!get_buf(self, &ptr, &size, ANY_BUFFER)) return NULL; ob = PyString_FromStringAndSize(NULL, size * count); if ( ob == NULL ) @@ -404,7 +444,7 @@ { void *ptr; Py_ssize_t size; - if (!get_buf(self, &ptr, &size)) + if (!get_buf(self, &ptr, &size, ANY_BUFFER)) return NULL; if ( idx < 0 || idx >= size ) { PyErr_SetString(PyExc_IndexError, "buffer index out of range"); @@ -418,7 +458,7 @@ { void *ptr; Py_ssize_t size; - if (!get_buf(self, &ptr, &size)) + if (!get_buf(self, &ptr, &size, ANY_BUFFER)) return NULL; if ( left < 0 ) left = 0; @@ -446,7 +486,7 @@ return -1; } - if (!get_buf(self, &ptr1, &size)) + if (!get_buf(self, &ptr1, &size, ANY_BUFFER)) return -1; if (idx < 0 || idx >= size) { @@ -513,7 +553,7 @@ "single-segment buffer object expected"); return -1; } - if (!get_buf(self, &ptr1, &size)) + if (!get_buf(self, &ptr1, &size, ANY_BUFFER)) return -1; if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 ) return -1; @@ -552,7 +592,7 @@ "accessing non-existent buffer segment"); return -1; } - if (!get_buf(self, pp, &size)) + if (!get_buf(self, pp, &size, READBUFFER)) return -1; return size; } @@ -560,12 +600,22 @@ 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; } - return buffer_getreadbuf(self, idx, pp); + + if ( idx != 0 ) { + PyErr_SetString(PyExc_SystemError, + "accessing non-existent buffer segment"); + return -1; + } + if (!get_buf(self, pp, &size, WRITEBUFFER)) + return -1; + return size; } static Py_ssize_t @@ -573,7 +623,7 @@ { void *ptr; Py_ssize_t size; - if (!get_buf(self, &ptr, &size)) + if (!get_buf(self, &ptr, &size, ANY_BUFFER)) return -1; if (lenp) *lenp = size; @@ -590,13 +640,12 @@ "accessing non-existent buffer segment"); return -1; } - if (!get_buf(self, &ptr, &size)) + if (!get_buf(self, &ptr, &size, CHARBUFFER)) return -1; *pp = (const char *)ptr; return size; } - static PySequenceMethods buffer_as_sequence = { (lenfunc)buffer_length, /*sq_length*/ (binaryfunc)buffer_concat, /*sq_concat*/ @@ -635,7 +684,7 @@ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &buffer_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */ buffer_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */
