blob: d3464c17be6aa138558f9a10fa983093953aa8c9 [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. Oliphantb99f7622007-08-18 11:21:56 +000019get_buf(PyBufferObject *self, PyBuffer *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;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000024 }
25 else {
Martin v. Löwis18e16552006-02-15 17:27:45 +000026 Py_ssize_t count, offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000027 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +000028 if ((*bp->bf_getbuffer)(self->b_base, view, flags) < 0)
29 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000030 count = view->len;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000031 /* apply constraints to the start/end */
32 if (self->b_offset > count)
33 offset = count;
34 else
35 offset = self->b_offset;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000036 view->buf = (char*)view->buf + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000037 if (self->b_size == Py_END_OF_BUFFER)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000038 view->len = count;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000039 else
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000040 view->len = self->b_size;
41 if (offset + view->len > count)
42 view->len = count - offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000043 }
44 return 1;
45}
46
47
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000048static int
49buffer_getbuf(PyBufferObject *self, PyBuffer *view, int flags)
50{
51 if (view == NULL) return 0;
52 if (!get_buf(self, view, flags))
53 return -1;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +000054 return PyBuffer_FillInfo(view, view->buf, view->len, self->b_readonly,
55 flags);
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000056}
57
58
59static void
60buffer_releasebuf(PyBufferObject *self, PyBuffer *view)
61{
62 /* No-op if there is no self->b_base */
63 if (self->b_base != NULL) {
64 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
65 if (bp->bf_releasebuffer != NULL) {
66 (*bp->bf_releasebuffer)(self->b_base, view);
67 }
68 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000069}
70
Guido van Rossum2e19bd71998-10-07 14:36:10 +000071static PyObject *
Jeremy Hyltonc4140a12007-08-29 16:21:59 +000072buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset,
73 void *ptr, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000074{
75 PyBufferObject * b;
76
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000077 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +000078 PyErr_SetString(PyExc_ValueError,
79 "size must be zero or positive");
80 return NULL;
81 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +000082 if (offset < 0) {
83 PyErr_SetString(PyExc_ValueError,
84 "offset must be zero or positive");
85 return NULL;
86 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +000087
Guido van Rossum2e19bd71998-10-07 14:36:10 +000088 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +000089 if (b == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000090 return NULL;
91
92 Py_XINCREF(base);
93 b->b_base = base;
94 b->b_ptr = ptr;
95 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000096 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000097 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000099
100 return (PyObject *) b;
101}
102
103static PyObject *
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000104buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset,
105 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000106{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000107 if (offset < 0) {
108 PyErr_SetString(PyExc_ValueError,
109 "offset must be zero or positive");
110 return NULL;
111 }
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000112 if (PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base)) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000113 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000114 PyBufferObject *b = (PyBufferObject *)base;
115 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000116 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000117 if (base_size < 0)
118 base_size = 0;
119 if (size == Py_END_OF_BUFFER || size > base_size)
120 size = base_size;
121 }
122 offset += b->b_offset;
123 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000124 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000125 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000126}
127
128
129PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000130PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000131{
132 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
133
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000134 if (pb == NULL ||
135 pb->bf_getbuffer == NULL) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000136 PyErr_SetString(PyExc_TypeError, "buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000137 return NULL;
138 }
139
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000140 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000141}
142
143PyObject *
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000144PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset,
145 Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000146{
147 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
148
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000149 if (pb == NULL ||
150 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000151 PyErr_SetString(PyExc_TypeError, "buffer object expected");
152 return NULL;
153 }
154
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000155 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000156}
157
158PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000159PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000160{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000161 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000162}
163
164PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000165PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000166{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000167 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000168}
169
170PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000171PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000172{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000173 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000174 PyBufferObject * b;
175
Fred Drake4574f231999-08-04 13:08:19 +0000176 if (size < 0) {
177 PyErr_SetString(PyExc_ValueError,
178 "size must be zero or positive");
179 return NULL;
180 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000181 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000182 /* Inline PyObject_New */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000183 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000184 if (o == NULL)
Fred Drake4574f231999-08-04 13:08:19 +0000185 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000186 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000187
188 b->b_base = NULL;
189 b->b_ptr = (void *)(b + 1);
190 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000191 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000192 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000193 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000194
Moshe Zadkacf703f02000-08-04 15:36:13 +0000195 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000196}
197
198/* Methods */
199
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000200static PyObject *
201buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
202{
203 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000204 Py_ssize_t offset = 0;
205 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000206
Georg Brandl02c42872005-08-26 06:42:30 +0000207 if (!_PyArg_NoKeywords("buffer()", kw))
208 return NULL;
209
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000210 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000211 return NULL;
212 return PyBuffer_FromObject(ob, offset, size);
213}
214
215PyDoc_STRVAR(buffer_doc,
216"buffer(object [, offset[, size]])\n\
217\n\
218Create a new buffer object which references the given object.\n\
219The buffer will reference a slice of the target object from the\n\
220start of the object (or at the specified offset). The slice will\n\
221extend to the end of the target object (or with the specified size).");
222
223
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000224static void
Fred Drake79912472000-07-09 04:06:11 +0000225buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000226{
227 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000228 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000229}
230
231static int
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000232get_bufx(PyObject *obj, PyBuffer *view, int flags)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000233{
234 PyBufferProcs *bp;
235
236 if (PyBuffer_Check(obj)) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000237 if (!get_buf((PyBufferObject *)obj, view, flags)) {
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000238 PyErr_Clear();
239 return 0;
240 }
241 else
242 return 1;
243 }
244 bp = obj->ob_type->tp_as_buffer;
245 if (bp == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000246 bp->bf_getbuffer == NULL)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000247 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000248 if ((*bp->bf_getbuffer)(obj, view, PyBUF_SIMPLE) < 0)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000249 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000250 return 1;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000251}
252
253static PyObject *
254buffer_richcompare(PyObject *self, PyObject *other, int op)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000255{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000256 void *p1, *p2;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000257 Py_ssize_t len1, len2, min_len;
258 int cmp, ok;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000259 PyBuffer v1, v2;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000260
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000261 ok = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000262 if (!get_bufx(self, &v1, PyBUF_SIMPLE))
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000263 ok = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000264 if (!get_bufx(other, &v2, PyBUF_SIMPLE)) {
265 if (ok) PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000266 ok = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000267 }
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000268 if (!ok) {
269 /* If we can't get the buffers,
270 == and != are still defined
271 (and the objects are unequal) */
272 PyObject *result;
273 if (op == Py_EQ)
274 result = Py_False;
275 else if (op == Py_NE)
276 result = Py_True;
277 else
278 result = Py_NotImplemented;
279 Py_INCREF(result);
280 return result;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000281 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000282 len1 = v1.len;
283 len2 = v2.len;
284 p1 = v1.buf;
285 p2 = v2.buf;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000286 min_len = (len1 < len2) ? len1 : len2;
287 cmp = memcmp(p1, p2, min_len);
288 if (cmp == 0)
289 cmp = (len1 < len2) ? -1 :
290 (len1 > len2) ? 1 : 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000291 PyObject_ReleaseBuffer((PyObject *)self, &v1);
292 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000293 return Py_CmpToRich(op, cmp);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000294}
295
296static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000297buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000298{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000299 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000300
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000301 if (self->b_base == NULL)
302 return PyUnicode_FromFormat(
303 "<%s buffer ptr %p, size %zd at %p>",
304 status,
305 self->b_ptr,
306 self->b_size,
307 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000308 else
Walter Dörwald1ab83302007-05-18 17:15:44 +0000309 return PyUnicode_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000310 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000311 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000312 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000313 self->b_size,
314 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000315 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000316}
317
318static long
Fred Drake79912472000-07-09 04:06:11 +0000319buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000320{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000321 PyBuffer view;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000322 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000323 register unsigned char *p;
324 register long x;
325
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000326 if (self->b_hash != -1)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000327 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000328
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000329 if (!get_buf(self, &view, PyBUF_SIMPLE))
330 return -1;
331 if (!(self->b_readonly)) {
332 PyErr_SetString(PyExc_TypeError,
333 "writable buffers are not hashable");
334 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000335 return -1;
336 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000337
338 p = (unsigned char *) view.buf;
339 len = view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000340 x = *p << 7;
341 while (--len >= 0)
342 x = (1000003*x) ^ *p++;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000343 x ^= view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000344 if (x == -1)
345 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000346 self->b_hash = x;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000347 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000348 return x;
349}
350
351static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000352buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000353{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000354 PyBuffer view;
355 PyObject *res;
356
357 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000358 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000359 res = PyString_FromStringAndSize((const char *)view.buf, view.len);
360 PyObject_ReleaseBuffer((PyObject *)self, &view);
361 return res;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000362}
363
364/* Sequence methods */
365
Martin v. Löwis18e16552006-02-15 17:27:45 +0000366static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000367buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000368{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000369 PyBuffer view;
370
371 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000372 return -1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000373 PyObject_ReleaseBuffer((PyObject *)self, &view);
374 return view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000375}
376
377static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000378buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000379{
380 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000381 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000382 PyObject *ob;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000383 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000384
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000385 if (pb == NULL ||
386 pb->bf_getbuffer == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000387 {
388 PyErr_BadArgument();
389 return NULL;
390 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000391
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000392 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000393 return NULL;
394
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000395 /* optimize special case */
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000396 /* XXX bad idea type-wise */
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000397 if (view.len == 0) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000398 PyObject_ReleaseBuffer((PyObject *)self, &view);
399 Py_INCREF(other);
400 return other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000401 }
402
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000403 if (PyObject_GetBuffer((PyObject *)other, &view2, PyBUF_SIMPLE) < 0) {
404 PyObject_ReleaseBuffer((PyObject *)self, &view);
405 return NULL;
406 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000407
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000408 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000409 ob = PyBytes_FromStringAndSize(NULL, view.len+view2.len);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000410 if (ob == NULL) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000411 PyObject_ReleaseBuffer((PyObject *)self, &view);
412 PyObject_ReleaseBuffer(other, &view2);
Neal Norwitz7c460742005-12-18 08:02:38 +0000413 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000414 }
415 p = PyBytes_AS_STRING(ob);
416 memcpy(p, view.buf, view.len);
417 memcpy(p + view.len, view2.buf, view2.len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000418
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000419 PyObject_ReleaseBuffer((PyObject *)self, &view);
420 PyObject_ReleaseBuffer(other, &view2);
421 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000422}
423
424static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000425buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000426{
427 PyObject *ob;
428 register char *p;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000429 PyBuffer view;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000430
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000431 if (count < 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000432 count = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000433 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000434 return NULL;
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000435 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000436 ob = PyBytes_FromStringAndSize(NULL, view.len * count);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000437 if (ob == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000438 return NULL;
439
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000440 p = PyBytes_AS_STRING(ob);
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000441 while (count--) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000442 memcpy(p, view.buf, view.len);
443 p += view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000444 }
445
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000446 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000447 return ob;
448}
449
450static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000451buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000452{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000453 PyBuffer view;
454 PyObject *ob;
455
456 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000457 return NULL;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000458 if (idx < 0 || idx >= view.len) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000459 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
460 return NULL;
461 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000462 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
463 PyObject_ReleaseBuffer((PyObject *)self, &view);
464 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000465}
466
467static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000468buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000469{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000470 PyObject *ob;
471 PyBuffer view;
472 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000473 return NULL;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000474 if (left < 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000475 left = 0;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000476 if (right < 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000477 right = 0;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000478 if (right > view.len)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000479 right = view.len;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000480 if (right < left)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000481 right = left;
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000482 /* XXX(nnorwitz): is it possible to access unitialized memory? */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000483 ob = PyBytes_FromStringAndSize((char *)view.buf + left,
484 right - left);
485 PyObject_ReleaseBuffer((PyObject *)self, &view);
486 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000487}
488
Thomas Woutersed03b412007-08-28 21:37:11 +0000489static PyObject *
490buffer_subscript(PyBufferObject *self, PyObject *item)
491{
492 PyBuffer view;
493 PyObject *ob;
494
495 if (!get_buf(self, &view, PyBUF_SIMPLE))
496 return NULL;
497 if (PyIndex_Check(item)) {
498 Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
499
500 if (idx == -1 && PyErr_Occurred())
501 return NULL;
502 if (idx < 0)
503 idx += view.len;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000504 if (idx < 0 || idx >= view.len) {
Thomas Woutersed03b412007-08-28 21:37:11 +0000505 PyErr_SetString(PyExc_IndexError,
506 "buffer index out of range");
507 return NULL;
508 }
509 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
510 PyObject_ReleaseBuffer((PyObject *)self, &view);
511 return ob;
512 }
513 else if (PySlice_Check(item)) {
514 Py_ssize_t start, stop, step, slicelength, cur, i;
515
516 if (PySlice_GetIndicesEx((PySliceObject*)item, view.len,
517 &start, &stop, &step, &slicelength) < 0) {
518 PyObject_ReleaseBuffer((PyObject *)self, &view);
519 return NULL;
520 }
521
522 if (slicelength <= 0) {
523 PyObject_ReleaseBuffer((PyObject *)self, &view);
524 return PyBytes_FromStringAndSize("", 0);
525 }
526 else if (step == 1) {
527 ob = PyBytes_FromStringAndSize((char *)view.buf +
528 start, stop - start);
529 PyObject_ReleaseBuffer((PyObject *)self, &view);
530 return ob;
531 }
532 else {
533 char *source_buf = (char *)view.buf;
534 char *result_buf = (char *)PyMem_Malloc(slicelength);
535
536 if (result_buf == NULL)
537 return PyErr_NoMemory();
538
539 for (cur = start, i = 0; i < slicelength;
540 cur += step, i++) {
541 result_buf[i] = source_buf[cur];
542 }
543
544 ob = PyBytes_FromStringAndSize(result_buf,
545 slicelength);
546 PyMem_Free(result_buf);
547 PyObject_ReleaseBuffer((PyObject *)self, &view);
548 return ob;
549 }
550 }
551 else {
552 PyErr_SetString(PyExc_TypeError,
553 "sequence index must be integer");
554 return NULL;
555 }
556}
557
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000558static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000559buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000560{
561 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000562 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000563
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000564 if (!get_buf(self, &view, PyBUF_SIMPLE))
565 return -1;
566
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000567 if (self->b_readonly || view.readonly) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000568 PyErr_SetString(PyExc_TypeError,
569 "buffer is read-only");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000570 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000571 return -1;
572 }
573
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000574 if (idx < 0 || idx >= view.len) {
575 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000576 PyErr_SetString(PyExc_IndexError,
577 "buffer assignment index out of range");
578 return -1;
579 }
580
581 pb = other ? other->ob_type->tp_as_buffer : NULL;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000582 if (pb == NULL ||
583 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000584 PyErr_BadArgument();
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000585 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000586 return -1;
587 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000588
589 if (PyObject_GetBuffer(other, &view2, PyBUF_SIMPLE) < 0) {
590 PyObject_ReleaseBuffer((PyObject *)self, &view);
591 return -1;
592 }
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000593 if (view.len != 1) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000594 PyObject_ReleaseBuffer((PyObject *)self, &view);
595 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000596 PyErr_SetString(PyExc_TypeError,
597 "right operand must be a single byte");
598 return -1;
599 }
600
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000601 ((char *)(view.buf))[idx] = *((char *)(view2.buf));
602 PyObject_ReleaseBuffer((PyObject *)self, &view);
603 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000604 return 0;
605}
606
607static int
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000608buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right,
609 PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000610{
611 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000612 PyBuffer v1, v2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000613 Py_ssize_t slice_len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000614
615 pb = other ? other->ob_type->tp_as_buffer : NULL;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000616 if (pb == NULL ||
617 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000618 PyErr_BadArgument();
619 return -1;
620 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000621 if (!get_buf(self, &v1, PyBUF_SIMPLE))
622 return -1;
623
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000624 if (self->b_readonly || v1.readonly) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000625 PyErr_SetString(PyExc_TypeError,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000626 "buffer is read-only");
627 PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000628 return -1;
629 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000630
631 if ((*pb->bf_getbuffer)(other, &v2, PyBUF_SIMPLE) < 0) {
632 PyObject_ReleaseBuffer((PyObject *)self, &v1);
633 return -1;
634 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000635
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000636 if (left < 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000637 left = 0;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000638 else if (left > v1.len)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000639 left = v1.len;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000640 if (right < left)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000641 right = left;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000642 else if (right > v1.len)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000643 right = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000644 slice_len = right - left;
645
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000646 if (v2.len != slice_len) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000647 PyErr_SetString(
648 PyExc_TypeError,
649 "right operand length must match slice length");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000650 PyObject_ReleaseBuffer((PyObject *)self, &v1);
651 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000652 return -1;
653 }
654
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000655 if (slice_len)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000656 memcpy((char *)v1.buf + left, v2.buf, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000657
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000658 PyObject_ReleaseBuffer((PyObject *)self, &v1);
659 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000660 return 0;
661}
662
Thomas Woutersed03b412007-08-28 21:37:11 +0000663static int
664buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
665{
666 PyBuffer v1;
667
668 if (!get_buf(self, &v1, PyBUF_SIMPLE))
669 return -1;
670 if (self->b_readonly || v1.readonly) {
671 PyErr_SetString(PyExc_TypeError,
672 "buffer is read-only");
673 PyObject_ReleaseBuffer((PyObject *)self, &v1);
674 return -1;
675 }
676 if (PyIndex_Check(item)) {
677 Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
678 if (idx == -1 && PyErr_Occurred())
679 return -1;
680 if (idx < 0)
681 idx += v1.len;
682 PyObject_ReleaseBuffer((PyObject *)self, &v1);
683 return buffer_ass_item(self, idx, value);
684 }
685 else if (PySlice_Check(item)) {
686 Py_ssize_t start, stop, step, slicelength;
687 PyBuffer v2;
688 PyBufferProcs *pb;
689
690 if (PySlice_GetIndicesEx((PySliceObject *)item, v1.len,
691 &start, &stop, &step, &slicelength) < 0) {
692 PyObject_ReleaseBuffer((PyObject *)self, &v1);
693 return -1;
694 }
695
696 pb = value ? value->ob_type->tp_as_buffer : NULL;
697 if (pb == NULL ||
698 pb->bf_getbuffer == NULL) {
699 PyObject_ReleaseBuffer((PyObject *)self, &v1);
700 PyErr_BadArgument();
701 return -1;
702 }
703 if ((*pb->bf_getbuffer)(value, &v2, PyBUF_SIMPLE) < 0) {
704 PyObject_ReleaseBuffer((PyObject *)self, &v1);
705 return -1;
706 }
707
708 if (v2.len != slicelength) {
709 PyObject_ReleaseBuffer((PyObject *)self, &v1);
710 PyObject_ReleaseBuffer(value, &v2);
711 PyErr_SetString(PyExc_TypeError, "right operand"
712 " length must match slice length");
713 return -1;
714 }
715
716 if (slicelength == 0)
717 /* nothing to do */;
718 else if (step == 1)
719 memcpy((char *)v1.buf + start, v2.buf, slicelength);
720 else {
721 Py_ssize_t cur, i;
722
723 for (cur = start, i = 0; i < slicelength;
724 cur += step, i++) {
725 ((char *)v1.buf)[cur] = ((char *)v2.buf)[i];
726 }
727 }
728 PyObject_ReleaseBuffer((PyObject *)self, &v1);
729 PyObject_ReleaseBuffer(value, &v2);
730 return 0;
731 } else {
732 PyErr_SetString(PyExc_TypeError,
733 "buffer indices must be integers");
734 PyObject_ReleaseBuffer((PyObject *)self, &v1);
735 return -1;
736 }
737}
738
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000739/* Buffer methods */
740
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000741static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000742 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000743 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000744 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
745 (ssizeargfunc)buffer_item, /*sq_item*/
746 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
747 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
748 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000749};
750
Thomas Woutersed03b412007-08-28 21:37:11 +0000751static PyMappingMethods buffer_as_mapping = {
752 (lenfunc)buffer_length,
753 (binaryfunc)buffer_subscript,
754 (objobjargproc)buffer_ass_subscript,
755};
756
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000757static PyBufferProcs buffer_as_buffer = {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000758 (getbufferproc)buffer_getbuf,
759 (releasebufferproc)buffer_releasebuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000760};
761
762PyTypeObject PyBuffer_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000763 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000764 "buffer",
765 sizeof(PyBufferObject),
766 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000767 (destructor)buffer_dealloc, /* tp_dealloc */
768 0, /* tp_print */
769 0, /* tp_getattr */
770 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000771 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000772 (reprfunc)buffer_repr, /* tp_repr */
773 0, /* tp_as_number */
774 &buffer_as_sequence, /* tp_as_sequence */
Thomas Woutersed03b412007-08-28 21:37:11 +0000775 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000776 (hashfunc)buffer_hash, /* tp_hash */
777 0, /* tp_call */
778 (reprfunc)buffer_str, /* tp_str */
779 PyObject_GenericGetAttr, /* tp_getattro */
780 0, /* tp_setattro */
781 &buffer_as_buffer, /* tp_as_buffer */
782 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000783 buffer_doc, /* tp_doc */
784 0, /* tp_traverse */
785 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000786 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000787 0, /* tp_weaklistoffset */
788 0, /* tp_iter */
789 0, /* tp_iternext */
790 0, /* tp_methods */
791 0, /* tp_members */
792 0, /* tp_getset */
793 0, /* tp_base */
794 0, /* tp_dict */
795 0, /* tp_descr_get */
796 0, /* tp_descr_set */
797 0, /* tp_dictoffset */
798 0, /* tp_init */
799 0, /* tp_alloc */
800 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000801};