Home | History | Annotate | Download | only in Objects
      1 
      2 /* Buffer object implementation */
      3 
      4 #include "Python.h"
      5 
      6 
      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;
     16 
     17 
     18 enum buffer_t {
     19     READ_BUFFER,
     20     WRITE_BUFFER,
     21     CHAR_BUFFER,
     22     ANY_BUFFER
     23 };
     24 
     25 static int
     26 get_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 (*size > count - offset)
     92             *size = count - offset;
     93     }
     94     return 1;
     95 }
     96 
     97 
     98 static PyObject *
     99 buffer_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 
    130 static PyObject *
    131 buffer_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 
    155 PyObject *
    156 PyBuffer_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 
    171 PyObject *
    172 PyBuffer_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 
    187 PyObject *
    188 PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
    189 {
    190     return buffer_from_memory(NULL, size, 0, ptr, 1);
    191 }
    192 
    193 PyObject *
    194 PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
    195 {
    196     return buffer_from_memory(NULL, size, 0, ptr, 0);
    197 }
    198 
    199 PyObject *
    200 PyBuffer_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 
    232 static PyObject *
    233 buffer_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 
    250 PyDoc_STRVAR(buffer_doc,
    251 "buffer(object [, offset[, size]])\n\
    252 \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).");
    257 
    258 
    259 static void
    260 buffer_dealloc(PyBufferObject *self)
    261 {
    262     Py_XDECREF(self->b_base);
    263     PyObject_DEL(self);
    264 }
    265 
    266 static int
    267 buffer_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 
    286 static PyObject *
    287 buffer_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 
    307 static long
    308 buffer_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     /*
    338       We make the hash of the empty buffer be 0, rather than using
    339       (prefix ^ suffix), since this slightly obfuscates the hash secret
    340     */
    341     if (len == 0) {
    342         self->b_hash = 0;
    343         return 0;
    344     }
    345     x = _Py_HashSecret.prefix;
    346     x ^= *p << 7;
    347     while (--len >= 0)
    348         x = (1000003*x) ^ *p++;
    349     x ^= size;
    350     x ^= _Py_HashSecret.suffix;
    351     if (x == -1)
    352         x = -2;
    353     self->b_hash = x;
    354     return x;
    355 }
    356 
    357 static PyObject *
    358 buffer_str(PyBufferObject *self)
    359 {
    360     void *ptr;
    361     Py_ssize_t size;
    362     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
    363         return NULL;
    364     return PyString_FromStringAndSize((const char *)ptr, size);
    365 }
    366 
    367 /* Sequence methods */
    368 
    369 static Py_ssize_t
    370 buffer_length(PyBufferObject *self)
    371 {
    372     void *ptr;
    373     Py_ssize_t size;
    374     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
    375         return -1;
    376     return size;
    377 }
    378 
    379 static PyObject *
    380 buffer_concat(PyBufferObject *self, PyObject *other)
    381 {
    382     PyBufferProcs *pb = other->ob_type->tp_as_buffer;
    383     void *ptr1, *ptr2;
    384     char *p;
    385     PyObject *ob;
    386     Py_ssize_t size, count;
    387 
    388     if ( pb == NULL ||
    389          pb->bf_getreadbuffer == NULL ||
    390          pb->bf_getsegcount == NULL )
    391     {
    392         PyErr_BadArgument();
    393         return NULL;
    394     }
    395     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
    396     {
    397         /* ### use a different exception type/message? */
    398         PyErr_SetString(PyExc_TypeError,
    399                         "single-segment buffer object expected");
    400         return NULL;
    401     }
    402 
    403     if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
    404         return NULL;
    405 
    406     /* optimize special case */
    407     if ( size == 0 )
    408     {
    409         Py_INCREF(other);
    410         return other;
    411     }
    412 
    413     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
    414         return NULL;
    415 
    416     assert(count <= PY_SIZE_MAX - size);
    417 
    418     ob = PyString_FromStringAndSize(NULL, size + count);
    419     if ( ob == NULL )
    420         return NULL;
    421     p = PyString_AS_STRING(ob);
    422     memcpy(p, ptr1, size);
    423     memcpy(p + size, ptr2, count);
    424 
    425     /* there is an extra byte in the string object, so this is safe */
    426     p[size + count] = '\0';
    427 
    428     return ob;
    429 }
    430 
    431 static PyObject *
    432 buffer_repeat(PyBufferObject *self, Py_ssize_t count)
    433 {
    434     PyObject *ob;
    435     register char *p;
    436     void *ptr;
    437     Py_ssize_t size;
    438 
    439     if ( count < 0 )
    440         count = 0;
    441     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
    442         return NULL;
    443     if (count > PY_SSIZE_T_MAX / size) {
    444         PyErr_SetString(PyExc_MemoryError, "result too large");
    445         return NULL;
    446     }
    447     ob = PyString_FromStringAndSize(NULL, size * count);
    448     if ( ob == NULL )
    449         return NULL;
    450 
    451     p = PyString_AS_STRING(ob);
    452     while ( count-- )
    453     {
    454         memcpy(p, ptr, size);
    455         p += size;
    456     }
    457 
    458     /* there is an extra byte in the string object, so this is safe */
    459     *p = '\0';
    460 
    461     return ob;
    462 }
    463 
    464 static PyObject *
    465 buffer_item(PyBufferObject *self, Py_ssize_t idx)
    466 {
    467     void *ptr;
    468     Py_ssize_t size;
    469     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
    470         return NULL;
    471     if ( idx < 0 || idx >= size ) {
    472         PyErr_SetString(PyExc_IndexError, "buffer index out of range");
    473         return NULL;
    474     }
    475     return PyString_FromStringAndSize((char *)ptr + idx, 1);
    476 }
    477 
    478 static PyObject *
    479 buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
    480 {
    481     void *ptr;
    482     Py_ssize_t size;
    483     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
    484         return NULL;
    485     if ( left < 0 )
    486         left = 0;
    487     if ( right < 0 )
    488         right = 0;
    489     if ( right > size )
    490         right = size;
    491     if ( right < left )
    492         right = left;
    493     return PyString_FromStringAndSize((char *)ptr + left,
    494                                       right - left);
    495 }
    496 
    497 static PyObject *
    498 buffer_subscript(PyBufferObject *self, PyObject *item)
    499 {
    500     void *p;
    501     Py_ssize_t size;
    502 
    503     if (!get_buf(self, &p, &size, ANY_BUFFER))
    504         return NULL;
    505     if (PyIndex_Check(item)) {
    506         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
    507         if (i == -1 && PyErr_Occurred())
    508             return NULL;
    509         if (i < 0)
    510             i += size;
    511         return buffer_item(self, i);
    512     }
    513     else if (PySlice_Check(item)) {
    514         Py_ssize_t start, stop, step, slicelength, cur, i;
    515 
    516         if (PySlice_GetIndicesEx((PySliceObject*)item, size,
    517                          &start, &stop, &step, &slicelength) < 0) {
    518             return NULL;
    519         }
    520 
    521         if (slicelength <= 0)
    522             return PyString_FromStringAndSize("", 0);
    523         else if (step == 1)
    524             return PyString_FromStringAndSize((char *)p + start,
    525                                               stop - start);
    526         else {
    527             PyObject *result;
    528             char *source_buf = (char *)p;
    529             char *result_buf = (char *)PyMem_Malloc(slicelength);
    530 
    531             if (result_buf == NULL)
    532                 return PyErr_NoMemory();
    533 
    534             for (cur = start, i = 0; i < slicelength;
    535                  cur += step, i++) {
    536                 result_buf[i] = source_buf[cur];
    537             }
    538 
    539             result = PyString_FromStringAndSize(result_buf,
    540                                                 slicelength);
    541             PyMem_Free(result_buf);
    542             return result;
    543         }
    544     }
    545     else {
    546         PyErr_SetString(PyExc_TypeError,
    547                         "sequence index must be integer");
    548         return NULL;
    549     }
    550 }
    551 
    552 static int
    553 buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
    554 {
    555     PyBufferProcs *pb;
    556     void *ptr1, *ptr2;
    557     Py_ssize_t size;
    558     Py_ssize_t count;
    559 
    560     if ( self->b_readonly ) {
    561         PyErr_SetString(PyExc_TypeError,
    562                         "buffer is read-only");
    563         return -1;
    564     }
    565 
    566     if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
    567         return -1;
    568 
    569     if (idx < 0 || idx >= size) {
    570         PyErr_SetString(PyExc_IndexError,
    571                         "buffer assignment index out of range");
    572         return -1;
    573     }
    574 
    575     pb = other ? other->ob_type->tp_as_buffer : NULL;
    576     if ( pb == NULL ||
    577          pb->bf_getreadbuffer == NULL ||
    578          pb->bf_getsegcount == NULL )
    579     {
    580         PyErr_BadArgument();
    581         return -1;
    582     }
    583     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
    584     {
    585         /* ### use a different exception type/message? */
    586         PyErr_SetString(PyExc_TypeError,
    587                         "single-segment buffer object expected");
    588         return -1;
    589     }
    590 
    591     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
    592         return -1;
    593     if ( count != 1 ) {
    594         PyErr_SetString(PyExc_TypeError,
    595                         "right operand must be a single byte");
    596         return -1;
    597     }
    598 
    599     ((char *)ptr1)[idx] = *(char *)ptr2;
    600     return 0;
    601 }
    602 
    603 static int
    604 buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
    605 {
    606     PyBufferProcs *pb;
    607     void *ptr1, *ptr2;
    608     Py_ssize_t size;
    609     Py_ssize_t slice_len;
    610     Py_ssize_t count;
    611 
    612     if ( self->b_readonly ) {
    613         PyErr_SetString(PyExc_TypeError,
    614                         "buffer is read-only");
    615         return -1;
    616     }
    617 
    618     pb = other ? other->ob_type->tp_as_buffer : NULL;
    619     if ( pb == NULL ||
    620          pb->bf_getreadbuffer == NULL ||
    621          pb->bf_getsegcount == NULL )
    622     {
    623         PyErr_BadArgument();
    624         return -1;
    625     }
    626     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
    627     {
    628         /* ### use a different exception type/message? */
    629         PyErr_SetString(PyExc_TypeError,
    630                         "single-segment buffer object expected");
    631         return -1;
    632     }
    633     if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
    634         return -1;
    635     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
    636         return -1;
    637 
    638     if ( left < 0 )
    639         left = 0;
    640     else if ( left > size )
    641         left = size;
    642     if ( right < left )
    643         right = left;
    644     else if ( right > size )
    645         right = size;
    646     slice_len = right - left;
    647 
    648     if ( count != slice_len ) {
    649         PyErr_SetString(
    650             PyExc_TypeError,
    651             "right operand length must match slice length");
    652         return -1;
    653     }
    654 
    655     if ( slice_len )
    656         memcpy((char *)ptr1 + left, ptr2, slice_len);
    657 
    658     return 0;
    659 }
    660 
    661 static int
    662 buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
    663 {
    664     PyBufferProcs *pb;
    665     void *ptr1, *ptr2;
    666     Py_ssize_t selfsize;
    667     Py_ssize_t othersize;
    668 
    669     if ( self->b_readonly ) {
    670         PyErr_SetString(PyExc_TypeError,
    671                         "buffer is read-only");
    672         return -1;
    673     }
    674 
    675     pb = value ? value->ob_type->tp_as_buffer : NULL;
    676     if ( pb == NULL ||
    677          pb->bf_getreadbuffer == NULL ||
    678          pb->bf_getsegcount == NULL )
    679     {
    680         PyErr_BadArgument();
    681         return -1;
    682     }
    683     if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
    684     {
    685         /* ### use a different exception type/message? */
    686         PyErr_SetString(PyExc_TypeError,
    687                         "single-segment buffer object expected");
    688         return -1;
    689     }
    690     if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
    691         return -1;
    692     if (PyIndex_Check(item)) {
    693         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
    694         if (i == -1 && PyErr_Occurred())
    695             return -1;
    696         if (i < 0)
    697             i += selfsize;
    698         return buffer_ass_item(self, i, value);
    699     }
    700     else if (PySlice_Check(item)) {
    701         Py_ssize_t start, stop, step, slicelength;
    702 
    703         if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
    704                         &start, &stop, &step, &slicelength) < 0)
    705             return -1;
    706 
    707         if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
    708             return -1;
    709 
    710         if (othersize != slicelength) {
    711             PyErr_SetString(
    712                 PyExc_TypeError,
    713                 "right operand length must match slice length");
    714             return -1;
    715         }
    716 
    717         if (slicelength == 0)
    718             return 0;
    719         else if (step == 1) {
    720             memcpy((char *)ptr1 + start, ptr2, slicelength);
    721             return 0;
    722         }
    723         else {
    724             Py_ssize_t cur, i;
    725 
    726             for (cur = start, i = 0; i < slicelength;
    727                  cur += step, i++) {
    728                 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
    729             }
    730 
    731             return 0;
    732         }
    733     } else {
    734         PyErr_SetString(PyExc_TypeError,
    735                         "buffer indices must be integers");
    736         return -1;
    737     }
    738 }
    739 
    740 /* Buffer methods */
    741 
    742 static Py_ssize_t
    743 buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
    744 {
    745     Py_ssize_t size;
    746     if ( idx != 0 ) {
    747         PyErr_SetString(PyExc_SystemError,
    748                         "accessing non-existent buffer segment");
    749         return -1;
    750     }
    751     if (!get_buf(self, pp, &size, READ_BUFFER))
    752         return -1;
    753     return size;
    754 }
    755 
    756 static Py_ssize_t
    757 buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
    758 {
    759     Py_ssize_t size;
    760 
    761     if ( self->b_readonly )
    762     {
    763         PyErr_SetString(PyExc_TypeError, "buffer is read-only");
    764         return -1;
    765     }
    766 
    767     if ( idx != 0 ) {
    768         PyErr_SetString(PyExc_SystemError,
    769                         "accessing non-existent buffer segment");
    770         return -1;
    771     }
    772     if (!get_buf(self, pp, &size, WRITE_BUFFER))
    773         return -1;
    774     return size;
    775 }
    776 
    777 static Py_ssize_t
    778 buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
    779 {
    780     void *ptr;
    781     Py_ssize_t size;
    782     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
    783         return -1;
    784     if (lenp)
    785         *lenp = size;
    786     return 1;
    787 }
    788 
    789 static Py_ssize_t
    790 buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
    791 {
    792     void *ptr;
    793     Py_ssize_t size;
    794     if ( idx != 0 ) {
    795         PyErr_SetString(PyExc_SystemError,
    796                         "accessing non-existent buffer segment");
    797         return -1;
    798     }
    799     if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
    800         return -1;
    801     *pp = (const char *)ptr;
    802     return size;
    803 }
    804 
    805 static int buffer_getbuffer(PyBufferObject *self, Py_buffer *buf, int flags)
    806 {
    807     void *ptr;
    808     Py_ssize_t size;
    809     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
    810         return -1;
    811     return PyBuffer_FillInfo(buf, (PyObject*)self, ptr, size,
    812                              self->b_readonly, flags);
    813 }
    814 
    815 static PySequenceMethods buffer_as_sequence = {
    816     (lenfunc)buffer_length, /*sq_length*/
    817     (binaryfunc)buffer_concat, /*sq_concat*/
    818     (ssizeargfunc)buffer_repeat, /*sq_repeat*/
    819     (ssizeargfunc)buffer_item, /*sq_item*/
    820     (ssizessizeargfunc)buffer_slice, /*sq_slice*/
    821     (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
    822     (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
    823 };
    824 
    825 static PyMappingMethods buffer_as_mapping = {
    826     (lenfunc)buffer_length,
    827     (binaryfunc)buffer_subscript,
    828     (objobjargproc)buffer_ass_subscript,
    829 };
    830 
    831 static PyBufferProcs buffer_as_buffer = {
    832     (readbufferproc)buffer_getreadbuf,
    833     (writebufferproc)buffer_getwritebuf,
    834     (segcountproc)buffer_getsegcount,
    835     (charbufferproc)buffer_getcharbuf,
    836     (getbufferproc)buffer_getbuffer,
    837 };
    838 
    839 PyTypeObject PyBuffer_Type = {
    840     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    841     "buffer",
    842     sizeof(PyBufferObject),
    843     0,
    844     (destructor)buffer_dealloc,                 /* tp_dealloc */
    845     0,                                          /* tp_print */
    846     0,                                          /* tp_getattr */
    847     0,                                          /* tp_setattr */
    848     (cmpfunc)buffer_compare,                    /* tp_compare */
    849     (reprfunc)buffer_repr,                      /* tp_repr */
    850     0,                                          /* tp_as_number */
    851     &buffer_as_sequence,                        /* tp_as_sequence */
    852     &buffer_as_mapping,                         /* tp_as_mapping */
    853     (hashfunc)buffer_hash,                      /* tp_hash */
    854     0,                                          /* tp_call */
    855     (reprfunc)buffer_str,                       /* tp_str */
    856     PyObject_GenericGetAttr,                    /* tp_getattro */
    857     0,                                          /* tp_setattro */
    858     &buffer_as_buffer,                          /* tp_as_buffer */
    859     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */
    860     buffer_doc,                                 /* tp_doc */
    861     0,                                          /* tp_traverse */
    862     0,                                          /* tp_clear */
    863     0,                                          /* tp_richcompare */
    864     0,                                          /* tp_weaklistoffset */
    865     0,                                          /* tp_iter */
    866     0,                                          /* tp_iternext */
    867     0,                                          /* tp_methods */
    868     0,                                          /* tp_members */
    869     0,                                          /* tp_getset */
    870     0,                                          /* tp_base */
    871     0,                                          /* tp_dict */
    872     0,                                          /* tp_descr_get */
    873     0,                                          /* tp_descr_set */
    874     0,                                          /* tp_dictoffset */
    875     0,                                          /* tp_init */
    876     0,                                          /* tp_alloc */
    877     buffer_new,                                 /* tp_new */
    878 };
    879