blob: dd2566820da989e5c5558f82683fc81e9c03a23c [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 )
Walter Dörwald1ab83302007-05-18 17:15:44 +0000322 return PyUnicode_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
Walter Dörwald1ab83302007-05-18 17:15:44 +0000328 return PyUnicode_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 */
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000427 /* XXX bad idea type-wise */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000428 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000429 {
430 Py_INCREF(other);
431 return other;
432 }
433
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000434 if (PyUnicode_Check(other)) {
435 /* XXX HACK */
Guido van Rossum0f0eb0b2007-05-15 20:37:11 +0000436 if ( (count = (*pb->bf_getcharbuffer)(other, 0,
437 (char **)&ptr2)) < 0 )
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000438 return NULL;
439 }
440 else {
441 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
442 return NULL;
443 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000444
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000445 /* XXX Should return a bytes object, really */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000446 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000447 if ( ob == NULL )
448 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000449 p = PyString_AS_STRING(ob);
450 memcpy(p, ptr1, size);
451 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000452
453 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000454 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000455
456 return ob;
457}
458
459static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000460buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000461{
462 PyObject *ob;
463 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000464 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000465 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000466
467 if ( count < 0 )
468 count = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000469 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000470 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000471 ob = PyString_FromStringAndSize(NULL, size * count);
472 if ( ob == NULL )
473 return NULL;
474
475 p = PyString_AS_STRING(ob);
476 while ( count-- )
477 {
478 memcpy(p, ptr, size);
479 p += size;
480 }
481
482 /* there is an extra byte in the string object, so this is safe */
483 *p = '\0';
484
485 return ob;
486}
487
488static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000489buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000490{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000491 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000492 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000493 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000494 return NULL;
495 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000496 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
497 return NULL;
498 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000499 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000500}
501
502static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000503buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000504{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000505 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000506 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000507 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000508 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000509 if ( left < 0 )
510 left = 0;
511 if ( right < 0 )
512 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000513 if ( right > size )
514 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000515 if ( right < left )
516 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000517 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000518 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000519}
520
521static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000522buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000523{
524 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000525 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000526 Py_ssize_t size;
527 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000528
529 if ( self->b_readonly ) {
530 PyErr_SetString(PyExc_TypeError,
531 "buffer is read-only");
532 return -1;
533 }
534
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000535 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000536 return -1;
537
538 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000539 PyErr_SetString(PyExc_IndexError,
540 "buffer assignment index out of range");
541 return -1;
542 }
543
544 pb = other ? other->ob_type->tp_as_buffer : NULL;
545 if ( pb == NULL ||
546 pb->bf_getreadbuffer == NULL ||
547 pb->bf_getsegcount == NULL )
548 {
549 PyErr_BadArgument();
550 return -1;
551 }
552 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
553 {
554 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000555 PyErr_SetString(PyExc_TypeError,
556 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000557 return -1;
558 }
559
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000560 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000561 return -1;
562 if ( count != 1 ) {
563 PyErr_SetString(PyExc_TypeError,
564 "right operand must be a single byte");
565 return -1;
566 }
567
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000568 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000569 return 0;
570}
571
572static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000573buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000574{
575 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000576 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000577 Py_ssize_t size;
578 Py_ssize_t slice_len;
579 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000580
581 if ( self->b_readonly ) {
582 PyErr_SetString(PyExc_TypeError,
583 "buffer is read-only");
584 return -1;
585 }
586
587 pb = other ? other->ob_type->tp_as_buffer : NULL;
588 if ( pb == NULL ||
589 pb->bf_getreadbuffer == NULL ||
590 pb->bf_getsegcount == NULL )
591 {
592 PyErr_BadArgument();
593 return -1;
594 }
595 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
596 {
597 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000598 PyErr_SetString(PyExc_TypeError,
599 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000600 return -1;
601 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000602 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000603 return -1;
604 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000605 return -1;
606
607 if ( left < 0 )
608 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000609 else if ( left > size )
610 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000611 if ( right < left )
612 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000613 else if ( right > size )
614 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000615 slice_len = right - left;
616
617 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000618 PyErr_SetString(
619 PyExc_TypeError,
620 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000621 return -1;
622 }
623
624 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000625 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000626
627 return 0;
628}
629
630/* Buffer methods */
631
Martin v. Löwis18e16552006-02-15 17:27:45 +0000632static Py_ssize_t
633buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000634{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000635 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000636 if ( idx != 0 ) {
637 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000638 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000639 return -1;
640 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000641 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000642 return -1;
643 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000644}
645
Martin v. Löwis18e16552006-02-15 17:27:45 +0000646static Py_ssize_t
647buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000648{
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000649 Py_ssize_t size;
650
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000651 if ( self->b_readonly )
652 {
653 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
654 return -1;
655 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000656
657 if ( idx != 0 ) {
658 PyErr_SetString(PyExc_SystemError,
659 "accessing non-existent buffer segment");
660 return -1;
661 }
662 if (!get_buf(self, pp, &size, WRITE_BUFFER))
663 return -1;
664 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000665}
666
Martin v. Löwis18e16552006-02-15 17:27:45 +0000667static Py_ssize_t
668buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000669{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000670 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000671 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000672 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000673 return -1;
674 if (lenp)
675 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000676 return 1;
677}
678
Martin v. Löwis18e16552006-02-15 17:27:45 +0000679static Py_ssize_t
680buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000681{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000682 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000683 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000684 if ( idx != 0 ) {
685 PyErr_SetString(PyExc_SystemError,
686 "accessing non-existent buffer segment");
687 return -1;
688 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000689 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000690 return -1;
691 *pp = (const char *)ptr;
692 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000693}
694
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000695static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000696 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000697 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000698 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
699 (ssizeargfunc)buffer_item, /*sq_item*/
700 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
701 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
702 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000703};
704
705static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000706 (readbufferproc)buffer_getreadbuf,
707 (writebufferproc)buffer_getwritebuf,
708 (segcountproc)buffer_getsegcount,
709 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000710};
711
712PyTypeObject PyBuffer_Type = {
713 PyObject_HEAD_INIT(&PyType_Type)
714 0,
715 "buffer",
716 sizeof(PyBufferObject),
717 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000718 (destructor)buffer_dealloc, /* tp_dealloc */
719 0, /* tp_print */
720 0, /* tp_getattr */
721 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000722 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000723 (reprfunc)buffer_repr, /* tp_repr */
724 0, /* tp_as_number */
725 &buffer_as_sequence, /* tp_as_sequence */
726 0, /* tp_as_mapping */
727 (hashfunc)buffer_hash, /* tp_hash */
728 0, /* tp_call */
729 (reprfunc)buffer_str, /* tp_str */
730 PyObject_GenericGetAttr, /* tp_getattro */
731 0, /* tp_setattro */
732 &buffer_as_buffer, /* tp_as_buffer */
733 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000734 buffer_doc, /* tp_doc */
735 0, /* tp_traverse */
736 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000737 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000738 0, /* tp_weaklistoffset */
739 0, /* tp_iter */
740 0, /* tp_iternext */
741 0, /* tp_methods */
742 0, /* tp_members */
743 0, /* tp_getset */
744 0, /* tp_base */
745 0, /* tp_dict */
746 0, /* tp_descr_get */
747 0, /* tp_descr_set */
748 0, /* tp_dictoffset */
749 0, /* tp_init */
750 0, /* tp_alloc */
751 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000752};