00001
00002
00003
00004
00005 #include "PyROOT.h"
00006 #include "PyBufferFactory.h"
00007
00008
00009 #include <map>
00010
00011 #if PY_VERSION_HEX >= 0x03000000
00012 static PyObject* PyBuffer_FromReadWriteMemory( void* ptr, int size ) {
00013 Py_buffer bufinfo = { ptr, NULL, size, 1, 0, 1, NULL, NULL, NULL, NULL, { 0, 0 }, NULL };
00014 return PyMemoryView_FromBuffer( &bufinfo );
00015 }
00016 #endif
00017
00018
00019
00020 namespace {
00021
00022
00023 struct PyBufferTop_t {
00024 PyObject_HEAD
00025 PyObject* fBase;
00026 void* fPtr;
00027 Py_ssize_t fSize;
00028 };
00029
00030
00031 char* sizeCallback = const_cast< char* >( "_size" );
00032 PyObject* sizeCallbackString_ = PyROOT_PyUnicode_FromString( sizeCallback );
00033
00034
00035 std::map< PyObject*, PyObject* > gSizeCallbacks;
00036
00037
00038 #define PYROOT_PREPARE_PYBUFFER_TYPE( name ) \
00039 PyTypeObject Py##name##Buffer_Type; \
00040 PySequenceMethods Py##name##Buffer_SeqMethods = *(PyBuffer_Type.tp_as_sequence);\
00041 PyMappingMethods Py##name##Buffer_MapMethods;
00042
00043 PYROOT_PREPARE_PYBUFFER_TYPE( Short )
00044 PYROOT_PREPARE_PYBUFFER_TYPE( UShort )
00045 PYROOT_PREPARE_PYBUFFER_TYPE( Int )
00046 PYROOT_PREPARE_PYBUFFER_TYPE( UInt )
00047 PYROOT_PREPARE_PYBUFFER_TYPE( Long )
00048 PYROOT_PREPARE_PYBUFFER_TYPE( ULong )
00049 PYROOT_PREPARE_PYBUFFER_TYPE( Float )
00050 PYROOT_PREPARE_PYBUFFER_TYPE( Double )
00051
00052
00053 Py_ssize_t buffer_length( PyObject* self )
00054 {
00055 #if PY_VERSION_HEX < 0x03000000
00056 Py_ssize_t nlen = (*(PyBuffer_Type.tp_as_sequence->sq_length))(self);
00057 #else
00058 Py_buffer bufinfo;
00059 (*(Py_TYPE(self)->tp_as_buffer->bf_getbuffer))( self, &bufinfo, PyBUF_SIMPLE );
00060 Py_ssize_t nlen = bufinfo.len;
00061 #endif
00062 if ( nlen != INT_MAX )
00063 return nlen;
00064
00065 std::map< PyObject*, PyObject* >::iterator iscbp = gSizeCallbacks.find( self );
00066 if ( iscbp != gSizeCallbacks.end() ) {
00067 PyObject* pylen = PyObject_CallObject( iscbp->second, NULL );
00068 Py_ssize_t nlen2 = PyInt_AsSsize_t( pylen );
00069 Py_DECREF( pylen );
00070
00071 if ( nlen2 == (Py_ssize_t)-1 && PyErr_Occurred() )
00072 PyErr_Clear();
00073 else
00074 return nlen2;
00075 }
00076
00077 return nlen;
00078 }
00079
00080
00081 const char* buffer_get( PyObject* self, int idx )
00082 {
00083 if ( idx < 0 || idx >= buffer_length( self ) ) {
00084 PyErr_SetString( PyExc_IndexError, "buffer index out of range" );
00085 return 0;
00086 }
00087
00088 #if PY_VERSION_HEX < 0x02050000
00089 const char* buf = 0;
00090 #else
00091 char* buf = 0;
00092 #endif
00093 #if PY_VERSION_HEX < 0x03000000
00094 (*(PyBuffer_Type.tp_as_buffer->bf_getcharbuffer))( self, 0, &buf );
00095 #else
00096 Py_buffer bufinfo;
00097 (*(PyBuffer_Type.tp_as_buffer->bf_getbuffer))( self, &bufinfo, PyBUF_SIMPLE );
00098 buf = (char*)bufinfo.buf;
00099 #endif
00100
00101 if ( ! buf )
00102 PyErr_SetString( PyExc_IndexError, "attempt to index a null-buffer" );
00103
00104 return buf;
00105 }
00106
00107
00108 #define PYROOT_IMPLEMENT_PYBUFFER_METHODS( name, type, stype, F1, F2 ) \
00109 PyObject* name##_buffer_str( PyObject* self ) \
00110 { \
00111 Py_ssize_t l = buffer_length( self ); \
00112 return PyROOT_PyUnicode_FromFormat( "<"#type" buffer, size "PY_SSIZE_T_FORMAT">", l );\
00113 } \
00114 \
00115 PyObject* name##_buffer_item( PyObject* self, Py_ssize_t idx ) { \
00116 const char* buf = buffer_get( self, idx ); \
00117 if ( buf ) \
00118 return F1( (stype)*((type*)buf + idx) ); \
00119 return 0; \
00120 } \
00121 \
00122 int name##_buffer_ass_item( PyObject* self, Py_ssize_t idx, PyObject* val ) {\
00123 const char* buf = buffer_get( self, idx ); \
00124 if ( ! buf ) \
00125 return -1; \
00126 \
00127 type value = F2( val ); \
00128 if ( value == (type)-1 && PyErr_Occurred() ) \
00129 return -1; \
00130 \
00131 *((type*)buf+idx) = (type)value; \
00132 return 0; \
00133 } \
00134 \
00135 PyObject* name##_buffer_subscript( PyObject* self, PyObject* item ) { \
00136 if ( PyIndex_Check( item ) ) { \
00137 Py_ssize_t idx = PyNumber_AsSsize_t( item, PyExc_IndexError ); \
00138 if ( idx == -1 && PyErr_Occurred() ) \
00139 return 0; \
00140 return name##_buffer_item( self, idx ); \
00141 } \
00142 return 0; \
00143 }
00144
00145 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Short, Short_t, Long_t, PyInt_FromLong, PyInt_AsLong )
00146 PYROOT_IMPLEMENT_PYBUFFER_METHODS( UShort, UShort_t, Long_t, PyInt_FromLong, PyInt_AsLong )
00147 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Int, Int_t, Long_t, PyInt_FromLong, PyInt_AsLong )
00148 PYROOT_IMPLEMENT_PYBUFFER_METHODS( UInt, UInt_t, Long_t, PyInt_FromLong, PyInt_AsLong )
00149 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Long, Long_t, Long_t, PyLong_FromLong, PyLong_AsLong )
00150 PYROOT_IMPLEMENT_PYBUFFER_METHODS( ULong, ULong_t, ULong_t, PyLong_FromUnsignedLong, PyLong_AsUnsignedLong )
00151 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Float, Float_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble )
00152 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Double, Double_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble )
00153
00154 int pyroot_buffer_ass_subscript( PyObject* self, PyObject* idx, PyObject* val ) {
00155 if ( PyIndex_Check( idx ) ) {
00156 Py_ssize_t i = PyNumber_AsSsize_t( idx, PyExc_IndexError );
00157 if ( i == -1 && PyErr_Occurred() )
00158 return -1;
00159 return Py_TYPE(self)->tp_as_sequence->sq_ass_item( self, i, val );
00160 } else {
00161 PyErr_SetString( PyExc_TypeError, "buffer indices must be integers" );
00162 return -1;
00163 }
00164 }
00165
00166
00167
00168 PyObject* buffer_setsize( PyObject* self, PyObject* pynlen )
00169 {
00170 Py_ssize_t nlen = PyInt_AsSsize_t( pynlen );
00171 if ( nlen == -1 && PyErr_Occurred() )
00172 return 0;
00173
00174 #if PY_VERSION_HEX < 0x03000000
00175 ((PyBufferTop_t*)self)->fSize = nlen;
00176 #else
00177 PyMemoryView_GET_BUFFER(self)->len = nlen;
00178 #endif
00179
00180 Py_INCREF( Py_None );
00181 return Py_None;
00182 }
00183
00184
00185 PyObject* buf_typecode( PyObject* pyobject, void* )
00186 {
00187
00188 if ( PyObject_TypeCheck( pyobject, &PyShortBuffer_Type ) )
00189 return PyBytes_FromString( (char*)"h" );
00190 else if ( PyObject_TypeCheck( pyobject, &PyUShortBuffer_Type ) )
00191 return PyBytes_FromString( (char*)"H" );
00192 else if ( PyObject_TypeCheck( pyobject, &PyIntBuffer_Type ) )
00193 return PyBytes_FromString( (char*)"i" );
00194 else if ( PyObject_TypeCheck( pyobject, &PyUIntBuffer_Type ) )
00195 return PyBytes_FromString( (char*)"I" );
00196 else if ( PyObject_TypeCheck( pyobject, &PyLongBuffer_Type ) )
00197 return PyBytes_FromString( (char*)"l" );
00198 else if ( PyObject_TypeCheck( pyobject, &PyULongBuffer_Type ) )
00199 return PyBytes_FromString( (char*)"L" );
00200 else if ( PyObject_TypeCheck( pyobject, &PyFloatBuffer_Type ) )
00201 return PyBytes_FromString( (char*)"f" );
00202 else if ( PyObject_TypeCheck( pyobject, &PyDoubleBuffer_Type ) )
00203 return PyBytes_FromString( (char*)"d" );
00204
00205 PyErr_SetString( PyExc_TypeError, "received unknown buffer object" );
00206 return 0;
00207 }
00208
00209
00210 PyGetSetDef buffer_getset[] = {
00211 { (char*)"typecode", (getter)buf_typecode, NULL, NULL, NULL },
00212 { (char*)NULL, NULL, NULL, NULL, NULL }
00213 };
00214
00215
00216 PyMethodDef buffer_methods[] = {
00217 { (char*)"SetSize", (PyCFunction)buffer_setsize, METH_O, NULL },
00218 { (char*)NULL, NULL, 0, NULL }
00219 };
00220
00221 }
00222
00223
00224
00225 PyROOT::TPyBufferFactory* PyROOT::TPyBufferFactory::Instance()
00226 {
00227
00228 static TPyBufferFactory* fac = new TPyBufferFactory;
00229 return fac;
00230 }
00231
00232
00233
00234 #define PYROOT_INSTALL_PYBUFFER_METHODS( name, type ) \
00235 Py##name##Buffer_Type.tp_name = (char*)"ROOT.Py"#name"Buffer"; \
00236 Py##name##Buffer_Type.tp_base = &PyBuffer_Type; \
00237 Py##name##Buffer_Type.tp_as_buffer = PyBuffer_Type.tp_as_buffer; \
00238 Py##name##Buffer_SeqMethods.sq_item = (ssizeargfunc)name##_buffer_item; \
00239 Py##name##Buffer_SeqMethods.sq_ass_item = (ssizeobjargproc)name##_buffer_ass_item;\
00240 Py##name##Buffer_SeqMethods.sq_length = (lenfunc)buffer_length; \
00241 Py##name##Buffer_Type.tp_as_sequence = &Py##name##Buffer_SeqMethods; \
00242 if ( PyBuffer_Type.tp_as_mapping ) { \
00243 Py##name##Buffer_MapMethods.mp_length = (lenfunc)buffer_length; \
00244 Py##name##Buffer_MapMethods.mp_subscript = (binaryfunc)name##_buffer_subscript;\
00245 Py##name##Buffer_MapMethods.mp_ass_subscript = (objobjargproc)pyroot_buffer_ass_subscript;\
00246 Py##name##Buffer_Type.tp_as_mapping = &Py##name##Buffer_MapMethods; \
00247 } \
00248 Py##name##Buffer_Type.tp_str = (reprfunc)name##_buffer_str; \
00249 Py##name##Buffer_Type.tp_methods = buffer_methods; \
00250 Py##name##Buffer_Type.tp_getset = buffer_getset; \
00251 PyType_Ready( &Py##name##Buffer_Type );
00252
00253 PyROOT::TPyBufferFactory::TPyBufferFactory()
00254 {
00255
00256 PYROOT_INSTALL_PYBUFFER_METHODS( Short, Short_t )
00257 PYROOT_INSTALL_PYBUFFER_METHODS( UShort, UShort_t )
00258 PYROOT_INSTALL_PYBUFFER_METHODS( Int, Int_t )
00259 PYROOT_INSTALL_PYBUFFER_METHODS( UInt, UInt_t )
00260 PYROOT_INSTALL_PYBUFFER_METHODS( Long, Long_t )
00261 PYROOT_INSTALL_PYBUFFER_METHODS( ULong, ULong_t )
00262 PYROOT_INSTALL_PYBUFFER_METHODS( Float, Float_t )
00263 PYROOT_INSTALL_PYBUFFER_METHODS( Double, Double_t )
00264 }
00265
00266
00267 PyROOT::TPyBufferFactory::~TPyBufferFactory()
00268 {
00269 }
00270
00271
00272
00273 #define PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( name, type ) \
00274 PyObject* PyROOT::TPyBufferFactory::PyBuffer_FromMemory( type* address, Py_ssize_t size )\
00275 { \
00276 size = size < 0 ? INT_MAX : size; \
00277 PyObject* buf = PyBuffer_FromReadWriteMemory( (void*)address, size ); \
00278 if ( buf ) { \
00279 Py_INCREF( (PyObject*)(void*)&Py##name##Buffer_Type ); \
00280 buf->ob_type = &Py##name##Buffer_Type; \
00281 } \
00282 return buf; \
00283 } \
00284 \
00285 PyObject* PyROOT::TPyBufferFactory::PyBuffer_FromMemory( type* address, PyObject* scb )\
00286 { \
00287 PyObject* buf = PyBuffer_FromMemory( address, Py_ssize_t(0) ); \
00288 if ( buf != 0 && PyCallable_Check( scb ) ) { \
00289 Py_INCREF( scb ); \
00290 gSizeCallbacks[ buf ] = scb; \
00291 } \
00292 return buf; \
00293 }
00294
00295 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Short, Short_t )
00296 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( UShort, UShort_t )
00297 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Int, Int_t )
00298 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( UInt, UInt_t )
00299 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Long, Long_t )
00300 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( ULong, ULong_t )
00301 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Float, Float_t )
00302 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Double, Double_t )