blob: 674d2b562b6838c8a1e6dcdb11374520d3e3862e [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;
11 int b_size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000012 int 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
19get_buf(PyBufferObject *self, void **ptr, int *size)
20{
21 if (self->b_base == NULL) {
22 assert (ptr != NULL);
23 *ptr = self->b_ptr;
24 *size = self->b_size;
25 }
26 else {
27 int count, offset;
28 getreadbufferproc proc;
29 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
30 if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
31 PyErr_SetString(PyExc_TypeError,
32 "single-segment buffer object expected");
33 return 0;
34 }
35 if (self->b_readonly)
36 proc = bp->bf_getreadbuffer;
37 else
38 proc = (getreadbufferproc)bp->bf_getwritebuffer;
39 if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
40 return 0;
41 /* apply constraints to the start/end */
42 if (self->b_offset > count)
43 offset = count;
44 else
45 offset = self->b_offset;
Martin v. Löwis093c1002004-03-25 16:16:28 +000046 *(char **)ptr = *(char **)ptr + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000047 if (self->b_size == Py_END_OF_BUFFER)
48 *size = count;
49 else
50 *size = self->b_size;
51 if (offset + *size > count)
52 *size = count - offset;
53 }
54 return 1;
55}
56
57
Guido van Rossum2e19bd71998-10-07 14:36:10 +000058static PyObject *
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000059buffer_from_memory(PyObject *base, int size, int offset, void *ptr,
60 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000061{
62 PyBufferObject * b;
63
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000064 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +000065 PyErr_SetString(PyExc_ValueError,
66 "size must be zero or positive");
67 return NULL;
68 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +000069 if (offset < 0) {
70 PyErr_SetString(PyExc_ValueError,
71 "offset must be zero or positive");
72 return NULL;
73 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +000074
Guido van Rossum2e19bd71998-10-07 14:36:10 +000075 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
76 if ( b == NULL )
77 return NULL;
78
79 Py_XINCREF(base);
80 b->b_base = base;
81 b->b_ptr = ptr;
82 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000083 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000084 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000085 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000086
87 return (PyObject *) b;
88}
89
90static PyObject *
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000091buffer_from_object(PyObject *base, int size, int offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000092{
Neil Schemenauer927a57f2004-09-24 19:17:26 +000093 if (offset < 0) {
94 PyErr_SetString(PyExc_ValueError,
95 "offset must be zero or positive");
96 return NULL;
97 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000098 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +000099 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000100 PyBufferObject *b = (PyBufferObject *)base;
101 if (b->b_size != Py_END_OF_BUFFER) {
102 int base_size = b->b_size - offset;
103 if (base_size < 0)
104 base_size = 0;
105 if (size == Py_END_OF_BUFFER || size > base_size)
106 size = base_size;
107 }
108 offset += b->b_offset;
109 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000110 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000111 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000112}
113
114
115PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000116PyBuffer_FromObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000117{
118 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
119
120 if ( pb == NULL ||
121 pb->bf_getreadbuffer == NULL ||
122 pb->bf_getsegcount == NULL )
123 {
124 PyErr_SetString(PyExc_TypeError, "buffer object expected");
125 return NULL;
126 }
127
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000128 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000129}
130
131PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000132PyBuffer_FromReadWriteObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000133{
134 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
135
136 if ( pb == NULL ||
137 pb->bf_getwritebuffer == NULL ||
138 pb->bf_getsegcount == NULL )
139 {
140 PyErr_SetString(PyExc_TypeError, "buffer object expected");
141 return NULL;
142 }
143
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000144 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000145}
146
147PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000148PyBuffer_FromMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000149{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000150 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000151}
152
153PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000154PyBuffer_FromReadWriteMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000155{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000156 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000157}
158
159PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000160PyBuffer_New(int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000161{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000162 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000163 PyBufferObject * b;
164
Fred Drake4574f231999-08-04 13:08:19 +0000165 if (size < 0) {
166 PyErr_SetString(PyExc_ValueError,
167 "size must be zero or positive");
168 return NULL;
169 }
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000170 /* Inline PyObject_New */
Moshe Zadkacf703f02000-08-04 15:36:13 +0000171 o = PyObject_MALLOC(sizeof(*b) + size);
172 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000173 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000174 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000175
176 b->b_base = NULL;
177 b->b_ptr = (void *)(b + 1);
178 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000179 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000180 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000181 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000182
Moshe Zadkacf703f02000-08-04 15:36:13 +0000183 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000184}
185
186/* Methods */
187
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000188static PyObject *
189buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
190{
191 PyObject *ob;
192 int offset = 0;
193 int size = Py_END_OF_BUFFER;
194
195 if ( !PyArg_ParseTuple(args, "O|ii:buffer", &ob, &offset, &size) )
196 return NULL;
197 return PyBuffer_FromObject(ob, offset, size);
198}
199
200PyDoc_STRVAR(buffer_doc,
201"buffer(object [, offset[, size]])\n\
202\n\
203Create a new buffer object which references the given object.\n\
204The buffer will reference a slice of the target object from the\n\
205start of the object (or at the specified offset). The slice will\n\
206extend to the end of the target object (or with the specified size).");
207
208
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000209static void
Fred Drake79912472000-07-09 04:06:11 +0000210buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000211{
212 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000213 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000214}
215
216static int
Fred Drake79912472000-07-09 04:06:11 +0000217buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000218{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000219 void *p1, *p2;
220 int len_self, len_other, min_len, cmp;
221
222 if (!get_buf(self, &p1, &len_self))
223 return -1;
224 if (!get_buf(other, &p2, &len_other))
225 return -1;
226 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000227 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000228 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000229 if (cmp != 0)
230 return cmp;
231 }
232 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
233}
234
235static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000236buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000237{
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000238 char *status = self->b_readonly ? "read-only" : "read-write";
239
240 if ( self->b_base == NULL )
Barry Warsaw7ce36942001-08-24 18:34:26 +0000241 return PyString_FromFormat("<%s buffer ptr %p, size %d at %p>",
242 status,
243 self->b_ptr,
244 self->b_size,
245 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000246 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000247 return PyString_FromFormat(
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000248 "<%s buffer for %p, size %d, offset %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000249 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000250 self->b_base,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000251 self->b_size,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000252 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000253 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000254}
255
256static long
Fred Drake79912472000-07-09 04:06:11 +0000257buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000258{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000259 void *ptr;
260 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000261 register int len;
262 register unsigned char *p;
263 register long x;
264
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000265 if ( self->b_hash != -1 )
266 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000267
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000268 /* XXX potential bugs here, a readonly buffer does not imply that the
269 * underlying memory is immutable. b_readonly is a necessary but not
270 * sufficient condition for a buffer to be hashable. Perhaps it would
271 * be better to only allow hashing if the underlying object is known to
272 * be immutable (e.g. PyString_Check() is true). Another idea would
273 * be to call tp_hash on the underlying object and see if it raises
274 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000275 if ( !self->b_readonly )
276 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000277 PyErr_SetString(PyExc_TypeError,
278 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000279 return -1;
280 }
281
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000282 if (!get_buf(self, &ptr, &size))
283 return -1;
284 p = (unsigned char *) ptr;
285 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000286 x = *p << 7;
287 while (--len >= 0)
288 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000289 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000290 if (x == -1)
291 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000292 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000293 return x;
294}
295
296static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000297buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000298{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000299 void *ptr;
300 int size;
301 if (!get_buf(self, &ptr, &size))
302 return NULL;
303 return PyString_FromStringAndSize(ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000304}
305
306/* Sequence methods */
307
308static int
Fred Drake79912472000-07-09 04:06:11 +0000309buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000310{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000311 void *ptr;
312 int size;
313 if (!get_buf(self, &ptr, &size))
314 return -1;
315 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000316}
317
318static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000319buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000320{
321 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000322 void *ptr1, *ptr2;
323 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000324 PyObject *ob;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000325 int size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000326
327 if ( pb == NULL ||
328 pb->bf_getreadbuffer == NULL ||
329 pb->bf_getsegcount == NULL )
330 {
331 PyErr_BadArgument();
332 return NULL;
333 }
334 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
335 {
336 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000337 PyErr_SetString(PyExc_TypeError,
338 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000339 return NULL;
340 }
341
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000342 if (!get_buf(self, &ptr1, &size))
343 return NULL;
344
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000345 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000346 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000347 {
348 Py_INCREF(other);
349 return other;
350 }
351
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000352 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000353 return NULL;
354
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000355 ob = PyString_FromStringAndSize(NULL, size + count);
356 p = PyString_AS_STRING(ob);
357 memcpy(p, ptr1, size);
358 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000359
360 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000361 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000362
363 return ob;
364}
365
366static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000367buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000368{
369 PyObject *ob;
370 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000371 void *ptr;
372 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000373
374 if ( count < 0 )
375 count = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000376 if (!get_buf(self, &ptr, &size))
377 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000378 ob = PyString_FromStringAndSize(NULL, size * count);
379 if ( ob == NULL )
380 return NULL;
381
382 p = PyString_AS_STRING(ob);
383 while ( count-- )
384 {
385 memcpy(p, ptr, size);
386 p += size;
387 }
388
389 /* there is an extra byte in the string object, so this is safe */
390 *p = '\0';
391
392 return ob;
393}
394
395static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000396buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000397{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000398 void *ptr;
399 int size;
400 if (!get_buf(self, &ptr, &size))
401 return NULL;
402 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000403 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
404 return NULL;
405 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000406 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000407}
408
409static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000410buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000411{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000412 void *ptr;
413 int size;
414 if (!get_buf(self, &ptr, &size))
415 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000416 if ( left < 0 )
417 left = 0;
418 if ( right < 0 )
419 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000420 if ( right > size )
421 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000422 if ( right < left )
423 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000424 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000425 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000426}
427
428static int
Fred Drake79912472000-07-09 04:06:11 +0000429buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000430{
431 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000432 void *ptr1, *ptr2;
433 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000434 int count;
435
436 if ( self->b_readonly ) {
437 PyErr_SetString(PyExc_TypeError,
438 "buffer is read-only");
439 return -1;
440 }
441
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000442 if (!get_buf(self, &ptr1, &size))
443 return -1;
444
445 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000446 PyErr_SetString(PyExc_IndexError,
447 "buffer assignment index out of range");
448 return -1;
449 }
450
451 pb = other ? other->ob_type->tp_as_buffer : NULL;
452 if ( pb == NULL ||
453 pb->bf_getreadbuffer == NULL ||
454 pb->bf_getsegcount == NULL )
455 {
456 PyErr_BadArgument();
457 return -1;
458 }
459 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
460 {
461 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000462 PyErr_SetString(PyExc_TypeError,
463 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000464 return -1;
465 }
466
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000467 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000468 return -1;
469 if ( count != 1 ) {
470 PyErr_SetString(PyExc_TypeError,
471 "right operand must be a single byte");
472 return -1;
473 }
474
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000475 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000476 return 0;
477}
478
479static int
Fred Drake79912472000-07-09 04:06:11 +0000480buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000481{
482 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000483 void *ptr1, *ptr2;
484 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000485 int slice_len;
486 int count;
487
488 if ( self->b_readonly ) {
489 PyErr_SetString(PyExc_TypeError,
490 "buffer is read-only");
491 return -1;
492 }
493
494 pb = other ? other->ob_type->tp_as_buffer : NULL;
495 if ( pb == NULL ||
496 pb->bf_getreadbuffer == NULL ||
497 pb->bf_getsegcount == NULL )
498 {
499 PyErr_BadArgument();
500 return -1;
501 }
502 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
503 {
504 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000505 PyErr_SetString(PyExc_TypeError,
506 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000507 return -1;
508 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000509 if (!get_buf(self, &ptr1, &size))
510 return -1;
511 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000512 return -1;
513
514 if ( left < 0 )
515 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000516 else if ( left > size )
517 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000518 if ( right < left )
519 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000520 else if ( right > size )
521 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000522 slice_len = right - left;
523
524 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000525 PyErr_SetString(
526 PyExc_TypeError,
527 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000528 return -1;
529 }
530
531 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000532 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000533
534 return 0;
535}
536
537/* Buffer methods */
538
539static int
Fred Drake79912472000-07-09 04:06:11 +0000540buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000541{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000542 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000543 if ( idx != 0 ) {
544 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000545 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000546 return -1;
547 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000548 if (!get_buf(self, pp, &size))
549 return -1;
550 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000551}
552
553static int
Fred Drake79912472000-07-09 04:06:11 +0000554buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000555{
556 if ( self->b_readonly )
557 {
558 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
559 return -1;
560 }
561 return buffer_getreadbuf(self, idx, pp);
562}
563
564static int
Fred Drake79912472000-07-09 04:06:11 +0000565buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000566{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000567 void *ptr;
568 int size;
569 if (!get_buf(self, &ptr, &size))
570 return -1;
571 if (lenp)
572 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000573 return 1;
574}
575
Guido van Rossum1db70701998-10-08 02:18:52 +0000576static int
Fred Drake79912472000-07-09 04:06:11 +0000577buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000578{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000579 void *ptr;
580 int size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000581 if ( idx != 0 ) {
582 PyErr_SetString(PyExc_SystemError,
583 "accessing non-existent buffer segment");
584 return -1;
585 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000586 if (!get_buf(self, &ptr, &size))
587 return -1;
588 *pp = (const char *)ptr;
589 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000590}
591
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000592
593static PySequenceMethods buffer_as_sequence = {
594 (inquiry)buffer_length, /*sq_length*/
595 (binaryfunc)buffer_concat, /*sq_concat*/
596 (intargfunc)buffer_repeat, /*sq_repeat*/
597 (intargfunc)buffer_item, /*sq_item*/
598 (intintargfunc)buffer_slice, /*sq_slice*/
599 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
600 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
601};
602
603static PyBufferProcs buffer_as_buffer = {
604 (getreadbufferproc)buffer_getreadbuf,
605 (getwritebufferproc)buffer_getwritebuf,
606 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000607 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000608};
609
610PyTypeObject PyBuffer_Type = {
611 PyObject_HEAD_INIT(&PyType_Type)
612 0,
613 "buffer",
614 sizeof(PyBufferObject),
615 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000616 (destructor)buffer_dealloc, /* tp_dealloc */
617 0, /* tp_print */
618 0, /* tp_getattr */
619 0, /* tp_setattr */
620 (cmpfunc)buffer_compare, /* tp_compare */
621 (reprfunc)buffer_repr, /* tp_repr */
622 0, /* tp_as_number */
623 &buffer_as_sequence, /* tp_as_sequence */
624 0, /* tp_as_mapping */
625 (hashfunc)buffer_hash, /* tp_hash */
626 0, /* tp_call */
627 (reprfunc)buffer_str, /* tp_str */
628 PyObject_GenericGetAttr, /* tp_getattro */
629 0, /* tp_setattro */
630 &buffer_as_buffer, /* tp_as_buffer */
631 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000632 buffer_doc, /* tp_doc */
633 0, /* tp_traverse */
634 0, /* tp_clear */
635 0, /* tp_richcompare */
636 0, /* tp_weaklistoffset */
637 0, /* tp_iter */
638 0, /* tp_iternext */
639 0, /* tp_methods */
640 0, /* tp_members */
641 0, /* tp_getset */
642 0, /* tp_base */
643 0, /* tp_dict */
644 0, /* tp_descr_get */
645 0, /* tp_descr_set */
646 0, /* tp_dictoffset */
647 0, /* tp_init */
648 0, /* tp_alloc */
649 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000650};