blob: f4c69a0222b8d744f8d0179f38768a39656ee84b [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 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000210 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000211 /* Inline PyObject_New */
Anthony Baxter377be112006-04-11 06:54:30 +0000212 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Moshe Zadkacf703f02000-08-04 15:36:13 +0000213 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000214 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000215 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000216
217 b->b_base = NULL;
218 b->b_ptr = (void *)(b + 1);
219 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000220 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000221 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000222 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000223
Moshe Zadkacf703f02000-08-04 15:36:13 +0000224 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000225}
226
227/* Methods */
228
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000229static PyObject *
230buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
231{
Georg Brandlf8f1fbd2008-03-25 11:59:51 +0000232 PyObject *ob;
233 Py_ssize_t offset = 0;
234 Py_ssize_t size = Py_END_OF_BUFFER;
235
Georg Brandl80055f62008-03-25 07:56:27 +0000236 if (Py_Py3kWarningFlag &&
237 PyErr_WarnEx(PyExc_DeprecationWarning,
Georg Brandld5b635f2008-03-25 08:29:14 +0000238 "buffer() not supported in 3.x; "
239 "use memoryview()", 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 )
Martin v. Löwis2c95cc62006-02-16 06:54:25 +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
Barry Warsaw7ce36942001-08-24 18:34:26 +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
323 * be immutable (e.g. PyString_Check() is true). Another idea would
324 * be to call tp_hash on the underlying object and see if it raises
325 * an error. */
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;
Anthony Baxter377be112006-04-11 06:54:30 +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
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000406 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000407 if ( ob == NULL )
408 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000409 p = PyString_AS_STRING(ob);
410 memcpy(p, ptr1, size);
411 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000412
413 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000414 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000415
416 return ob;
417}
418
419static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000420buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000421{
422 PyObject *ob;
423 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000424 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000425 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000426
427 if ( count < 0 )
428 count = 0;
Brett Cannonde3b0522006-06-08 17:00:45 +0000429 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000430 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000431 ob = PyString_FromStringAndSize(NULL, size * count);
432 if ( ob == NULL )
433 return NULL;
434
435 p = PyString_AS_STRING(ob);
436 while ( count-- )
437 {
438 memcpy(p, ptr, size);
439 p += size;
440 }
441
442 /* there is an extra byte in the string object, so this is safe */
443 *p = '\0';
444
445 return ob;
446}
447
448static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000449buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000450{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000451 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000452 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000453 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000454 return NULL;
455 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000456 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
457 return NULL;
458 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000459 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000460}
461
462static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000463buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000464{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000465 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000466 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000467 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000468 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000469 if ( left < 0 )
470 left = 0;
471 if ( right < 0 )
472 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000473 if ( right > size )
474 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000475 if ( right < left )
476 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000477 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000478 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000479}
480
Thomas Wouters3ccec682007-08-28 15:28:19 +0000481static PyObject *
482buffer_subscript(PyBufferObject *self, PyObject *item)
483{
484 void *p;
485 Py_ssize_t size;
486
487 if (!get_buf(self, &p, &size, ANY_BUFFER))
488 return NULL;
489 if (PyIndex_Check(item)) {
490 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
491 if (i == -1 && PyErr_Occurred())
492 return NULL;
493 if (i < 0)
494 i += size;
495 return buffer_item(self, i);
496 }
497 else if (PySlice_Check(item)) {
498 Py_ssize_t start, stop, step, slicelength, cur, i;
499
500 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
501 &start, &stop, &step, &slicelength) < 0) {
502 return NULL;
503 }
504
505 if (slicelength <= 0)
506 return PyString_FromStringAndSize("", 0);
507 else if (step == 1)
508 return PyString_FromStringAndSize((char *)p + start,
509 stop - start);
510 else {
511 PyObject *result;
512 char *source_buf = (char *)p;
513 char *result_buf = (char *)PyMem_Malloc(slicelength);
514
515 if (result_buf == NULL)
516 return PyErr_NoMemory();
517
518 for (cur = start, i = 0; i < slicelength;
519 cur += step, i++) {
520 result_buf[i] = source_buf[cur];
521 }
522
523 result = PyString_FromStringAndSize(result_buf,
524 slicelength);
525 PyMem_Free(result_buf);
526 return result;
527 }
528 }
529 else {
530 PyErr_SetString(PyExc_TypeError,
531 "sequence index must be integer");
532 return NULL;
533 }
534}
535
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000536static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000537buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000538{
539 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000540 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000541 Py_ssize_t size;
542 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000543
544 if ( self->b_readonly ) {
545 PyErr_SetString(PyExc_TypeError,
546 "buffer is read-only");
547 return -1;
548 }
549
Brett Cannonde3b0522006-06-08 17:00:45 +0000550 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000551 return -1;
552
553 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000554 PyErr_SetString(PyExc_IndexError,
555 "buffer assignment index out of range");
556 return -1;
557 }
558
559 pb = other ? other->ob_type->tp_as_buffer : NULL;
560 if ( pb == NULL ||
561 pb->bf_getreadbuffer == NULL ||
562 pb->bf_getsegcount == NULL )
563 {
564 PyErr_BadArgument();
565 return -1;
566 }
567 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
568 {
569 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000570 PyErr_SetString(PyExc_TypeError,
571 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000572 return -1;
573 }
574
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000575 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000576 return -1;
577 if ( count != 1 ) {
578 PyErr_SetString(PyExc_TypeError,
579 "right operand must be a single byte");
580 return -1;
581 }
582
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000583 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000584 return 0;
585}
586
587static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000588buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000589{
590 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000591 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000592 Py_ssize_t size;
593 Py_ssize_t slice_len;
594 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000595
596 if ( self->b_readonly ) {
597 PyErr_SetString(PyExc_TypeError,
598 "buffer is read-only");
599 return -1;
600 }
601
602 pb = other ? other->ob_type->tp_as_buffer : NULL;
603 if ( pb == NULL ||
604 pb->bf_getreadbuffer == NULL ||
605 pb->bf_getsegcount == NULL )
606 {
607 PyErr_BadArgument();
608 return -1;
609 }
610 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
611 {
612 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000613 PyErr_SetString(PyExc_TypeError,
614 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000615 return -1;
616 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000617 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000618 return -1;
619 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000620 return -1;
621
622 if ( left < 0 )
623 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000624 else if ( left > size )
625 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000626 if ( right < left )
627 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000628 else if ( right > size )
629 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000630 slice_len = right - left;
631
632 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000633 PyErr_SetString(
634 PyExc_TypeError,
635 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000636 return -1;
637 }
638
639 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000640 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000641
642 return 0;
643}
644
Thomas Wouters3ccec682007-08-28 15:28:19 +0000645static int
646buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
647{
648 PyBufferProcs *pb;
649 void *ptr1, *ptr2;
650 Py_ssize_t selfsize;
651 Py_ssize_t othersize;
652
653 if ( self->b_readonly ) {
654 PyErr_SetString(PyExc_TypeError,
655 "buffer is read-only");
656 return -1;
657 }
658
659 pb = value ? value->ob_type->tp_as_buffer : NULL;
660 if ( pb == NULL ||
661 pb->bf_getreadbuffer == NULL ||
662 pb->bf_getsegcount == NULL )
663 {
664 PyErr_BadArgument();
665 return -1;
666 }
667 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
668 {
669 /* ### use a different exception type/message? */
670 PyErr_SetString(PyExc_TypeError,
671 "single-segment buffer object expected");
672 return -1;
673 }
674 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
675 return -1;
676 if (PyIndex_Check(item)) {
677 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
678 if (i == -1 && PyErr_Occurred())
679 return -1;
680 if (i < 0)
681 i += selfsize;
682 return buffer_ass_item(self, i, value);
683 }
684 else if (PySlice_Check(item)) {
685 Py_ssize_t start, stop, step, slicelength;
686
687 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
688 &start, &stop, &step, &slicelength) < 0)
689 return -1;
690
Thomas Wouters3ccec682007-08-28 15:28:19 +0000691 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
692 return -1;
693
694 if (othersize != slicelength) {
695 PyErr_SetString(
696 PyExc_TypeError,
697 "right operand length must match slice length");
698 return -1;
699 }
700
701 if (slicelength == 0)
702 return 0;
703 else if (step == 1) {
704 memcpy((char *)ptr1 + start, ptr2, slicelength);
705 return 0;
706 }
707 else {
708 Py_ssize_t cur, i;
709
710 for (cur = start, i = 0; i < slicelength;
711 cur += step, i++) {
712 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
713 }
714
715 return 0;
716 }
717 } else {
718 PyErr_SetString(PyExc_TypeError,
719 "buffer indices must be integers");
720 return -1;
721 }
722}
723
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000724/* Buffer methods */
725
Martin v. Löwis18e16552006-02-15 17:27:45 +0000726static Py_ssize_t
727buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000728{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000729 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000730 if ( idx != 0 ) {
731 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000732 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000733 return -1;
734 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000735 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000736 return -1;
737 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000738}
739
Martin v. Löwis18e16552006-02-15 17:27:45 +0000740static Py_ssize_t
741buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000742{
Brett Cannonde3b0522006-06-08 17:00:45 +0000743 Py_ssize_t size;
744
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000745 if ( self->b_readonly )
746 {
747 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
748 return -1;
749 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000750
751 if ( idx != 0 ) {
752 PyErr_SetString(PyExc_SystemError,
753 "accessing non-existent buffer segment");
754 return -1;
755 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000756 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000757 return -1;
758 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000759}
760
Martin v. Löwis18e16552006-02-15 17:27:45 +0000761static Py_ssize_t
762buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000763{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000764 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000765 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000766 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000767 return -1;
768 if (lenp)
769 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000770 return 1;
771}
772
Martin v. Löwis18e16552006-02-15 17:27:45 +0000773static Py_ssize_t
774buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000775{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000776 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000777 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000778 if ( idx != 0 ) {
779 PyErr_SetString(PyExc_SystemError,
780 "accessing non-existent buffer segment");
781 return -1;
782 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000783 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000784 return -1;
785 *pp = (const char *)ptr;
786 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000787}
788
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000789static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000790 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000791 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000792 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
793 (ssizeargfunc)buffer_item, /*sq_item*/
794 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
795 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
796 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000797};
798
Thomas Wouters3ccec682007-08-28 15:28:19 +0000799static PyMappingMethods buffer_as_mapping = {
800 (lenfunc)buffer_length,
801 (binaryfunc)buffer_subscript,
802 (objobjargproc)buffer_ass_subscript,
803};
804
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000805static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000806 (readbufferproc)buffer_getreadbuf,
807 (writebufferproc)buffer_getwritebuf,
808 (segcountproc)buffer_getsegcount,
809 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000810};
811
812PyTypeObject PyBuffer_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000813 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000814 "buffer",
815 sizeof(PyBufferObject),
816 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000817 (destructor)buffer_dealloc, /* tp_dealloc */
818 0, /* tp_print */
819 0, /* tp_getattr */
820 0, /* tp_setattr */
821 (cmpfunc)buffer_compare, /* tp_compare */
822 (reprfunc)buffer_repr, /* tp_repr */
823 0, /* tp_as_number */
824 &buffer_as_sequence, /* tp_as_sequence */
Thomas Wouters3ccec682007-08-28 15:28:19 +0000825 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000826 (hashfunc)buffer_hash, /* tp_hash */
827 0, /* tp_call */
828 (reprfunc)buffer_str, /* tp_str */
829 PyObject_GenericGetAttr, /* tp_getattro */
830 0, /* tp_setattro */
831 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000832 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000833 buffer_doc, /* tp_doc */
834 0, /* tp_traverse */
835 0, /* tp_clear */
836 0, /* tp_richcompare */
837 0, /* tp_weaklistoffset */
838 0, /* tp_iter */
839 0, /* tp_iternext */
840 0, /* tp_methods */
841 0, /* tp_members */
842 0, /* tp_getset */
843 0, /* tp_base */
844 0, /* tp_dict */
845 0, /* tp_descr_get */
846 0, /* tp_descr_set */
847 0, /* tp_dictoffset */
848 0, /* tp_init */
849 0, /* tp_alloc */
850 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000851};