Python-2.7.3/Objects/bufferobject.c

No issues found

  1 /* Buffer object implementation */
  2 
  3 #include "Python.h"
  4 
  5 
  6 typedef struct {
  7     PyObject_HEAD
  8     PyObject *b_base;
  9     void *b_ptr;
 10     Py_ssize_t b_size;
 11     Py_ssize_t b_offset;
 12     int b_readonly;
 13     long b_hash;
 14 } PyBufferObject;
 15 
 16 
 17 enum buffer_t {
 18     READ_BUFFER,
 19     WRITE_BUFFER,
 20     CHAR_BUFFER,
 21     ANY_BUFFER
 22 };
 23 
 24 static int
 25 get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
 26     enum buffer_t buffer_type)
 27 {
 28     if (self->b_base == NULL) {
 29         assert (ptr != NULL);
 30         *ptr = self->b_ptr;
 31         *size = self->b_size;
 32     }
 33     else {
 34         Py_ssize_t count, offset;
 35         readbufferproc proc = 0;
 36         PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
 37         if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
 38             PyErr_SetString(PyExc_TypeError,
 39                 "single-segment buffer object expected");
 40             return 0;
 41         }
 42         if ((buffer_type == READ_BUFFER) ||
 43             ((buffer_type == ANY_BUFFER) && self->b_readonly))
 44             proc = bp->bf_getreadbuffer;
 45         else if ((buffer_type == WRITE_BUFFER) ||
 46             (buffer_type == ANY_BUFFER))
 47             proc = (readbufferproc)bp->bf_getwritebuffer;
 48         else if (buffer_type == CHAR_BUFFER) {
 49             if (!PyType_HasFeature(self->ob_type,
 50                         Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
 51             PyErr_SetString(PyExc_TypeError,
 52                 "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
 53             return 0;
 54             }
 55             proc = (readbufferproc)bp->bf_getcharbuffer;
 56         }
 57         if (!proc) {
 58             char *buffer_type_name;
 59             switch (buffer_type) {
 60             case READ_BUFFER:
 61                 buffer_type_name = "read";
 62                 break;
 63             case WRITE_BUFFER:
 64                 buffer_type_name = "write";
 65                 break;
 66             case CHAR_BUFFER:
 67                 buffer_type_name = "char";
 68                 break;
 69             default:
 70                 buffer_type_name = "no";
 71                 break;
 72             }
 73             PyErr_Format(PyExc_TypeError,
 74                 "%s buffer type not available",
 75                 buffer_type_name);
 76             return 0;
 77         }
 78         if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
 79             return 0;
 80         /* apply constraints to the start/end */
 81         if (self->b_offset > count)
 82             offset = count;
 83         else
 84             offset = self->b_offset;
 85         *(char **)ptr = *(char **)ptr + offset;
 86         if (self->b_size == Py_END_OF_BUFFER)
 87             *size = count;
 88         else
 89             *size = self->b_size;
 90         if (offset + *size > count)
 91             *size = count - offset;
 92     }
 93     return 1;
 94 }
 95 
 96 
 97 static PyObject *
 98 buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
 99                    int readonly)
