blob: 91f58c906b0852e83cef87a05a8221385cf91fc9 [file] [log] [blame]
Guido van Rossum2e19bd71998-10-07 14:36:10 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossum2e19bd71998-10-07 14:36:10 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum2e19bd71998-10-07 14:36:10 +00009******************************************************************/
10
11/* Buffer object implementation */
12
13#include "Python.h"
14
15
16typedef struct {
17 PyObject_HEAD
18 PyObject *b_base;
19 void *b_ptr;
20 int b_size;
21 int b_readonly;
22#ifdef CACHE_HASH
23 long b_hash;
24#endif
25} PyBufferObject;
26
27
28static PyObject *
Fred Drake79912472000-07-09 04:06:11 +000029_PyBuffer_FromMemory(PyObject *base, void *ptr, int size, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000030{
31 PyBufferObject * b;
32
Guido van Rossum49ded3e1999-03-19 19:04:25 +000033 if ( size < 0 ) {
34 PyErr_SetString(PyExc_ValueError,
35 "size must be zero or positive");
36 return NULL;
37 }
38
Guido van Rossum2e19bd71998-10-07 14:36:10 +000039 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
40 if ( b == NULL )
41 return NULL;
42
43 Py_XINCREF(base);
44 b->b_base = base;
45 b->b_ptr = ptr;
46 b->b_size = size;
47 b->b_readonly = readonly;
48#ifdef CACHE_HASH
49 b->b_hash = -1;
50#endif
51
52 return (PyObject *) b;
53}
54
55static PyObject *
Fred Drake79912472000-07-09 04:06:11 +000056_PyBuffer_FromObject(PyObject *base, int offset, int size,
57 getreadbufferproc proc, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000058{
59 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
60 void *p;
61 int count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000062
Guido van Rossum49ded3e1999-03-19 19:04:25 +000063 if ( offset < 0 ) {
64 PyErr_SetString(PyExc_ValueError,
65 "offset must be zero or positive");
66 return NULL;
67 }
68
Guido van Rossum2e19bd71998-10-07 14:36:10 +000069 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
70 {
Guido van Rossumcd037e71999-03-24 19:05:31 +000071 PyErr_SetString(PyExc_TypeError,
72 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +000073 return NULL;
74 }
75 if ( (count = (*proc)(base, 0, &p)) < 0 )
76 return NULL;
77
78 /* apply constraints to the start/end */
Guido van Rossum49ded3e1999-03-19 19:04:25 +000079 if ( size == Py_END_OF_BUFFER || size < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +000080 size = count;
81 if ( offset > count )
82 offset = count;
83 if ( offset + size > count )
84 size = count - offset;
85
86 /* if the base object is another buffer, then "deref" it */
87 if ( PyBuffer_Check(base) )
88 base = ((PyBufferObject *)base)->b_base;
89
90 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
91}
92
93
94PyObject *
Fred Drake79912472000-07-09 04:06:11 +000095PyBuffer_FromObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000096{
97 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
98
99 if ( pb == NULL ||
100 pb->bf_getreadbuffer == NULL ||
101 pb->bf_getsegcount == NULL )
102 {
103 PyErr_SetString(PyExc_TypeError, "buffer object expected");
104 return NULL;
105 }
106
Guido van Rossumcd037e71999-03-24 19:05:31 +0000107 return _PyBuffer_FromObject(base, offset, size,
108 pb->bf_getreadbuffer, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000109}
110
111PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000112PyBuffer_FromReadWriteObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000113{
114 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
115
116 if ( pb == NULL ||
117 pb->bf_getwritebuffer == NULL ||
118 pb->bf_getsegcount == NULL )
119 {
120 PyErr_SetString(PyExc_TypeError, "buffer object expected");
121 return NULL;
122 }
123
Guido van Rossumcd037e71999-03-24 19:05:31 +0000124 return _PyBuffer_FromObject(base, offset, size,
125 (getreadbufferproc)pb->bf_getwritebuffer,
126 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000127}
128
129PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000130PyBuffer_FromMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000131{
132 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
133}
134
135PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000136PyBuffer_FromReadWriteMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000137{
138 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
139}
140
141PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000142PyBuffer_New(int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000143{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000144 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000145 PyBufferObject * b;
146
Fred Drake4574f231999-08-04 13:08:19 +0000147 if (size < 0) {
148 PyErr_SetString(PyExc_ValueError,
149 "size must be zero or positive");
150 return NULL;
151 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000152 /* PyObject_New is inlined */
Moshe Zadkacf703f02000-08-04 15:36:13 +0000153 o = PyObject_MALLOC(sizeof(*b) + size);
154 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000155 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000156 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000157
158 b->b_base = NULL;
159 b->b_ptr = (void *)(b + 1);
160 b->b_size = size;
161 b->b_readonly = 0;
162#ifdef CACHE_HASH
163 b->b_hash = -1;
164#endif
165
Moshe Zadkacf703f02000-08-04 15:36:13 +0000166 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000167}
168
169/* Methods */
170
171static void
Fred Drake79912472000-07-09 04:06:11 +0000172buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000173{
174 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000175 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000176}
177
178static int
Fred Drake79912472000-07-09 04:06:11 +0000179buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000180{
181 int len_self = self->b_size;
182 int len_other = other->b_size;
183 int min_len = (len_self < len_other) ? len_self : len_other;
184 int cmp;
185 if (min_len > 0) {
186 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
187 if (cmp != 0)
188 return cmp;
189 }
190 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
191}
192
193static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000194buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195{
196 char buf[300];
197 char *status = self->b_readonly ? "read-only" : "read-write";
198
199 if ( self->b_base == NULL )
200 {
Fred Drakea44d3532000-06-30 15:01:00 +0000201 sprintf(buf, "<%s buffer ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000202 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000203 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000204 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000205 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000206 }
207 else
208 {
Fred Drakea44d3532000-06-30 15:01:00 +0000209 sprintf(buf, "<%s buffer for %p, ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000210 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000211 self->b_base,
212 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000213 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000214 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000215 }
216
217 return PyString_FromString(buf);
218}
219
220static long
Fred Drake79912472000-07-09 04:06:11 +0000221buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000222{
223 register int len;
224 register unsigned char *p;
225 register long x;
226
227#ifdef CACHE_HASH
228 if ( self->b_hash != -1 )
229 return self->b_hash;
230#endif
231
232 if ( !self->b_readonly )
233 {
234 /* ### use different wording, since this is conditional? */
235 PyErr_SetString(PyExc_TypeError, "unhashable type");
236 return -1;
237 }
238
239 len = self->b_size;
240 p = (unsigned char *) self->b_ptr;
241 x = *p << 7;
242 while (--len >= 0)
243 x = (1000003*x) ^ *p++;
244 x ^= self->b_size;
245 if (x == -1)
246 x = -2;
247#ifdef CACHE_HASH
248 self->b_hash = x;
249#endif
250 return x;
251}
252
253static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000254buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000255{
256 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
257}
258
259/* Sequence methods */
260
261static int
Fred Drake79912472000-07-09 04:06:11 +0000262buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000263{
264 return self->b_size;
265}
266
267static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000268buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000269{
270 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
271 char *p1;
272 void *p2;
273 PyObject *ob;
274 int count;
275
276 if ( pb == NULL ||
277 pb->bf_getreadbuffer == NULL ||
278 pb->bf_getsegcount == NULL )
279 {
280 PyErr_BadArgument();
281 return NULL;
282 }
283 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
284 {
285 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000286 PyErr_SetString(PyExc_TypeError,
287 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000288 return NULL;
289 }
290
291 /* optimize special case */
292 if ( self->b_size == 0 )
293 {
294 Py_INCREF(other);
295 return other;
296 }
297
298 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
299 return NULL;
300
301 /* optimize special case */
302 if ( count == 0 )
303 {
304 Py_INCREF(self);
305 return (PyObject *)self;
306 }
307
308 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
309 p1 = PyString_AS_STRING(ob);
310 memcpy(p1, self->b_ptr, self->b_size);
311 memcpy(p1 + self->b_size, p2, count);
312
313 /* there is an extra byte in the string object, so this is safe */
314 p1[self->b_size + count] = '\0';
315
316 return ob;
317}
318
319static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000320buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000321{
322 PyObject *ob;
323 register char *p;
324 void *ptr = self->b_ptr;
325 int size = self->b_size;
326
327 if ( count < 0 )
328 count = 0;
329 ob = PyString_FromStringAndSize(NULL, size * count);
330 if ( ob == NULL )
331 return NULL;
332
333 p = PyString_AS_STRING(ob);
334 while ( count-- )
335 {
336 memcpy(p, ptr, size);
337 p += size;
338 }
339
340 /* there is an extra byte in the string object, so this is safe */
341 *p = '\0';
342
343 return ob;
344}
345
346static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000347buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000348{
349 if ( idx < 0 || idx >= self->b_size )
350 {
351 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
352 return NULL;
353 }
354 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
355}
356
357static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000358buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000359{
360 if ( left < 0 )
361 left = 0;
362 if ( right < 0 )
363 right = 0;
364 if ( right > self->b_size )
365 right = self->b_size;
366 if ( left == 0 && right == self->b_size )
367 {
368 /* same as self */
369 Py_INCREF(self);
370 return (PyObject *)self;
371 }
372 if ( right < left )
373 right = left;
Guido van Rossumcd037e71999-03-24 19:05:31 +0000374 return PyString_FromStringAndSize((char *)self->b_ptr + left,
375 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000376}
377
378static int
Fred Drake79912472000-07-09 04:06:11 +0000379buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000380{
381 PyBufferProcs *pb;
382 void *p;
383 int count;
384
385 if ( self->b_readonly ) {
386 PyErr_SetString(PyExc_TypeError,
387 "buffer is read-only");
388 return -1;
389 }
390
391 if (idx < 0 || idx >= self->b_size) {
392 PyErr_SetString(PyExc_IndexError,
393 "buffer assignment index out of range");
394 return -1;
395 }
396
397 pb = other ? other->ob_type->tp_as_buffer : NULL;
398 if ( pb == NULL ||
399 pb->bf_getreadbuffer == NULL ||
400 pb->bf_getsegcount == NULL )
401 {
402 PyErr_BadArgument();
403 return -1;
404 }
405 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
406 {
407 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000408 PyErr_SetString(PyExc_TypeError,
409 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000410 return -1;
411 }
412
413 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
414 return -1;
415 if ( count != 1 ) {
416 PyErr_SetString(PyExc_TypeError,
417 "right operand must be a single byte");
418 return -1;
419 }
420
421 ((char *)self->b_ptr)[idx] = *(char *)p;
422 return 0;
423}
424
425static int
Fred Drake79912472000-07-09 04:06:11 +0000426buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000427{
428 PyBufferProcs *pb;
429 void *p;
430 int slice_len;
431 int count;
432
433 if ( self->b_readonly ) {
434 PyErr_SetString(PyExc_TypeError,
435 "buffer is read-only");
436 return -1;
437 }
438
439 pb = other ? other->ob_type->tp_as_buffer : NULL;
440 if ( pb == NULL ||
441 pb->bf_getreadbuffer == NULL ||
442 pb->bf_getsegcount == NULL )
443 {
444 PyErr_BadArgument();
445 return -1;
446 }
447 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
448 {
449 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000450 PyErr_SetString(PyExc_TypeError,
451 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000452 return -1;
453 }
454 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
455 return -1;
456
457 if ( left < 0 )
458 left = 0;
459 else if ( left > self->b_size )
460 left = self->b_size;
461 if ( right < left )
462 right = left;
463 else if ( right > self->b_size )
464 right = self->b_size;
465 slice_len = right - left;
466
467 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000468 PyErr_SetString(
469 PyExc_TypeError,
470 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000471 return -1;
472 }
473
474 if ( slice_len )
475 memcpy((char *)self->b_ptr + left, p, slice_len);
476
477 return 0;
478}
479
480/* Buffer methods */
481
482static int
Fred Drake79912472000-07-09 04:06:11 +0000483buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000484{
485 if ( idx != 0 ) {
486 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000487 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000488 return -1;
489 }
490 *pp = self->b_ptr;
491 return self->b_size;
492}
493
494static int
Fred Drake79912472000-07-09 04:06:11 +0000495buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000496{
497 if ( self->b_readonly )
498 {
499 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
500 return -1;
501 }
502 return buffer_getreadbuf(self, idx, pp);
503}
504
505static int
Fred Drake79912472000-07-09 04:06:11 +0000506buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000507{
508 if ( lenp )
509 *lenp = self->b_size;
510 return 1;
511}
512
Guido van Rossum1db70701998-10-08 02:18:52 +0000513static int
Fred Drake79912472000-07-09 04:06:11 +0000514buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000515{
516 if ( idx != 0 ) {
517 PyErr_SetString(PyExc_SystemError,
518 "accessing non-existent buffer segment");
519 return -1;
520 }
521 *pp = (const char *)self->b_ptr;
522 return self->b_size;
523}
524
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000525
526static PySequenceMethods buffer_as_sequence = {
527 (inquiry)buffer_length, /*sq_length*/
528 (binaryfunc)buffer_concat, /*sq_concat*/
529 (intargfunc)buffer_repeat, /*sq_repeat*/
530 (intargfunc)buffer_item, /*sq_item*/
531 (intintargfunc)buffer_slice, /*sq_slice*/
532 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
533 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
534};
535
536static PyBufferProcs buffer_as_buffer = {
537 (getreadbufferproc)buffer_getreadbuf,
538 (getwritebufferproc)buffer_getwritebuf,
539 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000540 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000541};
542
543PyTypeObject PyBuffer_Type = {
544 PyObject_HEAD_INIT(&PyType_Type)
545 0,
546 "buffer",
547 sizeof(PyBufferObject),
548 0,
549 (destructor)buffer_dealloc, /*tp_dealloc*/
550 0, /*tp_print*/
551 0, /*tp_getattr*/
552 0, /*tp_setattr*/
553 (cmpfunc)buffer_compare, /*tp_compare*/
554 (reprfunc)buffer_repr, /*tp_repr*/
555 0, /*tp_as_number*/
556 &buffer_as_sequence, /*tp_as_sequence*/
557 0, /*tp_as_mapping*/
558 (hashfunc)buffer_hash, /*tp_hash*/
559 0, /*tp_call*/
560 (reprfunc)buffer_str, /*tp_str*/
561 0, /*tp_getattro*/
562 0, /*tp_setattro*/
563 &buffer_as_buffer, /*tp_as_buffer*/
Guido van Rossum1db70701998-10-08 02:18:52 +0000564 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000565 0, /*tp_doc*/
566};