blob: f6359608cb83b7b1cdd067d225a82f9c4acc25a7 [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 */
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 */
436 if ( (count = (*pb->bf_getcharbuffer)(other, 0, &ptr2)) < 0 )
437 return NULL;
438 }
439 else {
440 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
441 return NULL;
442 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000443
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000444 /* XXX Should return a bytes object, really */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000445 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000446 if ( ob == NULL )
447 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000448 p = PyString_AS_STRING(ob);
449 memcpy(p, ptr1, size);
450 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000451
452 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000453 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000454
455 return ob;
456}
457
458static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000459buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000460{
461 PyObject *ob;
462 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000463 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000464 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000465
466 if ( count < 0 )
467 count = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000468 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000469 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000470 ob = PyString_FromStringAndSize(NULL, size * count);
471 if ( ob == NULL )
472 return NULL;
473
474 p = PyString_AS_STRING(ob);
475 while ( count-- )
476 {
477 memcpy(p, ptr, size);
478 p += size;
479 }
480
481 /* there is an extra byte in the string object, so this is safe */
482 *p = '\0';
483
484 return ob;
485}
486
487static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000488buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000489{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000490 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000491 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000492 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000493 return NULL;
494 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000495 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
496 return NULL;
497 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000498 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000499}
500
501static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000502buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000503{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000504 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000505 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000506 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000507 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000508 if ( left < 0 )
509 left = 0;
510 if ( right < 0 )
511 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000512 if ( right > size )
513 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000514 if ( right < left )
515 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000516 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000517 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000518}
519
520static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000521buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000522{
523 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000524 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000525 Py_ssize_t size;
526 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000527
528 if ( self->b_readonly ) {
529 PyErr_SetString(PyExc_TypeError,
530 "buffer is read-only");
531 return -1;
532 }
533
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000534 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000535 return -1;
536
537 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000538 PyErr_SetString(PyExc_IndexError,
539 "buffer assignment index out of range");
540 return -1;
541 }
542
543 pb = other ? other->ob_type->tp_as_buffer : NULL;
544 if ( pb == NULL ||
545 pb->bf_getreadbuffer == NULL ||
546 pb->bf_getsegcount == NULL )
547 {
548 PyErr_BadArgument();
549 return -1;
550 }
551 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
552 {
553 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000554 PyErr_SetString(PyExc_TypeError,
555 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000556 return -1;
557 }
558
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000559 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000560 return -1;
561 if ( count != 1 ) {
562 PyErr_SetString(PyExc_TypeError,
563 "right operand must be a single byte");
564 return -1;
565 }
566
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000567 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000568 return 0;
569}
570
571static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000572buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000573{
574 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000575 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000576 Py_ssize_t size;
577 Py_ssize_t slice_len;
578 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000579
580 if ( self->b_readonly ) {
581 PyErr_SetString(PyExc_TypeError,
582 "buffer is read-only");
583 return -1;
584 }
585
586 pb = other ? other->ob_type->tp_as_buffer : NULL;
587 if ( pb == NULL ||
588 pb->bf_getreadbuffer == NULL ||
589 pb->bf_getsegcount == NULL )
590 {
591 PyErr_BadArgument();
592 return -1;
593 }
594 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
595 {
596 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000597 PyErr_SetString(PyExc_TypeError,
598 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000599 return -1;
600 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000601 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000602 return -1;
603 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000604 return -1;
605
606 if ( left < 0 )
607 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000608 else if ( left > size )
609 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000610 if ( right < left )
611 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000612 else if ( right > size )
613 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000614 slice_len = right - left;
615
616 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000617 PyErr_SetString(
618 PyExc_TypeError,
619 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000620 return -1;
621 }
622
623 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000624 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000625
626 return 0;
627}
628
629/* Buffer methods */
630
Martin v. Löwis18e16552006-02-15 17:27:45 +0000631static Py_ssize_t
632buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000633{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000634 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000635 if ( idx != 0 ) {
636 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000637 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000638 return -1;
639 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000640 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000641 return -1;
642 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000643}
644
Martin v. Löwis18e16552006-02-15 17:27:45 +0000645static Py_ssize_t
646buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000647{
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000648 Py_ssize_t size;
649
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000650 if ( self->b_readonly )
651 {
652 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
653 return -1;
654 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000655
656 if ( idx != 0 ) {
657 PyErr_SetString(PyExc_SystemError,
658 "accessing non-existent buffer segment");
659 return -1;
660 }
661 if (!get_buf(self, pp, &size, WRITE_BUFFER))
662 return -1;
663 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000664}
665
Martin v. Löwis18e16552006-02-15 17:27:45 +0000666static Py_ssize_t
667buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000668{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000669 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000670 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000671 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000672 return -1;
673 if (lenp)
674 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000675 return 1;
676}
677
Martin v. Löwis18e16552006-02-15 17:27:45 +0000678static Py_ssize_t
679buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000680{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000681 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000682 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000683 if ( idx != 0 ) {
684 PyErr_SetString(PyExc_SystemError,
685 "accessing non-existent buffer segment");
686 return -1;
687 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000688 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000689 return -1;
690 *pp = (const char *)ptr;
691 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000692}
693
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000694static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000695 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000696 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000697 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
698 (ssizeargfunc)buffer_item, /*sq_item*/
699 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
700 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
701 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000702};
703
704static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000705 (readbufferproc)buffer_getreadbuf,
706 (writebufferproc)buffer_getwritebuf,
707 (segcountproc)buffer_getsegcount,
708 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000709};
710
711PyTypeObject PyBuffer_Type = {
712 PyObject_HEAD_INIT(&PyType_Type)
713 0,
714 "buffer",
715 sizeof(PyBufferObject),
716 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000717 (destructor)buffer_dealloc, /* tp_dealloc */
718 0, /* tp_print */
719 0, /* tp_getattr */
720 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000721 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000722 (reprfunc)buffer_repr, /* tp_repr */
723 0, /* tp_as_number */
724 &buffer_as_sequence, /* tp_as_sequence */
725 0, /* tp_as_mapping */
726 (hashfunc)buffer_hash, /* tp_hash */
727 0, /* tp_call */
728 (reprfunc)buffer_str, /* tp_str */
729 PyObject_GenericGetAttr, /* tp_getattro */
730 0, /* tp_setattro */
731 &buffer_as_buffer, /* tp_as_buffer */
732 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000733 buffer_doc, /* tp_doc */
734 0, /* tp_traverse */
735 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000736 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000737 0, /* tp_weaklistoffset */
738 0, /* tp_iter */
739 0, /* tp_iternext */
740 0, /* tp_methods */
741 0, /* tp_members */
742 0, /* tp_getset */
743 0, /* tp_base */
744 0, /* tp_dict */
745 0, /* tp_descr_get */
746 0, /* tp_descr_set */
747 0, /* tp_dictoffset */
748 0, /* tp_init */
749 0, /* tp_alloc */
750 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000751};