blob: 9a5c39f6f4c4369435f442ee333b43cf069c5ba0 [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
Benjamin Peterson9f4f4812008-04-27 03:01:45 +0000239 if (PyErr_WarnPy3k("buffer() not supported in 3.x; "
Georg Brandld5b635f2008-03-25 08:29:14 +0000240 "use memoryview()", 1) < 0)
Georg Brandl80055f62008-03-25 07:56:27 +0000241 return NULL;
242
Georg Brandl02c42872005-08-26 06:42:30 +0000243 if (!_PyArg_NoKeywords("buffer()", kw))
244 return NULL;
245
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000246 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000247 return NULL;
248 return PyBuffer_FromObject(ob, offset, size);
249}
250
251PyDoc_STRVAR(buffer_doc,
252"buffer(object [, offset[, size]])\n\
253\n\
254Create a new buffer object which references the given object.\n\
255The buffer will reference a slice of the target object from the\n\
256start of the object (or at the specified offset). The slice will\n\
257extend to the end of the target object (or with the specified size).");
258
259
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000260static void
Fred Drake79912472000-07-09 04:06:11 +0000261buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000262{
263 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000264 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000265}
266
267static int
Fred Drake79912472000-07-09 04:06:11 +0000268buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000269{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000270 void *p1, *p2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000271 Py_ssize_t len_self, len_other, min_len;
272 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000273
Brett Cannonde3b0522006-06-08 17:00:45 +0000274 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000275 return -1;
Brett Cannonde3b0522006-06-08 17:00:45 +0000276 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000277 return -1;
278 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000279 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000280 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000281 if (cmp != 0)
Thomas Hellerab1049c2006-08-08 17:37:00 +0000282 return cmp < 0 ? -1 : 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000283 }
284 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
285}
286
287static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000288buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000289{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000290 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000291
292 if ( self->b_base == NULL )
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000293 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000294 status,
295 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000296 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000297 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000298 else
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000299 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000300 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000301 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000302 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000303 self->b_size,
304 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000305 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000306}
307
308static long
Fred Drake79912472000-07-09 04:06:11 +0000309buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000310{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000311 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000312 Py_ssize_t size;
313 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000314 register unsigned char *p;
315 register long x;
316
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000317 if ( self->b_hash != -1 )
318 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000319
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000320 /* XXX potential bugs here, a readonly buffer does not imply that the
321 * underlying memory is immutable. b_readonly is a necessary but not
322 * sufficient condition for a buffer to be hashable. Perhaps it would
323 * be better to only allow hashing if the underlying object is known to
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000324 * be immutable (e.g. PyString_Check() is true). Another idea would
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000325 * be to call tp_hash on the underlying object and see if it raises
326 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000327 if ( !self->b_readonly )
328 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000329 PyErr_SetString(PyExc_TypeError,
330 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000331 return -1;
332 }
333
Brett Cannonde3b0522006-06-08 17:00:45 +0000334 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000335 return -1;
336 p = (unsigned char *) ptr;
337 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000338 x = *p << 7;
339 while (--len >= 0)
340 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000341 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000342 if (x == -1)
343 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000344 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000345 return x;
346}
347
348static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000349buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000350{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000351 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000352 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000353 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000354 return NULL;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000355 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000356}
357
358/* Sequence methods */
359
Martin v. Löwis18e16552006-02-15 17:27:45 +0000360static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000361buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000362{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000363 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000364 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000365 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000366 return -1;
367 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000368}
369
370static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000371buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000372{
373 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000374 void *ptr1, *ptr2;
375 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000376 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000377 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000378
379 if ( pb == NULL ||
380 pb->bf_getreadbuffer == NULL ||
381 pb->bf_getsegcount == NULL )
382 {
383 PyErr_BadArgument();
384 return NULL;
385 }
386 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
387 {
388 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000389 PyErr_SetString(PyExc_TypeError,
390 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000391 return NULL;
392 }
393
Brett Cannonde3b0522006-06-08 17:00:45 +0000394 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000395 return NULL;
396
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000397 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000398 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000399 {
400 Py_INCREF(other);
401 return other;
402 }
403
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000404 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000405 return NULL;
406
Gregory P. Smith9d534572008-06-11 07:41:16 +0000407 assert(count <= PY_SIZE_MAX - size);
408
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000409 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000410 if ( ob == NULL )
411 return NULL;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000412 p = PyString_AS_STRING(ob);
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000413 memcpy(p, ptr1, size);
414 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000415
416 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000417 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000418
419 return ob;
420}
421
422static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000423buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000424{
425 PyObject *ob;
426 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000427 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000428 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000429
430 if ( count < 0 )
431 count = 0;
Brett Cannonde3b0522006-06-08 17:00:45 +0000432 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000433 return NULL;
Neal Norwitze7d8be82008-07-31 17:17:14 +0000434 if (count > PY_SSIZE_T_MAX / size) {
435 PyErr_SetString(PyExc_MemoryError, "result too large");
436 return NULL;
437 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000438 ob = PyString_FromStringAndSize(NULL, size * count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000439 if ( ob == NULL )
440 return NULL;
441
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000442 p = PyString_AS_STRING(ob);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000443 while ( count-- )
444 {
445 memcpy(p, ptr, size);
446 p += size;
447 }
448
449 /* there is an extra byte in the string object, so this is safe */
450 *p = '\0';
451
452 return ob;
453}
454
455static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000456buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000457{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000458 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000459 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000460 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000461 return NULL;
462 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000463 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
464 return NULL;
465 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000466 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000467}
468
469static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000470buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000471{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000472 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000473 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000474 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000475 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000476 if ( left < 0 )
477 left = 0;
478 if ( right < 0 )
479 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000480 if ( right > size )
481 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000482 if ( right < left )
483 right = left;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000484 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000485 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000486}
487
Thomas Wouters3ccec682007-08-28 15:28:19 +0000488static PyObject *
489buffer_subscript(PyBufferObject *self, PyObject *item)
490{
491 void *p;
492 Py_ssize_t size;
493
494 if (!get_buf(self, &p, &size, ANY_BUFFER))
495 return NULL;
496 if (PyIndex_Check(item)) {
497 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
498 if (i == -1 && PyErr_Occurred())
499 return NULL;
500 if (i < 0)
501 i += size;
502 return buffer_item(self, i);
503 }
504 else if (PySlice_Check(item)) {
505 Py_ssize_t start, stop, step, slicelength, cur, i;
506
507 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
508 &start, &stop, &step, &slicelength) < 0) {
509 return NULL;
510 }
511
512 if (slicelength <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000513 return PyString_FromStringAndSize("", 0);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000514 else if (step == 1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000515 return PyString_FromStringAndSize((char *)p + start,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000516 stop - start);
517 else {
518 PyObject *result;
519 char *source_buf = (char *)p;
520 char *result_buf = (char *)PyMem_Malloc(slicelength);
521
522 if (result_buf == NULL)
523 return PyErr_NoMemory();
524
525 for (cur = start, i = 0; i < slicelength;
526 cur += step, i++) {
527 result_buf[i] = source_buf[cur];
528 }
529
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000530 result = PyString_FromStringAndSize(result_buf,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000531 slicelength);
532 PyMem_Free(result_buf);
533 return result;
534 }
535 }
536 else {
537 PyErr_SetString(PyExc_TypeError,
538 "sequence index must be integer");
539 return NULL;
540 }
541}
542
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000543static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000544buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000545{
546 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000547 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000548 Py_ssize_t size;
549 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000550
551 if ( self->b_readonly ) {
552 PyErr_SetString(PyExc_TypeError,
553 "buffer is read-only");
554 return -1;
555 }
556
Brett Cannonde3b0522006-06-08 17:00:45 +0000557 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000558 return -1;
559
560 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000561 PyErr_SetString(PyExc_IndexError,
562 "buffer assignment index out of range");
563 return -1;
564 }
565
566 pb = other ? other->ob_type->tp_as_buffer : NULL;
567 if ( pb == NULL ||
568 pb->bf_getreadbuffer == NULL ||
569 pb->bf_getsegcount == NULL )
570 {
571 PyErr_BadArgument();
572 return -1;
573 }
574 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
575 {
576 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000577 PyErr_SetString(PyExc_TypeError,
578 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000579 return -1;
580 }
581
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000582 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000583 return -1;
584 if ( count != 1 ) {
585 PyErr_SetString(PyExc_TypeError,
586 "right operand must be a single byte");
587 return -1;
588 }
589
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000590 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000591 return 0;
592}
593
594static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000595buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000596{
597 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000598 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000599 Py_ssize_t size;
600 Py_ssize_t slice_len;
601 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000602
603 if ( self->b_readonly ) {
604 PyErr_SetString(PyExc_TypeError,
605 "buffer is read-only");
606 return -1;
607 }
608
609 pb = other ? other->ob_type->tp_as_buffer : NULL;
610 if ( pb == NULL ||
611 pb->bf_getreadbuffer == NULL ||
612 pb->bf_getsegcount == NULL )
613 {
614 PyErr_BadArgument();
615 return -1;
616 }
617 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
618 {
619 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000620 PyErr_SetString(PyExc_TypeError,
621 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000622 return -1;
623 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000624 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000625 return -1;
626 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000627 return -1;
628
629 if ( left < 0 )
630 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000631 else if ( left > size )
632 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000633 if ( right < left )
634 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000635 else if ( right > size )
636 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000637 slice_len = right - left;
638
639 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000640 PyErr_SetString(
641 PyExc_TypeError,
642 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000643 return -1;
644 }
645
646 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000647 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000648
649 return 0;
650}
651
Thomas Wouters3ccec682007-08-28 15:28:19 +0000652static int
653buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
654{
655 PyBufferProcs *pb;
656 void *ptr1, *ptr2;
657 Py_ssize_t selfsize;
658 Py_ssize_t othersize;
659
660 if ( self->b_readonly ) {
661 PyErr_SetString(PyExc_TypeError,
662 "buffer is read-only");
663 return -1;
664 }
665
666 pb = value ? value->ob_type->tp_as_buffer : NULL;
667 if ( pb == NULL ||
668 pb->bf_getreadbuffer == NULL ||
669 pb->bf_getsegcount == NULL )
670 {
671 PyErr_BadArgument();
672 return -1;
673 }
674 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
675 {
676 /* ### use a different exception type/message? */
677 PyErr_SetString(PyExc_TypeError,
678 "single-segment buffer object expected");
679 return -1;
680 }
681 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
682 return -1;
683 if (PyIndex_Check(item)) {
684 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
685 if (i == -1 && PyErr_Occurred())
686 return -1;
687 if (i < 0)
688 i += selfsize;
689 return buffer_ass_item(self, i, value);
690 }
691 else if (PySlice_Check(item)) {
692 Py_ssize_t start, stop, step, slicelength;
693
694 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
695 &start, &stop, &step, &slicelength) < 0)
696 return -1;
697
Thomas Wouters3ccec682007-08-28 15:28:19 +0000698 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
699 return -1;
700
701 if (othersize != slicelength) {
702 PyErr_SetString(
703 PyExc_TypeError,
704 "right operand length must match slice length");
705 return -1;
706 }
707
708 if (slicelength == 0)
709 return 0;
710 else if (step == 1) {
711 memcpy((char *)ptr1 + start, ptr2, slicelength);
712 return 0;
713 }
714 else {
715 Py_ssize_t cur, i;
716
717 for (cur = start, i = 0; i < slicelength;
718 cur += step, i++) {
719 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
720 }
721
722 return 0;
723 }
724 } else {
725 PyErr_SetString(PyExc_TypeError,
726 "buffer indices must be integers");
727 return -1;
728 }
729}
730
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000731/* Buffer methods */
732
Martin v. Löwis18e16552006-02-15 17:27:45 +0000733static Py_ssize_t
734buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000735{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000736 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000737 if ( idx != 0 ) {
738 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000739 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000740 return -1;
741 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000742 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000743 return -1;
744 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000745}
746
Martin v. Löwis18e16552006-02-15 17:27:45 +0000747static Py_ssize_t
748buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000749{
Brett Cannonde3b0522006-06-08 17:00:45 +0000750 Py_ssize_t size;
751
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000752 if ( self->b_readonly )
753 {
754 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
755 return -1;
756 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000757
758 if ( idx != 0 ) {
759 PyErr_SetString(PyExc_SystemError,
760 "accessing non-existent buffer segment");
761 return -1;
762 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000763 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000764 return -1;
765 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000766}
767
Martin v. Löwis18e16552006-02-15 17:27:45 +0000768static Py_ssize_t
769buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000770{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000771 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000772 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000773 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000774 return -1;
775 if (lenp)
776 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000777 return 1;
778}
779
Martin v. Löwis18e16552006-02-15 17:27:45 +0000780static Py_ssize_t
781buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000782{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000783 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000784 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000785 if ( idx != 0 ) {
786 PyErr_SetString(PyExc_SystemError,
787 "accessing non-existent buffer segment");
788 return -1;
789 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000790 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000791 return -1;
792 *pp = (const char *)ptr;
793 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000794}
795
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000796static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000797 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000798 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000799 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
800 (ssizeargfunc)buffer_item, /*sq_item*/
801 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
802 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
803 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000804};
805
Thomas Wouters3ccec682007-08-28 15:28:19 +0000806static PyMappingMethods buffer_as_mapping = {
807 (lenfunc)buffer_length,
808 (binaryfunc)buffer_subscript,
809 (objobjargproc)buffer_ass_subscript,
810};
811
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000812static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000813 (readbufferproc)buffer_getreadbuf,
814 (writebufferproc)buffer_getwritebuf,
815 (segcountproc)buffer_getsegcount,
816 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000817};
818
819PyTypeObject PyBuffer_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000820 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000821 "buffer",
822 sizeof(PyBufferObject),
823 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000824 (destructor)buffer_dealloc, /* tp_dealloc */
825 0, /* tp_print */
826 0, /* tp_getattr */
827 0, /* tp_setattr */
828 (cmpfunc)buffer_compare, /* tp_compare */
829 (reprfunc)buffer_repr, /* tp_repr */
830 0, /* tp_as_number */
831 &buffer_as_sequence, /* tp_as_sequence */
Thomas Wouters3ccec682007-08-28 15:28:19 +0000832 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000833 (hashfunc)buffer_hash, /* tp_hash */
834 0, /* tp_call */
835 (reprfunc)buffer_str, /* tp_str */
836 PyObject_GenericGetAttr, /* tp_getattro */
837 0, /* tp_setattro */
838 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000839 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000840 buffer_doc, /* tp_doc */
841 0, /* tp_traverse */
842 0, /* tp_clear */
843 0, /* tp_richcompare */
844 0, /* tp_weaklistoffset */
845 0, /* tp_iter */
846 0, /* tp_iternext */
847 0, /* tp_methods */
848 0, /* tp_members */
849 0, /* tp_getset */
850 0, /* tp_base */
851 0, /* tp_dict */
852 0, /* tp_descr_get */
853 0, /* tp_descr_set */
854 0, /* tp_dictoffset */
855 0, /* tp_init */
856 0, /* tp_alloc */
857 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000858};