blob: d697d26c32d45481dceed05798a3eb4476770bf4 [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 *
Thomas Woutersed03b412007-08-28 21:37:11 +0000468buffer_subscript(PyBufferObject *self, PyObject *item)
469{
470 PyBuffer view;
471 PyObject *ob;
472
473 if (!get_buf(self, &view, PyBUF_SIMPLE))
474 return NULL;
475 if (PyIndex_Check(item)) {
476 Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
477
478 if (idx == -1 && PyErr_Occurred())
479 return NULL;
480 if (idx < 0)
481 idx += view.len;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000482 if (idx < 0 || idx >= view.len) {
Thomas Woutersed03b412007-08-28 21:37:11 +0000483 PyErr_SetString(PyExc_IndexError,
484 "buffer index out of range");
485 return NULL;
486 }
487 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
488 PyObject_ReleaseBuffer((PyObject *)self, &view);
489 return ob;
490 }
491 else if (PySlice_Check(item)) {
492 Py_ssize_t start, stop, step, slicelength, cur, i;
493
494 if (PySlice_GetIndicesEx((PySliceObject*)item, view.len,
495 &start, &stop, &step, &slicelength) < 0) {
496 PyObject_ReleaseBuffer((PyObject *)self, &view);
497 return NULL;
498 }
499
500 if (slicelength <= 0) {
501 PyObject_ReleaseBuffer((PyObject *)self, &view);
502 return PyBytes_FromStringAndSize("", 0);
503 }
504 else if (step == 1) {
505 ob = PyBytes_FromStringAndSize((char *)view.buf +
506 start, stop - start);
507 PyObject_ReleaseBuffer((PyObject *)self, &view);
508 return ob;
509 }
510 else {
511 char *source_buf = (char *)view.buf;
512 char *result_buf = (char *)PyMem_Malloc(slicelength);
513
514 if (result_buf == NULL)
515 return PyErr_NoMemory();
516
517 for (cur = start, i = 0; i < slicelength;
518 cur += step, i++) {
519 result_buf[i] = source_buf[cur];
520 }
521
522 ob = PyBytes_FromStringAndSize(result_buf,
523 slicelength);
524 PyMem_Free(result_buf);
525 PyObject_ReleaseBuffer((PyObject *)self, &view);
526 return ob;
527 }
528 }
529 else {
530 PyErr_SetString(PyExc_TypeError,
531 "sequence index must be integer");
532 return NULL;
533 }
534}
535
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000536static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000537buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000538{
539 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000540 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000541
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000542 if (!get_buf(self, &view, PyBUF_SIMPLE))
543 return -1;
544
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000545 if (self->b_readonly || view.readonly) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000546 PyErr_SetString(PyExc_TypeError,
547 "buffer is read-only");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000548 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000549 return -1;
550 }
551
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000552 if (idx < 0 || idx >= view.len) {
553 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000554 PyErr_SetString(PyExc_IndexError,
555 "buffer assignment index out of range");
556 return -1;
557 }
558
559 pb = other ? other->ob_type->tp_as_buffer : NULL;
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000560 if (pb == NULL ||
561 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000562 PyErr_BadArgument();
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000563 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000564 return -1;
565 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000566
567 if (PyObject_GetBuffer(other, &view2, PyBUF_SIMPLE) < 0) {
568 PyObject_ReleaseBuffer((PyObject *)self, &view);
569 return -1;
570 }
Jeremy Hyltonc4140a12007-08-29 16:21:59 +0000571 if (view.len != 1) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000572 PyObject_ReleaseBuffer((PyObject *)self, &view);
573 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000574 PyErr_SetString(PyExc_TypeError,
575 "right operand must be a single byte");
576 return -1;
577 }
578
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000579 ((char *)(view.buf))[idx] = *((char *)(view2.buf));
580 PyObject_ReleaseBuffer((PyObject *)self, &view);
581 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000582 return 0;
583}
584
585static int
Thomas Woutersed03b412007-08-28 21:37:11 +0000586buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
587{
588 PyBuffer v1;
589
590 if (!get_buf(self, &v1, PyBUF_SIMPLE))
591 return -1;
592 if (self->b_readonly || v1.readonly) {
593 PyErr_SetString(PyExc_TypeError,
594 "buffer is read-only");
595 PyObject_ReleaseBuffer((PyObject *)self, &v1);
596 return -1;
597 }
598 if (PyIndex_Check(item)) {
599 Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
600 if (idx == -1 && PyErr_Occurred())
601 return -1;
602 if (idx < 0)
603 idx += v1.len;
604 PyObject_ReleaseBuffer((PyObject *)self, &v1);
605 return buffer_ass_item(self, idx, value);
606 }
607 else if (PySlice_Check(item)) {
608 Py_ssize_t start, stop, step, slicelength;
609 PyBuffer v2;
610 PyBufferProcs *pb;
611
612 if (PySlice_GetIndicesEx((PySliceObject *)item, v1.len,
613 &start, &stop, &step, &slicelength) < 0) {
614 PyObject_ReleaseBuffer((PyObject *)self, &v1);
615 return -1;
616 }
617
618 pb = value ? value->ob_type->tp_as_buffer : NULL;
619 if (pb == NULL ||
620 pb->bf_getbuffer == NULL) {
621 PyObject_ReleaseBuffer((PyObject *)self, &v1);
622 PyErr_BadArgument();
623 return -1;
624 }
625 if ((*pb->bf_getbuffer)(value, &v2, PyBUF_SIMPLE) < 0) {
626 PyObject_ReleaseBuffer((PyObject *)self, &v1);
627 return -1;
628 }
629
630 if (v2.len != slicelength) {
631 PyObject_ReleaseBuffer((PyObject *)self, &v1);
632 PyObject_ReleaseBuffer(value, &v2);
633 PyErr_SetString(PyExc_TypeError, "right operand"
634 " length must match slice length");
635 return -1;
636 }
637
638 if (slicelength == 0)
639 /* nothing to do */;
640 else if (step == 1)
641 memcpy((char *)v1.buf + start, v2.buf, slicelength);
642 else {
643 Py_ssize_t cur, i;
644
645 for (cur = start, i = 0; i < slicelength;
646 cur += step, i++) {
647 ((char *)v1.buf)[cur] = ((char *)v2.buf)[i];
648 }
649 }
650 PyObject_ReleaseBuffer((PyObject *)self, &v1);
651 PyObject_ReleaseBuffer(value, &v2);
652 return 0;
653 } else {
654 PyErr_SetString(PyExc_TypeError,
655 "buffer indices must be integers");
656 PyObject_ReleaseBuffer((PyObject *)self, &v1);
657 return -1;
658 }
659}
660
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000661/* Buffer methods */
662
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000663static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000664 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000665 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000666 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
667 (ssizeargfunc)buffer_item, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000668 0, /*sq_slice*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000669 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000670 0, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000671};
672
Thomas Woutersed03b412007-08-28 21:37:11 +0000673static PyMappingMethods buffer_as_mapping = {
674 (lenfunc)buffer_length,
675 (binaryfunc)buffer_subscript,
676 (objobjargproc)buffer_ass_subscript,
677};
678
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000679static PyBufferProcs buffer_as_buffer = {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000680 (getbufferproc)buffer_getbuf,
681 (releasebufferproc)buffer_releasebuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000682};
683
684PyTypeObject PyBuffer_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000685 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000686 "buffer",
687 sizeof(PyBufferObject),
688 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000689 (destructor)buffer_dealloc, /* tp_dealloc */
690 0, /* tp_print */
691 0, /* tp_getattr */
692 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000693 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000694 (reprfunc)buffer_repr, /* tp_repr */
695 0, /* tp_as_number */
696 &buffer_as_sequence, /* tp_as_sequence */
Thomas Woutersed03b412007-08-28 21:37:11 +0000697 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000698 (hashfunc)buffer_hash, /* tp_hash */
699 0, /* tp_call */
700 (reprfunc)buffer_str, /* tp_str */
701 PyObject_GenericGetAttr, /* tp_getattro */
702 0, /* tp_setattro */
703 &buffer_as_buffer, /* tp_as_buffer */
704 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000705 buffer_doc, /* tp_doc */
706 0, /* tp_traverse */
707 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000708 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000709 0, /* tp_weaklistoffset */
710 0, /* tp_iter */
711 0, /* tp_iternext */
712 0, /* tp_methods */
713 0, /* tp_members */
714 0, /* tp_getset */
715 0, /* tp_base */
716 0, /* tp_dict */
717 0, /* tp_descr_get */
718 0, /* tp_descr_set */
719 0, /* tp_dictoffset */
720 0, /* tp_init */
721 0, /* tp_alloc */
722 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000723};