blob: 57d031cade56824b0a51304ce9541b73f063aa83 [file] [log] [blame]
Guido van Rossum2e19bd71998-10-07 14:36:10 +00001
2/* Buffer object implementation */
3
4#include "Python.h"
5
6
7typedef 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;
17
18
19static PyObject *
Fred Drake79912472000-07-09 04:06:11 +000020_PyBuffer_FromMemory(PyObject *base, void *ptr, int size, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000021{
22 PyBufferObject * b;
23
Guido van Rossum49ded3e1999-03-19 19:04:25 +000024 if ( size < 0 ) {
25 PyErr_SetString(PyExc_ValueError,
26 "size must be zero or positive");
27 return NULL;
28 }
29
Guido van Rossum2e19bd71998-10-07 14:36:10 +000030 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
31 if ( b == NULL )
32 return NULL;
33
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
42
43 return (PyObject *) b;
44}
45
46static PyObject *
Fred Drake79912472000-07-09 04:06:11 +000047_PyBuffer_FromObject(PyObject *base, int offset, int size,
48 getreadbufferproc proc, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000049{
50 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
51 void *p;
52 int count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000053
Guido van Rossum49ded3e1999-03-19 19:04:25 +000054 if ( offset < 0 ) {
55 PyErr_SetString(PyExc_ValueError,
56 "offset must be zero or positive");
57 return NULL;
58 }
59
Guido van Rossum2e19bd71998-10-07 14:36:10 +000060 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
61 {
Guido van Rossumcd037e71999-03-24 19:05:31 +000062 PyErr_SetString(PyExc_TypeError,
63 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +000064 return NULL;
65 }
66 if ( (count = (*proc)(base, 0, &p)) < 0 )
67 return NULL;
68
69 /* apply constraints to the start/end */
Guido van Rossum49ded3e1999-03-19 19:04:25 +000070 if ( size == Py_END_OF_BUFFER || size < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +000071 size = count;
72 if ( offset > count )
73 offset = count;
74 if ( offset + size > count )
75 size = count - offset;
Thomas Hellerfdc1bd32001-10-19 13:49:35 +000076
77 /* if the base object is another buffer, then "deref" it,
78 * except if the base of the other buffer is NULL
79 */
80 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) )
Guido van Rossum2e19bd71998-10-07 14:36:10 +000081 base = ((PyBufferObject *)base)->b_base;
Thomas Hellerfdc1bd32001-10-19 13:49:35 +000082
Guido van Rossum2e19bd71998-10-07 14:36:10 +000083 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
84}
85
86
87PyObject *
Fred Drake79912472000-07-09 04:06:11 +000088PyBuffer_FromObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000089{
90 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
91
92 if ( pb == NULL ||
93 pb->bf_getreadbuffer == NULL ||
94 pb->bf_getsegcount == NULL )
95 {
96 PyErr_SetString(PyExc_TypeError, "buffer object expected");
97 return NULL;
98 }
99
Guido van Rossumcd037e71999-03-24 19:05:31 +0000100 return _PyBuffer_FromObject(base, offset, size,
101 pb->bf_getreadbuffer, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000102}
103
104PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000105PyBuffer_FromReadWriteObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000106{
107 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
108
109 if ( pb == NULL ||
110 pb->bf_getwritebuffer == NULL ||
111 pb->bf_getsegcount == NULL )
112 {
113 PyErr_SetString(PyExc_TypeError, "buffer object expected");
114 return NULL;
115 }
116
Guido van Rossumcd037e71999-03-24 19:05:31 +0000117 return _PyBuffer_FromObject(base, offset, size,
118 (getreadbufferproc)pb->bf_getwritebuffer,
119 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000120}
121
122PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000123PyBuffer_FromMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000124{
125 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
126}
127
128PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000129PyBuffer_FromReadWriteMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000130{
131 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
132}
133
134PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000135PyBuffer_New(int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000136{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000137 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000138 PyBufferObject * b;
139
Fred Drake4574f231999-08-04 13:08:19 +0000140 if (size < 0) {
141 PyErr_SetString(PyExc_ValueError,
142 "size must be zero or positive");
143 return NULL;
144 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000145 /* PyObject_New is inlined */
Moshe Zadkacf703f02000-08-04 15:36:13 +0000146 o = PyObject_MALLOC(sizeof(*b) + size);
147 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000148 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000149 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000150
151 b->b_base = NULL;
152 b->b_ptr = (void *)(b + 1);
153 b->b_size = size;
154 b->b_readonly = 0;
155#ifdef CACHE_HASH
156 b->b_hash = -1;
157#endif
158
Moshe Zadkacf703f02000-08-04 15:36:13 +0000159 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000160}
161
162/* Methods */
163
164static void
Fred Drake79912472000-07-09 04:06:11 +0000165buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000166{
167 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000168 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000169}
170
171static int
Fred Drake79912472000-07-09 04:06:11 +0000172buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000173{
174 int len_self = self->b_size;
175 int len_other = other->b_size;
176 int min_len = (len_self < len_other) ? len_self : len_other;
177 int cmp;
178 if (min_len > 0) {
179 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
180 if (cmp != 0)
181 return cmp;
182 }
183 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
184}
185
186static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000187buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000188{
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000189 char *status = self->b_readonly ? "read-only" : "read-write";
190
191 if ( self->b_base == NULL )
Barry Warsaw7ce36942001-08-24 18:34:26 +0000192 return PyString_FromFormat("<%s buffer ptr %p, size %d at %p>",
193 status,
194 self->b_ptr,
195 self->b_size,
196 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000198 return PyString_FromFormat(
199 "<%s buffer for %p, ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000200 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000201 self->b_base,
202 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000204 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000205}
206
207static long
Fred Drake79912472000-07-09 04:06:11 +0000208buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000209{
210 register int len;
211 register unsigned char *p;
212 register long x;
213
214#ifdef CACHE_HASH
215 if ( self->b_hash != -1 )
216 return self->b_hash;
217#endif
218
219 if ( !self->b_readonly )
220 {
221 /* ### use different wording, since this is conditional? */
222 PyErr_SetString(PyExc_TypeError, "unhashable type");
223 return -1;
224 }
225
226 len = self->b_size;
227 p = (unsigned char *) self->b_ptr;
228 x = *p << 7;
229 while (--len >= 0)
230 x = (1000003*x) ^ *p++;
231 x ^= self->b_size;
232 if (x == -1)
233 x = -2;
234#ifdef CACHE_HASH
235 self->b_hash = x;
236#endif
237 return x;
238}
239
240static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000241buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000242{
243 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
244}
245
246/* Sequence methods */
247
248static int
Fred Drake79912472000-07-09 04:06:11 +0000249buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000250{
251 return self->b_size;
252}
253
254static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000255buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000256{
257 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
258 char *p1;
259 void *p2;
260 PyObject *ob;
261 int count;
262
263 if ( pb == NULL ||
264 pb->bf_getreadbuffer == NULL ||
265 pb->bf_getsegcount == NULL )
266 {
267 PyErr_BadArgument();
268 return NULL;
269 }
270 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
271 {
272 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000273 PyErr_SetString(PyExc_TypeError,
274 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000275 return NULL;
276 }
277
278 /* optimize special case */
279 if ( self->b_size == 0 )
280 {
281 Py_INCREF(other);
282 return other;
283 }
284
285 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
286 return NULL;
287
288 /* optimize special case */
289 if ( count == 0 )
290 {
291 Py_INCREF(self);
292 return (PyObject *)self;
293 }
294
295 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
296 p1 = PyString_AS_STRING(ob);
297 memcpy(p1, self->b_ptr, self->b_size);
298 memcpy(p1 + self->b_size, p2, count);
299
300 /* there is an extra byte in the string object, so this is safe */
301 p1[self->b_size + count] = '\0';
302
303 return ob;
304}
305
306static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000307buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000308{
309 PyObject *ob;
310 register char *p;
311 void *ptr = self->b_ptr;
312 int size = self->b_size;
313
314 if ( count < 0 )
315 count = 0;
316 ob = PyString_FromStringAndSize(NULL, size * count);
317 if ( ob == NULL )
318 return NULL;
319
320 p = PyString_AS_STRING(ob);
321 while ( count-- )
322 {
323 memcpy(p, ptr, size);
324 p += size;
325 }
326
327 /* there is an extra byte in the string object, so this is safe */
328 *p = '\0';
329
330 return ob;
331}
332
333static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000334buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000335{
336 if ( idx < 0 || idx >= self->b_size )
337 {
338 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
339 return NULL;
340 }
341 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
342}
343
344static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000345buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000346{
347 if ( left < 0 )
348 left = 0;
349 if ( right < 0 )
350 right = 0;
351 if ( right > self->b_size )
352 right = self->b_size;
353 if ( left == 0 && right == self->b_size )
354 {
355 /* same as self */
356 Py_INCREF(self);
357 return (PyObject *)self;
358 }
359 if ( right < left )
360 right = left;
Guido van Rossumcd037e71999-03-24 19:05:31 +0000361 return PyString_FromStringAndSize((char *)self->b_ptr + left,
362 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000363}
364
365static int
Fred Drake79912472000-07-09 04:06:11 +0000366buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000367{
368 PyBufferProcs *pb;
369 void *p;
370 int count;
371
372 if ( self->b_readonly ) {
373 PyErr_SetString(PyExc_TypeError,
374 "buffer is read-only");
375 return -1;
376 }
377
378 if (idx < 0 || idx >= self->b_size) {
379 PyErr_SetString(PyExc_IndexError,
380 "buffer assignment index out of range");
381 return -1;
382 }
383
384 pb = other ? other->ob_type->tp_as_buffer : NULL;
385 if ( pb == NULL ||
386 pb->bf_getreadbuffer == NULL ||
387 pb->bf_getsegcount == NULL )
388 {
389 PyErr_BadArgument();
390 return -1;
391 }
392 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
393 {
394 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000395 PyErr_SetString(PyExc_TypeError,
396 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000397 return -1;
398 }
399
400 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
401 return -1;
402 if ( count != 1 ) {
403 PyErr_SetString(PyExc_TypeError,
404 "right operand must be a single byte");
405 return -1;
406 }
407
408 ((char *)self->b_ptr)[idx] = *(char *)p;
409 return 0;
410}
411
412static int
Fred Drake79912472000-07-09 04:06:11 +0000413buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000414{
415 PyBufferProcs *pb;
416 void *p;
417 int slice_len;
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 pb = other ? other->ob_type->tp_as_buffer : NULL;
427 if ( pb == NULL ||
428 pb->bf_getreadbuffer == NULL ||
429 pb->bf_getsegcount == NULL )
430 {
431 PyErr_BadArgument();
432 return -1;
433 }
434 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
435 {
436 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000437 PyErr_SetString(PyExc_TypeError,
438 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000439 return -1;
440 }
441 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
442 return -1;
443
444 if ( left < 0 )
445 left = 0;
446 else if ( left > self->b_size )
447 left = self->b_size;
448 if ( right < left )
449 right = left;
450 else if ( right > self->b_size )
451 right = self->b_size;
452 slice_len = right - left;
453
454 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000455 PyErr_SetString(
456 PyExc_TypeError,
457 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000458 return -1;
459 }
460
461 if ( slice_len )
462 memcpy((char *)self->b_ptr + left, p, slice_len);
463
464 return 0;
465}
466
467/* Buffer methods */
468
469static int
Fred Drake79912472000-07-09 04:06:11 +0000470buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000471{
472 if ( idx != 0 ) {
473 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000474 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000475 return -1;
476 }
477 *pp = self->b_ptr;
478 return self->b_size;
479}
480
481static int
Fred Drake79912472000-07-09 04:06:11 +0000482buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000483{
484 if ( self->b_readonly )
485 {
486 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
487 return -1;
488 }
489 return buffer_getreadbuf(self, idx, pp);
490}
491
492static int
Fred Drake79912472000-07-09 04:06:11 +0000493buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000494{
495 if ( lenp )
496 *lenp = self->b_size;
497 return 1;
498}
499
Guido van Rossum1db70701998-10-08 02:18:52 +0000500static int
Fred Drake79912472000-07-09 04:06:11 +0000501buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000502{
503 if ( idx != 0 ) {
504 PyErr_SetString(PyExc_SystemError,
505 "accessing non-existent buffer segment");
506 return -1;
507 }
508 *pp = (const char *)self->b_ptr;
509 return self->b_size;
510}
511
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000512
513static PySequenceMethods buffer_as_sequence = {
514 (inquiry)buffer_length, /*sq_length*/
515 (binaryfunc)buffer_concat, /*sq_concat*/
516 (intargfunc)buffer_repeat, /*sq_repeat*/
517 (intargfunc)buffer_item, /*sq_item*/
518 (intintargfunc)buffer_slice, /*sq_slice*/
519 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
520 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
521};
522
523static PyBufferProcs buffer_as_buffer = {
524 (getreadbufferproc)buffer_getreadbuf,
525 (getwritebufferproc)buffer_getwritebuf,
526 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000527 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000528};
529
530PyTypeObject PyBuffer_Type = {
531 PyObject_HEAD_INIT(&PyType_Type)
532 0,
533 "buffer",
534 sizeof(PyBufferObject),
535 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000536 (destructor)buffer_dealloc, /* tp_dealloc */
537 0, /* tp_print */
538 0, /* tp_getattr */
539 0, /* tp_setattr */
540 (cmpfunc)buffer_compare, /* tp_compare */
541 (reprfunc)buffer_repr, /* tp_repr */
542 0, /* tp_as_number */
543 &buffer_as_sequence, /* tp_as_sequence */
544 0, /* tp_as_mapping */
545 (hashfunc)buffer_hash, /* tp_hash */
546 0, /* tp_call */
547 (reprfunc)buffer_str, /* tp_str */
548 PyObject_GenericGetAttr, /* tp_getattro */
549 0, /* tp_setattro */
550 &buffer_as_buffer, /* tp_as_buffer */
551 Py_TPFLAGS_DEFAULT, /* tp_flags */
552 0, /* tp_doc */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000553};