blob: 242261f7187634366a47381b498dc5e14dda8da4 [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{
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000187 char *status = self->b_readonly ? "read-only" : "read-write";
188
189 if ( self->b_base == NULL )
Barry Warsaw7ce36942001-08-24 18:34:26 +0000190 return PyString_FromFormat("<%s buffer ptr %p, size %d at %p>",
191 status,
192 self->b_ptr,
193 self->b_size,
194 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000196 return PyString_FromFormat(
197 "<%s buffer for %p, ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000198 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000199 self->b_base,
200 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000201 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000202 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203}
204
205static long
Fred Drake79912472000-07-09 04:06:11 +0000206buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000207{
208 register int len;
209 register unsigned char *p;
210 register long x;
211
212#ifdef CACHE_HASH
213 if ( self->b_hash != -1 )
214 return self->b_hash;
215#endif
216
217 if ( !self->b_readonly )
218 {
219 /* ### use different wording, since this is conditional? */
220 PyErr_SetString(PyExc_TypeError, "unhashable type");
221 return -1;
222 }
223
224 len = self->b_size;
225 p = (unsigned char *) self->b_ptr;
226 x = *p << 7;
227 while (--len >= 0)
228 x = (1000003*x) ^ *p++;
229 x ^= self->b_size;
230 if (x == -1)
231 x = -2;
232#ifdef CACHE_HASH
233 self->b_hash = x;
234#endif
235 return x;
236}
237
238static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000239buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000240{
241 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
242}
243
244/* Sequence methods */
245
246static int
Fred Drake79912472000-07-09 04:06:11 +0000247buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000248{
249 return self->b_size;
250}
251
252static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000253buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000254{
255 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
256 char *p1;
257 void *p2;
258 PyObject *ob;
259 int count;
260
261 if ( pb == NULL ||
262 pb->bf_getreadbuffer == NULL ||
263 pb->bf_getsegcount == NULL )
264 {
265 PyErr_BadArgument();
266 return NULL;
267 }
268 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
269 {
270 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000271 PyErr_SetString(PyExc_TypeError,
272 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000273 return NULL;
274 }
275
276 /* optimize special case */
277 if ( self->b_size == 0 )
278 {
279 Py_INCREF(other);
280 return other;
281 }
282
283 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
284 return NULL;
285
286 /* optimize special case */
287 if ( count == 0 )
288 {
289 Py_INCREF(self);
290 return (PyObject *)self;
291 }
292
293 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
294 p1 = PyString_AS_STRING(ob);
295 memcpy(p1, self->b_ptr, self->b_size);
296 memcpy(p1 + self->b_size, p2, count);
297
298 /* there is an extra byte in the string object, so this is safe */
299 p1[self->b_size + count] = '\0';
300
301 return ob;
302}
303
304static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000305buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000306{
307 PyObject *ob;
308 register char *p;
309 void *ptr = self->b_ptr;
310 int size = self->b_size;
311
312 if ( count < 0 )
313 count = 0;
314 ob = PyString_FromStringAndSize(NULL, size * count);
315 if ( ob == NULL )
316 return NULL;
317
318 p = PyString_AS_STRING(ob);
319 while ( count-- )
320 {
321 memcpy(p, ptr, size);
322 p += size;
323 }
324
325 /* there is an extra byte in the string object, so this is safe */
326 *p = '\0';
327
328 return ob;
329}
330
331static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000332buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000333{
334 if ( idx < 0 || idx >= self->b_size )
335 {
336 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
337 return NULL;
338 }
339 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
340}
341
342static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000343buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000344{
345 if ( left < 0 )
346 left = 0;
347 if ( right < 0 )
348 right = 0;
349 if ( right > self->b_size )
350 right = self->b_size;
351 if ( left == 0 && right == self->b_size )
352 {
353 /* same as self */
354 Py_INCREF(self);
355 return (PyObject *)self;
356 }
357 if ( right < left )
358 right = left;
Guido van Rossumcd037e71999-03-24 19:05:31 +0000359 return PyString_FromStringAndSize((char *)self->b_ptr + left,
360 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000361}
362
363static int
Fred Drake79912472000-07-09 04:06:11 +0000364buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000365{
366 PyBufferProcs *pb;
367 void *p;
368 int count;
369
370 if ( self->b_readonly ) {
371 PyErr_SetString(PyExc_TypeError,
372 "buffer is read-only");
373 return -1;
374 }
375
376 if (idx < 0 || idx >= self->b_size) {
377 PyErr_SetString(PyExc_IndexError,
378 "buffer assignment index out of range");
379 return -1;
380 }
381
382 pb = other ? other->ob_type->tp_as_buffer : NULL;
383 if ( pb == NULL ||
384 pb->bf_getreadbuffer == NULL ||
385 pb->bf_getsegcount == NULL )
386 {
387 PyErr_BadArgument();
388 return -1;
389 }
390 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
391 {
392 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000393 PyErr_SetString(PyExc_TypeError,
394 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000395 return -1;
396 }
397
398 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
399 return -1;
400 if ( count != 1 ) {
401 PyErr_SetString(PyExc_TypeError,
402 "right operand must be a single byte");
403 return -1;
404 }
405
406 ((char *)self->b_ptr)[idx] = *(char *)p;
407 return 0;
408}
409
410static int
Fred Drake79912472000-07-09 04:06:11 +0000411buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000412{
413 PyBufferProcs *pb;
414 void *p;
415 int slice_len;
416 int count;
417
418 if ( self->b_readonly ) {
419 PyErr_SetString(PyExc_TypeError,
420 "buffer is read-only");
421 return -1;
422 }
423
424 pb = other ? other->ob_type->tp_as_buffer : NULL;
425 if ( pb == NULL ||
426 pb->bf_getreadbuffer == NULL ||
427 pb->bf_getsegcount == NULL )
428 {
429 PyErr_BadArgument();
430 return -1;
431 }
432 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
433 {
434 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000435 PyErr_SetString(PyExc_TypeError,
436 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000437 return -1;
438 }
439 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
440 return -1;
441
442 if ( left < 0 )
443 left = 0;
444 else if ( left > self->b_size )
445 left = self->b_size;
446 if ( right < left )
447 right = left;
448 else if ( right > self->b_size )
449 right = self->b_size;
450 slice_len = right - left;
451
452 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000453 PyErr_SetString(
454 PyExc_TypeError,
455 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000456 return -1;
457 }
458
459 if ( slice_len )
460 memcpy((char *)self->b_ptr + left, p, slice_len);
461
462 return 0;
463}
464
465/* Buffer methods */
466
467static int
Fred Drake79912472000-07-09 04:06:11 +0000468buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000469{
470 if ( idx != 0 ) {
471 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000472 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000473 return -1;
474 }
475 *pp = self->b_ptr;
476 return self->b_size;
477}
478
479static int
Fred Drake79912472000-07-09 04:06:11 +0000480buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000481{
482 if ( self->b_readonly )
483 {
484 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
485 return -1;
486 }
487 return buffer_getreadbuf(self, idx, pp);
488}
489
490static int
Fred Drake79912472000-07-09 04:06:11 +0000491buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000492{
493 if ( lenp )
494 *lenp = self->b_size;
495 return 1;
496}
497
Guido van Rossum1db70701998-10-08 02:18:52 +0000498static int
Fred Drake79912472000-07-09 04:06:11 +0000499buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000500{
501 if ( idx != 0 ) {
502 PyErr_SetString(PyExc_SystemError,
503 "accessing non-existent buffer segment");
504 return -1;
505 }
506 *pp = (const char *)self->b_ptr;
507 return self->b_size;
508}
509
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000510
511static PySequenceMethods buffer_as_sequence = {
512 (inquiry)buffer_length, /*sq_length*/
513 (binaryfunc)buffer_concat, /*sq_concat*/
514 (intargfunc)buffer_repeat, /*sq_repeat*/
515 (intargfunc)buffer_item, /*sq_item*/
516 (intintargfunc)buffer_slice, /*sq_slice*/
517 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
518 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
519};
520
521static PyBufferProcs buffer_as_buffer = {
522 (getreadbufferproc)buffer_getreadbuf,
523 (getwritebufferproc)buffer_getwritebuf,
524 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000525 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000526};
527
528PyTypeObject PyBuffer_Type = {
529 PyObject_HEAD_INIT(&PyType_Type)
530 0,
531 "buffer",
532 sizeof(PyBufferObject),
533 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000534 (destructor)buffer_dealloc, /* tp_dealloc */
535 0, /* tp_print */
536 0, /* tp_getattr */
537 0, /* tp_setattr */
538 (cmpfunc)buffer_compare, /* tp_compare */
539 (reprfunc)buffer_repr, /* tp_repr */
540 0, /* tp_as_number */
541 &buffer_as_sequence, /* tp_as_sequence */
542 0, /* tp_as_mapping */
543 (hashfunc)buffer_hash, /* tp_hash */
544 0, /* tp_call */
545 (reprfunc)buffer_str, /* tp_str */
546 PyObject_GenericGetAttr, /* tp_getattro */
547 0, /* tp_setattro */
548 &buffer_as_buffer, /* tp_as_buffer */
549 Py_TPFLAGS_DEFAULT, /* tp_flags */
550 0, /* tp_doc */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000551};