blob: e307aabf69cf473a61b222ce14321305bf8684e0 [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
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000018static int
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000019get_buf(PyBufferObject *self, PyBuffer *view, int flags)
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000020{
21 if (self->b_base == NULL) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000022 view->buf = self->b_ptr;
23 view->len = self->b_size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000024 }
25 else {
Martin v. Löwis18e16552006-02-15 17:27:45 +000026 Py_ssize_t count, offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000027 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000028 if ((*bp->bf_getbuffer)(self->b_base, view, flags) < 0) return 0;
29 count = view->len;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000030 /* apply constraints to the start/end */
31 if (self->b_offset > count)
32 offset = count;
33 else
34 offset = self->b_offset;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000035 view->buf = (char*)view->buf + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000036 if (self->b_size == Py_END_OF_BUFFER)
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000037 view->len = count;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000038 else
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000039 view->len = self->b_size;
40 if (offset + view->len > count)
41 view->len = count - offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000042 }
43 return 1;
44}
45
46
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000047static int
48buffer_getbuf(PyBufferObject *self, PyBuffer *view, int flags)
49{
50 if (view == NULL) return 0;
51 if (!get_buf(self, view, flags))
52 return -1;
53 return PyBuffer_FillInfo(view, view->buf, view->len, self->b_readonly, flags);
54}
55
56
57static void
58buffer_releasebuf(PyBufferObject *self, PyBuffer *view)
59{
60 /* No-op if there is no self->b_base */
61 if (self->b_base != NULL) {
62 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
63 if (bp->bf_releasebuffer != NULL) {
64 (*bp->bf_releasebuffer)(self->b_base, view);
65 }
66 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000067}
68
Guido van Rossum2e19bd71998-10-07 14:36:10 +000069static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000070buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000071 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000072{
73 PyBufferObject * b;
74
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000075 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +000076 PyErr_SetString(PyExc_ValueError,
77 "size must be zero or positive");
78 return NULL;
79 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +000080 if (offset < 0) {
81 PyErr_SetString(PyExc_ValueError,
82 "offset must be zero or positive");
83 return NULL;
84 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +000085
Guido van Rossum2e19bd71998-10-07 14:36:10 +000086 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
87 if ( b == NULL )
88 return NULL;
89
90 Py_XINCREF(base);
91 b->b_base = base;
92 b->b_ptr = ptr;
93 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000094 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000095 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000096 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000097
98 return (PyObject *) b;
99}
100
101static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000102buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000103{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000104 if (offset < 0) {
105 PyErr_SetString(PyExc_ValueError,
106 "offset must be zero or positive");
107 return NULL;
108 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000109 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000110 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000111 PyBufferObject *b = (PyBufferObject *)base;
112 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000113 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000114 if (base_size < 0)
115 base_size = 0;
116 if (size == Py_END_OF_BUFFER || size > base_size)
117 size = base_size;
118 }
119 offset += b->b_offset;
120 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000121 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000122 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000123}
124
125
126PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000127PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000128{
129 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
130
131 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000132 pb->bf_getbuffer == NULL) {
133 PyErr_SetString(PyExc_TypeError, "buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000134 return NULL;
135 }
136
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000137 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000138}
139
140PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000141PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000142{
143 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
144
145 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000146 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000147 PyErr_SetString(PyExc_TypeError, "buffer object expected");
148 return NULL;
149 }
150
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000151 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000152}
153
154PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000155PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000156{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000157 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000158}
159
160PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000161PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000162{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000163 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000164}
165
166PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000167PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000168{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000169 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000170 PyBufferObject * b;
171
Fred Drake4574f231999-08-04 13:08:19 +0000172 if (size < 0) {
173 PyErr_SetString(PyExc_ValueError,
174 "size must be zero or positive");
175 return NULL;
176 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000177 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000178 /* Inline PyObject_New */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000179 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Moshe Zadkacf703f02000-08-04 15:36:13 +0000180 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000181 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000182 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000183
184 b->b_base = NULL;
185 b->b_ptr = (void *)(b + 1);
186 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000187 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000188 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000189 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000190
Moshe Zadkacf703f02000-08-04 15:36:13 +0000191 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000192}
193
194/* Methods */
195
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000196static PyObject *
197buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
198{
199 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000200 Py_ssize_t offset = 0;
201 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000202
Georg Brandl02c42872005-08-26 06:42:30 +0000203 if (!_PyArg_NoKeywords("buffer()", kw))
204 return NULL;
205
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000206 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000207 return NULL;
208 return PyBuffer_FromObject(ob, offset, size);
209}
210
211PyDoc_STRVAR(buffer_doc,
212"buffer(object [, offset[, size]])\n\
213\n\
214Create a new buffer object which references the given object.\n\
215The buffer will reference a slice of the target object from the\n\
216start of the object (or at the specified offset). The slice will\n\
217extend to the end of the target object (or with the specified size).");
218
219
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000220static void
Fred Drake79912472000-07-09 04:06:11 +0000221buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000222{
223 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000224 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000225}
226
227static int
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000228get_bufx(PyObject *obj, PyBuffer *view, int flags)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000229{
230 PyBufferProcs *bp;
231
232 if (PyBuffer_Check(obj)) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000233 if (!get_buf((PyBufferObject *)obj, view, flags)) {
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000234 PyErr_Clear();
235 return 0;
236 }
237 else
238 return 1;
239 }
240 bp = obj->ob_type->tp_as_buffer;
241 if (bp == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000242 bp->bf_getbuffer == NULL)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000243 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000244 if ((*bp->bf_getbuffer)(obj, view, PyBUF_SIMPLE) < 0)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000245 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000246 return 1;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000247}
248
249static PyObject *
250buffer_richcompare(PyObject *self, PyObject *other, int op)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000251{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000252 void *p1, *p2;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000253 Py_ssize_t len1, len2, min_len;
254 int cmp, ok;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000255 PyBuffer v1, v2;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000256
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000257 ok = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000258 if (!get_bufx(self, &v1, PyBUF_SIMPLE))
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000259 ok = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000260 if (!get_bufx(other, &v2, PyBUF_SIMPLE)) {
261 if (ok) PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000262 ok = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000263 }
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000264 if (!ok) {
265 /* If we can't get the buffers,
266 == and != are still defined
267 (and the objects are unequal) */
268 PyObject *result;
269 if (op == Py_EQ)
270 result = Py_False;
271 else if (op == Py_NE)
272 result = Py_True;
273 else
274 result = Py_NotImplemented;
275 Py_INCREF(result);
276 return result;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000277 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000278 len1 = v1.len;
279 len2 = v2.len;
280 p1 = v1.buf;
281 p2 = v2.buf;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000282 min_len = (len1 < len2) ? len1 : len2;
283 cmp = memcmp(p1, p2, min_len);
284 if (cmp == 0)
285 cmp = (len1 < len2) ? -1 :
286 (len1 > len2) ? 1 : 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000287 PyObject_ReleaseBuffer((PyObject *)self, &v1);
288 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000289 return Py_CmpToRich(op, cmp);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000290}
291
292static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000293buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000294{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000295 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000296
297 if ( self->b_base == NULL )
Walter Dörwald1ab83302007-05-18 17:15:44 +0000298 return PyUnicode_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000299 status,
300 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000301 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000302 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000303 else
Walter Dörwald1ab83302007-05-18 17:15:44 +0000304 return PyUnicode_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000305 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000306 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000307 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000308 self->b_size,
309 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000310 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000311}
312
313static long
Fred Drake79912472000-07-09 04:06:11 +0000314buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000315{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000316 PyBuffer view;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000317 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000318 register unsigned char *p;
319 register long x;
320
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000321 if ( self->b_hash != -1 )
322 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000323
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000324 if (!get_buf(self, &view, PyBUF_SIMPLE))
325 return -1;
326 if (!(self->b_readonly)) {
327 PyErr_SetString(PyExc_TypeError,
328 "writable buffers are not hashable");
329 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000330 return -1;
331 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000332
333 p = (unsigned char *) view.buf;
334 len = view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000335 x = *p << 7;
336 while (--len >= 0)
337 x = (1000003*x) ^ *p++;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000338 x ^= view.len;
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;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000342 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000343 return x;
344}
345
346static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000347buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000348{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000349 PyBuffer view;
350 PyObject *res;
351
352 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000353 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000354 res = PyString_FromStringAndSize((const char *)view.buf, view.len);
355 PyObject_ReleaseBuffer((PyObject *)self, &view);
356 return res;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000357}
358
359/* Sequence methods */
360
Martin v. Löwis18e16552006-02-15 17:27:45 +0000361static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000362buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000363{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000364 PyBuffer view;
365
366 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000367 return -1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000368 PyObject_ReleaseBuffer((PyObject *)self, &view);
369 return view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000370}
371
372static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000373buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000374{
375 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000376 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000377 PyObject *ob;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000378 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000379
380 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000381 pb->bf_getbuffer == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000382 {
383 PyErr_BadArgument();
384 return NULL;
385 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000386
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000387 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000388 return NULL;
389
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000390 /* optimize special case */
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000391 /* XXX bad idea type-wise */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000392 if ( view.len == 0 ) {
393 PyObject_ReleaseBuffer((PyObject *)self, &view);
394 Py_INCREF(other);
395 return other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000396 }
397
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000398 if (PyObject_GetBuffer((PyObject *)other, &view2, PyBUF_SIMPLE) < 0) {
399 PyObject_ReleaseBuffer((PyObject *)self, &view);
400 return NULL;
401 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000402
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000403 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000404 ob = PyBytes_FromStringAndSize(NULL, view.len+view2.len);
405 if ( ob == NULL ) {
406 PyObject_ReleaseBuffer((PyObject *)self, &view);
407 PyObject_ReleaseBuffer(other, &view2);
Neal Norwitz7c460742005-12-18 08:02:38 +0000408 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000409 }
410 p = PyBytes_AS_STRING(ob);
411 memcpy(p, view.buf, view.len);
412 memcpy(p + view.len, view2.buf, view2.len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000413
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000414 PyObject_ReleaseBuffer((PyObject *)self, &view);
415 PyObject_ReleaseBuffer(other, &view2);
416 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000417}
418
419static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000420buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000421{
422 PyObject *ob;
423 register char *p;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000424 PyBuffer view;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000425
426 if ( count < 0 )
427 count = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000428 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000429 return NULL;
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000430 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000431 ob = PyBytes_FromStringAndSize(NULL, view.len * count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000432 if ( ob == NULL )
433 return NULL;
434
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000435 p = PyBytes_AS_STRING(ob);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000436 while ( count-- )
437 {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000438 memcpy(p, view.buf, view.len);
439 p += view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000440 }
441
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000442 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000443 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{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000449 PyBuffer view;
450 PyObject *ob;
451
452 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000453 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000454 if ( idx < 0 || idx >= view.len ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000455 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
456 return NULL;
457 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000458 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
459 PyObject_ReleaseBuffer((PyObject *)self, &view);
460 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000461}
462
463static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000464buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000465{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000466 PyObject *ob;
467 PyBuffer view;
468 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000469 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000470 if ( left < 0 )
471 left = 0;
472 if ( right < 0 )
473 right = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000474 if ( right > view.len )
475 right = view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000476 if ( right < left )
477 right = left;
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000478 /* XXX(nnorwitz): is it possible to access unitialized memory? */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000479 ob = PyBytes_FromStringAndSize((char *)view.buf + left,
480 right - left);
481 PyObject_ReleaseBuffer((PyObject *)self, &view);
482 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000483}
484
Thomas Woutersed03b412007-08-28 21:37:11 +0000485static PyObject *
486buffer_subscript(PyBufferObject *self, PyObject *item)
487{
488 PyBuffer view;
489 PyObject *ob;
490
491 if (!get_buf(self, &view, PyBUF_SIMPLE))
492 return NULL;
493 if (PyIndex_Check(item)) {
494 Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
495
496 if (idx == -1 && PyErr_Occurred())
497 return NULL;
498 if (idx < 0)
499 idx += view.len;
500 if ( idx < 0 || idx >= view.len ) {
501 PyErr_SetString(PyExc_IndexError,
502 "buffer index out of range");
503 return NULL;
504 }
505 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
506 PyObject_ReleaseBuffer((PyObject *)self, &view);
507 return ob;
508 }
509 else if (PySlice_Check(item)) {
510 Py_ssize_t start, stop, step, slicelength, cur, i;
511
512 if (PySlice_GetIndicesEx((PySliceObject*)item, view.len,
513 &start, &stop, &step, &slicelength) < 0) {
514 PyObject_ReleaseBuffer((PyObject *)self, &view);
515 return NULL;
516 }
517
518 if (slicelength <= 0) {
519 PyObject_ReleaseBuffer((PyObject *)self, &view);
520 return PyBytes_FromStringAndSize("", 0);
521 }
522 else if (step == 1) {
523 ob = PyBytes_FromStringAndSize((char *)view.buf +
524 start, stop - start);
525 PyObject_ReleaseBuffer((PyObject *)self, &view);
526 return ob;
527 }
528 else {
529 char *source_buf = (char *)view.buf;
530 char *result_buf = (char *)PyMem_Malloc(slicelength);
531
532 if (result_buf == NULL)
533 return PyErr_NoMemory();
534
535 for (cur = start, i = 0; i < slicelength;
536 cur += step, i++) {
537 result_buf[i] = source_buf[cur];
538 }
539
540 ob = PyBytes_FromStringAndSize(result_buf,
541 slicelength);
542 PyMem_Free(result_buf);
543 PyObject_ReleaseBuffer((PyObject *)self, &view);
544 return ob;
545 }
546 }
547 else {
548 PyErr_SetString(PyExc_TypeError,
549 "sequence index must be integer");
550 return NULL;
551 }
552}
553
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000554static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000555buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000556{
557 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000558 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000559
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000560 if (!get_buf(self, &view, PyBUF_SIMPLE))
561 return -1;
562
563 if ( self->b_readonly || view.readonly ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000564 PyErr_SetString(PyExc_TypeError,
565 "buffer is read-only");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000566 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000567 return -1;
568 }
569
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000570 if (idx < 0 || idx >= view.len) {
571 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000572 PyErr_SetString(PyExc_IndexError,
573 "buffer assignment index out of range");
574 return -1;
575 }
576
577 pb = other ? other->ob_type->tp_as_buffer : NULL;
578 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000579 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000580 PyErr_BadArgument();
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000581 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000582 return -1;
583 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000584
585 if (PyObject_GetBuffer(other, &view2, PyBUF_SIMPLE) < 0) {
586 PyObject_ReleaseBuffer((PyObject *)self, &view);
587 return -1;
588 }
589 if ( view.len != 1 ) {
590 PyObject_ReleaseBuffer((PyObject *)self, &view);
591 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000592 PyErr_SetString(PyExc_TypeError,
593 "right operand must be a single byte");
594 return -1;
595 }
596
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000597 ((char *)(view.buf))[idx] = *((char *)(view2.buf));
598 PyObject_ReleaseBuffer((PyObject *)self, &view);
599 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000600 return 0;
601}
602
603static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000604buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000605{
606 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000607 PyBuffer v1, v2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000608 Py_ssize_t slice_len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000609
610 pb = other ? other->ob_type->tp_as_buffer : NULL;
611 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000612 pb->bf_getbuffer == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000613 {
614 PyErr_BadArgument();
615 return -1;
616 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000617 if (!get_buf(self, &v1, PyBUF_SIMPLE))
618 return -1;
619
620 if ( self->b_readonly || v1.readonly) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000621 PyErr_SetString(PyExc_TypeError,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000622 "buffer is read-only");
623 PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000624 return -1;
625 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000626
627 if ((*pb->bf_getbuffer)(other, &v2, PyBUF_SIMPLE) < 0) {
628 PyObject_ReleaseBuffer((PyObject *)self, &v1);
629 return -1;
630 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000631
632 if ( left < 0 )
633 left = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000634 else if ( left > v1.len )
635 left = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000636 if ( right < left )
637 right = left;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000638 else if ( right > v1.len )
639 right = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000640 slice_len = right - left;
641
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000642 if ( v2.len != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000643 PyErr_SetString(
644 PyExc_TypeError,
645 "right operand length must match slice length");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000646 PyObject_ReleaseBuffer((PyObject *)self, &v1);
647 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000648 return -1;
649 }
650
651 if ( slice_len )
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000652 memcpy((char *)v1.buf + left, v2.buf, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000653
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000654 PyObject_ReleaseBuffer((PyObject *)self, &v1);
655 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000656 return 0;
657}
658
Thomas Woutersed03b412007-08-28 21:37:11 +0000659static int
660buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
661{
662 PyBuffer v1;
663
664 if (!get_buf(self, &v1, PyBUF_SIMPLE))
665 return -1;
666 if (self->b_readonly || v1.readonly) {
667 PyErr_SetString(PyExc_TypeError,
668 "buffer is read-only");
669 PyObject_ReleaseBuffer((PyObject *)self, &v1);
670 return -1;
671 }
672 if (PyIndex_Check(item)) {
673 Py_ssize_t idx = PyNumber_AsSsize_t(item, PyExc_IndexError);
674 if (idx == -1 && PyErr_Occurred())
675 return -1;
676 if (idx < 0)
677 idx += v1.len;
678 PyObject_ReleaseBuffer((PyObject *)self, &v1);
679 return buffer_ass_item(self, idx, value);
680 }
681 else if (PySlice_Check(item)) {
682 Py_ssize_t start, stop, step, slicelength;
683 PyBuffer v2;
684 PyBufferProcs *pb;
685
686 if (PySlice_GetIndicesEx((PySliceObject *)item, v1.len,
687 &start, &stop, &step, &slicelength) < 0) {
688 PyObject_ReleaseBuffer((PyObject *)self, &v1);
689 return -1;
690 }
691
692 pb = value ? value->ob_type->tp_as_buffer : NULL;
693 if (pb == NULL ||
694 pb->bf_getbuffer == NULL) {
695 PyObject_ReleaseBuffer((PyObject *)self, &v1);
696 PyErr_BadArgument();
697 return -1;
698 }
699 if ((*pb->bf_getbuffer)(value, &v2, PyBUF_SIMPLE) < 0) {
700 PyObject_ReleaseBuffer((PyObject *)self, &v1);
701 return -1;
702 }
703
704 if (v2.len != slicelength) {
705 PyObject_ReleaseBuffer((PyObject *)self, &v1);
706 PyObject_ReleaseBuffer(value, &v2);
707 PyErr_SetString(PyExc_TypeError, "right operand"
708 " length must match slice length");
709 return -1;
710 }
711
712 if (slicelength == 0)
713 /* nothing to do */;
714 else if (step == 1)
715 memcpy((char *)v1.buf + start, v2.buf, slicelength);
716 else {
717 Py_ssize_t cur, i;
718
719 for (cur = start, i = 0; i < slicelength;
720 cur += step, i++) {
721 ((char *)v1.buf)[cur] = ((char *)v2.buf)[i];
722 }
723 }
724 PyObject_ReleaseBuffer((PyObject *)self, &v1);
725 PyObject_ReleaseBuffer(value, &v2);
726 return 0;
727 } else {
728 PyErr_SetString(PyExc_TypeError,
729 "buffer indices must be integers");
730 PyObject_ReleaseBuffer((PyObject *)self, &v1);
731 return -1;
732 }
733}
734
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000735/* Buffer methods */
736
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000737static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000738 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000739 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000740 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
741 (ssizeargfunc)buffer_item, /*sq_item*/
742 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
743 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
744 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000745};
746
Thomas Woutersed03b412007-08-28 21:37:11 +0000747static PyMappingMethods buffer_as_mapping = {
748 (lenfunc)buffer_length,
749 (binaryfunc)buffer_subscript,
750 (objobjargproc)buffer_ass_subscript,
751};
752
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000753static PyBufferProcs buffer_as_buffer = {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000754 (getbufferproc)buffer_getbuf,
755 (releasebufferproc)buffer_releasebuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000756};
757
758PyTypeObject PyBuffer_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000759 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000760 "buffer",
761 sizeof(PyBufferObject),
762 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000763 (destructor)buffer_dealloc, /* tp_dealloc */
764 0, /* tp_print */
765 0, /* tp_getattr */
766 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000767 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000768 (reprfunc)buffer_repr, /* tp_repr */
769 0, /* tp_as_number */
770 &buffer_as_sequence, /* tp_as_sequence */
Thomas Woutersed03b412007-08-28 21:37:11 +0000771 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000772 (hashfunc)buffer_hash, /* tp_hash */
773 0, /* tp_call */
774 (reprfunc)buffer_str, /* tp_str */
775 PyObject_GenericGetAttr, /* tp_getattro */
776 0, /* tp_setattro */
777 &buffer_as_buffer, /* tp_as_buffer */
778 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000779 buffer_doc, /* tp_doc */
780 0, /* tp_traverse */
781 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000782 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000783 0, /* tp_weaklistoffset */
784 0, /* tp_iter */
785 0, /* tp_iternext */
786 0, /* tp_methods */
787 0, /* tp_members */
788 0, /* tp_getset */
789 0, /* tp_base */
790 0, /* tp_dict */
791 0, /* tp_descr_get */
792 0, /* tp_descr_set */
793 0, /* tp_dictoffset */
794 0, /* tp_init */
795 0, /* tp_alloc */
796 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000797};