blob: c415013189fdf9e369269f29195d5a3acda11b2a [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
485static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000486buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000487{
488 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000489 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000490
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000491 if (!get_buf(self, &view, PyBUF_SIMPLE))
492 return -1;
493
494 if ( self->b_readonly || view.readonly ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000495 PyErr_SetString(PyExc_TypeError,
496 "buffer is read-only");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000497 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000498 return -1;
499 }
500
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000501 if (idx < 0 || idx >= view.len) {
502 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000503 PyErr_SetString(PyExc_IndexError,
504 "buffer assignment index out of range");
505 return -1;
506 }
507
508 pb = other ? other->ob_type->tp_as_buffer : NULL;
509 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000510 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000511 PyErr_BadArgument();
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000512 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000513 return -1;
514 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000515
516 if (PyObject_GetBuffer(other, &view2, PyBUF_SIMPLE) < 0) {
517 PyObject_ReleaseBuffer((PyObject *)self, &view);
518 return -1;
519 }
520 if ( view.len != 1 ) {
521 PyObject_ReleaseBuffer((PyObject *)self, &view);
522 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000523 PyErr_SetString(PyExc_TypeError,
524 "right operand must be a single byte");
525 return -1;
526 }
527
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000528 ((char *)(view.buf))[idx] = *((char *)(view2.buf));
529 PyObject_ReleaseBuffer((PyObject *)self, &view);
530 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000531 return 0;
532}
533
534static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000535buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000536{
537 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000538 PyBuffer v1, v2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000539 Py_ssize_t slice_len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000540
541 pb = other ? other->ob_type->tp_as_buffer : NULL;
542 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000543 pb->bf_getbuffer == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000544 {
545 PyErr_BadArgument();
546 return -1;
547 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000548 if (!get_buf(self, &v1, PyBUF_SIMPLE))
549 return -1;
550
551 if ( self->b_readonly || v1.readonly) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000552 PyErr_SetString(PyExc_TypeError,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000553 "buffer is read-only");
554 PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000555 return -1;
556 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000557
558 if ((*pb->bf_getbuffer)(other, &v2, PyBUF_SIMPLE) < 0) {
559 PyObject_ReleaseBuffer((PyObject *)self, &v1);
560 return -1;
561 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000562
563 if ( left < 0 )
564 left = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000565 else if ( left > v1.len )
566 left = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000567 if ( right < left )
568 right = left;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000569 else if ( right > v1.len )
570 right = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000571 slice_len = right - left;
572
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000573 if ( v2.len != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000574 PyErr_SetString(
575 PyExc_TypeError,
576 "right operand length must match slice length");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000577 PyObject_ReleaseBuffer((PyObject *)self, &v1);
578 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000579 return -1;
580 }
581
582 if ( slice_len )
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000583 memcpy((char *)v1.buf + left, v2.buf, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000584
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000585 PyObject_ReleaseBuffer((PyObject *)self, &v1);
586 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000587 return 0;
588}
589
590/* Buffer methods */
591
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000592static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000593 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000594 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000595 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
596 (ssizeargfunc)buffer_item, /*sq_item*/
597 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
598 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
599 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000600};
601
602static PyBufferProcs buffer_as_buffer = {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000603 (getbufferproc)buffer_getbuf,
604 (releasebufferproc)buffer_releasebuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000605};
606
607PyTypeObject PyBuffer_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000608 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000609 "buffer",
610 sizeof(PyBufferObject),
611 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000612 (destructor)buffer_dealloc, /* tp_dealloc */
613 0, /* tp_print */
614 0, /* tp_getattr */
615 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000616 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000617 (reprfunc)buffer_repr, /* tp_repr */
618 0, /* tp_as_number */
619 &buffer_as_sequence, /* tp_as_sequence */
620 0, /* tp_as_mapping */
621 (hashfunc)buffer_hash, /* tp_hash */
622 0, /* tp_call */
623 (reprfunc)buffer_str, /* tp_str */
624 PyObject_GenericGetAttr, /* tp_getattro */
625 0, /* tp_setattro */
626 &buffer_as_buffer, /* tp_as_buffer */
627 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000628 buffer_doc, /* tp_doc */
629 0, /* tp_traverse */
630 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000631 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000632 0, /* tp_weaklistoffset */
633 0, /* tp_iter */
634 0, /* tp_iternext */
635 0, /* tp_methods */
636 0, /* tp_members */
637 0, /* tp_getset */
638 0, /* tp_base */
639 0, /* tp_dict */
640 0, /* tp_descr_get */
641 0, /* tp_descr_set */
642 0, /* tp_dictoffset */
643 0, /* tp_init */
644 0, /* tp_alloc */
645 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000646};