blob: 031c000b8ea9cd6bfebf4a3a4baa19822d033f83 [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;
12 int b_readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000013 long b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000014} PyBufferObject;
15
16
17static PyObject *
Fred Drake79912472000-07-09 04:06:11 +000018_PyBuffer_FromMemory(PyObject *base, void *ptr, int size, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000019{
20 PyBufferObject * b;
21
Guido van Rossum49ded3e1999-03-19 19:04:25 +000022 if ( size < 0 ) {
23 PyErr_SetString(PyExc_ValueError,
24 "size must be zero or positive");
25 return NULL;
26 }
27
Guido van Rossum2e19bd71998-10-07 14:36:10 +000028 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
29 if ( b == NULL )
30 return NULL;
31
32 Py_XINCREF(base);
33 b->b_base = base;
34 b->b_ptr = ptr;
35 b->b_size = size;
36 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000037 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000038
39 return (PyObject *) b;
40}
41
42static PyObject *
Fred Drake79912472000-07-09 04:06:11 +000043_PyBuffer_FromObject(PyObject *base, int offset, int size,
44 getreadbufferproc proc, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000045{
46 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
47 void *p;
48 int count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000049
Guido van Rossum49ded3e1999-03-19 19:04:25 +000050 if ( offset < 0 ) {
51 PyErr_SetString(PyExc_ValueError,
52 "offset must be zero or positive");
53 return NULL;
54 }
55
Guido van Rossum2e19bd71998-10-07 14:36:10 +000056 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
57 {
Guido van Rossumcd037e71999-03-24 19:05:31 +000058 PyErr_SetString(PyExc_TypeError,
59 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +000060 return NULL;
61 }
62 if ( (count = (*proc)(base, 0, &p)) < 0 )
63 return NULL;
64
65 /* apply constraints to the start/end */
Guido van Rossum49ded3e1999-03-19 19:04:25 +000066 if ( size == Py_END_OF_BUFFER || size < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +000067 size = count;
68 if ( offset > count )
69 offset = count;
70 if ( offset + size > count )
71 size = count - offset;
Thomas Hellerfdc1bd32001-10-19 13:49:35 +000072
73 /* if the base object is another buffer, then "deref" it,
74 * except if the base of the other buffer is NULL
75 */
76 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) )
Guido van Rossum2e19bd71998-10-07 14:36:10 +000077 base = ((PyBufferObject *)base)->b_base;
Thomas Hellerfdc1bd32001-10-19 13:49:35 +000078
Guido van Rossum2e19bd71998-10-07 14:36:10 +000079 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
80}
81
82
83PyObject *
Fred Drake79912472000-07-09 04:06:11 +000084PyBuffer_FromObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000085{
86 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
87
88 if ( pb == NULL ||
89 pb->bf_getreadbuffer == NULL ||
90 pb->bf_getsegcount == NULL )
91 {
92 PyErr_SetString(PyExc_TypeError, "buffer object expected");
93 return NULL;
94 }
95
Guido van Rossumcd037e71999-03-24 19:05:31 +000096 return _PyBuffer_FromObject(base, offset, size,
97 pb->bf_getreadbuffer, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098}
99
100PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000101PyBuffer_FromReadWriteObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000102{
103 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
104
105 if ( pb == NULL ||
106 pb->bf_getwritebuffer == NULL ||
107 pb->bf_getsegcount == NULL )
108 {
109 PyErr_SetString(PyExc_TypeError, "buffer object expected");
110 return NULL;
111 }
112
Guido van Rossumcd037e71999-03-24 19:05:31 +0000113 return _PyBuffer_FromObject(base, offset, size,
114 (getreadbufferproc)pb->bf_getwritebuffer,
115 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000116}
117
118PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000119PyBuffer_FromMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000120{
121 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
122}
123
124PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000125PyBuffer_FromReadWriteMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000126{
127 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
128}
129
130PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000131PyBuffer_New(int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000132{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000133 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000134 PyBufferObject * b;
135
Fred Drake4574f231999-08-04 13:08:19 +0000136 if (size < 0) {
137 PyErr_SetString(PyExc_ValueError,
138 "size must be zero or positive");
139 return NULL;
140 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000141 /* PyObject_New is inlined */
Moshe Zadkacf703f02000-08-04 15:36:13 +0000142 o = PyObject_MALLOC(sizeof(*b) + size);
143 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000144 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000145 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000146
147 b->b_base = NULL;
148 b->b_ptr = (void *)(b + 1);
149 b->b_size = size;
150 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000151 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000152
Moshe Zadkacf703f02000-08-04 15:36:13 +0000153 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000154}
155
156/* Methods */
157
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000158static PyObject *
159buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
160{
161 PyObject *ob;
162 int offset = 0;
163 int size = Py_END_OF_BUFFER;
164
165 if ( !PyArg_ParseTuple(args, "O|ii:buffer", &ob, &offset, &size) )
166 return NULL;
167 return PyBuffer_FromObject(ob, offset, size);
168}
169
170PyDoc_STRVAR(buffer_doc,
171"buffer(object [, offset[, size]])\n\
172\n\
173Create a new buffer object which references the given object.\n\
174The buffer will reference a slice of the target object from the\n\
175start of the object (or at the specified offset). The slice will\n\
176extend to the end of the target object (or with the specified size).");
177
178
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000179static void
Fred Drake79912472000-07-09 04:06:11 +0000180buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000181{
182 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000183 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000184}
185
186static int
Fred Drake79912472000-07-09 04:06:11 +0000187buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000188{
189 int len_self = self->b_size;
190 int len_other = other->b_size;
191 int min_len = (len_self < len_other) ? len_self : len_other;
192 int cmp;
193 if (min_len > 0) {
194 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
195 if (cmp != 0)
196 return cmp;
197 }
198 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
199}
200
201static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000202buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203{
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000204 char *status = self->b_readonly ? "read-only" : "read-write";
205
206 if ( self->b_base == NULL )
Barry Warsaw7ce36942001-08-24 18:34:26 +0000207 return PyString_FromFormat("<%s buffer ptr %p, size %d at %p>",
208 status,
209 self->b_ptr,
210 self->b_size,
211 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000212 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000213 return PyString_FromFormat(
214 "<%s buffer for %p, ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000215 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000216 self->b_base,
217 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000218 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000219 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000220}
221
222static long
Fred Drake79912472000-07-09 04:06:11 +0000223buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000224{
225 register int len;
226 register unsigned char *p;
227 register long x;
228
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000229 if ( self->b_hash != -1 )
230 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000231
232 if ( !self->b_readonly )
233 {
234 /* ### use different wording, since this is conditional? */
235 PyErr_SetString(PyExc_TypeError, "unhashable type");
236 return -1;
237 }
238
239 len = self->b_size;
240 p = (unsigned char *) self->b_ptr;
241 x = *p << 7;
242 while (--len >= 0)
243 x = (1000003*x) ^ *p++;
244 x ^= self->b_size;
245 if (x == -1)
246 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000247 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000248 return x;
249}
250
251static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000252buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000253{
254 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
255}
256
257/* Sequence methods */
258
259static int
Fred Drake79912472000-07-09 04:06:11 +0000260buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000261{
262 return self->b_size;
263}
264
265static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000266buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000267{
268 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
269 char *p1;
270 void *p2;
271 PyObject *ob;
272 int count;
273
274 if ( pb == NULL ||
275 pb->bf_getreadbuffer == NULL ||
276 pb->bf_getsegcount == NULL )
277 {
278 PyErr_BadArgument();
279 return NULL;
280 }
281 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
282 {
283 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000284 PyErr_SetString(PyExc_TypeError,
285 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000286 return NULL;
287 }
288
289 /* optimize special case */
290 if ( self->b_size == 0 )
291 {
292 Py_INCREF(other);
293 return other;
294 }
295
296 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
297 return NULL;
298
299 /* optimize special case */
300 if ( count == 0 )
301 {
302 Py_INCREF(self);
303 return (PyObject *)self;
304 }
305
306 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
307 p1 = PyString_AS_STRING(ob);
308 memcpy(p1, self->b_ptr, self->b_size);
309 memcpy(p1 + self->b_size, p2, count);
310
311 /* there is an extra byte in the string object, so this is safe */
312 p1[self->b_size + count] = '\0';
313
314 return ob;
315}
316
317static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000318buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000319{
320 PyObject *ob;
321 register char *p;
322 void *ptr = self->b_ptr;
323 int size = self->b_size;
324
325 if ( count < 0 )
326 count = 0;
327 ob = PyString_FromStringAndSize(NULL, size * count);
328 if ( ob == NULL )
329 return NULL;
330
331 p = PyString_AS_STRING(ob);
332 while ( count-- )
333 {
334 memcpy(p, ptr, size);
335 p += size;
336 }
337
338 /* there is an extra byte in the string object, so this is safe */
339 *p = '\0';
340
341 return ob;
342}
343
344static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000345buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000346{
347 if ( idx < 0 || idx >= self->b_size )
348 {
349 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
350 return NULL;
351 }
352 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
353}
354
355static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000356buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000357{
358 if ( left < 0 )
359 left = 0;
360 if ( right < 0 )
361 right = 0;
362 if ( right > self->b_size )
363 right = self->b_size;
364 if ( left == 0 && right == self->b_size )
365 {
366 /* same as self */
367 Py_INCREF(self);
368 return (PyObject *)self;
369 }
370 if ( right < left )
371 right = left;
Guido van Rossumcd037e71999-03-24 19:05:31 +0000372 return PyString_FromStringAndSize((char *)self->b_ptr + left,
373 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000374}
375
376static int
Fred Drake79912472000-07-09 04:06:11 +0000377buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000378{
379 PyBufferProcs *pb;
380 void *p;
381 int count;
382
383 if ( self->b_readonly ) {
384 PyErr_SetString(PyExc_TypeError,
385 "buffer is read-only");
386 return -1;
387 }
388
389 if (idx < 0 || idx >= self->b_size) {
390 PyErr_SetString(PyExc_IndexError,
391 "buffer assignment index out of range");
392 return -1;
393 }
394
395 pb = other ? other->ob_type->tp_as_buffer : NULL;
396 if ( pb == NULL ||
397 pb->bf_getreadbuffer == NULL ||
398 pb->bf_getsegcount == NULL )
399 {
400 PyErr_BadArgument();
401 return -1;
402 }
403 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
404 {
405 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000406 PyErr_SetString(PyExc_TypeError,
407 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000408 return -1;
409 }
410
411 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
412 return -1;
413 if ( count != 1 ) {
414 PyErr_SetString(PyExc_TypeError,
415 "right operand must be a single byte");
416 return -1;
417 }
418
419 ((char *)self->b_ptr)[idx] = *(char *)p;
420 return 0;
421}
422
423static int
Fred Drake79912472000-07-09 04:06:11 +0000424buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000425{
426 PyBufferProcs *pb;
427 void *p;
428 int slice_len;
429 int count;
430
431 if ( self->b_readonly ) {
432 PyErr_SetString(PyExc_TypeError,
433 "buffer is read-only");
434 return -1;
435 }
436
437 pb = other ? other->ob_type->tp_as_buffer : NULL;
438 if ( pb == NULL ||
439 pb->bf_getreadbuffer == NULL ||
440 pb->bf_getsegcount == NULL )
441 {
442 PyErr_BadArgument();
443 return -1;
444 }
445 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
446 {
447 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000448 PyErr_SetString(PyExc_TypeError,
449 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000450 return -1;
451 }
452 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
453 return -1;
454
455 if ( left < 0 )
456 left = 0;
457 else if ( left > self->b_size )
458 left = self->b_size;
459 if ( right < left )
460 right = left;
461 else if ( right > self->b_size )
462 right = self->b_size;
463 slice_len = right - left;
464
465 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000466 PyErr_SetString(
467 PyExc_TypeError,
468 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000469 return -1;
470 }
471
472 if ( slice_len )
473 memcpy((char *)self->b_ptr + left, p, slice_len);
474
475 return 0;
476}
477
478/* Buffer methods */
479
480static int
Fred Drake79912472000-07-09 04:06:11 +0000481buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000482{
483 if ( idx != 0 ) {
484 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000485 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000486 return -1;
487 }
488 *pp = self->b_ptr;
489 return self->b_size;
490}
491
492static int
Fred Drake79912472000-07-09 04:06:11 +0000493buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000494{
495 if ( self->b_readonly )
496 {
497 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
498 return -1;
499 }
500 return buffer_getreadbuf(self, idx, pp);
501}
502
503static int
Fred Drake79912472000-07-09 04:06:11 +0000504buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000505{
506 if ( lenp )
507 *lenp = self->b_size;
508 return 1;
509}
510
Guido van Rossum1db70701998-10-08 02:18:52 +0000511static int
Fred Drake79912472000-07-09 04:06:11 +0000512buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000513{
514 if ( idx != 0 ) {
515 PyErr_SetString(PyExc_SystemError,
516 "accessing non-existent buffer segment");
517 return -1;
518 }
519 *pp = (const char *)self->b_ptr;
520 return self->b_size;
521}
522
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000523
524static PySequenceMethods buffer_as_sequence = {
525 (inquiry)buffer_length, /*sq_length*/
526 (binaryfunc)buffer_concat, /*sq_concat*/
527 (intargfunc)buffer_repeat, /*sq_repeat*/
528 (intargfunc)buffer_item, /*sq_item*/
529 (intintargfunc)buffer_slice, /*sq_slice*/
530 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
531 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
532};
533
534static PyBufferProcs buffer_as_buffer = {
535 (getreadbufferproc)buffer_getreadbuf,
536 (getwritebufferproc)buffer_getwritebuf,
537 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000538 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000539};
540
541PyTypeObject PyBuffer_Type = {
542 PyObject_HEAD_INIT(&PyType_Type)
543 0,
544 "buffer",
545 sizeof(PyBufferObject),
546 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000547 (destructor)buffer_dealloc, /* tp_dealloc */
548 0, /* tp_print */
549 0, /* tp_getattr */
550 0, /* tp_setattr */
551 (cmpfunc)buffer_compare, /* tp_compare */
552 (reprfunc)buffer_repr, /* tp_repr */
553 0, /* tp_as_number */
554 &buffer_as_sequence, /* tp_as_sequence */
555 0, /* tp_as_mapping */
556 (hashfunc)buffer_hash, /* tp_hash */
557 0, /* tp_call */
558 (reprfunc)buffer_str, /* tp_str */
559 PyObject_GenericGetAttr, /* tp_getattro */
560 0, /* tp_setattro */
561 &buffer_as_buffer, /* tp_as_buffer */
562 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000563 buffer_doc, /* tp_doc */
564 0, /* tp_traverse */
565 0, /* tp_clear */
566 0, /* tp_richcompare */
567 0, /* tp_weaklistoffset */
568 0, /* tp_iter */
569 0, /* tp_iternext */
570 0, /* tp_methods */
571 0, /* tp_members */
572 0, /* tp_getset */
573 0, /* tp_base */
574 0, /* tp_dict */
575 0, /* tp_descr_get */
576 0, /* tp_descr_set */
577 0, /* tp_dictoffset */
578 0, /* tp_init */
579 0, /* tp_alloc */
580 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000581};