• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
get_buf(PyBufferObject * self,void ** ptr,Py_ssize_t * size,enum buffer_t buffer_type)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 *
buffer_from_memory(PyObject * base,Py_ssize_t size,Py_ssize_t offset,void * ptr,int readonly)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 *
buffer_from_object(PyObject * base,Py_ssize_t size,Py_ssize_t offset,int readonly)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 *
PyBuffer_FromObject(PyObject * base,Py_ssize_t offset,Py_ssize_t size)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 *
PyBuffer_FromReadWriteObject(PyObject * base,Py_ssize_t offset,Py_ssize_t size)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 *
PyBuffer_FromMemory(void * ptr,Py_ssize_t size)188 PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
189 {
190     return buffer_from_memory(NULL, size, 0, ptr, 1);
191 }
192 
193 PyObject *
PyBuffer_FromReadWriteMemory(void * ptr,Py_ssize_t size)194 PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
195 {
196     return buffer_from_memory(NULL, size, 0, ptr, 0);
197 }
198 
199 PyObject *
PyBuffer_New(Py_ssize_t size)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 *
buffer_new(PyTypeObject * type,PyObject * args,PyObject * kw)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
buffer_dealloc(PyBufferObject * self)260 buffer_dealloc(PyBufferObject *self)
261 {
262     Py_XDECREF(self->b_base);
263     PyObject_DEL(self);
264 }
265 
266 static int
buffer_compare(PyBufferObject * self,PyBufferObject * other)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 *
buffer_repr(PyBufferObject * self)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
buffer_hash(PyBufferObject * self)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 *
buffer_str(PyBufferObject * self)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
buffer_length(PyBufferObject * self)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 *
buffer_concat(PyBufferObject * self,PyObject * other)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 *
buffer_repeat(PyBufferObject * self,Py_ssize_t count)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 *
buffer_item(PyBufferObject * self,Py_ssize_t idx)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 *
buffer_slice(PyBufferObject * self,Py_ssize_t left,Py_ssize_t right)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 *
buffer_subscript(PyBufferObject * self,PyObject * item)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
buffer_ass_item(PyBufferObject * self,Py_ssize_t idx,PyObject * other)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
buffer_ass_slice(PyBufferObject * self,Py_ssize_t left,Py_ssize_t right,PyObject * other)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
buffer_ass_subscript(PyBufferObject * self,PyObject * item,PyObject * value)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
buffer_getreadbuf(PyBufferObject * self,Py_ssize_t idx,void ** pp)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
buffer_getwritebuf(PyBufferObject * self,Py_ssize_t idx,void ** pp)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
buffer_getsegcount(PyBufferObject * self,Py_ssize_t * lenp)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
buffer_getcharbuf(PyBufferObject * self,Py_ssize_t idx,const char ** pp)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 
buffer_getbuffer(PyBufferObject * self,Py_buffer * buf,int flags)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