1
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    Py_ssize_t b_size;
12    Py_ssize_t b_offset;
13    int b_readonly;
14    long b_hash;
15} PyBufferObject;
16
17
18enum buffer_t {
19    READ_BUFFER,
20    WRITE_BUFFER,
21    CHAR_BUFFER,
22    ANY_BUFFER
23};
24
25static int
26get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
27    enum buffer_t buffer_type)
28{
29    if (self->b_base == NULL) {
30        assert (ptr != NULL);
31        *ptr = self->b_ptr;
32        *size = self->b_size;
33    }
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;
42        }
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;
55            }
56            proc = (readbufferproc)bp->bf_getcharbuffer;
57        }
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;
73            }
74            PyErr_Format(PyExc_TypeError,
75                "%s buffer type not available",
76                buffer_type_name);
77            return 0;
78        }
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;
93    }
94    return 1;
95}
96
97
98static PyObject *
99buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
100                   int readonly)
101{
102    PyBufferObject * b;
103
104    if (size < 0 && size != Py_END_OF_BUFFER) {
105        PyErr_SetString(PyExc_ValueError,
106                        "size must be zero or positive");
107        return NULL;
108    }
109    if (offset < 0) {
110        PyErr_SetString(PyExc_ValueError,
111                        "offset must be zero or positive");
112        return NULL;
113    }
114
115    b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116    if ( b == NULL )
117        return NULL;
118
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;
126
127    return (PyObject *) b;
128}
129
130static PyObject *
131buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
132{
133    if (offset < 0) {
134        PyErr_SetString(PyExc_ValueError,
135                        "offset must be zero or positive");
136        return NULL;
137    }
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;
147        }
148        offset += b->b_offset;
149        base = b->b_base;
150    }
151    return buffer_from_memory(base, size, offset, NULL, readonly);
152}
153
154
155PyObject *
156PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
157{
158    PyBufferProcs *pb = base->ob_type->tp_as_buffer;
159
160    if ( pb == NULL ||
161         pb->bf_getreadbuffer == NULL ||
162         pb->bf_getsegcount == NULL )
163    {
164        PyErr_SetString(PyExc_TypeError, "buffer object expected");
165        return NULL;
166    }
167
168    return buffer_from_object(base, size, offset, 1);
169}
170
171PyObject *
172PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
173{
174    PyBufferProcs *pb = base->ob_type->tp_as_buffer;
175
176    if ( pb == NULL ||
177         pb->bf_getwritebuffer == NULL ||
178         pb->bf_getsegcount == NULL )
179    {
180        PyErr_SetString(PyExc_TypeError, "buffer object expected");
181        return NULL;
182    }
183
184    return buffer_from_object(base, size,  offset, 0);
185}
186
187PyObject *
188PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
189{
190    return buffer_from_memory(NULL, size, 0, ptr, 1);
191}
192
193PyObject *
194PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
195{
196    return buffer_from_memory(NULL, size, 0, ptr, 0);
197}
198
199PyObject *
200PyBuffer_New(Py_ssize_t size)
201{
202    PyObject *o;
203    PyBufferObject * b;
204
205    if (size < 0) {
206        PyErr_SetString(PyExc_ValueError,
207                        "size must be zero or positive");
208        return NULL;
209    }
210    if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
211        /* unlikely */
212        return PyErr_NoMemory();
213    }
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);
219
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;
226
227    return o;
228}
229
230/* Methods */
231
232static PyObject *
233buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
234{
235    PyObject *ob;
236    Py_ssize_t offset = 0;
237    Py_ssize_t size = Py_END_OF_BUFFER;
238
239    if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
240        return NULL;
241
242    if (!_PyArg_NoKeywords("buffer()", kw))
243        return NULL;
244
245    if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
246        return NULL;
247    return PyBuffer_FromObject(ob, offset, size);
248}
249
250PyDoc_STRVAR(buffer_doc,
251"buffer(object [, offset[, size]])\n\
252\n\
253Create a new buffer object which references the given object.\n\
254The buffer will reference a slice of the target object from the\n\
255start of the object (or at the specified offset). The slice will\n\
256extend to the end of the target object (or with the specified size).");
257
258
259static void
260buffer_dealloc(PyBufferObject *self)
261{
262    Py_XDECREF(self->b_base);
263    PyObject_DEL(self);
264}
265
266static int
267buffer_compare(PyBufferObject *self, PyBufferObject *other)
268{
269    void *p1, *p2;
270    Py_ssize_t len_self, len_other, min_len;
271    int cmp;
272
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;
282    }
283    return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
284}
285
286static PyObject *
287buffer_repr(PyBufferObject *self)
288{
289    const char *status = self->b_readonly ? "read-only" : "read-write";
290
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);
305}
306
307static long
308buffer_hash(PyBufferObject *self)
309{
310    void *ptr;
311    Py_ssize_t size;
312    register Py_ssize_t len;
313    register unsigned char *p;
314    register long x;
315
316    if ( self->b_hash != -1 )
317        return self->b_hash;
318
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 )
327    {
328        PyErr_SetString(PyExc_TypeError,
329                        "writable buffers are not hashable");
330        return -1;
331    }
332
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;
345}
346
347static PyObject *
348buffer_str(PyBufferObject *self)
349{
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);
355}
356
357/* Sequence methods */
358
359static Py_ssize_t
360buffer_length(PyBufferObject *self)
361{
362    void *ptr;
363    Py_ssize_t size;
364    if (!get_buf(self, &ptr, &size, ANY_BUFFER))
365        return -1;
366    return size;
367}
368
369static PyObject *
370buffer_concat(PyBufferObject *self, PyObject *other)
371{
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;
377
378    if ( pb == NULL ||
379         pb->bf_getreadbuffer == NULL ||
380         pb->bf_getsegcount == NULL )
381    {
382        PyErr_BadArgument();
383        return NULL;
384    }
385    if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
386    {
387        /* ### use a different exception type/message? */
388        PyErr_SetString(PyExc_TypeError,
389                        "single-segment buffer object expected");
390        return NULL;
391    }
392
393    if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
394        return NULL;
395
396    /* optimize special case */
397    if ( size == 0 )
398    {
399        Py_INCREF(other);
400        return other;
401    }
402
403    if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
404        return NULL;
405
406    assert(count <= PY_SIZE_MAX - size);
407
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);
414
415    /* there is an extra byte in the string object, so this is safe */
416    p[size + count] = '\0';
417
418    return ob;
419}
420
421static PyObject *
422buffer_repeat(PyBufferObject *self, Py_ssize_t count)
423{
424    PyObject *ob;
425    register char *p;
426    void *ptr;
427    Py_ssize_t size;
428
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;
436    }
437    ob = PyString_FromStringAndSize(NULL, size * count);
438    if ( ob == NULL )
439        return NULL;
440
441    p = PyString_AS_STRING(ob);
442    while ( count-- )
443    {
444        memcpy(p, ptr, size);
445        p += size;
446    }
447
448    /* there is an extra byte in the string object, so this is safe */
449    *p = '\0';
450
451    return ob;
452}
453
454static PyObject *
455buffer_item(PyBufferObject *self, Py_ssize_t idx)
456{
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;
464    }
465    return PyString_FromStringAndSize((char *)ptr + idx, 1);
466}
467
468static PyObject *
469buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
470{
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);
485}
486
487static PyObject *
488buffer_subscript(PyBufferObject *self, PyObject *item)
489{
490    void *p;
491    Py_ssize_t size;
492
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);
502    }
503    else if (PySlice_Check(item)) {
504        Py_ssize_t start, stop, step, slicelength, cur, i;
505
506        if (PySlice_GetIndicesEx((PySliceObject*)item, size,
507                         &start, &stop, &step, &slicelength) < 0) {
508            return NULL;
509        }
510
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);
520
521            if (result_buf == NULL)
522                return PyErr_NoMemory();
523
524            for (cur = start, i = 0; i < slicelength;
525                 cur += step, i++) {
526                result_buf[i] = source_buf[cur];
527            }
528
529            result = PyString_FromStringAndSize(result_buf,
530                                                slicelength);
531            PyMem_Free(result_buf);
532            return result;
533        }
534    }
535    else {
536        PyErr_SetString(PyExc_TypeError,
537                        "sequence index must be integer");
538        return NULL;
539    }
540}
541
542static int
543buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
544{
545    PyBufferProcs *pb;
546    void *ptr1, *ptr2;
547    Py_ssize_t size;
548    Py_ssize_t count;
549
550    if ( self->b_readonly ) {
551        PyErr_SetString(PyExc_TypeError,
552                        "buffer is read-only");
553        return -1;
554    }
555
556    if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
557        return -1;
558
559    if (idx < 0 || idx >= size) {
560        PyErr_SetString(PyExc_IndexError,
561                        "buffer assignment index out of range");
562        return -1;
563    }
564
565    pb = other ? other->ob_type->tp_as_buffer : NULL;
566    if ( pb == NULL ||
567         pb->bf_getreadbuffer == NULL ||
568         pb->bf_getsegcount == NULL )
569    {
570        PyErr_BadArgument();
571        return -1;
572    }
573    if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
574    {
575        /* ### use a different exception type/message? */
576        PyErr_SetString(PyExc_TypeError,
577                        "single-segment buffer object expected");
578        return -1;
579    }
580
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;
587    }
588
589    ((char *)ptr1)[idx] = *(char *)ptr2;
590    return 0;
591}
592
593static int
594buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
595{
596    PyBufferProcs *pb;
597    void *ptr1, *ptr2;
598    Py_ssize_t size;
599    Py_ssize_t slice_len;
600    Py_ssize_t count;
601
602    if ( self->b_readonly ) {
603        PyErr_SetString(PyExc_TypeError,
604                        "buffer is read-only");
605        return -1;
606    }
607
608    pb = other ? other->ob_type->tp_as_buffer : NULL;
609    if ( pb == NULL ||
610         pb->bf_getreadbuffer == NULL ||
611         pb->bf_getsegcount == NULL )
612    {
613        PyErr_BadArgument();
614        return -1;
615    }
616    if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
617    {
618        /* ### use a different exception type/message? */
619        PyErr_SetString(PyExc_TypeError,
620                        "single-segment buffer object expected");
621        return -1;
622    }
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;
627
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;
637
638    if ( count != slice_len ) {
639        PyErr_SetString(
640            PyExc_TypeError,
641            "right operand length must match slice length");
642        return -1;
643    }
644
645    if ( slice_len )
646        memcpy((char *)ptr1 + left, ptr2, slice_len);
647
648    return 0;
649}
650
651static int
652buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
653{
654    PyBufferProcs *pb;
655    void *ptr1, *ptr2;
656    Py_ssize_t selfsize;
657    Py_ssize_t othersize;
658
659    if ( self->b_readonly ) {
660        PyErr_SetString(PyExc_TypeError,
661                        "buffer is read-only");
662        return -1;
663    }
664
665    pb = value ? value->ob_type->tp_as_buffer : NULL;
666    if ( pb == NULL ||
667         pb->bf_getreadbuffer == NULL ||
668         pb->bf_getsegcount == NULL )
669    {
670        PyErr_BadArgument();
671        return -1;
672    }
673    if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
674    {
675        /* ### use a different exception type/message? */
676        PyErr_SetString(PyExc_TypeError,
677                        "single-segment buffer object expected");
678        return -1;
679    }
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);
689    }
690    else if (PySlice_Check(item)) {
691        Py_ssize_t start, stop, step, slicelength;
692
693        if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
694                        &start, &stop, &step, &slicelength) < 0)
695            return -1;
696
697        if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
698            return -1;
699
700        if (othersize != slicelength) {
701            PyErr_SetString(
702                PyExc_TypeError,
703                "right operand length must match slice length");
704            return -1;
705        }
706
707        if (slicelength == 0)
708            return 0;
709        else if (step == 1) {
710            memcpy((char *)ptr1 + start, ptr2, slicelength);
711            return 0;
712        }
713        else {
714            Py_ssize_t cur, i;
715
716            for (cur = start, i = 0; i < slicelength;
717                 cur += step, i++) {
718                ((char *)ptr1)[cur] = ((char *)ptr2)[i];
719            }
720
721            return 0;
722        }
723    } else {
724        PyErr_SetString(PyExc_TypeError,
725                        "buffer indices must be integers");
726        return -1;
727    }
728}
729
730/* Buffer methods */
731
732static Py_ssize_t
733buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
734{
735    Py_ssize_t size;
736    if ( idx != 0 ) {
737        PyErr_SetString(PyExc_SystemError,
738                        "accessing non-existent buffer segment");
739        return -1;
740    }
741    if (!get_buf(self, pp, &size, READ_BUFFER))
742        return -1;
743    return size;
744}
745
746static Py_ssize_t
747buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
748{
749    Py_ssize_t size;
750
751    if ( self->b_readonly )
752    {
753        PyErr_SetString(PyExc_TypeError, "buffer is read-only");
754        return -1;
755    }
756
757    if ( idx != 0 ) {
758        PyErr_SetString(PyExc_SystemError,
759                        "accessing non-existent buffer segment");
760        return -1;
761    }
762    if (!get_buf(self, pp, &size, WRITE_BUFFER))
763        return -1;
764    return size;
765}
766
767static Py_ssize_t
768buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
769{
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;
777}
778
779static Py_ssize_t
780buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
781{
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;
788    }
789    if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
790        return -1;
791    *pp = (const char *)ptr;
792    return size;
793}
794
795static 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*/
803};
804
805static PyMappingMethods buffer_as_mapping = {
806    (lenfunc)buffer_length,
807    (binaryfunc)buffer_subscript,
808    (objobjargproc)buffer_ass_subscript,
809};
810
811static PyBufferProcs buffer_as_buffer = {
812    (readbufferproc)buffer_getreadbuf,
813    (writebufferproc)buffer_getwritebuf,
814    (segcountproc)buffer_getsegcount,
815    (charbufferproc)buffer_getcharbuf,
816};
817
818PyTypeObject PyBuffer_Type = {
819    PyVarObject_HEAD_INIT(&PyType_Type, 0)
820    "buffer",
821    sizeof(PyBufferObject),
822    0,
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 */
857};
858