blob: 51b9ef9b14315dd6f4bc6e5517cfc5b5532c03ac [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;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000013 long b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000014} PyBufferObject;
15
16
17static PyObject *
Fred Drake79912472000-07-09 04:06:11 +000018_PyBuffer_FromMemory(PyObject *base, void *ptr, int size, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000019{
20 PyBufferObject * b;
21
Guido van Rossum49ded3e1999-03-19 19:04:25 +000022 if ( size < 0 ) {
23 PyErr_SetString(PyExc_ValueError,
24 "size must be zero or positive");
25 return NULL;
26 }
27
Guido van Rossum2e19bd71998-10-07 14:36:10 +000028 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
29 if ( b == NULL )
30 return NULL;
31
32 Py_XINCREF(base);
33 b->b_base = base;
34 b->b_ptr = ptr;
35 b->b_size = size;
36 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000037 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000038
39 return (PyObject *) b;
40}
41
42static PyObject *
Fred Drake79912472000-07-09 04:06:11 +000043_PyBuffer_FromObject(PyObject *base, int offset, int size,
44 getreadbufferproc proc, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000045{
46 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
47 void *p;
48 int count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000049
Guido van Rossum49ded3e1999-03-19 19:04:25 +000050 if ( offset < 0 ) {
51 PyErr_SetString(PyExc_ValueError,
52 "offset must be zero or positive");
53 return NULL;
54 }
55
Guido van Rossum2e19bd71998-10-07 14:36:10 +000056 if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
57 {
Guido van Rossumcd037e71999-03-24 19:05:31 +000058 PyErr_SetString(PyExc_TypeError,
59 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +000060 return NULL;
61 }
62 if ( (count = (*proc)(base, 0, &p)) < 0 )
63 return NULL;
64
65 /* apply constraints to the start/end */
Guido van Rossum49ded3e1999-03-19 19:04:25 +000066 if ( size == Py_END_OF_BUFFER || size < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +000067 size = count;
68 if ( offset > count )
69 offset = count;
70 if ( offset + size > count )
71 size = count - offset;
Thomas Hellerfdc1bd32001-10-19 13:49:35 +000072
73 /* if the base object is another buffer, then "deref" it,
74 * except if the base of the other buffer is NULL
75 */
76 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) )
Guido van Rossum2e19bd71998-10-07 14:36:10 +000077 base = ((PyBufferObject *)base)->b_base;
Thomas Hellerfdc1bd32001-10-19 13:49:35 +000078
Guido van Rossum2e19bd71998-10-07 14:36:10 +000079 return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
80}
81
82
83PyObject *
Fred Drake79912472000-07-09 04:06:11 +000084PyBuffer_FromObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000085{
86 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
87
88 if ( pb == NULL ||
89 pb->bf_getreadbuffer == NULL ||
90 pb->bf_getsegcount == NULL )
91 {
92 PyErr_SetString(PyExc_TypeError, "buffer object expected");
93 return NULL;
94 }
95
Guido van Rossumcd037e71999-03-24 19:05:31 +000096 return _PyBuffer_FromObject(base, offset, size,
97 pb->bf_getreadbuffer, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098}
99
100PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000101PyBuffer_FromReadWriteObject(PyObject *base, int offset, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000102{
103 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
104
105 if ( pb == NULL ||
106 pb->bf_getwritebuffer == NULL ||
107 pb->bf_getsegcount == NULL )
108 {
109 PyErr_SetString(PyExc_TypeError, "buffer object expected");
110 return NULL;
111 }
112
Guido van Rossumcd037e71999-03-24 19:05:31 +0000113 return _PyBuffer_FromObject(base, offset, size,
114 (getreadbufferproc)pb->bf_getwritebuffer,
115 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000116}
117
118PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000119PyBuffer_FromMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000120{
121 return _PyBuffer_FromMemory(NULL, ptr, size, 1);
122}
123
124PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000125PyBuffer_FromReadWriteMemory(void *ptr, int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000126{
127 return _PyBuffer_FromMemory(NULL, ptr, size, 0);
128}
129
130PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000131PyBuffer_New(int size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000132{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000133 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000134 PyBufferObject * b;
135
Fred Drake4574f231999-08-04 13:08:19 +0000136 if (size < 0) {
137 PyErr_SetString(PyExc_ValueError,
138 "size must be zero or positive");
139 return NULL;
140 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000141 /* PyObject_New is inlined */
Moshe Zadkacf703f02000-08-04 15:36:13 +0000142 o = PyObject_MALLOC(sizeof(*b) + size);
143 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000144 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000145 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000146
147 b->b_base = NULL;
148 b->b_ptr = (void *)(b + 1);
149 b->b_size = size;
150 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000151 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000152
Moshe Zadkacf703f02000-08-04 15:36:13 +0000153 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000154}
155
156/* Methods */
157
158static void
Fred Drake79912472000-07-09 04:06:11 +0000159buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000160{
161 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000162 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000163}
164
165static int
Fred Drake79912472000-07-09 04:06:11 +0000166buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000167{
168 int len_self = self->b_size;
169 int len_other = other->b_size;
170 int min_len = (len_self < len_other) ? len_self : len_other;
171 int cmp;
172 if (min_len > 0) {
173 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
174 if (cmp != 0)
175 return cmp;
176 }
177 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
178}
179
180static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000181buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000182{
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000183 char *status = self->b_readonly ? "read-only" : "read-write";
184
185 if ( self->b_base == NULL )
Barry Warsaw7ce36942001-08-24 18:34:26 +0000186 return PyString_FromFormat("<%s buffer ptr %p, size %d at %p>",
187 status,
188 self->b_ptr,
189 self->b_size,
190 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000191 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000192 return PyString_FromFormat(
193 "<%s buffer for %p, ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000194 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000195 self->b_base,
196 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000198 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000199}
200
201static long
Fred Drake79912472000-07-09 04:06:11 +0000202buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203{
204 register int len;
205 register unsigned char *p;
206 register long x;
207
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000208 if ( self->b_hash != -1 )
209 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000210
211 if ( !self->b_readonly )
212 {
213 /* ### use different wording, since this is conditional? */
214 PyErr_SetString(PyExc_TypeError, "unhashable type");
215 return -1;
216 }
217
218 len = self->b_size;
219 p = (unsigned char *) self->b_ptr;
220 x = *p << 7;
221 while (--len >= 0)
222 x = (1000003*x) ^ *p++;
223 x ^= self->b_size;
224 if (x == -1)
225 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000226 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000227 return x;
228}
229
230static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000231buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000232{
233 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
234}
235
236/* Sequence methods */
237
238static int
Fred Drake79912472000-07-09 04:06:11 +0000239buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000240{
241 return self->b_size;
242}
243
244static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000245buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000246{
247 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
248 char *p1;
249 void *p2;
250 PyObject *ob;
251 int count;
252
253 if ( pb == NULL ||
254 pb->bf_getreadbuffer == NULL ||
255 pb->bf_getsegcount == NULL )
256 {
257 PyErr_BadArgument();
258 return NULL;
259 }
260 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
261 {
262 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000263 PyErr_SetString(PyExc_TypeError,
264 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000265 return NULL;
266 }
267
268 /* optimize special case */
269 if ( self->b_size == 0 )
270 {
271 Py_INCREF(other);
272 return other;
273 }
274
275 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
276 return NULL;
277
278 /* optimize special case */
279 if ( count == 0 )
280 {
281 Py_INCREF(self);
282 return (PyObject *)self;
283 }
284
285 ob = PyString_FromStringAndSize(NULL, self->b_size + count);
286 p1 = PyString_AS_STRING(ob);
287 memcpy(p1, self->b_ptr, self->b_size);
288 memcpy(p1 + self->b_size, p2, count);
289
290 /* there is an extra byte in the string object, so this is safe */
291 p1[self->b_size + count] = '\0';
292
293 return ob;
294}
295
296static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000297buffer_repeat(PyBufferObject *self, int count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000298{
299 PyObject *ob;
300 register char *p;
301 void *ptr = self->b_ptr;
302 int size = self->b_size;
303
304 if ( count < 0 )
305 count = 0;
306 ob = PyString_FromStringAndSize(NULL, size * count);
307 if ( ob == NULL )
308 return NULL;
309
310 p = PyString_AS_STRING(ob);
311 while ( count-- )
312 {
313 memcpy(p, ptr, size);
314 p += size;
315 }
316
317 /* there is an extra byte in the string object, so this is safe */
318 *p = '\0';
319
320 return ob;
321}
322
323static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000324buffer_item(PyBufferObject *self, int idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000325{
326 if ( idx < 0 || idx >= self->b_size )
327 {
328 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
329 return NULL;
330 }
331 return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
332}
333
334static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000335buffer_slice(PyBufferObject *self, int left, int right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000336{
337 if ( left < 0 )
338 left = 0;
339 if ( right < 0 )
340 right = 0;
341 if ( right > self->b_size )
342 right = self->b_size;
343 if ( left == 0 && right == self->b_size )
344 {
345 /* same as self */
346 Py_INCREF(self);
347 return (PyObject *)self;
348 }
349 if ( right < left )
350 right = left;
Guido van Rossumcd037e71999-03-24 19:05:31 +0000351 return PyString_FromStringAndSize((char *)self->b_ptr + left,
352 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000353}
354
355static int
Fred Drake79912472000-07-09 04:06:11 +0000356buffer_ass_item(PyBufferObject *self, int idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000357{
358 PyBufferProcs *pb;
359 void *p;
360 int count;
361
362 if ( self->b_readonly ) {
363 PyErr_SetString(PyExc_TypeError,
364 "buffer is read-only");
365 return -1;
366 }
367
368 if (idx < 0 || idx >= self->b_size) {
369 PyErr_SetString(PyExc_IndexError,
370 "buffer assignment index out of range");
371 return -1;
372 }
373
374 pb = other ? other->ob_type->tp_as_buffer : NULL;
375 if ( pb == NULL ||
376 pb->bf_getreadbuffer == NULL ||
377 pb->bf_getsegcount == NULL )
378 {
379 PyErr_BadArgument();
380 return -1;
381 }
382 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
383 {
384 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000385 PyErr_SetString(PyExc_TypeError,
386 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000387 return -1;
388 }
389
390 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
391 return -1;
392 if ( count != 1 ) {
393 PyErr_SetString(PyExc_TypeError,
394 "right operand must be a single byte");
395 return -1;
396 }
397
398 ((char *)self->b_ptr)[idx] = *(char *)p;
399 return 0;
400}
401
402static int
Fred Drake79912472000-07-09 04:06:11 +0000403buffer_ass_slice(PyBufferObject *self, int left, int right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000404{
405 PyBufferProcs *pb;
406 void *p;
407 int slice_len;
408 int count;
409
410 if ( self->b_readonly ) {
411 PyErr_SetString(PyExc_TypeError,
412 "buffer is read-only");
413 return -1;
414 }
415
416 pb = other ? other->ob_type->tp_as_buffer : NULL;
417 if ( pb == NULL ||
418 pb->bf_getreadbuffer == NULL ||
419 pb->bf_getsegcount == NULL )
420 {
421 PyErr_BadArgument();
422 return -1;
423 }
424 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
425 {
426 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000427 PyErr_SetString(PyExc_TypeError,
428 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000429 return -1;
430 }
431 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
432 return -1;
433
434 if ( left < 0 )
435 left = 0;
436 else if ( left > self->b_size )
437 left = self->b_size;
438 if ( right < left )
439 right = left;
440 else if ( right > self->b_size )
441 right = self->b_size;
442 slice_len = right - left;
443
444 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000445 PyErr_SetString(
446 PyExc_TypeError,
447 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000448 return -1;
449 }
450
451 if ( slice_len )
452 memcpy((char *)self->b_ptr + left, p, slice_len);
453
454 return 0;
455}
456
457/* Buffer methods */
458
459static int
Fred Drake79912472000-07-09 04:06:11 +0000460buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000461{
462 if ( idx != 0 ) {
463 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000464 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000465 return -1;
466 }
467 *pp = self->b_ptr;
468 return self->b_size;
469}
470
471static int
Fred Drake79912472000-07-09 04:06:11 +0000472buffer_getwritebuf(PyBufferObject *self, int idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000473{
474 if ( self->b_readonly )
475 {
476 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
477 return -1;
478 }
479 return buffer_getreadbuf(self, idx, pp);
480}
481
482static int
Fred Drake79912472000-07-09 04:06:11 +0000483buffer_getsegcount(PyBufferObject *self, int *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000484{
485 if ( lenp )
486 *lenp = self->b_size;
487 return 1;
488}
489
Guido van Rossum1db70701998-10-08 02:18:52 +0000490static int
Fred Drake79912472000-07-09 04:06:11 +0000491buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000492{
493 if ( idx != 0 ) {
494 PyErr_SetString(PyExc_SystemError,
495 "accessing non-existent buffer segment");
496 return -1;
497 }
498 *pp = (const char *)self->b_ptr;
499 return self->b_size;
500}
501
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000502
503static PySequenceMethods buffer_as_sequence = {
504 (inquiry)buffer_length, /*sq_length*/
505 (binaryfunc)buffer_concat, /*sq_concat*/
506 (intargfunc)buffer_repeat, /*sq_repeat*/
507 (intargfunc)buffer_item, /*sq_item*/
508 (intintargfunc)buffer_slice, /*sq_slice*/
509 (intobjargproc)buffer_ass_item, /*sq_ass_item*/
510 (intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
511};
512
513static PyBufferProcs buffer_as_buffer = {
514 (getreadbufferproc)buffer_getreadbuf,
515 (getwritebufferproc)buffer_getwritebuf,
516 (getsegcountproc)buffer_getsegcount,
Guido van Rossum1db70701998-10-08 02:18:52 +0000517 (getcharbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000518};
519
520PyTypeObject PyBuffer_Type = {
521 PyObject_HEAD_INIT(&PyType_Type)
522 0,
523 "buffer",
524 sizeof(PyBufferObject),
525 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000526 (destructor)buffer_dealloc, /* tp_dealloc */
527 0, /* tp_print */
528 0, /* tp_getattr */
529 0, /* tp_setattr */
530 (cmpfunc)buffer_compare, /* tp_compare */
531 (reprfunc)buffer_repr, /* tp_repr */
532 0, /* tp_as_number */
533 &buffer_as_sequence, /* tp_as_sequence */
534 0, /* tp_as_mapping */
535 (hashfunc)buffer_hash, /* tp_hash */
536 0, /* tp_call */
537 (reprfunc)buffer_str, /* tp_str */
538 PyObject_GenericGetAttr, /* tp_getattro */
539 0, /* tp_setattro */
540 &buffer_as_buffer, /* tp_as_buffer */
541 Py_TPFLAGS_DEFAULT, /* tp_flags */
542 0, /* tp_doc */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000543};