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 (*size
> count
- offset
)
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
;
338 We make the hash of the empty buffer be 0, rather than using
339 (prefix ^ suffix), since this slightly obfuscates the hash secret
345 x
= _Py_HashSecret
.prefix
;
348 x
= (1000003*x
) ^ *p
++;
350 x
^= _Py_HashSecret
.suffix
;
358 buffer_str(PyBufferObject
*self
)
362 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
364 return PyString_FromStringAndSize((const char *)ptr
, size
);
367 /* Sequence methods */
370 buffer_length(PyBufferObject
*self
)
374 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
380 buffer_concat(PyBufferObject
*self
, PyObject
*other
)
382 PyBufferProcs
*pb
= other
->ob_type
->tp_as_buffer
;
386 Py_ssize_t size
, count
;
389 pb
->bf_getreadbuffer
== NULL
||
390 pb
->bf_getsegcount
== NULL
)
395 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
397 /* ### use a different exception type/message? */
398 PyErr_SetString(PyExc_TypeError
,
399 "single-segment buffer object expected");
403 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
406 /* optimize special case */
413 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
416 assert(count
<= PY_SIZE_MAX
- size
);
418 ob
= PyString_FromStringAndSize(NULL
, size
+ count
);
421 p
= PyString_AS_STRING(ob
);
422 memcpy(p
, ptr1
, size
);
423 memcpy(p
+ size
, ptr2
, count
);
425 /* there is an extra byte in the string object, so this is safe */
426 p
[size
+ count
] = '\0';
432 buffer_repeat(PyBufferObject
*self
, Py_ssize_t count
)
441 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
443 if (count
> PY_SSIZE_T_MAX
/ size
) {
444 PyErr_SetString(PyExc_MemoryError
, "result too large");
447 ob
= PyString_FromStringAndSize(NULL
, size
* count
);
451 p
= PyString_AS_STRING(ob
);
454 memcpy(p
, ptr
, size
);
458 /* there is an extra byte in the string object, so this is safe */
465 buffer_item(PyBufferObject
*self
, Py_ssize_t idx
)
469 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
471 if ( idx
< 0 || idx
>= size
) {
472 PyErr_SetString(PyExc_IndexError
, "buffer index out of range");
475 return PyString_FromStringAndSize((char *)ptr
+ idx
, 1);
479 buffer_slice(PyBufferObject
*self
, Py_ssize_t left
, Py_ssize_t right
)
483 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
493 return PyString_FromStringAndSize((char *)ptr
+ left
,
498 buffer_subscript(PyBufferObject
*self
, PyObject
*item
)
503 if (!get_buf(self
, &p
, &size
, ANY_BUFFER
))
505 if (PyIndex_Check(item
)) {
506 Py_ssize_t i
= PyNumber_AsSsize_t(item
, PyExc_IndexError
);
507 if (i
== -1 && PyErr_Occurred())
511 return buffer_item(self
, i
);
513 else if (PySlice_Check(item
)) {
514 Py_ssize_t start
, stop
, step
, slicelength
, cur
, i
;
516 if (PySlice_GetIndicesEx((PySliceObject
*)item
, size
,
517 &start
, &stop
, &step
, &slicelength
) < 0) {
521 if (slicelength
<= 0)
522 return PyString_FromStringAndSize("", 0);
524 return PyString_FromStringAndSize((char *)p
+ start
,
528 char *source_buf
= (char *)p
;
529 char *result_buf
= (char *)PyMem_Malloc(slicelength
);
531 if (result_buf
== NULL
)
532 return PyErr_NoMemory();
534 for (cur
= start
, i
= 0; i
< slicelength
;
536 result_buf
[i
] = source_buf
[cur
];
539 result
= PyString_FromStringAndSize(result_buf
,
541 PyMem_Free(result_buf
);
546 PyErr_SetString(PyExc_TypeError
,
547 "sequence index must be integer");
553 buffer_ass_item(PyBufferObject
*self
, Py_ssize_t idx
, PyObject
*other
)
560 if ( self
->b_readonly
) {
561 PyErr_SetString(PyExc_TypeError
,
562 "buffer is read-only");
566 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
569 if (idx
< 0 || idx
>= size
) {
570 PyErr_SetString(PyExc_IndexError
,
571 "buffer assignment index out of range");
575 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
577 pb
->bf_getreadbuffer
== NULL
||
578 pb
->bf_getsegcount
== NULL
)
583 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
585 /* ### use a different exception type/message? */
586 PyErr_SetString(PyExc_TypeError
,
587 "single-segment buffer object expected");
591 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
594 PyErr_SetString(PyExc_TypeError
,
595 "right operand must be a single byte");
599 ((char *)ptr1
)[idx
] = *(char *)ptr2
;
604 buffer_ass_slice(PyBufferObject
*self
, Py_ssize_t left
, Py_ssize_t right
, PyObject
*other
)
609 Py_ssize_t slice_len
;
612 if ( self
->b_readonly
) {
613 PyErr_SetString(PyExc_TypeError
,
614 "buffer is read-only");
618 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
620 pb
->bf_getreadbuffer
== NULL
||
621 pb
->bf_getsegcount
== NULL
)
626 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
628 /* ### use a different exception type/message? */
629 PyErr_SetString(PyExc_TypeError
,
630 "single-segment buffer object expected");
633 if (!get_buf(self
, &ptr1
, &size
, ANY_BUFFER
))
635 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &ptr2
)) < 0 )
640 else if ( left
> size
)
644 else if ( right
> size
)
646 slice_len
= right
- left
;
648 if ( count
!= slice_len
) {
651 "right operand length must match slice length");
656 memcpy((char *)ptr1
+ left
, ptr2
, slice_len
);
662 buffer_ass_subscript(PyBufferObject
*self
, PyObject
*item
, PyObject
*value
)
667 Py_ssize_t othersize
;
669 if ( self
->b_readonly
) {
670 PyErr_SetString(PyExc_TypeError
,
671 "buffer is read-only");
675 pb
= value
? value
->ob_type
->tp_as_buffer
: NULL
;
677 pb
->bf_getreadbuffer
== NULL
||
678 pb
->bf_getsegcount
== NULL
)
683 if ( (*pb
->bf_getsegcount
)(value
, NULL
) != 1 )
685 /* ### use a different exception type/message? */
686 PyErr_SetString(PyExc_TypeError
,
687 "single-segment buffer object expected");
690 if (!get_buf(self
, &ptr1
, &selfsize
, ANY_BUFFER
))
692 if (PyIndex_Check(item
)) {
693 Py_ssize_t i
= PyNumber_AsSsize_t(item
, PyExc_IndexError
);
694 if (i
== -1 && PyErr_Occurred())
698 return buffer_ass_item(self
, i
, value
);
700 else if (PySlice_Check(item
)) {
701 Py_ssize_t start
, stop
, step
, slicelength
;
703 if (PySlice_GetIndicesEx((PySliceObject
*)item
, selfsize
,
704 &start
, &stop
, &step
, &slicelength
) < 0)
707 if ((othersize
= (*pb
->bf_getreadbuffer
)(value
, 0, &ptr2
)) < 0)
710 if (othersize
!= slicelength
) {
713 "right operand length must match slice length");
717 if (slicelength
== 0)
719 else if (step
== 1) {
720 memcpy((char *)ptr1
+ start
, ptr2
, slicelength
);
726 for (cur
= start
, i
= 0; i
< slicelength
;
728 ((char *)ptr1
)[cur
] = ((char *)ptr2
)[i
];
734 PyErr_SetString(PyExc_TypeError
,
735 "buffer indices must be integers");
743 buffer_getreadbuf(PyBufferObject
*self
, Py_ssize_t idx
, void **pp
)
747 PyErr_SetString(PyExc_SystemError
,
748 "accessing non-existent buffer segment");
751 if (!get_buf(self
, pp
, &size
, READ_BUFFER
))
757 buffer_getwritebuf(PyBufferObject
*self
, Py_ssize_t idx
, void **pp
)
761 if ( self
->b_readonly
)
763 PyErr_SetString(PyExc_TypeError
, "buffer is read-only");
768 PyErr_SetString(PyExc_SystemError
,
769 "accessing non-existent buffer segment");
772 if (!get_buf(self
, pp
, &size
, WRITE_BUFFER
))
778 buffer_getsegcount(PyBufferObject
*self
, Py_ssize_t
*lenp
)
782 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
790 buffer_getcharbuf(PyBufferObject
*self
, Py_ssize_t idx
, const char **pp
)
795 PyErr_SetString(PyExc_SystemError
,
796 "accessing non-existent buffer segment");
799 if (!get_buf(self
, &ptr
, &size
, CHAR_BUFFER
))
801 *pp
= (const char *)ptr
;
805 static int buffer_getbuffer(PyBufferObject
*self
, Py_buffer
*buf
, int flags
)
809 if (!get_buf(self
, &ptr
, &size
, ANY_BUFFER
))
811 return PyBuffer_FillInfo(buf
, (PyObject
*)self
, ptr
, size
,
812 self
->b_readonly
, flags
);
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*/
825 static PyMappingMethods buffer_as_mapping
= {
826 (lenfunc
)buffer_length
,
827 (binaryfunc
)buffer_subscript
,
828 (objobjargproc
)buffer_ass_subscript
,
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
,
839 PyTypeObject PyBuffer_Type
= {
840 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
842 sizeof(PyBufferObject
),
844 (destructor
)buffer_dealloc
, /* tp_dealloc */
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 */
855 (reprfunc
)buffer_str
, /* tp_str */
856 PyObject_GenericGetAttr
, /* tp_getattro */
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 */
863 0, /* tp_richcompare */
864 0, /* tp_weaklistoffset */
872 0, /* tp_descr_get */
873 0, /* tp_descr_set */
874 0, /* tp_dictoffset */
877 buffer_new
, /* tp_new */