2 /* Buffer object implementation */
26 get_buf(PyBufferObject
*self
, void **ptr
, Py_ssize_t
*size
,
27 enum buffer_t buffer_type
)
29 if (self
->b_base
== NULL
) {
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");
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");
56 proc
= (readbufferproc
)bp
->bf_getcharbuffer
;
59 char *buffer_type_name
;
60 switch (buffer_type
) {
62 buffer_type_name
= "read";
65 buffer_type_name
= "write";
68 buffer_type_name
= "char";
71 buffer_type_name
= "no";
74 PyErr_Format(PyExc_TypeError
,
75 "%s buffer type not available",
79 if ((count
= (*proc
)(self
->b_base
, 0, ptr
)) < 0)
81 /* apply constraints to the start/end */
82 if (self
->b_offset
> count
)
85 offset
= self
->b_offset
;
86 *(char **)ptr
= *(char **)ptr
+ offset
;
87 if (self
->b_size
== Py_END_OF_BUFFER
)
91 if (offset
+ *size
> count
)
92 *size
= count
- offset
;
99 buffer_from_memory(PyObject
*base
, Py_ssize_t size
, Py_ssize_t offset
, void *ptr
,
104 if (size
< 0 && size
!= Py_END_OF_BUFFER
) {
105 PyErr_SetString(PyExc_ValueError
,
106 "size must be zero or positive");
110 PyErr_SetString(PyExc_ValueError
,
111 "offset must be zero or positive");
115 b
= PyObject_NEW(PyBufferObject
, &PyBuffer_Type
);
123 b
->b_offset
= offset
;
124 b
->b_readonly
= readonly
;
127 return (PyObject
*) b
;
131 buffer_from_object(PyObject
*base
, Py_ssize_t size
, Py_ssize_t offset
, int readonly
)
134 PyErr_SetString(PyExc_ValueError
,
135 "offset must be zero or positive");
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
;
145 if (size
== Py_END_OF_BUFFER
|| size
> base_size
)
148 offset
+= b
->b_offset
;
151 return buffer_from_memory(base
, size
, offset
, NULL
, readonly
);
156 PyBuffer_FromObject(PyObject
*base
, Py_ssize_t offset
, Py_ssize_t size
)
158 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
161 pb
->bf_getreadbuffer
== NULL
||
162 pb
->bf_getsegcount
== NULL
)
164 PyErr_SetString(PyExc_TypeError
, "buffer object expected");
168 return buffer_from_object(base
, size
, offset
, 1);
172 PyBuffer_FromReadWriteObject(PyObject
*base
, Py_ssize_t offset
, Py_ssize_t size
)
174 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
177 pb
->bf_getwritebuffer
== NULL
||
178 pb
->bf_getsegcount
== NULL
)
180 PyErr_SetString(PyExc_TypeError
, "buffer object expected");
184 return buffer_from_object(base
, size
, offset
, 0);
188 PyBuffer_FromMemory(void *ptr
, Py_ssize_t size
)
190 return buffer_from_memory(NULL
, size
, 0, ptr
, 1);
194 PyBuffer_FromReadWriteMemory(void *ptr
, Py_ssize_t size
)
196 return buffer_from_memory(NULL
, size
, 0, ptr
, 0);
200 PyBuffer_New(Py_ssize_t size
)
206 PyErr_SetString(PyExc_ValueError
,
207 "size must be zero or positive");
210 if (sizeof(*b
) > PY_SSIZE_T_MAX
- size
) {
212 return PyErr_NoMemory();
214 /* Inline PyObject_New */
215 o
= (PyObject
*)PyObject_MALLOC(sizeof(*b
) + size
);
217 return PyErr_NoMemory();
218 b
= (PyBufferObject
*) PyObject_INIT(o
, &PyBuffer_Type
);
221 b
->b_ptr
= (void *)(b
+ 1);
233 buffer_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kw
)
236 Py_ssize_t offset
= 0;
237 Py_ssize_t size
= Py_END_OF_BUFFER
;
239 if (PyErr_WarnPy3k("buffer() not supported in 3.x; "
240 "use memoryview()", 1) < 0)
243 if (!_PyArg_NoKeywords("buffer()", kw
))
246 if (!PyArg_ParseTuple(args
, "O|nn:buffer", &ob
, &offset
, &size
))
248 return PyBuffer_FromObject(ob
, offset
, size
);
251 PyDoc_STRVAR(buffer_doc
,
252 "buffer(object [, offset[, size]])\n\
254 Create a new buffer object which references the given object.\n\
255 The buffer will reference a slice of the target object from the\n\
256 start of the object (or at the specified offset). The slice will\n\
257 extend to the end of the target object (or with the specified size).");
261 buffer_dealloc(PyBufferObject
*self
)
263 Py_XDECREF(self
->b_base
);
268 buffer_compare(PyBufferObject
*self
, PyBufferObject
*other
)
271 Py_ssize_t len_self
, len_other
, min_len
;
274 if (!get_buf(self
, &p1
, &len_self
, ANY_BUFFER
))
276 if (!get_buf(other
, &p2
, &len_other
, ANY_BUFFER
))
278 min_len
= (len_self
< len_other
) ? len_self
: len_other
;
280 cmp
= memcmp(p1
, p2
, min_len
);
282 return cmp
< 0 ? -1 : 1;
284 return (len_self
< len_other
) ? -1 : (len_self
> len_other
) ? 1 : 0;
288 buffer_repr(PyBufferObject
*self
)
290 const char *status
= self
->b_readonly
? "read-only" : "read-write";
292 if ( self
->b_base
== NULL
)
293 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
299 return PyString_FromFormat(
300 "<%s buffer for %p, size %zd, offset %zd at %p>",
309 buffer_hash(PyBufferObject
*self
)
313 register Py_ssize_t len
;
314 register unsigned char *p
;
317 if ( self
->b_hash
!= -1 )
320 /* XXX potential bugs here, a readonly buffer does not imply that the
321 * underlying memory is immutable. b_readonly is a necessary but not
322 * sufficient condition for a buffer to be hashable. Perhaps it would
323 * be better to only allow hashing if the underlying object is known to
324 * be immutable (e.g. PyString_Check() is true). Another idea would
325 * be to call tp_hash on the underlying object and see if it raises
327 if ( !self
->b_readonly
)
329 PyErr_SetString(PyExc_TypeError
,
330 "writable buffers are not hashable");
334 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
336 p
= (unsigned char *) ptr
;
340 x
= (1000003*x
) ^ *p
++;
349 buffer_str(PyBufferObject
*self
)
353 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
355 return PyString_FromStringAndSize((const char *)ptr
, size
);
358 /* Sequence methods */
361 buffer_length(PyBufferObject
*self
)
365 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
371 buffer_concat(PyBufferObject
*self
, PyObject
*other
)
373 PyBufferProcs
*pb
= other
->ob_type
->tp_as_buffer
;
377 Py_ssize_t size
, count
;
380 pb
->bf_getreadbuffer
== NULL
||
381 pb
->bf_getsegcount
== NULL
)
386 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
388 /* ### use a different exception type/message? */
389 PyErr_SetString(PyExc_TypeError
,
390 "single-segment buffer object expected");
394 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
397 /* optimize special case */
404 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
407 assert(count
<= PY_SIZE_MAX
- size
);
409 ob
= PyString_FromStringAndSize(NULL
, size
+ count
);
412 p
= PyString_AS_STRING(ob
);
413 memcpy(p
, ptr1
, size
);
414 memcpy(p
+ size
, ptr2
, count
);
416 /* there is an extra byte in the string object, so this is safe */
417 p
[size
+ count
] = '\0';
423 buffer_repeat(PyBufferObject
*self
, Py_ssize_t count
)
432 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
434 if (count
> PY_SSIZE_T_MAX
/ size
) {
435 PyErr_SetString(PyExc_MemoryError
, "result too large");
438 ob
= PyString_FromStringAndSize(NULL
, size
* count
);
442 p
= PyString_AS_STRING(ob
);
445 memcpy(p
, ptr
, size
);
449 /* there is an extra byte in the string object, so this is safe */
456 buffer_item(PyBufferObject
*self
, Py_ssize_t idx
)
460 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
462 if ( idx
< 0 || idx
>= size
) {
463 PyErr_SetString(PyExc_IndexError
, "buffer index out of range");
466 return PyString_FromStringAndSize((char *)ptr
+ idx
, 1);
470 buffer_slice(PyBufferObject
*self
, Py_ssize_t left
, Py_ssize_t right
)
474 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
484 return PyString_FromStringAndSize((char *)ptr
+ left
,
489 buffer_subscript(PyBufferObject
*self
, PyObject
*item
)
494 if (!get_buf(self
, &p
, &size
, ANY_BUFFER
))
496 if (PyIndex_Check(item
)) {
497 Py_ssize_t i
= PyNumber_AsSsize_t(item
, PyExc_IndexError
);
498 if (i
== -1 && PyErr_Occurred())
502 return buffer_item(self
, i
);
504 else if (PySlice_Check(item
)) {
505 Py_ssize_t start
, stop
, step
, slicelength
, cur
, i
;
507 if (PySlice_GetIndicesEx((PySliceObject
*)item
, size
,
508 &start
, &stop
, &step
, &slicelength
) < 0) {
512 if (slicelength
<= 0)
513 return PyString_FromStringAndSize("", 0);
515 return PyString_FromStringAndSize((char *)p
+ start
,
519 char *source_buf
= (char *)p
;
520 char *result_buf
= (char *)PyMem_Malloc(slicelength
);
522 if (result_buf
== NULL
)
523 return PyErr_NoMemory();
525 for (cur
= start
, i
= 0; i
< slicelength
;
527 result_buf
[i
] = source_buf
[cur
];
530 result
= PyString_FromStringAndSize(result_buf
,
532 PyMem_Free(result_buf
);
537 PyErr_SetString(PyExc_TypeError
,
538 "sequence index must be integer");
544 buffer_ass_item(PyBufferObject
*self
, Py_ssize_t idx
, PyObject
*other
)
551 if ( self
->b_readonly
) {
552 PyErr_SetString(PyExc_TypeError
,
553 "buffer is read-only");
557 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
560 if (idx
< 0 || idx
>= size
) {
561 PyErr_SetString(PyExc_IndexError
,
562 "buffer assignment index out of range");
566 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
568 pb
->bf_getreadbuffer
== NULL
||
569 pb
->bf_getsegcount
== NULL
)
574 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
576 /* ### use a different exception type/message? */
577 PyErr_SetString(PyExc_TypeError
,
578 "single-segment buffer object expected");
582 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
585 PyErr_SetString(PyExc_TypeError
,
586 "right operand must be a single byte");
590 ((char *)ptr1
)[idx
] = *(char *)ptr2
;
595 buffer_ass_slice(PyBufferObject
*self
, Py_ssize_t left
, Py_ssize_t right
, PyObject
*other
)
600 Py_ssize_t slice_len
;
603 if ( self
->b_readonly
) {
604 PyErr_SetString(PyExc_TypeError
,
605 "buffer is read-only");
609 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
611 pb
->bf_getreadbuffer
== NULL
||
612 pb
->bf_getsegcount
== NULL
)
617 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
619 /* ### use a different exception type/message? */
620 PyErr_SetString(PyExc_TypeError
,
621 "single-segment buffer object expected");
624 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
626 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
631 else if ( left
> size
)
635 else if ( right
> size
)
637 slice_len
= right
- left
;
639 if ( count
!= slice_len
) {
642 "right operand length must match slice length");
647 memcpy((char *)ptr1
+ left
, ptr2
, slice_len
);
653 buffer_ass_subscript(PyBufferObject
*self
, PyObject
*item
, PyObject
*value
)
658 Py_ssize_t othersize
;
660 if ( self
->b_readonly
) {
661 PyErr_SetString(PyExc_TypeError
,
662 "buffer is read-only");
666 pb
= value
? value
->ob_type
->tp_as_buffer
: NULL
;
668 pb
->bf_getreadbuffer
== NULL
||
669 pb
->bf_getsegcount
== NULL
)
674 if ( (*pb
->bf_getsegcount
)(value
, NULL
) != 1 )
676 /* ### use a different exception type/message? */
677 PyErr_SetString(PyExc_TypeError
,
678 "single-segment buffer object expected");
681 if (!get_buf(self
, &ptr1
, &selfsize
, ANY_BUFFER
))
683 if (PyIndex_Check(item
)) {
684 Py_ssize_t i
= PyNumber_AsSsize_t(item
, PyExc_IndexError
);
685 if (i
== -1 && PyErr_Occurred())
689 return buffer_ass_item(self
, i
, value
);
691 else if (PySlice_Check(item
)) {
692 Py_ssize_t start
, stop
, step
, slicelength
;
694 if (PySlice_GetIndicesEx((PySliceObject
*)item
, selfsize
,
695 &start
, &stop
, &step
, &slicelength
) < 0)
698 if ((othersize
= (*pb
->bf_getreadbuffer
)(value
, 0, &ptr2
)) < 0)
701 if (othersize
!= slicelength
) {
704 "right operand length must match slice length");
708 if (slicelength
== 0)
710 else if (step
== 1) {
711 memcpy((char *)ptr1
+ start
, ptr2
, slicelength
);
717 for (cur
= start
, i
= 0; i
< slicelength
;
719 ((char *)ptr1
)[cur
] = ((char *)ptr2
)[i
];
725 PyErr_SetString(PyExc_TypeError
,
726 "buffer indices must be integers");
734 buffer_getreadbuf(PyBufferObject
*self
, Py_ssize_t idx
, void **pp
)
738 PyErr_SetString(PyExc_SystemError
,
739 "accessing non-existent buffer segment");
742 if (!get_buf(self
, pp
, &size
, READ_BUFFER
))
748 buffer_getwritebuf(PyBufferObject
*self
, Py_ssize_t idx
, void **pp
)
752 if ( self
->b_readonly
)
754 PyErr_SetString(PyExc_TypeError
, "buffer is read-only");
759 PyErr_SetString(PyExc_SystemError
,
760 "accessing non-existent buffer segment");
763 if (!get_buf(self
, pp
, &size
, WRITE_BUFFER
))
769 buffer_getsegcount(PyBufferObject
*self
, Py_ssize_t
*lenp
)
773 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
781 buffer_getcharbuf(PyBufferObject
*self
, Py_ssize_t idx
, const char **pp
)
786 PyErr_SetString(PyExc_SystemError
,
787 "accessing non-existent buffer segment");
790 if (!get_buf(self
, &ptr
, &size
, CHAR_BUFFER
))
792 *pp
= (const char *)ptr
;
796 static PySequenceMethods buffer_as_sequence
= {
797 (lenfunc
)buffer_length
, /*sq_length*/
798 (binaryfunc
)buffer_concat
, /*sq_concat*/
799 (ssizeargfunc
)buffer_repeat
, /*sq_repeat*/
800 (ssizeargfunc
)buffer_item
, /*sq_item*/
801 (ssizessizeargfunc
)buffer_slice
, /*sq_slice*/
802 (ssizeobjargproc
)buffer_ass_item
, /*sq_ass_item*/
803 (ssizessizeobjargproc
)buffer_ass_slice
, /*sq_ass_slice*/
806 static PyMappingMethods buffer_as_mapping
= {
807 (lenfunc
)buffer_length
,
808 (binaryfunc
)buffer_subscript
,
809 (objobjargproc
)buffer_ass_subscript
,
812 static PyBufferProcs buffer_as_buffer
= {
813 (readbufferproc
)buffer_getreadbuf
,
814 (writebufferproc
)buffer_getwritebuf
,
815 (segcountproc
)buffer_getsegcount
,
816 (charbufferproc
)buffer_getcharbuf
,
819 PyTypeObject PyBuffer_Type
= {
820 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
822 sizeof(PyBufferObject
),
824 (destructor
)buffer_dealloc
, /* tp_dealloc */
828 (cmpfunc
)buffer_compare
, /* tp_compare */
829 (reprfunc
)buffer_repr
, /* tp_repr */
830 0, /* tp_as_number */
831 &buffer_as_sequence
, /* tp_as_sequence */
832 &buffer_as_mapping
, /* tp_as_mapping */
833 (hashfunc
)buffer_hash
, /* tp_hash */
835 (reprfunc
)buffer_str
, /* tp_str */
836 PyObject_GenericGetAttr
, /* tp_getattro */
838 &buffer_as_buffer
, /* tp_as_buffer */
839 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GETCHARBUFFER
, /* tp_flags */
840 buffer_doc
, /* tp_doc */
843 0, /* tp_richcompare */
844 0, /* tp_weaklistoffset */
852 0, /* tp_descr_get */
853 0, /* tp_descr_set */
854 0, /* tp_dictoffset */
857 buffer_new
, /* tp_new */