On 64-bit platforms running test_struct after test_tarfile would fail
[python.git] / Objects / bufferobject.c
blobd2597b9ee45ef1fde759c8e7846662c2a0325e73
2 /* Buffer object implementation */
4 #include "Python.h"
7 typedef struct {
8 PyObject_HEAD
9 PyObject *b_base;
10 void *b_ptr;
11 Py_ssize_t b_size;
12 Py_ssize_t b_offset;
13 int b_readonly;
14 long b_hash;
15 } PyBufferObject;
18 static int
19 get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size)
21 if (self->b_base == NULL) {
22 assert (ptr != NULL);
23 *ptr = self->b_ptr;
24 *size = self->b_size;
26 else {
27 Py_ssize_t count, offset;
28 readbufferproc 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;
35 if (self->b_readonly)
36 proc = bp->bf_getreadbuffer;
37 else
38 proc = (readbufferproc)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;
46 *(char **)ptr = *(char **)ptr + offset;
47 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;
54 return 1;
58 static PyObject *
59 buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
60 int readonly)
62 PyBufferObject * b;
64 if (size < 0 && size != Py_END_OF_BUFFER) {
65 PyErr_SetString(PyExc_ValueError,
66 "size must be zero or positive");
67 return NULL;
69 if (offset < 0) {
70 PyErr_SetString(PyExc_ValueError,
71 "offset must be zero or positive");
72 return NULL;
75 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
76 if ( b == NULL )
77 return NULL;
79 Py_XINCREF(base);
80 b->b_base = base;
81 b->b_ptr = ptr;
82 b->b_size = size;
83 b->b_offset = offset;
84 b->b_readonly = readonly;
85 b->b_hash = -1;
87 return (PyObject *) b;
90 static PyObject *
91 buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
93 if (offset < 0) {
94 PyErr_SetString(PyExc_ValueError,
95 "offset must be zero or positive");
96 return NULL;
98 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
99 /* another buffer, refer to the base object */
100 PyBufferObject *b = (PyBufferObject *)base;
101 if (b->b_size != Py_END_OF_BUFFER) {
102 Py_ssize_t 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;
108 offset += b->b_offset;
109 base = b->b_base;
111 return buffer_from_memory(base, size, offset, NULL, readonly);
115 PyObject *
116 PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
118 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
120 if ( pb == NULL ||
121 pb->bf_getreadbuffer == NULL ||
122 pb->bf_getsegcount == NULL )
124 PyErr_SetString(PyExc_TypeError, "buffer object expected");
125 return NULL;
128 return buffer_from_object(base, size, offset, 1);
131 PyObject *
132 PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
134 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
136 if ( pb == NULL ||
137 pb->bf_getwritebuffer == NULL ||
138 pb->bf_getsegcount == NULL )
140 PyErr_SetString(PyExc_TypeError, "buffer object expected");
141 return NULL;
144 return buffer_from_object(base, size, offset, 0);
147 PyObject *
148 PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
150 return buffer_from_memory(NULL, size, 0, ptr, 1);
153 PyObject *
154 PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
156 return buffer_from_memory(NULL, size, 0, ptr, 0);
159 PyObject *
160 PyBuffer_New(Py_ssize_t size)
162 PyObject *o;
163 PyBufferObject * b;
165 if (size < 0) {
166 PyErr_SetString(PyExc_ValueError,
167 "size must be zero or positive");
168 return NULL;
170 /* XXX: check for overflow in multiply */
171 /* Inline PyObject_New */
172 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
173 if ( o == NULL )
174 return PyErr_NoMemory();
175 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
177 b->b_base = NULL;
178 b->b_ptr = (void *)(b + 1);
179 b->b_size = size;
180 b->b_offset = 0;
181 b->b_readonly = 0;
182 b->b_hash = -1;
184 return o;
187 /* Methods */
189 static PyObject *
190 buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
192 PyObject *ob;
193 Py_ssize_t offset = 0;
194 Py_ssize_t size = Py_END_OF_BUFFER;
196 if (!_PyArg_NoKeywords("buffer()", kw))
197 return NULL;
199 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
200 return NULL;
201 return PyBuffer_FromObject(ob, offset, size);
204 PyDoc_STRVAR(buffer_doc,
205 "buffer(object [, offset[, size]])\n\
207 Create a new buffer object which references the given object.\n\
208 The buffer will reference a slice of the target object from the\n\
209 start of the object (or at the specified offset). The slice will\n\
210 extend to the end of the target object (or with the specified size).");
213 static void
214 buffer_dealloc(PyBufferObject *self)
216 Py_XDECREF(self->b_base);
217 PyObject_DEL(self);
220 static int
221 buffer_compare(PyBufferObject *self, PyBufferObject *other)
223 void *p1, *p2;
224 Py_ssize_t len_self, len_other, min_len;
225 int cmp;
227 if (!get_buf(self, &p1, &len_self))
228 return -1;
229 if (!get_buf(other, &p2, &len_other))
230 return -1;
231 min_len = (len_self < len_other) ? len_self : len_other;
232 if (min_len > 0) {
233 cmp = memcmp(p1, p2, min_len);
234 if (cmp != 0)
235 return cmp;
237 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
240 static PyObject *
241 buffer_repr(PyBufferObject *self)
243 const char *status = self->b_readonly ? "read-only" : "read-write";
245 if ( self->b_base == NULL )
246 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
247 status,
248 self->b_ptr,
249 self->b_size,
250 self);
251 else
252 return PyString_FromFormat(
253 "<%s buffer for %p, size %zd, offset %zd at %p>",
254 status,
255 self->b_base,
256 self->b_size,
257 self->b_offset,
258 self);
261 static long
262 buffer_hash(PyBufferObject *self)
264 void *ptr;
265 Py_ssize_t size;
266 register Py_ssize_t len;
267 register unsigned char *p;
268 register long x;
270 if ( self->b_hash != -1 )
271 return self->b_hash;
273 /* XXX potential bugs here, a readonly buffer does not imply that the
274 * underlying memory is immutable. b_readonly is a necessary but not
275 * sufficient condition for a buffer to be hashable. Perhaps it would
276 * be better to only allow hashing if the underlying object is known to
277 * be immutable (e.g. PyString_Check() is true). Another idea would
278 * be to call tp_hash on the underlying object and see if it raises
279 * an error. */
280 if ( !self->b_readonly )
282 PyErr_SetString(PyExc_TypeError,
283 "writable buffers are not hashable");
284 return -1;
287 if (!get_buf(self, &ptr, &size))
288 return -1;
289 p = (unsigned char *) ptr;
290 len = size;
291 x = *p << 7;
292 while (--len >= 0)
293 x = (1000003*x) ^ *p++;
294 x ^= size;
295 if (x == -1)
296 x = -2;
297 self->b_hash = x;
298 return x;
301 static PyObject *
302 buffer_str(PyBufferObject *self)
304 void *ptr;
305 Py_ssize_t size;
306 if (!get_buf(self, &ptr, &size))
307 return NULL;
308 return PyString_FromStringAndSize((const char *)ptr, size);
311 /* Sequence methods */
313 static Py_ssize_t
314 buffer_length(PyBufferObject *self)
316 void *ptr;
317 Py_ssize_t size;
318 if (!get_buf(self, &ptr, &size))
319 return -1;
320 return size;
323 static PyObject *
324 buffer_concat(PyBufferObject *self, PyObject *other)
326 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
327 void *ptr1, *ptr2;
328 char *p;
329 PyObject *ob;
330 Py_ssize_t size, count;
332 if ( pb == NULL ||
333 pb->bf_getreadbuffer == NULL ||
334 pb->bf_getsegcount == NULL )
336 PyErr_BadArgument();
337 return NULL;
339 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
341 /* ### use a different exception type/message? */
342 PyErr_SetString(PyExc_TypeError,
343 "single-segment buffer object expected");
344 return NULL;
347 if (!get_buf(self, &ptr1, &size))
348 return NULL;
350 /* optimize special case */
351 if ( size == 0 )
353 Py_INCREF(other);
354 return other;
357 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
358 return NULL;
360 ob = PyString_FromStringAndSize(NULL, size + count);
361 if ( ob == NULL )
362 return NULL;
363 p = PyString_AS_STRING(ob);
364 memcpy(p, ptr1, size);
365 memcpy(p + size, ptr2, count);
367 /* there is an extra byte in the string object, so this is safe */
368 p[size + count] = '\0';
370 return ob;
373 static PyObject *
374 buffer_repeat(PyBufferObject *self, Py_ssize_t count)
376 PyObject *ob;
377 register char *p;
378 void *ptr;
379 Py_ssize_t size;
381 if ( count < 0 )
382 count = 0;
383 if (!get_buf(self, &ptr, &size))
384 return NULL;
385 ob = PyString_FromStringAndSize(NULL, size * count);
386 if ( ob == NULL )
387 return NULL;
389 p = PyString_AS_STRING(ob);
390 while ( count-- )
392 memcpy(p, ptr, size);
393 p += size;
396 /* there is an extra byte in the string object, so this is safe */
397 *p = '\0';
399 return ob;
402 static PyObject *
403 buffer_item(PyBufferObject *self, Py_ssize_t idx)
405 void *ptr;
406 Py_ssize_t size;
407 if (!get_buf(self, &ptr, &size))
408 return NULL;
409 if ( idx < 0 || idx >= size ) {
410 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
411 return NULL;
413 return PyString_FromStringAndSize((char *)ptr + idx, 1);
416 static PyObject *
417 buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
419 void *ptr;
420 Py_ssize_t size;
421 if (!get_buf(self, &ptr, &size))
422 return NULL;
423 if ( left < 0 )
424 left = 0;
425 if ( right < 0 )
426 right = 0;
427 if ( right > size )
428 right = size;
429 if ( right < left )
430 right = left;
431 return PyString_FromStringAndSize((char *)ptr + left,
432 right - left);
435 static int
436 buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
438 PyBufferProcs *pb;
439 void *ptr1, *ptr2;
440 Py_ssize_t size;
441 Py_ssize_t count;
443 if ( self->b_readonly ) {
444 PyErr_SetString(PyExc_TypeError,
445 "buffer is read-only");
446 return -1;
449 if (!get_buf(self, &ptr1, &size))
450 return -1;
452 if (idx < 0 || idx >= size) {
453 PyErr_SetString(PyExc_IndexError,
454 "buffer assignment index out of range");
455 return -1;
458 pb = other ? other->ob_type->tp_as_buffer : NULL;
459 if ( pb == NULL ||
460 pb->bf_getreadbuffer == NULL ||
461 pb->bf_getsegcount == NULL )
463 PyErr_BadArgument();
464 return -1;
466 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
468 /* ### use a different exception type/message? */
469 PyErr_SetString(PyExc_TypeError,
470 "single-segment buffer object expected");
471 return -1;
474 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
475 return -1;
476 if ( count != 1 ) {
477 PyErr_SetString(PyExc_TypeError,
478 "right operand must be a single byte");
479 return -1;
482 ((char *)ptr1)[idx] = *(char *)ptr2;
483 return 0;
486 static int
487 buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
489 PyBufferProcs *pb;
490 void *ptr1, *ptr2;
491 Py_ssize_t size;
492 Py_ssize_t slice_len;
493 Py_ssize_t count;
495 if ( self->b_readonly ) {
496 PyErr_SetString(PyExc_TypeError,
497 "buffer is read-only");
498 return -1;
501 pb = other ? other->ob_type->tp_as_buffer : NULL;
502 if ( pb == NULL ||
503 pb->bf_getreadbuffer == NULL ||
504 pb->bf_getsegcount == NULL )
506 PyErr_BadArgument();
507 return -1;
509 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
511 /* ### use a different exception type/message? */
512 PyErr_SetString(PyExc_TypeError,
513 "single-segment buffer object expected");
514 return -1;
516 if (!get_buf(self, &ptr1, &size))
517 return -1;
518 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
519 return -1;
521 if ( left < 0 )
522 left = 0;
523 else if ( left > size )
524 left = size;
525 if ( right < left )
526 right = left;
527 else if ( right > size )
528 right = size;
529 slice_len = right - left;
531 if ( count != slice_len ) {
532 PyErr_SetString(
533 PyExc_TypeError,
534 "right operand length must match slice length");
535 return -1;
538 if ( slice_len )
539 memcpy((char *)ptr1 + left, ptr2, slice_len);
541 return 0;
544 /* Buffer methods */
546 static Py_ssize_t
547 buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
549 Py_ssize_t size;
550 if ( idx != 0 ) {
551 PyErr_SetString(PyExc_SystemError,
552 "accessing non-existent buffer segment");
553 return -1;
555 if (!get_buf(self, pp, &size))
556 return -1;
557 return size;
560 static Py_ssize_t
561 buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
563 if ( self->b_readonly )
565 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
566 return -1;
568 return buffer_getreadbuf(self, idx, pp);
571 static Py_ssize_t
572 buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
574 void *ptr;
575 Py_ssize_t size;
576 if (!get_buf(self, &ptr, &size))
577 return -1;
578 if (lenp)
579 *lenp = size;
580 return 1;
583 static Py_ssize_t
584 buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
586 void *ptr;
587 Py_ssize_t size;
588 if ( idx != 0 ) {
589 PyErr_SetString(PyExc_SystemError,
590 "accessing non-existent buffer segment");
591 return -1;
593 if (!get_buf(self, &ptr, &size))
594 return -1;
595 *pp = (const char *)ptr;
596 return size;
600 static PySequenceMethods buffer_as_sequence = {
601 (lenfunc)buffer_length, /*sq_length*/
602 (binaryfunc)buffer_concat, /*sq_concat*/
603 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
604 (ssizeargfunc)buffer_item, /*sq_item*/
605 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
606 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
607 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
610 static PyBufferProcs buffer_as_buffer = {
611 (readbufferproc)buffer_getreadbuf,
612 (writebufferproc)buffer_getwritebuf,
613 (segcountproc)buffer_getsegcount,
614 (charbufferproc)buffer_getcharbuf,
617 PyTypeObject PyBuffer_Type = {
618 PyObject_HEAD_INIT(&PyType_Type)
620 "buffer",
621 sizeof(PyBufferObject),
623 (destructor)buffer_dealloc, /* tp_dealloc */
624 0, /* tp_print */
625 0, /* tp_getattr */
626 0, /* tp_setattr */
627 (cmpfunc)buffer_compare, /* tp_compare */
628 (reprfunc)buffer_repr, /* tp_repr */
629 0, /* tp_as_number */
630 &buffer_as_sequence, /* tp_as_sequence */
631 0, /* tp_as_mapping */
632 (hashfunc)buffer_hash, /* tp_hash */
633 0, /* tp_call */
634 (reprfunc)buffer_str, /* tp_str */
635 PyObject_GenericGetAttr, /* tp_getattro */
636 0, /* tp_setattro */
637 &buffer_as_buffer, /* tp_as_buffer */
638 Py_TPFLAGS_DEFAULT, /* tp_flags */
639 buffer_doc, /* tp_doc */
640 0, /* tp_traverse */
641 0, /* tp_clear */
642 0, /* tp_richcompare */
643 0, /* tp_weaklistoffset */
644 0, /* tp_iter */
645 0, /* tp_iternext */
646 0, /* tp_methods */
647 0, /* tp_members */
648 0, /* tp_getset */
649 0, /* tp_base */
650 0, /* tp_dict */
651 0, /* tp_descr_get */
652 0, /* tp_descr_set */
653 0, /* tp_dictoffset */
654 0, /* tp_init */
655 0, /* tp_alloc */
656 buffer_new, /* tp_new */