2 /* Buffer object implementation */
20 _PyBuffer_FromMemory(PyObject
*base
, void *ptr
, int size
, int readonly
)
25 PyErr_SetString(PyExc_ValueError
,
26 "size must be zero or positive");
30 b
= PyObject_NEW(PyBufferObject
, &PyBuffer_Type
);
38 b
->b_readonly
= readonly
;
43 return (PyObject
*) b
;
47 _PyBuffer_FromObject(PyObject
*base
, int offset
, int size
,
48 getreadbufferproc proc
, int readonly
)
50 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
55 PyErr_SetString(PyExc_ValueError
,
56 "offset must be zero or positive");
60 if ( (*pb
->bf_getsegcount
)(base
, NULL
) != 1 )
62 PyErr_SetString(PyExc_TypeError
,
63 "single-segment buffer object expected");
66 if ( (count
= (*proc
)(base
, 0, &p
)) < 0 )
69 /* apply constraints to the start/end */
70 if ( size
== Py_END_OF_BUFFER
|| size
< 0 )
74 if ( offset
+ size
> count
)
75 size
= count
- offset
;
77 /* if the base object is another buffer, then "deref" it */
78 if ( PyBuffer_Check(base
) )
79 base
= ((PyBufferObject
*)base
)->b_base
;
81 return _PyBuffer_FromMemory(base
, (char *)p
+ offset
, size
, readonly
);
86 PyBuffer_FromObject(PyObject
*base
, int offset
, int size
)
88 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
91 pb
->bf_getreadbuffer
== NULL
||
92 pb
->bf_getsegcount
== NULL
)
94 PyErr_SetString(PyExc_TypeError
, "buffer object expected");
98 return _PyBuffer_FromObject(base
, offset
, size
,
99 pb
->bf_getreadbuffer
, 1);
103 PyBuffer_FromReadWriteObject(PyObject
*base
, int offset
, int size
)
105 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
108 pb
->bf_getwritebuffer
== NULL
||
109 pb
->bf_getsegcount
== NULL
)
111 PyErr_SetString(PyExc_TypeError
, "buffer object expected");
115 return _PyBuffer_FromObject(base
, offset
, size
,
116 (getreadbufferproc
)pb
->bf_getwritebuffer
,
121 PyBuffer_FromMemory(void *ptr
, int size
)
123 return _PyBuffer_FromMemory(NULL
, ptr
, size
, 1);
127 PyBuffer_FromReadWriteMemory(void *ptr
, int size
)
129 return _PyBuffer_FromMemory(NULL
, ptr
, size
, 0);
133 PyBuffer_New(int size
)
139 PyErr_SetString(PyExc_ValueError
,
140 "size must be zero or positive");
143 /* PyObject_New is inlined */
144 o
= PyObject_MALLOC(sizeof(*b
) + size
);
146 return PyErr_NoMemory();
147 b
= (PyBufferObject
*) PyObject_INIT(o
, &PyBuffer_Type
);
150 b
->b_ptr
= (void *)(b
+ 1);
163 buffer_dealloc(PyBufferObject
*self
)
165 Py_XDECREF(self
->b_base
);
170 buffer_compare(PyBufferObject
*self
, PyBufferObject
*other
)
172 int len_self
= self
->b_size
;
173 int len_other
= other
->b_size
;
174 int min_len
= (len_self
< len_other
) ? len_self
: len_other
;
177 cmp
= memcmp(self
->b_ptr
, other
->b_ptr
, min_len
);
181 return (len_self
< len_other
) ? -1 : (len_self
> len_other
) ? 1 : 0;
185 buffer_repr(PyBufferObject
*self
)
188 char *status
= self
->b_readonly
? "read-only" : "read-write";
190 if ( self
->b_base
== NULL
)
192 sprintf(buf
, "<%s buffer ptr %p, size %d at %p>",
200 sprintf(buf
, "<%s buffer for %p, ptr %p, size %d at %p>",
208 return PyString_FromString(buf
);
212 buffer_hash(PyBufferObject
*self
)
215 register unsigned char *p
;
219 if ( self
->b_hash
!= -1 )
223 if ( !self
->b_readonly
)
225 /* ### use different wording, since this is conditional? */
226 PyErr_SetString(PyExc_TypeError
, "unhashable type");
231 p
= (unsigned char *) self
->b_ptr
;
234 x
= (1000003*x
) ^ *p
++;
245 buffer_str(PyBufferObject
*self
)
247 return PyString_FromStringAndSize(self
->b_ptr
, self
->b_size
);
250 /* Sequence methods */
253 buffer_length(PyBufferObject
*self
)
259 buffer_concat(PyBufferObject
*self
, PyObject
*other
)
261 PyBufferProcs
*pb
= other
->ob_type
->tp_as_buffer
;
268 pb
->bf_getreadbuffer
== NULL
||
269 pb
->bf_getsegcount
== NULL
)
274 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
276 /* ### use a different exception type/message? */
277 PyErr_SetString(PyExc_TypeError
,
278 "single-segment buffer object expected");
282 /* optimize special case */
283 if ( self
->b_size
== 0 )
289 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p2
)) < 0 )
292 /* optimize special case */
296 return (PyObject
*)self
;
299 ob
= PyString_FromStringAndSize(NULL
, self
->b_size
+ count
);
300 p1
= PyString_AS_STRING(ob
);
301 memcpy(p1
, self
->b_ptr
, self
->b_size
);
302 memcpy(p1
+ self
->b_size
, p2
, count
);
304 /* there is an extra byte in the string object, so this is safe */
305 p1
[self
->b_size
+ count
] = '\0';
311 buffer_repeat(PyBufferObject
*self
, int count
)
315 void *ptr
= self
->b_ptr
;
316 int size
= self
->b_size
;
320 ob
= PyString_FromStringAndSize(NULL
, size
* count
);
324 p
= PyString_AS_STRING(ob
);
327 memcpy(p
, ptr
, size
);
331 /* there is an extra byte in the string object, so this is safe */
338 buffer_item(PyBufferObject
*self
, int idx
)
340 if ( idx
< 0 || idx
>= self
->b_size
)
342 PyErr_SetString(PyExc_IndexError
, "buffer index out of range");
345 return PyString_FromStringAndSize((char *)self
->b_ptr
+ idx
, 1);
349 buffer_slice(PyBufferObject
*self
, int left
, int right
)
355 if ( right
> self
->b_size
)
356 right
= self
->b_size
;
357 if ( left
== 0 && right
== self
->b_size
)
361 return (PyObject
*)self
;
365 return PyString_FromStringAndSize((char *)self
->b_ptr
+ left
,
370 buffer_ass_item(PyBufferObject
*self
, int idx
, PyObject
*other
)
376 if ( self
->b_readonly
) {
377 PyErr_SetString(PyExc_TypeError
,
378 "buffer is read-only");
382 if (idx
< 0 || idx
>= self
->b_size
) {
383 PyErr_SetString(PyExc_IndexError
,
384 "buffer assignment index out of range");
388 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
390 pb
->bf_getreadbuffer
== NULL
||
391 pb
->bf_getsegcount
== NULL
)
396 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
398 /* ### use a different exception type/message? */
399 PyErr_SetString(PyExc_TypeError
,
400 "single-segment buffer object expected");
404 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p
)) < 0 )
407 PyErr_SetString(PyExc_TypeError
,
408 "right operand must be a single byte");
412 ((char *)self
->b_ptr
)[idx
] = *(char *)p
;
417 buffer_ass_slice(PyBufferObject
*self
, int left
, int right
, PyObject
*other
)
424 if ( self
->b_readonly
) {
425 PyErr_SetString(PyExc_TypeError
,
426 "buffer is read-only");
430 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
432 pb
->bf_getreadbuffer
== NULL
||
433 pb
->bf_getsegcount
== NULL
)
438 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
440 /* ### use a different exception type/message? */
441 PyErr_SetString(PyExc_TypeError
,
442 "single-segment buffer object expected");
445 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p
)) < 0 )
450 else if ( left
> self
->b_size
)
454 else if ( right
> self
->b_size
)
455 right
= self
->b_size
;
456 slice_len
= right
- left
;
458 if ( count
!= slice_len
) {
461 "right operand length must match slice length");
466 memcpy((char *)self
->b_ptr
+ left
, p
, slice_len
);
474 buffer_getreadbuf(PyBufferObject
*self
, int idx
, void **pp
)
477 PyErr_SetString(PyExc_SystemError
,
478 "accessing non-existent buffer segment");
486 buffer_getwritebuf(PyBufferObject
*self
, int idx
, void **pp
)
488 if ( self
->b_readonly
)
490 PyErr_SetString(PyExc_TypeError
, "buffer is read-only");
493 return buffer_getreadbuf(self
, idx
, pp
);
497 buffer_getsegcount(PyBufferObject
*self
, int *lenp
)
500 *lenp
= self
->b_size
;
505 buffer_getcharbuf(PyBufferObject
*self
, int idx
, const char **pp
)
508 PyErr_SetString(PyExc_SystemError
,
509 "accessing non-existent buffer segment");
512 *pp
= (const char *)self
->b_ptr
;
517 static PySequenceMethods buffer_as_sequence
= {
518 (inquiry
)buffer_length
, /*sq_length*/
519 (binaryfunc
)buffer_concat
, /*sq_concat*/
520 (intargfunc
)buffer_repeat
, /*sq_repeat*/
521 (intargfunc
)buffer_item
, /*sq_item*/
522 (intintargfunc
)buffer_slice
, /*sq_slice*/
523 (intobjargproc
)buffer_ass_item
, /*sq_ass_item*/
524 (intintobjargproc
)buffer_ass_slice
, /*sq_ass_slice*/
527 static PyBufferProcs buffer_as_buffer
= {
528 (getreadbufferproc
)buffer_getreadbuf
,
529 (getwritebufferproc
)buffer_getwritebuf
,
530 (getsegcountproc
)buffer_getsegcount
,
531 (getcharbufferproc
)buffer_getcharbuf
,
534 PyTypeObject PyBuffer_Type
= {
535 PyObject_HEAD_INIT(&PyType_Type
)
538 sizeof(PyBufferObject
),
540 (destructor
)buffer_dealloc
, /*tp_dealloc*/
544 (cmpfunc
)buffer_compare
, /*tp_compare*/
545 (reprfunc
)buffer_repr
, /*tp_repr*/
547 &buffer_as_sequence
, /*tp_as_sequence*/
549 (hashfunc
)buffer_hash
, /*tp_hash*/
551 (reprfunc
)buffer_str
, /*tp_str*/
554 &buffer_as_buffer
, /*tp_as_buffer*/
555 Py_TPFLAGS_DEFAULT
, /*tp_flags*/