blob: ddef8685193971d932b2ac80c6c2ef3c388256e5 [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
Thomas Wouters0e3f5912006-08-11 14:57:12 +000018enum buffer_t {
19 READ_BUFFER,
20 WRITE_BUFFER,
21 CHAR_BUFFER,
22 ANY_BUFFER,
23};
24
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000025static int
Thomas Wouters0e3f5912006-08-11 14:57:12 +000026get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
27 enum buffer_t buffer_type)
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000028{
29 if (self->b_base == NULL) {
30 assert (ptr != NULL);
31 *ptr = self->b_ptr;
32 *size = self->b_size;
33 }
34 else {
Martin v. Löwis18e16552006-02-15 17:27:45 +000035 Py_ssize_t count, offset;
Thomas Wouters0e3f5912006-08-11 14:57:12 +000036 readbufferproc proc = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000037 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
38 if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
39 PyErr_SetString(PyExc_TypeError,
40 "single-segment buffer object expected");
41 return 0;
42 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +000043 if ((buffer_type == READ_BUFFER) ||
44 ((buffer_type == ANY_BUFFER) && self->b_readonly))
45 proc = bp->bf_getreadbuffer;
46 else if ((buffer_type == WRITE_BUFFER) ||
47 (buffer_type == ANY_BUFFER))
48 proc = (readbufferproc)bp->bf_getwritebuffer;
49 else if (buffer_type == CHAR_BUFFER) {
50 proc = (readbufferproc)bp->bf_getcharbuffer;
51 }
52 if (!proc) {
53 char *buffer_type_name;
54 switch (buffer_type) {
55 case READ_BUFFER:
56 buffer_type_name = "read";
57 break;
58 case WRITE_BUFFER:
59 buffer_type_name = "write";
60 break;
61 case CHAR_BUFFER:
62 buffer_type_name = "char";
63 break;
64 default:
65 buffer_type_name = "no";
66 break;
67 }
68 PyErr_Format(PyExc_TypeError,
69 "%s buffer type not available",
70 buffer_type_name);
71 return 0;
72 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000073 if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
74 return 0;
75 /* apply constraints to the start/end */
76 if (self->b_offset > count)
77 offset = count;
78 else
79 offset = self->b_offset;
Martin v. Löwis093c1002004-03-25 16:16:28 +000080 *(char **)ptr = *(char **)ptr + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000081 if (self->b_size == Py_END_OF_BUFFER)
82 *size = count;
83 else
84 *size = self->b_size;
85 if (offset + *size > count)
86 *size = count - offset;
87 }
88 return 1;
89}
90
91
Guido van Rossum2e19bd71998-10-07 14:36:10 +000092static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000093buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000094 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000095{
96 PyBufferObject * b;
97
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000098 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +000099 PyErr_SetString(PyExc_ValueError,
100 "size must be zero or positive");
101 return NULL;
102 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000103 if (offset < 0) {
104 PyErr_SetString(PyExc_ValueError,
105 "offset must be zero or positive");
106 return NULL;
107 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +0000108
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000109 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
110 if ( b == NULL )
111 return NULL;
112
113 Py_XINCREF(base);
114 b->b_base = base;
115 b->b_ptr = ptr;
116 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000117 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000118 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000119 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000120
121 return (PyObject *) b;
122}
123
124static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000125buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000126{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000127 if (offset < 0) {
128 PyErr_SetString(PyExc_ValueError,
129 "offset must be zero or positive");
130 return NULL;
131 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000132 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000133 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000134 PyBufferObject *b = (PyBufferObject *)base;
135 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000136 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000137 if (base_size < 0)
138 base_size = 0;
139 if (size == Py_END_OF_BUFFER || size > base_size)
140 size = base_size;
141 }
142 offset += b->b_offset;
143 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000144 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000145 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000146}
147
148
149PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000150PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000151{
152 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
153
154 if ( pb == NULL ||
155 pb->bf_getreadbuffer == NULL ||
156 pb->bf_getsegcount == NULL )
157 {
158 PyErr_SetString(PyExc_TypeError, "buffer object expected");
159 return NULL;
160 }
161
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000162 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000163}
164
165PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000166PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000167{
168 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
169
170 if ( pb == NULL ||
171 pb->bf_getwritebuffer == NULL ||
172 pb->bf_getsegcount == NULL )
173 {
174 PyErr_SetString(PyExc_TypeError, "buffer object expected");
175 return NULL;
176 }
177
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000178 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000179}
180
181PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000182PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000183{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000184 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000185}
186
187PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000188PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000189{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000190 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000191}
192
193PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000194PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000196 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197 PyBufferObject * b;
198
Fred Drake4574f231999-08-04 13:08:19 +0000199 if (size < 0) {
200 PyErr_SetString(PyExc_ValueError,
201 "size must be zero or positive");
202 return NULL;
203 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000204 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000205 /* Inline PyObject_New */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000206 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Moshe Zadkacf703f02000-08-04 15:36:13 +0000207 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000208 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000209 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000210
211 b->b_base = NULL;
212 b->b_ptr = (void *)(b + 1);
213 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000214 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000215 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000216 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000217
Moshe Zadkacf703f02000-08-04 15:36:13 +0000218 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000219}
220
221/* Methods */
222
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000223static PyObject *
224buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
225{
226 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000227 Py_ssize_t offset = 0;
228 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000229
Georg Brandl02c42872005-08-26 06:42:30 +0000230 if (!_PyArg_NoKeywords("buffer()", kw))
231 return NULL;
232
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000233 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000234 return NULL;
235 return PyBuffer_FromObject(ob, offset, size);
236}
237
238PyDoc_STRVAR(buffer_doc,
239"buffer(object [, offset[, size]])\n\
240\n\
241Create a new buffer object which references the given object.\n\
242The buffer will reference a slice of the target object from the\n\
243start of the object (or at the specified offset). The slice will\n\
244extend to the end of the target object (or with the specified size).");
245
246
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000247static void
Fred Drake79912472000-07-09 04:06:11 +0000248buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000249{
250 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000251 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000252}
253
254static int
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000255get_bufx(PyObject *obj, void **ptr, Py_ssize_t *size)
256{
257 PyBufferProcs *bp;
258
259 if (PyBuffer_Check(obj)) {
260 if (!get_buf((PyBufferObject *)obj, ptr, size, ANY_BUFFER)) {
261 PyErr_Clear();
262 return 0;
263 }
264 else
265 return 1;
266 }
267 bp = obj->ob_type->tp_as_buffer;
268 if (bp == NULL ||
269 bp->bf_getreadbuffer == NULL ||
270 bp->bf_getsegcount == NULL)
271 return 0;
272 if ((*bp->bf_getsegcount)(obj, NULL) != 1)
273 return 0;
274 *size = (*bp->bf_getreadbuffer)(obj, 0, ptr);
275 if (*size < 0) {
276 PyErr_Clear();
277 return 0;
278 }
279 return 1;
280}
281
282static PyObject *
283buffer_richcompare(PyObject *self, PyObject *other, int op)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000284{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000285 void *p1, *p2;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000286 Py_ssize_t len1, len2, min_len;
287 int cmp, ok;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000288
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000289 ok = 1;
290 if (!get_bufx(self, &p1, &len1))
291 ok = 0;
292 if (!get_bufx(other, &p2, &len2))
293 ok = 0;
294 if (!ok) {
295 /* If we can't get the buffers,
296 == and != are still defined
297 (and the objects are unequal) */
298 PyObject *result;
299 if (op == Py_EQ)
300 result = Py_False;
301 else if (op == Py_NE)
302 result = Py_True;
303 else
304 result = Py_NotImplemented;
305 Py_INCREF(result);
306 return result;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000307 }
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000308 min_len = (len1 < len2) ? len1 : len2;
309 cmp = memcmp(p1, p2, min_len);
310 if (cmp == 0)
311 cmp = (len1 < len2) ? -1 :
312 (len1 > len2) ? 1 : 0;
313 return Py_CmpToRich(op, cmp);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000314}
315
316static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000317buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000318{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000319 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000320
321 if ( self->b_base == NULL )
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000322 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000323 status,
324 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000325 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000326 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000327 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000328 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000329 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000330 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000331 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000332 self->b_size,
333 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000334 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000335}
336
337static long
Fred Drake79912472000-07-09 04:06:11 +0000338buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000339{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000340 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000341 Py_ssize_t size;
342 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000343 register unsigned char *p;
344 register long x;
345
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000346 if ( self->b_hash != -1 )
347 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000348
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000349 /* XXX potential bugs here, a readonly buffer does not imply that the
350 * underlying memory is immutable. b_readonly is a necessary but not
351 * sufficient condition for a buffer to be hashable. Perhaps it would
352 * be better to only allow hashing if the underlying object is known to
353 * be immutable (e.g. PyString_Check() is true). Another idea would
354 * be to call tp_hash on the underlying object and see if it raises
355 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000356 if ( !self->b_readonly )
357 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000358 PyErr_SetString(PyExc_TypeError,
359 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000360 return -1;
361 }
362
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000363 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000364 return -1;
365 p = (unsigned char *) ptr;
366 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000367 x = *p << 7;
368 while (--len >= 0)
369 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000370 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000371 if (x == -1)
372 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000373 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000374 return x;
375}
376
377static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000378buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000379{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000380 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000381 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000382 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000383 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000384 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000385}
386
387/* Sequence methods */
388
Martin v. Löwis18e16552006-02-15 17:27:45 +0000389static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000390buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000391{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000392 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000393 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000394 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000395 return -1;
396 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000397}
398
399static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000400buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000401{
402 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000403 void *ptr1, *ptr2;
404 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000405 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000406 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000407
408 if ( pb == NULL ||
409 pb->bf_getreadbuffer == NULL ||
410 pb->bf_getsegcount == NULL )
411 {
412 PyErr_BadArgument();
413 return NULL;
414 }
415 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
416 {
417 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000418 PyErr_SetString(PyExc_TypeError,
419 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000420 return NULL;
421 }
422
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000423 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000424 return NULL;
425
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000426 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000427 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000428 {
429 Py_INCREF(other);
430 return other;
431 }
432
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000433 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000434 return NULL;
435
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000436 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000437 if ( ob == NULL )
438 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000439 p = PyString_AS_STRING(ob);
440 memcpy(p, ptr1, size);
441 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000442
443 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000444 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000445
446 return ob;
447}
448
449static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000450buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000451{
452 PyObject *ob;
453 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000454 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000455 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000456
457 if ( count < 0 )
458 count = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000459 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000460 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000461 ob = PyString_FromStringAndSize(NULL, size * count);
462 if ( ob == NULL )
463 return NULL;
464
465 p = PyString_AS_STRING(ob);
466 while ( count-- )
467 {
468 memcpy(p, ptr, size);
469 p += size;
470 }
471
472 /* there is an extra byte in the string object, so this is safe */
473 *p = '\0';
474
475 return ob;
476}
477
478static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000479buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000480{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000481 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000482 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000483 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000484 return NULL;
485 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000486 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
487 return NULL;
488 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000489 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000490}
491
492static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000493buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000494{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000495 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000496 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000497 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000498 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000499 if ( left < 0 )
500 left = 0;
501 if ( right < 0 )
502 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000503 if ( right > size )
504 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000505 if ( right < left )
506 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000507 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000508 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000509}
510
511static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000512buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000513{
514 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000515 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000516 Py_ssize_t size;
517 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000518
519 if ( self->b_readonly ) {
520 PyErr_SetString(PyExc_TypeError,
521 "buffer is read-only");
522 return -1;
523 }
524
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000525 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000526 return -1;
527
528 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000529 PyErr_SetString(PyExc_IndexError,
530 "buffer assignment index out of range");
531 return -1;
532 }
533
534 pb = other ? other->ob_type->tp_as_buffer : NULL;
535 if ( pb == NULL ||
536 pb->bf_getreadbuffer == NULL ||
537 pb->bf_getsegcount == NULL )
538 {
539 PyErr_BadArgument();
540 return -1;
541 }
542 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
543 {
544 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000545 PyErr_SetString(PyExc_TypeError,
546 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000547 return -1;
548 }
549
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000550 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000551 return -1;
552 if ( count != 1 ) {
553 PyErr_SetString(PyExc_TypeError,
554 "right operand must be a single byte");
555 return -1;
556 }
557
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000558 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000559 return 0;
560}
561
562static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000563buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000564{
565 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000566 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000567 Py_ssize_t size;
568 Py_ssize_t slice_len;
569 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000570
571 if ( self->b_readonly ) {
572 PyErr_SetString(PyExc_TypeError,
573 "buffer is read-only");
574 return -1;
575 }
576
577 pb = other ? other->ob_type->tp_as_buffer : NULL;
578 if ( pb == NULL ||
579 pb->bf_getreadbuffer == NULL ||
580 pb->bf_getsegcount == NULL )
581 {
582 PyErr_BadArgument();
583 return -1;
584 }
585 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
586 {
587 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000588 PyErr_SetString(PyExc_TypeError,
589 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000590 return -1;
591 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000592 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000593 return -1;
594 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000595 return -1;
596
597 if ( left < 0 )
598 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000599 else if ( left > size )
600 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000601 if ( right < left )
602 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000603 else if ( right > size )
604 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000605 slice_len = right - left;
606
607 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000608 PyErr_SetString(
609 PyExc_TypeError,
610 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000611 return -1;
612 }
613
614 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000615 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000616
617 return 0;
618}
619
620/* Buffer methods */
621
Martin v. Löwis18e16552006-02-15 17:27:45 +0000622static Py_ssize_t
623buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000624{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000625 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000626 if ( idx != 0 ) {
627 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000628 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000629 return -1;
630 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000631 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000632 return -1;
633 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000634}
635
Martin v. Löwis18e16552006-02-15 17:27:45 +0000636static Py_ssize_t
637buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000638{
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000639 Py_ssize_t size;
640
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000641 if ( self->b_readonly )
642 {
643 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
644 return -1;
645 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000646
647 if ( idx != 0 ) {
648 PyErr_SetString(PyExc_SystemError,
649 "accessing non-existent buffer segment");
650 return -1;
651 }
652 if (!get_buf(self, pp, &size, WRITE_BUFFER))
653 return -1;
654 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000655}
656
Martin v. Löwis18e16552006-02-15 17:27:45 +0000657static Py_ssize_t
658buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000659{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000660 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000661 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000662 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000663 return -1;
664 if (lenp)
665 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000666 return 1;
667}
668
Martin v. Löwis18e16552006-02-15 17:27:45 +0000669static Py_ssize_t
670buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000671{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000672 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000673 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000674 if ( idx != 0 ) {
675 PyErr_SetString(PyExc_SystemError,
676 "accessing non-existent buffer segment");
677 return -1;
678 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000679 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000680 return -1;
681 *pp = (const char *)ptr;
682 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000683}
684
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000685static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000686 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000687 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000688 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
689 (ssizeargfunc)buffer_item, /*sq_item*/
690 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
691 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
692 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000693};
694
695static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000696 (readbufferproc)buffer_getreadbuf,
697 (writebufferproc)buffer_getwritebuf,
698 (segcountproc)buffer_getsegcount,
699 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000700};
701
702PyTypeObject PyBuffer_Type = {
703 PyObject_HEAD_INIT(&PyType_Type)
704 0,
705 "buffer",
706 sizeof(PyBufferObject),
707 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000708 (destructor)buffer_dealloc, /* tp_dealloc */
709 0, /* tp_print */
710 0, /* tp_getattr */
711 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000712 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000713 (reprfunc)buffer_repr, /* tp_repr */
714 0, /* tp_as_number */
715 &buffer_as_sequence, /* tp_as_sequence */
716 0, /* tp_as_mapping */
717 (hashfunc)buffer_hash, /* tp_hash */
718 0, /* tp_call */
719 (reprfunc)buffer_str, /* tp_str */
720 PyObject_GenericGetAttr, /* tp_getattro */
721 0, /* tp_setattro */
722 &buffer_as_buffer, /* tp_as_buffer */
723 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000724 buffer_doc, /* tp_doc */
725 0, /* tp_traverse */
726 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000727 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000728 0, /* tp_weaklistoffset */
729 0, /* tp_iter */
730 0, /* tp_iternext */
731 0, /* tp_methods */
732 0, /* tp_members */
733 0, /* tp_getset */
734 0, /* tp_base */
735 0, /* tp_dict */
736 0, /* tp_descr_get */
737 0, /* tp_descr_set */
738 0, /* tp_dictoffset */
739 0, /* tp_init */
740 0, /* tp_alloc */
741 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000742};