PageRenderTime 168ms CodeModel.GetById 60ms app.highlight 80ms RepoModel.GetById 21ms app.codeStats 0ms

/Objects/bufferobject.c

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