blob: 86d04878b09707431ef92da119d12a43a51fe690 [file] [log] [blame]
Guido van Rossum2e19bd71998-10-07 14:36:10 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* Buffer object implementation */
33
34#include "Python.h"
35
36
37typedef struct {
38 PyObject_HEAD
39 PyObject *b_base;
40 void *b_ptr;
41 int b_size;
42 int b_readonly;
43#ifdef CACHE_HASH
44 long b_hash;
45#endif
46} PyBufferObject;
47
48
49static PyObject *
50_PyBuffer_FromMemory(base, ptr, size, readonly)
51 PyObject *base;
52 void *ptr;
53 int size;
54 int readonly;
55{
56 PyBufferObject * b;
57
Guido van Rossum49ded3e1999-03-19 19:04:25 +000058 if ( size < 0 ) {
59 PyErr_SetString(PyExc_ValueError,
60 "size must be zero or positive");
61 return NULL;
62 }
63
Guido van Rossum2e19bd71998-10-07 14:36:10 +000064 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
65 if ( b == NULL )
66 return NULL;
67
68 Py_XINCREF(base);
69 b->b_base = base;
70 b->b_ptr = ptr;
71 b->b_size = size;
72 b->b_readonly = readonly;
73#ifdef CACHE_HASH
74 b->b_hash = -1;
75#endif
76
77 return (PyObject *) b;
78}
79
80static PyObject *
81_PyBuffer_FromObject(base, offset, size, proc, readonly)
82 PyObject *base;
83 int offset;
84 int size;
85 getreadbufferproc proc;
86 int readonly;
87{
88 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
89 void *p;
90 int count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000091
Guido van Rossum49ded3e1999-03-19 19:04:25 +000092 if ( offset < 0 ) {
93 PyErr_SetString(PyExc_ValueError,
94 "offset must be zero or positive");
95 return NULL;
96 }
97
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
99 {
100 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
101 return NULL;
102 }
103 if ( (count = (*proc)(base, 0, &p)) < 0 )
104 return NULL;
105
106 /* apply constraints to the start/end */
Guido van Rossum49ded3e1999-03-19 19:04:25 +0000107 if ( size == Py_END_OF_BUFFER || size < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000108 size = count;
109 if ( offset > count )
110 offset = count;
111 if ( offset + size > count )
112 size = count - offset;
113
114 /* if the base object is another buffer, then "deref" it */
115 if ( PyBuffer_Check(base) )
116 base = ((PyBufferObject *)base)->b_base;
117
118 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
119}
120
121
122PyObject *
123PyBuffer_FromObject(base, offset, size)
124 PyObject *base;
125 int offset;
126 int size;
127{
128 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
129
130 if ( pb == NULL ||
131 pb->bf_getreadbuffer == NULL ||
132 pb->bf_getsegcount == NULL )
133 {
134 PyErr_SetString(PyExc_TypeError, "buffer object expected");
135 return NULL;
136 }
137
138 return _PyBuffer_FromObject(base, offset, size, pb->bf_getreadbuffer, 1);
139}
140
141PyObject *
142PyBuffer_FromReadWriteObject(base, offset, size)
143 PyObject *base;
144 int offset;
145 int size;
146{
147 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
148
149 if ( pb == NULL ||
150 pb->bf_getwritebuffer == NULL ||
151 pb->bf_getsegcount == NULL )
152 {
153 PyErr_SetString(PyExc_TypeError, "buffer object expected");
154 return NULL;
155 }
156
157 return _PyBuffer_FromObject(base, offset, size, (getreadbufferproc)pb->bf_getwritebuffer, 0);
158}
159
160PyObject *
161PyBuffer_FromMemory(ptr, size)
162 void *ptr;
163 int size;
164{
165 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
166}
167
168PyObject *
169PyBuffer_FromReadWriteMemory(ptr, size)
170 void *ptr;
171 int size;
172{
173 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
174}
175
176PyObject *
177PyBuffer_New(size)
178 int size;
179{
180 PyBufferObject * b;
181
182 b = (PyBufferObject *)malloc(sizeof(*b) + size);
183 if ( b == NULL )
184 return NULL;
185 b->ob_type = &PyBuffer_Type;
186 _Py_NewReference((PyObject *)b);
187
188 b->b_base = NULL;
189 b->b_ptr = (void *)(b + 1);
190 b->b_size = size;
191 b->b_readonly = 0;
192#ifdef CACHE_HASH
193 b->b_hash = -1;
194#endif
195
196 return (PyObject *) b;
197}
198
199/* Methods */
200
201static void
202buffer_dealloc(self)
203 PyBufferObject *self;
204{
205 Py_XDECREF(self->b_base);
206 free((void *)self);
207}
208
209static int
210buffer_compare(self, other)
211 PyBufferObject *self;
212 PyBufferObject *other;
213{
214 int len_self = self->b_size;
215 int len_other = other->b_size;
216 int min_len = (len_self < len_other) ? len_self : len_other;
217 int cmp;
218 if (min_len > 0) {
219 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
220 if (cmp != 0)
221 return cmp;
222 }
223 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
224}
225
226static PyObject *
227buffer_repr(self)
228 PyBufferObject *self;
229{
230 char buf[300];
231 char *status = self->b_readonly ? "read-only" : "read-write";
232
233 if ( self->b_base == NULL )
234 {
Guido van Rossum7148ca91998-10-07 16:22:12 +0000235 sprintf(buf, "<%s buffer ptr %lx, size %d at %lx>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000236 status,
Guido van Rossum7148ca91998-10-07 16:22:12 +0000237 (long)self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000238 self->b_size,
239 (long)self);
240 }
241 else
242 {
Guido van Rossum7148ca91998-10-07 16:22:12 +0000243 sprintf(buf, "<%s buffer for %lx, ptr %lx, size %d at %lx>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000244 status,
245 (long)self->b_base,
Guido van Rossum7148ca91998-10-07 16:22:12 +0000246 (long)self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000247 self->b_size,
248 (long)self);
249 }
250
251 return PyString_FromString(buf);
252}
253
254static long
255buffer_hash(self)
256 PyBufferObject *self;
257{
258 register int len;
259 register unsigned char *p;
260 register long x;
261
262#ifdef CACHE_HASH
263 if ( self->b_hash != -1 )
264 return self->b_hash;
265#endif
266
267 if ( !self->b_readonly )
268 {
269 /* ### use different wording, since this is conditional? */
270 PyErr_SetString(PyExc_TypeError, "unhashable type");
271 return -1;
272 }
273
274 len = self->b_size;
275 p = (unsigned char *) self->b_ptr;
276 x = *p << 7;
277 while (--len >= 0)
278 x = (1000003*x) ^ *p++;
279 x ^= self->b_size;
280 if (x == -1)
281 x = -2;
282#ifdef CACHE_HASH
283 self->b_hash = x;
284#endif
285 return x;
286}
287
288static PyObject *
289buffer_str(self)
290 PyBufferObject *self;
291{
292 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
293}
294
295/* Sequence methods */
296
297static int
298buffer_length(self)
299 PyBufferObject *self;
300{
301 return self->b_size;
302}
303
304static PyObject *
305buffer_concat(self, other)
306 PyBufferObject *self;
307 PyObject *other;
308{
309 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
310 char *p1;
311 void *p2;
312 PyObject *ob;
313 int count;
314
315 if ( pb == NULL ||
316 pb->bf_getreadbuffer == NULL ||
317 pb->bf_getsegcount == NULL )
318 {
319 PyErr_BadArgument();
320 return NULL;
321 }
322 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
323 {
324 /* ### use a different exception type/message? */
325 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
326 return NULL;
327 }
328
329 /* optimize special case */
330 if ( self->b_size == 0 )
331 {
332 Py_INCREF(other);
333 return other;
334 }
335
336 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
337 return NULL;
338
339 /* optimize special case */
340 if ( count == 0 )
341 {
342 Py_INCREF(self);
343 return (PyObject *)self;
344 }
345
346 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
347 p1 = PyString_AS_STRING(ob);
348 memcpy(p1, self->b_ptr, self->b_size);
349 memcpy(p1 + self->b_size, p2, count);
350
351 /* there is an extra byte in the string object, so this is safe */
352 p1[self->b_size + count] = '\0';
353
354 return ob;
355}
356
357static PyObject *
358buffer_repeat(self, count)
359 PyBufferObject *self;
360 int count;
361{
362 PyObject *ob;
363 register char *p;
364 void *ptr = self->b_ptr;
365 int size = self->b_size;
366
367 if ( count < 0 )
368 count = 0;
369 ob = PyString_FromStringAndSize(NULL, size * count);
370 if ( ob == NULL )
371 return NULL;
372
373 p = PyString_AS_STRING(ob);
374 while ( count-- )
375 {
376 memcpy(p, ptr, size);
377 p += size;
378 }
379
380 /* there is an extra byte in the string object, so this is safe */
381 *p = '\0';
382
383 return ob;
384}
385
386static PyObject *
387buffer_item(self, idx)
388 PyBufferObject *self;
389 int idx;
390{
391 if ( idx < 0 || idx >= self->b_size )
392 {
393 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
394 return NULL;
395 }
396 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
397}
398
399static PyObject *
400buffer_slice(self, left, right)
401 PyBufferObject *self;
402 int left;
403 int right;
404{
405 if ( left < 0 )
406 left = 0;
407 if ( right < 0 )
408 right = 0;
409 if ( right > self->b_size )
410 right = self->b_size;
411 if ( left == 0 && right == self->b_size )
412 {
413 /* same as self */
414 Py_INCREF(self);
415 return (PyObject *)self;
416 }
417 if ( right < left )
418 right = left;
419 return PyString_FromStringAndSize((char *)self->b_ptr + left, right - left);
420}
421
422static int
423buffer_ass_item(self, idx, other)
424 PyBufferObject *self;
425 int idx;
426 PyObject *other;
427{
428 PyBufferProcs *pb;
429 void *p;
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 if (idx < 0 || idx >= self->b_size) {
439 PyErr_SetString(PyExc_IndexError,
440 "buffer assignment index out of range");
441 return -1;
442 }
443
444 pb = other ? other->ob_type->tp_as_buffer : NULL;
445 if ( pb == NULL ||
446 pb->bf_getreadbuffer == NULL ||
447 pb->bf_getsegcount == NULL )
448 {
449 PyErr_BadArgument();
450 return -1;
451 }
452 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
453 {
454 /* ### use a different exception type/message? */
455 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
456 return -1;
457 }
458
459 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
460 return -1;
461 if ( count != 1 ) {
462 PyErr_SetString(PyExc_TypeError,
463 "right operand must be a single byte");
464 return -1;
465 }
466
467 ((char *)self->b_ptr)[idx] = *(char *)p;
468 return 0;
469}
470
471static int
472buffer_ass_slice(self, left, right, other)
473 PyBufferObject *self;
474 int left;
475 int right;
476 PyObject *other;
477{
478 PyBufferProcs *pb;
479 void *p;
480 int slice_len;
481 int count;
482
483 if ( self->b_readonly ) {
484 PyErr_SetString(PyExc_TypeError,
485 "buffer is read-only");
486 return -1;
487 }
488
489 pb = other ? other->ob_type->tp_as_buffer : NULL;
490 if ( pb == NULL ||
491 pb->bf_getreadbuffer == NULL ||
492 pb->bf_getsegcount == NULL )
493 {
494 PyErr_BadArgument();
495 return -1;
496 }
497 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
498 {
499 /* ### use a different exception type/message? */
500 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
501 return -1;
502 }
503 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
504 return -1;
505
506 if ( left < 0 )
507 left = 0;
508 else if ( left > self->b_size )
509 left = self->b_size;
510 if ( right < left )
511 right = left;
512 else if ( right > self->b_size )
513 right = self->b_size;
514 slice_len = right - left;
515
516 if ( count != slice_len ) {
517 PyErr_SetString(PyExc_TypeError,
518 "right operand length must match slice length");
519 return -1;
520 }
521
522 if ( slice_len )
523 memcpy((char *)self->b_ptr + left, p, slice_len);
524
525 return 0;
526}
527
528/* Buffer methods */
529
530static int
531buffer_getreadbuf(self, idx, pp)
532 PyBufferObject *self;
533 int idx;
534 void ** pp;
535{
536 if ( idx != 0 ) {
537 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000538 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000539 return -1;
540 }
541 *pp = self->b_ptr;
542 return self->b_size;
543}
544
545static int
546buffer_getwritebuf(self, idx, pp)
547 PyBufferObject *self;
548 int idx;
549 void ** pp;
550{
551 if ( self->b_readonly )
552 {
553 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
554 return -1;
555 }
556 return buffer_getreadbuf(self, idx, pp);
557}
558
559static int
560buffer_getsegcount(self, lenp)
561 PyBufferObject *self;
562 int *lenp;
563{
564 if ( lenp )
565 *lenp = self->b_size;
566 return 1;
567}
568
Guido van Rossum1db70701998-10-08 02:18:52 +0000569static int
570buffer_getcharbuf(self, idx, pp)
571 PyBufferObject *self;
572 int idx;
573 const char ** pp;
574{
575 if ( idx != 0 ) {
576 PyErr_SetString(PyExc_SystemError,
577 "accessing non-existent buffer segment");
578 return -1;
579 }
580 *pp = (const char *)self->b_ptr;
581 return self->b_size;
582}
583
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000584
585static PySequenceMethods buffer_as_sequence = {
586 (inquiry)buffer_length, /*sq_length*/
587 (binaryfunc)buffer_concat, /*sq_concat*/
588 (intargfunc)buffer_repeat, /*sq_repeat*/
589 (intargfunc)buffer_item, /*sq_item*/
590 (intintargfunc)buffer_slice, /*sq_slice*/
591 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
592 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
593};
594
595static PyBufferProcs buffer_as_buffer = {
596 (getreadbufferproc)buffer_getreadbuf,
597 (getwritebufferproc)buffer_getwritebuf,
598 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000599 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000600};
601
602PyTypeObject PyBuffer_Type = {
603 PyObject_HEAD_INIT(&PyType_Type)
604 0,
605 "buffer",
606 sizeof(PyBufferObject),
607 0,
608 (destructor)buffer_dealloc, /*tp_dealloc*/
609 0, /*tp_print*/
610 0, /*tp_getattr*/
611 0, /*tp_setattr*/
612 (cmpfunc)buffer_compare, /*tp_compare*/
613 (reprfunc)buffer_repr, /*tp_repr*/
614 0, /*tp_as_number*/
615 &buffer_as_sequence, /*tp_as_sequence*/
616 0, /*tp_as_mapping*/
617 (hashfunc)buffer_hash, /*tp_hash*/
618 0, /*tp_call*/
619 (reprfunc)buffer_str, /*tp_str*/
620 0, /*tp_getattro*/
621 0, /*tp_setattro*/
622 &buffer_as_buffer, /*tp_as_buffer*/
Guido van Rossum1db70701998-10-08 02:18:52 +0000623 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000624 0, /*tp_doc*/
625};
626