blob: c0e3c80da49b368dbaaf2e984cb9415f27ae2826 [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 Rossume3a8e7e2002-08-19 19:26:42 +0000141 /* Inline PyObject_New */
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
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000158static PyObject *
159buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
160{
161 PyObject *ob;
162 int offset = 0;
163 int size = Py_END_OF_BUFFER;
164
165 if ( !PyArg_ParseTuple(args, "O|ii:buffer", &ob, &offset, &size) )
166 return NULL;
167 return PyBuffer_FromObject(ob, offset, size);
168}
169
170PyDoc_STRVAR(buffer_doc,
171"buffer(object [, offset[, size]])\n\
172\n\
173Create a new buffer object which references the given object.\n\
174The buffer will reference a slice of the target object from the\n\
175start of the object (or at the specified offset). The slice will\n\
176extend to the end of the target object (or with the specified size).");
177
178
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000179static void
Fred Drake79912472000-07-09 04:06:11 +0000180buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000181{
182 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000183 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000184}
185
186static int
Fred Drake79912472000-07-09 04:06:11 +0000187buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000188{
189 int len_self = self->b_size;
190 int len_other = other->b_size;
191 int min_len = (len_self < len_other) ? len_self : len_other;
192 int cmp;
193 if (min_len > 0) {
194 cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
195 if (cmp != 0)
196 return cmp;
197 }
198 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
199}
200
201static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000202buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203{
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000204 char *status = self->b_readonly ? "read-only" : "read-write";
205
206 if ( self->b_base == NULL )
Barry Warsaw7ce36942001-08-24 18:34:26 +0000207 return PyString_FromFormat("<%s buffer ptr %p, size %d at %p>",
208 status,
209 self->b_ptr,
210 self->b_size,
211 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000212 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000213 return PyString_FromFormat(
214 "<%s buffer for %p, ptr %p, size %d at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000215 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000216 self->b_base,
217 self->b_ptr,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000218 self->b_size,
Fred Drakea44d3532000-06-30 15:01:00 +0000219 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000220}
221
222static long
Fred Drake79912472000-07-09 04:06:11 +0000223buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000224{
225 register int len;
226 register unsigned char *p;
227 register long x;
228
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000229 if ( self->b_hash != -1 )
230 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000231
232 if ( !self->b_readonly )
233 {
234 /* ### use different wording, since this is conditional? */
235 PyErr_SetString(PyExc_TypeError, "unhashable type");
236 return -1;
237 }
238
239 len = self->b_size;
240 p = (unsigned char *) self->b_ptr;
241 x = *p << 7;
242 while (--len >= 0)
243 x = (1000003*x) ^ *p++;
244 x ^= self->b_size;
245 if (x == -1)
246 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000247 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000248 return x;
249}
250
251static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000252buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000253{
254 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
255}
256
257/* Sequence methods */
258
259static int
Fred Drake79912472000-07-09 04:06:11 +0000260buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000261{
262 return self->b_size;
263}
264
265static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000266buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000267{
268 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
269 char *p1;
270 void *p2;
271 PyObject *ob;
272 int count;
273
274 if ( pb == NULL ||
275 pb->bf_getreadbuffer == NULL ||
276 pb->bf_getsegcount == NULL )
277 {
278 PyErr_BadArgument();
279 return NULL;
280 }
281 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
282 {
283 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000284 PyErr_SetString(PyExc_TypeError,
285 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000286 return NULL;
287 }
288
289 /* optimize special case */
290 if ( self->b_size == 0 )
291 {
292 Py_INCREF(other);
293 return other;
294 }
295
296 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
297 return NULL;
298
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000299 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;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000357 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 */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000550 buffer_doc, /* tp_doc */
551 0, /* tp_traverse */
552 0, /* tp_clear */
553 0, /* tp_richcompare */
554 0, /* tp_weaklistoffset */
555 0, /* tp_iter */
556 0, /* tp_iternext */
557 0, /* tp_methods */
558 0, /* tp_members */
559 0, /* tp_getset */
560 0, /* tp_base */
561 0, /* tp_dict */
562 0, /* tp_descr_get */
563 0, /* tp_descr_set */
564 0, /* tp_dictoffset */
565 0, /* tp_init */
566 0, /* tp_alloc */
567 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000568};