blob: b2b7baa5d5c294254a14ca5e2f3294d42ebf1460 [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
58 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
59 if ( b == NULL )
60 return NULL;
61
62 Py_XINCREF(base);
63 b->b_base = base;
64 b->b_ptr = ptr;
65 b->b_size = size;
66 b->b_readonly = readonly;
67#ifdef CACHE_HASH
68 b->b_hash = -1;
69#endif
70
71 return (PyObject *) b;
72}
73
74static PyObject *
75_PyBuffer_FromObject(base, offset, size, proc, readonly)
76 PyObject *base;
77 int offset;
78 int size;
79 getreadbufferproc proc;
80 int readonly;
81{
82 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
83 void *p;
84 int count;
85 PyBufferObject *b;
86
87 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
88 {
89 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
90 return NULL;
91 }
92 if ( (count = (*proc)(base, 0, &p)) < 0 )
93 return NULL;
94
95 /* apply constraints to the start/end */
96 if ( size == Py_END_OF_BUFFER )
97 size = count;
98 if ( offset > count )
99 offset = count;
100 if ( offset + size > count )
101 size = count - offset;
102
103 /* if the base object is another buffer, then "deref" it */
104 if ( PyBuffer_Check(base) )
105 base = ((PyBufferObject *)base)->b_base;
106
107 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
108}
109
110
111PyObject *
112PyBuffer_FromObject(base, offset, size)
113 PyObject *base;
114 int offset;
115 int size;
116{
117 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
118
119 if ( pb == NULL ||
120 pb->bf_getreadbuffer == NULL ||
121 pb->bf_getsegcount == NULL )
122 {
123 PyErr_SetString(PyExc_TypeError, "buffer object expected");
124 return NULL;
125 }
126
127 return _PyBuffer_FromObject(base, offset, size, pb->bf_getreadbuffer, 1);
128}
129
130PyObject *
131PyBuffer_FromReadWriteObject(base, offset, size)
132 PyObject *base;
133 int offset;
134 int size;
135{
136 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
137
138 if ( pb == NULL ||
139 pb->bf_getwritebuffer == NULL ||
140 pb->bf_getsegcount == NULL )
141 {
142 PyErr_SetString(PyExc_TypeError, "buffer object expected");
143 return NULL;
144 }
145
146 return _PyBuffer_FromObject(base, offset, size, (getreadbufferproc)pb->bf_getwritebuffer, 0);
147}
148
149PyObject *
150PyBuffer_FromMemory(ptr, size)
151 void *ptr;
152 int size;
153{
154 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
155}
156
157PyObject *
158PyBuffer_FromReadWriteMemory(ptr, size)
159 void *ptr;
160 int size;
161{
162 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
163}
164
165PyObject *
166PyBuffer_New(size)
167 int size;
168{
169 PyBufferObject * b;
170
171 b = (PyBufferObject *)malloc(sizeof(*b) + size);
172 if ( b == NULL )
173 return NULL;
174 b->ob_type = &PyBuffer_Type;
175 _Py_NewReference((PyObject *)b);
176
177 b->b_base = NULL;
178 b->b_ptr = (void *)(b + 1);
179 b->b_size = size;
180 b->b_readonly = 0;
181#ifdef CACHE_HASH
182 b->b_hash = -1;
183#endif
184
185 return (PyObject *) b;
186}
187
188/* Methods */
189
190static void
191buffer_dealloc(self)
192 PyBufferObject *self;
193{
194 Py_XDECREF(self->b_base);
195 free((void *)self);
196}
197
198static int
199buffer_compare(self, other)
200 PyBufferObject *self;
201 PyBufferObject *other;
202{
203 int len_self = self->b_size;
204 int len_other = other->b_size;
205 int min_len = (len_self < len_other) ? len_self : len_other;
206 int cmp;
207 if (min_len > 0) {
208 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
209 if (cmp != 0)
210 return cmp;
211 }
212 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
213}
214
215static PyObject *
216buffer_repr(self)
217 PyBufferObject *self;
218{
219 char buf[300];
220 char *status = self->b_readonly ? "read-only" : "read-write";
221
222 if ( self->b_base == NULL )
223 {
224 sprintf(buf, "<%s buffer ptr %lx, size %ld at %lx>",
225 status,
226 self->b_ptr,
227 self->b_size,
228 (long)self);
229 }
230 else
231 {
232 sprintf(buf, "<%s buffer for %lx, ptr %lx, size %ld at %lx>",
233 status,
234 (long)self->b_base,
235 self->b_ptr,
236 self->b_size,
237 (long)self);
238 }
239
240 return PyString_FromString(buf);
241}
242
243static long
244buffer_hash(self)
245 PyBufferObject *self;
246{
247 register int len;
248 register unsigned char *p;
249 register long x;
250
251#ifdef CACHE_HASH
252 if ( self->b_hash != -1 )
253 return self->b_hash;
254#endif
255
256 if ( !self->b_readonly )
257 {
258 /* ### use different wording, since this is conditional? */
259 PyErr_SetString(PyExc_TypeError, "unhashable type");
260 return -1;
261 }
262
263 len = self->b_size;
264 p = (unsigned char *) self->b_ptr;
265 x = *p << 7;
266 while (--len >= 0)
267 x = (1000003*x) ^ *p++;
268 x ^= self->b_size;
269 if (x == -1)
270 x = -2;
271#ifdef CACHE_HASH
272 self->b_hash = x;
273#endif
274 return x;
275}
276
277static PyObject *
278buffer_str(self)
279 PyBufferObject *self;
280{
281 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
282}
283
284/* Sequence methods */
285
286static int
287buffer_length(self)
288 PyBufferObject *self;
289{
290 return self->b_size;
291}
292
293static PyObject *
294buffer_concat(self, other)
295 PyBufferObject *self;
296 PyObject *other;
297{
298 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
299 char *p1;
300 void *p2;
301 PyObject *ob;
302 int count;
303
304 if ( pb == NULL ||
305 pb->bf_getreadbuffer == NULL ||
306 pb->bf_getsegcount == NULL )
307 {
308 PyErr_BadArgument();
309 return NULL;
310 }
311 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
312 {
313 /* ### use a different exception type/message? */
314 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
315 return NULL;
316 }
317
318 /* optimize special case */
319 if ( self->b_size == 0 )
320 {
321 Py_INCREF(other);
322 return other;
323 }
324
325 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
326 return NULL;
327
328 /* optimize special case */
329 if ( count == 0 )
330 {
331 Py_INCREF(self);
332 return (PyObject *)self;
333 }
334
335 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
336 p1 = PyString_AS_STRING(ob);
337 memcpy(p1, self->b_ptr, self->b_size);
338 memcpy(p1 + self->b_size, p2, count);
339
340 /* there is an extra byte in the string object, so this is safe */
341 p1[self->b_size + count] = '\0';
342
343 return ob;
344}
345
346static PyObject *
347buffer_repeat(self, count)
348 PyBufferObject *self;
349 int count;
350{
351 PyObject *ob;
352 register char *p;
353 void *ptr = self->b_ptr;
354 int size = self->b_size;
355
356 if ( count < 0 )
357 count = 0;
358 ob = PyString_FromStringAndSize(NULL, size * count);
359 if ( ob == NULL )
360 return NULL;
361
362 p = PyString_AS_STRING(ob);
363 while ( count-- )
364 {
365 memcpy(p, ptr, size);
366 p += size;
367 }
368
369 /* there is an extra byte in the string object, so this is safe */
370 *p = '\0';
371
372 return ob;
373}
374
375static PyObject *
376buffer_item(self, idx)
377 PyBufferObject *self;
378 int idx;
379{
380 if ( idx < 0 || idx >= self->b_size )
381 {
382 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
383 return NULL;
384 }
385 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
386}
387
388static PyObject *
389buffer_slice(self, left, right)
390 PyBufferObject *self;
391 int left;
392 int right;
393{
394 if ( left < 0 )
395 left = 0;
396 if ( right < 0 )
397 right = 0;
398 if ( right > self->b_size )
399 right = self->b_size;
400 if ( left == 0 && right == self->b_size )
401 {
402 /* same as self */
403 Py_INCREF(self);
404 return (PyObject *)self;
405 }
406 if ( right < left )
407 right = left;
408 return PyString_FromStringAndSize((char *)self->b_ptr + left, right - left);
409}
410
411static int
412buffer_ass_item(self, idx, other)
413 PyBufferObject *self;
414 int idx;
415 PyObject *other;
416{
417 PyBufferProcs *pb;
418 void *p;
419 int count;
420
421 if ( self->b_readonly ) {
422 PyErr_SetString(PyExc_TypeError,
423 "buffer is read-only");
424 return -1;
425 }
426
427 if (idx < 0 || idx >= self->b_size) {
428 PyErr_SetString(PyExc_IndexError,
429 "buffer assignment index out of range");
430 return -1;
431 }
432
433 pb = other ? other->ob_type->tp_as_buffer : NULL;
434 if ( pb == NULL ||
435 pb->bf_getreadbuffer == NULL ||
436 pb->bf_getsegcount == NULL )
437 {
438 PyErr_BadArgument();
439 return -1;
440 }
441 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
442 {
443 /* ### use a different exception type/message? */
444 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
445 return -1;
446 }
447
448 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
449 return -1;
450 if ( count != 1 ) {
451 PyErr_SetString(PyExc_TypeError,
452 "right operand must be a single byte");
453 return -1;
454 }
455
456 ((char *)self->b_ptr)[idx] = *(char *)p;
457 return 0;
458}
459
460static int
461buffer_ass_slice(self, left, right, other)
462 PyBufferObject *self;
463 int left;
464 int right;
465 PyObject *other;
466{
467 PyBufferProcs *pb;
468 void *p;
469 int slice_len;
470 int count;
471
472 if ( self->b_readonly ) {
473 PyErr_SetString(PyExc_TypeError,
474 "buffer is read-only");
475 return -1;
476 }
477
478 pb = other ? other->ob_type->tp_as_buffer : NULL;
479 if ( pb == NULL ||
480 pb->bf_getreadbuffer == NULL ||
481 pb->bf_getsegcount == NULL )
482 {
483 PyErr_BadArgument();
484 return -1;
485 }
486 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
487 {
488 /* ### use a different exception type/message? */
489 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
490 return -1;
491 }
492 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
493 return -1;
494
495 if ( left < 0 )
496 left = 0;
497 else if ( left > self->b_size )
498 left = self->b_size;
499 if ( right < left )
500 right = left;
501 else if ( right > self->b_size )
502 right = self->b_size;
503 slice_len = right - left;
504
505 if ( count != slice_len ) {
506 PyErr_SetString(PyExc_TypeError,
507 "right operand length must match slice length");
508 return -1;
509 }
510
511 if ( slice_len )
512 memcpy((char *)self->b_ptr + left, p, slice_len);
513
514 return 0;
515}
516
517/* Buffer methods */
518
519static int
520buffer_getreadbuf(self, idx, pp)
521 PyBufferObject *self;
522 int idx;
523 void ** pp;
524{
525 if ( idx != 0 ) {
526 PyErr_SetString(PyExc_SystemError,
527 "Accessing non-existent buffer segment");
528 return -1;
529 }
530 *pp = self->b_ptr;
531 return self->b_size;
532}
533
534static int
535buffer_getwritebuf(self, idx, pp)
536 PyBufferObject *self;
537 int idx;
538 void ** pp;
539{
540 if ( self->b_readonly )
541 {
542 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
543 return -1;
544 }
545 return buffer_getreadbuf(self, idx, pp);
546}
547
548static int
549buffer_getsegcount(self, lenp)
550 PyBufferObject *self;
551 int *lenp;
552{
553 if ( lenp )
554 *lenp = self->b_size;
555 return 1;
556}
557
558
559static PySequenceMethods buffer_as_sequence = {
560 (inquiry)buffer_length, /*sq_length*/
561 (binaryfunc)buffer_concat, /*sq_concat*/
562 (intargfunc)buffer_repeat, /*sq_repeat*/
563 (intargfunc)buffer_item, /*sq_item*/
564 (intintargfunc)buffer_slice, /*sq_slice*/
565 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
566 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
567};
568
569static PyBufferProcs buffer_as_buffer = {
570 (getreadbufferproc)buffer_getreadbuf,
571 (getwritebufferproc)buffer_getwritebuf,
572 (getsegcountproc)buffer_getsegcount,
573};
574
575PyTypeObject PyBuffer_Type = {
576 PyObject_HEAD_INIT(&PyType_Type)
577 0,
578 "buffer",
579 sizeof(PyBufferObject),
580 0,
581 (destructor)buffer_dealloc, /*tp_dealloc*/
582 0, /*tp_print*/
583 0, /*tp_getattr*/
584 0, /*tp_setattr*/
585 (cmpfunc)buffer_compare, /*tp_compare*/
586 (reprfunc)buffer_repr, /*tp_repr*/
587 0, /*tp_as_number*/
588 &buffer_as_sequence, /*tp_as_sequence*/
589 0, /*tp_as_mapping*/
590 (hashfunc)buffer_hash, /*tp_hash*/
591 0, /*tp_call*/
592 (reprfunc)buffer_str, /*tp_str*/
593 0, /*tp_getattro*/
594 0, /*tp_setattro*/
595 &buffer_as_buffer, /*tp_as_buffer*/
596 0, /*tp_xxx4*/
597 0, /*tp_doc*/
598};
599