blob: eff06aa033d11bf4bd27f473c8706e2cd126917c [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;
Martin v. Löwis18e16552006-02-15 17:27:45 +000011 Py_ssize_t b_size;
12 Py_ssize_t b_offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000013 int b_readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000014 long b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000015} PyBufferObject;
16
17
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000018static int
Martin v. Löwis18e16552006-02-15 17:27:45 +000019get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size)
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000020{
21 if (self->b_base == NULL) {
22 assert (ptr != NULL);
23 *ptr = self->b_ptr;
24 *size = self->b_size;
25 }
26 else {
Martin v. Löwis18e16552006-02-15 17:27:45 +000027 Py_ssize_t count, offset;
28 readbufferproc proc;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000029 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
30 if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
31 PyErr_SetString(PyExc_TypeError,
32 "single-segment buffer object expected");
33 return 0;
34 }
35 if (self->b_readonly)
36 proc = bp->bf_getreadbuffer;
37 else
Martin v. Löwis18e16552006-02-15 17:27:45 +000038 proc = (readbufferproc)bp->bf_getwritebuffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000039 if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
40 return 0;
41 /* apply constraints to the start/end */
42 if (self->b_offset > count)
43 offset = count;
44 else
45 offset = self->b_offset;
Martin v. Löwis093c1002004-03-25 16:16:28 +000046 *(char **)ptr = *(char **)ptr + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000047 if (self->b_size == Py_END_OF_BUFFER)
48 *size = count;
49 else
50 *size = self->b_size;
51 if (offset + *size > count)
52 *size = count - offset;
53 }
54 return 1;
55}
56
57
Guido van Rossum2e19bd71998-10-07 14:36:10 +000058static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000059buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000060 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000061{
62 PyBufferObject * b;
63
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000064 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +000065 PyErr_SetString(PyExc_ValueError,
66 "size must be zero or positive");
67 return NULL;
68 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +000069 if (offset < 0) {
70 PyErr_SetString(PyExc_ValueError,
71 "offset must be zero or positive");
72 return NULL;
73 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +000074
Guido van Rossum2e19bd71998-10-07 14:36:10 +000075 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
76 if ( b == NULL )
77 return NULL;
78
79 Py_XINCREF(base);
80 b->b_base = base;
81 b->b_ptr = ptr;
82 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000083 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000084 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000085 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000086
87 return (PyObject *) b;
88}
89
90static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000091buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000092{
Neil Schemenauer927a57f2004-09-24 19:17:26 +000093 if (offset < 0) {
94 PyErr_SetString(PyExc_ValueError,
95 "offset must be zero or positive");
96 return NULL;
97 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000098 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +000099 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000100 PyBufferObject *b = (PyBufferObject *)base;
101 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000102 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000103 if (base_size < 0)
104 base_size = 0;
105 if (size == Py_END_OF_BUFFER || size > base_size)
106 size = base_size;
107 }
108 offset += b->b_offset;
109 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000110 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000111 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000112}
113
114
115PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000116PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000117{
118 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
119
120 if ( pb == NULL ||
121 pb->bf_getreadbuffer == NULL ||
122 pb->bf_getsegcount == NULL )
123 {
124 PyErr_SetString(PyExc_TypeError, "buffer object expected");
125 return NULL;
126 }
127
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000128 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000129}
130
131PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000132PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000133{
134 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
135
136 if ( pb == NULL ||
137 pb->bf_getwritebuffer == NULL ||
138 pb->bf_getsegcount == NULL )
139 {
140 PyErr_SetString(PyExc_TypeError, "buffer object expected");
141 return NULL;
142 }
143
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000144 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000145}
146
147PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000148PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000149{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000150 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000151}
152
153PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000154PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000155{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000156 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000157}
158
159PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000160PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000161{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000162 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000163 PyBufferObject * b;
164
Fred Drake4574f231999-08-04 13:08:19 +0000165 if (size < 0) {
166 PyErr_SetString(PyExc_ValueError,
167 "size must be zero or positive");
168 return NULL;
169 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000170 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000171 /* Inline PyObject_New */
Moshe Zadkacf703f02000-08-04 15:36:13 +0000172 o = PyObject_MALLOC(sizeof(*b) + size);
173 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000174 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000175 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000176
177 b->b_base = NULL;
178 b->b_ptr = (void *)(b + 1);
179 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000180 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000181 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000182 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000183
Moshe Zadkacf703f02000-08-04 15:36:13 +0000184 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000185}
186
187/* Methods */
188
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000189static PyObject *
190buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
191{
192 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000193 Py_ssize_t offset = 0;
194 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000195
Georg Brandl02c42872005-08-26 06:42:30 +0000196 if (!_PyArg_NoKeywords("buffer()", kw))
197 return NULL;
198
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000199 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000200 return NULL;
201 return PyBuffer_FromObject(ob, offset, size);
202}
203
204PyDoc_STRVAR(buffer_doc,
205"buffer(object [, offset[, size]])\n\
206\n\
207Create a new buffer object which references the given object.\n\
208The buffer will reference a slice of the target object from the\n\
209start of the object (or at the specified offset). The slice will\n\
210extend to the end of the target object (or with the specified size).");
211
212
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000213static void
Fred Drake79912472000-07-09 04:06:11 +0000214buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000215{
216 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000217 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000218}
219
220static int
Fred Drake79912472000-07-09 04:06:11 +0000221buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000222{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000223 void *p1, *p2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000224 Py_ssize_t len_self, len_other, min_len;
225 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000226
227 if (!get_buf(self, &p1, &len_self))
228 return -1;
229 if (!get_buf(other, &p2, &len_other))
230 return -1;
231 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000232 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000233 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000234 if (cmp != 0)
235 return cmp;
236 }
237 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
238}
239
240static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000241buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000242{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000243 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000244
245 if ( self->b_base == NULL )
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000246 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000247 status,
248 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000249 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000250 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000251 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000252 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000253 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000254 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000255 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000256 self->b_size,
257 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000258 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000259}
260
261static long
Fred Drake79912472000-07-09 04:06:11 +0000262buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000263{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000264 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000265 Py_ssize_t size;
266 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000267 register unsigned char *p;
268 register long x;
269
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000270 if ( self->b_hash != -1 )
271 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000272
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000273 /* XXX potential bugs here, a readonly buffer does not imply that the
274 * underlying memory is immutable. b_readonly is a necessary but not
275 * sufficient condition for a buffer to be hashable. Perhaps it would
276 * be better to only allow hashing if the underlying object is known to
277 * be immutable (e.g. PyString_Check() is true). Another idea would
278 * be to call tp_hash on the underlying object and see if it raises
279 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000280 if ( !self->b_readonly )
281 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000282 PyErr_SetString(PyExc_TypeError,
283 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000284 return -1;
285 }
286
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000287 if (!get_buf(self, &ptr, &size))
288 return -1;
289 p = (unsigned char *) ptr;
290 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000291 x = *p << 7;
292 while (--len >= 0)
293 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000294 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000295 if (x == -1)
296 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000297 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000298 return x;
299}
300
301static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000302buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000303{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000304 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000305 Py_ssize_t size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000306 if (!get_buf(self, &ptr, &size))
307 return NULL;
308 return PyString_FromStringAndSize(ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000309}
310
311/* Sequence methods */
312
Martin v. Löwis18e16552006-02-15 17:27:45 +0000313static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000314buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000315{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000316 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000317 Py_ssize_t size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000318 if (!get_buf(self, &ptr, &size))
319 return -1;
320 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000321}
322
323static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000324buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000325{
326 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000327 void *ptr1, *ptr2;
328 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000329 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000330 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000331
332 if ( pb == NULL ||
333 pb->bf_getreadbuffer == NULL ||
334 pb->bf_getsegcount == NULL )
335 {
336 PyErr_BadArgument();
337 return NULL;
338 }
339 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
340 {
341 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000342 PyErr_SetString(PyExc_TypeError,
343 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000344 return NULL;
345 }
346
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000347 if (!get_buf(self, &ptr1, &size))
348 return NULL;
349
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000350 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000351 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000352 {
353 Py_INCREF(other);
354 return other;
355 }
356
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000357 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000358 return NULL;
359
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000360 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000361 if ( ob == NULL )
362 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000363 p = PyString_AS_STRING(ob);
364 memcpy(p, ptr1, size);
365 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000366
367 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000368 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000369
370 return ob;
371}
372
373static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000374buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000375{
376 PyObject *ob;
377 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000378 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000379 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000380
381 if ( count < 0 )
382 count = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000383 if (!get_buf(self, &ptr, &size))
384 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000385 ob = PyString_FromStringAndSize(NULL, size * count);
386 if ( ob == NULL )
387 return NULL;
388
389 p = PyString_AS_STRING(ob);
390 while ( count-- )
391 {
392 memcpy(p, ptr, size);
393 p += size;
394 }
395
396 /* there is an extra byte in the string object, so this is safe */
397 *p = '\0';
398
399 return ob;
400}
401
402static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000403buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000404{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000405 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000406 Py_ssize_t size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000407 if (!get_buf(self, &ptr, &size))
408 return NULL;
409 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000410 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
411 return NULL;
412 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000413 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000414}
415
416static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000417buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000418{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000419 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000420 Py_ssize_t size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000421 if (!get_buf(self, &ptr, &size))
422 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000423 if ( left < 0 )
424 left = 0;
425 if ( right < 0 )
426 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000427 if ( right > size )
428 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000429 if ( right < left )
430 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000431 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000432 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000433}
434
435static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000436buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000437{
438 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000439 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000440 Py_ssize_t size;
441 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000442
443 if ( self->b_readonly ) {
444 PyErr_SetString(PyExc_TypeError,
445 "buffer is read-only");
446 return -1;
447 }
448
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000449 if (!get_buf(self, &ptr1, &size))
450 return -1;
451
452 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000453 PyErr_SetString(PyExc_IndexError,
454 "buffer assignment index out of range");
455 return -1;
456 }
457
458 pb = other ? other->ob_type->tp_as_buffer : NULL;
459 if ( pb == NULL ||
460 pb->bf_getreadbuffer == NULL ||
461 pb->bf_getsegcount == NULL )
462 {
463 PyErr_BadArgument();
464 return -1;
465 }
466 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
467 {
468 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000469 PyErr_SetString(PyExc_TypeError,
470 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000471 return -1;
472 }
473
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000474 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000475 return -1;
476 if ( count != 1 ) {
477 PyErr_SetString(PyExc_TypeError,
478 "right operand must be a single byte");
479 return -1;
480 }
481
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000482 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000483 return 0;
484}
485
486static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000487buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000488{
489 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000490 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000491 Py_ssize_t size;
492 Py_ssize_t slice_len;
493 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000494
495 if ( self->b_readonly ) {
496 PyErr_SetString(PyExc_TypeError,
497 "buffer is read-only");
498 return -1;
499 }
500
501 pb = other ? other->ob_type->tp_as_buffer : NULL;
502 if ( pb == NULL ||
503 pb->bf_getreadbuffer == NULL ||
504 pb->bf_getsegcount == NULL )
505 {
506 PyErr_BadArgument();
507 return -1;
508 }
509 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
510 {
511 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000512 PyErr_SetString(PyExc_TypeError,
513 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000514 return -1;
515 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000516 if (!get_buf(self, &ptr1, &size))
517 return -1;
518 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000519 return -1;
520
521 if ( left < 0 )
522 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000523 else if ( left > size )
524 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000525 if ( right < left )
526 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000527 else if ( right > size )
528 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000529 slice_len = right - left;
530
531 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000532 PyErr_SetString(
533 PyExc_TypeError,
534 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000535 return -1;
536 }
537
538 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000539 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000540
541 return 0;
542}
543
544/* Buffer methods */
545
Martin v. Löwis18e16552006-02-15 17:27:45 +0000546static Py_ssize_t
547buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000548{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000549 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000550 if ( idx != 0 ) {
551 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000552 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000553 return -1;
554 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000555 if (!get_buf(self, pp, &size))
556 return -1;
557 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000558}
559
Martin v. Löwis18e16552006-02-15 17:27:45 +0000560static Py_ssize_t
561buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000562{
563 if ( self->b_readonly )
564 {
565 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
566 return -1;
567 }
568 return buffer_getreadbuf(self, idx, pp);
569}
570
Martin v. Löwis18e16552006-02-15 17:27:45 +0000571static Py_ssize_t
572buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000573{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000574 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000575 Py_ssize_t size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000576 if (!get_buf(self, &ptr, &size))
577 return -1;
578 if (lenp)
579 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000580 return 1;
581}
582
Martin v. Löwis18e16552006-02-15 17:27:45 +0000583static Py_ssize_t
584buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000585{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000586 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000587 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000588 if ( idx != 0 ) {
589 PyErr_SetString(PyExc_SystemError,
590 "accessing non-existent buffer segment");
591 return -1;
592 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000593 if (!get_buf(self, &ptr, &size))
594 return -1;
595 *pp = (const char *)ptr;
596 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000597}
598
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000599
600static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000601 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000602 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000603 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
604 (ssizeargfunc)buffer_item, /*sq_item*/
605 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
606 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
607 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000608};
609
610static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000611 (readbufferproc)buffer_getreadbuf,
612 (writebufferproc)buffer_getwritebuf,
613 (segcountproc)buffer_getsegcount,
614 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000615};
616
617PyTypeObject PyBuffer_Type = {
618 PyObject_HEAD_INIT(&PyType_Type)
619 0,
620 "buffer",
621 sizeof(PyBufferObject),
622 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000623 (destructor)buffer_dealloc, /* tp_dealloc */
624 0, /* tp_print */
625 0, /* tp_getattr */
626 0, /* tp_setattr */
627 (cmpfunc)buffer_compare, /* tp_compare */
628 (reprfunc)buffer_repr, /* tp_repr */
629 0, /* tp_as_number */
630 &buffer_as_sequence, /* tp_as_sequence */
631 0, /* tp_as_mapping */
632 (hashfunc)buffer_hash, /* tp_hash */
633 0, /* tp_call */
634 (reprfunc)buffer_str, /* tp_str */
635 PyObject_GenericGetAttr, /* tp_getattro */
636 0, /* tp_setattro */
637 &buffer_as_buffer, /* tp_as_buffer */
638 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000639 buffer_doc, /* tp_doc */
640 0, /* tp_traverse */
641 0, /* tp_clear */
642 0, /* tp_richcompare */
643 0, /* tp_weaklistoffset */
644 0, /* tp_iter */
645 0, /* tp_iternext */
646 0, /* tp_methods */
647 0, /* tp_members */
648 0, /* tp_getset */
649 0, /* tp_base */
650 0, /* tp_dict */
651 0, /* tp_descr_get */
652 0, /* tp_descr_set */
653 0, /* tp_dictoffset */
654 0, /* tp_init */
655 0, /* tp_alloc */
656 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000657};