blob: 5f3c7a9eeb4affb891a8e5179aaaf535374b4bf1 [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,
Brett Cannonde3b0522006-06-08 17:00:45 +000022 ANY_BUFFER,
23};
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
475static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000476buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000477{
478 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000479 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000480 Py_ssize_t size;
481 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000482
483 if ( self->b_readonly ) {
484 PyErr_SetString(PyExc_TypeError,
485 "buffer is read-only");
486 return -1;
487 }
488
Brett Cannonde3b0522006-06-08 17:00:45 +0000489 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000490 return -1;
491
492 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000493 PyErr_SetString(PyExc_IndexError,
494 "buffer assignment index out of range");
495 return -1;
496 }
497
498 pb = other ? other->ob_type->tp_as_buffer : NULL;
499 if ( pb == NULL ||
500 pb->bf_getreadbuffer == NULL ||
501 pb->bf_getsegcount == NULL )
502 {
503 PyErr_BadArgument();
504 return -1;
505 }
506 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
507 {
508 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000509 PyErr_SetString(PyExc_TypeError,
510 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000511 return -1;
512 }
513
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000514 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000515 return -1;
516 if ( count != 1 ) {
517 PyErr_SetString(PyExc_TypeError,
518 "right operand must be a single byte");
519 return -1;
520 }
521
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000522 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000523 return 0;
524}
525
526static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000527buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000528{
529 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000530 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000531 Py_ssize_t size;
532 Py_ssize_t slice_len;
533 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000534
535 if ( self->b_readonly ) {
536 PyErr_SetString(PyExc_TypeError,
537 "buffer is read-only");
538 return -1;
539 }
540
541 pb = other ? other->ob_type->tp_as_buffer : NULL;
542 if ( pb == NULL ||
543 pb->bf_getreadbuffer == NULL ||
544 pb->bf_getsegcount == NULL )
545 {
546 PyErr_BadArgument();
547 return -1;
548 }
549 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
550 {
551 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000552 PyErr_SetString(PyExc_TypeError,
553 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000554 return -1;
555 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000556 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000557 return -1;
558 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000559 return -1;
560
561 if ( left < 0 )
562 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000563 else if ( left > size )
564 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000565 if ( right < left )
566 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000567 else if ( right > size )
568 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000569 slice_len = right - left;
570
571 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000572 PyErr_SetString(
573 PyExc_TypeError,
574 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000575 return -1;
576 }
577
578 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000579 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000580
581 return 0;
582}
583
584/* Buffer methods */
585
Martin v. Löwis18e16552006-02-15 17:27:45 +0000586static Py_ssize_t
587buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000588{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000589 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000590 if ( idx != 0 ) {
591 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000592 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000593 return -1;
594 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000595 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000596 return -1;
597 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000598}
599
Martin v. Löwis18e16552006-02-15 17:27:45 +0000600static Py_ssize_t
601buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000602{
Brett Cannonde3b0522006-06-08 17:00:45 +0000603 Py_ssize_t size;
604
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000605 if ( self->b_readonly )
606 {
607 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
608 return -1;
609 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000610
611 if ( idx != 0 ) {
612 PyErr_SetString(PyExc_SystemError,
613 "accessing non-existent buffer segment");
614 return -1;
615 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000616 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000617 return -1;
618 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000619}
620
Martin v. Löwis18e16552006-02-15 17:27:45 +0000621static Py_ssize_t
622buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000623{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000624 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000625 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000626 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000627 return -1;
628 if (lenp)
629 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000630 return 1;
631}
632
Martin v. Löwis18e16552006-02-15 17:27:45 +0000633static Py_ssize_t
634buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000635{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000636 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000637 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000638 if ( idx != 0 ) {
639 PyErr_SetString(PyExc_SystemError,
640 "accessing non-existent buffer segment");
641 return -1;
642 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000643 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000644 return -1;
645 *pp = (const char *)ptr;
646 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000647}
648
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000649static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000650 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000651 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000652 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
653 (ssizeargfunc)buffer_item, /*sq_item*/
654 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
655 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
656 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000657};
658
659static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000660 (readbufferproc)buffer_getreadbuf,
661 (writebufferproc)buffer_getwritebuf,
662 (segcountproc)buffer_getsegcount,
663 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000664};
665
666PyTypeObject PyBuffer_Type = {
667 PyObject_HEAD_INIT(&PyType_Type)
668 0,
669 "buffer",
670 sizeof(PyBufferObject),
671 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000672 (destructor)buffer_dealloc, /* tp_dealloc */
673 0, /* tp_print */
674 0, /* tp_getattr */
675 0, /* tp_setattr */
676 (cmpfunc)buffer_compare, /* tp_compare */
677 (reprfunc)buffer_repr, /* tp_repr */
678 0, /* tp_as_number */
679 &buffer_as_sequence, /* tp_as_sequence */
680 0, /* tp_as_mapping */
681 (hashfunc)buffer_hash, /* tp_hash */
682 0, /* tp_call */
683 (reprfunc)buffer_str, /* tp_str */
684 PyObject_GenericGetAttr, /* tp_getattro */
685 0, /* tp_setattro */
686 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000687 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000688 buffer_doc, /* tp_doc */
689 0, /* tp_traverse */
690 0, /* tp_clear */
691 0, /* tp_richcompare */
692 0, /* tp_weaklistoffset */
693 0, /* tp_iter */
694 0, /* tp_iternext */
695 0, /* tp_methods */
696 0, /* tp_members */
697 0, /* tp_getset */
698 0, /* tp_base */
699 0, /* tp_dict */
700 0, /* tp_descr_get */
701 0, /* tp_descr_set */
702 0, /* tp_dictoffset */
703 0, /* tp_init */
704 0, /* tp_alloc */
705 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000706};