1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Buffer object implementation */
50 _PyBuffer_FromMemory(base
, ptr
, size
, readonly
)
58 b
= PyObject_NEW(PyBufferObject
, &PyBuffer_Type
);
66 b
->b_readonly
= readonly
;
71 return (PyObject
*) b
;
75 _PyBuffer_FromObject(base
, offset
, size
, proc
, readonly
)
79 getreadbufferproc proc
;
82 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
86 if ( (*pb
->bf_getsegcount
)(base
, NULL
) != 1 )
88 PyErr_SetString(PyExc_TypeError
, "single-segment buffer object expected");
91 if ( (count
= (*proc
)(base
, 0, &p
)) < 0 )
94 /* apply constraints to the start/end */
95 if ( size
== Py_END_OF_BUFFER
)
99 if ( offset
+ size
> count
)
100 size
= count
- offset
;
102 /* if the base object is another buffer, then "deref" it */
103 if ( PyBuffer_Check(base
) )
104 base
= ((PyBufferObject
*)base
)->b_base
;
106 return _PyBuffer_FromMemory(base
, (char *)p
+ offset
, size
, readonly
);
111 PyBuffer_FromObject(base
, offset
, size
)
116 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
119 pb
->bf_getreadbuffer
== NULL
||
120 pb
->bf_getsegcount
== NULL
)
122 PyErr_SetString(PyExc_TypeError
, "buffer object expected");
126 return _PyBuffer_FromObject(base
, offset
, size
, pb
->bf_getreadbuffer
, 1);
130 PyBuffer_FromReadWriteObject(base
, offset
, size
)
135 PyBufferProcs
*pb
= base
->ob_type
->tp_as_buffer
;
138 pb
->bf_getwritebuffer
== NULL
||
139 pb
->bf_getsegcount
== NULL
)
141 PyErr_SetString(PyExc_TypeError
, "buffer object expected");
145 return _PyBuffer_FromObject(base
, offset
, size
, (getreadbufferproc
)pb
->bf_getwritebuffer
, 0);
149 PyBuffer_FromMemory(ptr
, size
)
153 return _PyBuffer_FromMemory(NULL
, ptr
, size
, 1);
157 PyBuffer_FromReadWriteMemory(ptr
, size
)
161 return _PyBuffer_FromMemory(NULL
, ptr
, size
, 0);
170 b
= (PyBufferObject
*)malloc(sizeof(*b
) + size
);
173 b
->ob_type
= &PyBuffer_Type
;
174 _Py_NewReference((PyObject
*)b
);
177 b
->b_ptr
= (void *)(b
+ 1);
184 return (PyObject
*) b
;
191 PyBufferObject
*self
;
193 Py_XDECREF(self
->b_base
);
198 buffer_compare(self
, other
)
199 PyBufferObject
*self
;
200 PyBufferObject
*other
;
202 int len_self
= self
->b_size
;
203 int len_other
= other
->b_size
;
204 int min_len
= (len_self
< len_other
) ? len_self
: len_other
;
207 cmp
= memcmp(self
->b_ptr
, other
->b_ptr
, min_len
);
211 return (len_self
< len_other
) ? -1 : (len_self
> len_other
) ? 1 : 0;
216 PyBufferObject
*self
;
219 char *status
= self
->b_readonly
? "read-only" : "read-write";
221 if ( self
->b_base
== NULL
)
223 sprintf(buf
, "<%s buffer ptr %lx, size %d at %lx>",
231 sprintf(buf
, "<%s buffer for %lx, ptr %lx, size %d at %lx>",
239 return PyString_FromString(buf
);
244 PyBufferObject
*self
;
247 register unsigned char *p
;
251 if ( self
->b_hash
!= -1 )
255 if ( !self
->b_readonly
)
257 /* ### use different wording, since this is conditional? */
258 PyErr_SetString(PyExc_TypeError
, "unhashable type");
263 p
= (unsigned char *) self
->b_ptr
;
266 x
= (1000003*x
) ^ *p
++;
278 PyBufferObject
*self
;
280 return PyString_FromStringAndSize(self
->b_ptr
, self
->b_size
);
283 /* Sequence methods */
287 PyBufferObject
*self
;
293 buffer_concat(self
, other
)
294 PyBufferObject
*self
;
297 PyBufferProcs
*pb
= other
->ob_type
->tp_as_buffer
;
304 pb
->bf_getreadbuffer
== NULL
||
305 pb
->bf_getsegcount
== NULL
)
310 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
312 /* ### use a different exception type/message? */
313 PyErr_SetString(PyExc_TypeError
, "single-segment buffer object expected");
317 /* optimize special case */
318 if ( self
->b_size
== 0 )
324 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p2
)) < 0 )
327 /* optimize special case */
331 return (PyObject
*)self
;
334 ob
= PyString_FromStringAndSize(NULL
, self
->b_size
+ count
);
335 p1
= PyString_AS_STRING(ob
);
336 memcpy(p1
, self
->b_ptr
, self
->b_size
);
337 memcpy(p1
+ self
->b_size
, p2
, count
);
339 /* there is an extra byte in the string object, so this is safe */
340 p1
[self
->b_size
+ count
] = '\0';
346 buffer_repeat(self
, count
)
347 PyBufferObject
*self
;
352 void *ptr
= self
->b_ptr
;
353 int size
= self
->b_size
;
357 ob
= PyString_FromStringAndSize(NULL
, size
* count
);
361 p
= PyString_AS_STRING(ob
);
364 memcpy(p
, ptr
, size
);
368 /* there is an extra byte in the string object, so this is safe */
375 buffer_item(self
, idx
)
376 PyBufferObject
*self
;
379 if ( idx
< 0 || idx
>= self
->b_size
)
381 PyErr_SetString(PyExc_IndexError
, "buffer index out of range");
384 return PyString_FromStringAndSize((char *)self
->b_ptr
+ idx
, 1);
388 buffer_slice(self
, left
, right
)
389 PyBufferObject
*self
;
397 if ( right
> self
->b_size
)
398 right
= self
->b_size
;
399 if ( left
== 0 && right
== self
->b_size
)
403 return (PyObject
*)self
;
407 return PyString_FromStringAndSize((char *)self
->b_ptr
+ left
, right
- left
);
411 buffer_ass_item(self
, idx
, other
)
412 PyBufferObject
*self
;
420 if ( self
->b_readonly
) {
421 PyErr_SetString(PyExc_TypeError
,
422 "buffer is read-only");
426 if (idx
< 0 || idx
>= self
->b_size
) {
427 PyErr_SetString(PyExc_IndexError
,
428 "buffer assignment index out of range");
432 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
434 pb
->bf_getreadbuffer
== NULL
||
435 pb
->bf_getsegcount
== NULL
)
440 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
442 /* ### use a different exception type/message? */
443 PyErr_SetString(PyExc_TypeError
, "single-segment buffer object expected");
447 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p
)) < 0 )
450 PyErr_SetString(PyExc_TypeError
,
451 "right operand must be a single byte");
455 ((char *)self
->b_ptr
)[idx
] = *(char *)p
;
460 buffer_ass_slice(self
, left
, right
, other
)
461 PyBufferObject
*self
;
471 if ( self
->b_readonly
) {
472 PyErr_SetString(PyExc_TypeError
,
473 "buffer is read-only");
477 pb
= other
? other
->ob_type
->tp_as_buffer
: NULL
;
479 pb
->bf_getreadbuffer
== NULL
||
480 pb
->bf_getsegcount
== NULL
)
485 if ( (*pb
->bf_getsegcount
)(other
, NULL
) != 1 )
487 /* ### use a different exception type/message? */
488 PyErr_SetString(PyExc_TypeError
, "single-segment buffer object expected");
491 if ( (count
= (*pb
->bf_getreadbuffer
)(other
, 0, &p
)) < 0 )
496 else if ( left
> self
->b_size
)
500 else if ( right
> self
->b_size
)
501 right
= self
->b_size
;
502 slice_len
= right
- left
;
504 if ( count
!= slice_len
) {
505 PyErr_SetString(PyExc_TypeError
,
506 "right operand length must match slice length");
511 memcpy((char *)self
->b_ptr
+ left
, p
, slice_len
);
519 buffer_getreadbuf(self
, idx
, pp
)
520 PyBufferObject
*self
;
525 PyErr_SetString(PyExc_SystemError
,
526 "accessing non-existent buffer segment");
534 buffer_getwritebuf(self
, idx
, pp
)
535 PyBufferObject
*self
;
539 if ( self
->b_readonly
)
541 PyErr_SetString(PyExc_TypeError
, "buffer is read-only");
544 return buffer_getreadbuf(self
, idx
, pp
);
548 buffer_getsegcount(self
, lenp
)
549 PyBufferObject
*self
;
553 *lenp
= self
->b_size
;
558 buffer_getcharbuf(self
, idx
, pp
)
559 PyBufferObject
*self
;
564 PyErr_SetString(PyExc_SystemError
,
565 "accessing non-existent buffer segment");
568 *pp
= (const char *)self
->b_ptr
;
573 static PySequenceMethods buffer_as_sequence
= {
574 (inquiry
)buffer_length
, /*sq_length*/
575 (binaryfunc
)buffer_concat
, /*sq_concat*/
576 (intargfunc
)buffer_repeat
, /*sq_repeat*/
577 (intargfunc
)buffer_item
, /*sq_item*/
578 (intintargfunc
)buffer_slice
, /*sq_slice*/
579 (intobjargproc
)buffer_ass_item
, /*sq_ass_item*/
580 (intintobjargproc
)buffer_ass_slice
, /*sq_ass_slice*/
583 static PyBufferProcs buffer_as_buffer
= {
584 (getreadbufferproc
)buffer_getreadbuf
,
585 (getwritebufferproc
)buffer_getwritebuf
,
586 (getsegcountproc
)buffer_getsegcount
,
587 (getcharbufferproc
)buffer_getcharbuf
,
590 PyTypeObject PyBuffer_Type
= {
591 PyObject_HEAD_INIT(&PyType_Type
)
594 sizeof(PyBufferObject
),
596 (destructor
)buffer_dealloc
, /*tp_dealloc*/
600 (cmpfunc
)buffer_compare
, /*tp_compare*/
601 (reprfunc
)buffer_repr
, /*tp_repr*/
603 &buffer_as_sequence
, /*tp_as_sequence*/
605 (hashfunc
)buffer_hash
, /*tp_hash*/
607 (reprfunc
)buffer_str
, /*tp_str*/
610 &buffer_as_buffer
, /*tp_as_buffer*/
611 Py_TPFLAGS_DEFAULT
, /*tp_flags*/