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", 1) < 0)
242 if (!_PyArg_NoKeywords("buffer()", kw
))
245 if (!PyArg_ParseTuple(args
, "O|nn:buffer", &ob
, &offset
, &size
))
247 return PyBuffer_FromObject(ob
, offset
, size
);
250 PyDoc_STRVAR(buffer_doc
,
251 "buffer(object [, offset[, size]])\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).");
260 buffer_dealloc(PyBufferObject
*self
)
262 Py_XDECREF(self
->b_base
);
267 buffer_compare(PyBufferObject
*self
, PyBufferObject
*other
)
270 Py_ssize_t len_self
, len_other
, min_len
;
273 if (!get_buf(self
, &p1
, &len_self
, ANY_BUFFER
))
275 if (!get_buf(other
, &p2
, &len_other
, ANY_BUFFER
))
277 min_len
= (len_self
< len_other
) ? len_self
: len_other
;
279 cmp
= memcmp(p1
, p2
, min_len
);
281 return cmp
< 0 ? -1 : 1;
283 return (len_self
< len_other
) ? -1 : (len_self
> len_other
) ? 1 : 0;
287 buffer_repr(PyBufferObject
*self
)
289 const char *status
= self
->b_readonly
? "read-only" : "read-write";
291 if ( self
->b_base
== NULL
)
292 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
298 return PyString_FromFormat(
299 "<%s buffer for %p, size %zd, offset %zd at %p>",
308 buffer_hash(PyBufferObject
*self
)
312 register Py_ssize_t len
;
313 register unsigned char *p
;
316 if ( self
->b_hash
!= -1 )
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
326 if ( !self
->b_readonly
)
328 PyErr_SetString(PyExc_TypeError
,
329 "writable buffers are not hashable");
333 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
335 p
= (unsigned char *) ptr
;
339 x
= (1000003*x
) ^ *p
++;
348 buffer_str(PyBufferObject
*self
)
352 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
354 return PyString_FromStringAndSize((const char *)ptr
, size
);
357 /* Sequence methods */
360 buffer_length(PyBufferObject
*self
)
364 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
370 buffer_concat(PyBufferObject
*self
, PyObject
*other
)
372 PyBufferProcs
*pb
= other
->ob_type
->tp_as_buffer
;
376 Py_ssize_t size
, count
;
379 pb
->bf_getreadbuffer
== NULL
||
380 pb
->bf_getsegcount
== NULL
)
385 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
387 /* ### use a different exception type/message? */
388 PyErr_SetString(PyExc_TypeError
,
389 "single-segment buffer object expected");
393 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
396 /* optimize special case */
403 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
406 assert(count
<= PY_SIZE_MAX
- size
);
408 ob
= PyString_FromStringAndSize(NULL
, size
+ count
);
411 p
= PyString_AS_STRING(ob
);
412 memcpy(p
, ptr1
, size
);
413 memcpy(p
+ size
, ptr2
, count
);
415 /* there is an extra byte in the string object, so this is safe */
416 p
[size
+ count
] = '\0';
422 buffer_repeat(PyBufferObject
*self
, Py_ssize_t count
)
431 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
433 if (count
> PY_SSIZE_T_MAX
/ size
) {
434 PyErr_SetString(PyExc_MemoryError
, "result too large");
437 ob
= PyString_FromStringAndSize(NULL
, size
* count
);
441 p
= PyString_AS_STRING(ob
);
444 memcpy(p
, ptr
, size
);
448 /* there is an extra byte in the string object, so this is safe */
455 buffer_item(PyBufferObject
*self
, Py_ssize_t idx
)
459 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
461 if ( idx
< 0 || idx
>= size
) {
462 PyErr_SetString(PyExc_IndexError
, "buffer index out of range");
465 return PyString_FromStringAndSize((char *)ptr
+ idx
, 1);
469 buffer_slice(PyBufferObject
*self
, Py_ssize_t left
, Py_ssize_t right
)
473 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
483 return PyString_FromStringAndSize((char *)ptr
+ left
,
488 buffer_subscript(PyBufferObject
*self
, PyObject
*item
)
493 if (!get_buf(self
, &p
, &size
, ANY_BUFFER
))
495 if (PyIndex_Check(item
)) {
496 Py_ssize_t i
= PyNumber_AsSsize_t(item
, PyExc_IndexError
);
497 if (i
== -1 && PyErr_Occurred())
501 return buffer_item(self
, i
);
503 else if (PySlice_Check(item
)) {
504 Py_ssize_t start
, stop
, step
, slicelength
, cur
, i
;
506 if (PySlice_GetIndicesEx((PySliceObject
*)item
, size
,
507 &start
, &stop
, &step
, &slicelength
) < 0) {
511 if (slicelength
<= 0)
512 return PyString_FromStringAndSize("", 0);
514 return PyString_FromStringAndSize((char *)p
+ start
,
518 char *source_buf
= (char *)p
;
519 char *result_buf
= (char *)PyMem_Malloc(slicelength
);
521 if (result_buf
== NULL
)
522 return PyErr_NoMemory();
524 for (cur
= start
, i
= 0; i
< slicelength
;
526 result_buf
[i
] = source_buf
[cur
];
529 result
= PyString_FromStringAndSize(result_buf
,
531 PyMem_Free(result_buf
);
536 PyErr_SetString(PyExc_TypeError
,
537 "sequence index must be integer");
543 buffer_ass_item(PyBufferObject
*self
, Py_ssize_t idx
, PyObject
*other
)
550 if ( self
->b_readonly
) {
551 PyErr_SetString(PyExc_TypeError
,
552 "buffer is read-only");
556 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
559 if (idx
< 0 || idx
>= size
) {
560 PyErr_SetString(PyExc_IndexError
,
561 "buffer assignment index out of range");
565 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
567 pb
->bf_getreadbuffer
== NULL
||
568 pb
->bf_getsegcount
== NULL
)
573 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
575 /* ### use a different exception type/message? */
576 PyErr_SetString(PyExc_TypeError
,
577 "single-segment buffer object expected");
581 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
584 PyErr_SetString(PyExc_TypeError
,
585 "right operand must be a single byte");
589 ((char *)ptr1
)[idx
] = *(char *)ptr2
;
594 buffer_ass_slice(PyBufferObject
*self
, Py_ssize_t left
, Py_ssize_t right
, PyObject
*other
)
599 Py_ssize_t slice_len
;
602 if ( self
->b_readonly
) {
603 PyErr_SetString(PyExc_TypeError
,
604 "buffer is read-only");
608 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
610 pb
->bf_getreadbuffer
== NULL
||
611 pb
->bf_getsegcount
== NULL
)
616 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
618 /* ### use a different exception type/message? */
619 PyErr_SetString(PyExc_TypeError
,
620 "single-segment buffer object expected");
623 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
625 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
630 else if ( left
> size
)
634 else if ( right
> size
)
636 slice_len
= right
- left
;
638 if ( count
!= slice_len
) {
641 "right operand length must match slice length");
646 memcpy((char *)ptr1
+ left
, ptr2
, slice_len
);
652 buffer_ass_subscript(PyBufferObject
*self
, PyObject
*item
, PyObject
*value
)
657 Py_ssize_t othersize
;
659 if ( self
->b_readonly
) {
660 PyErr_SetString(PyExc_TypeError
,
661 "buffer is read-only");
665 pb
= value
? value
->ob_type
->tp_as_buffer
: NULL
;
667 pb
->bf_getreadbuffer
== NULL
||
668 pb
->bf_getsegcount
== NULL
)
673 if ( (*pb
->bf_getsegcount
)(value
, NULL
) != 1 )
675 /* ### use a different exception type/message? */
676 PyErr_SetString(PyExc_TypeError
,
677 "single-segment buffer object expected");
680 if (!get_buf(self
, &ptr1
, &selfsize
, ANY_BUFFER
))
682 if (PyIndex_Check(item
)) {
683 Py_ssize_t i
= PyNumber_AsSsize_t(item
, PyExc_IndexError
);
684 if (i
== -1 && PyErr_Occurred())
688 return buffer_ass_item(self
, i
, value
);
690 else if (PySlice_Check(item
)) {
691 Py_ssize_t start
, stop
, step
, slicelength
;
693 if (PySlice_GetIndicesEx((PySliceObject
*)item
, selfsize
,
694 &start
, &stop
, &step
, &slicelength
) < 0)
697 if ((othersize
= (*pb
->bf_getreadbuffer
)(value
, 0, &ptr2
)) < 0)
700 if (othersize
!= slicelength
) {
703 "right operand length must match slice length");
707 if (slicelength
== 0)
709 else if (step
== 1) {
710 memcpy((char *)ptr1
+ start
, ptr2
, slicelength
);
716 for (cur
= start
, i
= 0; i
< slicelength
;
718 ((char *)ptr1
)[cur
] = ((char *)ptr2
)[i
];
724 PyErr_SetString(PyExc_TypeError
,
725 "buffer indices must be integers");
733 buffer_getreadbuf(PyBufferObject
*self
, Py_ssize_t idx
, void **pp
)
737 PyErr_SetString(PyExc_SystemError
,
738 "accessing non-existent buffer segment");
741 if (!get_buf(self
, pp
, &size
, READ_BUFFER
))
747 buffer_getwritebuf(PyBufferObject
*self
, Py_ssize_t idx
, void **pp
)
751 if ( self
->b_readonly
)
753 PyErr_SetString(PyExc_TypeError
, "buffer is read-only");
758 PyErr_SetString(PyExc_SystemError
,
759 "accessing non-existent buffer segment");
762 if (!get_buf(self
, pp
, &size
, WRITE_BUFFER
))
768 buffer_getsegcount(PyBufferObject
*self
, Py_ssize_t
*lenp
)
772 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
780 buffer_getcharbuf(PyBufferObject
*self
, Py_ssize_t idx
, const char **pp
)
785 PyErr_SetString(PyExc_SystemError
,
786 "accessing non-existent buffer segment");
789 if (!get_buf(self
, &ptr
, &size
, CHAR_BUFFER
))
791 *pp
= (const char *)ptr
;
795 static PySequenceMethods buffer_as_sequence
= {
796 (lenfunc
)buffer_length
, /*sq_length*/
797 (binaryfunc
)buffer_concat
, /*sq_concat*/
798 (ssizeargfunc
)buffer_repeat
, /*sq_repeat*/
799 (ssizeargfunc
)buffer_item
, /*sq_item*/
800 (ssizessizeargfunc
)buffer_slice
, /*sq_slice*/
801 (ssizeobjargproc
)buffer_ass_item
, /*sq_ass_item*/
802 (ssizessizeobjargproc
)buffer_ass_slice
, /*sq_ass_slice*/
805 static PyMappingMethods buffer_as_mapping
= {
806 (lenfunc
)buffer_length
,
807 (binaryfunc
)buffer_subscript
,
808 (objobjargproc
)buffer_ass_subscript
,
811 static PyBufferProcs buffer_as_buffer
= {
812 (readbufferproc
)buffer_getreadbuf
,
813 (writebufferproc
)buffer_getwritebuf
,
814 (segcountproc
)buffer_getsegcount
,
815 (charbufferproc
)buffer_getcharbuf
,
818 PyTypeObject PyBuffer_Type
= {
819 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
821 sizeof(PyBufferObject
),
823 (destructor
)buffer_dealloc
, /* tp_dealloc */
827 (cmpfunc
)buffer_compare
, /* tp_compare */
828 (reprfunc
)buffer_repr
, /* tp_repr */
829 0, /* tp_as_number */
830 &buffer_as_sequence
, /* tp_as_sequence */
831 &buffer_as_mapping
, /* tp_as_mapping */
832 (hashfunc
)buffer_hash
, /* tp_hash */
834 (reprfunc
)buffer_str
, /* tp_str */
835 PyObject_GenericGetAttr
, /* tp_getattro */
837 &buffer_as_buffer
, /* tp_as_buffer */
838 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GETCHARBUFFER
, /* tp_flags */
839 buffer_doc
, /* tp_doc */
842 0, /* tp_richcompare */
843 0, /* tp_weaklistoffset */
851 0, /* tp_descr_get */
852 0, /* tp_descr_set */
853 0, /* tp_dictoffset */
856 buffer_new
, /* tp_new */