blob: 5b08e1eaefb0cf88f058f5562cd7f75b3c25677a [file] [log] [blame]
Guido van Rossum2e19bd71998-10-07 14:36:10 +00001
2/* Buffer object implementation */
3
4#include "Python.h"
5
6
7typedef struct {
8 PyObject_HEAD
9 PyObject *b_base;
10 void *b_ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +000011 Py_ssize_t b_size;
12 Py_ssize_t b_offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000013 int b_readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000014 long b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000015} PyBufferObject;
16
17
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,
27 enum buffer_t buffer_type)
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000028{
29 if (self->b_base == NULL) {
30 assert (ptr != NULL);
31 *ptr = self->b_ptr;
32 *size = self->b_size;
33 }
34 else {
Martin v. Löwis18e16552006-02-15 17:27:45 +000035 Py_ssize_t count, offset;
Skip Montanaro9a8ae8f2006-06-10 22:38:13 +000036 readbufferproc proc = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000037 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
38 if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
39 PyErr_SetString(PyExc_TypeError,
40 "single-segment buffer object expected");
41 return 0;
42 }
Brett Cannonc48b0e62006-06-09 17:05:48 +000043 if ((buffer_type == READ_BUFFER) ||
Brett Cannonde3b0522006-06-08 17:00:45 +000044 ((buffer_type == ANY_BUFFER) && self->b_readonly))
45 proc = bp->bf_getreadbuffer;
Brett Cannonc48b0e62006-06-09 17:05:48 +000046 else if ((buffer_type == WRITE_BUFFER) ||
Brett Cannonde3b0522006-06-08 17:00:45 +000047 (buffer_type == ANY_BUFFER))
48 proc = (readbufferproc)bp->bf_getwritebuffer;
Brett Cannonc48b0e62006-06-09 17:05:48 +000049 else if (buffer_type == CHAR_BUFFER) {
Brett Cannonde3b0522006-06-08 17:00:45 +000050 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) {
Brett Cannonc48b0e62006-06-09 17:05:48 +000061 case READ_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000062 buffer_type_name = "read";
63 break;
Brett Cannonc48b0e62006-06-09 17:05:48 +000064 case WRITE_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000065 buffer_type_name = "write";
66 break;
Brett Cannonc48b0e62006-06-09 17:05:48 +000067 case CHAR_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000068 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 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000079 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;
Martin v. Löwis093c1002004-03-25 16:16:28 +000086 *(char **)ptr = *(char **)ptr + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000087 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;
95}
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,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000100 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000101{
102 PyBufferObject * b;
103
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000104 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +0000105 PyErr_SetString(PyExc_ValueError,
106 "size must be zero or positive");
107 return NULL;
108 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000109 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
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000115 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116 if ( b == NULL )
117 return NULL;
118
119 Py_XINCREF(base);
120 b->b_base = base;
121 b->b_ptr = ptr;
122 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000123 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000124 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000125 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000126
127 return (PyObject *) b;
128}
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{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000133 if (offset < 0) {
134 PyErr_SetString(PyExc_ValueError,
135 "offset must be zero or positive");
136 return NULL;
137 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000138 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000139 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000140 PyBufferObject *b = (PyBufferObject *)base;
141 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000142 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000143 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;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000150 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000151 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{
158 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
159
160 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 }
167
Neil Schemenauer4252a7a2004-03-11 02:42:45 +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{
174 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
175
176 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 }
183
Neil Schemenauer4252a7a2004-03-11 02:42:45 +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{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +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{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +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{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000202 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203 PyBufferObject * b;
204
Fred Drake4574f231999-08-04 13:08:19 +0000205 if (size < 0) {
206 PyErr_SetString(PyExc_ValueError,
207 "size must be zero or positive");
208 return NULL;
209 }
Gregory P. Smith9d534572008-06-11 07:41:16 +0000210 if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
211 /* unlikely */
212 return PyErr_NoMemory();
213 }
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000214 /* Inline PyObject_New */
Anthony Baxter377be112006-04-11 06:54:30 +0000215 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Moshe Zadkacf703f02000-08-04 15:36:13 +0000216 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000217 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000218 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000219
220 b->b_base = NULL;
221 b->b_ptr = (void *)(b + 1);
222 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000223 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000224 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000225 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000226
Moshe Zadkacf703f02000-08-04 15:36:13 +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{
Georg Brandlf8f1fbd2008-03-25 11:59:51 +0000235 PyObject *ob;
236 Py_ssize_t offset = 0;
237 Py_ssize_t size = Py_END_OF_BUFFER;
238
Brett Cannon0563a8f2008-08-08 04:15:53 +0000239 if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
Georg Brandl80055f62008-03-25 07:56:27 +0000240 return NULL;
241
Georg Brandl02c42872005-08-26 06:42:30 +0000242 if (!_PyArg_NoKeywords("buffer()", kw))
243 return NULL;
244
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000245 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000246 return NULL;
247 return PyBuffer_FromObject(ob, offset, size);
248}
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{
262 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000263 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{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000269 void *p1, *p2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000270 Py_ssize_t len_self, len_other, min_len;
271 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000272
Brett Cannonde3b0522006-06-08 17:00:45 +0000273 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000274 return -1;
Brett Cannonde3b0522006-06-08 17:00:45 +0000275 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000276 return -1;
277 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000278 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000279 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000280 if (cmp != 0)
Thomas Hellerab1049c2006-08-08 17:37:00 +0000281 return cmp < 0 ? -1 : 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000282 }
283 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
284}
285
286static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000287buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000288{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000289 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000290
291 if ( self->b_base == NULL )
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000292 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000293 status,
294 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000295 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000296 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000297 else
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000298 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000299 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000300 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000301 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000302 self->b_size,
303 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000304 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{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000310 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000311 Py_ssize_t size;
312 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000313 register unsigned char *p;
314 register long x;
315
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000316 if ( self->b_hash != -1 )
317 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000318
Neil Schemenauer0eadcd92004-03-11 01:00:44 +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
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000323 * be immutable (e.g. PyString_Check() is true). Another idea would
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000324 * be to call tp_hash on the underlying object and see if it raises
325 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000326 if ( !self->b_readonly )
327 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000328 PyErr_SetString(PyExc_TypeError,
329 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000330 return -1;
331 }
332
Brett Cannonde3b0522006-06-08 17:00:45 +0000333 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000334 return -1;
335 p = (unsigned char *) ptr;
336 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000337 x = *p << 7;
338 while (--len >= 0)
339 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000340 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000341 if (x == -1)
342 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000343 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000344 return x;
345}
346
347static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000348buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000349{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000350 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000351 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000352 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000353 return NULL;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000354 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000355}
356
357/* Sequence methods */
358
Martin v. Löwis18e16552006-02-15 17:27:45 +0000359static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000360buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000361{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000362 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000363 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000364 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000365 return -1;
366 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000367}
368
369static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000370buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000371{
372 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000373 void *ptr1, *ptr2;
374 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000375 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000376 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000377
378 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? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000388 PyErr_SetString(PyExc_TypeError,
389 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000390 return NULL;
391 }
392
Brett Cannonde3b0522006-06-08 17:00:45 +0000393 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000394 return NULL;
395
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000396 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000397 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000398 {
399 Py_INCREF(other);
400 return other;
401 }
402
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000403 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000404 return NULL;
405
Gregory P. Smith9d534572008-06-11 07:41:16 +0000406 assert(count <= PY_SIZE_MAX - size);
407
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000408 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000409 if ( ob == NULL )
410 return NULL;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000411 p = PyString_AS_STRING(ob);
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000412 memcpy(p, ptr1, size);
413 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000414
415 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000416 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000417
418 return ob;
419}
420
421static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000422buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000423{
424 PyObject *ob;
425 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000426 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000427 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000428
429 if ( count < 0 )
430 count = 0;
Brett Cannonde3b0522006-06-08 17:00:45 +0000431 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000432 return NULL;
Neal Norwitze7d8be82008-07-31 17:17:14 +0000433 if (count > PY_SSIZE_T_MAX / size) {
434 PyErr_SetString(PyExc_MemoryError, "result too large");
435 return NULL;
436 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000437 ob = PyString_FromStringAndSize(NULL, size * count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000438 if ( ob == NULL )
439 return NULL;
440
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000441 p = PyString_AS_STRING(ob);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000442 while ( count-- )
443 {
444 memcpy(p, ptr, size);
445 p += size;
446 }
447
448 /* there is an extra byte in the string object, so this is safe */
449 *p = '\0';
450
451 return ob;
452}
453
454static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000455buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000456{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000457 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000458 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000459 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000460 return NULL;
461 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000462 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
463 return NULL;
464 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000465 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000466}
467
468static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000469buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000470{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000471 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000472 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000473 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000474 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000475 if ( left < 0 )
476 left = 0;
477 if ( right < 0 )
478 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000479 if ( right > size )
480 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000481 if ( right < left )
482 right = left;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000483 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000484 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000485}
486
Thomas Wouters3ccec682007-08-28 15:28:19 +0000487static PyObject *
488buffer_subscript(PyBufferObject *self, PyObject *item)
489{
490 void *p;
491 Py_ssize_t size;
492
493 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;
505
506 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
507 &start, &stop, &step, &slicelength) < 0) {
508 return NULL;
509 }
510
511 if (slicelength <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000512 return PyString_FromStringAndSize("", 0);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000513 else if (step == 1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000514 return PyString_FromStringAndSize((char *)p + start,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000515 stop - start);
516 else {
517 PyObject *result;
518 char *source_buf = (char *)p;
519 char *result_buf = (char *)PyMem_Malloc(slicelength);
520
521 if (result_buf == NULL)
522 return PyErr_NoMemory();
523
524 for (cur = start, i = 0; i < slicelength;
525 cur += step, i++) {
526 result_buf[i] = source_buf[cur];
527 }
528
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000529 result = PyString_FromStringAndSize(result_buf,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000530 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 }
540}
541
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000542static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000543buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000544{
545 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000546 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000547 Py_ssize_t size;
548 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000549
550 if ( self->b_readonly ) {
551 PyErr_SetString(PyExc_TypeError,
552 "buffer is read-only");
553 return -1;
554 }
555
Brett Cannonde3b0522006-06-08 17:00:45 +0000556 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000557 return -1;
558
559 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000560 PyErr_SetString(PyExc_IndexError,
561 "buffer assignment index out of range");
562 return -1;
563 }
564
565 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? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000576 PyErr_SetString(PyExc_TypeError,
577 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000578 return -1;
579 }
580
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000581 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000582 return -1;
583 if ( count != 1 ) {
584 PyErr_SetString(PyExc_TypeError,
585 "right operand must be a single byte");
586 return -1;
587 }
588
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000589 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000590 return 0;
591}
592
593static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000594buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000595{
596 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000597 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000598 Py_ssize_t size;
599 Py_ssize_t slice_len;
600 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000601
602 if ( self->b_readonly ) {
603 PyErr_SetString(PyExc_TypeError,
604 "buffer is read-only");
605 return -1;
606 }
607
608 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? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000619 PyErr_SetString(PyExc_TypeError,
620 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000621 return -1;
622 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000623 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000624 return -1;
625 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000626 return -1;
627
628 if ( left < 0 )
629 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000630 else if ( left > size )
631 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000632 if ( right < left )
633 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000634 else if ( right > size )
635 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000636 slice_len = right - left;
637
638 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000639 PyErr_SetString(
640 PyExc_TypeError,
641 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000642 return -1;
643 }
644
645 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000646 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000647
648 return 0;
649}
650
Thomas Wouters3ccec682007-08-28 15:28:19 +0000651static int
652buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
653{
654 PyBufferProcs *pb;
655 void *ptr1, *ptr2;
656 Py_ssize_t selfsize;
657 Py_ssize_t othersize;
658
659 if ( self->b_readonly ) {
660 PyErr_SetString(PyExc_TypeError,
661 "buffer is read-only");
662 return -1;
663 }
664
665 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;
692
693 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
694 &start, &stop, &step, &slicelength) < 0)
695 return -1;
696
Thomas Wouters3ccec682007-08-28 15:28:19 +0000697 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
698 return -1;
699
700 if (othersize != slicelength) {
701 PyErr_SetString(
702 PyExc_TypeError,
703 "right operand length must match slice length");
704 return -1;
705 }
706
707 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 }
728}
729
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000730/* Buffer methods */
731
Martin v. Löwis18e16552006-02-15 17:27:45 +0000732static Py_ssize_t
733buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000734{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000735 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000736 if ( idx != 0 ) {
737 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000738 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000739 return -1;
740 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000741 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000742 return -1;
743 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000744}
745
Martin v. Löwis18e16552006-02-15 17:27:45 +0000746static Py_ssize_t
747buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000748{
Brett Cannonde3b0522006-06-08 17:00:45 +0000749 Py_ssize_t size;
750
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000751 if ( self->b_readonly )
752 {
753 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
754 return -1;
755 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000756
757 if ( idx != 0 ) {
758 PyErr_SetString(PyExc_SystemError,
759 "accessing non-existent buffer segment");
760 return -1;
761 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000762 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000763 return -1;
764 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000765}
766
Martin v. Löwis18e16552006-02-15 17:27:45 +0000767static Py_ssize_t
768buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000769{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000770 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000771 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000772 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000773 return -1;
774 if (lenp)
775 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000776 return 1;
777}
778
Martin v. Löwis18e16552006-02-15 17:27:45 +0000779static Py_ssize_t
780buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000781{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000782 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000783 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000784 if ( idx != 0 ) {
785 PyErr_SetString(PyExc_SystemError,
786 "accessing non-existent buffer segment");
787 return -1;
788 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000789 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000790 return -1;
791 *pp = (const char *)ptr;
792 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000793}
794
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000795static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000796 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000797 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000798 (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 Rossum2e19bd71998-10-07 14:36:10 +0000803};
804
Thomas Wouters3ccec682007-08-28 15:28:19 +0000805static PyMappingMethods buffer_as_mapping = {
806 (lenfunc)buffer_length,
807 (binaryfunc)buffer_subscript,
808 (objobjargproc)buffer_ass_subscript,
809};
810
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000811static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000812 (readbufferproc)buffer_getreadbuf,
813 (writebufferproc)buffer_getwritebuf,
814 (segcountproc)buffer_getsegcount,
815 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000816};
817
818PyTypeObject PyBuffer_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000819 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000820 "buffer",
821 sizeof(PyBufferObject),
822 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000823 (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 */
Thomas Wouters3ccec682007-08-28 15:28:19 +0000831 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000832 (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 */
Brett Cannonde3b0522006-06-08 17:00:45 +0000838 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000839 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 Rossum2e19bd71998-10-07 14:36:10 +0000857};