blob: 67d26a17db596e0da5672910b784d5ae14f21a7c [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{
144 PyBufferObject * b;
145
Fred Drake4574f231999-08-04 13:08:19 +0000146 if (size < 0) {
147 PyErr_SetString(PyExc_ValueError,
148 "size must be zero or positive");
149 return NULL;
150 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000151 /* PyObject_New is inlined */
152 b = (PyBufferObject *) PyObject_MALLOC(sizeof(*b) + size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000153 if ( b == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000154 return PyErr_NoMemory();
Guido van Rossumb18618d2000-05-03 23:44:39 +0000155 PyObject_INIT((PyObject *)b, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000156
157 b->b_base = NULL;
158 b->b_ptr = (void *)(b + 1);
159 b->b_size = size;
160 b->b_readonly = 0;
161#ifdef CACHE_HASH
162 b->b_hash = -1;
163#endif
164
165 return (PyObject *) b;
166}
167
168/* Methods */
169
170static void
Fred Drake79912472000-07-09 04:06:11 +0000171buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000172{
173 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000174 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000175}
176
177static int
Fred Drake79912472000-07-09 04:06:11 +0000178buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000179{
180 int len_self = self->b_size;
181 int len_other = other->b_size;
182 int min_len = (len_self < len_other) ? len_self : len_other;
183 int cmp;
184 if (min_len > 0) {
185 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
186 if (cmp != 0)
187 return cmp;
188 }
189 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
190}
191
192static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000193buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000194{
195 char buf[300];
196 char *status = self->b_readonly ? "read-only" : "read-write";
197
198 if ( self->b_base == NULL )
199 {
Fred Drakea44d3532000-06-30 15:01:00 +0000200 sprintf(buf, "<%s buffer ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000201 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000202 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000204 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000205 }
206 else
207 {
Fred Drakea44d3532000-06-30 15:01:00 +0000208 sprintf(buf, "<%s buffer for %p, ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000209 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000210 self->b_base,
211 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000212 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000213 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000214 }
215
216 return PyString_FromString(buf);
217}
218
219static long
Fred Drake79912472000-07-09 04:06:11 +0000220buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000221{
222 register int len;
223 register unsigned char *p;
224 register long x;
225
226#ifdef CACHE_HASH
227 if ( self->b_hash != -1 )
228 return self->b_hash;
229#endif
230
231 if ( !self->b_readonly )
232 {
233 /* ### use different wording, since this is conditional? */
234 PyErr_SetString(PyExc_TypeError, "unhashable type");
235 return -1;
236 }
237
238 len = self->b_size;
239 p = (unsigned char *) self->b_ptr;
240 x = *p << 7;
241 while (--len >= 0)
242 x = (1000003*x) ^ *p++;
243 x ^= self->b_size;
244 if (x == -1)
245 x = -2;
246#ifdef CACHE_HASH
247 self->b_hash = x;
248#endif
249 return x;
250}
251
252static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000253buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000254{
255 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
256}
257
258/* Sequence methods */
259
260static int
Fred Drake79912472000-07-09 04:06:11 +0000261buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000262{
263 return self->b_size;
264}
265
266static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000267buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000268{
269 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
270 char *p1;
271 void *p2;
272 PyObject *ob;
273 int count;
274
275 if ( pb == NULL ||
276 pb->bf_getreadbuffer == NULL ||
277 pb->bf_getsegcount == NULL )
278 {
279 PyErr_BadArgument();
280 return NULL;
281 }
282 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
283 {
284 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000285 PyErr_SetString(PyExc_TypeError,
286 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000287 return NULL;
288 }
289
290 /* optimize special case */
291 if ( self->b_size == 0 )
292 {
293 Py_INCREF(other);
294 return other;
295 }
296
297 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
298 return NULL;
299
300 /* optimize special case */
301 if ( count == 0 )
302 {
303 Py_INCREF(self);
304 return (PyObject *)self;
305 }
306
307 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
308 p1 = PyString_AS_STRING(ob);
309 memcpy(p1, self->b_ptr, self->b_size);
310 memcpy(p1 + self->b_size, p2, count);
311
312 /* there is an extra byte in the string object, so this is safe */
313 p1[self->b_size + count] = '\0';
314
315 return ob;
316}
317
318static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000319buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000320{
321 PyObject *ob;
322 register char *p;
323 void *ptr = self->b_ptr;
324 int size = self->b_size;
325
326 if ( count < 0 )
327 count = 0;
328 ob = PyString_FromStringAndSize(NULL, size * count);
329 if ( ob == NULL )
330 return NULL;
331
332 p = PyString_AS_STRING(ob);
333 while ( count-- )
334 {
335 memcpy(p, ptr, size);
336 p += size;
337 }
338
339 /* there is an extra byte in the string object, so this is safe */
340 *p = '\0';
341
342 return ob;
343}
344
345static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000346buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000347{
348 if ( idx < 0 || idx >= self->b_size )
349 {
350 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
351 return NULL;
352 }
353 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
354}
355
356static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000357buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000358{
359 if ( left < 0 )
360 left = 0;
361 if ( right < 0 )
362 right = 0;
363 if ( right > self->b_size )
364 right = self->b_size;
365 if ( left == 0 && right == self->b_size )
366 {
367 /* same as self */
368 Py_INCREF(self);
369 return (PyObject *)self;
370 }
371 if ( right < left )
372 right = left;
Guido van Rossumcd037e71999-03-24 19:05:31 +0000373 return PyString_FromStringAndSize((char *)self->b_ptr + left,
374 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000375}
376
377static int
Fred Drake79912472000-07-09 04:06:11 +0000378buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000379{
380 PyBufferProcs *pb;
381 void *p;
382 int count;
383
384 if ( self->b_readonly ) {
385 PyErr_SetString(PyExc_TypeError,
386 "buffer is read-only");
387 return -1;
388 }
389
390 if (idx < 0 || idx >= self->b_size) {
391 PyErr_SetString(PyExc_IndexError,
392 "buffer assignment index out of range");
393 return -1;
394 }
395
396 pb = other ? other->ob_type->tp_as_buffer : NULL;
397 if ( pb == NULL ||
398 pb->bf_getreadbuffer == NULL ||
399 pb->bf_getsegcount == NULL )
400 {
401 PyErr_BadArgument();
402 return -1;
403 }
404 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
405 {
406 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000407 PyErr_SetString(PyExc_TypeError,
408 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000409 return -1;
410 }
411
412 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
413 return -1;
414 if ( count != 1 ) {
415 PyErr_SetString(PyExc_TypeError,
416 "right operand must be a single byte");
417 return -1;
418 }
419
420 ((char *)self->b_ptr)[idx] = *(char *)p;
421 return 0;
422}
423
424static int
Fred Drake79912472000-07-09 04:06:11 +0000425buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000426{
427 PyBufferProcs *pb;
428 void *p;
429 int slice_len;
430 int count;
431
432 if ( self->b_readonly ) {
433 PyErr_SetString(PyExc_TypeError,
434 "buffer is read-only");
435 return -1;
436 }
437
438 pb = other ? other->ob_type->tp_as_buffer : NULL;
439 if ( pb == NULL ||
440 pb->bf_getreadbuffer == NULL ||
441 pb->bf_getsegcount == NULL )
442 {
443 PyErr_BadArgument();
444 return -1;
445 }
446 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
447 {
448 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000449 PyErr_SetString(PyExc_TypeError,
450 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000451 return -1;
452 }
453 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
454 return -1;
455
456 if ( left < 0 )
457 left = 0;
458 else if ( left > self->b_size )
459 left = self->b_size;
460 if ( right < left )
461 right = left;
462 else if ( right > self->b_size )
463 right = self->b_size;
464 slice_len = right - left;
465
466 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000467 PyErr_SetString(
468 PyExc_TypeError,
469 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000470 return -1;
471 }
472
473 if ( slice_len )
474 memcpy((char *)self->b_ptr + left, p, slice_len);
475
476 return 0;
477}
478
479/* Buffer methods */
480
481static int
Fred Drake79912472000-07-09 04:06:11 +0000482buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000483{
484 if ( idx != 0 ) {
485 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000486 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000487 return -1;
488 }
489 *pp = self->b_ptr;
490 return self->b_size;
491}
492
493static int
Fred Drake79912472000-07-09 04:06:11 +0000494buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000495{
496 if ( self->b_readonly )
497 {
498 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
499 return -1;
500 }
501 return buffer_getreadbuf(self, idx, pp);
502}
503
504static int
Fred Drake79912472000-07-09 04:06:11 +0000505buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000506{
507 if ( lenp )
508 *lenp = self->b_size;
509 return 1;
510}
511
Guido van Rossum1db70701998-10-08 02:18:52 +0000512static int
Fred Drake79912472000-07-09 04:06:11 +0000513buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000514{
515 if ( idx != 0 ) {
516 PyErr_SetString(PyExc_SystemError,
517 "accessing non-existent buffer segment");
518 return -1;
519 }
520 *pp = (const char *)self->b_ptr;
521 return self->b_size;
522}
523
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000524
525static PySequenceMethods buffer_as_sequence = {
526 (inquiry)buffer_length, /*sq_length*/
527 (binaryfunc)buffer_concat, /*sq_concat*/
528 (intargfunc)buffer_repeat, /*sq_repeat*/
529 (intargfunc)buffer_item, /*sq_item*/
530 (intintargfunc)buffer_slice, /*sq_slice*/
531 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
532 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
533};
534
535static PyBufferProcs buffer_as_buffer = {
536 (getreadbufferproc)buffer_getreadbuf,
537 (getwritebufferproc)buffer_getwritebuf,
538 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000539 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000540};
541
542PyTypeObject PyBuffer_Type = {
543 PyObject_HEAD_INIT(&PyType_Type)
544 0,
545 "buffer",
546 sizeof(PyBufferObject),
547 0,
548 (destructor)buffer_dealloc, /*tp_dealloc*/
549 0, /*tp_print*/
550 0, /*tp_getattr*/
551 0, /*tp_setattr*/
552 (cmpfunc)buffer_compare, /*tp_compare*/
553 (reprfunc)buffer_repr, /*tp_repr*/
554 0, /*tp_as_number*/
555 &buffer_as_sequence, /*tp_as_sequence*/
556 0, /*tp_as_mapping*/
557 (hashfunc)buffer_hash, /*tp_hash*/
558 0, /*tp_call*/
559 (reprfunc)buffer_str, /*tp_str*/
560 0, /*tp_getattro*/
561 0, /*tp_setattro*/
562 &buffer_as_buffer, /*tp_as_buffer*/
Guido van Rossum1db70701998-10-08 02:18:52 +0000563 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000564 0, /*tp_doc*/
565};