Fix an amazing number of typos & malformed sentences reported by Detlef
[python/dscho.git] / Objects / bufferobject.c
blob091688d677e6dbced1257138a681fee611f3eb35
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 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
59 if ( b == NULL )
60 return NULL;
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
71 return (PyObject *) b;
74 static PyObject *
75 _PyBuffer_FromObject(base, offset, size, proc, readonly)
76 PyObject *base;
77 int offset;
78 int size;
79 getreadbufferproc proc;
80 int readonly;
82 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
83 void *p;
84 int count;
86 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
88 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
89 return NULL;
91 if ( (count = (*proc)(base, 0, &p)) < 0 )
92 return NULL;
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;
102 /* if the base object is another buffer, then "deref" it */
103 if ( PyBuffer_Check(base) )
104 base = ((PyBufferObject *)base)->b_base;
106 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
110 PyObject *
111 PyBuffer_FromObject(base, offset, size)
112 PyObject *base;
113 int offset;
114 int size;
116 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
118 if ( pb == NULL ||
119 pb->bf_getreadbuffer == NULL ||
120 pb->bf_getsegcount == NULL )
122 PyErr_SetString(PyExc_TypeError, "buffer object expected");
123 return NULL;
126 return _PyBuffer_FromObject(base, offset, size, pb->bf_getreadbuffer, 1);
129 PyObject *
130 PyBuffer_FromReadWriteObject(base, offset, size)
131 PyObject *base;
132 int offset;
133 int size;
135 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
137 if ( pb == NULL ||
138 pb->bf_getwritebuffer == NULL ||
139 pb->bf_getsegcount == NULL )
141 PyErr_SetString(PyExc_TypeError, "buffer object expected");
142 return NULL;
145 return _PyBuffer_FromObject(base, offset, size, (getreadbufferproc)pb->bf_getwritebuffer, 0);
148 PyObject *
149 PyBuffer_FromMemory(ptr, size)
150 void *ptr;
151 int size;
153 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
156 PyObject *
157 PyBuffer_FromReadWriteMemory(ptr, size)
158 void *ptr;
159 int size;
161 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
164 PyObject *
165 PyBuffer_New(size)
166 int size;
168 PyBufferObject * b;
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);
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
184 return (PyObject *) b;
187 /* Methods */
189 static void
190 buffer_dealloc(self)
191 PyBufferObject *self;
193 Py_XDECREF(self->b_base);
194 free((void *)self);
197 static int
198 buffer_compare(self, other)
199 PyBufferObject *self;
200 PyBufferObject *other;
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;
211 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
214 static PyObject *
215 buffer_repr(self)
216 PyBufferObject *self;
218 char buf[300];
219 char *status = self->b_readonly ? "read-only" : "read-write";
221 if ( self->b_base == NULL )
223 sprintf(buf, "<%s buffer ptr %lx, size %d at %lx>",
224 status,
225 (long)self->b_ptr,
226 self->b_size,
227 (long)self);
229 else
231 sprintf(buf, "<%s buffer for %lx, ptr %lx, size %d at %lx>",
232 status,
233 (long)self->b_base,
234 (long)self->b_ptr,
235 self->b_size,
236 (long)self);
239 return PyString_FromString(buf);
242 static long
243 buffer_hash(self)
244 PyBufferObject *self;
246 register int len;
247 register unsigned char *p;
248 register long x;
250 #ifdef CACHE_HASH
251 if ( self->b_hash != -1 )
252 return self->b_hash;
253 #endif
255 if ( !self->b_readonly )
257 /* ### use different wording, since this is conditional? */
258 PyErr_SetString(PyExc_TypeError, "unhashable type");
259 return -1;
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;
276 static PyObject *
277 buffer_str(self)
278 PyBufferObject *self;
280 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
283 /* Sequence methods */
285 static int
286 buffer_length(self)
287 PyBufferObject *self;
289 return self->b_size;
292 static PyObject *
293 buffer_concat(self, other)
294 PyBufferObject *self;
295 PyObject *other;
297 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
298 char *p1;
299 void *p2;
300 PyObject *ob;
301 int count;
303 if ( pb == NULL ||
304 pb->bf_getreadbuffer == NULL ||
305 pb->bf_getsegcount == NULL )
307 PyErr_BadArgument();
308 return NULL;
310 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
312 /* ### use a different exception type/message? */
313 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
314 return NULL;
317 /* optimize special case */
318 if ( self->b_size == 0 )
320 Py_INCREF(other);
321 return other;
324 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
325 return NULL;
327 /* optimize special case */
328 if ( count == 0 )
330 Py_INCREF(self);
331 return (PyObject *)self;
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);
339 /* there is an extra byte in the string object, so this is safe */
340 p1[self->b_size + count] = '\0';
342 return ob;
345 static PyObject *
346 buffer_repeat(self, count)
347 PyBufferObject *self;
348 int count;
350 PyObject *ob;
351 register char *p;
352 void *ptr = self->b_ptr;
353 int size = self->b_size;
355 if ( count < 0 )
356 count = 0;
357 ob = PyString_FromStringAndSize(NULL, size * count);
358 if ( ob == NULL )
359 return NULL;
361 p = PyString_AS_STRING(ob);
362 while ( count-- )
364 memcpy(p, ptr, size);
365 p += size;
368 /* there is an extra byte in the string object, so this is safe */
369 *p = '\0';
371 return ob;
374 static PyObject *
375 buffer_item(self, idx)
376 PyBufferObject *self;
377 int idx;
379 if ( idx < 0 || idx >= self->b_size )
381 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
382 return NULL;
384 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
387 static PyObject *
388 buffer_slice(self, left, right)
389 PyBufferObject *self;
390 int left;
391 int right;
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 )
401 /* same as self */
402 Py_INCREF(self);
403 return (PyObject *)self;
405 if ( right < left )
406 right = left;
407 return PyString_FromStringAndSize((char *)self->b_ptr + left, right - left);
410 static int
411 buffer_ass_item(self, idx, other)
412 PyBufferObject *self;
413 int idx;
414 PyObject *other;
416 PyBufferProcs *pb;
417 void *p;
418 int count;
420 if ( self->b_readonly ) {
421 PyErr_SetString(PyExc_TypeError,
422 "buffer is read-only");
423 return -1;
426 if (idx < 0 || idx >= self->b_size) {
427 PyErr_SetString(PyExc_IndexError,
428 "buffer assignment index out of range");
429 return -1;
432 pb = other ? other->ob_type->tp_as_buffer : NULL;
433 if ( pb == NULL ||
434 pb->bf_getreadbuffer == NULL ||
435 pb->bf_getsegcount == NULL )
437 PyErr_BadArgument();
438 return -1;
440 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
442 /* ### use a different exception type/message? */
443 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
444 return -1;
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;
455 ((char *)self->b_ptr)[idx] = *(char *)p;
456 return 0;
459 static int
460 buffer_ass_slice(self, left, right, other)
461 PyBufferObject *self;
462 int left;
463 int right;
464 PyObject *other;
466 PyBufferProcs *pb;
467 void *p;
468 int slice_len;
469 int count;
471 if ( self->b_readonly ) {
472 PyErr_SetString(PyExc_TypeError,
473 "buffer is read-only");
474 return -1;
477 pb = other ? other->ob_type->tp_as_buffer : NULL;
478 if ( pb == NULL ||
479 pb->bf_getreadbuffer == NULL ||
480 pb->bf_getsegcount == NULL )
482 PyErr_BadArgument();
483 return -1;
485 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
487 /* ### use a different exception type/message? */
488 PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected");
489 return -1;
491 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
492 return -1;
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;
504 if ( count != slice_len ) {
505 PyErr_SetString(PyExc_TypeError,
506 "right operand length must match slice length");
507 return -1;
510 if ( slice_len )
511 memcpy((char *)self->b_ptr + left, p, slice_len);
513 return 0;
516 /* Buffer methods */
518 static int
519 buffer_getreadbuf(self, idx, pp)
520 PyBufferObject *self;
521 int idx;
522 void ** pp;
524 if ( idx != 0 ) {
525 PyErr_SetString(PyExc_SystemError,
526 "accessing non-existent buffer segment");
527 return -1;
529 *pp = self->b_ptr;
530 return self->b_size;
533 static int
534 buffer_getwritebuf(self, idx, pp)
535 PyBufferObject *self;
536 int idx;
537 void ** pp;
539 if ( self->b_readonly )
541 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
542 return -1;
544 return buffer_getreadbuf(self, idx, pp);
547 static int
548 buffer_getsegcount(self, lenp)
549 PyBufferObject *self;
550 int *lenp;
552 if ( lenp )
553 *lenp = self->b_size;
554 return 1;
557 static int
558 buffer_getcharbuf(self, idx, pp)
559 PyBufferObject *self;
560 int idx;
561 const char ** pp;
563 if ( idx != 0 ) {
564 PyErr_SetString(PyExc_SystemError,
565 "accessing non-existent buffer segment");
566 return -1;
568 *pp = (const char *)self->b_ptr;
569 return self->b_size;
573 static 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*/
583 static PyBufferProcs buffer_as_buffer = {
584 (getreadbufferproc)buffer_getreadbuf,
585 (getwritebufferproc)buffer_getwritebuf,
586 (getsegcountproc)buffer_getsegcount,
587 (getcharbufferproc)buffer_getcharbuf,
590 PyTypeObject PyBuffer_Type = {
591 PyObject_HEAD_INIT(&PyType_Type)
593 "buffer",
594 sizeof(PyBufferObject),
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*/
611 Py_TPFLAGS_DEFAULT, /*tp_flags*/
612 0, /*tp_doc*/