2 /* Buffer object implementation */
18 _PyBuffer_FromMemory(PyObject
*base
, void *ptr
, int size
, int readonly
)
23 PyErr_SetString(PyExc_ValueError
,
24 "size must be zero or positive");
28 b
= PyObject_NEW(PyBufferObject
, &PyBuffer_Type
);
36 b
->b_readonly
= readonly
;
39 return (PyObject
*) b
;
43 _PyBuffer_FromObject(PyObject
*base
, int offset
, int size
,
44 getreadbufferproc proc
, int readonly
)
46 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
51 PyErr_SetString(PyExc_ValueError
,
52 "offset must be zero or positive");
56 if ( (*pb
->bf_getsegcount
)(base
, NULL
) != 1 )
58 PyErr_SetString(PyExc_TypeError
,
59 "single-segment buffer object expected");
62 if ( (count
= (*proc
)(base
, 0, &p
)) < 0 )
65 /* apply constraints to the start/end */
66 if ( size
== Py_END_OF_BUFFER
|| size
< 0 )
70 if ( offset
+ size
> count
)
71 size
= count
- offset
;
73 /* if the base object is another buffer, then "deref" it,
74 * except if the base of the other buffer is NULL
76 if ( PyBuffer_Check(base
) && (((PyBufferObject
*)base
)->b_base
) )
77 base
= ((PyBufferObject
*)base
)->b_base
;
79 return _PyBuffer_FromMemory(base
, (char *)p
+ offset
, size
, readonly
);
84 PyBuffer_FromObject(PyObject
*base
, int offset
, int size
)
86 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
89 pb
->bf_getreadbuffer
== NULL
||
90 pb
->bf_getsegcount
== NULL
)
92 PyErr_SetString(PyExc_TypeError
, "buffer object expected");
96 return _PyBuffer_FromObject(base
, offset
, size
,
97 pb
->bf_getreadbuffer
, 1);
101 PyBuffer_FromReadWriteObject(PyObject
*base
, int offset
, int size
)
103 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
106 pb
->bf_getwritebuffer
== NULL
||
107 pb
->bf_getsegcount
== NULL
)
109 PyErr_SetString(PyExc_TypeError
, "buffer object expected");
113 return _PyBuffer_FromObject(base
, offset
, size
,
114 (getreadbufferproc
)pb
->bf_getwritebuffer
,
119 PyBuffer_FromMemory(void *ptr
, int size
)
121 return _PyBuffer_FromMemory(NULL
, ptr
, size
, 1);
125 PyBuffer_FromReadWriteMemory(void *ptr
, int size
)
127 return _PyBuffer_FromMemory(NULL
, ptr
, size
, 0);
131 PyBuffer_New(int size
)
137 PyErr_SetString(PyExc_ValueError
,
138 "size must be zero or positive");
141 /* Inline PyObject_New */
142 o
= PyObject_MALLOC(sizeof(*b
) + size
);
144 return PyErr_NoMemory();
145 b
= (PyBufferObject
*) PyObject_INIT(o
, &PyBuffer_Type
);
148 b
->b_ptr
= (void *)(b
+ 1);
159 buffer_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kw
)
163 int size
= Py_END_OF_BUFFER
;
165 if ( !PyArg_ParseTuple(args
, "O|ii:buffer", &ob
, &offset
, &size
) )
167 return PyBuffer_FromObject(ob
, offset
, size
);
170 PyDoc_STRVAR(buffer_doc
,
171 "buffer(object [, offset[, size]])\n\
173 Create a new buffer object which references the given object.\n\
174 The buffer will reference a slice of the target object from the\n\
175 start of the object (or at the specified offset). The slice will\n\
176 extend to the end of the target object (or with the specified size).");
180 buffer_dealloc(PyBufferObject
*self
)
182 Py_XDECREF(self
->b_base
);
187 buffer_compare(PyBufferObject
*self
, PyBufferObject
*other
)
189 int len_self
= self
->b_size
;
190 int len_other
= other
->b_size
;
191 int min_len
= (len_self
< len_other
) ? len_self
: len_other
;
194 cmp
= memcmp(self
->b_ptr
, other
->b_ptr
, min_len
);
198 return (len_self
< len_other
) ? -1 : (len_self
> len_other
) ? 1 : 0;
202 buffer_repr(PyBufferObject
*self
)
204 char *status
= self
->b_readonly
? "read-only" : "read-write";
206 if ( self
->b_base
== NULL
)
207 return PyString_FromFormat("<%s buffer ptr %p, size %d at %p>",
213 return PyString_FromFormat(
214 "<%s buffer for %p, ptr %p, size %d at %p>",
223 buffer_hash(PyBufferObject
*self
)
226 register unsigned char *p
;
229 if ( self
->b_hash
!= -1 )
232 if ( !self
->b_readonly
)
234 /* ### use different wording, since this is conditional? */
235 PyErr_SetString(PyExc_TypeError
, "unhashable type");
240 p
= (unsigned char *) self
->b_ptr
;
243 x
= (1000003*x
) ^ *p
++;
252 buffer_str(PyBufferObject
*self
)
254 return PyString_FromStringAndSize(self
->b_ptr
, self
->b_size
);
257 /* Sequence methods */
260 buffer_length(PyBufferObject
*self
)
266 buffer_concat(PyBufferObject
*self
, PyObject
*other
)
268 PyBufferProcs
*pb
= other
->ob_type
->tp_as_buffer
;
275 pb
->bf_getreadbuffer
== NULL
||
276 pb
->bf_getsegcount
== NULL
)
281 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
283 /* ### use a different exception type/message? */
284 PyErr_SetString(PyExc_TypeError
,
285 "single-segment buffer object expected");
289 /* optimize special case */
290 if ( self
->b_size
== 0 )
296 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p2
)) < 0 )
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
;
359 return PyString_FromStringAndSize((char *)self
->b_ptr
+ left
,
364 buffer_ass_item(PyBufferObject
*self
, int idx
, PyObject
*other
)
370 if ( self
->b_readonly
) {
371 PyErr_SetString(PyExc_TypeError
,
372 "buffer is read-only");
376 if (idx
< 0 || idx
>= self
->b_size
) {
377 PyErr_SetString(PyExc_IndexError
,
378 "buffer assignment index out of range");
382 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
384 pb
->bf_getreadbuffer
== NULL
||
385 pb
->bf_getsegcount
== NULL
)
390 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
392 /* ### use a different exception type/message? */
393 PyErr_SetString(PyExc_TypeError
,
394 "single-segment buffer object expected");
398 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p
)) < 0 )
401 PyErr_SetString(PyExc_TypeError
,
402 "right operand must be a single byte");
406 ((char *)self
->b_ptr
)[idx
] = *(char *)p
;
411 buffer_ass_slice(PyBufferObject
*self
, int left
, int right
, PyObject
*other
)
418 if ( self
->b_readonly
) {
419 PyErr_SetString(PyExc_TypeError
,
420 "buffer is read-only");
424 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
426 pb
->bf_getreadbuffer
== NULL
||
427 pb
->bf_getsegcount
== NULL
)
432 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
434 /* ### use a different exception type/message? */
435 PyErr_SetString(PyExc_TypeError
,
436 "single-segment buffer object expected");
439 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p
)) < 0 )
444 else if ( left
> self
->b_size
)
448 else if ( right
> self
->b_size
)
449 right
= self
->b_size
;
450 slice_len
= right
- left
;
452 if ( count
!= slice_len
) {
455 "right operand length must match slice length");
460 memcpy((char *)self
->b_ptr
+ left
, p
, slice_len
);
468 buffer_getreadbuf(PyBufferObject
*self
, int idx
, void **pp
)
471 PyErr_SetString(PyExc_SystemError
,
472 "accessing non-existent buffer segment");
480 buffer_getwritebuf(PyBufferObject
*self
, int idx
, void **pp
)
482 if ( self
->b_readonly
)
484 PyErr_SetString(PyExc_TypeError
, "buffer is read-only");
487 return buffer_getreadbuf(self
, idx
, pp
);
491 buffer_getsegcount(PyBufferObject
*self
, int *lenp
)
494 *lenp
= self
->b_size
;
499 buffer_getcharbuf(PyBufferObject
*self
, int idx
, const char **pp
)
502 PyErr_SetString(PyExc_SystemError
,
503 "accessing non-existent buffer segment");
506 *pp
= (const char *)self
->b_ptr
;
511 static PySequenceMethods buffer_as_sequence
= {
512 (inquiry
)buffer_length
, /*sq_length*/
513 (binaryfunc
)buffer_concat
, /*sq_concat*/
514 (intargfunc
)buffer_repeat
, /*sq_repeat*/
515 (intargfunc
)buffer_item
, /*sq_item*/
516 (intintargfunc
)buffer_slice
, /*sq_slice*/
517 (intobjargproc
)buffer_ass_item
, /*sq_ass_item*/
518 (intintobjargproc
)buffer_ass_slice
, /*sq_ass_slice*/
521 static PyBufferProcs buffer_as_buffer
= {
522 (getreadbufferproc
)buffer_getreadbuf
,
523 (getwritebufferproc
)buffer_getwritebuf
,
524 (getsegcountproc
)buffer_getsegcount
,
525 (getcharbufferproc
)buffer_getcharbuf
,
528 PyTypeObject PyBuffer_Type
= {
529 PyObject_HEAD_INIT(&PyType_Type
)
532 sizeof(PyBufferObject
),
534 (destructor
)buffer_dealloc
, /* tp_dealloc */
538 (cmpfunc
)buffer_compare
, /* tp_compare */
539 (reprfunc
)buffer_repr
, /* tp_repr */
540 0, /* tp_as_number */
541 &buffer_as_sequence
, /* tp_as_sequence */
542 0, /* tp_as_mapping */
543 (hashfunc
)buffer_hash
, /* tp_hash */
545 (reprfunc
)buffer_str
, /* tp_str */
546 PyObject_GenericGetAttr
, /* tp_getattro */
548 &buffer_as_buffer
, /* tp_as_buffer */
549 Py_TPFLAGS_DEFAULT
, /* tp_flags */
550 buffer_doc
, /* tp_doc */
553 0, /* tp_richcompare */
554 0, /* tp_weaklistoffset */
562 0, /* tp_descr_get */
563 0, /* tp_descr_set */
564 0, /* tp_dictoffset */
567 buffer_new
, /* tp_new */