Use a more idiomatic check in check_truediv.
[python.git] / Objects / bufferobject.c
blob5b08e1eaefb0cf88f058f5562cd7f75b3c25677a
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", 1) < 0)
240 return NULL;
242 if (!_PyArg_NoKeywords("buffer()", kw))
243 return NULL;
245 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
246 return NULL;
247 return PyBuffer_FromObject(ob, offset, size);
250 PyDoc_STRVAR(buffer_doc,
251 "buffer(object [, offset[, size]])\n\
253 Create a new buffer object which references the given object.\n\
254 The buffer will reference a slice of the target object from the\n\
255 start of the object (or at the specified offset). The slice will\n\
256 extend to the end of the target object (or with the specified size).");
259 static void
260 buffer_dealloc(PyBufferObject *self)
262 Py_XDECREF(self->b_base);
263 PyObject_DEL(self);
266 static int
267 buffer_compare(PyBufferObject *self, PyBufferObject *other)
269 void *p1, *p2;
270 Py_ssize_t len_self, len_other, min_len;
271 int cmp;
273 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
274 return -1;
275 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
276 return -1;
277 min_len = (len_self < len_other) ? len_self : len_other;
278 if (min_len > 0) {
279 cmp = memcmp(p1, p2, min_len);
280 if (cmp != 0)
281 return cmp < 0 ? -1 : 1;
283 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
286 static PyObject *
287 buffer_repr(PyBufferObject *self)
289 const char *status = self->b_readonly ? "read-only" : "read-write";
291 if ( self->b_base == NULL )
292 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
293 status,
294 self->b_ptr,
295 self->b_size,
296 self);
297 else
298 return PyString_FromFormat(
299 "<%s buffer for %p, size %zd, offset %zd at %p>",
300 status,
301 self->b_base,
302 self->b_size,
303 self->b_offset,
304 self);
307 static long
308 buffer_hash(PyBufferObject *self)
310 void *ptr;
311 Py_ssize_t size;
312 register Py_ssize_t len;
313 register unsigned char *p;
314 register long x;
316 if ( self->b_hash != -1 )
317 return self->b_hash;
319 /* XXX potential bugs here, a readonly buffer does not imply that the
320 * underlying memory is immutable. b_readonly is a necessary but not
321 * sufficient condition for a buffer to be hashable. Perhaps it would
322 * be better to only allow hashing if the underlying object is known to
323 * be immutable (e.g. PyString_Check() is true). Another idea would
324 * be to call tp_hash on the underlying object and see if it raises
325 * an error. */
326 if ( !self->b_readonly )
328 PyErr_SetString(PyExc_TypeError,
329 "writable buffers are not hashable");
330 return -1;
333 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
334 return -1;
335 p = (unsigned char *) ptr;
336 len = size;
337 x = *p << 7;
338 while (--len >= 0)
339 x = (1000003*x) ^ *p++;
340 x ^= size;
341 if (x == -1)
342 x = -2;
343 self->b_hash = x;
344 return x;
347 static PyObject *
348 buffer_str(PyBufferObject *self)
350 void *ptr;
351 Py_ssize_t size;
352 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
353 return NULL;
354 return PyString_FromStringAndSize((const char *)ptr, size);
357 /* Sequence methods */
359 static Py_ssize_t
360 buffer_length(PyBufferObject *self)
362 void *ptr;
363 Py_ssize_t size;
364 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
365 return -1;
366 return size;
369 static PyObject *
370 buffer_concat(PyBufferObject *self, PyObject *other)
372 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
373 void *ptr1, *ptr2;
374 char *p;
375 PyObject *ob;
376 Py_ssize_t size, count;
378 if ( pb == NULL ||
379 pb->bf_getreadbuffer == NULL ||
380 pb->bf_getsegcount == NULL )
382 PyErr_BadArgument();
383 return NULL;
385 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
387 /* ### use a different exception type/message? */
388 PyErr_SetString(PyExc_TypeError,
389 "single-segment buffer object expected");
390 return NULL;
393 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
394 return NULL;
396 /* optimize special case */
397 if ( size == 0 )
399 Py_INCREF(other);
400 return other;
403 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
404 return NULL;
406 assert(count <= PY_SIZE_MAX - size);
408 ob = PyString_FromStringAndSize(NULL, size + count);
409 if ( ob == NULL )
410 return NULL;
411 p = PyString_AS_STRING(ob);
412 memcpy(p, ptr1, size);
413 memcpy(p + size, ptr2, count);
415 /* there is an extra byte in the string object, so this is safe */
416 p[size + count] = '\0';
418 return ob;
421 static PyObject *
422 buffer_repeat(PyBufferObject *self, Py_ssize_t count)
424 PyObject *ob;
425 register char *p;
426 void *ptr;
427 Py_ssize_t size;
429 if ( count < 0 )
430 count = 0;
431 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
432 return NULL;
433 if (count > PY_SSIZE_T_MAX / size) {
434 PyErr_SetString(PyExc_MemoryError, "result too large");
435 return NULL;
437 ob = PyString_FromStringAndSize(NULL, size * count);
438 if ( ob == NULL )
439 return NULL;
441 p = PyString_AS_STRING(ob);
442 while ( count-- )
444 memcpy(p, ptr, size);
445 p += size;
448 /* there is an extra byte in the string object, so this is safe */
449 *p = '\0';
451 return ob;
454 static PyObject *
455 buffer_item(PyBufferObject *self, Py_ssize_t idx)
457 void *ptr;
458 Py_ssize_t size;
459 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
460 return NULL;
461 if ( idx < 0 || idx >= size ) {
462 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
463 return NULL;
465 return PyString_FromStringAndSize((char *)ptr + idx, 1);
468 static PyObject *
469 buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
471 void *ptr;
472 Py_ssize_t size;
473 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
474 return NULL;
475 if ( left < 0 )
476 left = 0;
477 if ( right < 0 )
478 right = 0;
479 if ( right > size )
480 right = size;
481 if ( right < left )
482 right = left;
483 return PyString_FromStringAndSize((char *)ptr + left,
484 right - left);
487 static PyObject *
488 buffer_subscript(PyBufferObject *self, PyObject *item)
490 void *p;
491 Py_ssize_t size;
493 if (!get_buf(self, &p, &size, ANY_BUFFER))
494 return NULL;
495 if (PyIndex_Check(item)) {
496 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
497 if (i == -1 && PyErr_Occurred())
498 return NULL;
499 if (i < 0)
500 i += size;
501 return buffer_item(self, i);
503 else if (PySlice_Check(item)) {
504 Py_ssize_t start, stop, step, slicelength, cur, i;
506 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
507 &start, &stop, &step, &slicelength) < 0) {
508 return NULL;
511 if (slicelength <= 0)
512 return PyString_FromStringAndSize("", 0);
513 else if (step == 1)
514 return PyString_FromStringAndSize((char *)p + start,
515 stop - start);
516 else {
517 PyObject *result;
518 char *source_buf = (char *)p;
519 char *result_buf = (char *)PyMem_Malloc(slicelength);
521 if (result_buf == NULL)
522 return PyErr_NoMemory();
524 for (cur = start, i = 0; i < slicelength;
525 cur += step, i++) {
526 result_buf[i] = source_buf[cur];
529 result = PyString_FromStringAndSize(result_buf,
530 slicelength);
531 PyMem_Free(result_buf);
532 return result;
535 else {
536 PyErr_SetString(PyExc_TypeError,
537 "sequence index must be integer");
538 return NULL;
542 static int
543 buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
545 PyBufferProcs *pb;
546 void *ptr1, *ptr2;
547 Py_ssize_t size;
548 Py_ssize_t count;
550 if ( self->b_readonly ) {
551 PyErr_SetString(PyExc_TypeError,
552 "buffer is read-only");
553 return -1;
556 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
557 return -1;
559 if (idx < 0 || idx >= size) {
560 PyErr_SetString(PyExc_IndexError,
561 "buffer assignment index out of range");
562 return -1;
565 pb = other ? other->ob_type->tp_as_buffer : NULL;
566 if ( pb == NULL ||
567 pb->bf_getreadbuffer == NULL ||
568 pb->bf_getsegcount == NULL )
570 PyErr_BadArgument();
571 return -1;
573 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
575 /* ### use a different exception type/message? */
576 PyErr_SetString(PyExc_TypeError,
577 "single-segment buffer object expected");
578 return -1;
581 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
582 return -1;
583 if ( count != 1 ) {
584 PyErr_SetString(PyExc_TypeError,
585 "right operand must be a single byte");
586 return -1;
589 ((char *)ptr1)[idx] = *(char *)ptr2;
590 return 0;
593 static int
594 buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
596 PyBufferProcs *pb;
597 void *ptr1, *ptr2;
598 Py_ssize_t size;
599 Py_ssize_t slice_len;
600 Py_ssize_t count;
602 if ( self->b_readonly ) {
603 PyErr_SetString(PyExc_TypeError,
604 "buffer is read-only");
605 return -1;
608 pb = other ? other->ob_type->tp_as_buffer : NULL;
609 if ( pb == NULL ||
610 pb->bf_getreadbuffer == NULL ||
611 pb->bf_getsegcount == NULL )
613 PyErr_BadArgument();
614 return -1;
616 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
618 /* ### use a different exception type/message? */
619 PyErr_SetString(PyExc_TypeError,
620 "single-segment buffer object expected");
621 return -1;
623 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
624 return -1;
625 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
626 return -1;
628 if ( left < 0 )
629 left = 0;
630 else if ( left > size )
631 left = size;
632 if ( right < left )
633 right = left;
634 else if ( right > size )
635 right = size;
636 slice_len = right - left;
638 if ( count != slice_len ) {
639 PyErr_SetString(
640 PyExc_TypeError,
641 "right operand length must match slice length");
642 return -1;
645 if ( slice_len )
646 memcpy((char *)ptr1 + left, ptr2, slice_len);
648 return 0;
651 static int
652 buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
654 PyBufferProcs *pb;
655 void *ptr1, *ptr2;
656 Py_ssize_t selfsize;
657 Py_ssize_t othersize;
659 if ( self->b_readonly ) {
660 PyErr_SetString(PyExc_TypeError,
661 "buffer is read-only");
662 return -1;
665 pb = value ? value->ob_type->tp_as_buffer : NULL;
666 if ( pb == NULL ||
667 pb->bf_getreadbuffer == NULL ||
668 pb->bf_getsegcount == NULL )
670 PyErr_BadArgument();
671 return -1;
673 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
675 /* ### use a different exception type/message? */
676 PyErr_SetString(PyExc_TypeError,
677 "single-segment buffer object expected");
678 return -1;
680 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
681 return -1;
682 if (PyIndex_Check(item)) {
683 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
684 if (i == -1 && PyErr_Occurred())
685 return -1;
686 if (i < 0)
687 i += selfsize;
688 return buffer_ass_item(self, i, value);
690 else if (PySlice_Check(item)) {
691 Py_ssize_t start, stop, step, slicelength;
693 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
694 &start, &stop, &step, &slicelength) < 0)
695 return -1;
697 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
698 return -1;
700 if (othersize != slicelength) {
701 PyErr_SetString(
702 PyExc_TypeError,
703 "right operand length must match slice length");
704 return -1;
707 if (slicelength == 0)
708 return 0;
709 else if (step == 1) {
710 memcpy((char *)ptr1 + start, ptr2, slicelength);
711 return 0;
713 else {
714 Py_ssize_t cur, i;
716 for (cur = start, i = 0; i < slicelength;
717 cur += step, i++) {
718 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
721 return 0;
723 } else {
724 PyErr_SetString(PyExc_TypeError,
725 "buffer indices must be integers");
726 return -1;
730 /* Buffer methods */
732 static Py_ssize_t
733 buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
735 Py_ssize_t size;
736 if ( idx != 0 ) {
737 PyErr_SetString(PyExc_SystemError,
738 "accessing non-existent buffer segment");
739 return -1;
741 if (!get_buf(self, pp, &size, READ_BUFFER))
742 return -1;
743 return size;
746 static Py_ssize_t
747 buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
749 Py_ssize_t size;
751 if ( self->b_readonly )
753 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
754 return -1;
757 if ( idx != 0 ) {
758 PyErr_SetString(PyExc_SystemError,
759 "accessing non-existent buffer segment");
760 return -1;
762 if (!get_buf(self, pp, &size, WRITE_BUFFER))
763 return -1;
764 return size;
767 static Py_ssize_t
768 buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
770 void *ptr;
771 Py_ssize_t size;
772 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
773 return -1;
774 if (lenp)
775 *lenp = size;
776 return 1;
779 static Py_ssize_t
780 buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
782 void *ptr;
783 Py_ssize_t size;
784 if ( idx != 0 ) {
785 PyErr_SetString(PyExc_SystemError,
786 "accessing non-existent buffer segment");
787 return -1;
789 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
790 return -1;
791 *pp = (const char *)ptr;
792 return size;
795 static PySequenceMethods buffer_as_sequence = {
796 (lenfunc)buffer_length, /*sq_length*/
797 (binaryfunc)buffer_concat, /*sq_concat*/
798 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
799 (ssizeargfunc)buffer_item, /*sq_item*/
800 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
801 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
802 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
805 static PyMappingMethods buffer_as_mapping = {
806 (lenfunc)buffer_length,
807 (binaryfunc)buffer_subscript,
808 (objobjargproc)buffer_ass_subscript,
811 static PyBufferProcs buffer_as_buffer = {
812 (readbufferproc)buffer_getreadbuf,
813 (writebufferproc)buffer_getwritebuf,
814 (segcountproc)buffer_getsegcount,
815 (charbufferproc)buffer_getcharbuf,
818 PyTypeObject PyBuffer_Type = {
819 PyVarObject_HEAD_INIT(&PyType_Type, 0)
820 "buffer",
821 sizeof(PyBufferObject),
823 (destructor)buffer_dealloc, /* tp_dealloc */
824 0, /* tp_print */
825 0, /* tp_getattr */
826 0, /* tp_setattr */
827 (cmpfunc)buffer_compare, /* tp_compare */
828 (reprfunc)buffer_repr, /* tp_repr */
829 0, /* tp_as_number */
830 &buffer_as_sequence, /* tp_as_sequence */
831 &buffer_as_mapping, /* tp_as_mapping */
832 (hashfunc)buffer_hash, /* tp_hash */
833 0, /* tp_call */
834 (reprfunc)buffer_str, /* tp_str */
835 PyObject_GenericGetAttr, /* tp_getattro */
836 0, /* tp_setattro */
837 &buffer_as_buffer, /* tp_as_buffer */
838 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
839 buffer_doc, /* tp_doc */
840 0, /* tp_traverse */
841 0, /* tp_clear */
842 0, /* tp_richcompare */
843 0, /* tp_weaklistoffset */
844 0, /* tp_iter */
845 0, /* tp_iternext */
846 0, /* tp_methods */
847 0, /* tp_members */
848 0, /* tp_getset */
849 0, /* tp_base */
850 0, /* tp_dict */
851 0, /* tp_descr_get */
852 0, /* tp_descr_set */
853 0, /* tp_dictoffset */
854 0, /* tp_init */
855 0, /* tp_alloc */
856 buffer_new, /* tp_new */