Added 'list_only' option (and modified 'run()' to respect it).
[python/dscho.git] / Objects / bufferobject.c
blob05b1f11406d4f2dc0391a5c45e334dadaf5fb070
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Buffer object implementation */
34 #include "Python.h"
37 typedef 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;
49 static PyObject *
50 _PyBuffer_FromMemory(base, ptr, size, readonly)
51 PyObject *base;
52 void *ptr;
53 int size;
54 int readonly;
56 PyBufferObject * b;
58 if ( size < 0 ) {
59 PyErr_SetString(PyExc_ValueError,
60 "size must be zero or positive");
61 return NULL;
64 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
65 if ( b == NULL )
66 return NULL;
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
77 return (PyObject *) b;
80 static PyObject *
81 _PyBuffer_FromObject(base, offset, size, proc, readonly)
82 PyObject *base;
83 int offset;
84 int size;
85 getreadbufferproc proc;
86 int readonly;
88 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
89 void *p;
90 int count;
92 if ( offset < 0 ) {
93 PyErr_SetString(PyExc_ValueError,
94 "offset must be zero or positive");
95 return NULL;
98 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
100 PyErr_SetString(PyExc_TypeError,
101 "single-segment buffer object expected");
102 return NULL;
104 if ( (count = (*proc)(base, 0, &p)) < 0 )
105 return NULL;
107 /* apply constraints to the start/end */
108 if ( size == Py_END_OF_BUFFER || size < 0 )
109 size = count;
110 if ( offset > count )
111 offset = count;
112 if ( offset + size > count )
113 size = count - offset;
115 /* if the base object is another buffer, then "deref" it */
116 if ( PyBuffer_Check(base) )
117 base = ((PyBufferObject *)base)->b_base;
119 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
123 PyObject *
124 PyBuffer_FromObject(base, offset, size)
125 PyObject *base;
126 int offset;
127 int size;
129 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
131 if ( pb == NULL ||
132 pb->bf_getreadbuffer == NULL ||
133 pb->bf_getsegcount == NULL )
135 PyErr_SetString(PyExc_TypeError, "buffer object expected");
136 return NULL;
139 return _PyBuffer_FromObject(base, offset, size,
140 pb->bf_getreadbuffer, 1);
143 PyObject *
144 PyBuffer_FromReadWriteObject(base, offset, size)
145 PyObject *base;
146 int offset;
147 int size;
149 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
151 if ( pb == NULL ||
152 pb->bf_getwritebuffer == NULL ||
153 pb->bf_getsegcount == NULL )
155 PyErr_SetString(PyExc_TypeError, "buffer object expected");
156 return NULL;
159 return _PyBuffer_FromObject(base, offset, size,
160 (getreadbufferproc)pb->bf_getwritebuffer,
164 PyObject *
165 PyBuffer_FromMemory(ptr, size)
166 void *ptr;
167 int size;
169 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
172 PyObject *
173 PyBuffer_FromReadWriteMemory(ptr, size)
174 void *ptr;
175 int size;
177 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
180 PyObject *
181 PyBuffer_New(size)
182 int size;
184 PyBufferObject * b;
186 if (size < 0) {
187 PyErr_SetString(PyExc_ValueError,
188 "size must be zero or positive");
189 return NULL;
191 b = (PyBufferObject *)malloc(sizeof(*b) + size);
192 if ( b == NULL )
193 return PyErr_NoMemory();
194 b->ob_type = &PyBuffer_Type;
195 _Py_NewReference((PyObject *)b);
197 b->b_base = NULL;
198 b->b_ptr = (void *)(b + 1);
199 b->b_size = size;
200 b->b_readonly = 0;
201 #ifdef CACHE_HASH
202 b->b_hash = -1;
203 #endif
205 return (PyObject *) b;
208 /* Methods */
210 static void
211 buffer_dealloc(self)
212 PyBufferObject *self;
214 Py_XDECREF(self->b_base);
215 free((void *)self);
218 static int
219 buffer_compare(self, other)
220 PyBufferObject *self;
221 PyBufferObject *other;
223 int len_self = self->b_size;
224 int len_other = other->b_size;
225 int min_len = (len_self < len_other) ? len_self : len_other;
226 int cmp;
227 if (min_len > 0) {
228 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
229 if (cmp != 0)
230 return cmp;
232 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
235 static PyObject *
236 buffer_repr(self)
237 PyBufferObject *self;
239 char buf[300];
240 char *status = self->b_readonly ? "read-only" : "read-write";
242 if ( self->b_base == NULL )
244 sprintf(buf, "<%s buffer ptr %lx, size %d at %lx>",
245 status,
246 (long)self->b_ptr,
247 self->b_size,
248 (long)self);
250 else
252 sprintf(buf, "<%s buffer for %lx, ptr %lx, size %d at %lx>",
253 status,
254 (long)self->b_base,
255 (long)self->b_ptr,
256 self->b_size,
257 (long)self);
260 return PyString_FromString(buf);
263 static long
264 buffer_hash(self)
265 PyBufferObject *self;
267 register int len;
268 register unsigned char *p;
269 register long x;
271 #ifdef CACHE_HASH
272 if ( self->b_hash != -1 )
273 return self->b_hash;
274 #endif
276 if ( !self->b_readonly )
278 /* ### use different wording, since this is conditional? */
279 PyErr_SetString(PyExc_TypeError, "unhashable type");
280 return -1;
283 len = self->b_size;
284 p = (unsigned char *) self->b_ptr;
285 x = *p << 7;
286 while (--len >= 0)
287 x = (1000003*x) ^ *p++;
288 x ^= self->b_size;
289 if (x == -1)
290 x = -2;
291 #ifdef CACHE_HASH
292 self->b_hash = x;
293 #endif
294 return x;
297 static PyObject *
298 buffer_str(self)
299 PyBufferObject *self;
301 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
304 /* Sequence methods */
306 static int
307 buffer_length(self)
308 PyBufferObject *self;
310 return self->b_size;
313 static PyObject *
314 buffer_concat(self, other)
315 PyBufferObject *self;
316 PyObject *other;
318 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
319 char *p1;
320 void *p2;
321 PyObject *ob;
322 int count;
324 if ( pb == NULL ||
325 pb->bf_getreadbuffer == NULL ||
326 pb->bf_getsegcount == NULL )
328 PyErr_BadArgument();
329 return NULL;
331 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
333 /* ### use a different exception type/message? */
334 PyErr_SetString(PyExc_TypeError,
335 "single-segment buffer object expected");
336 return NULL;
339 /* optimize special case */
340 if ( self->b_size == 0 )
342 Py_INCREF(other);
343 return other;
346 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
347 return NULL;
349 /* optimize special case */
350 if ( count == 0 )
352 Py_INCREF(self);
353 return (PyObject *)self;
356 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
357 p1 = PyString_AS_STRING(ob);
358 memcpy(p1, self->b_ptr, self->b_size);
359 memcpy(p1 + self->b_size, p2, count);
361 /* there is an extra byte in the string object, so this is safe */
362 p1[self->b_size + count] = '\0';
364 return ob;
367 static PyObject *
368 buffer_repeat(self, count)
369 PyBufferObject *self;
370 int count;
372 PyObject *ob;
373 register char *p;
374 void *ptr = self->b_ptr;
375 int size = self->b_size;
377 if ( count < 0 )
378 count = 0;
379 ob = PyString_FromStringAndSize(NULL, size * count);
380 if ( ob == NULL )
381 return NULL;
383 p = PyString_AS_STRING(ob);
384 while ( count-- )
386 memcpy(p, ptr, size);
387 p += size;
390 /* there is an extra byte in the string object, so this is safe */
391 *p = '\0';
393 return ob;
396 static PyObject *
397 buffer_item(self, idx)
398 PyBufferObject *self;
399 int idx;
401 if ( idx < 0 || idx >= self->b_size )
403 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
404 return NULL;
406 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
409 static PyObject *
410 buffer_slice(self, left, right)
411 PyBufferObject *self;
412 int left;
413 int right;
415 if ( left < 0 )
416 left = 0;
417 if ( right < 0 )
418 right = 0;
419 if ( right > self->b_size )
420 right = self->b_size;
421 if ( left == 0 && right == self->b_size )
423 /* same as self */
424 Py_INCREF(self);
425 return (PyObject *)self;
427 if ( right < left )
428 right = left;
429 return PyString_FromStringAndSize((char *)self->b_ptr + left,
430 right - left);
433 static int
434 buffer_ass_item(self, idx, other)
435 PyBufferObject *self;
436 int idx;
437 PyObject *other;
439 PyBufferProcs *pb;
440 void *p;
441 int count;
443 if ( self->b_readonly ) {
444 PyErr_SetString(PyExc_TypeError,
445 "buffer is read-only");
446 return -1;
449 if (idx < 0 || idx >= self->b_size) {
450 PyErr_SetString(PyExc_IndexError,
451 "buffer assignment index out of range");
452 return -1;
455 pb = other ? other->ob_type->tp_as_buffer : NULL;
456 if ( pb == NULL ||
457 pb->bf_getreadbuffer == NULL ||
458 pb->bf_getsegcount == NULL )
460 PyErr_BadArgument();
461 return -1;
463 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
465 /* ### use a different exception type/message? */
466 PyErr_SetString(PyExc_TypeError,
467 "single-segment buffer object expected");
468 return -1;
471 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
472 return -1;
473 if ( count != 1 ) {
474 PyErr_SetString(PyExc_TypeError,
475 "right operand must be a single byte");
476 return -1;
479 ((char *)self->b_ptr)[idx] = *(char *)p;
480 return 0;
483 static int
484 buffer_ass_slice(self, left, right, other)
485 PyBufferObject *self;
486 int left;
487 int right;
488 PyObject *other;
490 PyBufferProcs *pb;
491 void *p;
492 int slice_len;
493 int count;
495 if ( self->b_readonly ) {
496 PyErr_SetString(PyExc_TypeError,
497 "buffer is read-only");
498 return -1;
501 pb = other ? other->ob_type->tp_as_buffer : NULL;
502 if ( pb == NULL ||
503 pb->bf_getreadbuffer == NULL ||
504 pb->bf_getsegcount == NULL )
506 PyErr_BadArgument();
507 return -1;
509 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
511 /* ### use a different exception type/message? */
512 PyErr_SetString(PyExc_TypeError,
513 "single-segment buffer object expected");
514 return -1;
516 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
517 return -1;
519 if ( left < 0 )
520 left = 0;
521 else if ( left > self->b_size )
522 left = self->b_size;
523 if ( right < left )
524 right = left;
525 else if ( right > self->b_size )
526 right = self->b_size;
527 slice_len = right - left;
529 if ( count != slice_len ) {
530 PyErr_SetString(
531 PyExc_TypeError,
532 "right operand length must match slice length");
533 return -1;
536 if ( slice_len )
537 memcpy((char *)self->b_ptr + left, p, slice_len);
539 return 0;
542 /* Buffer methods */
544 static int
545 buffer_getreadbuf(self, idx, pp)
546 PyBufferObject *self;
547 int idx;
548 void ** pp;
550 if ( idx != 0 ) {
551 PyErr_SetString(PyExc_SystemError,
552 "accessing non-existent buffer segment");
553 return -1;
555 *pp = self->b_ptr;
556 return self->b_size;
559 static int
560 buffer_getwritebuf(self, idx, pp)
561 PyBufferObject *self;
562 int idx;
563 void ** pp;
565 if ( self->b_readonly )
567 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
568 return -1;
570 return buffer_getreadbuf(self, idx, pp);
573 static int
574 buffer_getsegcount(self, lenp)
575 PyBufferObject *self;
576 int *lenp;
578 if ( lenp )
579 *lenp = self->b_size;
580 return 1;
583 static int
584 buffer_getcharbuf(self, idx, pp)
585 PyBufferObject *self;
586 int idx;
587 const char ** pp;
589 if ( idx != 0 ) {
590 PyErr_SetString(PyExc_SystemError,
591 "accessing non-existent buffer segment");
592 return -1;
594 *pp = (const char *)self->b_ptr;
595 return self->b_size;
599 static PySequenceMethods buffer_as_sequence = {
600 (inquiry)buffer_length, /*sq_length*/
601 (binaryfunc)buffer_concat, /*sq_concat*/
602 (intargfunc)buffer_repeat, /*sq_repeat*/
603 (intargfunc)buffer_item, /*sq_item*/
604 (intintargfunc)buffer_slice, /*sq_slice*/
605 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
606 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
609 static PyBufferProcs buffer_as_buffer = {
610 (getreadbufferproc)buffer_getreadbuf,
611 (getwritebufferproc)buffer_getwritebuf,
612 (getsegcountproc)buffer_getsegcount,
613 (getcharbufferproc)buffer_getcharbuf,
616 PyTypeObject PyBuffer_Type = {
617 PyObject_HEAD_INIT(&PyType_Type)
619 "buffer",
620 sizeof(PyBufferObject),
622 (destructor)buffer_dealloc, /*tp_dealloc*/
623 0, /*tp_print*/
624 0, /*tp_getattr*/
625 0, /*tp_setattr*/
626 (cmpfunc)buffer_compare, /*tp_compare*/
627 (reprfunc)buffer_repr, /*tp_repr*/
628 0, /*tp_as_number*/
629 &buffer_as_sequence, /*tp_as_sequence*/
630 0, /*tp_as_mapping*/
631 (hashfunc)buffer_hash, /*tp_hash*/
632 0, /*tp_call*/
633 (reprfunc)buffer_str, /*tp_str*/
634 0, /*tp_getattro*/
635 0, /*tp_setattro*/
636 &buffer_as_buffer, /*tp_as_buffer*/
637 Py_TPFLAGS_DEFAULT, /*tp_flags*/
638 0, /*tp_doc*/