bufferobject.c revision a44d353e2b6d947d36ab9d36c1fc84335a0878fe
10ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold/***********************************************************
20ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldCopyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
30ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldThe Netherlands.
40ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
52f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa                        All Rights Reserved
60ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
70ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldPermission to use, copy, modify, and distribute this software and its
86c55bdb98e967675456a71a0971b81058536cac8Chris Sosadocumentation for any purpose and without fee is hereby granted,
9a0261611f9be78ee9d456fd50bea81e9eda07c17Gilad Arnoldprovided that the above copyright notice appear in all copies and that
1015384a4ded97f171906a72106791d19e96e68fa7Gilad Arnoldboth that copyright notice and this permission notice appear in
110ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldsupporting documentation, and that the names of Stichting Mathematisch
120ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldCentrum or CWI or Corporation for National Research Initiatives or
1303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad ArnoldCNRI not be used in advertising or publicity pertaining to
146c55bdb98e967675456a71a0971b81058536cac8Chris Sosadistribution of the software without specific, written prior
156c55bdb98e967675456a71a0971b81058536cac8Chris Sosapermission.
160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
178ddeb9c8d6df7eb2e033651e39f434ebdf8af3ccSimran BasiWhile CWI is the initial source for this software, a modified version
182f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosais made available by the Corporation for National Research Initiatives
190ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold(CNRI) at the Internet address ftp://ftp.python.org.
200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
210ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldSTICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
220ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldREGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
230338ff3b754d52b41ca2d0432164a757daa1112dGilad ArnoldMERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
240ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldCENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
250ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
260ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
270ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldTORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
280ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldPERFORMANCE OF THIS SOFTWARE.
290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
30ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa******************************************************************/
31ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa
32ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa/* Buffer object implementation */
33f789cf3a52c720344062f0a6c782bb758f08b189Don Garrett
34f789cf3a52c720344062f0a6c782bb758f08b189Don Garrett#include "Python.h"
35f789cf3a52c720344062f0a6c782bb758f08b189Don Garrett
36ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa
370338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnoldtypedef struct {
380338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	PyObject_HEAD
390338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	PyObject *b_base;
400338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	void *b_ptr;
410338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int b_size;
420338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int b_readonly;
430338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold#ifdef CACHE_HASH
440338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	long b_hash;
450338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold#endif
460338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold} PyBufferObject;
470338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
480338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
490338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnoldstatic PyObject *
500338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold_PyBuffer_FromMemory(base, ptr, size, readonly)
510ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyObject *base;
52ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	void *ptr;
53ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	int size;
54ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	int readonly;
55ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa{
56ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	PyBufferObject * b;
57ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa
58ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	if ( size < 0 ) {
59ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa		PyErr_SetString(PyExc_ValueError,
6045f02ae47134953169805d281992c9edf0019250Chris Sosa				"size must be zero or positive");
6145f02ae47134953169805d281992c9edf0019250Chris Sosa		return NULL;
6245f02ae47134953169805d281992c9edf0019250Chris Sosa	}
630338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
640338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
650338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	if ( b == NULL )
660338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		return NULL;
670338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
680338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	Py_XINCREF(base);
690338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	b->b_base = base;
700338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	b->b_ptr = ptr;
710338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	b->b_size = size;
720338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	b->b_readonly = readonly;
730338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold#ifdef CACHE_HASH
740338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	b->b_hash = -1;
750338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold#endif
760338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
770338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	return (PyObject *) b;
780338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold}
790338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
800338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnoldstatic PyObject *
810338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold_PyBuffer_FromObject(base, offset, size, proc, readonly)
820338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	PyObject *base;
830338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int offset;
840338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int size;
8545f02ae47134953169805d281992c9edf0019250Chris Sosa	getreadbufferproc proc;
860ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	int readonly;
87ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa{
880338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	PyBufferProcs *pb = base->ob_type->tp_as_buffer;
8945f02ae47134953169805d281992c9edf0019250Chris Sosa	void *p;
9045f02ae47134953169805d281992c9edf0019250Chris Sosa	int count;
910338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
9245f02ae47134953169805d281992c9edf0019250Chris Sosa	if ( offset < 0 ) {
9345f02ae47134953169805d281992c9edf0019250Chris Sosa		PyErr_SetString(PyExc_ValueError,
940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold				"offset must be zero or positive");
950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return NULL;
960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	{
100ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa		PyErr_SetString(PyExc_TypeError,
1010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold				"single-segment buffer object expected");
1020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return NULL;
1030338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	}
1040338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	if ( (count = (*proc)(base, 0, &p)) < 0 )
1050338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		return NULL;
1060338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
1070338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	/* apply constraints to the start/end */
1080338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	if ( size == Py_END_OF_BUFFER || size < 0 )
1090338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		size = count;
1100338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	if ( offset > count )
1110338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		offset = count;
1120338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	if ( offset + size > count )
1130338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		size = count - offset;
1140338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
1150338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	/* if the base object is another buffer, then "deref" it */
1160338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	if ( PyBuffer_Check(base) )
1170338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		base = ((PyBufferObject *)base)->b_base;
1180338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
1190338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	return _PyBuffer_FromMemory(base, (char *)p + offset, size, readonly);
1200338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold}
1210338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
1220338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
1230338ff3b754d52b41ca2d0432164a757daa1112dGilad ArnoldPyObject *
1240338ff3b754d52b41ca2d0432164a757daa1112dGilad ArnoldPyBuffer_FromObject(base, offset, size)
1250338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	PyObject *base;
1260338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int offset;
1270338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int size;
1280338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold{
1290338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	PyBufferProcs *pb = base->ob_type->tp_as_buffer;
1300338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
1310338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	if ( pb == NULL ||
1320338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	     pb->bf_getreadbuffer == NULL ||
1330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	     pb->bf_getsegcount == NULL )
1340338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	{
1350338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		PyErr_SetString(PyExc_TypeError, "buffer object expected");
1360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return NULL;
1370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
1380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
1390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	return _PyBuffer_FromObject(base, offset, size,
1400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold				    pb->bf_getreadbuffer, 1);
1410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold}
1420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
143ae6acd9b3e1c6f56310cdb4e05737122b7b2818cChris SosaPyObject *
1440ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldPyBuffer_FromReadWriteObject(base, offset, size)
1450ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyObject *base;
1460ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	int offset;
1470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	int size;
1480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold{
1490ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyBufferProcs *pb = base->ob_type->tp_as_buffer;
1500ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
1510ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( pb == NULL ||
1520ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	     pb->bf_getwritebuffer == NULL ||
1530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	     pb->bf_getsegcount == NULL )
1540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	{
1550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		PyErr_SetString(PyExc_TypeError, "buffer object expected");
1560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return NULL;
1570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
1580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
1590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	return _PyBuffer_FromObject(base, offset, size,
1600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold				    (getreadbufferproc)pb->bf_getwritebuffer,
1610ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold				    0);
1620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold}
1630ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
16445f02ae47134953169805d281992c9edf0019250Chris SosaPyObject *
16545f02ae47134953169805d281992c9edf0019250Chris SosaPyBuffer_FromMemory(ptr, size)
1660338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	void *ptr;
1670338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int size;
1680338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold{
16945f02ae47134953169805d281992c9edf0019250Chris Sosa	return _PyBuffer_FromMemory(NULL, ptr, size, 1);
17045f02ae47134953169805d281992c9edf0019250Chris Sosa}
1710338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
17245f02ae47134953169805d281992c9edf0019250Chris SosaPyObject *
17345f02ae47134953169805d281992c9edf0019250Chris SosaPyBuffer_FromReadWriteMemory(ptr, size)
17445f02ae47134953169805d281992c9edf0019250Chris Sosa	void *ptr;
1750338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int size;
1760338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold{
1770338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	return _PyBuffer_FromMemory(NULL, ptr, size, 0);
1780338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold}
1790338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold
1800338ff3b754d52b41ca2d0432164a757daa1112dGilad ArnoldPyObject *
1810338ff3b754d52b41ca2d0432164a757daa1112dGilad ArnoldPyBuffer_New(size)
1820338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	int size;
1830338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold{
184fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa	PyBufferObject * b;
185fec1349a3e70eb41dce8bc07a8c63563d23d64b2Chris Sosa
1860338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	if (size < 0) {
1870338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		PyErr_SetString(PyExc_ValueError,
1880338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold				"size must be zero or positive");
1890338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold		return NULL;
1900ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
1910ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	/* PyObject_New is inlined */
1920ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	b = (PyBufferObject *) PyObject_MALLOC(sizeof(*b) + size);
1930ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( b == NULL )
1940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return PyErr_NoMemory();
1950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyObject_INIT((PyObject *)b, &PyBuffer_Type);
1960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
1970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	b->b_base = NULL;
1980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	b->b_ptr = (void *)(b + 1);
1990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	b->b_size = size;
2000ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	b->b_readonly = 0;
2010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold#ifdef CACHE_HASH
2020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	b->b_hash = -1;
2030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold#endif
2040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
2050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	return (PyObject *) b;
2060ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold}
2070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
208cfa14a695654bc9cbfe9b9ce5868d669d0c57e0fGilad Arnold/* Methods */
209cfa14a695654bc9cbfe9b9ce5868d669d0c57e0fGilad Arnold
210cfa14a695654bc9cbfe9b9ce5868d669d0c57e0fGilad Arnoldstatic void
2110ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldbuffer_dealloc(self)
2120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyBufferObject *self;
2130ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold{
2140ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	Py_XDECREF(self->b_base);
2150ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyObject_DEL(self);
2160ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold}
2170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
2180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldstatic int
2190ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldbuffer_compare(self, other)
2200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyBufferObject *self;
2210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyBufferObject *other;
2220ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold{
2230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	int len_self = self->b_size;
2240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	int len_other = other->b_size;
2250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	int min_len = (len_self < len_other) ? len_self : len_other;
2260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	int cmp;
2270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if (min_len > 0) {
2280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
2290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		if (cmp != 0)
2300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold			return cmp;
2310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
2320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
2330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold}
234ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa
2350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldstatic PyObject *
2360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldbuffer_repr(self)
2370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyBufferObject *self;
2380338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold{
239ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	char buf[300];
240ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	char *status = self->b_readonly ? "read-only" : "read-write";
2410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
2420ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( self->b_base == NULL )
243ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	{
244ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa		sprintf(buf, "<%s buffer ptr %p, size %d at %p>",
245ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa			status,
246ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa			self->b_ptr,
2470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold			self->b_size,
2480ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold			self);
249cfa14a695654bc9cbfe9b9ce5868d669d0c57e0fGilad Arnold	}
250cfa14a695654bc9cbfe9b9ce5868d669d0c57e0fGilad Arnold	else
2510ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	{
2520ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		sprintf(buf, "<%s buffer for %p, ptr %p, size %d at %p>",
2530ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold			status,
2540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold			self->b_base,
2550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold			self->b_ptr,
2560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold			self->b_size,
2570ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold			self);
2580ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
2590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
2600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	return PyString_FromString(buf);
2610ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold}
2620ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
2630ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldstatic long
2640ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldbuffer_hash(self)
2650338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	PyBufferObject *self;
2660338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold{
2670ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	register int len;
2680ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	register unsigned char *p;
2690ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	register long x;
2700ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
2710ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold#ifdef CACHE_HASH
2720ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( self->b_hash != -1 )
2730ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return self->b_hash;
2740338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold#endif
2750ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
2760ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( !self->b_readonly )
2770ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	{
2780ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		/* ### use different wording, since this is conditional? */
2790ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		PyErr_SetString(PyExc_TypeError, "unhashable type");
28003901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold		return -1;
2810ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
28203901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold
2830ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	len = self->b_size;
2840ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	p = (unsigned char *) self->b_ptr;
2850ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	x = *p << 7;
2860ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	while (--len >= 0)
2870ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		x = (1000003*x) ^ *p++;
288ae6acd9b3e1c6f56310cdb4e05737122b7b2818cChris Sosa	x ^= self->b_size;
289ae6acd9b3e1c6f56310cdb4e05737122b7b2818cChris Sosa	if (x == -1)
290ae6acd9b3e1c6f56310cdb4e05737122b7b2818cChris Sosa		x = -2;
291ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa#ifdef CACHE_HASH
292ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	self->b_hash = x;
293ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa#endif
294ae6acd9b3e1c6f56310cdb4e05737122b7b2818cChris Sosa	return x;
295ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa}
2960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
2970ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldstatic PyObject *
2980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldbuffer_str(self)
2990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyBufferObject *self;
3000ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold{
3010ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	return PyString_FromStringAndSize(self->b_ptr, self->b_size);
3020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold}
3030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
3040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold/* Sequence methods */
3050ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
30603901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnoldstatic int
3070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldbuffer_length(self)
3080ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyBufferObject *self;
3090ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold{
3100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	return self->b_size;
31103901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold}
31203901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold
31303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnoldstatic PyObject *
31403901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnoldbuffer_concat(self, other)
31503901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold	PyBufferObject *self;
31603901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold	PyObject *other;
31703901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold{
3180338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	PyBufferProcs *pb = other->ob_type->tp_as_buffer;
31903901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold	char *p1;
320a0261611f9be78ee9d456fd50bea81e9eda07c17Gilad Arnold	void *p2;
321a0261611f9be78ee9d456fd50bea81e9eda07c17Gilad Arnold	PyObject *ob;
322a0261611f9be78ee9d456fd50bea81e9eda07c17Gilad Arnold	int count;
32303901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold
3240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( pb == NULL ||
3250ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	     pb->bf_getreadbuffer == NULL ||
3260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	     pb->bf_getsegcount == NULL )
3270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	{
32803901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold		PyErr_BadArgument();
3290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return NULL;
3300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
3310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
3320338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	{
3330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		/* ### use a different exception type/message? */
3340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		PyErr_SetString(PyExc_TypeError,
3350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold				"single-segment buffer object expected");
336793344b359304c31d78197788b55cfbbe2636025Chris Sosa		return NULL;
337793344b359304c31d78197788b55cfbbe2636025Chris Sosa	}
338793344b359304c31d78197788b55cfbbe2636025Chris Sosa
339793344b359304c31d78197788b55cfbbe2636025Chris Sosa	/* optimize special case */
3400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( self->b_size == 0 )
3410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	{
342793344b359304c31d78197788b55cfbbe2636025Chris Sosa	    Py_INCREF(other);
3430ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	    return other;
344793344b359304c31d78197788b55cfbbe2636025Chris Sosa	}
345260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
34603901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
3470ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return NULL;
3486f36e954e1d73e961b8d47ebf4ec7d267c4307f4Gilad Arnold
3496f36e954e1d73e961b8d47ebf4ec7d267c4307f4Gilad Arnold	/* optimize special case */
3506f36e954e1d73e961b8d47ebf4ec7d267c4307f4Gilad Arnold	if ( count == 0 )
351793344b359304c31d78197788b55cfbbe2636025Chris Sosa	{
352793344b359304c31d78197788b55cfbbe2636025Chris Sosa	    Py_INCREF(self);
353260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	    return (PyObject *)self;
3540ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
3550ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
3560ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	ob = PyString_FromStringAndSize(NULL, self->b_size + count);
35703901089c0db27508a6b2ff61ae8b75eba77cf37Gilad Arnold	p1 = PyString_AS_STRING(ob);
358ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	memcpy(p1, self->b_ptr, self->b_size);
3590ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	memcpy(p1 + self->b_size, p2, count);
3600ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
361ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	/* there is an extra byte in the string object, so this is safe */
3620338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	p1[self->b_size + count] = '\0';
3630ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
3646c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	return ob;
365260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold}
366260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
3676c55bdb98e967675456a71a0971b81058536cac8Chris Sosastatic PyObject *
368ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosabuffer_repeat(self, count)
3696c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	PyBufferObject *self;
3706c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	int count;
3716c55bdb98e967675456a71a0971b81058536cac8Chris Sosa{
372260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	PyObject *ob;
3733563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	register char *p;
3743563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	void *ptr = self->b_ptr;
3753563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	int size = self->b_size;
3763563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa
3773563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	if ( count < 0 )
3783563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa		count = 0;
3793563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	ob = PyString_FromStringAndSize(NULL, size * count);
3803563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	if ( ob == NULL )
3813563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa		return NULL;
3823563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa
3833563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	p = PyString_AS_STRING(ob);
3843563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	while ( count-- )
3853563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	{
3863563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	    memcpy(p, ptr, size);
3873563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	    p += size;
3883563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	}
3893563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa
3903563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	/* there is an extra byte in the string object, so this is safe */
391260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	*p = '\0';
3923563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa
3933563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	return ob;
394260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold}
395260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
3963563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosastatic PyObject *
397260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldbuffer_item(self, idx)
398260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	PyBufferObject *self;
399260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	int idx;
400260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold{
401260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( idx < 0 || idx >= self->b_size )
4023563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	{
4033563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa		PyErr_SetString(PyExc_IndexError, "buffer index out of range");
4043563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa		return NULL;
405260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	}
406260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
407260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold}
408260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
409260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldstatic PyObject *
410260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldbuffer_slice(self, left, right)
411260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	PyBufferObject *self;
412260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	int left;
413260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	int right;
414260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold{
415260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( left < 0 )
416260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		left = 0;
417260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( right < 0 )
418260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		right = 0;
419260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( right > self->b_size )
420260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		right = self->b_size;
421260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( left == 0 && right == self->b_size )
422260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	{
423260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		/* same as self */
424260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		Py_INCREF(self);
425260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		return (PyObject *)self;
426260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	}
4270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( right < left )
4286c55bdb98e967675456a71a0971b81058536cac8Chris Sosa		right = left;
429793344b359304c31d78197788b55cfbbe2636025Chris Sosa	return PyString_FromStringAndSize((char *)self->b_ptr + left,
430793344b359304c31d78197788b55cfbbe2636025Chris Sosa					  right - left);
431793344b359304c31d78197788b55cfbbe2636025Chris Sosa}
432260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
433260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldstatic int
434793344b359304c31d78197788b55cfbbe2636025Chris Sosabuffer_ass_item(self, idx, other)
435793344b359304c31d78197788b55cfbbe2636025Chris Sosa	PyBufferObject *self;
436793344b359304c31d78197788b55cfbbe2636025Chris Sosa	int idx;
437793344b359304c31d78197788b55cfbbe2636025Chris Sosa	PyObject *other;
438260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold{
439260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	PyBufferProcs *pb;
440260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	void *p;
441260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	int count;
44294b9ad4983cc735e162a3549c1628d08241b0d57Gilad Arnold
443260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( self->b_readonly ) {
444260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		PyErr_SetString(PyExc_TypeError,
445260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold				"buffer is read-only");
446260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		return -1;
447260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	}
448260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
449260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if (idx < 0 || idx >= self->b_size) {
450260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		PyErr_SetString(PyExc_IndexError,
451260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold				"buffer assignment index out of range");
452260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		return -1;
453260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	}
454260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
45594b9ad4983cc735e162a3549c1628d08241b0d57Gilad Arnold	pb = other ? other->ob_type->tp_as_buffer : NULL;
456260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( pb == NULL ||
457260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	     pb->bf_getreadbuffer == NULL ||
458260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	     pb->bf_getsegcount == NULL )
459260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	{
460260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		PyErr_BadArgument();
461260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		return -1;
462260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	}
463260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
464260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	{
465260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		/* ### use a different exception type/message? */
466793344b359304c31d78197788b55cfbbe2636025Chris Sosa		PyErr_SetString(PyExc_TypeError,
467793344b359304c31d78197788b55cfbbe2636025Chris Sosa				"single-segment buffer object expected");
468793344b359304c31d78197788b55cfbbe2636025Chris Sosa		return -1;
469793344b359304c31d78197788b55cfbbe2636025Chris Sosa	}
470793344b359304c31d78197788b55cfbbe2636025Chris Sosa
471793344b359304c31d78197788b55cfbbe2636025Chris Sosa	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
472793344b359304c31d78197788b55cfbbe2636025Chris Sosa		return -1;
473260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( count != 1 ) {
474260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		PyErr_SetString(PyExc_TypeError,
475793344b359304c31d78197788b55cfbbe2636025Chris Sosa				"right operand must be a single byte");
476793344b359304c31d78197788b55cfbbe2636025Chris Sosa		return -1;
4776c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	}
478793344b359304c31d78197788b55cfbbe2636025Chris Sosa
479793344b359304c31d78197788b55cfbbe2636025Chris Sosa	((char *)self->b_ptr)[idx] = *(char *)p;
480793344b359304c31d78197788b55cfbbe2636025Chris Sosa	return 0;
481260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold}
482793344b359304c31d78197788b55cfbbe2636025Chris Sosa
483793344b359304c31d78197788b55cfbbe2636025Chris Sosastatic int
4846c55bdb98e967675456a71a0971b81058536cac8Chris Sosabuffer_ass_slice(self, left, right, other)
4852f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa	PyBufferObject *self;
486ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	int left;
4873563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	int right;
4883563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	PyObject *other;
4893563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa{
4903563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	PyBufferProcs *pb;
4913563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	void *p;
4923563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	int slice_len;
4933563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa	int count;
4943563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa
4956f36e954e1d73e961b8d47ebf4ec7d267c4307f4Gilad Arnold	if ( self->b_readonly ) {
4966f36e954e1d73e961b8d47ebf4ec7d267c4307f4Gilad Arnold		PyErr_SetString(PyExc_TypeError,
4976f36e954e1d73e961b8d47ebf4ec7d267c4307f4Gilad Arnold				"buffer is read-only");
4980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return -1;
4996f36e954e1d73e961b8d47ebf4ec7d267c4307f4Gilad Arnold	}
5006f36e954e1d73e961b8d47ebf4ec7d267c4307f4Gilad Arnold
5016c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	pb = other ? other->ob_type->tp_as_buffer : NULL;
5020ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( pb == NULL ||
503260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	     pb->bf_getreadbuffer == NULL ||
504260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	     pb->bf_getsegcount == NULL )
505260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	{
506260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		PyErr_BadArgument();
5070ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		return -1;
5080ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
5090ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
5100ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	{
5113563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa		/* ### use a different exception type/message? */
5120ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold		PyErr_SetString(PyExc_TypeError,
513260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold				"single-segment buffer object expected");
5146c55bdb98e967675456a71a0971b81058536cac8Chris Sosa		return -1;
515260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	}
516260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
517260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		return -1;
518260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
519260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( left < 0 )
5206c55bdb98e967675456a71a0971b81058536cac8Chris Sosa		left = 0;
521260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	else if ( left > self->b_size )
522260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		left = self->b_size;
523260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( right < left )
524260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		right = left;
525260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	else if ( right > self->b_size )
5263563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa		right = self->b_size;
527260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	slice_len = right - left;
52838ba6b79b19b5bdd9cfe71b26efd0c267768527aGilad Arnold
5296c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	if ( count != slice_len ) {
530260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		PyErr_SetString(
531260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold			PyExc_TypeError,
532260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold			"right operand length must match slice length");
533cfa14a695654bc9cbfe9b9ce5868d669d0c57e0fGilad Arnold		return -1;
534260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	}
5356c55bdb98e967675456a71a0971b81058536cac8Chris Sosa
536260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( slice_len )
5376c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	    memcpy((char *)self->b_ptr + left, p, slice_len);
5386c55bdb98e967675456a71a0971b81058536cac8Chris Sosa
539260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	return 0;
540260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold}
541260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
542260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold/* Buffer methods */
543260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
544260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldstatic int
545260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldbuffer_getreadbuf(self, idx, pp)
546260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	PyBufferObject *self;
547260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	int idx;
548260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	void ** pp;
549260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold{
550260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( idx != 0 ) {
551260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		PyErr_SetString(PyExc_SystemError,
5526c55bdb98e967675456a71a0971b81058536cac8Chris Sosa				"accessing non-existent buffer segment");
5536c55bdb98e967675456a71a0971b81058536cac8Chris Sosa		return -1;
554260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	}
555260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	*pp = self->b_ptr;
556260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	return self->b_size;
557260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold}
558260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
559260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldstatic int
560260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldbuffer_getwritebuf(self, idx, pp)
5616c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	PyBufferObject *self;
5626c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	int idx;
5636c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	void ** pp;
5646c55bdb98e967675456a71a0971b81058536cac8Chris Sosa{
565260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( self->b_readonly )
5660338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	{
5676c55bdb98e967675456a71a0971b81058536cac8Chris Sosa		PyErr_SetString(PyExc_TypeError, "buffer is read-only");
568260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		return -1;
5690ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
5706c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	return buffer_getreadbuf(self, idx, pp);
5712f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa}
5722f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa
5732f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosastatic int
5742f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosabuffer_getsegcount(self, lenp)
5752f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa	PyBufferObject *self;
5762f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa	int *lenp;
577260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold{
578260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	if ( lenp )
579260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		*lenp = self->b_size;
580260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	return 1;
581260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold}
582260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold
583260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldstatic int
584260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnoldbuffer_getcharbuf(self, idx, pp)
585260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	PyBufferObject *self;
586260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	int idx;
587260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	const char ** pp;
5883563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa{
58919426059c61c1b318b5d4bd04d70dacb63ec827dChris Sosa	if ( idx != 0 ) {
59019426059c61c1b318b5d4bd04d70dacb63ec827dChris Sosa		PyErr_SetString(PyExc_SystemError,
59119426059c61c1b318b5d4bd04d70dacb63ec827dChris Sosa				"accessing non-existent buffer segment");
592260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold		return -1;
5930ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	}
5940ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	*pp = (const char *)self->b_ptr;
5950ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	return self->b_size;
5960ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold}
5972f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa
5980ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
5990ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnoldstatic PySequenceMethods buffer_as_sequence = {
6002f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa	(inquiry)buffer_length, /*sq_length*/
6012f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa	(binaryfunc)buffer_concat, /*sq_concat*/
6022f1ae9f1f2464ebbeb226a6669fa90ef211a179cChris Sosa	(intargfunc)buffer_repeat, /*sq_repeat*/
6030ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	(intargfunc)buffer_item, /*sq_item*/
6040ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	(intintargfunc)buffer_slice, /*sq_slice*/
605260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	(intobjargproc)buffer_ass_item, /*sq_ass_item*/
606260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	(intintobjargproc)buffer_ass_slice, /*sq_ass_slice*/
6076c55bdb98e967675456a71a0971b81058536cac8Chris Sosa};
608ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa
609ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosastatic PyBufferProcs buffer_as_buffer = {
6106c55bdb98e967675456a71a0971b81058536cac8Chris Sosa	(getreadbufferproc)buffer_getreadbuf,
6110338ff3b754d52b41ca2d0432164a757daa1112dGilad Arnold	(getwritebufferproc)buffer_getwritebuf,
612260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold	(getsegcountproc)buffer_getsegcount,
61319426059c61c1b318b5d4bd04d70dacb63ec827dChris Sosa	(getcharbufferproc)buffer_getcharbuf,
614260957d6079ee23ec6c9857a95fa183a78741b0bGilad Arnold};
6153563042207623fbb9db02018156e8b5fa0e4c2c3Chris Sosa
6160ed760cbee4ce839988585003d445465bb0b95b9Gilad ArnoldPyTypeObject PyBuffer_Type = {
6170ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	PyObject_HEAD_INIT(&PyType_Type)
6180ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,
6190ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	"buffer",
6200ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	sizeof(PyBufferObject),
6210ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,
6220ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	(destructor)buffer_dealloc, /*tp_dealloc*/
6230ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,		/*tp_print*/
6240ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,		/*tp_getattr*/
625ed8c1858bc32b066e4fbe4100a9ad49bdf1adc61Chris Sosa	0,		/*tp_setattr*/
6260ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	(cmpfunc)buffer_compare, /*tp_compare*/
6270ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	(reprfunc)buffer_repr, /*tp_repr*/
6280ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,		/*tp_as_number*/
6290ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	&buffer_as_sequence,	/*tp_as_sequence*/
6300ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,		/*tp_as_mapping*/
6310ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	(hashfunc)buffer_hash,	/*tp_hash*/
6320ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,		/*tp_call*/
6330ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	(reprfunc)buffer_str,		/*tp_str*/
6340ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,		/*tp_getattro*/
6350ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,		/*tp_setattro*/
6360ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	&buffer_as_buffer,	/*tp_as_buffer*/
6370ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	Py_TPFLAGS_DEFAULT,	/*tp_flags*/
6380ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold	0,		/*tp_doc*/
6390ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold};
6400ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold
6410ed760cbee4ce839988585003d445465bb0b95b9Gilad Arnold