blob: ccd49805ceab5411d3a8bd02f1643c719146a2b8 [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 }
Neal Norwitzfaa54a32007-08-19 04:23:20 +000067 /* XXX(nnorwitz): do we need to release view here? it leaks. */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +000068}
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
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000404 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000405 ob = PyBytes_FromStringAndSize(NULL, view.len+view2.len);
406 if ( ob == NULL ) {
407 PyObject_ReleaseBuffer((PyObject *)self, &view);
408 PyObject_ReleaseBuffer(other, &view2);
Neal Norwitz7c460742005-12-18 08:02:38 +0000409 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000410 }
411 p = PyBytes_AS_STRING(ob);
412 memcpy(p, view.buf, view.len);
413 memcpy(p + view.len, view2.buf, view2.len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000414
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000415 PyObject_ReleaseBuffer((PyObject *)self, &view);
416 PyObject_ReleaseBuffer(other, &view2);
417 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000418}
419
420static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000421buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000422{
423 PyObject *ob;
424 register char *p;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000425 PyBuffer view;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000426
427 if ( count < 0 )
428 count = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000429 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000430 return NULL;
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000431 /* XXX(nnorwitz): need to check for overflow! */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000432 ob = PyBytes_FromStringAndSize(NULL, view.len * count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000433 if ( ob == NULL )
434 return NULL;
435
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000436 p = PyBytes_AS_STRING(ob);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000437 while ( count-- )
438 {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000439 memcpy(p, view.buf, view.len);
440 p += view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000441 }
442
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000443 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000444 return ob;
445}
446
447static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000448buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000449{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000450 PyBuffer view;
451 PyObject *ob;
452
453 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000454 return NULL;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000455 if ( idx < 0 || idx >= view.len ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000456 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
457 return NULL;
458 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000459 ob = PyBytes_FromStringAndSize((char *)view.buf + idx, 1);
460 PyObject_ReleaseBuffer((PyObject *)self, &view);
461 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000462}
463
464static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000465buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000466{
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000467 PyObject *ob;
468 PyBuffer view;
469 if (!get_buf(self, &view, PyBUF_SIMPLE))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000470 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000471 if ( left < 0 )
472 left = 0;
473 if ( right < 0 )
474 right = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000475 if ( right > view.len )
476 right = view.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000477 if ( right < left )
478 right = left;
Neal Norwitzfaa54a32007-08-19 04:23:20 +0000479 /* XXX(nnorwitz): is it possible to access unitialized memory? */
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000480 ob = PyBytes_FromStringAndSize((char *)view.buf + left,
481 right - left);
482 PyObject_ReleaseBuffer((PyObject *)self, &view);
483 return ob;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000484}
485
486static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000487buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000488{
489 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000490 PyBuffer view, view2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000491
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000492 if (!get_buf(self, &view, PyBUF_SIMPLE))
493 return -1;
494
495 if ( self->b_readonly || view.readonly ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000496 PyErr_SetString(PyExc_TypeError,
497 "buffer is read-only");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000498 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000499 return -1;
500 }
501
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000502 if (idx < 0 || idx >= view.len) {
503 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000504 PyErr_SetString(PyExc_IndexError,
505 "buffer assignment index out of range");
506 return -1;
507 }
508
509 pb = other ? other->ob_type->tp_as_buffer : NULL;
510 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000511 pb->bf_getbuffer == NULL) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000512 PyErr_BadArgument();
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000513 PyObject_ReleaseBuffer((PyObject *)self, &view);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000514 return -1;
515 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000516
517 if (PyObject_GetBuffer(other, &view2, PyBUF_SIMPLE) < 0) {
518 PyObject_ReleaseBuffer((PyObject *)self, &view);
519 return -1;
520 }
521 if ( view.len != 1 ) {
522 PyObject_ReleaseBuffer((PyObject *)self, &view);
523 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000524 PyErr_SetString(PyExc_TypeError,
525 "right operand must be a single byte");
526 return -1;
527 }
528
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000529 ((char *)(view.buf))[idx] = *((char *)(view2.buf));
530 PyObject_ReleaseBuffer((PyObject *)self, &view);
531 PyObject_ReleaseBuffer(other, &view2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000532 return 0;
533}
534
535static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000536buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000537{
538 PyBufferProcs *pb;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000539 PyBuffer v1, v2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000540 Py_ssize_t slice_len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000541
542 pb = other ? other->ob_type->tp_as_buffer : NULL;
543 if ( pb == NULL ||
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000544 pb->bf_getbuffer == NULL)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000545 {
546 PyErr_BadArgument();
547 return -1;
548 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000549 if (!get_buf(self, &v1, PyBUF_SIMPLE))
550 return -1;
551
552 if ( self->b_readonly || v1.readonly) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000553 PyErr_SetString(PyExc_TypeError,
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000554 "buffer is read-only");
555 PyObject_ReleaseBuffer((PyObject *)self, &v1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000556 return -1;
557 }
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000558
559 if ((*pb->bf_getbuffer)(other, &v2, PyBUF_SIMPLE) < 0) {
560 PyObject_ReleaseBuffer((PyObject *)self, &v1);
561 return -1;
562 }
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000563
564 if ( left < 0 )
565 left = 0;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000566 else if ( left > v1.len )
567 left = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000568 if ( right < left )
569 right = left;
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000570 else if ( right > v1.len )
571 right = v1.len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000572 slice_len = right - left;
573
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000574 if ( v2.len != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000575 PyErr_SetString(
576 PyExc_TypeError,
577 "right operand length must match slice length");
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000578 PyObject_ReleaseBuffer((PyObject *)self, &v1);
579 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000580 return -1;
581 }
582
583 if ( slice_len )
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000584 memcpy((char *)v1.buf + left, v2.buf, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000585
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000586 PyObject_ReleaseBuffer((PyObject *)self, &v1);
587 PyObject_ReleaseBuffer(other, &v2);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000588 return 0;
589}
590
591/* Buffer methods */
592
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000593static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000594 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000595 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000596 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
597 (ssizeargfunc)buffer_item, /*sq_item*/
598 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
599 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
600 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000601};
602
603static PyBufferProcs buffer_as_buffer = {
Travis E. Oliphantb99f7622007-08-18 11:21:56 +0000604 (getbufferproc)buffer_getbuf,
605 (releasebufferproc)buffer_releasebuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000606};
607
608PyTypeObject PyBuffer_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000609 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000610 "buffer",
611 sizeof(PyBufferObject),
612 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000613 (destructor)buffer_dealloc, /* tp_dealloc */
614 0, /* tp_print */
615 0, /* tp_getattr */
616 0, /* tp_setattr */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000617 0, /* tp_compare */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000618 (reprfunc)buffer_repr, /* tp_repr */
619 0, /* tp_as_number */
620 &buffer_as_sequence, /* tp_as_sequence */
621 0, /* tp_as_mapping */
622 (hashfunc)buffer_hash, /* tp_hash */
623 0, /* tp_call */
624 (reprfunc)buffer_str, /* tp_str */
625 PyObject_GenericGetAttr, /* tp_getattro */
626 0, /* tp_setattro */
627 &buffer_as_buffer, /* tp_as_buffer */
628 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000629 buffer_doc, /* tp_doc */
630 0, /* tp_traverse */
631 0, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000632 buffer_richcompare, /* tp_richcompare */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000633 0, /* tp_weaklistoffset */
634 0, /* tp_iter */
635 0, /* tp_iternext */
636 0, /* tp_methods */
637 0, /* tp_members */
638 0, /* tp_getset */
639 0, /* tp_base */
640 0, /* tp_dict */
641 0, /* tp_descr_get */
642 0, /* tp_descr_set */
643 0, /* tp_dictoffset */
644 0, /* tp_init */
645 0, /* tp_alloc */
646 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000647};