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