Tone down math.fsum warning.
[python.git] / Objects / bufferobject.c
blob9a5c39f6f4c4369435f442ee333b43cf069c5ba0
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 enum buffer_t {
19 READ_BUFFER,
20 WRITE_BUFFER,
21 CHAR_BUFFER,
22 ANY_BUFFER
25 static int
26 get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
27 enum buffer_t buffer_type)
29 if (self->b_base == NULL) {
30 assert (ptr != NULL);
31 *ptr = self->b_ptr;
32 *size = self->b_size;
34 else {
35 Py_ssize_t count, offset;
36 readbufferproc proc = 0;
37 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
38 if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
39 PyErr_SetString(PyExc_TypeError,
40 "single-segment buffer object expected");
41 return 0;
43 if ((buffer_type == READ_BUFFER) ||
44 ((buffer_type == ANY_BUFFER) && self->b_readonly))
45 proc = bp->bf_getreadbuffer;
46 else if ((buffer_type == WRITE_BUFFER) ||
47 (buffer_type == ANY_BUFFER))
48 proc = (readbufferproc)bp->bf_getwritebuffer;
49 else if (buffer_type == CHAR_BUFFER) {
50 if (!PyType_HasFeature(self->ob_type,
51 Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
52 PyErr_SetString(PyExc_TypeError,
53 "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
54 return 0;
56 proc = (readbufferproc)bp->bf_getcharbuffer;
58 if (!proc) {
59 char *buffer_type_name;
60 switch (buffer_type) {
61 case READ_BUFFER:
62 buffer_type_name = "read";
63 break;
64 case WRITE_BUFFER:
65 buffer_type_name = "write";
66 break;
67 case CHAR_BUFFER:
68 buffer_type_name = "char";
69 break;
70 default:
71 buffer_type_name = "no";
72 break;
74 PyErr_Format(PyExc_TypeError,
75 "%s buffer type not available",
76 buffer_type_name);
77 return 0;
79 if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
80 return 0;
81 /* apply constraints to the start/end */
82 if (self->b_offset > count)
83 offset = count;
84 else
85 offset = self->b_offset;
86 *(char **)ptr = *(char **)ptr + offset;
87 if (self->b_size == Py_END_OF_BUFFER)
88 *size = count;
89 else
90 *size = self->b_size;
91 if (offset + *size > count)
92 *size = count - offset;
94 return 1;
98 static PyObject *
99 buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
100 int readonly)
102 PyBufferObject * b;
104 if (size < 0 && size != Py_END_OF_BUFFER) {
105 PyErr_SetString(PyExc_ValueError,
106 "size must be zero or positive");
107 return NULL;
109 if (offset < 0) {
110 PyErr_SetString(PyExc_ValueError,
111 "offset must be zero or positive");
112 return NULL;
115 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116 if ( b == NULL )
117 return NULL;
119 Py_XINCREF(base);
120 b->b_base = base;
121 b->b_ptr = ptr;
122 b->b_size = size;
123 b->b_offset = offset;
124 b->b_readonly = readonly;
125 b->b_hash = -1;
127 return (PyObject *) b;
130 static PyObject *
131 buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
133 if (offset < 0) {
134 PyErr_SetString(PyExc_ValueError,
135 "offset must be zero or positive");
136 return NULL;
138 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
139 /* another buffer, refer to the base object */
140 PyBufferObject *b = (PyBufferObject *)base;
141 if (b->b_size != Py_END_OF_BUFFER) {
142 Py_ssize_t base_size = b->b_size - offset;
143 if (base_size < 0)
144 base_size = 0;
145 if (size == Py_END_OF_BUFFER || size > base_size)
146 size = base_size;
148 offset += b->b_offset;
149 base = b->b_base;
151 return buffer_from_memory(base, size, offset, NULL, readonly);
155 PyObject *
156 PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
158 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
160 if ( pb == NULL ||
161 pb->bf_getreadbuffer == NULL ||
162 pb->bf_getsegcount == NULL )
164 PyErr_SetString(PyExc_TypeError, "buffer object expected");
165 return NULL;
168 return buffer_from_object(base, size, offset, 1);
171 PyObject *
172 PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
174 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
176 if ( pb == NULL ||
177 pb->bf_getwritebuffer == NULL ||
178 pb->bf_getsegcount == NULL )
180 PyErr_SetString(PyExc_TypeError, "buffer object expected");
181 return NULL;
184 return buffer_from_object(base, size, offset, 0);
187 PyObject *
188 PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
190 return buffer_from_memory(NULL, size, 0, ptr, 1);
193 PyObject *
194 PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
196 return buffer_from_memory(NULL, size, 0, ptr, 0);
199 PyObject *
200 PyBuffer_New(Py_ssize_t size)
202 PyObject *o;
203 PyBufferObject * b;
205 if (size < 0) {
206 PyErr_SetString(PyExc_ValueError,
207 "size must be zero or positive");
208 return NULL;
210 if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
211 /* unlikely */
212 return PyErr_NoMemory();
214 /* Inline PyObject_New */
215 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
216 if ( o == NULL )
217 return PyErr_NoMemory();
218 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
220 b->b_base = NULL;
221 b->b_ptr = (void *)(b + 1);
222 b->b_size = size;
223 b->b_offset = 0;
224 b->b_readonly = 0;
225 b->b_hash = -1;
227 return o;
230 /* Methods */
232 static PyObject *
233 buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
235 PyObject *ob;
236 Py_ssize_t offset = 0;
237 Py_ssize_t size = Py_END_OF_BUFFER;
239 if (PyErr_WarnPy3k("buffer() not supported in 3.x; "
240 "use memoryview()", 1) < 0)
241 return NULL;
243 if (!_PyArg_NoKeywords("buffer()", kw))
244 return NULL;
246 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
247 return NULL;
248 return PyBuffer_FromObject(ob, offset, size);
251 PyDoc_STRVAR(buffer_doc,
252 "buffer(object [, offset[, size]])\n\
254 Create a new buffer object which references the given object.\n\
255 The buffer will reference a slice of the target object from the\n\
256 start of the object (or at the specified offset). The slice will\n\
257 extend to the end of the target object (or with the specified size).");
260 static void
261 buffer_dealloc(PyBufferObject *self)
263 Py_XDECREF(self->b_base);
264 PyObject_DEL(self);
267 static int
268 buffer_compare(PyBufferObject *self, PyBufferObject *other)
270 void *p1, *p2;
271 Py_ssize_t len_self, len_other, min_len;
272 int cmp;
274 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
275 return -1;
276 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
277 return -1;
278 min_len = (len_self < len_other) ? len_self : len_other;
279 if (min_len > 0) {
280 cmp = memcmp(p1, p2, min_len);
281 if (cmp != 0)
282 return cmp < 0 ? -1 : 1;
284 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
287 static PyObject *
288 buffer_repr(PyBufferObject *self)
290 const char *status = self->b_readonly ? "read-only" : "read-write";
292 if ( self->b_base == NULL )
293 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
294 status,
295 self->b_ptr,
296 self->b_size,
297 self);
298 else
299 return PyString_FromFormat(
300 "<%s buffer for %p, size %zd, offset %zd at %p>",
301 status,
302 self->b_base,
303 self->b_size,
304 self->b_offset,
305 self);
308 static long
309 buffer_hash(PyBufferObject *self)
311 void *ptr;
312 Py_ssize_t size;
313 register Py_ssize_t len;
314 register unsigned char *p;
315 register long x;
317 if ( self->b_hash != -1 )
318 return self->b_hash;
320 /* XXX potential bugs here, a readonly buffer does not imply that the
321 * underlying memory is immutable. b_readonly is a necessary but not
322 * sufficient condition for a buffer to be hashable. Perhaps it would
323 * be better to only allow hashing if the underlying object is known to
324 * be immutable (e.g. PyString_Check() is true). Another idea would
325 * be to call tp_hash on the underlying object and see if it raises
326 * an error. */
327 if ( !self->b_readonly )
329 PyErr_SetString(PyExc_TypeError,
330 "writable buffers are not hashable");
331 return -1;
334 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
335 return -1;
336 p = (unsigned char *) ptr;
337 len = size;
338 x = *p << 7;
339 while (--len >= 0)
340 x = (1000003*x) ^ *p++;
341 x ^= size;
342 if (x == -1)
343 x = -2;
344 self->b_hash = x;
345 return x;
348 static PyObject *
349 buffer_str(PyBufferObject *self)
351 void *ptr;
352 Py_ssize_t size;
353 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
354 return NULL;
355 return PyString_FromStringAndSize((const char *)ptr, size);
358 /* Sequence methods */
360 static Py_ssize_t
361 buffer_length(PyBufferObject *self)
363 void *ptr;
364 Py_ssize_t size;
365 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
366 return -1;
367 return size;
370 static PyObject *
371 buffer_concat(PyBufferObject *self, PyObject *other)
373 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
374 void *ptr1, *ptr2;
375 char *p;
376 PyObject *ob;
377 Py_ssize_t size, count;
379 if ( pb == NULL ||
380 pb->bf_getreadbuffer == NULL ||
381 pb->bf_getsegcount == NULL )
383 PyErr_BadArgument();
384 return NULL;
386 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
388 /* ### use a different exception type/message? */
389 PyErr_SetString(PyExc_TypeError,
390 "single-segment buffer object expected");
391 return NULL;
394 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
395 return NULL;
397 /* optimize special case */
398 if ( size == 0 )
400 Py_INCREF(other);
401 return other;
404 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
405 return NULL;
407 assert(count <= PY_SIZE_MAX - size);
409 ob = PyString_FromStringAndSize(NULL, size + count);
410 if ( ob == NULL )
411 return NULL;
412 p = PyString_AS_STRING(ob);
413 memcpy(p, ptr1, size);
414 memcpy(p + size, ptr2, count);
416 /* there is an extra byte in the string object, so this is safe */
417 p[size + count] = '\0';
419 return ob;
422 static PyObject *
423 buffer_repeat(PyBufferObject *self, Py_ssize_t count)
425 PyObject *ob;
426 register char *p;
427 void *ptr;
428 Py_ssize_t size;
430 if ( count < 0 )
431 count = 0;
432 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
433 return NULL;
434 if (count > PY_SSIZE_T_MAX / size) {
435 PyErr_SetString(PyExc_MemoryError, "result too large");
436 return NULL;
438 ob = PyString_FromStringAndSize(NULL, size * count);
439 if ( ob == NULL )
440 return NULL;
442 p = PyString_AS_STRING(ob);
443 while ( count-- )
445 memcpy(p, ptr, size);
446 p += size;
449 /* there is an extra byte in the string object, so this is safe */
450 *p = '\0';
452 return ob;
455 static PyObject *
456 buffer_item(PyBufferObject *self, Py_ssize_t idx)
458 void *ptr;
459 Py_ssize_t size;
460 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
461 return NULL;
462 if ( idx < 0 || idx >= size ) {
463 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
464 return NULL;
466 return PyString_FromStringAndSize((char *)ptr + idx, 1);
469 static PyObject *
470 buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
472 void *ptr;
473 Py_ssize_t size;
474 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
475 return NULL;
476 if ( left < 0 )
477 left = 0;
478 if ( right < 0 )
479 right = 0;
480 if ( right > size )
481 right = size;
482 if ( right < left )
483 right = left;
484 return PyString_FromStringAndSize((char *)ptr + left,
485 right - left);
488 static PyObject *
489 buffer_subscript(PyBufferObject *self, PyObject *item)
491 void *p;
492 Py_ssize_t size;
494 if (!get_buf(self, &p, &size, ANY_BUFFER))
495 return NULL;
496 if (PyIndex_Check(item)) {
497 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
498 if (i == -1 && PyErr_Occurred())
499 return NULL;
500 if (i < 0)
501 i += size;
502 return buffer_item(self, i);
504 else if (PySlice_Check(item)) {
505 Py_ssize_t start, stop, step, slicelength, cur, i;
507 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
508 &start, &stop, &step, &slicelength) < 0) {
509 return NULL;
512 if (slicelength <= 0)
513 return PyString_FromStringAndSize("", 0);
514 else if (step == 1)
515 return PyString_FromStringAndSize((char *)p + start,
516 stop - start);
517 else {
518 PyObject *result;
519 char *source_buf = (char *)p;
520 char *result_buf = (char *)PyMem_Malloc(slicelength);
522 if (result_buf == NULL)
523 return PyErr_NoMemory();
525 for (cur = start, i = 0; i < slicelength;
526 cur += step, i++) {
527 result_buf[i] = source_buf[cur];
530 result = PyString_FromStringAndSize(result_buf,
531 slicelength);
532 PyMem_Free(result_buf);
533 return result;
536 else {
537 PyErr_SetString(PyExc_TypeError,
538 "sequence index must be integer");
539 return NULL;
543 static int
544 buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
546 PyBufferProcs *pb;
547 void *ptr1, *ptr2;
548 Py_ssize_t size;
549 Py_ssize_t count;
551 if ( self->b_readonly ) {
552 PyErr_SetString(PyExc_TypeError,
553 "buffer is read-only");
554 return -1;
557 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
558 return -1;
560 if (idx < 0 || idx >= size) {
561 PyErr_SetString(PyExc_IndexError,
562 "buffer assignment index out of range");
563 return -1;
566 pb = other ? other->ob_type->tp_as_buffer : NULL;
567 if ( pb == NULL ||
568 pb->bf_getreadbuffer == NULL ||
569 pb->bf_getsegcount == NULL )
571 PyErr_BadArgument();
572 return -1;
574 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
576 /* ### use a different exception type/message? */
577 PyErr_SetString(PyExc_TypeError,
578 "single-segment buffer object expected");
579 return -1;
582 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
583 return -1;
584 if ( count != 1 ) {
585 PyErr_SetString(PyExc_TypeError,
586 "right operand must be a single byte");
587 return -1;
590 ((char *)ptr1)[idx] = *(char *)ptr2;
591 return 0;
594 static int
595 buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
597 PyBufferProcs *pb;
598 void *ptr1, *ptr2;
599 Py_ssize_t size;
600 Py_ssize_t slice_len;
601 Py_ssize_t count;
603 if ( self->b_readonly ) {
604 PyErr_SetString(PyExc_TypeError,
605 "buffer is read-only");
606 return -1;
609 pb = other ? other->ob_type->tp_as_buffer : NULL;
610 if ( pb == NULL ||
611 pb->bf_getreadbuffer == NULL ||
612 pb->bf_getsegcount == NULL )
614 PyErr_BadArgument();
615 return -1;
617 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
619 /* ### use a different exception type/message? */
620 PyErr_SetString(PyExc_TypeError,
621 "single-segment buffer object expected");
622 return -1;
624 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
625 return -1;
626 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
627 return -1;
629 if ( left < 0 )
630 left = 0;
631 else if ( left > size )
632 left = size;
633 if ( right < left )
634 right = left;
635 else if ( right > size )
636 right = size;
637 slice_len = right - left;
639 if ( count != slice_len ) {
640 PyErr_SetString(
641 PyExc_TypeError,
642 "right operand length must match slice length");
643 return -1;
646 if ( slice_len )
647 memcpy((char *)ptr1 + left, ptr2, slice_len);
649 return 0;
652 static int
653 buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
655 PyBufferProcs *pb;
656 void *ptr1, *ptr2;
657 Py_ssize_t selfsize;
658 Py_ssize_t othersize;
660 if ( self->b_readonly ) {
661 PyErr_SetString(PyExc_TypeError,
662 "buffer is read-only");
663 return -1;
666 pb = value ? value->ob_type->tp_as_buffer : NULL;
667 if ( pb == NULL ||
668 pb->bf_getreadbuffer == NULL ||
669 pb->bf_getsegcount == NULL )
671 PyErr_BadArgument();
672 return -1;
674 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
676 /* ### use a different exception type/message? */
677 PyErr_SetString(PyExc_TypeError,
678 "single-segment buffer object expected");
679 return -1;
681 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
682 return -1;
683 if (PyIndex_Check(item)) {
684 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
685 if (i == -1 && PyErr_Occurred())
686 return -1;
687 if (i < 0)
688 i += selfsize;
689 return buffer_ass_item(self, i, value);
691 else if (PySlice_Check(item)) {
692 Py_ssize_t start, stop, step, slicelength;
694 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
695 &start, &stop, &step, &slicelength) < 0)
696 return -1;
698 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
699 return -1;
701 if (othersize != slicelength) {
702 PyErr_SetString(
703 PyExc_TypeError,
704 "right operand length must match slice length");
705 return -1;
708 if (slicelength == 0)
709 return 0;
710 else if (step == 1) {
711 memcpy((char *)ptr1 + start, ptr2, slicelength);
712 return 0;
714 else {
715 Py_ssize_t cur, i;
717 for (cur = start, i = 0; i < slicelength;
718 cur += step, i++) {
719 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
722 return 0;
724 } else {
725 PyErr_SetString(PyExc_TypeError,
726 "buffer indices must be integers");
727 return -1;
731 /* Buffer methods */
733 static Py_ssize_t
734 buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
736 Py_ssize_t size;
737 if ( idx != 0 ) {
738 PyErr_SetString(PyExc_SystemError,
739 "accessing non-existent buffer segment");
740 return -1;
742 if (!get_buf(self, pp, &size, READ_BUFFER))
743 return -1;
744 return size;
747 static Py_ssize_t
748 buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
750 Py_ssize_t size;
752 if ( self->b_readonly )
754 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
755 return -1;
758 if ( idx != 0 ) {
759 PyErr_SetString(PyExc_SystemError,
760 "accessing non-existent buffer segment");
761 return -1;
763 if (!get_buf(self, pp, &size, WRITE_BUFFER))
764 return -1;
765 return size;
768 static Py_ssize_t
769 buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
771 void *ptr;
772 Py_ssize_t size;
773 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
774 return -1;
775 if (lenp)
776 *lenp = size;
777 return 1;
780 static Py_ssize_t
781 buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
783 void *ptr;
784 Py_ssize_t size;
785 if ( idx != 0 ) {
786 PyErr_SetString(PyExc_SystemError,
787 "accessing non-existent buffer segment");
788 return -1;
790 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
791 return -1;
792 *pp = (const char *)ptr;
793 return size;
796 static PySequenceMethods buffer_as_sequence = {
797 (lenfunc)buffer_length, /*sq_length*/
798 (binaryfunc)buffer_concat, /*sq_concat*/
799 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
800 (ssizeargfunc)buffer_item, /*sq_item*/
801 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
802 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
803 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
806 static PyMappingMethods buffer_as_mapping = {
807 (lenfunc)buffer_length,
808 (binaryfunc)buffer_subscript,
809 (objobjargproc)buffer_ass_subscript,
812 static PyBufferProcs buffer_as_buffer = {
813 (readbufferproc)buffer_getreadbuf,
814 (writebufferproc)buffer_getwritebuf,
815 (segcountproc)buffer_getsegcount,
816 (charbufferproc)buffer_getcharbuf,
819 PyTypeObject PyBuffer_Type = {
820 PyVarObject_HEAD_INIT(&PyType_Type, 0)
821 "buffer",
822 sizeof(PyBufferObject),
824 (destructor)buffer_dealloc, /* tp_dealloc */
825 0, /* tp_print */
826 0, /* tp_getattr */
827 0, /* tp_setattr */
828 (cmpfunc)buffer_compare, /* tp_compare */
829 (reprfunc)buffer_repr, /* tp_repr */
830 0, /* tp_as_number */
831 &buffer_as_sequence, /* tp_as_sequence */
832 &buffer_as_mapping, /* tp_as_mapping */
833 (hashfunc)buffer_hash, /* tp_hash */
834 0, /* tp_call */
835 (reprfunc)buffer_str, /* tp_str */
836 PyObject_GenericGetAttr, /* tp_getattro */
837 0, /* tp_setattro */
838 &buffer_as_buffer, /* tp_as_buffer */
839 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
840 buffer_doc, /* tp_doc */
841 0, /* tp_traverse */
842 0, /* tp_clear */
843 0, /* tp_richcompare */
844 0, /* tp_weaklistoffset */
845 0, /* tp_iter */
846 0, /* tp_iternext */
847 0, /* tp_methods */
848 0, /* tp_members */
849 0, /* tp_getset */
850 0, /* tp_base */
851 0, /* tp_dict */
852 0, /* tp_descr_get */
853 0, /* tp_descr_set */
854 0, /* tp_dictoffset */
855 0, /* tp_init */
856 0, /* tp_alloc */
857 buffer_new, /* tp_new */