blob: 56748e671e68c0236d076b58536e69847fc526af [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);
Neal Norwitz7c460742005-12-18 08:02:38 +0000359 if ( ob == NULL )
360 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000361 p = PyString_AS_STRING(ob);
362 memcpy(p, ptr1, size);
363 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000364
365 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000366 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000367
368 return ob;
369}
370
371static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000372buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000373{
374 PyObject *ob;
375 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000376 void *ptr;
377 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000378
379 if ( count < 0 )
380 count = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000381 if (!get_buf(self, &ptr, &size))
382 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000383 ob = PyString_FromStringAndSize(NULL, size * count);
384 if ( ob == NULL )
385 return NULL;
386
387 p = PyString_AS_STRING(ob);
388 while ( count-- )
389 {
390 memcpy(p, ptr, size);
391 p += size;
392 }
393
394 /* there is an extra byte in the string object, so this is safe */
395 *p = '\0';
396
397 return ob;
398}
399
400static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000401buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000402{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000403 void *ptr;
404 int size;
405 if (!get_buf(self, &ptr, &size))
406 return NULL;
407 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000408 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
409 return NULL;
410 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000411 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000412}
413
414static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000415buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000416{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000417 void *ptr;
418 int size;
419 if (!get_buf(self, &ptr, &size))
420 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000421 if ( left < 0 )
422 left = 0;
423 if ( right < 0 )
424 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000425 if ( right > size )
426 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000427 if ( right < left )
428 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000429 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000430 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000431}
432
433static int
Fred Drake79912472000-07-09 04:06:11 +0000434buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000435{
436 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000437 void *ptr1, *ptr2;
438 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000439 int count;
440
441 if ( self->b_readonly ) {
442 PyErr_SetString(PyExc_TypeError,
443 "buffer is read-only");
444 return -1;
445 }
446
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000447 if (!get_buf(self, &ptr1, &size))
448 return -1;
449
450 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000451 PyErr_SetString(PyExc_IndexError,
452 "buffer assignment index out of range");
453 return -1;
454 }
455
456 pb = other ? other->ob_type->tp_as_buffer : NULL;
457 if ( pb == NULL ||
458 pb->bf_getreadbuffer == NULL ||
459 pb->bf_getsegcount == NULL )
460 {
461 PyErr_BadArgument();
462 return -1;
463 }
464 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
465 {
466 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000467 PyErr_SetString(PyExc_TypeError,
468 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000469 return -1;
470 }
471
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000472 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000473 return -1;
474 if ( count != 1 ) {
475 PyErr_SetString(PyExc_TypeError,
476 "right operand must be a single byte");
477 return -1;
478 }
479
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000480 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000481 return 0;
482}
483
484static int
Fred Drake79912472000-07-09 04:06:11 +0000485buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000486{
487 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000488 void *ptr1, *ptr2;
489 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000490 int slice_len;
491 int count;
492
493 if ( self->b_readonly ) {
494 PyErr_SetString(PyExc_TypeError,
495 "buffer is read-only");
496 return -1;
497 }
498
499 pb = other ? other->ob_type->tp_as_buffer : NULL;
500 if ( pb == NULL ||
501 pb->bf_getreadbuffer == NULL ||
502 pb->bf_getsegcount == NULL )
503 {
504 PyErr_BadArgument();
505 return -1;
506 }
507 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
508 {
509 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000510 PyErr_SetString(PyExc_TypeError,
511 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000512 return -1;
513 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000514 if (!get_buf(self, &ptr1, &size))
515 return -1;
516 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000517 return -1;
518
519 if ( left < 0 )
520 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000521 else if ( left > size )
522 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000523 if ( right < left )
524 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000525 else if ( right > size )
526 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000527 slice_len = right - left;
528
529 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000530 PyErr_SetString(
531 PyExc_TypeError,
532 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000533 return -1;
534 }
535
536 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000537 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000538
539 return 0;
540}
541
542/* Buffer methods */
543
544static int
Fred Drake79912472000-07-09 04:06:11 +0000545buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000546{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000547 int size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000548 if ( idx != 0 ) {
549 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000550 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000551 return -1;
552 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000553 if (!get_buf(self, pp, &size))
554 return -1;
555 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000556}
557
558static int
Fred Drake79912472000-07-09 04:06:11 +0000559buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000560{
561 if ( self->b_readonly )
562 {
563 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
564 return -1;
565 }
566 return buffer_getreadbuf(self, idx, pp);
567}
568
569static int
Fred Drake79912472000-07-09 04:06:11 +0000570buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000571{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000572 void *ptr;
573 int size;
574 if (!get_buf(self, &ptr, &size))
575 return -1;
576 if (lenp)
577 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000578 return 1;
579}
580
Guido van Rossum1db70701998-10-08 02:18:52 +0000581static int
Fred Drake79912472000-07-09 04:06:11 +0000582buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000583{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000584 void *ptr;
585 int size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000586 if ( idx != 0 ) {
587 PyErr_SetString(PyExc_SystemError,
588 "accessing non-existent buffer segment");
589 return -1;
590 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000591 if (!get_buf(self, &ptr, &size))
592 return -1;
593 *pp = (const char *)ptr;
594 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000595}
596
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000597
598static PySequenceMethods buffer_as_sequence = {
599 (inquiry)buffer_length, /*sq_length*/
600 (binaryfunc)buffer_concat, /*sq_concat*/
601 (intargfunc)buffer_repeat, /*sq_repeat*/
602 (intargfunc)buffer_item, /*sq_item*/
603 (intintargfunc)buffer_slice, /*sq_slice*/
604 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
605 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
606};
607
608static PyBufferProcs buffer_as_buffer = {
609 (getreadbufferproc)buffer_getreadbuf,
610 (getwritebufferproc)buffer_getwritebuf,
611 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000612 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000613};
614
615PyTypeObject PyBuffer_Type = {
616 PyObject_HEAD_INIT(&PyType_Type)
617 0,
618 "buffer",
619 sizeof(PyBufferObject),
620 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000621 (destructor)buffer_dealloc, /* tp_dealloc */
622 0, /* tp_print */
623 0, /* tp_getattr */
624 0, /* tp_setattr */
625 (cmpfunc)buffer_compare, /* tp_compare */
626 (reprfunc)buffer_repr, /* tp_repr */
627 0, /* tp_as_number */
628 &buffer_as_sequence, /* tp_as_sequence */
629 0, /* tp_as_mapping */
630 (hashfunc)buffer_hash, /* tp_hash */
631 0, /* tp_call */
632 (reprfunc)buffer_str, /* tp_str */
633 PyObject_GenericGetAttr, /* tp_getattro */
634 0, /* tp_setattro */
635 &buffer_as_buffer, /* tp_as_buffer */
636 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000637 buffer_doc, /* tp_doc */
638 0, /* tp_traverse */
639 0, /* tp_clear */
640 0, /* tp_richcompare */
641 0, /* tp_weaklistoffset */
642 0, /* tp_iter */
643 0, /* tp_iternext */
644 0, /* tp_methods */
645 0, /* tp_members */
646 0, /* tp_getset */
647 0, /* tp_base */
648 0, /* tp_dict */
649 0, /* tp_descr_get */
650 0, /* tp_descr_set */
651 0, /* tp_dictoffset */
652 0, /* tp_init */
653 0, /* tp_alloc */
654 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000655};