blob: da8d9fc6a25767eb5962e0d48948fc93c16597d6 [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
Georg Brandl02c42872005-08-26 06:42:30 +0000195 if (!_PyArg_NoKeywords("buffer()", kw))
196 return NULL;
197
198 if (!PyArg_ParseTuple(args, "O|ii:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000199 return NULL;
200 return PyBuffer_FromObject(ob, offset, size);
201}
202
203PyDoc_STRVAR(buffer_doc,
204"buffer(object [, offset[, size]])\n\
205\n\
206Create a new buffer object which references the given object.\n\
207The buffer will reference a slice of the target object from the\n\
208start of the object (or at the specified offset). The slice will\n\
209extend to the end of the target object (or with the specified size).");
210
211
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000212static void
Fred Drake79912472000-07-09 04:06:11 +0000213buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000214{
215 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000216 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000217}
218
219static int
Fred Drake79912472000-07-09 04:06:11 +0000220buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000221{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000222 void *p1, *p2;
223 int len_self, len_other, min_len, cmp;
224
225 if (!get_buf(self, &p1, &len_self))
226 return -1;
227 if (!get_buf(other, &p2, &len_other))
228 return -1;
229 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000230 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000231 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000232 if (cmp != 0)
233 return cmp;
234 }
235 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
236}
237
238static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000239buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000240{
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000241 char *status = self->b_readonly ? "read-only" : "read-write";
242
243 if ( self->b_base == NULL )
Barry Warsaw7ce36942001-08-24 18:34:26 +0000244 return PyString_FromFormat("<%s buffer ptr %p, size %d at %p>",
245 status,
246 self->b_ptr,
247 self->b_size,
248 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000249 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000250 return PyString_FromFormat(
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000251 "<%s buffer for %p, size %d, offset %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000252 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000253 self->b_base,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000254 self->b_size,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000255 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000256 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000257}
258
259static long
Fred Drake79912472000-07-09 04:06:11 +0000260buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000261{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000262 void *ptr;
263 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000264 register int len;
265 register unsigned char *p;
266 register long x;
267
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000268 if ( self->b_hash != -1 )
269 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000270
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000271 /* XXX potential bugs here, a readonly buffer does not imply that the
272 * underlying memory is immutable. b_readonly is a necessary but not
273 * sufficient condition for a buffer to be hashable. Perhaps it would
274 * be better to only allow hashing if the underlying object is known to
275 * be immutable (e.g. PyString_Check() is true). Another idea would
276 * be to call tp_hash on the underlying object and see if it raises
277 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000278 if ( !self->b_readonly )
279 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000280 PyErr_SetString(PyExc_TypeError,
281 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000282 return -1;
283 }
284
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000285 if (!get_buf(self, &ptr, &size))
286 return -1;
287 p = (unsigned char *) ptr;
288 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000289 x = *p << 7;
290 while (--len >= 0)
291 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000292 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000293 if (x == -1)
294 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000295 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000296 return x;
297}
298
299static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000300buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000301{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000302 void *ptr;
303 int size;
304 if (!get_buf(self, &ptr, &size))
305 return NULL;
306 return PyString_FromStringAndSize(ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000307}
308
309/* Sequence methods */
310
311static int
Fred Drake79912472000-07-09 04:06:11 +0000312buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000313{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000314 void *ptr;
315 int size;
316 if (!get_buf(self, &ptr, &size))
317 return -1;
318 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000319}
320
321static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000322buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000323{
324 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000325 void *ptr1, *ptr2;
326 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000327 PyObject *ob;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000328 int size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000329
330 if ( pb == NULL ||
331 pb->bf_getreadbuffer == NULL ||
332 pb->bf_getsegcount == NULL )
333 {
334 PyErr_BadArgument();
335 return NULL;
336 }
337 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
338 {
339 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000340 PyErr_SetString(PyExc_TypeError,
341 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000342 return NULL;
343 }
344
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000345 if (!get_buf(self, &ptr1, &size))
346 return NULL;
347
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000348 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000349 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000350 {
351 Py_INCREF(other);
352 return other;
353 }
354
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000355 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000356 return NULL;
357
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000358 ob = PyString_FromStringAndSize(NULL, size + count);
359 p = PyString_AS_STRING(ob);
360 memcpy(p, ptr1, size);
361 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000362
363 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000364 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000365
366 return ob;
367}
368
369static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000370buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000371{
372 PyObject *ob;
373 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000374 void *ptr;
375 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000376
377 if ( count < 0 )
378 count = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000379 if (!get_buf(self, &ptr, &size))
380 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000381 ob = PyString_FromStringAndSize(NULL, size * count);
382 if ( ob == NULL )
383 return NULL;
384
385 p = PyString_AS_STRING(ob);
386 while ( count-- )
387 {
388 memcpy(p, ptr, size);
389 p += size;
390 }
391
392 /* there is an extra byte in the string object, so this is safe */
393 *p = '\0';
394
395 return ob;
396}
397
398static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000399buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000400{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000401 void *ptr;
402 int size;
403 if (!get_buf(self, &ptr, &size))
404 return NULL;
405 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000406 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
407 return NULL;
408 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000409 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000410}
411
412static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000413buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000414{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000415 void *ptr;
416 int size;
417 if (!get_buf(self, &ptr, &size))
418 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000419 if ( left < 0 )
420 left = 0;
421 if ( right < 0 )
422 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000423 if ( right > size )
424 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000425 if ( right < left )
426 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000427 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000428 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000429}
430
431static int
Fred Drake79912472000-07-09 04:06:11 +0000432buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000433{
434 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000435 void *ptr1, *ptr2;
436 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000437 int count;
438
439 if ( self->b_readonly ) {
440 PyErr_SetString(PyExc_TypeError,
441 "buffer is read-only");
442 return -1;
443 }
444
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000445 if (!get_buf(self, &ptr1, &size))
446 return -1;
447
448 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000449 PyErr_SetString(PyExc_IndexError,
450 "buffer assignment index out of range");
451 return -1;
452 }
453
454 pb = other ? other->ob_type->tp_as_buffer : NULL;
455 if ( pb == NULL ||
456 pb->bf_getreadbuffer == NULL ||
457 pb->bf_getsegcount == NULL )
458 {
459 PyErr_BadArgument();
460 return -1;
461 }
462 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
463 {
464 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000465 PyErr_SetString(PyExc_TypeError,
466 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000467 return -1;
468 }
469
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000470 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000471 return -1;
472 if ( count != 1 ) {
473 PyErr_SetString(PyExc_TypeError,
474 "right operand must be a single byte");
475 return -1;
476 }
477
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000478 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000479 return 0;
480}
481
482static int
Fred Drake79912472000-07-09 04:06:11 +0000483buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000484{
485 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000486 void *ptr1, *ptr2;
487 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000488 int slice_len;
489 int count;
490
491 if ( self->b_readonly ) {
492 PyErr_SetString(PyExc_TypeError,
493 "buffer is read-only");
494 return -1;
495 }
496
497 pb = other ? other->ob_type->tp_as_buffer : NULL;
498 if ( pb == NULL ||
499 pb->bf_getreadbuffer == NULL ||
500 pb->bf_getsegcount == NULL )
501 {
502 PyErr_BadArgument();
503 return -1;
504 }
505 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
506 {
507 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000508 PyErr_SetString(PyExc_TypeError,
509 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000510 return -1;
511 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000512 if (!get_buf(self, &ptr1, &size))
513 return -1;
514 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000515 return -1;
516
517 if ( left < 0 )
518 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000519 else if ( left > size )
520 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000521 if ( right < left )
522 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000523 else if ( right > size )
524 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000525 slice_len = right - left;
526
527 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000528 PyErr_SetString(
529 PyExc_TypeError,
530 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000531 return -1;
532 }
533
534 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000535 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000536
537 return 0;
538}
539
540/* Buffer methods */
541
542static int
Fred Drake79912472000-07-09 04:06:11 +0000543buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000544{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000545 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000546 if ( idx != 0 ) {
547 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000548 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000549 return -1;
550 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000551 if (!get_buf(self, pp, &size))
552 return -1;
553 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000554}
555
556static int
Fred Drake79912472000-07-09 04:06:11 +0000557buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000558{
559 if ( self->b_readonly )
560 {
561 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
562 return -1;
563 }
564 return buffer_getreadbuf(self, idx, pp);
565}
566
567static int
Fred Drake79912472000-07-09 04:06:11 +0000568buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000569{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000570 void *ptr;
571 int size;
572 if (!get_buf(self, &ptr, &size))
573 return -1;
574 if (lenp)
575 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000576 return 1;
577}
578
Guido van Rossum1db70701998-10-08 02:18:52 +0000579static int
Fred Drake79912472000-07-09 04:06:11 +0000580buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000581{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000582 void *ptr;
583 int size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000584 if ( idx != 0 ) {
585 PyErr_SetString(PyExc_SystemError,
586 "accessing non-existent buffer segment");
587 return -1;
588 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000589 if (!get_buf(self, &ptr, &size))
590 return -1;
591 *pp = (const char *)ptr;
592 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000593}
594
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000595
596static PySequenceMethods buffer_as_sequence = {
597 (inquiry)buffer_length, /*sq_length*/
598 (binaryfunc)buffer_concat, /*sq_concat*/
599 (intargfunc)buffer_repeat, /*sq_repeat*/
600 (intargfunc)buffer_item, /*sq_item*/
601 (intintargfunc)buffer_slice, /*sq_slice*/
602 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
603 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
604};
605
606static PyBufferProcs buffer_as_buffer = {
607 (getreadbufferproc)buffer_getreadbuf,
608 (getwritebufferproc)buffer_getwritebuf,
609 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000610 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000611};
612
613PyTypeObject PyBuffer_Type = {
614 PyObject_HEAD_INIT(&PyType_Type)
615 0,
616 "buffer",
617 sizeof(PyBufferObject),
618 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000619 (destructor)buffer_dealloc, /* tp_dealloc */
620 0, /* tp_print */
621 0, /* tp_getattr */
622 0, /* tp_setattr */
623 (cmpfunc)buffer_compare, /* tp_compare */
624 (reprfunc)buffer_repr, /* tp_repr */
625 0, /* tp_as_number */
626 &buffer_as_sequence, /* tp_as_sequence */
627 0, /* tp_as_mapping */
628 (hashfunc)buffer_hash, /* tp_hash */
629 0, /* tp_call */
630 (reprfunc)buffer_str, /* tp_str */
631 PyObject_GenericGetAttr, /* tp_getattro */
632 0, /* tp_setattro */
633 &buffer_as_buffer, /* tp_as_buffer */
634 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000635 buffer_doc, /* tp_doc */
636 0, /* tp_traverse */
637 0, /* tp_clear */
638 0, /* tp_richcompare */
639 0, /* tp_weaklistoffset */
640 0, /* tp_iter */
641 0, /* tp_iternext */
642 0, /* tp_methods */
643 0, /* tp_members */
644 0, /* tp_getset */
645 0, /* tp_base */
646 0, /* tp_dict */
647 0, /* tp_descr_get */
648 0, /* tp_descr_set */
649 0, /* tp_dictoffset */
650 0, /* tp_init */
651 0, /* tp_alloc */
652 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000653};