blob: 0f7e76372a4988dc7c364b5374a5b78d60d0ccb2 [file] [log] [blame]
Guido van Rossum4e6f6191998-10-07 14:36:10 +00001
2/* Buffer object implementation */
3
4#include "Python.h"
5
6
7typedef struct {
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +00008 PyObject_HEAD
9 PyObject *b_base;
10 void *b_ptr;
11 Py_ssize_t b_size;
12 Py_ssize_t b_offset;
13 int b_readonly;
14 long b_hash;
Guido van Rossum4e6f6191998-10-07 14:36:10 +000015} PyBufferObject;
16
17
Brett Cannon6d572ff2006-06-08 17:00:45 +000018enum buffer_t {
Brett Cannon2084d0b2006-06-09 17:05:48 +000019 READ_BUFFER,
20 WRITE_BUFFER,
21 CHAR_BUFFER,
Martin v. Löwis237725b2007-06-08 17:29:20 +000022 ANY_BUFFER
Brett Cannon6d572ff2006-06-08 17:00:45 +000023};
24
Neil Schemenauerdde2dbb2004-03-11 02:42:45 +000025static int
Brett Cannon6d572ff2006-06-08 17:00:45 +000026get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +000027 enum buffer_t buffer_type)
Neil Schemenauerdde2dbb2004-03-11 02:42:45 +000028{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +000029 if (self->b_base == NULL) {
30 assert (ptr != NULL);
31 *ptr = self->b_ptr;
32 *size = self->b_size;
33 }
34 else {
35 Py_ssize_t count, offset;
36 readbufferproc proc = 0;
37 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 }
43 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 if (!PyType_HasFeature(self->ob_type,
51 Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
52 PyErr_SetString(PyExc_TypeError,
53 "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
54 return 0;
55 }
56 proc = (readbufferproc)bp->bf_getcharbuffer;
57 }
58 if (!proc) {
59 char *buffer_type_name;
60 switch (buffer_type) {
61 case READ_BUFFER:
62 buffer_type_name = "read";
63 break;
64 case WRITE_BUFFER:
65 buffer_type_name = "write";
66 break;
67 case CHAR_BUFFER:
68 buffer_type_name = "char";
69 break;
70 default:
71 buffer_type_name = "no";
72 break;
73 }
74 PyErr_Format(PyExc_TypeError,
75 "%s buffer type not available",
76 buffer_type_name);
77 return 0;
78 }
79 if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
80 return 0;
81 /* apply constraints to the start/end */
82 if (self->b_offset > count)
83 offset = count;
84 else
85 offset = self->b_offset;
86 *(char **)ptr = *(char **)ptr + offset;
87 if (self->b_size == Py_END_OF_BUFFER)
88 *size = count;
89 else
90 *size = self->b_size;
91 if (offset + *size > count)
92 *size = count - offset;
93 }
94 return 1;
Neil Schemenauerdde2dbb2004-03-11 02:42:45 +000095}
96
97
Guido van Rossum4e6f6191998-10-07 14:36:10 +000098static PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +000099buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000100 int readonly)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000101{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000102 PyBufferObject * b;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000103
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000104 if (size < 0 && size != Py_END_OF_BUFFER) {
105 PyErr_SetString(PyExc_ValueError,
106 "size must be zero or positive");
107 return NULL;
108 }
109 if (offset < 0) {
110 PyErr_SetString(PyExc_ValueError,
111 "offset must be zero or positive");
112 return NULL;
113 }
Guido van Rossum76c6e9e1999-03-19 19:04:25 +0000114
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000115 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116 if ( b == NULL )
117 return NULL;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000118
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000119 Py_XINCREF(base);
120 b->b_base = base;
121 b->b_ptr = ptr;
122 b->b_size = size;
123 b->b_offset = offset;
124 b->b_readonly = readonly;
125 b->b_hash = -1;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000126
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000127 return (PyObject *) b;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000128}
129
130static PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000131buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000132{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000133 if (offset < 0) {
134 PyErr_SetString(PyExc_ValueError,
135 "offset must be zero or positive");
136 return NULL;
137 }
138 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
139 /* another buffer, refer to the base object */
140 PyBufferObject *b = (PyBufferObject *)base;
141 if (b->b_size != Py_END_OF_BUFFER) {
142 Py_ssize_t base_size = b->b_size - offset;
143 if (base_size < 0)
144 base_size = 0;
145 if (size == Py_END_OF_BUFFER || size > base_size)
146 size = base_size;
147 }
148 offset += b->b_offset;
149 base = b->b_base;
150 }
151 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000152}
153
154
155PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000156PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000157{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000158 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000159
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000160 if ( pb == NULL ||
161 pb->bf_getreadbuffer == NULL ||
162 pb->bf_getsegcount == NULL )
163 {
164 PyErr_SetString(PyExc_TypeError, "buffer object expected");
165 return NULL;
166 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000167
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000168 return buffer_from_object(base, size, offset, 1);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000169}
170
171PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000172PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000173{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000174 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000175
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000176 if ( pb == NULL ||
177 pb->bf_getwritebuffer == NULL ||
178 pb->bf_getsegcount == NULL )
179 {
180 PyErr_SetString(PyExc_TypeError, "buffer object expected");
181 return NULL;
182 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000183
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000184 return buffer_from_object(base, size, offset, 0);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000185}
186
187PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000188PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000189{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000190 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000191}
192
193PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000194PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000195{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000196 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000197}
198
199PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000200PyBuffer_New(Py_ssize_t size)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000201{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000202 PyObject *o;
203 PyBufferObject * b;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000204
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000205 if (size < 0) {
206 PyErr_SetString(PyExc_ValueError,
207 "size must be zero or positive");
208 return NULL;
209 }
210 if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
211 /* unlikely */
212 return PyErr_NoMemory();
213 }
214 /* Inline PyObject_New */
215 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
216 if ( o == NULL )
217 return PyErr_NoMemory();
218 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000219
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000220 b->b_base = NULL;
221 b->b_ptr = (void *)(b + 1);
222 b->b_size = size;
223 b->b_offset = 0;
224 b->b_readonly = 0;
225 b->b_hash = -1;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000226
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000227 return o;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000228}
229
230/* Methods */
231
Guido van Rossum41d00072002-06-14 20:41:17 +0000232static PyObject *
233buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
234{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000235 PyObject *ob;
236 Py_ssize_t offset = 0;
237 Py_ssize_t size = Py_END_OF_BUFFER;
Georg Brandldccaa0a2008-03-25 11:59:51 +0000238
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000239 if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
240 return NULL;
Georg Brandlf666fb22005-08-26 06:42:30 +0000241
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000242 if (!_PyArg_NoKeywords("buffer()", kw))
243 return NULL;
244
245 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
246 return NULL;
247 return PyBuffer_FromObject(ob, offset, size);
Guido van Rossum41d00072002-06-14 20:41:17 +0000248}
249
250PyDoc_STRVAR(buffer_doc,
251"buffer(object [, offset[, size]])\n\
252\n\
253Create a new buffer object which references the given object.\n\
254The buffer will reference a slice of the target object from the\n\
255start of the object (or at the specified offset). The slice will\n\
256extend to the end of the target object (or with the specified size).");
257
258
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000259static void
Fred Drakeedb6d8e2000-07-09 04:06:11 +0000260buffer_dealloc(PyBufferObject *self)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000261{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000262 Py_XDECREF(self->b_base);
263 PyObject_DEL(self);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000264}
265
266static int
Fred Drakeedb6d8e2000-07-09 04:06:11 +0000267buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000268{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000269 void *p1, *p2;
270 Py_ssize_t len_self, len_other, min_len;
271 int cmp;
Neil Schemenauerdde2dbb2004-03-11 02:42:45 +0000272
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000273 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
274 return -1;
275 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
276 return -1;
277 min_len = (len_self < len_other) ? len_self : len_other;
278 if (min_len > 0) {
279 cmp = memcmp(p1, p2, min_len);
280 if (cmp != 0)
281 return cmp < 0 ? -1 : 1;
282 }
283 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000284}
285
286static PyObject *
Fred Drakeedb6d8e2000-07-09 04:06:11 +0000287buffer_repr(PyBufferObject *self)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000288{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000289 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000290
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000291 if ( self->b_base == NULL )
292 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
293 status,
294 self->b_ptr,
295 self->b_size,
296 self);
297 else
298 return PyString_FromFormat(
299 "<%s buffer for %p, size %zd, offset %zd at %p>",
300 status,
301 self->b_base,
302 self->b_size,
303 self->b_offset,
304 self);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000305}
306
307static long
Fred Drakeedb6d8e2000-07-09 04:06:11 +0000308buffer_hash(PyBufferObject *self)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000309{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000310 void *ptr;
311 Py_ssize_t size;
312 register Py_ssize_t len;
313 register unsigned char *p;
314 register long x;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000315
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000316 if ( self->b_hash != -1 )
317 return self->b_hash;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000318
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000319 /* XXX potential bugs here, a readonly buffer does not imply that the
320 * underlying memory is immutable. b_readonly is a necessary but not
321 * sufficient condition for a buffer to be hashable. Perhaps it would
322 * be better to only allow hashing if the underlying object is known to
323 * be immutable (e.g. PyString_Check() is true). Another idea would
324 * be to call tp_hash on the underlying object and see if it raises
325 * an error. */
326 if ( !self->b_readonly )
327 {
328 PyErr_SetString(PyExc_TypeError,
329 "writable buffers are not hashable");
330 return -1;
331 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000332
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000333 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
334 return -1;
335 p = (unsigned char *) ptr;
336 len = size;
337 x = *p << 7;
338 while (--len >= 0)
339 x = (1000003*x) ^ *p++;
340 x ^= size;
341 if (x == -1)
342 x = -2;
343 self->b_hash = x;
344 return x;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000345}
346
347static PyObject *
Fred Drakeedb6d8e2000-07-09 04:06:11 +0000348buffer_str(PyBufferObject *self)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000349{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000350 void *ptr;
351 Py_ssize_t size;
352 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
353 return NULL;
354 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000355}
356
357/* Sequence methods */
358
Martin v. Löwis26a63482006-02-15 17:27:45 +0000359static Py_ssize_t
Fred Drakeedb6d8e2000-07-09 04:06:11 +0000360buffer_length(PyBufferObject *self)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000361{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000362 void *ptr;
363 Py_ssize_t size;
364 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
365 return -1;
366 return size;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000367}
368
369static PyObject *
Fred Drakeedb6d8e2000-07-09 04:06:11 +0000370buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000371{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000372 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
373 void *ptr1, *ptr2;
374 char *p;
375 PyObject *ob;
376 Py_ssize_t size, count;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000377
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000378 if ( pb == NULL ||
379 pb->bf_getreadbuffer == NULL ||
380 pb->bf_getsegcount == NULL )
381 {
382 PyErr_BadArgument();
383 return NULL;
384 }
385 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
386 {
387 /* ### use a different exception type/message? */
388 PyErr_SetString(PyExc_TypeError,
389 "single-segment buffer object expected");
390 return NULL;
391 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000392
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000393 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
394 return NULL;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000395
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000396 /* optimize special case */
397 if ( size == 0 )
398 {
399 Py_INCREF(other);
400 return other;
401 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000402
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000403 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
404 return NULL;
Gregory P. Smith55d04f92008-06-11 07:41:16 +0000405
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000406 assert(count <= PY_SIZE_MAX - size);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000407
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000408 ob = PyString_FromStringAndSize(NULL, size + count);
409 if ( ob == NULL )
410 return NULL;
411 p = PyString_AS_STRING(ob);
412 memcpy(p, ptr1, size);
413 memcpy(p + size, ptr2, count);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000414
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000415 /* there is an extra byte in the string object, so this is safe */
416 p[size + count] = '\0';
417
418 return ob;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000419}
420
421static PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000422buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000423{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000424 PyObject *ob;
425 register char *p;
426 void *ptr;
427 Py_ssize_t size;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000428
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000429 if ( count < 0 )
430 count = 0;
431 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
432 return NULL;
433 if (count > PY_SSIZE_T_MAX / size) {
434 PyErr_SetString(PyExc_MemoryError, "result too large");
435 return NULL;
436 }
437 ob = PyString_FromStringAndSize(NULL, size * count);
438 if ( ob == NULL )
439 return NULL;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000440
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000441 p = PyString_AS_STRING(ob);
442 while ( count-- )
443 {
444 memcpy(p, ptr, size);
445 p += size;
446 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000447
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000448 /* there is an extra byte in the string object, so this is safe */
449 *p = '\0';
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000450
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000451 return ob;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000452}
453
454static PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000455buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000456{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000457 void *ptr;
458 Py_ssize_t size;
459 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
460 return NULL;
461 if ( idx < 0 || idx >= size ) {
462 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
463 return NULL;
464 }
465 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000466}
467
468static PyObject *
Martin v. Löwis26a63482006-02-15 17:27:45 +0000469buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000470{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000471 void *ptr;
472 Py_ssize_t size;
473 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
474 return NULL;
475 if ( left < 0 )
476 left = 0;
477 if ( right < 0 )
478 right = 0;
479 if ( right > size )
480 right = size;
481 if ( right < left )
482 right = left;
483 return PyString_FromStringAndSize((char *)ptr + left,
484 right - left);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000485}
486
Thomas Woutersf6424442007-08-28 15:28:19 +0000487static PyObject *
488buffer_subscript(PyBufferObject *self, PyObject *item)
489{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000490 void *p;
491 Py_ssize_t size;
Thomas Woutersf6424442007-08-28 15:28:19 +0000492
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000493 if (!get_buf(self, &p, &size, ANY_BUFFER))
494 return NULL;
495 if (PyIndex_Check(item)) {
496 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
497 if (i == -1 && PyErr_Occurred())
498 return NULL;
499 if (i < 0)
500 i += size;
501 return buffer_item(self, i);
502 }
503 else if (PySlice_Check(item)) {
504 Py_ssize_t start, stop, step, slicelength, cur, i;
Thomas Woutersf6424442007-08-28 15:28:19 +0000505
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000506 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
507 &start, &stop, &step, &slicelength) < 0) {
508 return NULL;
509 }
Thomas Woutersf6424442007-08-28 15:28:19 +0000510
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000511 if (slicelength <= 0)
512 return PyString_FromStringAndSize("", 0);
513 else if (step == 1)
514 return PyString_FromStringAndSize((char *)p + start,
515 stop - start);
516 else {
517 PyObject *result;
518 char *source_buf = (char *)p;
519 char *result_buf = (char *)PyMem_Malloc(slicelength);
Thomas Woutersf6424442007-08-28 15:28:19 +0000520
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000521 if (result_buf == NULL)
522 return PyErr_NoMemory();
Thomas Woutersf6424442007-08-28 15:28:19 +0000523
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000524 for (cur = start, i = 0; i < slicelength;
525 cur += step, i++) {
526 result_buf[i] = source_buf[cur];
527 }
528
529 result = PyString_FromStringAndSize(result_buf,
530 slicelength);
531 PyMem_Free(result_buf);
532 return result;
533 }
534 }
535 else {
536 PyErr_SetString(PyExc_TypeError,
537 "sequence index must be integer");
538 return NULL;
539 }
Thomas Woutersf6424442007-08-28 15:28:19 +0000540}
541
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000542static int
Martin v. Löwis26a63482006-02-15 17:27:45 +0000543buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000544{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000545 PyBufferProcs *pb;
546 void *ptr1, *ptr2;
547 Py_ssize_t size;
548 Py_ssize_t count;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000549
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000550 if ( self->b_readonly ) {
551 PyErr_SetString(PyExc_TypeError,
552 "buffer is read-only");
553 return -1;
554 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000555
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000556 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
557 return -1;
Neil Schemenauerdde2dbb2004-03-11 02:42:45 +0000558
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000559 if (idx < 0 || idx >= size) {
560 PyErr_SetString(PyExc_IndexError,
561 "buffer assignment index out of range");
562 return -1;
563 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000564
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000565 pb = other ? other->ob_type->tp_as_buffer : NULL;
566 if ( pb == NULL ||
567 pb->bf_getreadbuffer == NULL ||
568 pb->bf_getsegcount == NULL )
569 {
570 PyErr_BadArgument();
571 return -1;
572 }
573 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
574 {
575 /* ### use a different exception type/message? */
576 PyErr_SetString(PyExc_TypeError,
577 "single-segment buffer object expected");
578 return -1;
579 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000580
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000581 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
582 return -1;
583 if ( count != 1 ) {
584 PyErr_SetString(PyExc_TypeError,
585 "right operand must be a single byte");
586 return -1;
587 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000588
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000589 ((char *)ptr1)[idx] = *(char *)ptr2;
590 return 0;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000591}
592
593static int
Martin v. Löwis26a63482006-02-15 17:27:45 +0000594buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000595{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000596 PyBufferProcs *pb;
597 void *ptr1, *ptr2;
598 Py_ssize_t size;
599 Py_ssize_t slice_len;
600 Py_ssize_t count;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000601
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000602 if ( self->b_readonly ) {
603 PyErr_SetString(PyExc_TypeError,
604 "buffer is read-only");
605 return -1;
606 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000607
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000608 pb = other ? other->ob_type->tp_as_buffer : NULL;
609 if ( pb == NULL ||
610 pb->bf_getreadbuffer == NULL ||
611 pb->bf_getsegcount == NULL )
612 {
613 PyErr_BadArgument();
614 return -1;
615 }
616 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
617 {
618 /* ### use a different exception type/message? */
619 PyErr_SetString(PyExc_TypeError,
620 "single-segment buffer object expected");
621 return -1;
622 }
623 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
624 return -1;
625 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
626 return -1;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000627
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000628 if ( left < 0 )
629 left = 0;
630 else if ( left > size )
631 left = size;
632 if ( right < left )
633 right = left;
634 else if ( right > size )
635 right = size;
636 slice_len = right - left;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000637
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000638 if ( count != slice_len ) {
639 PyErr_SetString(
640 PyExc_TypeError,
641 "right operand length must match slice length");
642 return -1;
643 }
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000644
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000645 if ( slice_len )
646 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000647
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000648 return 0;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000649}
650
Thomas Woutersf6424442007-08-28 15:28:19 +0000651static int
652buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
653{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000654 PyBufferProcs *pb;
655 void *ptr1, *ptr2;
656 Py_ssize_t selfsize;
657 Py_ssize_t othersize;
Thomas Woutersf6424442007-08-28 15:28:19 +0000658
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000659 if ( self->b_readonly ) {
660 PyErr_SetString(PyExc_TypeError,
661 "buffer is read-only");
662 return -1;
663 }
Thomas Woutersf6424442007-08-28 15:28:19 +0000664
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000665 pb = value ? value->ob_type->tp_as_buffer : NULL;
666 if ( pb == NULL ||
667 pb->bf_getreadbuffer == NULL ||
668 pb->bf_getsegcount == NULL )
669 {
670 PyErr_BadArgument();
671 return -1;
672 }
673 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
674 {
675 /* ### use a different exception type/message? */
676 PyErr_SetString(PyExc_TypeError,
677 "single-segment buffer object expected");
678 return -1;
679 }
680 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
681 return -1;
682 if (PyIndex_Check(item)) {
683 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
684 if (i == -1 && PyErr_Occurred())
685 return -1;
686 if (i < 0)
687 i += selfsize;
688 return buffer_ass_item(self, i, value);
689 }
690 else if (PySlice_Check(item)) {
691 Py_ssize_t start, stop, step, slicelength;
Thomas Woutersf6424442007-08-28 15:28:19 +0000692
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000693 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
694 &start, &stop, &step, &slicelength) < 0)
695 return -1;
Thomas Woutersf6424442007-08-28 15:28:19 +0000696
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000697 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
698 return -1;
Thomas Woutersf6424442007-08-28 15:28:19 +0000699
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000700 if (othersize != slicelength) {
701 PyErr_SetString(
702 PyExc_TypeError,
703 "right operand length must match slice length");
704 return -1;
705 }
Thomas Woutersf6424442007-08-28 15:28:19 +0000706
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000707 if (slicelength == 0)
708 return 0;
709 else if (step == 1) {
710 memcpy((char *)ptr1 + start, ptr2, slicelength);
711 return 0;
712 }
713 else {
714 Py_ssize_t cur, i;
715
716 for (cur = start, i = 0; i < slicelength;
717 cur += step, i++) {
718 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
719 }
720
721 return 0;
722 }
723 } else {
724 PyErr_SetString(PyExc_TypeError,
725 "buffer indices must be integers");
726 return -1;
727 }
Thomas Woutersf6424442007-08-28 15:28:19 +0000728}
729
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000730/* Buffer methods */
731
Martin v. Löwis26a63482006-02-15 17:27:45 +0000732static Py_ssize_t
733buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000734{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000735 Py_ssize_t size;
736 if ( idx != 0 ) {
737 PyErr_SetString(PyExc_SystemError,
738 "accessing non-existent buffer segment");
739 return -1;
740 }
741 if (!get_buf(self, pp, &size, READ_BUFFER))
742 return -1;
743 return size;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000744}
745
Martin v. Löwis26a63482006-02-15 17:27:45 +0000746static Py_ssize_t
747buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000748{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000749 Py_ssize_t size;
Brett Cannon6d572ff2006-06-08 17:00:45 +0000750
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000751 if ( self->b_readonly )
752 {
753 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
754 return -1;
755 }
Brett Cannon6d572ff2006-06-08 17:00:45 +0000756
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000757 if ( idx != 0 ) {
758 PyErr_SetString(PyExc_SystemError,
759 "accessing non-existent buffer segment");
760 return -1;
761 }
762 if (!get_buf(self, pp, &size, WRITE_BUFFER))
763 return -1;
764 return size;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000765}
766
Martin v. Löwis26a63482006-02-15 17:27:45 +0000767static Py_ssize_t
768buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000769{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000770 void *ptr;
771 Py_ssize_t size;
772 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
773 return -1;
774 if (lenp)
775 *lenp = size;
776 return 1;
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000777}
778
Martin v. Löwis26a63482006-02-15 17:27:45 +0000779static Py_ssize_t
780buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum58a554f1998-10-08 02:18:52 +0000781{
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000782 void *ptr;
783 Py_ssize_t size;
784 if ( idx != 0 ) {
785 PyErr_SetString(PyExc_SystemError,
786 "accessing non-existent buffer segment");
787 return -1;
788 }
789 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
790 return -1;
791 *pp = (const char *)ptr;
792 return size;
Guido van Rossum58a554f1998-10-08 02:18:52 +0000793}
794
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000795static PySequenceMethods buffer_as_sequence = {
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000796 (lenfunc)buffer_length, /*sq_length*/
797 (binaryfunc)buffer_concat, /*sq_concat*/
798 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
799 (ssizeargfunc)buffer_item, /*sq_item*/
800 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
801 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
802 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000803};
804
Thomas Woutersf6424442007-08-28 15:28:19 +0000805static PyMappingMethods buffer_as_mapping = {
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000806 (lenfunc)buffer_length,
807 (binaryfunc)buffer_subscript,
808 (objobjargproc)buffer_ass_subscript,
Thomas Woutersf6424442007-08-28 15:28:19 +0000809};
810
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000811static PyBufferProcs buffer_as_buffer = {
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000812 (readbufferproc)buffer_getreadbuf,
813 (writebufferproc)buffer_getwritebuf,
814 (segcountproc)buffer_getsegcount,
815 (charbufferproc)buffer_getcharbuf,
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000816};
817
818PyTypeObject PyBuffer_Type = {
Antoine Pitrouc43ba3b2010-05-09 15:15:40 +0000819 PyVarObject_HEAD_INIT(&PyType_Type, 0)
820 "buffer",
821 sizeof(PyBufferObject),
822 0,
823 (destructor)buffer_dealloc, /* tp_dealloc */
824 0, /* tp_print */
825 0, /* tp_getattr */
826 0, /* tp_setattr */
827 (cmpfunc)buffer_compare, /* tp_compare */
828 (reprfunc)buffer_repr, /* tp_repr */
829 0, /* tp_as_number */
830 &buffer_as_sequence, /* tp_as_sequence */
831 &buffer_as_mapping, /* tp_as_mapping */
832 (hashfunc)buffer_hash, /* tp_hash */
833 0, /* tp_call */
834 (reprfunc)buffer_str, /* tp_str */
835 PyObject_GenericGetAttr, /* tp_getattro */
836 0, /* tp_setattro */
837 &buffer_as_buffer, /* tp_as_buffer */
838 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
839 buffer_doc, /* tp_doc */
840 0, /* tp_traverse */
841 0, /* tp_clear */
842 0, /* tp_richcompare */
843 0, /* tp_weaklistoffset */
844 0, /* tp_iter */
845 0, /* tp_iternext */
846 0, /* tp_methods */
847 0, /* tp_members */
848 0, /* tp_getset */
849 0, /* tp_base */
850 0, /* tp_dict */
851 0, /* tp_descr_get */
852 0, /* tp_descr_set */
853 0, /* tp_dictoffset */
854 0, /* tp_init */
855 0, /* tp_alloc */
856 buffer_new, /* tp_new */
Guido van Rossum4e6f6191998-10-07 14:36:10 +0000857};