blob: 88c0e417fee17af9fb105631eb1937e1c9516cf2 [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;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000430 ob = PyString_FromStringAndSize(NULL, size * count);
431 if ( ob == NULL )
432 return NULL;
433
434 p = PyString_AS_STRING(ob);
435 while ( count-- )
436 {
437 memcpy(p, ptr, size);
438 p += size;
439 }
440
441 /* there is an extra byte in the string object, so this is safe */
442 *p = '\0';
443
444 return ob;
445}
446
447static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000448buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000449{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000450 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000451 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000452 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000453 return NULL;
454 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000455 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
456 return NULL;
457 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000458 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000459}
460
461static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000462buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000463{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000464 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000465 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000466 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000467 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000468 if ( left < 0 )
469 left = 0;
470 if ( right < 0 )
471 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000472 if ( right > size )
473 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000474 if ( right < left )
475 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000476 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000477 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000478}
479
480static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000481buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000482{
483 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000484 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000485 Py_ssize_t size;
486 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000487
488 if ( self->b_readonly ) {
489 PyErr_SetString(PyExc_TypeError,
490 "buffer is read-only");
491 return -1;
492 }
493
Brett Cannonde3b0522006-06-08 17:00:45 +0000494 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000495 return -1;
496
497 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000498 PyErr_SetString(PyExc_IndexError,
499 "buffer assignment index out of range");
500 return -1;
501 }
502
503 pb = other ? other->ob_type->tp_as_buffer : NULL;
504 if ( pb == NULL ||
505 pb->bf_getreadbuffer == NULL ||
506 pb->bf_getsegcount == NULL )
507 {
508 PyErr_BadArgument();
509 return -1;
510 }
511 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
512 {
513 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000514 PyErr_SetString(PyExc_TypeError,
515 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000516 return -1;
517 }
518
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000519 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000520 return -1;
521 if ( count != 1 ) {
522 PyErr_SetString(PyExc_TypeError,
523 "right operand must be a single byte");
524 return -1;
525 }
526
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000527 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000528 return 0;
529}
530
531static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000532buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000533{
534 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000535 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000536 Py_ssize_t size;
537 Py_ssize_t slice_len;
538 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000539
540 if ( self->b_readonly ) {
541 PyErr_SetString(PyExc_TypeError,
542 "buffer is read-only");
543 return -1;
544 }
545
546 pb = other ? other->ob_type->tp_as_buffer : NULL;
547 if ( pb == NULL ||
548 pb->bf_getreadbuffer == NULL ||
549 pb->bf_getsegcount == NULL )
550 {
551 PyErr_BadArgument();
552 return -1;
553 }
554 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
555 {
556 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000557 PyErr_SetString(PyExc_TypeError,
558 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000559 return -1;
560 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000561 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000562 return -1;
563 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000564 return -1;
565
566 if ( left < 0 )
567 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000568 else if ( left > size )
569 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000570 if ( right < left )
571 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000572 else if ( right > size )
573 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000574 slice_len = right - left;
575
576 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000577 PyErr_SetString(
578 PyExc_TypeError,
579 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000580 return -1;
581 }
582
583 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000584 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000585
586 return 0;
587}
588
589/* Buffer methods */
590
Martin v. Löwis18e16552006-02-15 17:27:45 +0000591static Py_ssize_t
592buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000593{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000594 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000595 if ( idx != 0 ) {
596 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000597 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000598 return -1;
599 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000600 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000601 return -1;
602 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000603}
604
Martin v. Löwis18e16552006-02-15 17:27:45 +0000605static Py_ssize_t
606buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000607{
Brett Cannonde3b0522006-06-08 17:00:45 +0000608 Py_ssize_t size;
609
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000610 if ( self->b_readonly )
611 {
612 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
613 return -1;
614 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000615
616 if ( idx != 0 ) {
617 PyErr_SetString(PyExc_SystemError,
618 "accessing non-existent buffer segment");
619 return -1;
620 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000621 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000622 return -1;
623 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000624}
625
Martin v. Löwis18e16552006-02-15 17:27:45 +0000626static Py_ssize_t
627buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000628{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000629 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000630 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000631 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000632 return -1;
633 if (lenp)
634 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000635 return 1;
636}
637
Martin v. Löwis18e16552006-02-15 17:27:45 +0000638static Py_ssize_t
639buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000640{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000641 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000642 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000643 if ( idx != 0 ) {
644 PyErr_SetString(PyExc_SystemError,
645 "accessing non-existent buffer segment");
646 return -1;
647 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000648 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000649 return -1;
650 *pp = (const char *)ptr;
651 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000652}
653
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000654static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000655 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000656 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000657 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
658 (ssizeargfunc)buffer_item, /*sq_item*/
659 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
660 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
661 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000662};
663
664static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000665 (readbufferproc)buffer_getreadbuf,
666 (writebufferproc)buffer_getwritebuf,
667 (segcountproc)buffer_getsegcount,
668 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000669};
670
671PyTypeObject PyBuffer_Type = {
672 PyObject_HEAD_INIT(&PyType_Type)
673 0,
674 "buffer",
675 sizeof(PyBufferObject),
676 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000677 (destructor)buffer_dealloc, /* tp_dealloc */
678 0, /* tp_print */
679 0, /* tp_getattr */
680 0, /* tp_setattr */
681 (cmpfunc)buffer_compare, /* tp_compare */
682 (reprfunc)buffer_repr, /* tp_repr */
683 0, /* tp_as_number */
684 &buffer_as_sequence, /* tp_as_sequence */
685 0, /* tp_as_mapping */
686 (hashfunc)buffer_hash, /* tp_hash */
687 0, /* tp_call */
688 (reprfunc)buffer_str, /* tp_str */
689 PyObject_GenericGetAttr, /* tp_getattro */
690 0, /* tp_setattro */
691 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000692 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000693 buffer_doc, /* tp_doc */
694 0, /* tp_traverse */
695 0, /* tp_clear */
696 0, /* tp_richcompare */
697 0, /* tp_weaklistoffset */
698 0, /* tp_iter */
699 0, /* tp_iternext */
700 0, /* tp_methods */
701 0, /* tp_members */
702 0, /* tp_getset */
703 0, /* tp_base */
704 0, /* tp_dict */
705 0, /* tp_descr_get */
706 0, /* tp_descr_set */
707 0, /* tp_dictoffset */
708 0, /* tp_init */
709 0, /* tp_alloc */
710 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000711};