blob: e1ed76444bdab0bca73416c9fe87d2b3026c680f [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öwis897704d2007-06-08 17:29:40 +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öwis73c01d42008-02-14 11:26:18 +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{
235 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000236 Py_ssize_t offset = 0;
237 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000238
Georg Brandl02c42872005-08-26 06:42:30 +0000239 if (!_PyArg_NoKeywords("buffer()", kw))
240 return NULL;
241
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000242 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000243 return NULL;
244 return PyBuffer_FromObject(ob, offset, size);
245}
246
247PyDoc_STRVAR(buffer_doc,
248"buffer(object [, offset[, size]])\n\
249\n\
250Create a new buffer object which references the given object.\n\
251The buffer will reference a slice of the target object from the\n\
252start of the object (or at the specified offset). The slice will\n\
253extend to the end of the target object (or with the specified size).");
254
255
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000256static void
Fred Drake79912472000-07-09 04:06:11 +0000257buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000258{
259 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000260 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000261}
262
263static int
Fred Drake79912472000-07-09 04:06:11 +0000264buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000265{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000266 void *p1, *p2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000267 Py_ssize_t len_self, len_other, min_len;
268 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000269
Brett Cannonde3b0522006-06-08 17:00:45 +0000270 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000271 return -1;
Brett Cannonde3b0522006-06-08 17:00:45 +0000272 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000273 return -1;
274 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000275 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000276 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000277 if (cmp != 0)
Thomas Hellerab1049c2006-08-08 17:37:00 +0000278 return cmp < 0 ? -1 : 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000279 }
280 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
281}
282
283static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000284buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000285{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000286 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000287
288 if ( self->b_base == NULL )
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000289 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000290 status,
291 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000292 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000293 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000294 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000295 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000296 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000297 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000298 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000299 self->b_size,
300 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000301 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000302}
303
304static long
Fred Drake79912472000-07-09 04:06:11 +0000305buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000306{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000307 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000308 Py_ssize_t size;
309 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000310 register unsigned char *p;
311 register long x;
312
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000313 if ( self->b_hash != -1 )
314 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000315
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000316 /* XXX potential bugs here, a readonly buffer does not imply that the
317 * underlying memory is immutable. b_readonly is a necessary but not
318 * sufficient condition for a buffer to be hashable. Perhaps it would
319 * be better to only allow hashing if the underlying object is known to
320 * be immutable (e.g. PyString_Check() is true). Another idea would
321 * be to call tp_hash on the underlying object and see if it raises
322 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000323 if ( !self->b_readonly )
324 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000325 PyErr_SetString(PyExc_TypeError,
326 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000327 return -1;
328 }
329
Brett Cannonde3b0522006-06-08 17:00:45 +0000330 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000331 return -1;
332 p = (unsigned char *) ptr;
333 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000334 x = *p << 7;
335 while (--len >= 0)
336 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000337 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000338 if (x == -1)
339 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000340 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000341 return x;
342}
343
344static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000345buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000346{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000347 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000348 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000349 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000350 return NULL;
Anthony Baxter377be112006-04-11 06:54:30 +0000351 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000352}
353
354/* Sequence methods */
355
Martin v. Löwis18e16552006-02-15 17:27:45 +0000356static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000357buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000358{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000359 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000360 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000361 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000362 return -1;
363 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000364}
365
366static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000367buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000368{
369 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000370 void *ptr1, *ptr2;
371 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000372 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000373 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000374
375 if ( pb == NULL ||
376 pb->bf_getreadbuffer == NULL ||
377 pb->bf_getsegcount == NULL )
378 {
379 PyErr_BadArgument();
380 return NULL;
381 }
382 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
383 {
384 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000385 PyErr_SetString(PyExc_TypeError,
386 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000387 return NULL;
388 }
389
Brett Cannonde3b0522006-06-08 17:00:45 +0000390 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000391 return NULL;
392
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000393 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000394 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000395 {
396 Py_INCREF(other);
397 return other;
398 }
399
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000400 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000401 return NULL;
402
Martin v. Löwis73c01d42008-02-14 11:26:18 +0000403 assert(count <= PY_SIZE_MAX - size);
404
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000405 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000406 if ( ob == NULL )
407 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000408 p = PyString_AS_STRING(ob);
409 memcpy(p, ptr1, size);
410 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000411
412 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000413 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000414
415 return ob;
416}
417
418static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000419buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000420{
421 PyObject *ob;
422 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000423 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000424 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000425
426 if ( count < 0 )
427 count = 0;
Brett Cannonde3b0522006-06-08 17:00:45 +0000428 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000429 return NULL;
Neal Norwitz4f3be8a2008-07-31 17:08:14 +0000430 if (count > PY_SSIZE_T_MAX / size) {
431 PyErr_SetString(PyExc_MemoryError, "result too large");
432 return NULL;
433 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000434 ob = PyString_FromStringAndSize(NULL, size * count);
435 if ( ob == NULL )
436 return NULL;
437
438 p = PyString_AS_STRING(ob);
439 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 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +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;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +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
484static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000485buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000486{
487 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000488 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000489 Py_ssize_t size;
490 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000491
492 if ( self->b_readonly ) {
493 PyErr_SetString(PyExc_TypeError,
494 "buffer is read-only");
495 return -1;
496 }
497
Brett Cannonde3b0522006-06-08 17:00:45 +0000498 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000499 return -1;
500
501 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000502 PyErr_SetString(PyExc_IndexError,
503 "buffer assignment index out of range");
504 return -1;
505 }
506
507 pb = other ? other->ob_type->tp_as_buffer : NULL;
508 if ( pb == NULL ||
509 pb->bf_getreadbuffer == NULL ||
510 pb->bf_getsegcount == NULL )
511 {
512 PyErr_BadArgument();
513 return -1;
514 }
515 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
516 {
517 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000518 PyErr_SetString(PyExc_TypeError,
519 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000520 return -1;
521 }
522
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000523 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000524 return -1;
525 if ( count != 1 ) {
526 PyErr_SetString(PyExc_TypeError,
527 "right operand must be a single byte");
528 return -1;
529 }
530
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000531 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000532 return 0;
533}
534
535static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000536buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000537{
538 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000539 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000540 Py_ssize_t size;
541 Py_ssize_t slice_len;
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
550 pb = other ? other->ob_type->tp_as_buffer : NULL;
551 if ( pb == NULL ||
552 pb->bf_getreadbuffer == NULL ||
553 pb->bf_getsegcount == NULL )
554 {
555 PyErr_BadArgument();
556 return -1;
557 }
558 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
559 {
560 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000561 PyErr_SetString(PyExc_TypeError,
562 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000563 return -1;
564 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000565 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000566 return -1;
567 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000568 return -1;
569
570 if ( left < 0 )
571 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000572 else if ( left > size )
573 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000574 if ( right < left )
575 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000576 else if ( right > size )
577 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000578 slice_len = right - left;
579
580 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000581 PyErr_SetString(
582 PyExc_TypeError,
583 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000584 return -1;
585 }
586
587 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000588 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000589
590 return 0;
591}
592
593/* Buffer methods */
594
Martin v. Löwis18e16552006-02-15 17:27:45 +0000595static Py_ssize_t
596buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000597{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000598 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000599 if ( idx != 0 ) {
600 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000601 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000602 return -1;
603 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000604 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000605 return -1;
606 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000607}
608
Martin v. Löwis18e16552006-02-15 17:27:45 +0000609static Py_ssize_t
610buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000611{
Brett Cannonde3b0522006-06-08 17:00:45 +0000612 Py_ssize_t size;
613
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000614 if ( self->b_readonly )
615 {
616 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
617 return -1;
618 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000619
620 if ( idx != 0 ) {
621 PyErr_SetString(PyExc_SystemError,
622 "accessing non-existent buffer segment");
623 return -1;
624 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000625 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000626 return -1;
627 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000628}
629
Martin v. Löwis18e16552006-02-15 17:27:45 +0000630static Py_ssize_t
631buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000632{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000633 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000634 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000635 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000636 return -1;
637 if (lenp)
638 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000639 return 1;
640}
641
Martin v. Löwis18e16552006-02-15 17:27:45 +0000642static Py_ssize_t
643buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000644{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000645 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000646 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000647 if ( idx != 0 ) {
648 PyErr_SetString(PyExc_SystemError,
649 "accessing non-existent buffer segment");
650 return -1;
651 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000652 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000653 return -1;
654 *pp = (const char *)ptr;
655 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000656}
657
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000658static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000659 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000660 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000661 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
662 (ssizeargfunc)buffer_item, /*sq_item*/
663 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
664 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
665 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000666};
667
668static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000669 (readbufferproc)buffer_getreadbuf,
670 (writebufferproc)buffer_getwritebuf,
671 (segcountproc)buffer_getsegcount,
672 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000673};
674
675PyTypeObject PyBuffer_Type = {
676 PyObject_HEAD_INIT(&PyType_Type)
677 0,
678 "buffer",
679 sizeof(PyBufferObject),
680 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000681 (destructor)buffer_dealloc, /* tp_dealloc */
682 0, /* tp_print */
683 0, /* tp_getattr */
684 0, /* tp_setattr */
685 (cmpfunc)buffer_compare, /* tp_compare */
686 (reprfunc)buffer_repr, /* tp_repr */
687 0, /* tp_as_number */
688 &buffer_as_sequence, /* tp_as_sequence */
689 0, /* tp_as_mapping */
690 (hashfunc)buffer_hash, /* tp_hash */
691 0, /* tp_call */
692 (reprfunc)buffer_str, /* tp_str */
693 PyObject_GenericGetAttr, /* tp_getattro */
694 0, /* tp_setattro */
695 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000696 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000697 buffer_doc, /* tp_doc */
698 0, /* tp_traverse */
699 0, /* tp_clear */
700 0, /* tp_richcompare */
701 0, /* tp_weaklistoffset */
702 0, /* tp_iter */
703 0, /* tp_iternext */
704 0, /* tp_methods */
705 0, /* tp_members */
706 0, /* tp_getset */
707 0, /* tp_base */
708 0, /* tp_dict */
709 0, /* tp_descr_get */
710 0, /* tp_descr_set */
711 0, /* tp_dictoffset */
712 0, /* tp_init */
713 0, /* tp_alloc */
714 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000715};