Files for 2.1b1 distribution.
[python/dscho.git] / Objects / bufferobject.c
blob1a17ec5ba8c915702ddd7124fe18f22e0652e4f5
2 /* Buffer object implementation */
4 #include "Python.h"
7 typedef struct {
8 PyObject_HEAD
9 PyObject *b_base;
10 void *b_ptr;
11 int b_size;
12 int b_readonly;
13 #ifdef CACHE_HASH
14 long b_hash;
15 #endif
16 } PyBufferObject;
19 static PyObject *
20 _PyBuffer_FromMemory(PyObject *base, void *ptr, int size, int readonly)
22 PyBufferObject * b;
24 if ( size < 0 ) {
25 PyErr_SetString(PyExc_ValueError,
26 "size must be zero or positive");
27 return NULL;
30 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
31 if ( b == NULL )
32 return NULL;
34 Py_XINCREF(base);
35 b->b_base = base;
36 b->b_ptr = ptr;
37 b->b_size = size;
38 b->b_readonly = readonly;
39 #ifdef CACHE_HASH
40 b->b_hash = -1;
41 #endif
43 return (PyObject *) b;
46 static PyObject *
47 _PyBuffer_FromObject(PyObject *base, int offset, int size,
48 getreadbufferproc proc, int readonly)
50 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
51 void *p;
52 int count;
54 if ( offset < 0 ) {
55 PyErr_SetString(PyExc_ValueError,
56 "offset must be zero or positive");
57 return NULL;
60 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
62 PyErr_SetString(PyExc_TypeError,
63 "single-segment buffer object expected");
64 return NULL;
66 if ( (count = (*proc)(base, 0, &p)) < 0 )
67 return NULL;
69 /* apply constraints to the start/end */
70 if ( size == Py_END_OF_BUFFER || size < 0 )
71 size = count;
72 if ( offset > count )
73 offset = count;
74 if ( offset + size > count )
75 size = count - offset;
77 /* if the base object is another buffer, then "deref" it */
78 if ( PyBuffer_Check(base) )
79 base = ((PyBufferObject *)base)->b_base;
81 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
85 PyObject *
86 PyBuffer_FromObject(PyObject *base, int offset, int size)
88 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
90 if ( pb == NULL ||
91 pb->bf_getreadbuffer == NULL ||
92 pb->bf_getsegcount == NULL )
94 PyErr_SetString(PyExc_TypeError, "buffer object expected");
95 return NULL;
98 return _PyBuffer_FromObject(base, offset, size,
99 pb->bf_getreadbuffer, 1);
102 PyObject *
103 PyBuffer_FromReadWriteObject(PyObject *base, int offset, int size)
105 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
107 if ( pb == NULL ||
108 pb->bf_getwritebuffer == NULL ||
109 pb->bf_getsegcount == NULL )
111 PyErr_SetString(PyExc_TypeError, "buffer object expected");
112 return NULL;
115 return _PyBuffer_FromObject(base, offset, size,
116 (getreadbufferproc)pb->bf_getwritebuffer,
120 PyObject *
121 PyBuffer_FromMemory(void *ptr, int size)
123 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
126 PyObject *
127 PyBuffer_FromReadWriteMemory(void *ptr, int size)
129 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
132 PyObject *
133 PyBuffer_New(int size)
135 PyObject *o;
136 PyBufferObject * b;
138 if (size < 0) {
139 PyErr_SetString(PyExc_ValueError,
140 "size must be zero or positive");
141 return NULL;
143 /* PyObject_New is inlined */
144 o = PyObject_MALLOC(sizeof(*b) + size);
145 if ( o == NULL )
146 return PyErr_NoMemory();
147 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
149 b->b_base = NULL;
150 b->b_ptr = (void *)(b + 1);
151 b->b_size = size;
152 b->b_readonly = 0;
153 #ifdef CACHE_HASH
154 b->b_hash = -1;
155 #endif
157 return o;
160 /* Methods */
162 static void
163 buffer_dealloc(PyBufferObject *self)
165 Py_XDECREF(self->b_base);
166 PyObject_DEL(self);
169 static int
170 buffer_compare(PyBufferObject *self, PyBufferObject *other)
172 int len_self = self->b_size;
173 int len_other = other->b_size;
174 int min_len = (len_self < len_other) ? len_self : len_other;
175 int cmp;
176 if (min_len > 0) {
177 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
178 if (cmp != 0)
179 return cmp;
181 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
184 static PyObject *
185 buffer_repr(PyBufferObject *self)
187 char buf[300];
188 char *status = self->b_readonly ? "read-only" : "read-write";
190 if ( self->b_base == NULL )
192 sprintf(buf, "<%s buffer ptr %p, size %d at %p>",
193 status,
194 self->b_ptr,
195 self->b_size,
196 self);
198 else
200 sprintf(buf, "<%s buffer for %p, ptr %p, size %d at %p>",
201 status,
202 self->b_base,
203 self->b_ptr,
204 self->b_size,
205 self);
208 return PyString_FromString(buf);
211 static long
212 buffer_hash(PyBufferObject *self)
214 register int len;
215 register unsigned char *p;
216 register long x;
218 #ifdef CACHE_HASH
219 if ( self->b_hash != -1 )
220 return self->b_hash;
221 #endif
223 if ( !self->b_readonly )
225 /* ### use different wording, since this is conditional? */
226 PyErr_SetString(PyExc_TypeError, "unhashable type");
227 return -1;
230 len = self->b_size;
231 p = (unsigned char *) self->b_ptr;
232 x = *p << 7;
233 while (--len >= 0)
234 x = (1000003*x) ^ *p++;
235 x ^= self->b_size;
236 if (x == -1)
237 x = -2;
238 #ifdef CACHE_HASH
239 self->b_hash = x;
240 #endif
241 return x;
244 static PyObject *
245 buffer_str(PyBufferObject *self)
247 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
250 /* Sequence methods */
252 static int
253 buffer_length(PyBufferObject *self)
255 return self->b_size;
258 static PyObject *
259 buffer_concat(PyBufferObject *self, PyObject *other)
261 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
262 char *p1;
263 void *p2;
264 PyObject *ob;
265 int count;
267 if ( pb == NULL ||
268 pb->bf_getreadbuffer == NULL ||
269 pb->bf_getsegcount == NULL )
271 PyErr_BadArgument();
272 return NULL;
274 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
276 /* ### use a different exception type/message? */
277 PyErr_SetString(PyExc_TypeError,
278 "single-segment buffer object expected");
279 return NULL;
282 /* optimize special case */
283 if ( self->b_size == 0 )
285 Py_INCREF(other);
286 return other;
289 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
290 return NULL;
292 /* optimize special case */
293 if ( count == 0 )
295 Py_INCREF(self);
296 return (PyObject *)self;
299 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
300 p1 = PyString_AS_STRING(ob);
301 memcpy(p1, self->b_ptr, self->b_size);
302 memcpy(p1 + self->b_size, p2, count);
304 /* there is an extra byte in the string object, so this is safe */
305 p1[self->b_size + count] = '\0';
307 return ob;
310 static PyObject *
311 buffer_repeat(PyBufferObject *self, int count)
313 PyObject *ob;
314 register char *p;
315 void *ptr = self->b_ptr;
316 int size = self->b_size;
318 if ( count < 0 )
319 count = 0;
320 ob = PyString_FromStringAndSize(NULL, size * count);
321 if ( ob == NULL )
322 return NULL;
324 p = PyString_AS_STRING(ob);
325 while ( count-- )
327 memcpy(p, ptr, size);
328 p += size;
331 /* there is an extra byte in the string object, so this is safe */
332 *p = '\0';
334 return ob;
337 static PyObject *
338 buffer_item(PyBufferObject *self, int idx)
340 if ( idx < 0 || idx >= self->b_size )
342 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
343 return NULL;
345 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
348 static PyObject *
349 buffer_slice(PyBufferObject *self, int left, int right)
351 if ( left < 0 )
352 left = 0;
353 if ( right < 0 )
354 right = 0;
355 if ( right > self->b_size )
356 right = self->b_size;
357 if ( left == 0 && right == self->b_size )
359 /* same as self */
360 Py_INCREF(self);
361 return (PyObject *)self;
363 if ( right < left )
364 right = left;
365 return PyString_FromStringAndSize((char *)self->b_ptr + left,
366 right - left);
369 static int
370 buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
372 PyBufferProcs *pb;
373 void *p;
374 int count;
376 if ( self->b_readonly ) {
377 PyErr_SetString(PyExc_TypeError,
378 "buffer is read-only");
379 return -1;
382 if (idx < 0 || idx >= self->b_size) {
383 PyErr_SetString(PyExc_IndexError,
384 "buffer assignment index out of range");
385 return -1;
388 pb = other ? other->ob_type->tp_as_buffer : NULL;
389 if ( pb == NULL ||
390 pb->bf_getreadbuffer == NULL ||
391 pb->bf_getsegcount == NULL )
393 PyErr_BadArgument();
394 return -1;
396 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
398 /* ### use a different exception type/message? */
399 PyErr_SetString(PyExc_TypeError,
400 "single-segment buffer object expected");
401 return -1;
404 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
405 return -1;
406 if ( count != 1 ) {
407 PyErr_SetString(PyExc_TypeError,
408 "right operand must be a single byte");
409 return -1;
412 ((char *)self->b_ptr)[idx] = *(char *)p;
413 return 0;
416 static int
417 buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
419 PyBufferProcs *pb;
420 void *p;
421 int slice_len;
422 int count;
424 if ( self->b_readonly ) {
425 PyErr_SetString(PyExc_TypeError,
426 "buffer is read-only");
427 return -1;
430 pb = other ? other->ob_type->tp_as_buffer : NULL;
431 if ( pb == NULL ||
432 pb->bf_getreadbuffer == NULL ||
433 pb->bf_getsegcount == NULL )
435 PyErr_BadArgument();
436 return -1;
438 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
440 /* ### use a different exception type/message? */
441 PyErr_SetString(PyExc_TypeError,
442 "single-segment buffer object expected");
443 return -1;
445 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
446 return -1;
448 if ( left < 0 )
449 left = 0;
450 else if ( left > self->b_size )
451 left = self->b_size;
452 if ( right < left )
453 right = left;
454 else if ( right > self->b_size )
455 right = self->b_size;
456 slice_len = right - left;
458 if ( count != slice_len ) {
459 PyErr_SetString(
460 PyExc_TypeError,
461 "right operand length must match slice length");
462 return -1;
465 if ( slice_len )
466 memcpy((char *)self->b_ptr + left, p, slice_len);
468 return 0;
471 /* Buffer methods */
473 static int
474 buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
476 if ( idx != 0 ) {
477 PyErr_SetString(PyExc_SystemError,
478 "accessing non-existent buffer segment");
479 return -1;
481 *pp = self->b_ptr;
482 return self->b_size;
485 static int
486 buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
488 if ( self->b_readonly )
490 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
491 return -1;
493 return buffer_getreadbuf(self, idx, pp);
496 static int
497 buffer_getsegcount(PyBufferObject *self, int *lenp)
499 if ( lenp )
500 *lenp = self->b_size;
501 return 1;
504 static int
505 buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
507 if ( idx != 0 ) {
508 PyErr_SetString(PyExc_SystemError,
509 "accessing non-existent buffer segment");
510 return -1;
512 *pp = (const char *)self->b_ptr;
513 return self->b_size;
517 static PySequenceMethods buffer_as_sequence = {
518 (inquiry)buffer_length, /*sq_length*/
519 (binaryfunc)buffer_concat, /*sq_concat*/
520 (intargfunc)buffer_repeat, /*sq_repeat*/
521 (intargfunc)buffer_item, /*sq_item*/
522 (intintargfunc)buffer_slice, /*sq_slice*/
523 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
524 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
527 static PyBufferProcs buffer_as_buffer = {
528 (getreadbufferproc)buffer_getreadbuf,
529 (getwritebufferproc)buffer_getwritebuf,
530 (getsegcountproc)buffer_getsegcount,
531 (getcharbufferproc)buffer_getcharbuf,
534 PyTypeObject PyBuffer_Type = {
535 PyObject_HEAD_INIT(&PyType_Type)
537 "buffer",
538 sizeof(PyBufferObject),
540 (destructor)buffer_dealloc, /*tp_dealloc*/
541 0, /*tp_print*/
542 0, /*tp_getattr*/
543 0, /*tp_setattr*/
544 (cmpfunc)buffer_compare, /*tp_compare*/
545 (reprfunc)buffer_repr, /*tp_repr*/
546 0, /*tp_as_number*/
547 &buffer_as_sequence, /*tp_as_sequence*/
548 0, /*tp_as_mapping*/
549 (hashfunc)buffer_hash, /*tp_hash*/
550 0, /*tp_call*/
551 (reprfunc)buffer_str, /*tp_str*/
552 0, /*tp_getattro*/
553 0, /*tp_setattro*/
554 &buffer_as_buffer, /*tp_as_buffer*/
555 Py_TPFLAGS_DEFAULT, /*tp_flags*/
556 0, /*tp_doc*/