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 };