blob: 3bd8c6be3ea19b7bef316c3a8fffeaa59ed0e0c0 [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;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000434 ob = PyString_FromStringAndSize(NULL, size * count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000435 if ( ob == NULL )
436 return NULL;
437
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000438 p = PyString_AS_STRING(ob);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000439 while ( count-- )
440 {
441 memcpy(p, ptr, size);
442 p += size;
443 }
444
445 /* there is an extra byte in the string object, so this is safe */
446 *p = '\0';
447
448 return ob;
449}
450
451static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000452buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000453{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000454 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000455 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000456 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000457 return NULL;
458 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000459 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
460 return NULL;
461 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000462 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000463}
464
465static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000466buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000467{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000468 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000469 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000470 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000471 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000472 if ( left < 0 )
473 left = 0;
474 if ( right < 0 )
475 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000476 if ( right > size )
477 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000478 if ( right < left )
479 right = left;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000480 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000481 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000482}
483
Thomas Wouters3ccec682007-08-28 15:28:19 +0000484static PyObject *
485buffer_subscript(PyBufferObject *self, PyObject *item)
486{
487 void *p;
488 Py_ssize_t size;
489
490 if (!get_buf(self, &p, &size, ANY_BUFFER))
491 return NULL;
492 if (PyIndex_Check(item)) {
493 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
494 if (i == -1 && PyErr_Occurred())
495 return NULL;
496 if (i < 0)
497 i += size;
498 return buffer_item(self, i);
499 }
500 else if (PySlice_Check(item)) {
501 Py_ssize_t start, stop, step, slicelength, cur, i;
502
503 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
504 &start, &stop, &step, &slicelength) < 0) {
505 return NULL;
506 }
507
508 if (slicelength <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000509 return PyString_FromStringAndSize("", 0);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000510 else if (step == 1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000511 return PyString_FromStringAndSize((char *)p + start,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000512 stop - start);
513 else {
514 PyObject *result;
515 char *source_buf = (char *)p;
516 char *result_buf = (char *)PyMem_Malloc(slicelength);
517
518 if (result_buf == NULL)
519 return PyErr_NoMemory();
520
521 for (cur = start, i = 0; i < slicelength;
522 cur += step, i++) {
523 result_buf[i] = source_buf[cur];
524 }
525
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000526 result = PyString_FromStringAndSize(result_buf,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000527 slicelength);
528 PyMem_Free(result_buf);
529 return result;
530 }
531 }
532 else {
533 PyErr_SetString(PyExc_TypeError,
534 "sequence index must be integer");
535 return NULL;
536 }
537}
538
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000539static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000540buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000541{
542 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000543 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000544 Py_ssize_t size;
545 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000546
547 if ( self->b_readonly ) {
548 PyErr_SetString(PyExc_TypeError,
549 "buffer is read-only");
550 return -1;
551 }
552
Brett Cannonde3b0522006-06-08 17:00:45 +0000553 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000554 return -1;
555
556 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000557 PyErr_SetString(PyExc_IndexError,
558 "buffer assignment index out of range");
559 return -1;
560 }
561
562 pb = other ? other->ob_type->tp_as_buffer : NULL;
563 if ( pb == NULL ||
564 pb->bf_getreadbuffer == NULL ||
565 pb->bf_getsegcount == NULL )
566 {
567 PyErr_BadArgument();
568 return -1;
569 }
570 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
571 {
572 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000573 PyErr_SetString(PyExc_TypeError,
574 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000575 return -1;
576 }
577
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000578 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000579 return -1;
580 if ( count != 1 ) {
581 PyErr_SetString(PyExc_TypeError,
582 "right operand must be a single byte");
583 return -1;
584 }
585
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000586 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000587 return 0;
588}
589
590static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000591buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000592{
593 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000594 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000595 Py_ssize_t size;
596 Py_ssize_t slice_len;
597 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000598
599 if ( self->b_readonly ) {
600 PyErr_SetString(PyExc_TypeError,
601 "buffer is read-only");
602 return -1;
603 }
604
605 pb = other ? other->ob_type->tp_as_buffer : NULL;
606 if ( pb == NULL ||
607 pb->bf_getreadbuffer == NULL ||
608 pb->bf_getsegcount == NULL )
609 {
610 PyErr_BadArgument();
611 return -1;
612 }
613 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
614 {
615 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000616 PyErr_SetString(PyExc_TypeError,
617 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000618 return -1;
619 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000620 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000621 return -1;
622 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000623 return -1;
624
625 if ( left < 0 )
626 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000627 else if ( left > size )
628 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000629 if ( right < left )
630 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000631 else if ( right > size )
632 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000633 slice_len = right - left;
634
635 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000636 PyErr_SetString(
637 PyExc_TypeError,
638 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000639 return -1;
640 }
641
642 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000643 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000644
645 return 0;
646}
647
Thomas Wouters3ccec682007-08-28 15:28:19 +0000648static int
649buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
650{
651 PyBufferProcs *pb;
652 void *ptr1, *ptr2;
653 Py_ssize_t selfsize;
654 Py_ssize_t othersize;
655
656 if ( self->b_readonly ) {
657 PyErr_SetString(PyExc_TypeError,
658 "buffer is read-only");
659 return -1;
660 }
661
662 pb = value ? value->ob_type->tp_as_buffer : NULL;
663 if ( pb == NULL ||
664 pb->bf_getreadbuffer == NULL ||
665 pb->bf_getsegcount == NULL )
666 {
667 PyErr_BadArgument();
668 return -1;
669 }
670 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
671 {
672 /* ### use a different exception type/message? */
673 PyErr_SetString(PyExc_TypeError,
674 "single-segment buffer object expected");
675 return -1;
676 }
677 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
678 return -1;
679 if (PyIndex_Check(item)) {
680 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
681 if (i == -1 && PyErr_Occurred())
682 return -1;
683 if (i < 0)
684 i += selfsize;
685 return buffer_ass_item(self, i, value);
686 }
687 else if (PySlice_Check(item)) {
688 Py_ssize_t start, stop, step, slicelength;
689
690 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
691 &start, &stop, &step, &slicelength) < 0)
692 return -1;
693
Thomas Wouters3ccec682007-08-28 15:28:19 +0000694 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
695 return -1;
696
697 if (othersize != slicelength) {
698 PyErr_SetString(
699 PyExc_TypeError,
700 "right operand length must match slice length");
701 return -1;
702 }
703
704 if (slicelength == 0)
705 return 0;
706 else if (step == 1) {
707 memcpy((char *)ptr1 + start, ptr2, slicelength);
708 return 0;
709 }
710 else {
711 Py_ssize_t cur, i;
712
713 for (cur = start, i = 0; i < slicelength;
714 cur += step, i++) {
715 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
716 }
717
718 return 0;
719 }
720 } else {
721 PyErr_SetString(PyExc_TypeError,
722 "buffer indices must be integers");
723 return -1;
724 }
725}
726
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000727/* Buffer methods */
728
Martin v. Löwis18e16552006-02-15 17:27:45 +0000729static Py_ssize_t
730buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000731{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000732 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000733 if ( idx != 0 ) {
734 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000735 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000736 return -1;
737 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000738 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000739 return -1;
740 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000741}
742
Martin v. Löwis18e16552006-02-15 17:27:45 +0000743static Py_ssize_t
744buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000745{
Brett Cannonde3b0522006-06-08 17:00:45 +0000746 Py_ssize_t size;
747
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000748 if ( self->b_readonly )
749 {
750 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
751 return -1;
752 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000753
754 if ( idx != 0 ) {
755 PyErr_SetString(PyExc_SystemError,
756 "accessing non-existent buffer segment");
757 return -1;
758 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000759 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000760 return -1;
761 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000762}
763
Martin v. Löwis18e16552006-02-15 17:27:45 +0000764static Py_ssize_t
765buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000766{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000767 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000768 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000769 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000770 return -1;
771 if (lenp)
772 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000773 return 1;
774}
775
Martin v. Löwis18e16552006-02-15 17:27:45 +0000776static Py_ssize_t
777buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000778{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000779 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000780 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000781 if ( idx != 0 ) {
782 PyErr_SetString(PyExc_SystemError,
783 "accessing non-existent buffer segment");
784 return -1;
785 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000786 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000787 return -1;
788 *pp = (const char *)ptr;
789 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000790}
791
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000792static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000793 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000794 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000795 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
796 (ssizeargfunc)buffer_item, /*sq_item*/
797 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
798 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
799 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000800};
801
Thomas Wouters3ccec682007-08-28 15:28:19 +0000802static PyMappingMethods buffer_as_mapping = {
803 (lenfunc)buffer_length,
804 (binaryfunc)buffer_subscript,
805 (objobjargproc)buffer_ass_subscript,
806};
807
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000808static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000809 (readbufferproc)buffer_getreadbuf,
810 (writebufferproc)buffer_getwritebuf,
811 (segcountproc)buffer_getsegcount,
812 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000813};
814
815PyTypeObject PyBuffer_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000816 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000817 "buffer",
818 sizeof(PyBufferObject),
819 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000820 (destructor)buffer_dealloc, /* tp_dealloc */
821 0, /* tp_print */
822 0, /* tp_getattr */
823 0, /* tp_setattr */
824 (cmpfunc)buffer_compare, /* tp_compare */
825 (reprfunc)buffer_repr, /* tp_repr */
826 0, /* tp_as_number */
827 &buffer_as_sequence, /* tp_as_sequence */
Thomas Wouters3ccec682007-08-28 15:28:19 +0000828 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000829 (hashfunc)buffer_hash, /* tp_hash */
830 0, /* tp_call */
831 (reprfunc)buffer_str, /* tp_str */
832 PyObject_GenericGetAttr, /* tp_getattro */
833 0, /* tp_setattro */
834 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000835 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000836 buffer_doc, /* tp_doc */
837 0, /* tp_traverse */
838 0, /* tp_clear */
839 0, /* tp_richcompare */
840 0, /* tp_weaklistoffset */
841 0, /* tp_iter */
842 0, /* tp_iternext */
843 0, /* tp_methods */
844 0, /* tp_members */
845 0, /* tp_getset */
846 0, /* tp_base */
847 0, /* tp_dict */
848 0, /* tp_descr_get */
849 0, /* tp_descr_set */
850 0, /* tp_dictoffset */
851 0, /* tp_init */
852 0, /* tp_alloc */
853 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000854};