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