blob: d2297f306f44d0ae64ac3d26e6a42fd32378b038 [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;
Benjamin Petersona72d15c2017-09-13 21:20:29 -070037 PyBufferProcs *bp = Py_TYPE(self->b_base)->tp_as_buffer;
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000038 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) {
Benjamin Petersona72d15c2017-09-13 21:20:29 -070050 if (!PyType_HasFeature(Py_TYPE(self),
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000051 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;
Benjamin Peterson550b9452014-06-23 20:12:27 -070091 if (*size > count - offset)
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000092 *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 *
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200465buffer_item_impl(void *ptr, Py_ssize_t size, Py_ssize_t idx)
466{
467 if ( idx < 0 || idx >= size ) {
468 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
469 return NULL;
470 }
471 return PyString_FromStringAndSize((char *)ptr + idx, 1);
472}
473
474static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000475buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000476{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000477 void *ptr;
478 Py_ssize_t size;
479 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
480 return NULL;
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200481 return buffer_item_impl(ptr, size, idx);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000482}
483
484static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000485buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000486{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000487 void *ptr;
488 Py_ssize_t size;
489 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
490 return NULL;
491 if ( left < 0 )
492 left = 0;
493 if ( right < 0 )
494 right = 0;
495 if ( right > size )
496 right = size;
497 if ( right < left )
498 right = left;
499 return PyString_FromStringAndSize((char *)ptr + left,
500 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000501}
502
Thomas Wouters3ccec682007-08-28 15:28:19 +0000503static PyObject *
504buffer_subscript(PyBufferObject *self, PyObject *item)
505{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000506 void *p;
507 Py_ssize_t size;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000508
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000509 if (PyIndex_Check(item)) {
510 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
511 if (i == -1 && PyErr_Occurred())
512 return NULL;
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200513 if (!get_buf(self, &p, &size, ANY_BUFFER))
514 return NULL;
515
516 if (i < 0) {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000517 i += size;
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200518 }
519 return buffer_item_impl(p, size, i);
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000520 }
521 else if (PySlice_Check(item)) {
522 Py_ssize_t start, stop, step, slicelength, cur, i;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000523
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200524 if (_PySlice_Unpack(item, &start, &stop, &step) < 0)
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000525 return NULL;
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200526 if (!get_buf(self, &p, &size, ANY_BUFFER))
527 return NULL;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000528
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200529 slicelength = _PySlice_AdjustIndices(size, &start, &stop, step);
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000530 if (slicelength <= 0)
531 return PyString_FromStringAndSize("", 0);
532 else if (step == 1)
533 return PyString_FromStringAndSize((char *)p + start,
534 stop - start);
535 else {
536 PyObject *result;
537 char *source_buf = (char *)p;
538 char *result_buf = (char *)PyMem_Malloc(slicelength);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000539
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000540 if (result_buf == NULL)
541 return PyErr_NoMemory();
Thomas Wouters3ccec682007-08-28 15:28:19 +0000542
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000543 for (cur = start, i = 0; i < slicelength;
544 cur += step, i++) {
545 result_buf[i] = source_buf[cur];
546 }
547
548 result = PyString_FromStringAndSize(result_buf,
549 slicelength);
550 PyMem_Free(result_buf);
551 return result;
552 }
553 }
554 else {
555 PyErr_SetString(PyExc_TypeError,
556 "sequence index must be integer");
557 return NULL;
558 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000559}
560
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000561static int
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200562buffer_ass_item_impl(void *ptr1, Py_ssize_t size, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000563{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000564 PyBufferProcs *pb;
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200565 void *ptr2;
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000566 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000567
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000568 if (idx < 0 || idx >= size) {
569 PyErr_SetString(PyExc_IndexError,
570 "buffer assignment index out of range");
571 return -1;
572 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000573
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000574 pb = other ? other->ob_type->tp_as_buffer : NULL;
575 if ( pb == NULL ||
576 pb->bf_getreadbuffer == NULL ||
577 pb->bf_getsegcount == NULL )
578 {
579 PyErr_BadArgument();
580 return -1;
581 }
582 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
583 {
584 /* ### use a different exception type/message? */
585 PyErr_SetString(PyExc_TypeError,
586 "single-segment buffer object expected");
587 return -1;
588 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000589
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000590 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
591 return -1;
592 if ( count != 1 ) {
593 PyErr_SetString(PyExc_TypeError,
594 "right operand must be a single byte");
595 return -1;
596 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000597
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000598 ((char *)ptr1)[idx] = *(char *)ptr2;
599 return 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000600}
601
602static int
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200603buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
604{
605 void *ptr1;
606 Py_ssize_t size;
607
608 if ( self->b_readonly ) {
609 PyErr_SetString(PyExc_TypeError,
610 "buffer is read-only");
611 return -1;
612 }
613
614 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
615 return -1;
616 return buffer_ass_item_impl(ptr1, size, idx, other);
617}
618
619static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000620buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000621{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000622 PyBufferProcs *pb;
623 void *ptr1, *ptr2;
624 Py_ssize_t size;
625 Py_ssize_t slice_len;
626 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000627
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000628 if ( self->b_readonly ) {
629 PyErr_SetString(PyExc_TypeError,
630 "buffer is read-only");
631 return -1;
632 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000633
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000634 pb = other ? other->ob_type->tp_as_buffer : NULL;
635 if ( pb == NULL ||
636 pb->bf_getreadbuffer == NULL ||
637 pb->bf_getsegcount == NULL )
638 {
639 PyErr_BadArgument();
640 return -1;
641 }
642 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
643 {
644 /* ### use a different exception type/message? */
645 PyErr_SetString(PyExc_TypeError,
646 "single-segment buffer object expected");
647 return -1;
648 }
649 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
650 return -1;
651 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
652 return -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000653
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000654 if ( left < 0 )
655 left = 0;
656 else if ( left > size )
657 left = size;
658 if ( right < left )
659 right = left;
660 else if ( right > size )
661 right = size;
662 slice_len = right - left;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000663
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000664 if ( count != slice_len ) {
665 PyErr_SetString(
666 PyExc_TypeError,
667 "right operand length must match slice length");
668 return -1;
669 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000670
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000671 if ( slice_len )
672 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000673
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000674 return 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000675}
676
Thomas Wouters3ccec682007-08-28 15:28:19 +0000677static int
678buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
679{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000680 PyBufferProcs *pb;
681 void *ptr1, *ptr2;
682 Py_ssize_t selfsize;
683 Py_ssize_t othersize;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000684
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000685 if ( self->b_readonly ) {
686 PyErr_SetString(PyExc_TypeError,
687 "buffer is read-only");
688 return -1;
689 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000690
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000691 pb = value ? value->ob_type->tp_as_buffer : NULL;
692 if ( pb == NULL ||
693 pb->bf_getreadbuffer == NULL ||
694 pb->bf_getsegcount == NULL )
695 {
696 PyErr_BadArgument();
697 return -1;
698 }
699 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
700 {
701 /* ### use a different exception type/message? */
702 PyErr_SetString(PyExc_TypeError,
703 "single-segment buffer object expected");
704 return -1;
705 }
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000706 if (PyIndex_Check(item)) {
707 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
708 if (i == -1 && PyErr_Occurred())
709 return -1;
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200710 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
711 return -1;
712
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000713 if (i < 0)
714 i += selfsize;
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200715 return buffer_ass_item_impl(ptr1, selfsize, i, value);
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000716 }
717 else if (PySlice_Check(item)) {
718 Py_ssize_t start, stop, step, slicelength;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000719
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200720 if (_PySlice_Unpack(item, &start, &stop, &step) < 0)
721 return -1;
722 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000723 return -1;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000724
Serhiy Storchaka8e21cc32017-02-01 22:47:44 +0200725 slicelength = _PySlice_AdjustIndices(selfsize, &start, &stop, step);
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000726 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
727 return -1;
Thomas Wouters3ccec682007-08-28 15:28:19 +0000728
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000729 if (othersize != slicelength) {
730 PyErr_SetString(
731 PyExc_TypeError,
732 "right operand length must match slice length");
733 return -1;
734 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000735
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000736 if (slicelength == 0)
737 return 0;
738 else if (step == 1) {
739 memcpy((char *)ptr1 + start, ptr2, slicelength);
740 return 0;
741 }
742 else {
743 Py_ssize_t cur, i;
744
745 for (cur = start, i = 0; i < slicelength;
746 cur += step, i++) {
747 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
748 }
749
750 return 0;
751 }
752 } else {
753 PyErr_SetString(PyExc_TypeError,
754 "buffer indices must be integers");
755 return -1;
756 }
Thomas Wouters3ccec682007-08-28 15:28:19 +0000757}
758
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000759/* Buffer methods */
760
Martin v. Löwis18e16552006-02-15 17:27:45 +0000761static Py_ssize_t
762buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000763{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000764 Py_ssize_t size;
765 if ( idx != 0 ) {
766 PyErr_SetString(PyExc_SystemError,
767 "accessing non-existent buffer segment");
768 return -1;
769 }
770 if (!get_buf(self, pp, &size, READ_BUFFER))
771 return -1;
772 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000773}
774
Martin v. Löwis18e16552006-02-15 17:27:45 +0000775static Py_ssize_t
776buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000777{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000778 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000779
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000780 if ( self->b_readonly )
781 {
782 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
783 return -1;
784 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000785
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000786 if ( idx != 0 ) {
787 PyErr_SetString(PyExc_SystemError,
788 "accessing non-existent buffer segment");
789 return -1;
790 }
791 if (!get_buf(self, pp, &size, WRITE_BUFFER))
792 return -1;
793 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000794}
795
Martin v. Löwis18e16552006-02-15 17:27:45 +0000796static Py_ssize_t
797buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000798{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000799 void *ptr;
800 Py_ssize_t size;
801 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
802 return -1;
803 if (lenp)
804 *lenp = size;
805 return 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000806}
807
Martin v. Löwis18e16552006-02-15 17:27:45 +0000808static Py_ssize_t
809buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000810{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000811 void *ptr;
812 Py_ssize_t size;
813 if ( idx != 0 ) {
814 PyErr_SetString(PyExc_SystemError,
815 "accessing non-existent buffer segment");
816 return -1;
817 }
818 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
819 return -1;
820 *pp = (const char *)ptr;
821 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000822}
823
Kristján Valur Jónsson1d108bc2013-03-19 16:50:51 -0700824static int buffer_getbuffer(PyBufferObject *self, Py_buffer *buf, int flags)
825{
826 void *ptr;
827 Py_ssize_t size;
828 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
829 return -1;
830 return PyBuffer_FillInfo(buf, (PyObject*)self, ptr, size,
831 self->b_readonly, flags);
832}
833
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000834static PySequenceMethods buffer_as_sequence = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000835 (lenfunc)buffer_length, /*sq_length*/
836 (binaryfunc)buffer_concat, /*sq_concat*/
837 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
838 (ssizeargfunc)buffer_item, /*sq_item*/
839 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
840 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
841 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000842};
843
Thomas Wouters3ccec682007-08-28 15:28:19 +0000844static PyMappingMethods buffer_as_mapping = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000845 (lenfunc)buffer_length,
846 (binaryfunc)buffer_subscript,
847 (objobjargproc)buffer_ass_subscript,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000848};
849
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000850static PyBufferProcs buffer_as_buffer = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000851 (readbufferproc)buffer_getreadbuf,
852 (writebufferproc)buffer_getwritebuf,
853 (segcountproc)buffer_getsegcount,
854 (charbufferproc)buffer_getcharbuf,
Kristján Valur Jónsson1d108bc2013-03-19 16:50:51 -0700855 (getbufferproc)buffer_getbuffer,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000856};
857
858PyTypeObject PyBuffer_Type = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000859 PyVarObject_HEAD_INIT(&PyType_Type, 0)
860 "buffer",
861 sizeof(PyBufferObject),
862 0,
863 (destructor)buffer_dealloc, /* tp_dealloc */
864 0, /* tp_print */
865 0, /* tp_getattr */
866 0, /* tp_setattr */
867 (cmpfunc)buffer_compare, /* tp_compare */
868 (reprfunc)buffer_repr, /* tp_repr */
869 0, /* tp_as_number */
870 &buffer_as_sequence, /* tp_as_sequence */
871 &buffer_as_mapping, /* tp_as_mapping */
872 (hashfunc)buffer_hash, /* tp_hash */
873 0, /* tp_call */
874 (reprfunc)buffer_str, /* tp_str */
875 PyObject_GenericGetAttr, /* tp_getattro */
876 0, /* tp_setattro */
877 &buffer_as_buffer, /* tp_as_buffer */
Kristján Valur Jónsson1d108bc2013-03-19 16:50:51 -0700878 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000879 buffer_doc, /* tp_doc */
880 0, /* tp_traverse */
881 0, /* tp_clear */
882 0, /* tp_richcompare */
883 0, /* tp_weaklistoffset */
884 0, /* tp_iter */
885 0, /* tp_iternext */
886 0, /* tp_methods */
887 0, /* tp_members */
888 0, /* tp_getset */
889 0, /* tp_base */
890 0, /* tp_dict */
891 0, /* tp_descr_get */
892 0, /* tp_descr_set */
893 0, /* tp_dictoffset */
894 0, /* tp_init */
895 0, /* tp_alloc */
896 buffer_new, /* tp_new */
Benjamin Peterson550b9452014-06-23 20:12:27 -0700897};