blob: 1a17ec5ba8c915702ddd7124fe18f22e0652e4f5 [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;
76
77 /* if the base object is another buffer, then "deref" it */
78 if ( PyBuffer_Check(base) )
79 base = ((PyBufferObject *)base)->b_base;
80
81 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
82}
83
84
85PyObject *
Fred Drake79912472000-07-09 04:06:11 +000086PyBuffer_FromObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000087{
88 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
89
90 if ( pb == NULL ||
91 pb->bf_getreadbuffer == NULL ||
92 pb->bf_getsegcount == NULL )
93 {
94 PyErr_SetString(PyExc_TypeError, "buffer object expected");
95 return NULL;
96 }
97
Guido van Rossumcd037e71999-03-24 19:05:31 +000098 return _PyBuffer_FromObject(base, offset, size,
99 pb->bf_getreadbuffer, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000100}
101
102PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000103PyBuffer_FromReadWriteObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000104{
105 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
106
107 if ( pb == NULL ||
108 pb->bf_getwritebuffer == NULL ||
109 pb->bf_getsegcount == NULL )
110 {
111 PyErr_SetString(PyExc_TypeError, "buffer object expected");
112 return NULL;
113 }
114
Guido van Rossumcd037e71999-03-24 19:05:31 +0000115 return _PyBuffer_FromObject(base, offset, size,
116 (getreadbufferproc)pb->bf_getwritebuffer,
117 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000118}
119
120PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000121PyBuffer_FromMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000122{
123 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
124}
125
126PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000127PyBuffer_FromReadWriteMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000128{
129 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
130}
131
132PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000133PyBuffer_New(int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000134{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000135 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000136 PyBufferObject * b;
137
Fred Drake4574f231999-08-04 13:08:19 +0000138 if (size < 0) {
139 PyErr_SetString(PyExc_ValueError,
140 "size must be zero or positive");
141 return NULL;
142 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000143 /* PyObject_New is inlined */
Moshe Zadkacf703f02000-08-04 15:36:13 +0000144 o = PyObject_MALLOC(sizeof(*b) + size);
145 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000146 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000147 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000148
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
156
Moshe Zadkacf703f02000-08-04 15:36:13 +0000157 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000158}
159
160/* Methods */
161
162static void
Fred Drake79912472000-07-09 04:06:11 +0000163buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000164{
165 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000166 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000167}
168
169static int
Fred Drake79912472000-07-09 04:06:11 +0000170buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000171{
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;
180 }
181 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
182}
183
184static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000185buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000186{
187 char buf[300];
188 char *status = self->b_readonly ? "read-only" : "read-write";
189
190 if ( self->b_base == NULL )
191 {
Fred Drakea44d3532000-06-30 15:01:00 +0000192 sprintf(buf, "<%s buffer ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000193 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000194 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000196 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197 }
198 else
199 {
Fred Drakea44d3532000-06-30 15:01:00 +0000200 sprintf(buf, "<%s buffer for %p, ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000201 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000202 self->b_base,
203 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000204 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000205 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000206 }
207
208 return PyString_FromString(buf);
209}
210
211static long
Fred Drake79912472000-07-09 04:06:11 +0000212buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000213{
214 register int len;
215 register unsigned char *p;
216 register long x;
217
218#ifdef CACHE_HASH
219 if ( self->b_hash != -1 )
220 return self->b_hash;
221#endif
222
223 if ( !self->b_readonly )
224 {
225 /* ### use different wording, since this is conditional? */
226 PyErr_SetString(PyExc_TypeError, "unhashable type");
227 return -1;
228 }
229
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;
242}
243
244static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000245buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000246{
247 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
248}
249
250/* Sequence methods */
251
252static int
Fred Drake79912472000-07-09 04:06:11 +0000253buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000254{
255 return self->b_size;
256}
257
258static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000259buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000260{
261 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
262 char *p1;
263 void *p2;
264 PyObject *ob;
265 int count;
266
267 if ( pb == NULL ||
268 pb->bf_getreadbuffer == NULL ||
269 pb->bf_getsegcount == NULL )
270 {
271 PyErr_BadArgument();
272 return NULL;
273 }
274 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
275 {
276 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000277 PyErr_SetString(PyExc_TypeError,
278 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000279 return NULL;
280 }
281
282 /* optimize special case */
283 if ( self->b_size == 0 )
284 {
285 Py_INCREF(other);
286 return other;
287 }
288
289 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
290 return NULL;
291
292 /* optimize special case */
293 if ( count == 0 )
294 {
295 Py_INCREF(self);
296 return (PyObject *)self;
297 }
298
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);
303
304 /* there is an extra byte in the string object, so this is safe */
305 p1[self->b_size + count] = '\0';
306
307 return ob;
308}
309
310static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000311buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000312{
313 PyObject *ob;
314 register char *p;
315 void *ptr = self->b_ptr;
316 int size = self->b_size;
317
318 if ( count < 0 )
319 count = 0;
320 ob = PyString_FromStringAndSize(NULL, size * count);
321 if ( ob == NULL )
322 return NULL;
323
324 p = PyString_AS_STRING(ob);
325 while ( count-- )
326 {
327 memcpy(p, ptr, size);
328 p += size;
329 }
330
331 /* there is an extra byte in the string object, so this is safe */
332 *p = '\0';
333
334 return ob;
335}
336
337static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000338buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000339{
340 if ( idx < 0 || idx >= self->b_size )
341 {
342 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
343 return NULL;
344 }
345 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
346}
347
348static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000349buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000350{
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 )
358 {
359 /* same as self */
360 Py_INCREF(self);
361 return (PyObject *)self;
362 }
363 if ( right < left )
364 right = left;
Guido van Rossumcd037e71999-03-24 19:05:31 +0000365 return PyString_FromStringAndSize((char *)self->b_ptr + left,
366 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000367}
368
369static int
Fred Drake79912472000-07-09 04:06:11 +0000370buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000371{
372 PyBufferProcs *pb;
373 void *p;
374 int count;
375
376 if ( self->b_readonly ) {
377 PyErr_SetString(PyExc_TypeError,
378 "buffer is read-only");
379 return -1;
380 }
381
382 if (idx < 0 || idx >= self->b_size) {
383 PyErr_SetString(PyExc_IndexError,
384 "buffer assignment index out of range");
385 return -1;
386 }
387
388 pb = other ? other->ob_type->tp_as_buffer : NULL;
389 if ( pb == NULL ||
390 pb->bf_getreadbuffer == NULL ||
391 pb->bf_getsegcount == NULL )
392 {
393 PyErr_BadArgument();
394 return -1;
395 }
396 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
397 {
398 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000399 PyErr_SetString(PyExc_TypeError,
400 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000401 return -1;
402 }
403
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;
410 }
411
412 ((char *)self->b_ptr)[idx] = *(char *)p;
413 return 0;
414}
415
416static int
Fred Drake79912472000-07-09 04:06:11 +0000417buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000418{
419 PyBufferProcs *pb;
420 void *p;
421 int slice_len;
422 int count;
423
424 if ( self->b_readonly ) {
425 PyErr_SetString(PyExc_TypeError,
426 "buffer is read-only");
427 return -1;
428 }
429
430 pb = other ? other->ob_type->tp_as_buffer : NULL;
431 if ( pb == NULL ||
432 pb->bf_getreadbuffer == NULL ||
433 pb->bf_getsegcount == NULL )
434 {
435 PyErr_BadArgument();
436 return -1;
437 }
438 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
439 {
440 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000441 PyErr_SetString(PyExc_TypeError,
442 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000443 return -1;
444 }
445 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
446 return -1;
447
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;
457
458 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000459 PyErr_SetString(
460 PyExc_TypeError,
461 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000462 return -1;
463 }
464
465 if ( slice_len )
466 memcpy((char *)self->b_ptr + left, p, slice_len);
467
468 return 0;
469}
470
471/* Buffer methods */
472
473static int
Fred Drake79912472000-07-09 04:06:11 +0000474buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000475{
476 if ( idx != 0 ) {
477 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000478 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000479 return -1;
480 }
481 *pp = self->b_ptr;
482 return self->b_size;
483}
484
485static int
Fred Drake79912472000-07-09 04:06:11 +0000486buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000487{
488 if ( self->b_readonly )
489 {
490 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
491 return -1;
492 }
493 return buffer_getreadbuf(self, idx, pp);
494}
495
496static int
Fred Drake79912472000-07-09 04:06:11 +0000497buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000498{
499 if ( lenp )
500 *lenp = self->b_size;
501 return 1;
502}
503
Guido van Rossum1db70701998-10-08 02:18:52 +0000504static int
Fred Drake79912472000-07-09 04:06:11 +0000505buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000506{
507 if ( idx != 0 ) {
508 PyErr_SetString(PyExc_SystemError,
509 "accessing non-existent buffer segment");
510 return -1;
511 }
512 *pp = (const char *)self->b_ptr;
513 return self->b_size;
514}
515
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000516
517static 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*/
525};
526
527static PyBufferProcs buffer_as_buffer = {
528 (getreadbufferproc)buffer_getreadbuf,
529 (getwritebufferproc)buffer_getwritebuf,
530 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000531 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000532};
533
534PyTypeObject PyBuffer_Type = {
535 PyObject_HEAD_INIT(&PyType_Type)
536 0,
537 "buffer",
538 sizeof(PyBufferObject),
539 0,
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*/
Guido van Rossum1db70701998-10-08 02:18:52 +0000555 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000556 0, /*tp_doc*/
557};