blob: a8bbd151c8f9aadad1d9a2743b00b12016bf4e7d [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 }
67 return;
68}
69
Guido van Rossum2e19bd71998-10-07 14:36:10 +000070static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000071buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000072 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000073{
74 PyBufferObject * b;
75
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000076 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +000077 PyErr_SetString(PyExc_ValueError,
78 "size must be zero or positive");
79 return NULL;
80 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +000081 if (offset < 0) {
82 PyErr_SetString(PyExc_ValueError,
83 "offset must be zero or positive");
84 return NULL;
85 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +000086
Guido van Rossum2e19bd71998-10-07 14:36:10 +000087 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
88 if ( b == NULL )
89 return NULL;
90
91 Py_XINCREF(base);
92 b->b_base = base;
93 b->b_ptr = ptr;
94 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000095 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000096 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000097 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098
99 return (PyObject *) b;
100}
101
102static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000103buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000104{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000105 if (offset < 0) {
106 PyErr_SetString(PyExc_ValueError,
107 "offset must be zero or positive");
108 return NULL;
109 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000110 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000111 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000112 PyBufferObject *b = (PyBufferObject *)base;
113 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000114 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000115 if (base_size < 0)
116 base_size = 0;
117 if (size == Py_END_OF_BUFFER || size > base_size)
118 size = base_size;
119 }
120 offset += b->b_offset;
121 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000122 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000123 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000124}
125
126
127PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000128PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000129{
130 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
131
132 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000133 pb->bf_getbuffer == NULL) {
134 PyErr_SetString(PyExc_TypeError, "buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000135 return NULL;
136 }
137
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000138 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000139}
140
141PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000142PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000143{
144 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
145
146 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000147 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000148 PyErr_SetString(PyExc_TypeError, "buffer object expected");
149 return NULL;
150 }
151
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000152 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000153}
154
155PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000156PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000157{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000158 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000159}
160
161PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000162PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000163{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000164 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000165}
166
167PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000168PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000169{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000170 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000171 PyBufferObject * b;
172
Fred Drake4574f231999-08-04 13:08:19 +0000173 if (size < 0) {
174 PyErr_SetString(PyExc_ValueError,
175 "size must be zero or positive");
176 return NULL;
177 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000178 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000179 /* Inline PyObject_New */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000180 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Moshe Zadkacf703f02000-08-04 15:36:13 +0000181 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000182 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000183 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000184
185 b->b_base = NULL;
186 b->b_ptr = (void *)(b + 1);
187 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000188 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000189 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000190 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000191
Moshe Zadkacf703f02000-08-04 15:36:13 +0000192 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000193}
194
195/* Methods */
196
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000197static PyObject *
198buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
199{
200 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000201 Py_ssize_t offset = 0;
202 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000203
Georg Brandl02c42872005-08-26 06:42:30 +0000204 if (!_PyArg_NoKeywords("buffer()", kw))
205 return NULL;
206
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000207 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000208 return NULL;
209 return PyBuffer_FromObject(ob, offset, size);
210}
211
212PyDoc_STRVAR(buffer_doc,
213"buffer(object [, offset[, size]])\n\
214\n\
215Create a new buffer object which references the given object.\n\
216The buffer will reference a slice of the target object from the\n\
217start of the object (or at the specified offset). The slice will\n\
218extend to the end of the target object (or with the specified size).");
219
220
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000221static void
Fred Drake79912472000-07-09 04:06:11 +0000222buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000223{
224 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000225 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000226}
227
228static int
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000229get_bufx(PyObject *obj, PyBuffer *view, int flags)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000230{
231 PyBufferProcs *bp;
232
233 if (PyBuffer_Check(obj)) {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000234 if (!get_buf((PyBufferObject *)obj, view, flags)) {
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000235 PyErr_Clear();
236 return 0;
237 }
238 else
239 return 1;
240 }
241 bp = obj->ob_type->tp_as_buffer;
242 if (bp == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000243 bp->bf_getbuffer == NULL)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000244 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000245 if ((*bp->bf_getbuffer)(obj, view, PyBUF_SIMPLE) < 0)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000246 return 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000247 return 1;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000248}
249
250static PyObject *
251buffer_richcompare(PyObject *self, PyObject *other, int op)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000252{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000253 void *p1, *p2;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000254 Py_ssize_t len1, len2, min_len;
255 int cmp, ok;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000256 PyBuffer v1, v2;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000257
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000258 ok = 1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000259 if (!get_bufx(self, &v1, PyBUF_SIMPLE))
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000260 ok = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000261 if (!get_bufx(other, &v2, PyBUF_SIMPLE)) {
262 if (ok) PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000263 ok = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000264 }
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000265 if (!ok) {
266 /* If we can't get the buffers,
267 == and != are still defined
268 (and the objects are unequal) */
269 PyObject *result;
270 if (op == Py_EQ)
271 result = Py_False;
272 else if (op == Py_NE)
273 result = Py_True;
274 else
275 result = Py_NotImplemented;
276 Py_INCREF(result);
277 return result;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000278 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000279 len1 = v1.len;
280 len2 = v2.len;
281 p1 = v1.buf;
282 p2 = v2.buf;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000283 min_len = (len1 < len2) ? len1 : len2;
284 cmp = memcmp(p1, p2, min_len);
285 if (cmp == 0)
286 cmp = (len1 < len2) ? -1 :
287 (len1 > len2) ? 1 : 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000288 PyObject_ReleaseBuffer((PyObject *)self, &v1);
289 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000290 return Py_CmpToRich(op, cmp);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000291}
292
293static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000294buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000295{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000296 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000297
298 if ( self->b_base == NULL )
Walter Dörwald1ab83302007-05-18 17:15:44 +0000299 return PyUnicode_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000300 status,
301 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000302 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000303 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000304 else
Walter Dörwald1ab83302007-05-18 17:15:44 +0000305 return PyUnicode_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000306 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000307 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000308 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000309 self->b_size,
310 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000311 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000312}
313
314static long
Fred Drake79912472000-07-09 04:06:11 +0000315buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000316{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000317 PyBuffer view;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000318 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000319 register unsigned char *p;
320 register long x;
321
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000322 if ( self->b_hash != -1 )
323 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000324
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000325 if (!get_buf(self, &view, PyBUF_SIMPLE))
326 return -1;
327 if (!(self->b_readonly)) {
328 PyErr_SetString(PyExc_TypeError,
329 "writable buffers are not hashable");
330 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000331 return -1;
332 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000333
334 p = (unsigned char *) view.buf;
335 len = view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000336 x = *p << 7;
337 while (--len >= 0)
338 x = (1000003*x) ^ *p++;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000339 x ^= view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000340 if (x == -1)
341 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000342 self->b_hash = x;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000343 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000344 return x;
345}
346
347static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000348buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000349{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000350 PyBuffer view;
351 PyObject *res;
352
353 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000354 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000355 res = PyString_FromStringAndSize((const char *)view.buf, view.len);
356 PyObject_ReleaseBuffer((PyObject *)self, &view);
357 return res;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000358}
359
360/* Sequence methods */
361
Martin v. Löwis18e16552006-02-15 17:27:45 +0000362static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000363buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000364{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000365 PyBuffer view;
366
367 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000368 return -1;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000369 PyObject_ReleaseBuffer((PyObject *)self, &view);
370 return view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000371}
372
373static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000374buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000375{
376 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000377 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000378 PyObject *ob;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000379 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000380
381 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000382 pb->bf_getbuffer == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000383 {
384 PyErr_BadArgument();
385 return NULL;
386 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000387
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000388 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000389 return NULL;
390
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000391 /* optimize special case */
Guido van Rossumbc14efb2007-05-08 23:08:31 +0000392 /* XXX bad idea type-wise */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000393 if ( view.len == 0 ) {
394 PyObject_ReleaseBuffer((PyObject *)self, &view);
395 Py_INCREF(other);
396 return other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000397 }
398
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000399 if (PyObject_GetBuffer((PyObject *)other, &view2, PyBUF_SIMPLE) < 0) {
400 PyObject_ReleaseBuffer((PyObject *)self, &view);
401 return NULL;
402 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000403
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;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000430 ob = PyBytes_FromStringAndSize(NULL, view.len * count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000431 if ( ob == NULL )
432 return NULL;
433
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000434 p = PyBytes_AS_STRING(ob);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000435 while ( count-- )
436 {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000437 memcpy(p, view.buf, view.len);
438 p += view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000439 }
440
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000441 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000442 return ob;
443}
444
445static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000446buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000447{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000448 PyBuffer view;
449 PyObject *ob;
450
451 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000452 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000453 if ( idx < 0 || idx >= view.len ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000454 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
455 return NULL;
456 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000457 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
458 PyObject_ReleaseBuffer((PyObject *)self, &view);
459 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000460}
461
462static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000463buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000464{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000465 PyObject *ob;
466 PyBuffer view;
467 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000468 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000469 if ( left < 0 )
470 left = 0;
471 if ( right < 0 )
472 right = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000473 if ( right > view.len )
474 right = view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000475 if ( right < left )
476 right = left;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000477 ob = PyBytes_FromStringAndSize((char *)view.buf + left,
478 right - left);
479 PyObject_ReleaseBuffer((PyObject *)self, &view);
480 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000481}
482
483static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000484buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000485{
486 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000487 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000488
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000489 if (!get_buf(self, &view, PyBUF_SIMPLE))
490 return -1;
491
492 if ( self->b_readonly || view.readonly ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000493 PyErr_SetString(PyExc_TypeError,
494 "buffer is read-only");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000495 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000496 return -1;
497 }
498
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000499 if (idx < 0 || idx >= view.len) {
500 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000501 PyErr_SetString(PyExc_IndexError,
502 "buffer assignment index out of range");
503 return -1;
504 }
505
506 pb = other ? other->ob_type->tp_as_buffer : NULL;
507 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000508 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000509 PyErr_BadArgument();
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000510 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000511 return -1;
512 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000513
514 if (PyObject_GetBuffer(other, &view2, PyBUF_SIMPLE) < 0) {
515 PyObject_ReleaseBuffer((PyObject *)self, &view);
516 return -1;
517 }
518 if ( view.len != 1 ) {
519 PyObject_ReleaseBuffer((PyObject *)self, &view);
520 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000521 PyErr_SetString(PyExc_TypeError,
522 "right operand must be a single byte");
523 return -1;
524 }
525
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000526 ((char *)(view.buf))[idx] = *((char *)(view2.buf));
527 PyObject_ReleaseBuffer((PyObject *)self, &view);
528 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000529 return 0;
530}
531
532static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000533buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000534{
535 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000536 PyBuffer v1, v2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000537 Py_ssize_t slice_len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000538
539 pb = other ? other->ob_type->tp_as_buffer : NULL;
540 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000541 pb->bf_getbuffer == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000542 {
543 PyErr_BadArgument();
544 return -1;
545 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000546 if (!get_buf(self, &v1, PyBUF_SIMPLE))
547 return -1;
548
549 if ( self->b_readonly || v1.readonly) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000550 PyErr_SetString(PyExc_TypeError,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000551 "buffer is read-only");
552 PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000553 return -1;
554 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000555
556 if ((*pb->bf_getbuffer)(other, &v2, PyBUF_SIMPLE) < 0) {
557 PyObject_ReleaseBuffer((PyObject *)self, &v1);
558 return -1;
559 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000560
561 if ( left < 0 )
562 left = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000563 else if ( left > v1.len )
564 left = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000565 if ( right < left )
566 right = left;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000567 else if ( right > v1.len )
568 right = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000569 slice_len = right - left;
570
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000571 if ( v2.len != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000572 PyErr_SetString(
573 PyExc_TypeError,
574 "right operand length must match slice length");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000575 PyObject_ReleaseBuffer((PyObject *)self, &v1);
576 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000577 return -1;
578 }
579
580 if ( slice_len )
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000581 memcpy((char *)v1.buf + left, v2.buf, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000582
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000583 PyObject_ReleaseBuffer((PyObject *)self, &v1);
584 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000585 return 0;
586}
587
588/* Buffer methods */
589
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000590static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000591 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000592 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000593 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
594 (ssizeargfunc)buffer_item, /*sq_item*/
595 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
596 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
597 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000598};
599
600static PyBufferProcs buffer_as_buffer = {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000601 (getbufferproc)buffer_getbuf,
602 (releasebufferproc)buffer_releasebuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000603};
604
605PyTypeObject PyBuffer_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000606 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000607 "buffer",
608 sizeof(PyBufferObject),
609 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000610 (destructor)buffer_dealloc, /* tp_dealloc */
611 0, /* tp_print */
612 0, /* tp_getattr */
613 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000614 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000615 (reprfunc)buffer_repr, /* tp_repr */
616 0, /* tp_as_number */
617 &buffer_as_sequence, /* tp_as_sequence */
618 0, /* tp_as_mapping */
619 (hashfunc)buffer_hash, /* tp_hash */
620 0, /* tp_call */
621 (reprfunc)buffer_str, /* tp_str */
622 PyObject_GenericGetAttr, /* tp_getattro */
623 0, /* tp_setattro */
624 &buffer_as_buffer, /* tp_as_buffer */
625 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000626 buffer_doc, /* tp_doc */
627 0, /* tp_traverse */
628 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000629 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000630 0, /* tp_weaklistoffset */
631 0, /* tp_iter */
632 0, /* tp_iternext */
633 0, /* tp_methods */
634 0, /* tp_members */
635 0, /* tp_getset */
636 0, /* tp_base */
637 0, /* tp_dict */
638 0, /* tp_descr_get */
639 0, /* tp_descr_set */
640 0, /* tp_dictoffset */
641 0, /* tp_init */
642 0, /* tp_alloc */
643 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000644};