blob: c52f0bc908ee0b9380319683a56232a54898ed50 [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 {
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +000015} PyBufferObject;
16
17
Brett Cannonde3b0522006-06-08 17:00:45 +000018enum buffer_t {
Brett Cannonc48b0e62006-06-09 17:05:48 +000019 READ_BUFFER,
20 WRITE_BUFFER,
21 CHAR_BUFFER,
Martin v. Löwisda587ab2007-06-08 17:29:20 +000022 ANY_BUFFER
Brett Cannonde3b0522006-06-08 17:00:45 +000023};
24
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000025static int
Brett Cannonde3b0522006-06-08 17:00:45 +000026get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000027 enum buffer_t buffer_type)
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000028{
Antoine Pitrouc7c96a92010-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 Schemenauer4252a7a2004-03-11 02:42:45 +000095}
96
97
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000099buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000100 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000101{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000102 PyBufferObject * b;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000103
Antoine Pitrouc7c96a92010-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 Rossum49ded3e1999-03-19 19:04:25 +0000114
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000115 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116 if ( b == NULL )
117 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000118
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000126
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000127 return (PyObject *) b;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000128}
129
130static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000131buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000132{
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000152}
153
154
155PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000156PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000157{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000158 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000159
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000167
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000168 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000169}
170
171PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000172PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000173{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000174 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000175
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000183
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000184 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000185}
186
187PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000188PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000189{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000190 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000191}
192
193PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000194PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000196 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197}
198
199PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000200PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000201{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000202 PyObject *o;
203 PyBufferObject * b;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000204
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000219
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000226
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000227 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000228}
229
230/* Methods */
231
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000232static PyObject *
233buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
234{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000235 PyObject *ob;
236 Py_ssize_t offset = 0;
237 Py_ssize_t size = Py_END_OF_BUFFER;
Georg Brandlf8f1fbd2008-03-25 11:59:51 +0000238
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000239 if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
240 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000241
Antoine Pitrouc7c96a92010-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 Rossumbea18cc2002-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 Rossum2e19bd71998-10-07 14:36:10 +0000259static void
Fred Drake79912472000-07-09 04:06:11 +0000260buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000261{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000262 Py_XDECREF(self->b_base);
263 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000264}
265
266static int
Fred Drake79912472000-07-09 04:06:11 +0000267buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000268{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000269 void *p1, *p2;
270 Py_ssize_t len_self, len_other, min_len;
271 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000272
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000284}
285
286static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000287buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000288{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000289 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000290
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000305}
306
307static long
Fred Drake79912472000-07-09 04:06:11 +0000308buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000309{
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000315
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000316 if ( self->b_hash != -1 )
317 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000318
Antoine Pitrouc7c96a92010-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 Rossum2e19bd71998-10-07 14:36:10 +0000332
Antoine Pitrouc7c96a92010-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;
Barry Warsaw1e13eb02012-02-20 20:42:21 -0500337 /*
338 We make the hash of the empty buffer be 0, rather than using
339 (prefix ^ suffix), since this slightly obfuscates the hash secret
340 */
341 if (len == 0) {
342 self->b_hash = 0;
343 return 0;
344 }
345 x = _Py_HashSecret.prefix;
346 x ^= *p << 7;
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000347 while (--len >= 0)
348 x = (1000003*x) ^ *p++;
349 x ^= size;
Barry Warsaw1e13eb02012-02-20 20:42:21 -0500350 x ^= _Py_HashSecret.suffix;
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000351 if (x == -1)
352 x = -2;
353 self->b_hash = x;
354 return x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000355}
356
357static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000358buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000359{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000360 void *ptr;
361 Py_ssize_t size;
362 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
363 return NULL;
364 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000365}
366
367/* Sequence methods */
368
Martin v. Löwis18e16552006-02-15 17:27:45 +0000369static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000370buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000371{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000372 void *ptr;
373 Py_ssize_t size;
374 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
375 return -1;
376 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000377}
378
379static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000380buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000381{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000382 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
383 void *ptr1, *ptr2;
384 char *p;
385 PyObject *ob;
386 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000387
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000388 if ( pb == NULL ||
389 pb->bf_getreadbuffer == NULL ||
390 pb->bf_getsegcount == NULL )
391 {
392 PyErr_BadArgument();
393 return NULL;
394 }
395 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
396 {
397 /* ### use a different exception type/message? */
398 PyErr_SetString(PyExc_TypeError,
399 "single-segment buffer object expected");
400 return NULL;
401 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000402
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000403 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
404 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000405
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000406 /* optimize special case */
407 if ( size == 0 )
408 {
409 Py_INCREF(other);
410 return other;
411 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000412
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000413 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
414 return NULL;
Gregory P. Smith9d534572008-06-11 07:41:16 +0000415
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000416 assert(count <= PY_SIZE_MAX - size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000417
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000418 ob = PyString_FromStringAndSize(NULL, size + count);
419 if ( ob == NULL )
420 return NULL;
421 p = PyString_AS_STRING(ob);
422 memcpy(p, ptr1, size);
423 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000424
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000425 /* there is an extra byte in the string object, so this is safe */
426 p[size + count] = '\0';
427
428 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000429}
430
431static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000432buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000433{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000434 PyObject *ob;
435 register char *p;
436 void *ptr;
437 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000438
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000439 if ( count < 0 )
440 count = 0;
441 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
442 return NULL;
443 if (count > PY_SSIZE_T_MAX / size) {
444 PyErr_SetString(PyExc_MemoryError, "result too large");
445 return NULL;
446 }
447 ob = PyString_FromStringAndSize(NULL, size * count);
448 if ( ob == NULL )
449 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000450
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000451 p = PyString_AS_STRING(ob);
452 while ( count-- )
453 {
454 memcpy(p, ptr, size);
455 p += size;
456 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000457
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000458 /* there is an extra byte in the string object, so this is safe */
459 *p = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000460
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000461 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000462}
463
464static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000465buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000466{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000467 void *ptr;
468 Py_ssize_t size;
469 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
470 return NULL;
471 if ( idx < 0 || idx >= size ) {
472 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
473 return NULL;
474 }
475 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000476}
477
478static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000479buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000480{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000481 void *ptr;
482 Py_ssize_t size;
483 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
484 return NULL;
485 if ( left < 0 )
486 left = 0;
487 if ( right < 0 )
488 right = 0;
489 if ( right > size )
490 right = size;
491 if ( right < left )
492 right = left;
493 return PyString_FromStringAndSize((char *)ptr + left,
494 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000495}
496
Thomas Wouters3ccec682007-08-28 15:28:19 +0000497static PyObject *
498buffer_subscript(PyBufferObject *self, PyObject *item)
499{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000500 void *p;
501 Py_ssize_t size;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000502
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000503 if (!get_buf(self, &p, &size, ANY_BUFFER))
504 return NULL;
505 if (PyIndex_Check(item)) {
506 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
507 if (i == -1 && PyErr_Occurred())
508 return NULL;
509 if (i < 0)
510 i += size;
511 return buffer_item(self, i);
512 }
513 else if (PySlice_Check(item)) {
514 Py_ssize_t start, stop, step, slicelength, cur, i;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000515
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000516 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
517 &start, &stop, &step, &slicelength) < 0) {
518 return NULL;
519 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000520
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000521 if (slicelength <= 0)
522 return PyString_FromStringAndSize("", 0);
523 else if (step == 1)
524 return PyString_FromStringAndSize((char *)p + start,
525 stop - start);
526 else {
527 PyObject *result;
528 char *source_buf = (char *)p;
529 char *result_buf = (char *)PyMem_Malloc(slicelength);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000530
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000531 if (result_buf == NULL)
532 return PyErr_NoMemory();
Thomas Wouters3ccec682007-08-28 15:28:19 +0000533
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000534 for (cur = start, i = 0; i < slicelength;
535 cur += step, i++) {
536 result_buf[i] = source_buf[cur];
537 }
538
539 result = PyString_FromStringAndSize(result_buf,
540 slicelength);
541 PyMem_Free(result_buf);
542 return result;
543 }
544 }
545 else {
546 PyErr_SetString(PyExc_TypeError,
547 "sequence index must be integer");
548 return NULL;
549 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000550}
551
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000552static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000553buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000554{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000555 PyBufferProcs *pb;
556 void *ptr1, *ptr2;
557 Py_ssize_t size;
558 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000559
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000560 if ( self->b_readonly ) {
561 PyErr_SetString(PyExc_TypeError,
562 "buffer is read-only");
563 return -1;
564 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000565
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000566 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
567 return -1;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000568
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000569 if (idx < 0 || idx >= size) {
570 PyErr_SetString(PyExc_IndexError,
571 "buffer assignment index out of range");
572 return -1;
573 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000574
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000575 pb = other ? other->ob_type->tp_as_buffer : NULL;
576 if ( pb == NULL ||
577 pb->bf_getreadbuffer == NULL ||
578 pb->bf_getsegcount == NULL )
579 {
580 PyErr_BadArgument();
581 return -1;
582 }
583 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
584 {
585 /* ### use a different exception type/message? */
586 PyErr_SetString(PyExc_TypeError,
587 "single-segment buffer object expected");
588 return -1;
589 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000590
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000591 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
592 return -1;
593 if ( count != 1 ) {
594 PyErr_SetString(PyExc_TypeError,
595 "right operand must be a single byte");
596 return -1;
597 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000598
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000599 ((char *)ptr1)[idx] = *(char *)ptr2;
600 return 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000601}
602
603static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000604buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000605{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000606 PyBufferProcs *pb;
607 void *ptr1, *ptr2;
608 Py_ssize_t size;
609 Py_ssize_t slice_len;
610 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000611
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000612 if ( self->b_readonly ) {
613 PyErr_SetString(PyExc_TypeError,
614 "buffer is read-only");
615 return -1;
616 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000617
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000618 pb = other ? other->ob_type->tp_as_buffer : NULL;
619 if ( pb == NULL ||
620 pb->bf_getreadbuffer == NULL ||
621 pb->bf_getsegcount == NULL )
622 {
623 PyErr_BadArgument();
624 return -1;
625 }
626 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
627 {
628 /* ### use a different exception type/message? */
629 PyErr_SetString(PyExc_TypeError,
630 "single-segment buffer object expected");
631 return -1;
632 }
633 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
634 return -1;
635 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
636 return -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000637
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000638 if ( left < 0 )
639 left = 0;
640 else if ( left > size )
641 left = size;
642 if ( right < left )
643 right = left;
644 else if ( right > size )
645 right = size;
646 slice_len = right - left;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000647
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000648 if ( count != slice_len ) {
649 PyErr_SetString(
650 PyExc_TypeError,
651 "right operand length must match slice length");
652 return -1;
653 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000654
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000655 if ( slice_len )
656 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000657
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000658 return 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000659}
660
Thomas Wouters3ccec682007-08-28 15:28:19 +0000661static int
662buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
663{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000664 PyBufferProcs *pb;
665 void *ptr1, *ptr2;
666 Py_ssize_t selfsize;
667 Py_ssize_t othersize;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000668
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000669 if ( self->b_readonly ) {
670 PyErr_SetString(PyExc_TypeError,
671 "buffer is read-only");
672 return -1;
673 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000674
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000675 pb = value ? value->ob_type->tp_as_buffer : NULL;
676 if ( pb == NULL ||
677 pb->bf_getreadbuffer == NULL ||
678 pb->bf_getsegcount == NULL )
679 {
680 PyErr_BadArgument();
681 return -1;
682 }
683 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
684 {
685 /* ### use a different exception type/message? */
686 PyErr_SetString(PyExc_TypeError,
687 "single-segment buffer object expected");
688 return -1;
689 }
690 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
691 return -1;
692 if (PyIndex_Check(item)) {
693 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
694 if (i == -1 && PyErr_Occurred())
695 return -1;
696 if (i < 0)
697 i += selfsize;
698 return buffer_ass_item(self, i, value);
699 }
700 else if (PySlice_Check(item)) {
701 Py_ssize_t start, stop, step, slicelength;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000702
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000703 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
704 &start, &stop, &step, &slicelength) < 0)
705 return -1;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000706
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000707 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
708 return -1;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000709
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000710 if (othersize != slicelength) {
711 PyErr_SetString(
712 PyExc_TypeError,
713 "right operand length must match slice length");
714 return -1;
715 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000716
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000717 if (slicelength == 0)
718 return 0;
719 else if (step == 1) {
720 memcpy((char *)ptr1 + start, ptr2, slicelength);
721 return 0;
722 }
723 else {
724 Py_ssize_t cur, i;
725
726 for (cur = start, i = 0; i < slicelength;
727 cur += step, i++) {
728 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
729 }
730
731 return 0;
732 }
733 } else {
734 PyErr_SetString(PyExc_TypeError,
735 "buffer indices must be integers");
736 return -1;
737 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000738}
739
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000740/* Buffer methods */
741
Martin v. Löwis18e16552006-02-15 17:27:45 +0000742static Py_ssize_t
743buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000744{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000745 Py_ssize_t size;
746 if ( idx != 0 ) {
747 PyErr_SetString(PyExc_SystemError,
748 "accessing non-existent buffer segment");
749 return -1;
750 }
751 if (!get_buf(self, pp, &size, READ_BUFFER))
752 return -1;
753 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000754}
755
Martin v. Löwis18e16552006-02-15 17:27:45 +0000756static Py_ssize_t
757buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000758{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000759 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000760
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000761 if ( self->b_readonly )
762 {
763 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
764 return -1;
765 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000766
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000767 if ( idx != 0 ) {
768 PyErr_SetString(PyExc_SystemError,
769 "accessing non-existent buffer segment");
770 return -1;
771 }
772 if (!get_buf(self, pp, &size, WRITE_BUFFER))
773 return -1;
774 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000775}
776
Martin v. Löwis18e16552006-02-15 17:27:45 +0000777static Py_ssize_t
778buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000779{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000780 void *ptr;
781 Py_ssize_t size;
782 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
783 return -1;
784 if (lenp)
785 *lenp = size;
786 return 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000787}
788
Martin v. Löwis18e16552006-02-15 17:27:45 +0000789static Py_ssize_t
790buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000791{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000792 void *ptr;
793 Py_ssize_t size;
794 if ( idx != 0 ) {
795 PyErr_SetString(PyExc_SystemError,
796 "accessing non-existent buffer segment");
797 return -1;
798 }
799 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
800 return -1;
801 *pp = (const char *)ptr;
802 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000803}
804
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000805static PySequenceMethods buffer_as_sequence = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000806 (lenfunc)buffer_length, /*sq_length*/
807 (binaryfunc)buffer_concat, /*sq_concat*/
808 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
809 (ssizeargfunc)buffer_item, /*sq_item*/
810 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
811 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
812 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000813};
814
Thomas Wouters3ccec682007-08-28 15:28:19 +0000815static PyMappingMethods buffer_as_mapping = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000816 (lenfunc)buffer_length,
817 (binaryfunc)buffer_subscript,
818 (objobjargproc)buffer_ass_subscript,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000819};
820
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000821static PyBufferProcs buffer_as_buffer = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000822 (readbufferproc)buffer_getreadbuf,
823 (writebufferproc)buffer_getwritebuf,
824 (segcountproc)buffer_getsegcount,
825 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000826};
827
828PyTypeObject PyBuffer_Type = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000829 PyVarObject_HEAD_INIT(&PyType_Type, 0)
830 "buffer",
831 sizeof(PyBufferObject),
832 0,
833 (destructor)buffer_dealloc, /* tp_dealloc */
834 0, /* tp_print */
835 0, /* tp_getattr */
836 0, /* tp_setattr */
837 (cmpfunc)buffer_compare, /* tp_compare */
838 (reprfunc)buffer_repr, /* tp_repr */
839 0, /* tp_as_number */
840 &buffer_as_sequence, /* tp_as_sequence */
841 &buffer_as_mapping, /* tp_as_mapping */
842 (hashfunc)buffer_hash, /* tp_hash */
843 0, /* tp_call */
844 (reprfunc)buffer_str, /* tp_str */
845 PyObject_GenericGetAttr, /* tp_getattro */
846 0, /* tp_setattro */
847 &buffer_as_buffer, /* tp_as_buffer */
848 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
849 buffer_doc, /* tp_doc */
850 0, /* tp_traverse */
851 0, /* tp_clear */
852 0, /* tp_richcompare */
853 0, /* tp_weaklistoffset */
854 0, /* tp_iter */
855 0, /* tp_iternext */
856 0, /* tp_methods */
857 0, /* tp_members */
858 0, /* tp_getset */
859 0, /* tp_base */
860 0, /* tp_dict */
861 0, /* tp_descr_get */
862 0, /* tp_descr_set */
863 0, /* tp_dictoffset */
864 0, /* tp_init */
865 0, /* tp_alloc */
866 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000867};