blob: e01938c2e93c257152e823d328c2b1314dba9b32 [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{
232 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000233 Py_ssize_t offset = 0;
234 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000235
Georg Brandl02c42872005-08-26 06:42:30 +0000236 if (!_PyArg_NoKeywords("buffer()", kw))
237 return NULL;
238
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000239 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000240 return NULL;
241 return PyBuffer_FromObject(ob, offset, size);
242}
243
244PyDoc_STRVAR(buffer_doc,
245"buffer(object [, offset[, size]])\n\
246\n\
247Create a new buffer object which references the given object.\n\
248The buffer will reference a slice of the target object from the\n\
249start of the object (or at the specified offset). The slice will\n\
250extend to the end of the target object (or with the specified size).");
251
252
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000253static void
Fred Drake79912472000-07-09 04:06:11 +0000254buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000255{
256 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000257 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000258}
259
260static int
Fred Drake79912472000-07-09 04:06:11 +0000261buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000262{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000263 void *p1, *p2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000264 Py_ssize_t len_self, len_other, min_len;
265 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000266
Brett Cannonde3b0522006-06-08 17:00:45 +0000267 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000268 return -1;
Brett Cannonde3b0522006-06-08 17:00:45 +0000269 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000270 return -1;
271 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000272 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000273 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000274 if (cmp != 0)
Thomas Hellerab1049c2006-08-08 17:37:00 +0000275 return cmp < 0 ? -1 : 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000276 }
277 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
278}
279
280static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000281buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000282{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000283 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000284
285 if ( self->b_base == NULL )
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000286 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000287 status,
288 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000289 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000290 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000291 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000292 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000293 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000294 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000295 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000296 self->b_size,
297 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000298 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000299}
300
301static long
Fred Drake79912472000-07-09 04:06:11 +0000302buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000303{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000304 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000305 Py_ssize_t size;
306 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000307 register unsigned char *p;
308 register long x;
309
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000310 if ( self->b_hash != -1 )
311 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000312
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000313 /* XXX potential bugs here, a readonly buffer does not imply that the
314 * underlying memory is immutable. b_readonly is a necessary but not
315 * sufficient condition for a buffer to be hashable. Perhaps it would
316 * be better to only allow hashing if the underlying object is known to
317 * be immutable (e.g. PyString_Check() is true). Another idea would
318 * be to call tp_hash on the underlying object and see if it raises
319 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000320 if ( !self->b_readonly )
321 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000322 PyErr_SetString(PyExc_TypeError,
323 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000324 return -1;
325 }
326
Brett Cannonde3b0522006-06-08 17:00:45 +0000327 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000328 return -1;
329 p = (unsigned char *) ptr;
330 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000331 x = *p << 7;
332 while (--len >= 0)
333 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000334 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000335 if (x == -1)
336 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000337 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000338 return x;
339}
340
341static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000342buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000343{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000344 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000345 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000346 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000347 return NULL;
Anthony Baxter377be112006-04-11 06:54:30 +0000348 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000349}
350
351/* Sequence methods */
352
Martin v. Löwis18e16552006-02-15 17:27:45 +0000353static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000354buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000355{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000356 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000357 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000358 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000359 return -1;
360 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000361}
362
363static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000364buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000365{
366 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000367 void *ptr1, *ptr2;
368 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000369 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000370 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000371
372 if ( pb == NULL ||
373 pb->bf_getreadbuffer == NULL ||
374 pb->bf_getsegcount == NULL )
375 {
376 PyErr_BadArgument();
377 return NULL;
378 }
379 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
380 {
381 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000382 PyErr_SetString(PyExc_TypeError,
383 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000384 return NULL;
385 }
386
Brett Cannonde3b0522006-06-08 17:00:45 +0000387 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000388 return NULL;
389
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000390 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000391 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000392 {
393 Py_INCREF(other);
394 return other;
395 }
396
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000397 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000398 return NULL;
399
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000400 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000401 if ( ob == NULL )
402 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000403 p = PyString_AS_STRING(ob);
404 memcpy(p, ptr1, size);
405 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000406
407 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000408 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000409
410 return ob;
411}
412
413static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000414buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000415{
416 PyObject *ob;
417 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000418 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000419 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000420
421 if ( count < 0 )
422 count = 0;
Brett Cannonde3b0522006-06-08 17:00:45 +0000423 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000424 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000425 ob = PyString_FromStringAndSize(NULL, size * count);
426 if ( ob == NULL )
427 return NULL;
428
429 p = PyString_AS_STRING(ob);
430 while ( count-- )
431 {
432 memcpy(p, ptr, size);
433 p += size;
434 }
435
436 /* there is an extra byte in the string object, so this is safe */
437 *p = '\0';
438
439 return ob;
440}
441
442static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000443buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000444{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000445 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000446 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000447 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000448 return NULL;
449 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000450 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
451 return NULL;
452 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000453 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000454}
455
456static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000457buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000458{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000459 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000460 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000461 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000462 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000463 if ( left < 0 )
464 left = 0;
465 if ( right < 0 )
466 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000467 if ( right > size )
468 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000469 if ( right < left )
470 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000471 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000472 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000473}
474
Thomas Wouters3ccec682007-08-28 15:28:19 +0000475static PyObject *
476buffer_subscript(PyBufferObject *self, PyObject *item)
477{
478 void *p;
479 Py_ssize_t size;
480
481 if (!get_buf(self, &p, &size, ANY_BUFFER))
482 return NULL;
483 if (PyIndex_Check(item)) {
484 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
485 if (i == -1 && PyErr_Occurred())
486 return NULL;
487 if (i < 0)
488 i += size;
489 return buffer_item(self, i);
490 }
491 else if (PySlice_Check(item)) {
492 Py_ssize_t start, stop, step, slicelength, cur, i;
493
494 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
495 &start, &stop, &step, &slicelength) < 0) {
496 return NULL;
497 }
498
499 if (slicelength <= 0)
500 return PyString_FromStringAndSize("", 0);
501 else if (step == 1)
502 return PyString_FromStringAndSize((char *)p + start,
503 stop - start);
504 else {
505 PyObject *result;
506 char *source_buf = (char *)p;
507 char *result_buf = (char *)PyMem_Malloc(slicelength);
508
509 if (result_buf == NULL)
510 return PyErr_NoMemory();
511
512 for (cur = start, i = 0; i < slicelength;
513 cur += step, i++) {
514 result_buf[i] = source_buf[cur];
515 }
516
517 result = PyString_FromStringAndSize(result_buf,
518 slicelength);
519 PyMem_Free(result_buf);
520 return result;
521 }
522 }
523 else {
524 PyErr_SetString(PyExc_TypeError,
525 "sequence index must be integer");
526 return NULL;
527 }
528}
529
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000530static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000531buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000532{
533 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000534 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000535 Py_ssize_t size;
536 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000537
538 if ( self->b_readonly ) {
539 PyErr_SetString(PyExc_TypeError,
540 "buffer is read-only");
541 return -1;
542 }
543
Brett Cannonde3b0522006-06-08 17:00:45 +0000544 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000545 return -1;
546
547 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000548 PyErr_SetString(PyExc_IndexError,
549 "buffer assignment index out of range");
550 return -1;
551 }
552
553 pb = other ? other->ob_type->tp_as_buffer : NULL;
554 if ( pb == NULL ||
555 pb->bf_getreadbuffer == NULL ||
556 pb->bf_getsegcount == NULL )
557 {
558 PyErr_BadArgument();
559 return -1;
560 }
561 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
562 {
563 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000564 PyErr_SetString(PyExc_TypeError,
565 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000566 return -1;
567 }
568
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000569 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000570 return -1;
571 if ( count != 1 ) {
572 PyErr_SetString(PyExc_TypeError,
573 "right operand must be a single byte");
574 return -1;
575 }
576
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000577 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000578 return 0;
579}
580
581static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000582buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000583{
584 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000585 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000586 Py_ssize_t size;
587 Py_ssize_t slice_len;
588 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000589
590 if ( self->b_readonly ) {
591 PyErr_SetString(PyExc_TypeError,
592 "buffer is read-only");
593 return -1;
594 }
595
596 pb = other ? other->ob_type->tp_as_buffer : NULL;
597 if ( pb == NULL ||
598 pb->bf_getreadbuffer == NULL ||
599 pb->bf_getsegcount == NULL )
600 {
601 PyErr_BadArgument();
602 return -1;
603 }
604 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
605 {
606 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000607 PyErr_SetString(PyExc_TypeError,
608 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000609 return -1;
610 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000611 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000612 return -1;
613 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000614 return -1;
615
616 if ( left < 0 )
617 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000618 else if ( left > size )
619 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000620 if ( right < left )
621 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000622 else if ( right > size )
623 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000624 slice_len = right - left;
625
626 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000627 PyErr_SetString(
628 PyExc_TypeError,
629 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000630 return -1;
631 }
632
633 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000634 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000635
636 return 0;
637}
638
Thomas Wouters3ccec682007-08-28 15:28:19 +0000639static int
640buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
641{
642 PyBufferProcs *pb;
643 void *ptr1, *ptr2;
644 Py_ssize_t selfsize;
645 Py_ssize_t othersize;
646
647 if ( self->b_readonly ) {
648 PyErr_SetString(PyExc_TypeError,
649 "buffer is read-only");
650 return -1;
651 }
652
653 pb = value ? value->ob_type->tp_as_buffer : NULL;
654 if ( pb == NULL ||
655 pb->bf_getreadbuffer == NULL ||
656 pb->bf_getsegcount == NULL )
657 {
658 PyErr_BadArgument();
659 return -1;
660 }
661 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
662 {
663 /* ### use a different exception type/message? */
664 PyErr_SetString(PyExc_TypeError,
665 "single-segment buffer object expected");
666 return -1;
667 }
668 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
669 return -1;
670 if (PyIndex_Check(item)) {
671 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
672 if (i == -1 && PyErr_Occurred())
673 return -1;
674 if (i < 0)
675 i += selfsize;
676 return buffer_ass_item(self, i, value);
677 }
678 else if (PySlice_Check(item)) {
679 Py_ssize_t start, stop, step, slicelength;
680
681 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
682 &start, &stop, &step, &slicelength) < 0)
683 return -1;
684
Thomas Wouters3ccec682007-08-28 15:28:19 +0000685 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
686 return -1;
687
688 if (othersize != slicelength) {
689 PyErr_SetString(
690 PyExc_TypeError,
691 "right operand length must match slice length");
692 return -1;
693 }
694
695 if (slicelength == 0)
696 return 0;
697 else if (step == 1) {
698 memcpy((char *)ptr1 + start, ptr2, slicelength);
699 return 0;
700 }
701 else {
702 Py_ssize_t cur, i;
703
704 for (cur = start, i = 0; i < slicelength;
705 cur += step, i++) {
706 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
707 }
708
709 return 0;
710 }
711 } else {
712 PyErr_SetString(PyExc_TypeError,
713 "buffer indices must be integers");
714 return -1;
715 }
716}
717
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000718/* Buffer methods */
719
Martin v. Löwis18e16552006-02-15 17:27:45 +0000720static Py_ssize_t
721buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000722{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000723 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000724 if ( idx != 0 ) {
725 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000726 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000727 return -1;
728 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000729 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000730 return -1;
731 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000732}
733
Martin v. Löwis18e16552006-02-15 17:27:45 +0000734static Py_ssize_t
735buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000736{
Brett Cannonde3b0522006-06-08 17:00:45 +0000737 Py_ssize_t size;
738
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000739 if ( self->b_readonly )
740 {
741 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
742 return -1;
743 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000744
745 if ( idx != 0 ) {
746 PyErr_SetString(PyExc_SystemError,
747 "accessing non-existent buffer segment");
748 return -1;
749 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000750 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000751 return -1;
752 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000753}
754
Martin v. Löwis18e16552006-02-15 17:27:45 +0000755static Py_ssize_t
756buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000757{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000758 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000759 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000760 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000761 return -1;
762 if (lenp)
763 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000764 return 1;
765}
766
Martin v. Löwis18e16552006-02-15 17:27:45 +0000767static Py_ssize_t
768buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000769{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000770 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000771 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000772 if ( idx != 0 ) {
773 PyErr_SetString(PyExc_SystemError,
774 "accessing non-existent buffer segment");
775 return -1;
776 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000777 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000778 return -1;
779 *pp = (const char *)ptr;
780 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000781}
782
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000783static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000784 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000785 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000786 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
787 (ssizeargfunc)buffer_item, /*sq_item*/
788 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
789 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
790 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000791};
792
Thomas Wouters3ccec682007-08-28 15:28:19 +0000793static PyMappingMethods buffer_as_mapping = {
794 (lenfunc)buffer_length,
795 (binaryfunc)buffer_subscript,
796 (objobjargproc)buffer_ass_subscript,
797};
798
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000799static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000800 (readbufferproc)buffer_getreadbuf,
801 (writebufferproc)buffer_getwritebuf,
802 (segcountproc)buffer_getsegcount,
803 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000804};
805
806PyTypeObject PyBuffer_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000807 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000808 "buffer",
809 sizeof(PyBufferObject),
810 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000811 (destructor)buffer_dealloc, /* tp_dealloc */
812 0, /* tp_print */
813 0, /* tp_getattr */
814 0, /* tp_setattr */
815 (cmpfunc)buffer_compare, /* tp_compare */
816 (reprfunc)buffer_repr, /* tp_repr */
817 0, /* tp_as_number */
818 &buffer_as_sequence, /* tp_as_sequence */
Thomas Wouters3ccec682007-08-28 15:28:19 +0000819 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000820 (hashfunc)buffer_hash, /* tp_hash */
821 0, /* tp_call */
822 (reprfunc)buffer_str, /* tp_str */
823 PyObject_GenericGetAttr, /* tp_getattro */
824 0, /* tp_setattro */
825 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000826 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000827 buffer_doc, /* tp_doc */
828 0, /* tp_traverse */
829 0, /* tp_clear */
830 0, /* tp_richcompare */
831 0, /* tp_weaklistoffset */
832 0, /* tp_iter */
833 0, /* tp_iternext */
834 0, /* tp_methods */
835 0, /* tp_members */
836 0, /* tp_getset */
837 0, /* tp_base */
838 0, /* tp_dict */
839 0, /* tp_descr_get */
840 0, /* tp_descr_set */
841 0, /* tp_dictoffset */
842 0, /* tp_init */
843 0, /* tp_alloc */
844 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000845};