blob: 3a0e3d5589c24efd9ddabc2af3d7bdaf6bc8d02e [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
Thomas Wouters0e3f5912006-08-11 14:57:12 +000018enum buffer_t {
19 READ_BUFFER,
20 WRITE_BUFFER,
21 CHAR_BUFFER,
22 ANY_BUFFER,
23};
24
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000025static int
Thomas Wouters0e3f5912006-08-11 14:57:12 +000026get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
27 enum buffer_t buffer_type)
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000028{
29 if (self->b_base == NULL) {
30 assert (ptr != NULL);
31 *ptr = self->b_ptr;
32 *size = self->b_size;
33 }
34 else {
Martin v. Löwis18e16552006-02-15 17:27:45 +000035 Py_ssize_t count, offset;
Thomas Wouters0e3f5912006-08-11 14:57:12 +000036 readbufferproc proc = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000037 PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
38 if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
39 PyErr_SetString(PyExc_TypeError,
40 "single-segment buffer object expected");
41 return 0;
42 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +000043 if ((buffer_type == READ_BUFFER) ||
44 ((buffer_type == ANY_BUFFER) && self->b_readonly))
45 proc = bp->bf_getreadbuffer;
46 else if ((buffer_type == WRITE_BUFFER) ||
47 (buffer_type == ANY_BUFFER))
48 proc = (readbufferproc)bp->bf_getwritebuffer;
49 else if (buffer_type == CHAR_BUFFER) {
50 proc = (readbufferproc)bp->bf_getcharbuffer;
51 }
52 if (!proc) {
53 char *buffer_type_name;
54 switch (buffer_type) {
55 case READ_BUFFER:
56 buffer_type_name = "read";
57 break;
58 case WRITE_BUFFER:
59 buffer_type_name = "write";
60 break;
61 case CHAR_BUFFER:
62 buffer_type_name = "char";
63 break;
64 default:
65 buffer_type_name = "no";
66 break;
67 }
68 PyErr_Format(PyExc_TypeError,
69 "%s buffer type not available",
70 buffer_type_name);
71 return 0;
72 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000073 if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
74 return 0;
75 /* apply constraints to the start/end */
76 if (self->b_offset > count)
77 offset = count;
78 else
79 offset = self->b_offset;
Martin v. Löwis093c1002004-03-25 16:16:28 +000080 *(char **)ptr = *(char **)ptr + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000081 if (self->b_size == Py_END_OF_BUFFER)
82 *size = count;
83 else
84 *size = self->b_size;
85 if (offset + *size > count)
86 *size = count - offset;
87 }
88 return 1;
89}
90
91
Guido van Rossum2e19bd71998-10-07 14:36:10 +000092static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000093buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000094 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +000095{
96 PyBufferObject * b;
97
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000098 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +000099 PyErr_SetString(PyExc_ValueError,
100 "size must be zero or positive");
101 return NULL;
102 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000103 if (offset < 0) {
104 PyErr_SetString(PyExc_ValueError,
105 "offset must be zero or positive");
106 return NULL;
107 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +0000108
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000109 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
110 if ( b == NULL )
111 return NULL;
112
113 Py_XINCREF(base);
114 b->b_base = base;
115 b->b_ptr = ptr;
116 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000117 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000118 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000119 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000120
121 return (PyObject *) b;
122}
123
124static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000125buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000126{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000127 if (offset < 0) {
128 PyErr_SetString(PyExc_ValueError,
129 "offset must be zero or positive");
130 return NULL;
131 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000132 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000133 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000134 PyBufferObject *b = (PyBufferObject *)base;
135 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000136 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000137 if (base_size < 0)
138 base_size = 0;
139 if (size == Py_END_OF_BUFFER || size > base_size)
140 size = base_size;
141 }
142 offset += b->b_offset;
143 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000144 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000145 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000146}
147
148
149PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000150PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000151{
152 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
153
154 if ( pb == NULL ||
155 pb->bf_getreadbuffer == NULL ||
156 pb->bf_getsegcount == NULL )
157 {
158 PyErr_SetString(PyExc_TypeError, "buffer object expected");
159 return NULL;
160 }
161
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000162 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000163}
164
165PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000166PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000167{
168 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
169
170 if ( pb == NULL ||
171 pb->bf_getwritebuffer == NULL ||
172 pb->bf_getsegcount == NULL )
173 {
174 PyErr_SetString(PyExc_TypeError, "buffer object expected");
175 return NULL;
176 }
177
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000178 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000179}
180
181PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000182PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000183{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000184 return buffer_from_memory(NULL, size, 0, ptr, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000185}
186
187PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000188PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000189{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000190 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000191}
192
193PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000194PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000196 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197 PyBufferObject * b;
198
Fred Drake4574f231999-08-04 13:08:19 +0000199 if (size < 0) {
200 PyErr_SetString(PyExc_ValueError,
201 "size must be zero or positive");
202 return NULL;
203 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000204 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000205 /* Inline PyObject_New */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000206 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Moshe Zadkacf703f02000-08-04 15:36:13 +0000207 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000208 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000209 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000210
211 b->b_base = NULL;
212 b->b_ptr = (void *)(b + 1);
213 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000214 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000215 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000216 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000217
Moshe Zadkacf703f02000-08-04 15:36:13 +0000218 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000219}
220
221/* Methods */
222
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000223static PyObject *
224buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
225{
226 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000227 Py_ssize_t offset = 0;
228 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000229
Georg Brandl02c42872005-08-26 06:42:30 +0000230 if (!_PyArg_NoKeywords("buffer()", kw))
231 return NULL;
232
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000233 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000234 return NULL;
235 return PyBuffer_FromObject(ob, offset, size);
236}
237
238PyDoc_STRVAR(buffer_doc,
239"buffer(object [, offset[, size]])\n\
240\n\
241Create a new buffer object which references the given object.\n\
242The buffer will reference a slice of the target object from the\n\
243start of the object (or at the specified offset). The slice will\n\
244extend to the end of the target object (or with the specified size).");
245
246
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000247static void
Fred Drake79912472000-07-09 04:06:11 +0000248buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000249{
250 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000251 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000252}
253
254static int
Fred Drake79912472000-07-09 04:06:11 +0000255buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000256{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000257 void *p1, *p2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000258 Py_ssize_t len_self, len_other, min_len;
259 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000260
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000261 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000262 return -1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000263 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000264 return -1;
265 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000266 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000267 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000268 if (cmp != 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000269 return cmp < 0 ? -1 : 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000270 }
271 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
272}
273
274static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000275buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000276{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000277 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000278
279 if ( self->b_base == NULL )
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000280 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000281 status,
282 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000283 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000284 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000285 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000286 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000287 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000288 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000289 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000290 self->b_size,
291 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000292 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000293}
294
295static long
Fred Drake79912472000-07-09 04:06:11 +0000296buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000297{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000298 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000299 Py_ssize_t size;
300 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000301 register unsigned char *p;
302 register long x;
303
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000304 if ( self->b_hash != -1 )
305 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000306
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000307 /* XXX potential bugs here, a readonly buffer does not imply that the
308 * underlying memory is immutable. b_readonly is a necessary but not
309 * sufficient condition for a buffer to be hashable. Perhaps it would
310 * be better to only allow hashing if the underlying object is known to
311 * be immutable (e.g. PyString_Check() is true). Another idea would
312 * be to call tp_hash on the underlying object and see if it raises
313 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000314 if ( !self->b_readonly )
315 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000316 PyErr_SetString(PyExc_TypeError,
317 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000318 return -1;
319 }
320
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000321 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000322 return -1;
323 p = (unsigned char *) ptr;
324 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000325 x = *p << 7;
326 while (--len >= 0)
327 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000328 x ^= size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000329 if (x == -1)
330 x = -2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000331 self->b_hash = x;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000332 return x;
333}
334
335static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000336buffer_str(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000337{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000338 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000339 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000340 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000341 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000342 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000343}
344
345/* Sequence methods */
346
Martin v. Löwis18e16552006-02-15 17:27:45 +0000347static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000348buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000349{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000350 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000351 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000352 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000353 return -1;
354 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000355}
356
357static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000358buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000359{
360 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000361 void *ptr1, *ptr2;
362 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000363 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000364 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000365
366 if ( pb == NULL ||
367 pb->bf_getreadbuffer == NULL ||
368 pb->bf_getsegcount == NULL )
369 {
370 PyErr_BadArgument();
371 return NULL;
372 }
373 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
374 {
375 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000376 PyErr_SetString(PyExc_TypeError,
377 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000378 return NULL;
379 }
380
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000381 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000382 return NULL;
383
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000384 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000385 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000386 {
387 Py_INCREF(other);
388 return other;
389 }
390
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000391 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000392 return NULL;
393
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000394 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000395 if ( ob == NULL )
396 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000397 p = PyString_AS_STRING(ob);
398 memcpy(p, ptr1, size);
399 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000400
401 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000402 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000403
404 return ob;
405}
406
407static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000408buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000409{
410 PyObject *ob;
411 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000412 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000413 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000414
415 if ( count < 0 )
416 count = 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000417 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000418 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000419 ob = PyString_FromStringAndSize(NULL, size * count);
420 if ( ob == NULL )
421 return NULL;
422
423 p = PyString_AS_STRING(ob);
424 while ( count-- )
425 {
426 memcpy(p, ptr, size);
427 p += size;
428 }
429
430 /* there is an extra byte in the string object, so this is safe */
431 *p = '\0';
432
433 return ob;
434}
435
436static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000437buffer_item(PyBufferObject *self, Py_ssize_t idx)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000438{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000439 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000440 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000441 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000442 return NULL;
443 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000444 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
445 return NULL;
446 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000447 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000448}
449
450static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000451buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000452{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000453 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000454 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000455 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000456 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000457 if ( left < 0 )
458 left = 0;
459 if ( right < 0 )
460 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000461 if ( right > size )
462 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000463 if ( right < left )
464 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000465 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000466 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000467}
468
469static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000470buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000471{
472 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000473 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000474 Py_ssize_t size;
475 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000476
477 if ( self->b_readonly ) {
478 PyErr_SetString(PyExc_TypeError,
479 "buffer is read-only");
480 return -1;
481 }
482
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000483 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000484 return -1;
485
486 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000487 PyErr_SetString(PyExc_IndexError,
488 "buffer assignment index out of range");
489 return -1;
490 }
491
492 pb = other ? other->ob_type->tp_as_buffer : NULL;
493 if ( pb == NULL ||
494 pb->bf_getreadbuffer == NULL ||
495 pb->bf_getsegcount == NULL )
496 {
497 PyErr_BadArgument();
498 return -1;
499 }
500 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
501 {
502 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000503 PyErr_SetString(PyExc_TypeError,
504 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000505 return -1;
506 }
507
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000508 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000509 return -1;
510 if ( count != 1 ) {
511 PyErr_SetString(PyExc_TypeError,
512 "right operand must be a single byte");
513 return -1;
514 }
515
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000516 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000517 return 0;
518}
519
520static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000521buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000522{
523 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000524 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000525 Py_ssize_t size;
526 Py_ssize_t slice_len;
527 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000528
529 if ( self->b_readonly ) {
530 PyErr_SetString(PyExc_TypeError,
531 "buffer is read-only");
532 return -1;
533 }
534
535 pb = other ? other->ob_type->tp_as_buffer : NULL;
536 if ( pb == NULL ||
537 pb->bf_getreadbuffer == NULL ||
538 pb->bf_getsegcount == NULL )
539 {
540 PyErr_BadArgument();
541 return -1;
542 }
543 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
544 {
545 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000546 PyErr_SetString(PyExc_TypeError,
547 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000548 return -1;
549 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000550 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000551 return -1;
552 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000553 return -1;
554
555 if ( left < 0 )
556 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000557 else if ( left > size )
558 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000559 if ( right < left )
560 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000561 else if ( right > size )
562 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000563 slice_len = right - left;
564
565 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000566 PyErr_SetString(
567 PyExc_TypeError,
568 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000569 return -1;
570 }
571
572 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000573 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000574
575 return 0;
576}
577
578/* Buffer methods */
579
Martin v. Löwis18e16552006-02-15 17:27:45 +0000580static Py_ssize_t
581buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000582{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000583 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000584 if ( idx != 0 ) {
585 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000586 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000587 return -1;
588 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000589 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000590 return -1;
591 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000592}
593
Martin v. Löwis18e16552006-02-15 17:27:45 +0000594static Py_ssize_t
595buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000596{
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000597 Py_ssize_t size;
598
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000599 if ( self->b_readonly )
600 {
601 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
602 return -1;
603 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000604
605 if ( idx != 0 ) {
606 PyErr_SetString(PyExc_SystemError,
607 "accessing non-existent buffer segment");
608 return -1;
609 }
610 if (!get_buf(self, pp, &size, WRITE_BUFFER))
611 return -1;
612 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000613}
614
Martin v. Löwis18e16552006-02-15 17:27:45 +0000615static Py_ssize_t
616buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000617{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000618 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000619 Py_ssize_t size;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000620 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000621 return -1;
622 if (lenp)
623 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000624 return 1;
625}
626
Martin v. Löwis18e16552006-02-15 17:27:45 +0000627static Py_ssize_t
628buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000629{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000630 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000631 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000632 if ( idx != 0 ) {
633 PyErr_SetString(PyExc_SystemError,
634 "accessing non-existent buffer segment");
635 return -1;
636 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000637 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000638 return -1;
639 *pp = (const char *)ptr;
640 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000641}
642
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000643static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000644 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000645 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000646 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
647 (ssizeargfunc)buffer_item, /*sq_item*/
648 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
649 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
650 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000651};
652
653static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000654 (readbufferproc)buffer_getreadbuf,
655 (writebufferproc)buffer_getwritebuf,
656 (segcountproc)buffer_getsegcount,
657 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000658};
659
660PyTypeObject PyBuffer_Type = {
661 PyObject_HEAD_INIT(&PyType_Type)
662 0,
663 "buffer",
664 sizeof(PyBufferObject),
665 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000666 (destructor)buffer_dealloc, /* tp_dealloc */
667 0, /* tp_print */
668 0, /* tp_getattr */
669 0, /* tp_setattr */
670 (cmpfunc)buffer_compare, /* tp_compare */
671 (reprfunc)buffer_repr, /* tp_repr */
672 0, /* tp_as_number */
673 &buffer_as_sequence, /* tp_as_sequence */
674 0, /* tp_as_mapping */
675 (hashfunc)buffer_hash, /* tp_hash */
676 0, /* tp_call */
677 (reprfunc)buffer_str, /* tp_str */
678 PyObject_GenericGetAttr, /* tp_getattro */
679 0, /* tp_setattro */
680 &buffer_as_buffer, /* tp_as_buffer */
681 Py_TPFLAGS_DEFAULT, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000682 buffer_doc, /* tp_doc */
683 0, /* tp_traverse */
684 0, /* tp_clear */
685 0, /* tp_richcompare */
686 0, /* tp_weaklistoffset */
687 0, /* tp_iter */
688 0, /* tp_iternext */
689 0, /* tp_methods */
690 0, /* tp_members */
691 0, /* tp_getset */
692 0, /* tp_base */
693 0, /* tp_dict */
694 0, /* tp_descr_get */
695 0, /* tp_descr_set */
696 0, /* tp_dictoffset */
697 0, /* tp_init */
698 0, /* tp_alloc */
699 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000700};