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 = Py_TYPE(self->b_base)->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(Py_TYPE(self),
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_impl(void * ptr,Py_ssize_t size,Py_ssize_t idx)465 buffer_item_impl(void *ptr, Py_ssize_t size, Py_ssize_t idx)
466 {
467 if ( idx < 0 || idx >= size ) {
468 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
469 return NULL;
470 }
471 return PyString_FromStringAndSize((char *)ptr + idx, 1);
472 }
473
474 static PyObject *
buffer_item(PyBufferObject * self,Py_ssize_t idx)475 buffer_item(PyBufferObject *self, Py_ssize_t idx)
476 {
477 void *ptr;
478 Py_ssize_t size;
479 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
480 return NULL;
481 return buffer_item_impl(ptr, size, idx);
482 }
483
484 static PyObject *
buffer_slice(PyBufferObject * self,Py_ssize_t left,Py_ssize_t right)485 buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
486 {
487 void *ptr;
488 Py_ssize_t size;
489 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
490 return NULL;
491 if ( left < 0 )
492 left = 0;
493 if ( right < 0 )
494 right = 0;
495 if ( right > size )
496 right = size;
497 if ( right < left )
498 right = left;
499 return PyString_FromStringAndSize((char *)ptr + left,
500 right - left);
501 }
502
503 static PyObject *
buffer_subscript(PyBufferObject * self,PyObject * item)504 buffer_subscript(PyBufferObject *self, PyObject *item)
505 {
506 void *p;
507 Py_ssize_t size;
508
509 if (PyIndex_Check(item)) {
510 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
511 if (i == -1 && PyErr_Occurred())
512 return NULL;
513 if (!get_buf(self, &p, &size, ANY_BUFFER))
514 return NULL;
515
516 if (i < 0) {
517 i += size;
518 }
519 return buffer_item_impl(p, size, i);
520 }
521 else if (PySlice_Check(item)) {
522 Py_ssize_t start, stop, step, slicelength, cur, i;
523
524 if (_PySlice_Unpack(item, &start, &stop, &step) < 0)
525 return NULL;
526 if (!get_buf(self, &p, &size, ANY_BUFFER))
527 return NULL;
528
529 slicelength = _PySlice_AdjustIndices(size, &start, &stop, step);
530 if (slicelength <= 0)
531 return PyString_FromStringAndSize("", 0);
532 else if (step == 1)
533 return PyString_FromStringAndSize((char *)p + start,
534 stop - start);
535 else {
536 PyObject *result;
537 char *source_buf = (char *)p;
538 char *result_buf = (char *)PyMem_Malloc(slicelength);
539
540 if (result_buf == NULL)
541 return PyErr_NoMemory();
542
543 for (cur = start, i = 0; i < slicelength;
544 cur += step, i++) {
545 result_buf[i] = source_buf[cur];
546 }
547
548 result = PyString_FromStringAndSize(result_buf,
549 slicelength);
550 PyMem_Free(result_buf);
551 return result;
552 }
553 }
554 else {
555 PyErr_SetString(PyExc_TypeError,
556 "sequence index must be integer");
557 return NULL;
558 }
559 }
560
561 static int
buffer_ass_item_impl(void * ptr1,Py_ssize_t size,Py_ssize_t idx,PyObject * other)562 buffer_ass_item_impl(void *ptr1, Py_ssize_t size, Py_ssize_t idx, PyObject *other)
563 {
564 PyBufferProcs *pb;
565 void *ptr2;
566 Py_ssize_t count;
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
buffer_ass_item(PyBufferObject * self,Py_ssize_t idx,PyObject * other)603 buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
604 {
605 void *ptr1;
606 Py_ssize_t size;
607
608 if ( self->b_readonly ) {
609 PyErr_SetString(PyExc_TypeError,
610 "buffer is read-only");
611 return -1;
612 }
613
614 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
615 return -1;
616 return buffer_ass_item_impl(ptr1, size, idx, other);
617 }
618
619 static int
buffer_ass_slice(PyBufferObject * self,Py_ssize_t left,Py_ssize_t right,PyObject * other)620 buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
621 {
622 PyBufferProcs *pb;
623 void *ptr1, *ptr2;
624 Py_ssize_t size;
625 Py_ssize_t slice_len;
626 Py_ssize_t count;
627
628 if ( self->b_readonly ) {
629 PyErr_SetString(PyExc_TypeError,
630 "buffer is read-only");
631 return -1;
632 }
633
634 pb = other ? other->ob_type->tp_as_buffer : NULL;
635 if ( pb == NULL ||
636 pb->bf_getreadbuffer == NULL ||
637 pb->bf_getsegcount == NULL )
638 {
639 PyErr_BadArgument();
640 return -1;
641 }
642 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
643 {
644 /* ### use a different exception type/message? */
645 PyErr_SetString(PyExc_TypeError,
646 "single-segment buffer object expected");
647 return -1;
648 }
649 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
650 return -1;
651 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
652 return -1;
653
654 if ( left < 0 )
655 left = 0;
656 else if ( left > size )
657 left = size;
658 if ( right < left )
659 right = left;
660 else if ( right > size )
661 right = size;
662 slice_len = right - left;
663
664 if ( count != slice_len ) {
665 PyErr_SetString(
666 PyExc_TypeError,
667 "right operand length must match slice length");
668 return -1;
669 }
670
671 if ( slice_len )
672 memcpy((char *)ptr1 + left, ptr2, slice_len);
673
674 return 0;
675 }
676
677 static int
buffer_ass_subscript(PyBufferObject * self,PyObject * item,PyObject * value)678 buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
679 {
680 PyBufferProcs *pb;
681 void *ptr1, *ptr2;
682 Py_ssize_t selfsize;
683 Py_ssize_t othersize;
684
685 if ( self->b_readonly ) {
686 PyErr_SetString(PyExc_TypeError,
687 "buffer is read-only");
688 return -1;
689 }
690
691 pb = value ? value->ob_type->tp_as_buffer : NULL;
692 if ( pb == NULL ||
693 pb->bf_getreadbuffer == NULL ||
694 pb->bf_getsegcount == NULL )
695 {
696 PyErr_BadArgument();
697 return -1;
698 }
699 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
700 {
701 /* ### use a different exception type/message? */
702 PyErr_SetString(PyExc_TypeError,
703 "single-segment buffer object expected");
704 return -1;
705 }
706 if (PyIndex_Check(item)) {
707 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
708 if (i == -1 && PyErr_Occurred())
709 return -1;
710 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
711 return -1;
712
713 if (i < 0)
714 i += selfsize;
715 return buffer_ass_item_impl(ptr1, selfsize, i, value);
716 }
717 else if (PySlice_Check(item)) {
718 Py_ssize_t start, stop, step, slicelength;
719
720 if (_PySlice_Unpack(item, &start, &stop, &step) < 0)
721 return -1;
722 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
723 return -1;
724
725 slicelength = _PySlice_AdjustIndices(selfsize, &start, &stop, step);
726 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
727 return -1;
728
729 if (othersize != slicelength) {
730 PyErr_SetString(
731 PyExc_TypeError,
732 "right operand length must match slice length");
733 return -1;
734 }
735
736 if (slicelength == 0)
737 return 0;
738 else if (step == 1) {
739 memcpy((char *)ptr1 + start, ptr2, slicelength);
740 return 0;
741 }
742 else {
743 Py_ssize_t cur, i;
744
745 for (cur = start, i = 0; i < slicelength;
746 cur += step, i++) {
747 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
748 }
749
750 return 0;
751 }
752 } else {
753 PyErr_SetString(PyExc_TypeError,
754 "buffer indices must be integers");
755 return -1;
756 }
757 }
758
759 /* Buffer methods */
760
761 static Py_ssize_t
buffer_getreadbuf(PyBufferObject * self,Py_ssize_t idx,void ** pp)762 buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
763 {
764 Py_ssize_t size;
765 if ( idx != 0 ) {
766 PyErr_SetString(PyExc_SystemError,
767 "accessing non-existent buffer segment");
768 return -1;
769 }
770 if (!get_buf(self, pp, &size, READ_BUFFER))
771 return -1;
772 return size;
773 }
774
775 static Py_ssize_t
buffer_getwritebuf(PyBufferObject * self,Py_ssize_t idx,void ** pp)776 buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
777 {
778 Py_ssize_t size;
779
780 if ( self->b_readonly )
781 {
782 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
783 return -1;
784 }
785
786 if ( idx != 0 ) {
787 PyErr_SetString(PyExc_SystemError,
788 "accessing non-existent buffer segment");
789 return -1;
790 }
791 if (!get_buf(self, pp, &size, WRITE_BUFFER))
792 return -1;
793 return size;
794 }
795
796 static Py_ssize_t
buffer_getsegcount(PyBufferObject * self,Py_ssize_t * lenp)797 buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
798 {
799 void *ptr;
800 Py_ssize_t size;
801 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
802 return -1;
803 if (lenp)
804 *lenp = size;
805 return 1;
806 }
807
808 static Py_ssize_t
buffer_getcharbuf(PyBufferObject * self,Py_ssize_t idx,const char ** pp)809 buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
810 {
811 void *ptr;
812 Py_ssize_t size;
813 if ( idx != 0 ) {
814 PyErr_SetString(PyExc_SystemError,
815 "accessing non-existent buffer segment");
816 return -1;
817 }
818 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
819 return -1;
820 *pp = (const char *)ptr;
821 return size;
822 }
823
buffer_getbuffer(PyBufferObject * self,Py_buffer * buf,int flags)824 static int buffer_getbuffer(PyBufferObject *self, Py_buffer *buf, int flags)
825 {
826 void *ptr;
827 Py_ssize_t size;
828 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
829 return -1;
830 return PyBuffer_FillInfo(buf, (PyObject*)self, ptr, size,
831 self->b_readonly, flags);
832 }
833
834 static PySequenceMethods buffer_as_sequence = {
835 (lenfunc)buffer_length, /*sq_length*/
836 (binaryfunc)buffer_concat, /*sq_concat*/
837 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
838 (ssizeargfunc)buffer_item, /*sq_item*/
839 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
840 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
841 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
842 };
843
844 static PyMappingMethods buffer_as_mapping = {
845 (lenfunc)buffer_length,
846 (binaryfunc)buffer_subscript,
847 (objobjargproc)buffer_ass_subscript,
848 };
849
850 static PyBufferProcs buffer_as_buffer = {
851 (readbufferproc)buffer_getreadbuf,
852 (writebufferproc)buffer_getwritebuf,
853 (segcountproc)buffer_getsegcount,
854 (charbufferproc)buffer_getcharbuf,
855 (getbufferproc)buffer_getbuffer,
856 };
857
858 PyTypeObject PyBuffer_Type = {
859 PyVarObject_HEAD_INIT(&PyType_Type, 0)
860 "buffer",
861 sizeof(PyBufferObject),
862 0,
863 (destructor)buffer_dealloc, /* tp_dealloc */
864 0, /* tp_print */
865 0, /* tp_getattr */
866 0, /* tp_setattr */
867 (cmpfunc)buffer_compare, /* tp_compare */
868 (reprfunc)buffer_repr, /* tp_repr */
869 0, /* tp_as_number */
870 &buffer_as_sequence, /* tp_as_sequence */
871 &buffer_as_mapping, /* tp_as_mapping */
872 (hashfunc)buffer_hash, /* tp_hash */
873 0, /* tp_call */
874 (reprfunc)buffer_str, /* tp_str */
875 PyObject_GenericGetAttr, /* tp_getattro */
876 0, /* tp_setattro */
877 &buffer_as_buffer, /* tp_as_buffer */
878 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */
879 buffer_doc, /* tp_doc */
880 0, /* tp_traverse */
881 0, /* tp_clear */
882 0, /* tp_richcompare */
883 0, /* tp_weaklistoffset */
884 0, /* tp_iter */
885 0, /* tp_iternext */
886 0, /* tp_methods */
887 0, /* tp_members */
888 0, /* tp_getset */
889 0, /* tp_base */
890 0, /* tp_dict */
891 0, /* tp_descr_get */
892 0, /* tp_descr_set */
893 0, /* tp_dictoffset */
894 0, /* tp_init */
895 0, /* tp_alloc */
896 buffer_new, /* tp_new */
897 };
898