Line data Source code
1 :
2 : /* Buffer object implementation */
3 :
4 : #include "Python.h"
5 :
6 :
7 : typedef struct {
8 : PyObject_HEAD
9 : PyObject *b_base;
10 : void *b_ptr;
11 : Py_ssize_t b_size;
12 : Py_ssize_t b_offset;
13 : int b_readonly;
14 : long b_hash;
15 : } PyBufferObject;
16 :
17 :
18 : enum buffer_t {
19 : READ_BUFFER,
20 : WRITE_BUFFER,
21 : CHAR_BUFFER,
22 : ANY_BUFFER
23 : };
24 :
25 : static int
26 0 : get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
27 : enum buffer_t buffer_type)
28 : {
29 0 : if (self->b_base == NULL) {
30 : assert (ptr != NULL);
31 0 : *ptr = self->b_ptr;
32 0 : *size = self->b_size;
33 : }
34 : else {
35 : Py_ssize_t count, offset;
36 0 : readbufferproc proc = 0;
37 0 : PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
38 0 : if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
39 0 : PyErr_SetString(PyExc_TypeError,
40 : "single-segment buffer object expected");
41 0 : return 0;
42 : }
43 0 : if ((buffer_type == READ_BUFFER) ||
44 0 : ((buffer_type == ANY_BUFFER) && self->b_readonly))
45 0 : proc = bp->bf_getreadbuffer;
46 0 : else if ((buffer_type == WRITE_BUFFER) ||
47 : (buffer_type == ANY_BUFFER))
48 0 : proc = (readbufferproc)bp->bf_getwritebuffer;
49 0 : else if (buffer_type == CHAR_BUFFER) {
50 0 : if (!PyType_HasFeature(self->ob_type,
51 : Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
52 0 : PyErr_SetString(PyExc_TypeError,
53 : "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
54 0 : return 0;
55 : }
56 0 : proc = (readbufferproc)bp->bf_getcharbuffer;
57 : }
58 0 : if (!proc) {
59 : char *buffer_type_name;
60 0 : switch (buffer_type) {
61 : case READ_BUFFER:
62 0 : buffer_type_name = "read";
63 0 : break;
64 : case WRITE_BUFFER:
65 0 : buffer_type_name = "write";
66 0 : break;
67 : case CHAR_BUFFER:
68 0 : buffer_type_name = "char";
69 0 : break;
70 : default:
71 0 : buffer_type_name = "no";
72 0 : break;
73 : }
74 0 : PyErr_Format(PyExc_TypeError,
75 : "%s buffer type not available",
76 : buffer_type_name);
77 0 : return 0;
78 : }
79 0 : if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
80 0 : return 0;
81 : /* apply constraints to the start/end */
82 0 : if (self->b_offset > count)
83 0 : offset = count;
84 : else
85 0 : offset = self->b_offset;
86 0 : *(char **)ptr = *(char **)ptr + offset;
87 0 : if (self->b_size == Py_END_OF_BUFFER)
88 0 : *size = count;
89 : else
90 0 : *size = self->b_size;
91 0 : if (*size > count - offset)
92 0 : *size = count - offset;
93 : }
94 0 : return 1;
95 : }
96 :
97 :
98 : static PyObject *
99 0 : buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
100 : int readonly)
101 : {
102 : PyBufferObject * b;
103 :
104 0 : if (size < 0 && size != Py_END_OF_BUFFER) {
105 0 : PyErr_SetString(PyExc_ValueError,
106 : "size must be zero or positive");
107 0 : return NULL;
108 : }
109 0 : if (offset < 0) {
110 0 : PyErr_SetString(PyExc_ValueError,
111 : "offset must be zero or positive");
112 0 : return NULL;
113 : }
114 :
115 0 : b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
116 0 : if ( b == NULL )
117 0 : return NULL;
118 :
119 0 : Py_XINCREF(base);
120 0 : b->b_base = base;
121 0 : b->b_ptr = ptr;
122 0 : b->b_size = size;
123 0 : b->b_offset = offset;
124 0 : b->b_readonly = readonly;
125 0 : b->b_hash = -1;
126 :
127 0 : return (PyObject *) b;
128 : }
129 :
130 : static PyObject *
131 0 : buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
132 : {
133 0 : if (offset < 0) {
134 0 : PyErr_SetString(PyExc_ValueError,
135 : "offset must be zero or positive");
136 0 : return NULL;
137 : }
138 0 : if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
139 : /* another buffer, refer to the base object */
140 0 : PyBufferObject *b = (PyBufferObject *)base;
141 0 : if (b->b_size != Py_END_OF_BUFFER) {
142 0 : Py_ssize_t base_size = b->b_size - offset;
143 0 : if (base_size < 0)
144 0 : base_size = 0;
145 0 : if (size == Py_END_OF_BUFFER || size > base_size)
146 0 : size = base_size;
147 : }
148 0 : offset += b->b_offset;
149 0 : base = b->b_base;
150 : }
151 0 : return buffer_from_memory(base, size, offset, NULL, readonly);
152 : }
153 :
154 :
155 : PyObject *
156 0 : PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
157 : {
158 0 : PyBufferProcs *pb = base->ob_type->tp_as_buffer;
159 :
160 0 : if ( pb == NULL ||
161 0 : pb->bf_getreadbuffer == NULL ||
162 0 : pb->bf_getsegcount == NULL )
163 : {
164 0 : PyErr_SetString(PyExc_TypeError, "buffer object expected");
165 0 : return NULL;
166 : }
167 :
168 0 : return buffer_from_object(base, size, offset, 1);
169 : }
170 :
171 : PyObject *
172 0 : PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
173 : {
174 0 : PyBufferProcs *pb = base->ob_type->tp_as_buffer;
175 :
176 0 : if ( pb == NULL ||
177 0 : pb->bf_getwritebuffer == NULL ||
178 0 : pb->bf_getsegcount == NULL )
179 : {
180 0 : PyErr_SetString(PyExc_TypeError, "buffer object expected");
181 0 : return NULL;
182 : }
183 :
184 0 : return buffer_from_object(base, size, offset, 0);
185 : }
186 :
187 : PyObject *
188 0 : PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
189 : {
190 0 : return buffer_from_memory(NULL, size, 0, ptr, 1);
191 : }
192 :
193 : PyObject *
194 0 : PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
195 : {
196 0 : return buffer_from_memory(NULL, size, 0, ptr, 0);
197 : }
198 :
199 : PyObject *
200 0 : PyBuffer_New(Py_ssize_t size)
201 : {
202 : PyObject *o;
203 : PyBufferObject * b;
204 :
205 0 : if (size < 0) {
206 0 : PyErr_SetString(PyExc_ValueError,
207 : "size must be zero or positive");
208 0 : return NULL;
209 : }
210 0 : if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
211 : /* unlikely */
212 0 : return PyErr_NoMemory();
213 : }
214 : /* Inline PyObject_New */
215 0 : o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
216 0 : if ( o == NULL )
217 0 : return PyErr_NoMemory();
218 0 : b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
219 :
220 0 : b->b_base = NULL;
221 0 : b->b_ptr = (void *)(b + 1);
222 0 : b->b_size = size;
223 0 : b->b_offset = 0;
224 0 : b->b_readonly = 0;
225 0 : b->b_hash = -1;
226 :
227 0 : return o;
228 : }
229 :
230 : /* Methods */
231 :
232 : static PyObject *
233 0 : buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
234 : {
235 : PyObject *ob;
236 0 : Py_ssize_t offset = 0;
237 0 : Py_ssize_t size = Py_END_OF_BUFFER;
238 :
239 0 : if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
240 0 : return NULL;
241 :
242 0 : if (!_PyArg_NoKeywords("buffer()", kw))
243 0 : return NULL;
244 :
245 0 : if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
246 0 : return NULL;
247 0 : return PyBuffer_FromObject(ob, offset, size);
248 : }
249 :
250 : PyDoc_STRVAR(buffer_doc,
251 : "buffer(object [, offset[, size]])\n\
252 : \n\
253 : Create a new buffer object which references the given object.\n\
254 : The buffer will reference a slice of the target object from the\n\
255 : start of the object (or at the specified offset). The slice will\n\
256 : extend to the end of the target object (or with the specified size).");
257 :
258 :
259 : static void
260 0 : buffer_dealloc(PyBufferObject *self)
261 : {
262 0 : Py_XDECREF(self->b_base);
263 0 : PyObject_DEL(self);
264 0 : }
265 :
266 : static int
267 0 : buffer_compare(PyBufferObject *self, PyBufferObject *other)
268 : {
269 : void *p1, *p2;
270 : Py_ssize_t len_self, len_other, min_len;
271 : int cmp;
272 :
273 0 : if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
274 0 : return -1;
275 0 : if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
276 0 : return -1;
277 0 : min_len = (len_self < len_other) ? len_self : len_other;
278 0 : if (min_len > 0) {
279 0 : cmp = memcmp(p1, p2, min_len);
280 0 : if (cmp != 0)
281 0 : return cmp < 0 ? -1 : 1;
282 : }
283 0 : return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
284 : }
285 :
286 : static PyObject *
287 0 : buffer_repr(PyBufferObject *self)
288 : {
289 0 : const char *status = self->b_readonly ? "read-only" : "read-write";
290 :
291 0 : if ( self->b_base == NULL )
292 0 : return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
293 : status,
294 : self->b_ptr,
295 : self->b_size,
296 : self);
297 : else
298 0 : return PyString_FromFormat(
299 : "<%s buffer for %p, size %zd, offset %zd at %p>",
300 : status,
301 : self->b_base,
302 : self->b_size,
303 : self->b_offset,
304 : self);
305 : }
306 :
307 : static long
308 0 : buffer_hash(PyBufferObject *self)
309 : {
310 : void *ptr;
311 : Py_ssize_t size;
312 : register Py_ssize_t len;
313 : register unsigned char *p;
314 : register long x;
315 :
316 0 : if ( self->b_hash != -1 )
317 0 : return self->b_hash;
318 :
319 : /* XXX potential bugs here, a readonly buffer does not imply that the
320 : * underlying memory is immutable. b_readonly is a necessary but not
321 : * sufficient condition for a buffer to be hashable. Perhaps it would
322 : * be better to only allow hashing if the underlying object is known to
323 : * be immutable (e.g. PyString_Check() is true). Another idea would
324 : * be to call tp_hash on the underlying object and see if it raises
325 : * an error. */
326 0 : if ( !self->b_readonly )
327 : {
328 0 : PyErr_SetString(PyExc_TypeError,
329 : "writable buffers are not hashable");
330 0 : return -1;
331 : }
332 :
333 0 : if (!get_buf(self, &ptr, &size, ANY_BUFFER))
334 0 : return -1;
335 0 : p = (unsigned char *) ptr;
336 0 : len = size;
337 : /*
338 : We make the hash of the empty buffer be 0, rather than using
339 : (prefix ^ suffix), since this slightly obfuscates the hash secret
340 : */
341 0 : if (len == 0) {
342 0 : self->b_hash = 0;
343 0 : return 0;
344 : }
345 0 : x = _Py_HashSecret.prefix;
346 0 : x ^= *p << 7;
347 0 : while (--len >= 0)
348 0 : x = (1000003*x) ^ *p++;
349 0 : x ^= size;
350 0 : x ^= _Py_HashSecret.suffix;
351 0 : if (x == -1)
352 0 : x = -2;
353 0 : self->b_hash = x;
354 0 : return x;
355 : }
356 :
357 : static PyObject *
358 0 : buffer_str(PyBufferObject *self)
359 : {
360 : void *ptr;
361 : Py_ssize_t size;
362 0 : if (!get_buf(self, &ptr, &size, ANY_BUFFER))
363 0 : return NULL;
364 0 : return PyString_FromStringAndSize((const char *)ptr, size);
365 : }
366 :
367 : /* Sequence methods */
368 :
369 : static Py_ssize_t
370 0 : buffer_length(PyBufferObject *self)
371 : {
372 : void *ptr;
373 : Py_ssize_t size;
374 0 : if (!get_buf(self, &ptr, &size, ANY_BUFFER))
375 0 : return -1;
376 0 : return size;
377 : }
378 :
379 : static PyObject *
380 0 : buffer_concat(PyBufferObject *self, PyObject *other)
381 : {
382 0 : PyBufferProcs *pb = other->ob_type->tp_as_buffer;
383 : void *ptr1, *ptr2;
384 : char *p;
385 : PyObject *ob;
386 : Py_ssize_t size, count;
387 :
388 0 : if ( pb == NULL ||
389 0 : pb->bf_getreadbuffer == NULL ||
390 0 : pb->bf_getsegcount == NULL )
391 : {
392 0 : PyErr_BadArgument();
393 0 : return NULL;
394 : }
395 0 : if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
396 : {
397 : /* ### use a different exception type/message? */
398 0 : PyErr_SetString(PyExc_TypeError,
399 : "single-segment buffer object expected");
400 0 : return NULL;
401 : }
402 :
403 0 : if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
404 0 : return NULL;
405 :
406 : /* optimize special case */
407 0 : if ( size == 0 )
408 : {
409 0 : Py_INCREF(other);
410 0 : return other;
411 : }
412 :
413 0 : if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
414 0 : return NULL;
415 :
416 : assert(count <= PY_SIZE_MAX - size);
417 :
418 0 : ob = PyString_FromStringAndSize(NULL, size + count);
419 0 : if ( ob == NULL )
420 0 : return NULL;
421 0 : p = PyString_AS_STRING(ob);
422 0 : memcpy(p, ptr1, size);
423 0 : memcpy(p + size, ptr2, count);
424 :
425 : /* there is an extra byte in the string object, so this is safe */
426 0 : p[size + count] = '\0';
427 :
428 0 : return ob;
429 : }
430 :
431 : static PyObject *
432 0 : buffer_repeat(PyBufferObject *self, Py_ssize_t count)
433 : {
434 : PyObject *ob;
435 : register char *p;
436 : void *ptr;
437 : Py_ssize_t size;
438 :
439 0 : if ( count < 0 )
440 0 : count = 0;
441 0 : if (!get_buf(self, &ptr, &size, ANY_BUFFER))
442 0 : return NULL;
443 0 : if (count > PY_SSIZE_T_MAX / size) {
444 0 : PyErr_SetString(PyExc_MemoryError, "result too large");
445 0 : return NULL;
446 : }
447 0 : ob = PyString_FromStringAndSize(NULL, size * count);
448 0 : if ( ob == NULL )
449 0 : return NULL;
450 :
451 0 : p = PyString_AS_STRING(ob);
452 0 : while ( count-- )
453 : {
454 0 : memcpy(p, ptr, size);
455 0 : p += size;
456 : }
457 :
458 : /* there is an extra byte in the string object, so this is safe */
459 0 : *p = '\0';
460 :
461 0 : return ob;
462 : }
463 :
464 : static PyObject *
465 0 : buffer_item(PyBufferObject *self, Py_ssize_t idx)
466 : {
467 : void *ptr;
468 : Py_ssize_t size;
469 0 : if (!get_buf(self, &ptr, &size, ANY_BUFFER))
470 0 : return NULL;
471 0 : if ( idx < 0 || idx >= size ) {
472 0 : PyErr_SetString(PyExc_IndexError, "buffer index out of range");
473 0 : return NULL;
474 : }
475 0 : return PyString_FromStringAndSize((char *)ptr + idx, 1);
476 : }
477 :
478 : static PyObject *
479 0 : buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
480 : {
481 : void *ptr;
482 : Py_ssize_t size;
483 0 : if (!get_buf(self, &ptr, &size, ANY_BUFFER))
484 0 : return NULL;
485 0 : if ( left < 0 )
486 0 : left = 0;
487 0 : if ( right < 0 )
488 0 : right = 0;
489 0 : if ( right > size )
490 0 : right = size;
491 0 : if ( right < left )
492 0 : right = left;
493 0 : return PyString_FromStringAndSize((char *)ptr + left,
494 : right - left);
495 : }
496 :
497 : static PyObject *
498 0 : buffer_subscript(PyBufferObject *self, PyObject *item)
499 : {
500 : void *p;
501 : Py_ssize_t size;
502 :
503 0 : if (!get_buf(self, &p, &size, ANY_BUFFER))
504 0 : return NULL;
505 0 : if (PyIndex_Check(item)) {
506 0 : Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
507 0 : if (i == -1 && PyErr_Occurred())
508 0 : return NULL;
509 0 : if (i < 0)
510 0 : i += size;
511 0 : return buffer_item(self, i);
512 : }
513 0 : else if (PySlice_Check(item)) {
514 : Py_ssize_t start, stop, step, slicelength, cur, i;
515 :
516 0 : if (PySlice_GetIndicesEx((PySliceObject*)item, size,
517 : &start, &stop, &step, &slicelength) < 0) {
518 0 : return NULL;
519 : }
520 :
521 0 : if (slicelength <= 0)
522 0 : return PyString_FromStringAndSize("", 0);
523 0 : else if (step == 1)
524 0 : return PyString_FromStringAndSize((char *)p + start,
525 : stop - start);
526 : else {
527 : PyObject *result;
528 0 : char *source_buf = (char *)p;
529 0 : char *result_buf = (char *)PyMem_Malloc(slicelength);
530 :
531 0 : if (result_buf == NULL)
532 0 : return PyErr_NoMemory();
533 :
534 0 : for (cur = start, i = 0; i < slicelength;
535 0 : cur += step, i++) {
536 0 : result_buf[i] = source_buf[cur];
537 : }
538 :
539 0 : result = PyString_FromStringAndSize(result_buf,
540 : slicelength);
541 0 : PyMem_Free(result_buf);
542 0 : return result;
543 : }
544 : }
545 : else {
546 0 : PyErr_SetString(PyExc_TypeError,
547 : "sequence index must be integer");
548 0 : return NULL;
549 : }
550 : }
551 :
552 : static int
553 0 : buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
554 : {
555 : PyBufferProcs *pb;
556 : void *ptr1, *ptr2;
557 : Py_ssize_t size;
558 : Py_ssize_t count;
559 :
560 0 : if ( self->b_readonly ) {
561 0 : PyErr_SetString(PyExc_TypeError,
562 : "buffer is read-only");
563 0 : return -1;
564 : }
565 :
566 0 : if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
567 0 : return -1;
568 :
569 0 : if (idx < 0 || idx >= size) {
570 0 : PyErr_SetString(PyExc_IndexError,
571 : "buffer assignment index out of range");
572 0 : return -1;
573 : }
574 :
575 0 : pb = other ? other->ob_type->tp_as_buffer : NULL;
576 0 : if ( pb == NULL ||
577 0 : pb->bf_getreadbuffer == NULL ||
578 0 : pb->bf_getsegcount == NULL )
579 : {
580 0 : PyErr_BadArgument();
581 0 : return -1;
582 : }
583 0 : if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
584 : {
585 : /* ### use a different exception type/message? */
586 0 : PyErr_SetString(PyExc_TypeError,
587 : "single-segment buffer object expected");
588 0 : return -1;
589 : }
590 :
591 0 : if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
592 0 : return -1;
593 0 : if ( count != 1 ) {
594 0 : PyErr_SetString(PyExc_TypeError,
595 : "right operand must be a single byte");
596 0 : return -1;
597 : }
598 :
599 0 : ((char *)ptr1)[idx] = *(char *)ptr2;
600 0 : return 0;
601 : }
602 :
603 : static int
604 0 : buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
605 : {
606 : PyBufferProcs *pb;
607 : void *ptr1, *ptr2;
608 : Py_ssize_t size;
609 : Py_ssize_t slice_len;
610 : Py_ssize_t count;
611 :
612 0 : if ( self->b_readonly ) {
613 0 : PyErr_SetString(PyExc_TypeError,
614 : "buffer is read-only");
615 0 : return -1;
616 : }
617 :
618 0 : pb = other ? other->ob_type->tp_as_buffer : NULL;
619 0 : if ( pb == NULL ||
620 0 : pb->bf_getreadbuffer == NULL ||
621 0 : pb->bf_getsegcount == NULL )
622 : {
623 0 : PyErr_BadArgument();
624 0 : return -1;
625 : }
626 0 : if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
627 : {
628 : /* ### use a different exception type/message? */
629 0 : PyErr_SetString(PyExc_TypeError,
630 : "single-segment buffer object expected");
631 0 : return -1;
632 : }
633 0 : if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
634 0 : return -1;
635 0 : if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
636 0 : return -1;
637 :
638 0 : if ( left < 0 )
639 0 : left = 0;
640 0 : else if ( left > size )
641 0 : left = size;
642 0 : if ( right < left )
643 0 : right = left;
644 0 : else if ( right > size )
645 0 : right = size;
646 0 : slice_len = right - left;
647 :
648 0 : if ( count != slice_len ) {
649 0 : PyErr_SetString(
650 : PyExc_TypeError,
651 : "right operand length must match slice length");
652 0 : return -1;
653 : }
654 :
655 0 : if ( slice_len )
656 0 : memcpy((char *)ptr1 + left, ptr2, slice_len);
657 :
658 0 : return 0;
659 : }
660 :
661 : static int
662 0 : buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
663 : {
664 : PyBufferProcs *pb;
665 : void *ptr1, *ptr2;
666 : Py_ssize_t selfsize;
667 : Py_ssize_t othersize;
668 :
669 0 : if ( self->b_readonly ) {
670 0 : PyErr_SetString(PyExc_TypeError,
671 : "buffer is read-only");
672 0 : return -1;
673 : }
674 :
675 0 : pb = value ? value->ob_type->tp_as_buffer : NULL;
676 0 : if ( pb == NULL ||
677 0 : pb->bf_getreadbuffer == NULL ||
678 0 : pb->bf_getsegcount == NULL )
679 : {
680 0 : PyErr_BadArgument();
681 0 : return -1;
682 : }
683 0 : if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
684 : {
685 : /* ### use a different exception type/message? */
686 0 : PyErr_SetString(PyExc_TypeError,
687 : "single-segment buffer object expected");
688 0 : return -1;
689 : }
690 0 : if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
691 0 : return -1;
692 0 : if (PyIndex_Check(item)) {
693 0 : Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
694 0 : if (i == -1 && PyErr_Occurred())
695 0 : return -1;
696 0 : if (i < 0)
697 0 : i += selfsize;
698 0 : return buffer_ass_item(self, i, value);
699 : }
700 0 : else if (PySlice_Check(item)) {
701 : Py_ssize_t start, stop, step, slicelength;
702 :
703 0 : if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
704 : &start, &stop, &step, &slicelength) < 0)
705 0 : return -1;
706 :
707 0 : if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
708 0 : return -1;
709 :
710 0 : if (othersize != slicelength) {
711 0 : PyErr_SetString(
712 : PyExc_TypeError,
713 : "right operand length must match slice length");
714 0 : return -1;
715 : }
716 :
717 0 : if (slicelength == 0)
718 0 : return 0;
719 0 : else if (step == 1) {
720 0 : memcpy((char *)ptr1 + start, ptr2, slicelength);
721 0 : return 0;
722 : }
723 : else {
724 : Py_ssize_t cur, i;
725 :
726 0 : for (cur = start, i = 0; i < slicelength;
727 0 : cur += step, i++) {
728 0 : ((char *)ptr1)[cur] = ((char *)ptr2)[i];
729 : }
730 :
731 0 : return 0;
732 : }
733 : } else {
734 0 : PyErr_SetString(PyExc_TypeError,
735 : "buffer indices must be integers");
736 0 : return -1;
737 : }
738 : }
739 :
740 : /* Buffer methods */
741 :
742 : static Py_ssize_t
743 0 : buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
744 : {
745 : Py_ssize_t size;
746 0 : if ( idx != 0 ) {
747 0 : PyErr_SetString(PyExc_SystemError,
748 : "accessing non-existent buffer segment");
749 0 : return -1;
750 : }
751 0 : if (!get_buf(self, pp, &size, READ_BUFFER))
752 0 : return -1;
753 0 : return size;
754 : }
755 :
756 : static Py_ssize_t
757 0 : buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
758 : {
759 : Py_ssize_t size;
760 :
761 0 : if ( self->b_readonly )
762 : {
763 0 : PyErr_SetString(PyExc_TypeError, "buffer is read-only");
764 0 : return -1;
765 : }
766 :
767 0 : if ( idx != 0 ) {
768 0 : PyErr_SetString(PyExc_SystemError,
769 : "accessing non-existent buffer segment");
770 0 : return -1;
771 : }
772 0 : if (!get_buf(self, pp, &size, WRITE_BUFFER))
773 0 : return -1;
774 0 : return size;
775 : }
776 :
777 : static Py_ssize_t
778 0 : buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
779 : {
780 : void *ptr;
781 : Py_ssize_t size;
782 0 : if (!get_buf(self, &ptr, &size, ANY_BUFFER))
783 0 : return -1;
784 0 : if (lenp)
785 0 : *lenp = size;
786 0 : return 1;
787 : }
788 :
789 : static Py_ssize_t
790 0 : buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
791 : {
792 : void *ptr;
793 : Py_ssize_t size;
794 0 : if ( idx != 0 ) {
795 0 : PyErr_SetString(PyExc_SystemError,
796 : "accessing non-existent buffer segment");
797 0 : return -1;
798 : }
799 0 : if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
800 0 : return -1;
801 0 : *pp = (const char *)ptr;
802 0 : return size;
803 : }
804 :
805 0 : static int buffer_getbuffer(PyBufferObject *self, Py_buffer *buf, int flags)
806 : {
807 : void *ptr;
808 : Py_ssize_t size;
809 0 : if (!get_buf(self, &ptr, &size, ANY_BUFFER))
810 0 : return -1;
811 0 : return PyBuffer_FillInfo(buf, (PyObject*)self, ptr, size,
812 : self->b_readonly, flags);
813 : }
814 :
815 : static PySequenceMethods buffer_as_sequence = {
816 : (lenfunc)buffer_length, /*sq_length*/
817 : (binaryfunc)buffer_concat, /*sq_concat*/
818 : (ssizeargfunc)buffer_repeat, /*sq_repeat*/
819 : (ssizeargfunc)buffer_item, /*sq_item*/
820 : (ssizessizeargfunc)buffer_slice, /*sq_slice*/
821 : (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
822 : (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
823 : };
824 :
825 : static PyMappingMethods buffer_as_mapping = {
826 : (lenfunc)buffer_length,
827 : (binaryfunc)buffer_subscript,
828 : (objobjargproc)buffer_ass_subscript,
829 : };
830 :
831 : static PyBufferProcs buffer_as_buffer = {
832 : (readbufferproc)buffer_getreadbuf,
833 : (writebufferproc)buffer_getwritebuf,
834 : (segcountproc)buffer_getsegcount,
835 : (charbufferproc)buffer_getcharbuf,
836 : (getbufferproc)buffer_getbuffer,
837 : };
838 :
839 : PyTypeObject PyBuffer_Type = {
840 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
841 : "buffer",
842 : sizeof(PyBufferObject),
843 : 0,
844 : (destructor)buffer_dealloc, /* tp_dealloc */
845 : 0, /* tp_print */
846 : 0, /* tp_getattr */
847 : 0, /* tp_setattr */
848 : (cmpfunc)buffer_compare, /* tp_compare */
849 : (reprfunc)buffer_repr, /* tp_repr */
850 : 0, /* tp_as_number */
851 : &buffer_as_sequence, /* tp_as_sequence */
852 : &buffer_as_mapping, /* tp_as_mapping */
853 : (hashfunc)buffer_hash, /* tp_hash */
854 : 0, /* tp_call */
855 : (reprfunc)buffer_str, /* tp_str */
856 : PyObject_GenericGetAttr, /* tp_getattro */
857 : 0, /* tp_setattro */
858 : &buffer_as_buffer, /* tp_as_buffer */
859 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */
860 : buffer_doc, /* tp_doc */
861 : 0, /* tp_traverse */
862 : 0, /* tp_clear */
863 : 0, /* tp_richcompare */
864 : 0, /* tp_weaklistoffset */
865 : 0, /* tp_iter */
866 : 0, /* tp_iternext */
867 : 0, /* tp_methods */
868 : 0, /* tp_members */
869 : 0, /* tp_getset */
870 : 0, /* tp_base */
871 : 0, /* tp_dict */
872 : 0, /* tp_descr_get */
873 : 0, /* tp_descr_set */
874 : 0, /* tp_dictoffset */
875 : 0, /* tp_init */
876 : 0, /* tp_alloc */
877 : buffer_new, /* tp_new */
878 : };
|