blob: 0a818d634c15dfc2e29554894ae9eeb37c08ec49 [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
Brett Cannonde3b0522006-06-08 17:00:45 +000018enum buffer_t {
Brett Cannonc48b0e62006-06-09 17:05:48 +000019 READ_BUFFER,
20 WRITE_BUFFER,
21 CHAR_BUFFER,
Martin v. Löwisda587ab2007-06-08 17:29:20 +000022 ANY_BUFFER
Brett Cannonde3b0522006-06-08 17:00:45 +000023};
24
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000025static int
Brett Cannonde3b0522006-06-08 17:00:45 +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;
Skip Montanaro9a8ae8f2006-06-10 22:38:13 +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 }
Brett Cannonc48b0e62006-06-09 17:05:48 +000043 if ((buffer_type == READ_BUFFER) ||
Brett Cannonde3b0522006-06-08 17:00:45 +000044 ((buffer_type == ANY_BUFFER) && self->b_readonly))
45 proc = bp->bf_getreadbuffer;
Brett Cannonc48b0e62006-06-09 17:05:48 +000046 else if ((buffer_type == WRITE_BUFFER) ||
Brett Cannonde3b0522006-06-08 17:00:45 +000047 (buffer_type == ANY_BUFFER))
48 proc = (readbufferproc)bp->bf_getwritebuffer;
Brett Cannonc48b0e62006-06-09 17:05:48 +000049 else if (buffer_type == CHAR_BUFFER) {
Brett Cannonde3b0522006-06-08 17:00:45 +000050 if (!PyType_HasFeature(self->ob_type,
51 Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
52 PyErr_SetString(PyExc_TypeError,
53 "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
54 return 0;
55 }
56 proc = (readbufferproc)bp->bf_getcharbuffer;
57 }
58 if (!proc) {
59 char *buffer_type_name;
60 switch (buffer_type) {
Brett Cannonc48b0e62006-06-09 17:05:48 +000061 case READ_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000062 buffer_type_name = "read";
63 break;
Brett Cannonc48b0e62006-06-09 17:05:48 +000064 case WRITE_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000065 buffer_type_name = "write";
66 break;
Brett Cannonc48b0e62006-06-09 17:05:48 +000067 case CHAR_BUFFER:
Brett Cannonde3b0522006-06-08 17:00:45 +000068 buffer_type_name = "char";
69 break;
70 default:
71 buffer_type_name = "no";
72 break;
73 }
74 PyErr_Format(PyExc_TypeError,
75 "%s buffer type not available",
76 buffer_type_name);
77 return 0;
78 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000079 if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
80 return 0;
81 /* apply constraints to the start/end */
82 if (self->b_offset > count)
83 offset = count;
84 else
85 offset = self->b_offset;
Martin v. Löwis093c1002004-03-25 16:16:28 +000086 *(char **)ptr = *(char **)ptr + offset;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +000087 if (self->b_size == Py_END_OF_BUFFER)
88 *size = count;
89 else
90 *size = self->b_size;
91 if (offset + *size > count)
92 *size = count - offset;
93 }
94 return 1;
95}
96
97
Guido van Rossum2e19bd71998-10-07 14:36:10 +000098static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +000099buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000100 int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000101{
102 PyBufferObject * b;
103
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000104 if (size < 0 && size != Py_END_OF_BUFFER) {
Guido van Rossum49ded3e1999-03-19 19:04:25 +0000105 PyErr_SetString(PyExc_ValueError,
106 "size must be zero or positive");
107 return NULL;
108 }
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000109 if (offset < 0) {
110 PyErr_SetString(PyExc_ValueError,
111 "offset must be zero or positive");
112 return NULL;
113 }
Guido van Rossum49ded3e1999-03-19 19:04:25 +0000114
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000115 b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116 if ( b == NULL )
117 return NULL;
118
119 Py_XINCREF(base);
120 b->b_base = base;
121 b->b_ptr = ptr;
122 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000123 b->b_offset = offset;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000124 b->b_readonly = readonly;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000125 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000126
127 return (PyObject *) b;
128}
129
130static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000131buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000132{
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000133 if (offset < 0) {
134 PyErr_SetString(PyExc_ValueError,
135 "offset must be zero or positive");
136 return NULL;
137 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000138 if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
Neil Schemenauerfb6ba072004-09-24 15:41:27 +0000139 /* another buffer, refer to the base object */
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000140 PyBufferObject *b = (PyBufferObject *)base;
141 if (b->b_size != Py_END_OF_BUFFER) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000142 Py_ssize_t base_size = b->b_size - offset;
Neil Schemenauer927a57f2004-09-24 19:17:26 +0000143 if (base_size < 0)
144 base_size = 0;
145 if (size == Py_END_OF_BUFFER || size > base_size)
146 size = base_size;
147 }
148 offset += b->b_offset;
149 base = b->b_base;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000150 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000151 return buffer_from_memory(base, size, offset, NULL, readonly);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000152}
153
154
155PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000156PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000157{
158 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
159
160 if ( pb == NULL ||
161 pb->bf_getreadbuffer == NULL ||
162 pb->bf_getsegcount == NULL )
163 {
164 PyErr_SetString(PyExc_TypeError, "buffer object expected");
165 return NULL;
166 }
167
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000168 return buffer_from_object(base, size, offset, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000169}
170
171PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000172PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000173{
174 PyBufferProcs *pb = base->ob_type->tp_as_buffer;
175
176 if ( pb == NULL ||
177 pb->bf_getwritebuffer == NULL ||
178 pb->bf_getsegcount == NULL )
179 {
180 PyErr_SetString(PyExc_TypeError, "buffer object expected");
181 return NULL;
182 }
183
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000184 return buffer_from_object(base, size, offset, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000185}
186
187PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000188PyBuffer_FromMemory(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, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000191}
192
193PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000194PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000195{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000196 return buffer_from_memory(NULL, size, 0, ptr, 0);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000197}
198
199PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000200PyBuffer_New(Py_ssize_t size)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000201{
Moshe Zadkacf703f02000-08-04 15:36:13 +0000202 PyObject *o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000203 PyBufferObject * b;
204
Fred Drake4574f231999-08-04 13:08:19 +0000205 if (size < 0) {
206 PyErr_SetString(PyExc_ValueError,
207 "size must be zero or positive");
208 return NULL;
209 }
Martin v. Löwis18e16552006-02-15 17:27:45 +0000210 /* XXX: check for overflow in multiply */
Guido van Rossume3a8e7e2002-08-19 19:26:42 +0000211 /* Inline PyObject_New */
Anthony Baxter377be112006-04-11 06:54:30 +0000212 o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
Moshe Zadkacf703f02000-08-04 15:36:13 +0000213 if ( o == NULL )
Fred Drake4574f231999-08-04 13:08:19 +0000214 return PyErr_NoMemory();
Moshe Zadkacf703f02000-08-04 15:36:13 +0000215 b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000216
217 b->b_base = NULL;
218 b->b_ptr = (void *)(b + 1);
219 b->b_size = size;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000220 b->b_offset = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000221 b->b_readonly = 0;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000222 b->b_hash = -1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000223
Moshe Zadkacf703f02000-08-04 15:36:13 +0000224 return o;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000225}
226
227/* Methods */
228
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000229static PyObject *
230buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
231{
Georg Brandl80055f62008-03-25 07:56:27 +0000232 if (Py_Py3kWarningFlag &&
233 PyErr_WarnEx(PyExc_DeprecationWarning,
234 "buffer will be removed in 3.x", 1) < 0)
235 return NULL;
236
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000237 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000238 Py_ssize_t offset = 0;
239 Py_ssize_t size = Py_END_OF_BUFFER;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000240
Georg Brandl02c42872005-08-26 06:42:30 +0000241 if (!_PyArg_NoKeywords("buffer()", kw))
242 return NULL;
243
Thomas Wouters02cbdd32006-02-16 19:44:46 +0000244 if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000245 return NULL;
246 return PyBuffer_FromObject(ob, offset, size);
247}
248
249PyDoc_STRVAR(buffer_doc,
250"buffer(object [, offset[, size]])\n\
251\n\
252Create a new buffer object which references the given object.\n\
253The buffer will reference a slice of the target object from the\n\
254start of the object (or at the specified offset). The slice will\n\
255extend to the end of the target object (or with the specified size).");
256
257
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000258static void
Fred Drake79912472000-07-09 04:06:11 +0000259buffer_dealloc(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000260{
261 Py_XDECREF(self->b_base);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000262 PyObject_DEL(self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000263}
264
265static int
Fred Drake79912472000-07-09 04:06:11 +0000266buffer_compare(PyBufferObject *self, PyBufferObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000267{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000268 void *p1, *p2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000269 Py_ssize_t len_self, len_other, min_len;
270 int cmp;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000271
Brett Cannonde3b0522006-06-08 17:00:45 +0000272 if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000273 return -1;
Brett Cannonde3b0522006-06-08 17:00:45 +0000274 if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000275 return -1;
276 min_len = (len_self < len_other) ? len_self : len_other;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000277 if (min_len > 0) {
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000278 cmp = memcmp(p1, p2, min_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000279 if (cmp != 0)
Thomas Hellerab1049c2006-08-08 17:37:00 +0000280 return cmp < 0 ? -1 : 1;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000281 }
282 return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
283}
284
285static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000286buffer_repr(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000287{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000288 const char *status = self->b_readonly ? "read-only" : "read-write";
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000289
290 if ( self->b_base == NULL )
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000291 return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
Barry Warsaw7ce36942001-08-24 18:34:26 +0000292 status,
293 self->b_ptr,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000294 self->b_size,
Barry Warsaw7ce36942001-08-24 18:34:26 +0000295 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000296 else
Barry Warsaw7ce36942001-08-24 18:34:26 +0000297 return PyString_FromFormat(
Martin v. Löwis2c95cc62006-02-16 06:54:25 +0000298 "<%s buffer for %p, size %zd, offset %zd at %p>",
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000299 status,
Fred Drakea44d3532000-06-30 15:01:00 +0000300 self->b_base,
Martin v. Löwise0e89f72006-02-16 06:59:22 +0000301 self->b_size,
302 self->b_offset,
Fred Drakea44d3532000-06-30 15:01:00 +0000303 self);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000304}
305
306static long
Fred Drake79912472000-07-09 04:06:11 +0000307buffer_hash(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000308{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000309 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000310 Py_ssize_t size;
311 register Py_ssize_t len;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000312 register unsigned char *p;
313 register long x;
314
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000315 if ( self->b_hash != -1 )
316 return self->b_hash;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000317
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000318 /* XXX potential bugs here, a readonly buffer does not imply that the
319 * underlying memory is immutable. b_readonly is a necessary but not
320 * sufficient condition for a buffer to be hashable. Perhaps it would
321 * be better to only allow hashing if the underlying object is known to
322 * be immutable (e.g. PyString_Check() is true). Another idea would
323 * be to call tp_hash on the underlying object and see if it raises
324 * an error. */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000325 if ( !self->b_readonly )
326 {
Neil Schemenauer0eadcd92004-03-11 01:00:44 +0000327 PyErr_SetString(PyExc_TypeError,
328 "writable buffers are not hashable");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000329 return -1;
330 }
331
Brett Cannonde3b0522006-06-08 17:00:45 +0000332 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000333 return -1;
334 p = (unsigned char *) ptr;
335 len = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000336 x = *p << 7;
337 while (--len >= 0)
338 x = (1000003*x) ^ *p++;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000339 x ^= size;
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;
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{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000349 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000350 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000351 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000352 return NULL;
Anthony Baxter377be112006-04-11 06:54:30 +0000353 return PyString_FromStringAndSize((const char *)ptr, size);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000354}
355
356/* Sequence methods */
357
Martin v. Löwis18e16552006-02-15 17:27:45 +0000358static Py_ssize_t
Fred Drake79912472000-07-09 04:06:11 +0000359buffer_length(PyBufferObject *self)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000360{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000361 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000362 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000363 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000364 return -1;
365 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000366}
367
368static PyObject *
Fred Drake79912472000-07-09 04:06:11 +0000369buffer_concat(PyBufferObject *self, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000370{
371 PyBufferProcs *pb = other->ob_type->tp_as_buffer;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000372 void *ptr1, *ptr2;
373 char *p;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000374 PyObject *ob;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000375 Py_ssize_t size, count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000376
377 if ( pb == NULL ||
378 pb->bf_getreadbuffer == NULL ||
379 pb->bf_getsegcount == NULL )
380 {
381 PyErr_BadArgument();
382 return NULL;
383 }
384 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
385 {
386 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000387 PyErr_SetString(PyExc_TypeError,
388 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000389 return NULL;
390 }
391
Brett Cannonde3b0522006-06-08 17:00:45 +0000392 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000393 return NULL;
394
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000395 /* optimize special case */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000396 if ( size == 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000397 {
398 Py_INCREF(other);
399 return other;
400 }
401
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000402 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000403 return NULL;
404
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000405 ob = PyString_FromStringAndSize(NULL, size + count);
Neal Norwitz7c460742005-12-18 08:02:38 +0000406 if ( ob == NULL )
407 return NULL;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000408 p = PyString_AS_STRING(ob);
409 memcpy(p, ptr1, size);
410 memcpy(p + size, ptr2, count);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000411
412 /* there is an extra byte in the string object, so this is safe */
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000413 p[size + count] = '\0';
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000414
415 return ob;
416}
417
418static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000419buffer_repeat(PyBufferObject *self, Py_ssize_t count)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000420{
421 PyObject *ob;
422 register char *p;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000423 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000424 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000425
426 if ( count < 0 )
427 count = 0;
Brett Cannonde3b0522006-06-08 17:00:45 +0000428 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000429 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000430 ob = PyString_FromStringAndSize(NULL, size * count);
431 if ( ob == NULL )
432 return NULL;
433
434 p = PyString_AS_STRING(ob);
435 while ( count-- )
436 {
437 memcpy(p, ptr, size);
438 p += size;
439 }
440
441 /* there is an extra byte in the string object, so this is safe */
442 *p = '\0';
443
444 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{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000450 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000451 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000452 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000453 return NULL;
454 if ( idx < 0 || idx >= size ) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000455 PyErr_SetString(PyExc_IndexError, "buffer index out of range");
456 return NULL;
457 }
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000458 return PyString_FromStringAndSize((char *)ptr + idx, 1);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000459}
460
461static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000462buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000463{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000464 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000465 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000466 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000467 return NULL;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000468 if ( left < 0 )
469 left = 0;
470 if ( right < 0 )
471 right = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000472 if ( right > size )
473 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000474 if ( right < left )
475 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000476 return PyString_FromStringAndSize((char *)ptr + left,
Guido van Rossumcd037e71999-03-24 19:05:31 +0000477 right - left);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000478}
479
Thomas Wouters3ccec682007-08-28 15:28:19 +0000480static PyObject *
481buffer_subscript(PyBufferObject *self, PyObject *item)
482{
483 void *p;
484 Py_ssize_t size;
485
486 if (!get_buf(self, &p, &size, ANY_BUFFER))
487 return NULL;
488 if (PyIndex_Check(item)) {
489 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
490 if (i == -1 && PyErr_Occurred())
491 return NULL;
492 if (i < 0)
493 i += size;
494 return buffer_item(self, i);
495 }
496 else if (PySlice_Check(item)) {
497 Py_ssize_t start, stop, step, slicelength, cur, i;
498
499 if (PySlice_GetIndicesEx((PySliceObject*)item, size,
500 &start, &stop, &step, &slicelength) < 0) {
501 return NULL;
502 }
503
504 if (slicelength <= 0)
505 return PyString_FromStringAndSize("", 0);
506 else if (step == 1)
507 return PyString_FromStringAndSize((char *)p + start,
508 stop - start);
509 else {
510 PyObject *result;
511 char *source_buf = (char *)p;
512 char *result_buf = (char *)PyMem_Malloc(slicelength);
513
514 if (result_buf == NULL)
515 return PyErr_NoMemory();
516
517 for (cur = start, i = 0; i < slicelength;
518 cur += step, i++) {
519 result_buf[i] = source_buf[cur];
520 }
521
522 result = PyString_FromStringAndSize(result_buf,
523 slicelength);
524 PyMem_Free(result_buf);
525 return result;
526 }
527 }
528 else {
529 PyErr_SetString(PyExc_TypeError,
530 "sequence index must be integer");
531 return NULL;
532 }
533}
534
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000535static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000536buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000537{
538 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000539 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000540 Py_ssize_t size;
541 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000542
543 if ( self->b_readonly ) {
544 PyErr_SetString(PyExc_TypeError,
545 "buffer is read-only");
546 return -1;
547 }
548
Brett Cannonde3b0522006-06-08 17:00:45 +0000549 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000550 return -1;
551
552 if (idx < 0 || idx >= size) {
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000553 PyErr_SetString(PyExc_IndexError,
554 "buffer assignment index out of range");
555 return -1;
556 }
557
558 pb = other ? other->ob_type->tp_as_buffer : NULL;
559 if ( pb == NULL ||
560 pb->bf_getreadbuffer == NULL ||
561 pb->bf_getsegcount == NULL )
562 {
563 PyErr_BadArgument();
564 return -1;
565 }
566 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
567 {
568 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000569 PyErr_SetString(PyExc_TypeError,
570 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000571 return -1;
572 }
573
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000574 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000575 return -1;
576 if ( count != 1 ) {
577 PyErr_SetString(PyExc_TypeError,
578 "right operand must be a single byte");
579 return -1;
580 }
581
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000582 ((char *)ptr1)[idx] = *(char *)ptr2;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000583 return 0;
584}
585
586static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000587buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000588{
589 PyBufferProcs *pb;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000590 void *ptr1, *ptr2;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000591 Py_ssize_t size;
592 Py_ssize_t slice_len;
593 Py_ssize_t count;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000594
595 if ( self->b_readonly ) {
596 PyErr_SetString(PyExc_TypeError,
597 "buffer is read-only");
598 return -1;
599 }
600
601 pb = other ? other->ob_type->tp_as_buffer : NULL;
602 if ( pb == NULL ||
603 pb->bf_getreadbuffer == NULL ||
604 pb->bf_getsegcount == NULL )
605 {
606 PyErr_BadArgument();
607 return -1;
608 }
609 if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
610 {
611 /* ### use a different exception type/message? */
Guido van Rossumcd037e71999-03-24 19:05:31 +0000612 PyErr_SetString(PyExc_TypeError,
613 "single-segment buffer object expected");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000614 return -1;
615 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000616 if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000617 return -1;
618 if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000619 return -1;
620
621 if ( left < 0 )
622 left = 0;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000623 else if ( left > size )
624 left = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000625 if ( right < left )
626 right = left;
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000627 else if ( right > size )
628 right = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000629 slice_len = right - left;
630
631 if ( count != slice_len ) {
Guido van Rossumcd037e71999-03-24 19:05:31 +0000632 PyErr_SetString(
633 PyExc_TypeError,
634 "right operand length must match slice length");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000635 return -1;
636 }
637
638 if ( slice_len )
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000639 memcpy((char *)ptr1 + left, ptr2, slice_len);
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000640
641 return 0;
642}
643
Thomas Wouters3ccec682007-08-28 15:28:19 +0000644static int
645buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
646{
647 PyBufferProcs *pb;
648 void *ptr1, *ptr2;
649 Py_ssize_t selfsize;
650 Py_ssize_t othersize;
651
652 if ( self->b_readonly ) {
653 PyErr_SetString(PyExc_TypeError,
654 "buffer is read-only");
655 return -1;
656 }
657
658 pb = value ? value->ob_type->tp_as_buffer : NULL;
659 if ( pb == NULL ||
660 pb->bf_getreadbuffer == NULL ||
661 pb->bf_getsegcount == NULL )
662 {
663 PyErr_BadArgument();
664 return -1;
665 }
666 if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
667 {
668 /* ### use a different exception type/message? */
669 PyErr_SetString(PyExc_TypeError,
670 "single-segment buffer object expected");
671 return -1;
672 }
673 if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
674 return -1;
675 if (PyIndex_Check(item)) {
676 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
677 if (i == -1 && PyErr_Occurred())
678 return -1;
679 if (i < 0)
680 i += selfsize;
681 return buffer_ass_item(self, i, value);
682 }
683 else if (PySlice_Check(item)) {
684 Py_ssize_t start, stop, step, slicelength;
685
686 if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
687 &start, &stop, &step, &slicelength) < 0)
688 return -1;
689
Thomas Wouters3ccec682007-08-28 15:28:19 +0000690 if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
691 return -1;
692
693 if (othersize != slicelength) {
694 PyErr_SetString(
695 PyExc_TypeError,
696 "right operand length must match slice length");
697 return -1;
698 }
699
700 if (slicelength == 0)
701 return 0;
702 else if (step == 1) {
703 memcpy((char *)ptr1 + start, ptr2, slicelength);
704 return 0;
705 }
706 else {
707 Py_ssize_t cur, i;
708
709 for (cur = start, i = 0; i < slicelength;
710 cur += step, i++) {
711 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
712 }
713
714 return 0;
715 }
716 } else {
717 PyErr_SetString(PyExc_TypeError,
718 "buffer indices must be integers");
719 return -1;
720 }
721}
722
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000723/* Buffer methods */
724
Martin v. Löwis18e16552006-02-15 17:27:45 +0000725static Py_ssize_t
726buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000727{
Martin v. Löwis18e16552006-02-15 17:27:45 +0000728 Py_ssize_t size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000729 if ( idx != 0 ) {
730 PyErr_SetString(PyExc_SystemError,
Guido van Rossum1db70701998-10-08 02:18:52 +0000731 "accessing non-existent buffer segment");
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000732 return -1;
733 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000734 if (!get_buf(self, pp, &size, READ_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000735 return -1;
736 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000737}
738
Martin v. Löwis18e16552006-02-15 17:27:45 +0000739static Py_ssize_t
740buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000741{
Brett Cannonde3b0522006-06-08 17:00:45 +0000742 Py_ssize_t size;
743
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000744 if ( self->b_readonly )
745 {
746 PyErr_SetString(PyExc_TypeError, "buffer is read-only");
747 return -1;
748 }
Brett Cannonde3b0522006-06-08 17:00:45 +0000749
750 if ( idx != 0 ) {
751 PyErr_SetString(PyExc_SystemError,
752 "accessing non-existent buffer segment");
753 return -1;
754 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000755 if (!get_buf(self, pp, &size, WRITE_BUFFER))
Brett Cannonde3b0522006-06-08 17:00:45 +0000756 return -1;
757 return size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000758}
759
Martin v. Löwis18e16552006-02-15 17:27:45 +0000760static Py_ssize_t
761buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000762{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000763 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000764 Py_ssize_t size;
Brett Cannonde3b0522006-06-08 17:00:45 +0000765 if (!get_buf(self, &ptr, &size, ANY_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000766 return -1;
767 if (lenp)
768 *lenp = size;
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000769 return 1;
770}
771
Martin v. Löwis18e16552006-02-15 17:27:45 +0000772static Py_ssize_t
773buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
Guido van Rossum1db70701998-10-08 02:18:52 +0000774{
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000775 void *ptr;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000776 Py_ssize_t size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000777 if ( idx != 0 ) {
778 PyErr_SetString(PyExc_SystemError,
779 "accessing non-existent buffer segment");
780 return -1;
781 }
Brett Cannonc48b0e62006-06-09 17:05:48 +0000782 if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
Neil Schemenauer4252a7a2004-03-11 02:42:45 +0000783 return -1;
784 *pp = (const char *)ptr;
785 return size;
Guido van Rossum1db70701998-10-08 02:18:52 +0000786}
787
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000788static PySequenceMethods buffer_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000789 (lenfunc)buffer_length, /*sq_length*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000790 (binaryfunc)buffer_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000791 (ssizeargfunc)buffer_repeat, /*sq_repeat*/
792 (ssizeargfunc)buffer_item, /*sq_item*/
793 (ssizessizeargfunc)buffer_slice, /*sq_slice*/
794 (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
795 (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000796};
797
Thomas Wouters3ccec682007-08-28 15:28:19 +0000798static PyMappingMethods buffer_as_mapping = {
799 (lenfunc)buffer_length,
800 (binaryfunc)buffer_subscript,
801 (objobjargproc)buffer_ass_subscript,
802};
803
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000804static PyBufferProcs buffer_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000805 (readbufferproc)buffer_getreadbuf,
806 (writebufferproc)buffer_getwritebuf,
807 (segcountproc)buffer_getsegcount,
808 (charbufferproc)buffer_getcharbuf,
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000809};
810
811PyTypeObject PyBuffer_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000812 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000813 "buffer",
814 sizeof(PyBufferObject),
815 0,
Tim Peters6d6c1a32001-08-02 04:15:00 +0000816 (destructor)buffer_dealloc, /* tp_dealloc */
817 0, /* tp_print */
818 0, /* tp_getattr */
819 0, /* tp_setattr */
820 (cmpfunc)buffer_compare, /* tp_compare */
821 (reprfunc)buffer_repr, /* tp_repr */
822 0, /* tp_as_number */
823 &buffer_as_sequence, /* tp_as_sequence */
Thomas Wouters3ccec682007-08-28 15:28:19 +0000824 &buffer_as_mapping, /* tp_as_mapping */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000825 (hashfunc)buffer_hash, /* tp_hash */
826 0, /* tp_call */
827 (reprfunc)buffer_str, /* tp_str */
828 PyObject_GenericGetAttr, /* tp_getattro */
829 0, /* tp_setattro */
830 &buffer_as_buffer, /* tp_as_buffer */
Brett Cannonde3b0522006-06-08 17:00:45 +0000831 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000832 buffer_doc, /* tp_doc */
833 0, /* tp_traverse */
834 0, /* tp_clear */
835 0, /* tp_richcompare */
836 0, /* tp_weaklistoffset */
837 0, /* tp_iter */
838 0, /* tp_iternext */
839 0, /* tp_methods */
840 0, /* tp_members */
841 0, /* tp_getset */
842 0, /* tp_base */
843 0, /* tp_dict */
844 0, /* tp_descr_get */
845 0, /* tp_descr_set */
846 0, /* tp_dictoffset */
847 0, /* tp_init */
848 0, /* tp_alloc */
849 buffer_new, /* tp_new */
Guido van Rossum2e19bd71998-10-07 14:36:10 +0000850};