100 {
101     PyBufferObject * b;
102 
103     if (size < 0 && size != Py_END_OF_BUFFER) {
104         PyErr_SetString(PyExc_ValueError,
105                         "size must be zero or positive");
106         return NULL;
107     }
108     if (offset < 0) {
109         PyErr_SetString(PyExc_ValueError,
110                         "offset must be zero or positive");
111         return NULL;
112     }
113 
114     b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
115     if ( b == NULL )
116         return NULL;
117 
118     Py_XINCREF(base);
119     b->b_base = base;
120     b->b_ptr = ptr;
121     b->b_size = size;
122     b->b_offset = offset;
123     b->b_readonly = readonly;
124     b->b_hash = -1;
125 
126     return (PyObject *) b;
127 }
128 
129 static PyObject *
130 buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
131 {
132     if (offset < 0) {
133         PyErr_SetString(PyExc_ValueError,
134                         "offset must be zero or positive");
135         return NULL;
136     }
137     if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
138         /* another buffer, refer to the base object */
139         PyBufferObject *b = (PyBufferObject *)base;
140         if (b->b_size != Py_END_OF_BUFFER) {
141             Py_ssize_t base_size = b->b_size - offset;
142             if (base_size < 0)
143                 base_size = 0;
144             if (size == Py_END_OF_BUFFER || size > base_size)
145                 size = base_size;
146         }
147         offset += b->b_offset;
148         base = b->b_base;
149     }
150     return buffer_from_memory(base, size, offset, NULL, readonly);
151 }
152 
153 
154 PyObject *
155 PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
156 {
157     PyBufferProcs *pb = base->ob_type->tp_as_buffer;
158 
159     if ( pb == NULL ||
160          pb->bf_getreadbuffer == NULL ||
161          pb->bf_getsegcount == NULL )
162     {
163         PyErr_SetString(PyExc_TypeError, "buffer object expected");
164         return NULL;
165     }
166 
167     return buffer_from_object(base, size, offset, 1);
168 }
169 
170 PyObject *
171 PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
172 {
173     PyBufferProcs *pb = base->ob_type->tp_as_buffer;
174 
175     if ( pb == NULL ||
176          pb->bf_getwritebuffer == NULL ||
177          pb->bf_getsegcount == NULL )
178     {
179         PyErr_SetString(PyExc_TypeError, "buffer object expected");
180         return NULL;
181     }
182 
183     return buffer_from_object(base, size,  offset, 0);
184 }
185 
186 PyObject *
187 PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
188 {
189     return buffer_from_memory(NULL, size, 0, ptr, 1);
190 }
191 
192 PyObject *
193 PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
194 {
195     return buffer_from_memory(NULL, size, 0, ptr, 0);
196 }
197 
198 PyObject *
199 PyBuffer_New(Py_ssize_t size)
200 {
201     PyObject *o;
202     PyBufferObject * b;
203 
204     if (size < 0) {
205         PyErr_SetString(PyExc_ValueError,
206                         "size must be zero or positive");
207         return NULL;
208     }
209     if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
210         /* unlikely */
211         return PyErr_NoMemory();
212     }
213     /* Inline PyObject_New */
214     o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
215     if ( o == NULL )
216         return PyErr_NoMemory();
217     b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
218 
219     b->b_base = NULL;
220     b->b_ptr = (void *)(b + 1);
221     b->b_size = size;
222     b->b_offset = 0;
223     b->b_readonly = 0;
224     b->b_hash = -1;
225 
226     return o;
227 }
228 
229 /* Methods */
230 
231 static PyObject *
232 buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
233 {
234     PyObject *ob;
235     Py_ssize_t offset = 0;
236     Py_ssize_t size = Py_END_OF_BUFFER;
237 
238     if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
239         return NULL;
240 
241     if (!_PyArg_NoKeywords("buffer()", kw))
242         return NULL;
243 
244     if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
245         return NULL;
246     return PyBuffer_FromObject(ob, offset, size);
247 }
248 
249 PyDoc_STRVAR(buffer_doc,
250 "buffer(object [, offset[, size]])\n\
251 \n\
252 Create a new buffer object which references the given object.\n\
253 The buffer will reference a slice of the target object from the\n\
254 start of the object (or at the specified offset). The slice will\n\
255 extend to the end of the target object (or with the specified size).");
256 
257 
258 static void
259 buffer_dealloc(PyBufferObject *self)
260 {
261     Py_XDECREF(self->b_base);
262     PyObject_DEL(self);
263 }
264 
265 static int
266 buffer_compare(PyBufferObject *self, PyBufferObject *other)
267 {
268     void *p1, *p2;
269     Py_ssize_t len_self, len_other, min_len;
270     int cmp;
271 
272     if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
273         return -1;
274     if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
275         return -1;
276     min_len = (len_self < len_other) ? len_self : len_other;
277     if (min_len > 0) {
278         cmp = memcmp(p1, p2, min_len);
279         if (cmp != 0)
280             return cmp < 0 ? -1 : 1;
281     }
282     return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
283 }
284 
285 static PyObject *
286 buffer_repr(PyBufferObject *self)
287 {
288     const char *status = self->b_readonly ? "read-only" : "read-write";
289 
290     if ( self->b_base == NULL )
291         return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
292                                    status,
293                                    self->b_ptr,
294                                    self->b_size,
295                                    self);
296     else
297         return PyString_FromFormat(
298             "<%s buffer for %p, size %zd, offset %zd at %p>",
299             status,
300             self->b_base,
301             self->b_size,
302             self->b_offset,
303             self);
304 }
305 
306 static long
307 buffer_hash(PyBufferObject *self)
308 {
309     void *ptr;
310     Py_ssize_t size;
311     register Py_ssize_t len;
312     register unsigned char *p;
313     register long x;
314 
315     if ( self->b_hash != -1 )
316         return self->b_hash;
317 
318     /* XXX potential bugs here, a readonly buffer does not imply that the
319      * underlying memory is immutable.  b_readonly is a necessary but not
320      * sufficient condition for a buffer to be hashable.  Perhaps it would
321      * be better to only allow hashing if the underlying object is known to
322      * be immutable (e.g. PyString_Check() is true).  Another idea would
323      * be to call tp_hash on the underlying object and see if it raises
324      * an error. */
325     if ( !self->b_readonly )
326     {
327         PyErr_SetString(PyExc_TypeError,
328                         "writable buffers are not hashable");
329         return -1;
330     }
331 
332     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
333         return -1;
334     p = (unsigned char *) ptr;
335     len = size;
336     /*
337       We make the hash of the empty buffer be 0, rather than using
338       (prefix ^ suffix), since this slightly obfuscates the hash secret
339     */
340     if (len == 0) {
341         self->b_hash = 0;
342         return 0;
343     }
344     x = _Py_HashSecret.prefix;
345     x ^= *p << 7;
346     while (--len >= 0)
347         x = (1000003*x) ^ *p++;
348     x ^= size;
349     x ^= _Py_HashSecret.suffix;
350     if (x == -1)
351         x = -2;
352     self->b_hash = x;
353     return x;
354 }
355 
356 static PyObject *
357 buffer_str(PyBufferObject *self)
358 {
359     void *ptr;
360     Py_ssize_t size;
361     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
362         return NULL;
363     return PyString_FromStringAndSize((const char *)ptr, size);
364 }
365 
366 /* Sequence methods */
367 
368 static Py_ssize_t
369 buffer_length(PyBufferObject *self)
370 {
371     void *ptr;
372     Py_ssize_t size;
373     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
374         return -1;
375     return size;
376 }
377 
378 static PyObject *
379 buffer_concat(PyBufferObject *self, PyObject *other)
380 {
381     PyBufferProcs *pb = other->ob_type->tp_as_buffer;
382     void *ptr1, *ptr2;
383     char *p;
384     PyObject *ob;
385     Py_ssize_t size, count;
386 
387     if ( pb == NULL ||
388          pb->bf_getreadbuffer == NULL ||
389          pb->bf_getsegcount == NULL )
390     {
391         PyErr_BadArgument();
392         return NULL;
393     }
394     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
395     {
396         /* ### use a different exception type/message? */
397         PyErr_SetString(PyExc_TypeError,
398                         "single-segment buffer object expected");
399         return NULL;
400     }
401 
402     if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
403         return NULL;
404 
405     /* optimize special case */
406     if ( size == 0 )
407     {
408         Py_INCREF(other);
409         return other;
410     }
411 
412     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
413         return NULL;
414 
415     assert(count <= PY_SIZE_MAX - size);
416 
417     ob = PyString_FromStringAndSize(NULL, size + count);
418     if ( ob == NULL )
419         return NULL;
420     p = PyString_AS_STRING(ob);
421     memcpy(p, ptr1, size);
422     memcpy(p + size, ptr2, count);
423 
424     /* there is an extra byte in the string object, so this is safe */
425     p[size + count] = '\0';
426 
427     return ob;
428 }
429 
430 static PyObject *
431 buffer_repeat(PyBufferObject *self, Py_ssize_t count)
432 {
433     PyObject *ob;
434     register char *p;
435     void *ptr;
436     Py_ssize_t size;
437 
438     if ( count < 0 )
439         count = 0;
440     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
441         return NULL;
442     if (count > PY_SSIZE_T_MAX / size) {
443         PyErr_SetString(PyExc_MemoryError, "result too large");
444         return NULL;
445     }
446     ob = PyString_FromStringAndSize(NULL, size * count);
447     if ( ob == NULL )
448         return NULL;
449 
450     p = PyString_AS_STRING(ob);
451     while ( count-- )
452     {
453         memcpy(p, ptr, size);
454         p += size;
455     }
456 
457     /* there is an extra byte in the string object, so this is safe */
458     *p = '\0';
459 
460     return ob;
461 }
462 
463 static PyObject *
464 buffer_item(PyBufferObject *self, Py_ssize_t idx)
465 {
466     void *ptr;
467     Py_ssize_t size;
468     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
469         return NULL;
470     if ( idx < 0 || idx >= size ) {
471         PyErr_SetString(PyExc_IndexError, "buffer index out of range");
472         return NULL;
473     }
474     return PyString_FromStringAndSize((char *)ptr + idx, 1);
475 }
476 
477 static PyObject *
478 buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
479 {
480     void *ptr;
481     Py_ssize_t size;
482     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
483         return NULL;
484     if ( left < 0 )
485         left = 0;
486     if ( right < 0 )
487         right = 0;
488     if ( right > size )
489         right = size;
490     if ( right < left )
491         right = left;
492     return PyString_FromStringAndSize((char *)ptr + left,
493                                       right - left);
494 }
495 
496 static PyObject *
497 buffer_subscript(PyBufferObject *self, PyObject *item)
498 {
499     void *p;
500     Py_ssize_t size;
501 
502     if (!get_buf(self, &p, &size, ANY_BUFFER))
503         return NULL;
504     if (PyIndex_Check(item)) {
505         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
506         if (i == -1 && PyErr_Occurred())
507             return NULL;
508         if (i < 0)
509             i += size;
510         return buffer_item(self, i);
511     }
512     else if (PySlice_Check(item)) {
513         Py_ssize_t start, stop, step, slicelength, cur, i;
514 
515         if (PySlice_GetIndicesEx((PySliceObject*)item, size,
516                          &start, &stop, &step, &slicelength) < 0) {
517             return NULL;
518         }
519 
520         if (slicelength <= 0)
521             return PyString_FromStringAndSize("", 0);
522         else if (step == 1)
523             return PyString_FromStringAndSize((char *)p + start,
524                                               stop - start);
525         else {
526             PyObject *result;
527             char *source_buf = (char *)p;
528             char *result_buf = (char *)PyMem_Malloc(slicelength);
529 
530             if (result_buf == NULL)
531                 return PyErr_NoMemory();
532 
533             for (cur = start, i = 0; i < slicelength;
534                  cur += step, i++) {
535                 result_buf[i] = source_buf[cur];
536             }
537 
538             result = PyString_FromStringAndSize(result_buf,
539                                                 slicelength);
540             PyMem_Free(result_buf);
541             return result;
542         }
543     }
544     else {
545         PyErr_SetString(PyExc_TypeError,
546                         "sequence index must be integer");
547         return NULL;
548     }
549 }
550 
551 static int
552 buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
553 {
554     PyBufferProcs *pb;
555     void *ptr1, *ptr2;
556     Py_ssize_t size;
557     Py_ssize_t count;
558 
559     if ( self->b_readonly ) {
560         PyErr_SetString(PyExc_TypeError,
561                         "buffer is read-only");
562         return -1;
563     }
564 
565     if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
566         return -1;
567 
568     if (idx < 0 || idx >= size) {
569         PyErr_SetString(PyExc_IndexError,
570                         "buffer assignment index out of range");
571         return -1;
572     }
573 
574     pb = other ? other->ob_type->tp_as_buffer : NULL;
575     if ( pb == NULL ||
576          pb->bf_getreadbuffer == NULL ||
577          pb->bf_getsegcount == NULL )
578     {
579         PyErr_BadArgument();
580         return -1;
581     }
582     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
583     {
584         /* ### use a different exception type/message? */
585         PyErr_SetString(PyExc_TypeError,
586                         "single-segment buffer object expected");
587         return -1;
588     }
589 
590     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
591         return -1;
592     if ( count != 1 ) {
593         PyErr_SetString(PyExc_TypeError,
594                         "right operand must be a single byte");
595         return -1;
596     }
597 
598     ((char *)ptr1)[idx] = *(char *)ptr2;
599     return 0;
600 }
601 
602 static int
603 buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
604 {
605     PyBufferProcs *pb;
606     void *ptr1, *ptr2;
607     Py_ssize_t size;
608     Py_ssize_t slice_len;
609     Py_ssize_t count;
610 
611     if ( self->b_readonly ) {
612         PyErr_SetString(PyExc_TypeError,
613                         "buffer is read-only");
614         return -1;
615     }
616 
617     pb = other ? other->ob_type->tp_as_buffer : NULL;
618     if ( pb == NULL ||
619          pb->bf_getreadbuffer == NULL ||
620          pb->bf_getsegcount == NULL )
621     {
622         PyErr_BadArgument();
623         return -1;
624     }
625     if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
626     {
627         /* ### use a different exception type/message? */
628         PyErr_SetString(PyExc_TypeError,
629                         "single-segment buffer object expected");
630         return -1;
631     }
632     if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
633         return -1;
634     if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
635         return -1;
636 
637     if ( left < 0 )
638         left = 0;
639     else if ( left > size )
640         left = size;
641     if ( right < left )
642         right = left;
643     else if ( right > size )
644         right = size;
645     slice_len = right - left;
646 
647     if ( count != slice_len ) {
648         PyErr_SetString(
649             PyExc_TypeError,
650             "right operand length must match slice length");
651         return -1;
652     }
653 
654     if ( slice_len )
655         memcpy((char *)ptr1 + left, ptr2, slice_len);
656 
657     return 0;
658 }
659 
660 static int
661 buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
662 {
663     PyBufferProcs *pb;
664     void *ptr1, *ptr2;
665     Py_ssize_t selfsize;
666     Py_ssize_t othersize;
667 
668     if ( self->b_readonly ) {
669         PyErr_SetString(PyExc_TypeError,
670                         "buffer is read-only");
671         return -1;
672     }
673 
674     pb = value ? value->ob_type->tp_as_buffer : NULL;
675     if ( pb == NULL ||
676          pb->bf_getreadbuffer == NULL ||
677          pb->bf_getsegcount == NULL )
678     {
679         PyErr_BadArgument();
680         return -1;
681     }
682     if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
683     {
684         /* ### use a different exception type/message? */
685         PyErr_SetString(PyExc_TypeError,
686                         "single-segment buffer object expected");
687         return -1;
688     }
689     if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
690         return -1;
691     if (PyIndex_Check(item)) {
692         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
693         if (i == -1 && PyErr_Occurred())
694             return -1;
695         if (i < 0)
696             i += selfsize;
697         return buffer_ass_item(self, i, value);
698     }
699     else if (PySlice_Check(item)) {
700         Py_ssize_t start, stop, step, slicelength;
701 
702         if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
703                         &start, &stop, &step, &slicelength) < 0)
704             return -1;
705 
706         if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
707             return -1;
708 
709         if (othersize != slicelength) {
710             PyErr_SetString(
711                 PyExc_TypeError,
712                 "right operand length must match slice length");
713             return -1;
714         }
715 
716         if (slicelength == 0)
717             return 0;
718         else if (step == 1) {
719             memcpy((char *)ptr1 + start, ptr2, slicelength);
720             return 0;
721         }
722         else {
723             Py_ssize_t cur, i;
724 
725             for (cur = start, i = 0; i < slicelength;
726                  cur += step, i++) {
727                 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
728             }
729 
730             return 0;
731         }
732     } else {
733         PyErr_SetString(PyExc_TypeError,
734                         "buffer indices must be integers");
735         return -1;
736     }
737 }
738 
739 /* Buffer methods */
740 
741 static Py_ssize_t
742 buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
743 {
744     Py_ssize_t size;
745     if ( idx != 0 ) {
746         PyErr_SetString(PyExc_SystemError,
747                         "accessing non-existent buffer segment");
748         return -1;
749     }
750     if (!get_buf(self, pp, &size, READ_BUFFER))
751         return -1;
752     return size;
753 }
754 
755 static Py_ssize_t
756 buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
757 {
758     Py_ssize_t size;
759 
760     if ( self->b_readonly )
761     {
762         PyErr_SetString(PyExc_TypeError, "buffer is read-only");
763         return -1;
764     }
765 
766     if ( idx != 0 ) {
767         PyErr_SetString(PyExc_SystemError,
768                         "accessing non-existent buffer segment");
769         return -1;
770     }
771     if (!get_buf(self, pp, &size, WRITE_BUFFER))
772         return -1;
773     return size;
774 }
775 
776 static Py_ssize_t
777 buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
778 {
779     void *ptr;
780     Py_ssize_t size;
781     if (!get_buf(self, &ptr, &size, ANY_BUFFER))
782         return -1;
783     if (lenp)
784         *lenp = size;
785     return 1;
786 }
787 
788 static Py_ssize_t
789 buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
790 {
791     void *ptr;
792     Py_ssize_t size;
793     if ( idx != 0 ) {
794         PyErr_SetString(PyExc_SystemError,
795                         "accessing non-existent buffer segment");
796         return -1;
797     }
798     if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
799         return -1;
800     *pp = (const char *)ptr;
801     return size;
802 }
803 
804 static PySequenceMethods buffer_as_sequence = {
805     (lenfunc)buffer_length, /*sq_length*/
806     (binaryfunc)buffer_concat, /*sq_concat*/
807     (ssizeargfunc)buffer_repeat, /*sq_repeat*/
808     (ssizeargfunc)buffer_item, /*sq_item*/
809     (ssizessizeargfunc)buffer_slice, /*sq_slice*/
810     (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
811     (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
812 };
813 
814 static PyMappingMethods buffer_as_mapping = {
815     (lenfunc)buffer_length,
816     (binaryfunc)buffer_subscript,
817     (objobjargproc)buffer_ass_subscript,
818 };
819 
820 static PyBufferProcs buffer_as_buffer = {
821     (readbufferproc)buffer_getreadbuf,
822     (writebufferproc)buffer_getwritebuf,
823     (segcountproc)buffer_getsegcount,
824     (charbufferproc)buffer_getcharbuf,
825 };
826 
827 PyTypeObject PyBuffer_Type = {
828     PyVarObject_HEAD_INIT(&PyType_Type, 0)
829     "buffer",
830     sizeof(PyBufferObject),
831     0,
832     (destructor)buffer_dealloc,                 /* tp_dealloc */
833     0,                                          /* tp_print */
834     0,                                          /* tp_getattr */
835     0,                                          /* tp_setattr */
836     (cmpfunc)buffer_compare,                    /* tp_compare */
837     (reprfunc)buffer_repr,                      /* tp_repr */
838     0,                                          /* tp_as_number */
839     &buffer_as_sequence,                        /* tp_as_sequence */
840     &buffer_as_mapping,                         /* tp_as_mapping */
841     (hashfunc)buffer_hash,                      /* tp_hash */
842     0,                                          /* tp_call */
843     (reprfunc)buffer_str,                       /* tp_str */
844     PyObject_GenericGetAttr,                    /* tp_getattro */
845     0,                                          /* tp_setattro */
846     &buffer_as_buffer,                          /* tp_as_buffer */
847     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
848     buffer_doc,                                 /* tp_doc */
849     0,                                          /* tp_traverse */
850     0,                                          /* tp_clear */
851     0,                                          /* tp_richcompare */
852     0,                                          /* tp_weaklistoffset */
853     0,                                          /* tp_iter */
854     0,                                          /* tp_iternext */
855     0,                                          /* tp_methods */
856     0,                                          /* tp_members */
857     0,                                          /* tp_getset */
858     0,                                          /* tp_base */
859     0,                                          /* tp_dict */
860     0,                                          /* tp_descr_get */
861     0,                                          /* tp_descr_set */
862     0,                                          /* tp_dictoffset */
863     0,                                          /* tp_init */
864     0,                                          /* tp_alloc */
865     buffer_new,                                 /* tp_new */
866 };