blob: 37d9bcbb5a6ad7801b5c66b5a85a803a95b842c4 [file] [log] [blame]
Guido van Rossum2e19bd71998-10-07 14:36:10 +00001
2/* Buffer object implementation */
3
4#include "Python.h"
5
6
7typedef struct {
8 PyObject_HEAD
9 PyObject *b_base;
10 void *b_ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +000011 Py_ssize_t b_size;
12 Py_ssize_t b_offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000013 int b_readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000014 long b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000015} PyBufferObject;
16
17
Brett Cannonde3b0522006-06-08 17:00:45 +000018enum buffer_t {
Brett Cannonc48b0e62006-06-09 17:05:48 +000019 READ_BUFFER,
20 WRITE_BUFFER,
21 CHAR_BUFFER,
Martin v. Löwisda587ab2007-06-08 17:29:20 +000022 ANY_BUFFER
Brett Cannonde3b0522006-06-08 17:00:45 +000023};
24
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000025static int
Brett Cannonde3b0522006-06-08 17:00:45 +000026get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
27 enum buffer_t buffer_type)
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000028{
29 if (self->b_base == NULL) {
30 assert (ptr != NULL);
31 *ptr = self->b_ptr;
32 *size = self->b_size;
33 }
34 else {
Martin v. Löwis18e16552006-02-15 17:27:45 +000035 Py_ssize_t count, offset;
Skip Montanaro9a8ae8f2006-06-10 22:38:13 +000036 readbufferproc proc = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000037 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
38 if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
39 PyErr_SetString(PyExc_TypeError,
40 "single-segment buffer object expected");
41 return 0;
42 }
Brett Cannonc48b0e62006-06-09 17:05:48 +000043 if ((buffer_type == READ_BUFFER) ||
Brett Cannonde3b0522006-06-08 17:00:45 +000044 ((buffer_type == ANY_BUFFER) && self->b_readonly))
45 proc = bp->bf_getreadbuffer;
Brett Cannonc48b0e62006-06-09 17:05:48 +000046 else if ((buffer_type == WRITE_BUFFER) ||
Brett Cannonde3b0522006-06-08 17:00:45 +000047 (buffer_type == ANY_BUFFER))
48 proc = (readbufferproc)bp->bf_getwritebuffer;
Brett Cannonc48b0e62006-06-09 17:05:48 +000049 else if (buffer_type == CHAR_BUFFER) {
Brett Cannonde3b0522006-06-08 17:00:45 +000050 if (!PyType_HasFeature(self->ob_type,
51 Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
52 PyErr_SetString(PyExc_TypeError,
53 "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
54 return 0;
55 }
56 proc = (readbufferproc)bp->bf_getcharbuffer;
57 }
58 if (!proc) {
59 char *buffer_type_name;
60 switch (buffer_type) {
Brett Cannonc48b0e62006-06-09 17:05:48 +000061 case READ_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000062 buffer_type_name = "read";
63 break;
Brett Cannonc48b0e62006-06-09 17:05:48 +000064 case WRITE_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000065 buffer_type_name = "write";
66 break;
Brett Cannonc48b0e62006-06-09 17:05:48 +000067 case CHAR_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000068 buffer_type_name = "char";
69 break;
70 default:
71 buffer_type_name = "no";
72 break;
73 }
74 PyErr_Format(PyExc_TypeError,
75 "%s buffer type not available",
76 buffer_type_name);
77 return 0;
78 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000079 if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
80 return 0;
81 /* apply constraints to the start/end */
82 if (self->b_offset > count)
83 offset = count;
84 else
85 offset = self->b_offset;
Martin v. Löwis093c1002004-03-25 16:16:28 +000086 *(char **)ptr = *(char **)ptr + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000087 if (self->b_size == Py_END_OF_BUFFER)
88 *size = count;
89 else
90 *size = self->b_size;
91 if (offset + *size > count)
92 *size = count - offset;
93 }
94 return 1;
95}
96
97
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000099buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000100 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000101{
102 PyBufferObject * b;
103
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000104 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +0000105 PyErr_SetString(PyExc_ValueError,
106 "size must be zero or positive");
107 return NULL;
108 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000109 if (offset < 0) {
110 PyErr_SetString(PyExc_ValueError,
111 "offset must be zero or positive");
112 return NULL;
113 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +0000114
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000115 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116 if ( b == NULL )
117 return NULL;
118
119 Py_XINCREF(base);
120 b->b_base = base;
121 b->b_ptr = ptr;
122 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000123 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000124 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000125 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000126
127 return (PyObject *) b;
128}
129
130static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000131buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000132{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000133 if (offset < 0) {
134 PyErr_SetString(PyExc_ValueError,
135 "offset must be zero or positive");
136 return NULL;
137 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000138 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000139 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000140 PyBufferObject *b = (PyBufferObject *)base;
141 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000142 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000143 if (base_size < 0)
144 base_size = 0;
145 if (size == Py_END_OF_BUFFER || size > base_size)
146 size = base_size;
147 }
148 offset += b->b_offset;
149 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000150 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000151 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000152}
153
154
155PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000156PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000157{
158 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
159
160 if ( pb == NULL ||
161 pb->bf_getreadbuffer == NULL ||
162 pb->bf_getsegcount == NULL )
163 {
164 PyErr_SetString(PyExc_TypeError, "buffer object expected");
165 return NULL;
166 }
167
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000168 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000169}
170
171PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000172PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000173{
174 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
175
176 if ( pb == NULL ||
177 pb->bf_getwritebuffer == NULL ||
178 pb->bf_getsegcount == NULL )
179 {
180 PyErr_SetString(PyExc_TypeError, "buffer object expected");
181 return NULL;
182 }
183
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000184 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000185}
186
187PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000188PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000189{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000190 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000191}
192
193PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000194PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000196 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197}
198
199PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000200PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000201{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000202 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203 PyBufferObject * b;
204
Fred Drake4574f231999-08-04 13:08:19 +0000205 if (size < 0) {
206 PyErr_SetString(PyExc_ValueError,
207 "size must be zero or positive");
208 return NULL;
209 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000210 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000211 /* Inline PyObject_New */
Anthony Baxter377be112006-04-11 06:54:30 +0000212 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Moshe Zadkacf703f02000-08-04 15:36:13 +0000213 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000214 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000215 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000216
217 b->b_base = NULL;
218 b->b_ptr = (void *)(b + 1);
219 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000220 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000221 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000222 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000223
Moshe Zadkacf703f02000-08-04 15:36:13 +0000224 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000225}
226
227/* Methods */
228
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000229static PyObject *
230buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
231{
Georg Brandlf8f1fbd2008-03-25 11:59:51 +0000232 PyObject *ob;
233 Py_ssize_t offset = 0;
234 Py_ssize_t size = Py_END_OF_BUFFER;
235
Benjamin Peterson9f4f4812008-04-27 03:01:45 +0000236 if (PyErr_WarnPy3k("buffer() not supported in 3.x; "
Georg Brandld5b635f2008-03-25 08:29:14 +0000237 "use memoryview()", 1) < 0)
Georg Brandl80055f62008-03-25 07:56:27 +0000238 return NULL;
239
Georg Brandl02c42872005-08-26 06:42:30 +0000240 if (!_PyArg_NoKeywords("buffer()", kw))
241 return NULL;
242
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000243 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000244 return NULL;
245 return PyBuffer_FromObject(ob, offset, size);
246}
247
248PyDoc_STRVAR(buffer_doc,
249"buffer(object [, offset[, size]])\n\
250\n\
251Create a new buffer object which references the given object.\n\
252The buffer will reference a slice of the target object from the\n\
253start of the object (or at the specified offset). The slice will\n\
254extend to the end of the target object (or with the specified size).");
255
256
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000257static void
Fred Drake79912472000-07-09 04:06:11 +0000258buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000259{
260 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000261 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000262}
263
264static int
Fred Drake79912472000-07-09 04:06:11 +0000265buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000266{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000267 void *p1, *p2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000268 Py_ssize_t len_self, len_other, min_len;
269 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000270
Brett Cannonde3b0522006-06-08 17:00:45 +0000271 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000272 return -1;
Brett Cannonde3b0522006-06-08 17:00:45 +0000273 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000274 return -1;
275 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000276 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000277 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000278 if (cmp != 0)
Thomas Hellerab1049c2006-08-08 17:37:00 +0000279 return cmp < 0 ? -1 : 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000280 }
281 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
282}
283
284static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000285buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000286{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000287 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000288
289 if ( self->b_base == NULL )
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000290 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000291 status,
292 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000293 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000294 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000295 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000296 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000297 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000298 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000299 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000300 self->b_size,
301 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000302 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000303}
304
305static long
Fred Drake79912472000-07-09 04:06:11 +0000306buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000307{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000308 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000309 Py_ssize_t size;
310 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000311 register unsigned char *p;
312 register long x;
313
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000314 if ( self->b_hash != -1 )
315 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000316
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000317 /* XXX potential bugs here, a readonly buffer does not imply that the
318 * underlying memory is immutable. b_readonly is a necessary but not
319 * sufficient condition for a buffer to be hashable. Perhaps it would
320 * be better to only allow hashing if the underlying object is known to
321 * be immutable (e.g. PyString_Check() is true). Another idea would
322 * be to call tp_hash on the underlying object and see if it raises
323 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000324 if ( !self->b_readonly )
325 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000326 PyErr_SetString(PyExc_TypeError,
327 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000328 return -1;
329 }
330
Brett Cannonde3b0522006-06-08 17:00:45 +0000331 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000332 return -1;
333 p = (unsigned char *) ptr;
334 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000335 x = *p << 7;
336 while (--len >= 0)
337 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000338 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000339 if (x == -1)
340 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000341 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000342 return x;
343}
344
345static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000346buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000347{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000348 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000349 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000350 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000351 return NULL;
Anthony Baxter377be112006-04-11 06:54:30 +0000352 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000353}
354
355/* Sequence methods */
356
Martin v. Löwis18e16552006-02-15 17:27:45 +0000357static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000358buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000359{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000360 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000361 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000362 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000363 return -1;
364 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000365}
366
367static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000368buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000369{
370 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000371 void *ptr1, *ptr2;
372 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000373 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000374 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000375
376 if ( pb == NULL ||
377 pb->bf_getreadbuffer == NULL ||
378 pb->bf_getsegcount == NULL )
379 {
380 PyErr_BadArgument();
381 return NULL;
382 }
383 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
384 {
385 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000386 PyErr_SetString(PyExc_TypeError,
387 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000388 return NULL;
389 }
390
Brett Cannonde3b0522006-06-08 17:00:45 +0000391 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000392 return NULL;
393
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000394 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000395 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000396 {
397 Py_INCREF(other);
398 return other;
399 }
400
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000401 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000402 return NULL;
403
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000404 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000405 if ( ob == NULL )
406 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000407 p = PyString_AS_STRING(ob);
408 memcpy(p, ptr1, size);
409 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000410
411 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000412 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000413
414 return ob;
415}
416
417static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000418buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000419{
420 PyObject *ob;
421 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000422 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000423 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000424
425 if ( count < 0 )
426 count = 0;
Brett Cannonde3b0522006-06-08 17:00:45 +0000427 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000428 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000429 ob = PyString_FromStringAndSize(NULL, size * count);
430 if ( ob == NULL )
431 return NULL;
432
433 p = PyString_AS_STRING(ob);
434 while ( count-- )
435 {
436 memcpy(p, ptr, size);
437 p += size;
438 }
439
440 /* there is an extra byte in the string object, so this is safe */
441 *p = '\0';
442
443 return ob;
444}
445
446static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000447buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000448{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000449 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000450 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000451 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000452 return NULL;
453 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000454 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
455 return NULL;
456 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000457 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000458}
459
460static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000461buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000462{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000463 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000464 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000465 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000466 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000467 if ( left < 0 )
468 left = 0;
469 if ( right < 0 )
470 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000471 if ( right > size )
472 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000473 if ( right < left )
474 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000475 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000476 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000477}
478
Thomas Wouters3ccec682007-08-28 15:28:19 +0000479static PyObject *
480buffer_subscript(PyBufferObject *self, PyObject *item)
481{
482 void *p;
483 Py_ssize_t size;
484
485 if (!get_buf(self, &p, &size, ANY_BUFFER))
486 return NULL;
487 if (PyIndex_Check(item)) {
488 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
489 if (i == -1 && PyErr_Occurred())
490 return NULL;
491 if (i < 0)
492 i += size;
493 return buffer_item(self, i);
494 }
495 else if (PySlice_Check(item)) {
496 Py_ssize_t start, stop, step, slicelength, cur, i;
497
498 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
499 &start, &stop, &step, &slicelength) < 0) {
500 return NULL;
501 }
502
503 if (slicelength <= 0)
504 return PyString_FromStringAndSize("", 0);
505 else if (step == 1)
506 return PyString_FromStringAndSize((char *)p + start,
507 stop - start);
508 else {
509 PyObject *result;
510 char *source_buf = (char *)p;
511 char *result_buf = (char *)PyMem_Malloc(slicelength);
512
513 if (result_buf == NULL)
514 return PyErr_NoMemory();
515
516 for (cur = start, i = 0; i < slicelength;
517 cur += step, i++) {
518 result_buf[i] = source_buf[cur];
519 }
520
521 result = PyString_FromStringAndSize(result_buf,
522 slicelength);
523 PyMem_Free(result_buf);
524 return result;
525 }
526 }
527 else {
528 PyErr_SetString(PyExc_TypeError,
529 "sequence index must be integer");
530 return NULL;
531 }
532}
533
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000534static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000535buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000536{
537 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000538 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000539 Py_ssize_t size;
540 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000541
542 if ( self->b_readonly ) {
543 PyErr_SetString(PyExc_TypeError,
544 "buffer is read-only");
545 return -1;
546 }
547
Brett Cannonde3b0522006-06-08 17:00:45 +0000548 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000549 return -1;
550
551 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000552 PyErr_SetString(PyExc_IndexError,
553 "buffer assignment index out of range");
554 return -1;
555 }
556
557 pb = other ? other->ob_type->tp_as_buffer : NULL;
558 if ( pb == NULL ||
559 pb->bf_getreadbuffer == NULL ||
560 pb->bf_getsegcount == NULL )
561 {
562 PyErr_BadArgument();
563 return -1;
564 }
565 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
566 {
567 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000568 PyErr_SetString(PyExc_TypeError,
569 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000570 return -1;
571 }
572
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000573 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000574 return -1;
575 if ( count != 1 ) {
576 PyErr_SetString(PyExc_TypeError,
577 "right operand must be a single byte");
578 return -1;
579 }
580
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000581 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000582 return 0;
583}
584
585static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000586buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000587{
588 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000589 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000590 Py_ssize_t size;
591 Py_ssize_t slice_len;
592 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000593
594 if ( self->b_readonly ) {
595 PyErr_SetString(PyExc_TypeError,
596 "buffer is read-only");
597 return -1;
598 }
599
600 pb = other ? other->ob_type->tp_as_buffer : NULL;
601 if ( pb == NULL ||
602 pb->bf_getreadbuffer == NULL ||
603 pb->bf_getsegcount == NULL )
604 {
605 PyErr_BadArgument();
606 return -1;
607 }
608 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
609 {
610 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000611 PyErr_SetString(PyExc_TypeError,
612 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000613 return -1;
614 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000615 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000616 return -1;
617 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000618 return -1;
619
620 if ( left < 0 )
621 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000622 else if ( left > size )
623 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000624 if ( right < left )
625 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000626 else if ( right > size )
627 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000628 slice_len = right - left;
629
630 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000631 PyErr_SetString(
632 PyExc_TypeError,
633 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000634 return -1;
635 }
636
637 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000638 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000639
640 return 0;
641}
642
Thomas Wouters3ccec682007-08-28 15:28:19 +0000643static int
644buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
645{
646 PyBufferProcs *pb;
647 void *ptr1, *ptr2;
648 Py_ssize_t selfsize;
649 Py_ssize_t othersize;
650
651 if ( self->b_readonly ) {
652 PyErr_SetString(PyExc_TypeError,
653 "buffer is read-only");
654 return -1;
655 }
656
657 pb = value ? value->ob_type->tp_as_buffer : NULL;
658 if ( pb == NULL ||
659 pb->bf_getreadbuffer == NULL ||
660 pb->bf_getsegcount == NULL )
661 {
662 PyErr_BadArgument();
663 return -1;
664 }
665 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
666 {
667 /* ### use a different exception type/message? */
668 PyErr_SetString(PyExc_TypeError,
669 "single-segment buffer object expected");
670 return -1;
671 }
672 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
673 return -1;
674 if (PyIndex_Check(item)) {
675 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
676 if (i == -1 && PyErr_Occurred())
677 return -1;
678 if (i < 0)
679 i += selfsize;
680 return buffer_ass_item(self, i, value);
681 }
682 else if (PySlice_Check(item)) {
683 Py_ssize_t start, stop, step, slicelength;
684
685 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
686 &start, &stop, &step, &slicelength) < 0)
687 return -1;
688
Thomas Wouters3ccec682007-08-28 15:28:19 +0000689 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
690 return -1;
691
692 if (othersize != slicelength) {
693 PyErr_SetString(
694 PyExc_TypeError,
695 "right operand length must match slice length");
696 return -1;
697 }
698
699 if (slicelength == 0)
700 return 0;
701 else if (step == 1) {
702 memcpy((char *)ptr1 + start, ptr2, slicelength);
703 return 0;
704 }
705 else {
706 Py_ssize_t cur, i;
707
708 for (cur = start, i = 0; i < slicelength;
709 cur += step, i++) {
710 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
711 }
712
713 return 0;
714 }
715 } else {
716 PyErr_SetString(PyExc_TypeError,
717 "buffer indices must be integers");
718 return -1;
719 }
720}
721
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000722/* Buffer methods */
723
Martin v. Löwis18e16552006-02-15 17:27:45 +0000724static Py_ssize_t
725buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000726{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000727 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000728 if ( idx != 0 ) {
729 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000730 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000731 return -1;
732 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000733 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000734 return -1;
735 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000736}
737
Martin v. Löwis18e16552006-02-15 17:27:45 +0000738static Py_ssize_t
739buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000740{
Brett Cannonde3b0522006-06-08 17:00:45 +0000741 Py_ssize_t size;
742
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000743 if ( self->b_readonly )
744 {
745 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
746 return -1;
747 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000748
749 if ( idx != 0 ) {
750 PyErr_SetString(PyExc_SystemError,
751 "accessing non-existent buffer segment");
752 return -1;
753 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000754 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000755 return -1;
756 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000757}
758
Martin v. Löwis18e16552006-02-15 17:27:45 +0000759static Py_ssize_t
760buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000761{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000762 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000763 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000764 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000765 return -1;
766 if (lenp)
767 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000768 return 1;
769}
770
Martin v. Löwis18e16552006-02-15 17:27:45 +0000771static Py_ssize_t
772buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000773{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000774 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000775 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000776 if ( idx != 0 ) {
777 PyErr_SetString(PyExc_SystemError,
778 "accessing non-existent buffer segment");
779 return -1;
780 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000781 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000782 return -1;
783 *pp = (const char *)ptr;
784 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000785}
786
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000787static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000788 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000789 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000790 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
791 (ssizeargfunc)buffer_item, /*sq_item*/
792 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
793 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
794 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000795};
796
Thomas Wouters3ccec682007-08-28 15:28:19 +0000797static PyMappingMethods buffer_as_mapping = {
798 (lenfunc)buffer_length,
799 (binaryfunc)buffer_subscript,
800 (objobjargproc)buffer_ass_subscript,
801};
802
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000803static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000804 (readbufferproc)buffer_getreadbuf,
805 (writebufferproc)buffer_getwritebuf,
806 (segcountproc)buffer_getsegcount,
807 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000808};
809
810PyTypeObject PyBuffer_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000811 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000812 "buffer",
813 sizeof(PyBufferObject),
814 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000815 (destructor)buffer_dealloc, /* tp_dealloc */
816 0, /* tp_print */
817 0, /* tp_getattr */
818 0, /* tp_setattr */
819 (cmpfunc)buffer_compare, /* tp_compare */
820 (reprfunc)buffer_repr, /* tp_repr */
821 0, /* tp_as_number */
822 &buffer_as_sequence, /* tp_as_sequence */
Thomas Wouters3ccec682007-08-28 15:28:19 +0000823 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000824 (hashfunc)buffer_hash, /* tp_hash */
825 0, /* tp_call */
826 (reprfunc)buffer_str, /* tp_str */
827 PyObject_GenericGetAttr, /* tp_getattro */
828 0, /* tp_setattro */
829 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000830 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000831 buffer_doc, /* tp_doc */
832 0, /* tp_traverse */
833 0, /* tp_clear */
834 0, /* tp_richcompare */
835 0, /* tp_weaklistoffset */
836 0, /* tp_iter */
837 0, /* tp_iternext */
838 0, /* tp_methods */
839 0, /* tp_members */
840 0, /* tp_getset */
841 0, /* tp_base */
842 0, /* tp_dict */
843 0, /* tp_descr_get */
844 0, /* tp_descr_set */
845 0, /* tp_dictoffset */
846 0, /* tp_init */
847 0, /* tp_alloc */
848 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000849};