blob: 62b869bdf3b0829464f1e6fd1a5bdd482cf7b2af [file] [log] [blame]
Guido van Rossum2e19bd71998-10-07 14:36:10 +00001
2/* Buffer object implementation */
3
4#include "Python.h"
5
6
7typedef struct {
8 PyObject_HEAD
9 PyObject *b_base;
10 void *b_ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +000011 Py_ssize_t b_size;
12 Py_ssize_t b_offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000013 int b_readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000014 long b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000015} PyBufferObject;
16
17
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000018static int
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +000019get_buf(PyBufferObject *self, Py_buffer *view, int flags)
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000020{
21 if (self->b_base == NULL) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000022 view->buf = self->b_ptr;
23 view->len = self->b_size;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +000024 view->readonly = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000025 }
26 else {
Martin v. Löwis18e16552006-02-15 17:27:45 +000027 Py_ssize_t count, offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000028 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +000029 if ((*bp->bf_getbuffer)(self->b_base, view, flags) < 0)
30 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000031 count = view->len;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000032 /* apply constraints to the start/end */
33 if (self->b_offset > count)
34 offset = count;
35 else
36 offset = self->b_offset;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000037 view->buf = (char*)view->buf + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000038 if (self->b_size == Py_END_OF_BUFFER)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000039 view->len = count;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000040 else
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000041 view->len = self->b_size;
42 if (offset + view->len > count)
43 view->len = count - offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000044 }
45 return 1;
46}
47
48
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000049static int
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +000050buffer_getbuf(PyBufferObject *self, Py_buffer *view, int flags)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000051{
52 if (view == NULL) return 0;
53 if (!get_buf(self, view, flags))
54 return -1;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +000055 return PyBuffer_FillInfo(view, view->buf, view->len, self->b_readonly,
56 flags);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000057}
58
59
60static void
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +000061buffer_releasebuf(PyBufferObject *self, Py_buffer *view)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000062{
63 /* No-op if there is no self->b_base */
64 if (self->b_base != NULL) {
65 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
66 if (bp->bf_releasebuffer != NULL) {
67 (*bp->bf_releasebuffer)(self->b_base, view);
68 }
69 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000070}
71
Guido van Rossum2e19bd71998-10-07 14:36:10 +000072static PyObject *
Jeremy Hyltonc4140a12007-08-29 16:21:59 +000073buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset,
74 void *ptr, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000075{
76 PyBufferObject * b;
77
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000078 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +000079 PyErr_SetString(PyExc_ValueError,
80 "size must be zero or positive");
81 return NULL;
82 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +000083 if (offset < 0) {
84 PyErr_SetString(PyExc_ValueError,
85 "offset must be zero or positive");
86 return NULL;
87 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +000088
Guido van Rossum2e19bd71998-10-07 14:36:10 +000089 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +000090 if (b == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000091 return NULL;
92
93 Py_XINCREF(base);
94 b->b_base = base;
95 b->b_ptr = ptr;
96 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000097 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000099 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000100
101 return (PyObject *) b;
102}
103
104static PyObject *
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000105buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset,
106 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000107{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000108 if (offset < 0) {
109 PyErr_SetString(PyExc_ValueError,
110 "offset must be zero or positive");
111 return NULL;
112 }
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000113 if (PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base)) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000114 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000115 PyBufferObject *b = (PyBufferObject *)base;
116 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000117 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000118 if (base_size < 0)
119 base_size = 0;
120 if (size == Py_END_OF_BUFFER || size > base_size)
121 size = base_size;
122 }
123 offset += b->b_offset;
124 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000125 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000126 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000127}
128
129
130PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000131PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000132{
133 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
134
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000135 if (pb == NULL ||
136 pb->bf_getbuffer == NULL) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000137 PyErr_SetString(PyExc_TypeError, "buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000138 return NULL;
139 }
140
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000141 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000142}
143
144PyObject *
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000145PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset,
146 Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000147{
148 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
149
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000150 if (pb == NULL ||
151 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000152 PyErr_SetString(PyExc_TypeError, "buffer object expected");
153 return NULL;
154 }
155
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000156 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000157}
158
159PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000160PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000161{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000162 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000163}
164
165PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000166PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000167{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000168 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000169}
170
171PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000172PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000173{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000174 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000175 PyBufferObject * b;
176
Fred Drake4574f231999-08-04 13:08:19 +0000177 if (size < 0) {
178 PyErr_SetString(PyExc_ValueError,
179 "size must be zero or positive");
180 return NULL;
181 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000182 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000183 /* Inline PyObject_New */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000184 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000185 if (o == NULL)
Fred Drake4574f231999-08-04 13:08:19 +0000186 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000187 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000188
189 b->b_base = NULL;
190 b->b_ptr = (void *)(b + 1);
191 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000192 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000193 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000194 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195
Moshe Zadkacf703f02000-08-04 15:36:13 +0000196 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197}
198
199/* Methods */
200
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000201static PyObject *
202buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
203{
204 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000205 Py_ssize_t offset = 0;
206 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000207
Georg Brandl02c42872005-08-26 06:42:30 +0000208 if (!_PyArg_NoKeywords("buffer()", kw))
209 return NULL;
210
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000211 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000212 return NULL;
213 return PyBuffer_FromObject(ob, offset, size);
214}
215
216PyDoc_STRVAR(buffer_doc,
217"buffer(object [, offset[, size]])\n\
218\n\
219Create a new buffer object which references the given object.\n\
220The buffer will reference a slice of the target object from the\n\
221start of the object (or at the specified offset). The slice will\n\
222extend to the end of the target object (or with the specified size).");
223
224
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000225static void
Fred Drake79912472000-07-09 04:06:11 +0000226buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000227{
228 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000229 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000230}
231
232static int
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000233get_bufx(PyObject *obj, Py_buffer *view, int flags)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000234{
235 PyBufferProcs *bp;
236
237 if (PyBuffer_Check(obj)) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000238 if (!get_buf((PyBufferObject *)obj, view, flags)) {
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000239 PyErr_Clear();
240 return 0;
241 }
242 else
243 return 1;
244 }
245 bp = obj->ob_type->tp_as_buffer;
246 if (bp == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000247 bp->bf_getbuffer == NULL)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000248 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000249 if ((*bp->bf_getbuffer)(obj, view, PyBUF_SIMPLE) < 0)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000250 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000251 return 1;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000252}
253
254static PyObject *
255buffer_richcompare(PyObject *self, PyObject *other, int op)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000256{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000257 void *p1, *p2;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000258 Py_ssize_t len1, len2, min_len;
259 int cmp, ok;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000260 Py_buffer v1, v2;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000261
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000262 ok = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000263 if (!get_bufx(self, &v1, PyBUF_SIMPLE))
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000264 ok = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000265 if (!get_bufx(other, &v2, PyBUF_SIMPLE)) {
266 if (ok) PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000267 ok = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000268 }
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000269 if (!ok) {
270 /* If we can't get the buffers,
271 == and != are still defined
272 (and the objects are unequal) */
273 PyObject *result;
274 if (op == Py_EQ)
275 result = Py_False;
276 else if (op == Py_NE)
277 result = Py_True;
278 else
279 result = Py_NotImplemented;
280 Py_INCREF(result);
281 return result;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000282 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000283 len1 = v1.len;
284 len2 = v2.len;
285 p1 = v1.buf;
286 p2 = v2.buf;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000287 min_len = (len1 < len2) ? len1 : len2;
288 cmp = memcmp(p1, p2, min_len);
289 if (cmp == 0)
290 cmp = (len1 < len2) ? -1 :
291 (len1 > len2) ? 1 : 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000292 PyObject_ReleaseBuffer((PyObject *)self, &v1);
293 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000294 return Py_CmpToRich(op, cmp);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000295}
296
297static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000298buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000299{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000300 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000301
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000302 if (self->b_base == NULL)
303 return PyUnicode_FromFormat(
304 "<%s buffer ptr %p, size %zd at %p>",
305 status,
306 self->b_ptr,
307 self->b_size,
308 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000309 else
Walter Dörwald1ab83302007-05-18 17:15:44 +0000310 return PyUnicode_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000311 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000312 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000313 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000314 self->b_size,
315 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000316 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000317}
318
319static long
Fred Drake79912472000-07-09 04:06:11 +0000320buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000321{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000322 Py_buffer view;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000323 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000324 register unsigned char *p;
325 register long x;
326
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000327 if (self->b_hash != -1)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000328 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000329
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000330 if (!get_buf(self, &view, PyBUF_SIMPLE))
331 return -1;
332 if (!(self->b_readonly)) {
333 PyErr_SetString(PyExc_TypeError,
334 "writable buffers are not hashable");
335 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000336 return -1;
337 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000338
339 p = (unsigned char *) view.buf;
340 len = view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000341 x = *p << 7;
342 while (--len >= 0)
343 x = (1000003*x) ^ *p++;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000344 x ^= view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000345 if (x == -1)
346 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000347 self->b_hash = x;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000348 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000349 return x;
350}
351
352static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000353buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000354{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000355 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000356 PyObject *res;
357
358 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000359 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000360 res = PyString_FromStringAndSize((const char *)view.buf, view.len);
361 PyObject_ReleaseBuffer((PyObject *)self, &view);
362 return res;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000363}
364
365/* Sequence methods */
366
Martin v. Löwis18e16552006-02-15 17:27:45 +0000367static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000368buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000369{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000370 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000371
372 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000373 return -1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000374 PyObject_ReleaseBuffer((PyObject *)self, &view);
375 return view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000376}
377
378static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000379buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000380{
381 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000382 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000383 PyObject *ob;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000384 Py_buffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000385
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000386 if (pb == NULL ||
387 pb->bf_getbuffer == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000388 {
389 PyErr_BadArgument();
390 return NULL;
391 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000392
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000393 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000394 return NULL;
395
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000396 /* optimize special case */
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000397 /* XXX bad idea type-wise */
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000398 if (view.len == 0) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000399 PyObject_ReleaseBuffer((PyObject *)self, &view);
400 Py_INCREF(other);
401 return other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000402 }
403
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000404 if (PyObject_GetBuffer((PyObject *)other, &view2, PyBUF_SIMPLE) < 0) {
405 PyObject_ReleaseBuffer((PyObject *)self, &view);
406 return NULL;
407 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000408
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000409 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000410 ob = PyBytes_FromStringAndSize(NULL, view.len+view2.len);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000411 if (ob == NULL) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000412 PyObject_ReleaseBuffer((PyObject *)self, &view);
413 PyObject_ReleaseBuffer(other, &view2);
Neal Norwitz7c460742005-12-18 08:02:38 +0000414 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000415 }
416 p = PyBytes_AS_STRING(ob);
417 memcpy(p, view.buf, view.len);
418 memcpy(p + view.len, view2.buf, view2.len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000419
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000420 PyObject_ReleaseBuffer((PyObject *)self, &view);
421 PyObject_ReleaseBuffer(other, &view2);
422 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000423}
424
425static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000426buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000427{
428 PyObject *ob;
429 register char *p;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000430 Py_buffer view;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000431
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000432 if (count < 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000433 count = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000434 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000435 return NULL;
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000436 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000437 ob = PyBytes_FromStringAndSize(NULL, view.len * count);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000438 if (ob == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000439 return NULL;
440
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000441 p = PyBytes_AS_STRING(ob);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000442 while (count--) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000443 memcpy(p, view.buf, view.len);
444 p += view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000445 }
446
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000447 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000448 return ob;
449}
450
451static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000452buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000453{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000454 Py_buffer view;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000455 PyObject *ob;
456
457 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000458 return NULL;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000459 if (idx < 0 || idx >= view.len) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000460 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
461 return NULL;
462 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000463 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
464 PyObject_ReleaseBuffer((PyObject *)self, &view);
465 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000466}
467
468static PyObject *
Thomas Woutersed03b412007-08-28 21:37:11 +0000469buffer_subscript(PyBufferObject *self, PyObject *item)
470{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000471 Py_buffer view;
Thomas Woutersed03b412007-08-28 21:37:11 +0000472 PyObject *ob;
473
474 if (!get_buf(self, &view, PyBUF_SIMPLE))
475 return NULL;
476 if (PyIndex_Check(item)) {
477 Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
478
479 if (idx == -1 && PyErr_Occurred())
480 return NULL;
481 if (idx < 0)
482 idx += view.len;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000483 if (idx < 0 || idx >= view.len) {
Thomas Woutersed03b412007-08-28 21:37:11 +0000484 PyErr_SetString(PyExc_IndexError,
485 "buffer index out of range");
486 return NULL;
487 }
488 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
489 PyObject_ReleaseBuffer((PyObject *)self, &view);
490 return ob;
491 }
492 else if (PySlice_Check(item)) {
493 Py_ssize_t start, stop, step, slicelength, cur, i;
494
495 if (PySlice_GetIndicesEx((PySliceObject*)item, view.len,
496 &start, &stop, &step, &slicelength) < 0) {
497 PyObject_ReleaseBuffer((PyObject *)self, &view);
498 return NULL;
499 }
500
501 if (slicelength <= 0) {
502 PyObject_ReleaseBuffer((PyObject *)self, &view);
503 return PyBytes_FromStringAndSize("", 0);
504 }
505 else if (step == 1) {
506 ob = PyBytes_FromStringAndSize((char *)view.buf +
507 start, stop - start);
508 PyObject_ReleaseBuffer((PyObject *)self, &view);
509 return ob;
510 }
511 else {
512 char *source_buf = (char *)view.buf;
513 char *result_buf = (char *)PyMem_Malloc(slicelength);
514
515 if (result_buf == NULL)
516 return PyErr_NoMemory();
517
518 for (cur = start, i = 0; i < slicelength;
519 cur += step, i++) {
520 result_buf[i] = source_buf[cur];
521 }
522
523 ob = PyBytes_FromStringAndSize(result_buf,
524 slicelength);
525 PyMem_Free(result_buf);
526 PyObject_ReleaseBuffer((PyObject *)self, &view);
527 return ob;
528 }
529 }
530 else {
531 PyErr_SetString(PyExc_TypeError,
532 "sequence index must be integer");
533 return NULL;
534 }
535}
536
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000537static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000538buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000539{
540 PyBufferProcs *pb;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000541 Py_buffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000542
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000543 if (!get_buf(self, &view, PyBUF_SIMPLE))
544 return -1;
545
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000546 if (self->b_readonly || view.readonly) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000547 PyErr_SetString(PyExc_TypeError,
548 "buffer is read-only");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000549 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000550 return -1;
551 }
552
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000553 if (idx < 0 || idx >= view.len) {
554 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000555 PyErr_SetString(PyExc_IndexError,
556 "buffer assignment index out of range");
557 return -1;
558 }
559
560 pb = other ? other->ob_type->tp_as_buffer : NULL;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000561 if (pb == NULL ||
562 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000563 PyErr_BadArgument();
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000564 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000565 return -1;
566 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000567
568 if (PyObject_GetBuffer(other, &view2, PyBUF_SIMPLE) < 0) {
569 PyObject_ReleaseBuffer((PyObject *)self, &view);
570 return -1;
571 }
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000572 if (view.len != 1) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000573 PyObject_ReleaseBuffer((PyObject *)self, &view);
574 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000575 PyErr_SetString(PyExc_TypeError,
576 "right operand must be a single byte");
577 return -1;
578 }
579
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000580 ((char *)(view.buf))[idx] = *((char *)(view2.buf));
581 PyObject_ReleaseBuffer((PyObject *)self, &view);
582 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000583 return 0;
584}
585
586static int
Thomas Woutersed03b412007-08-28 21:37:11 +0000587buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
588{
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000589 Py_buffer v1;
Thomas Woutersed03b412007-08-28 21:37:11 +0000590
591 if (!get_buf(self, &v1, PyBUF_SIMPLE))
592 return -1;
593 if (self->b_readonly || v1.readonly) {
594 PyErr_SetString(PyExc_TypeError,
595 "buffer is read-only");
596 PyObject_ReleaseBuffer((PyObject *)self, &v1);
597 return -1;
598 }
599 if (PyIndex_Check(item)) {
600 Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
601 if (idx == -1 && PyErr_Occurred())
602 return -1;
603 if (idx < 0)
604 idx += v1.len;
605 PyObject_ReleaseBuffer((PyObject *)self, &v1);
606 return buffer_ass_item(self, idx, value);
607 }
608 else if (PySlice_Check(item)) {
609 Py_ssize_t start, stop, step, slicelength;
Travis E. Oliphant8ae62b62007-09-23 02:00:13 +0000610 Py_buffer v2;
Thomas Woutersed03b412007-08-28 21:37:11 +0000611 PyBufferProcs *pb;
612
613 if (PySlice_GetIndicesEx((PySliceObject *)item, v1.len,
614 &start, &stop, &step, &slicelength) < 0) {
615 PyObject_ReleaseBuffer((PyObject *)self, &v1);
616 return -1;
617 }
618
619 pb = value ? value->ob_type->tp_as_buffer : NULL;
620 if (pb == NULL ||
621 pb->bf_getbuffer == NULL) {
622 PyObject_ReleaseBuffer((PyObject *)self, &v1);
623 PyErr_BadArgument();
624 return -1;
625 }
626 if ((*pb->bf_getbuffer)(value, &v2, PyBUF_SIMPLE) < 0) {
627 PyObject_ReleaseBuffer((PyObject *)self, &v1);
628 return -1;
629 }
630
631 if (v2.len != slicelength) {
632 PyObject_ReleaseBuffer((PyObject *)self, &v1);
633 PyObject_ReleaseBuffer(value, &v2);
634 PyErr_SetString(PyExc_TypeError, "right operand"
635 " length must match slice length");
636 return -1;
637 }
638
639 if (slicelength == 0)
640 /* nothing to do */;
641 else if (step == 1)
642 memcpy((char *)v1.buf + start, v2.buf, slicelength);
643 else {
644 Py_ssize_t cur, i;
645
646 for (cur = start, i = 0; i < slicelength;
647 cur += step, i++) {
648 ((char *)v1.buf)[cur] = ((char *)v2.buf)[i];
649 }
650 }
651 PyObject_ReleaseBuffer((PyObject *)self, &v1);
652 PyObject_ReleaseBuffer(value, &v2);
653 return 0;
654 } else {
655 PyErr_SetString(PyExc_TypeError,
656 "buffer indices must be integers");
657 PyObject_ReleaseBuffer((PyObject *)self, &v1);
658 return -1;
659 }
660}
661
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000662/* Buffer methods */
663
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000664static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000665 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000666 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000667 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
668 (ssizeargfunc)buffer_item, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000669 0, /*sq_slice*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000670 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000671 0, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000672};
673
Thomas Woutersed03b412007-08-28 21:37:11 +0000674static PyMappingMethods buffer_as_mapping = {
675 (lenfunc)buffer_length,
676 (binaryfunc)buffer_subscript,
677 (objobjargproc)buffer_ass_subscript,
678};
679
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000680static PyBufferProcs buffer_as_buffer = {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000681 (getbufferproc)buffer_getbuf,
682 (releasebufferproc)buffer_releasebuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000683};
684
685PyTypeObject PyBuffer_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000686 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000687 "buffer",
688 sizeof(PyBufferObject),
689 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000690 (destructor)buffer_dealloc, /* tp_dealloc */
691 0, /* tp_print */
692 0, /* tp_getattr */
693 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000694 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000695 (reprfunc)buffer_repr, /* tp_repr */
696 0, /* tp_as_number */
697 &buffer_as_sequence, /* tp_as_sequence */
Thomas Woutersed03b412007-08-28 21:37:11 +0000698 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000699 (hashfunc)buffer_hash, /* tp_hash */
700 0, /* tp_call */
701 (reprfunc)buffer_str, /* tp_str */
702 PyObject_GenericGetAttr, /* tp_getattro */
703 0, /* tp_setattro */
704 &buffer_as_buffer, /* tp_as_buffer */
705 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000706 buffer_doc, /* tp_doc */
707 0, /* tp_traverse */
708 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000709 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000710 0, /* tp_weaklistoffset */
711 0, /* tp_iter */
712 0, /* tp_iternext */
713 0, /* tp_methods */
714 0, /* tp_members */
715 0, /* tp_getset */
716 0, /* tp_base */
717 0, /* tp_dict */
718 0, /* tp_descr_get */
719 0, /* tp_descr_set */
720 0, /* tp_dictoffset */
721 0, /* tp_init */
722 0, /* tp_alloc */
723 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000724};