11 #if PY_VERSION_HEX >= 0x03000000
12 static PyObject* PyBuffer_FromReadWriteMemory(
void* ptr,
int size ) {
13 #if PY_VERSION_HEX > 0x03000000
21 Py_buffer bufinfo = { ptr, NULL, size, 1, 0, 1, NULL, NULL, NULL, NULL,
22 #if PY_VERSION_HEX < 0x03030000
26 return PyMemoryView_FromBuffer( &bufinfo );
35 struct PyBufferTop_t {
44 std::map< PyObject*, PyObject* > gSizeCallbacks;
47 #define PYROOT_PREPARE_PYBUFFER_TYPE( name ) \
48 PyTypeObject Py##name##Buffer_Type; \
49 PySequenceMethods Py##name##Buffer_SeqMethods = *(PyBuffer_Type.tp_as_sequence);\
50 PyMappingMethods Py##name##Buffer_MapMethods;
52 PYROOT_PREPARE_PYBUFFER_TYPE( Bool )
53 PYROOT_PREPARE_PYBUFFER_TYPE( Char )
54 PYROOT_PREPARE_PYBUFFER_TYPE( UChar )
55 PYROOT_PREPARE_PYBUFFER_TYPE( Short )
56 PYROOT_PREPARE_PYBUFFER_TYPE( UShort )
57 PYROOT_PREPARE_PYBUFFER_TYPE( Int )
58 PYROOT_PREPARE_PYBUFFER_TYPE( UInt )
59 PYROOT_PREPARE_PYBUFFER_TYPE( Long )
60 PYROOT_PREPARE_PYBUFFER_TYPE( ULong )
61 PYROOT_PREPARE_PYBUFFER_TYPE( Float )
62 PYROOT_PREPARE_PYBUFFER_TYPE( Double )
65 Py_ssize_t buffer_length( PyObject* self )
68 #if PY_VERSION_HEX < 0x03000000
69 Py_ssize_t nlen = ((PyBufferTop_t*)
self)->fSize;
70 Py_ssize_t item = ((PyBufferTop_t*)
self)->fItemSize;
72 Py_buffer* bufinfo = PyMemoryView_GET_BUFFER(
self);
73 Py_ssize_t nlen = bufinfo->len;
74 Py_ssize_t item = bufinfo->itemsize;
76 if ( nlen != INT_MAX )
79 std::map< PyObject*, PyObject* >::iterator iscbp = gSizeCallbacks.find(
self );
80 if ( iscbp != gSizeCallbacks.end() ) {
81 PyObject* pylen = PyObject_CallObject( iscbp->second, NULL );
82 Py_ssize_t nlen2 = PyInt_AsSsize_t( pylen );
85 if ( nlen2 == (Py_ssize_t)-1 && PyErr_Occurred() )
97 const char* buffer_get( PyObject*
self,
int idx )
99 if ( idx < 0 || idx >= buffer_length(
self ) ) {
100 PyErr_SetString( PyExc_IndexError,
"buffer index out of range" );
104 #if PY_VERSION_HEX < 0x02050000
109 #if PY_VERSION_HEX < 0x03000000
110 (*(PyBuffer_Type.tp_as_buffer->bf_getcharbuffer))(
self, 0, &buf );
113 (*(PyBuffer_Type.tp_as_buffer->bf_getbuffer))(
self, &bufinfo, PyBUF_SIMPLE );
114 buf = (
char*)bufinfo.buf;
115 (*(PyBuffer_Type.tp_as_buffer->bf_releasebuffer))(
self, &bufinfo);
116 Py_DECREF(bufinfo.obj);
120 PyErr_SetString( PyExc_IndexError,
"attempt to index a null-buffer" );
127 #define PYROOT_IMPLEMENT_PYBUFFER_METHODS( name, type, stype, F1, F2 ) \
128 PyObject* name##_buffer_str( PyObject* self ) \
130 Py_ssize_t l = buffer_length( self ); \
131 return PyROOT_PyUnicode_FromFormat( "<"#type" buffer, size " PY_SSIZE_T_FORMAT ">", l );\
134 PyObject* name##_buffer_item( PyObject* self, Py_ssize_t idx ) { \
135 const char* buf = buffer_get( self, idx ); \
137 return F1( (stype)*((type*)buf + idx) ); \
141 int name##_buffer_ass_item( PyObject* self, Py_ssize_t idx, PyObject* val ) {\
142 const char* buf = buffer_get( self, idx ); \
146 type value = F2( val ); \
147 if ( value == (type)-1 && PyErr_Occurred() ) \
150 *((type*)buf+idx) = (type)value; \
154 PyObject* name##_buffer_subscript( PyObject* self, PyObject* item ) { \
155 if ( PyIndex_Check( item ) ) { \
156 Py_ssize_t idx = PyNumber_AsSsize_t( item, PyExc_IndexError ); \
157 if ( idx == -1 && PyErr_Occurred() ) \
159 return name##_buffer_item( self, idx ); \
164 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Bool, Bool_t, Long_t, PyBool_FromLong, PyInt_AsLong )
165 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Char, Char_t, Long_t, PyInt_FromLong, PyInt_AsLong )
166 PYROOT_IMPLEMENT_PYBUFFER_METHODS( UChar, UChar_t, Long_t, PyInt_FromLong, PyInt_AsLong )
167 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Short, Short_t, Long_t, PyInt_FromLong, PyInt_AsLong )
168 PYROOT_IMPLEMENT_PYBUFFER_METHODS( UShort, UShort_t, Long_t, PyInt_FromLong, PyInt_AsLong )
169 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Int, Int_t, Long_t, PyInt_FromLong, PyInt_AsLong )
170 PYROOT_IMPLEMENT_PYBUFFER_METHODS( UInt, UInt_t, Long_t, PyInt_FromLong, PyInt_AsLong )
171 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Long, Long_t, Long_t, PyLong_FromLong, PyLong_AsLong )
172 PYROOT_IMPLEMENT_PYBUFFER_METHODS( ULong, ULong_t, ULong_t, PyLong_FromUnsignedLong, PyLong_AsUnsignedLong )
173 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Float, Float_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble )
174 PYROOT_IMPLEMENT_PYBUFFER_METHODS( Double, Double_t, Double_t, PyFloat_FromDouble, PyFloat_AsDouble )
176 int pyroot_buffer_ass_subscript( PyObject* self, PyObject* idx, PyObject* val ) {
178 if ( PyIndex_Check( idx ) ) {
179 Py_ssize_t i = PyNumber_AsSsize_t( idx, PyExc_IndexError );
180 if ( i == -1 && PyErr_Occurred() )
182 return Py_TYPE(
self)->tp_as_sequence->sq_ass_item(
self, i, val );
184 PyErr_SetString( PyExc_TypeError,
"buffer indices must be integers" );
193 PyObject* buffer_setsize( PyObject*
self, PyObject* pynlen )
195 Py_ssize_t nlen = PyInt_AsSsize_t( pynlen );
196 if ( nlen == -1 && PyErr_Occurred() )
199 #if PY_VERSION_HEX < 0x03000000
200 ((PyBufferTop_t*)
self)->fSize = nlen * ((PyBufferTop_t*)
self)->fItemSize;
202 PyMemoryView_GET_BUFFER(
self)->len = nlen * PyMemoryView_GET_BUFFER(
self)->itemsize;
205 Py_INCREF( Py_None );
209 PyObject *SetSize(PyObject *
self, PyObject *pynlen)
211 if (PyErr_WarnEx(PyExc_FutureWarning,
212 "buffer.SetSize(N) is deprecated and will disappear in a future version of ROOT. "
213 "Instead, use buffer.reshape((N,))", 1) < 0) {
217 return buffer_setsize(
self, pynlen);
220 PyObject *reshape(PyObject *
self, PyObject *shape)
223 if (!PyTuple_Check(shape) || PyTuple_GET_SIZE(shape) != 1) {
225 PyObject* pystr = PyObject_Str(shape);
227 PyErr_Format(PyExc_TypeError,
"tuple object of length 1 expected, received %s",
228 PyROOT_PyUnicode_AsStringChecked(pystr));
233 PyErr_SetString(PyExc_TypeError,
"tuple object of length 1 expected");
237 return buffer_setsize(
self, PyTuple_GET_ITEM(shape, 0));
243 PyObject* buf_typecode( PyObject* pyobject,
void* )
245 if ( PyObject_TypeCheck( pyobject, &PyBoolBuffer_Type ) )
246 return PyROOT_PyUnicode_FromString( (
char*)
"b" );
247 else if ( PyObject_TypeCheck( pyobject, &PyCharBuffer_Type ) )
248 return PyROOT_PyUnicode_FromString( (
char*)
"b" );
249 else if ( PyObject_TypeCheck( pyobject, &PyUCharBuffer_Type ) )
250 return PyROOT_PyUnicode_FromString( (
char*)
"B" );
251 else if ( PyObject_TypeCheck( pyobject, &PyShortBuffer_Type ) )
252 return PyROOT_PyUnicode_FromString( (
char*)
"h" );
253 else if ( PyObject_TypeCheck( pyobject, &PyUShortBuffer_Type ) )
254 return PyROOT_PyUnicode_FromString( (
char*)
"H" );
255 else if ( PyObject_TypeCheck( pyobject, &PyIntBuffer_Type ) )
256 return PyROOT_PyUnicode_FromString( (
char*)
"i" );
257 else if ( PyObject_TypeCheck( pyobject, &PyUIntBuffer_Type ) )
258 return PyROOT_PyUnicode_FromString( (
char*)
"I" );
259 else if ( PyObject_TypeCheck( pyobject, &PyLongBuffer_Type ) )
260 return PyROOT_PyUnicode_FromString( (
char*)
"l" );
261 else if ( PyObject_TypeCheck( pyobject, &PyULongBuffer_Type ) )
262 return PyROOT_PyUnicode_FromString( (
char*)
"L" );
263 else if ( PyObject_TypeCheck( pyobject, &PyFloatBuffer_Type ) )
264 return PyROOT_PyUnicode_FromString( (
char*)
"f" );
265 else if ( PyObject_TypeCheck( pyobject, &PyDoubleBuffer_Type ) )
266 return PyROOT_PyUnicode_FromString( (
char*)
"d" );
268 PyErr_SetString( PyExc_TypeError,
"received unknown buffer object" );
274 PyGetSetDef buffer_getset[] = {
275 { (
char*)
"typecode", (getter)buf_typecode, NULL, NULL, NULL },
276 { (
char*)NULL, NULL, NULL, NULL, NULL }
281 PyMethodDef buffer_methods[] = {
282 { (
char*)
"SetSize", (PyCFunction)SetSize, METH_O, NULL },
283 { (
char*)
"reshape", (PyCFunction)reshape, METH_O, NULL },
284 { (
char*)NULL, NULL, 0, NULL }
291 PyROOT::TPyBufferFactory* PyROOT::TPyBufferFactory::Instance()
294 static TPyBufferFactory* fac =
new TPyBufferFactory;
300 #define PYROOT_INSTALL_PYBUFFER_METHODS( name, type ) \
301 Py##name##Buffer_Type.tp_name = (char*)"ROOT.Py"#name"Buffer"; \
302 Py##name##Buffer_Type.tp_base = &PyBuffer_Type; \
303 Py##name##Buffer_Type.tp_as_buffer = PyBuffer_Type.tp_as_buffer; \
304 Py##name##Buffer_SeqMethods.sq_item = (ssizeargfunc)name##_buffer_item; \
305 Py##name##Buffer_SeqMethods.sq_ass_item = (ssizeobjargproc)name##_buffer_ass_item;\
306 Py##name##Buffer_SeqMethods.sq_length = (lenfunc)buffer_length; \
307 Py##name##Buffer_Type.tp_as_sequence = &Py##name##Buffer_SeqMethods; \
308 if ( PyBuffer_Type.tp_as_mapping ) { \
309 Py##name##Buffer_MapMethods.mp_length = (lenfunc)buffer_length; \
310 Py##name##Buffer_MapMethods.mp_subscript = (binaryfunc)name##_buffer_subscript;\
311 Py##name##Buffer_MapMethods.mp_ass_subscript = (objobjargproc)pyroot_buffer_ass_subscript;\
312 Py##name##Buffer_Type.tp_as_mapping = &Py##name##Buffer_MapMethods; \
314 Py##name##Buffer_Type.tp_str = (reprfunc)name##_buffer_str; \
315 Py##name##Buffer_Type.tp_methods = buffer_methods; \
316 Py##name##Buffer_Type.tp_getset = buffer_getset; \
317 PyType_Ready( &Py##name##Buffer_Type );
319 PyROOT::TPyBufferFactory::TPyBufferFactory()
322 PYROOT_INSTALL_PYBUFFER_METHODS( Bool, Bool_t )
323 PYROOT_INSTALL_PYBUFFER_METHODS( Char, Char_t )
324 PYROOT_INSTALL_PYBUFFER_METHODS( UChar, UChar_t )
325 PYROOT_INSTALL_PYBUFFER_METHODS( Short, Short_t )
326 PYROOT_INSTALL_PYBUFFER_METHODS( UShort, UShort_t )
327 PYROOT_INSTALL_PYBUFFER_METHODS( Int, Int_t )
328 PYROOT_INSTALL_PYBUFFER_METHODS( UInt, UInt_t )
329 PYROOT_INSTALL_PYBUFFER_METHODS( Long, Long_t )
330 PYROOT_INSTALL_PYBUFFER_METHODS( ULong, ULong_t )
331 PYROOT_INSTALL_PYBUFFER_METHODS( Float, Float_t )
332 PYROOT_INSTALL_PYBUFFER_METHODS( Double, Double_t )
337 PyROOT::TPyBufferFactory::~TPyBufferFactory()
341 const char* getBoolFormat() {
return "b";}
342 const char* getCharFormat() {
return "b";}
343 const char* getUCharFormat() {
return "B";}
344 const char* getShortFormat() {
return "h";}
345 const char* getUShortFormat() {
return "H";}
346 const char* getIntFormat() {
return "i";}
347 const char* getUIntFormat() {
return "I";}
348 const char* getLongFormat() {
return "l";}
349 const char* getULongFormat() {
return "L";}
350 const char* getFloatFormat() {
return "f";}
351 const char* getDoubleFormat() {
return "d";}
353 #if PY_VERSION_HEX < 0x03000000
354 #define PYBUFFER_SETITEMSIZE(buf,type) ((PyBufferTop_t*)buf)->fItemSize = Py_ssize_t(sizeof(type))
355 #define PYBUFFER_SETFORMAT(buf,name)
357 #define PYBUFFER_SETITEMSIZE(buf,type) PyMemoryView_GET_BUFFER(buf)->itemsize = Py_ssize_t(sizeof(type))
358 #define PYBUFFER_SETFORMAT(buf,name) PyMemoryView_GET_BUFFER(buf)->format = (char *)get##name##Format()
362 #define PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( name, type ) \
363 PyObject* PyROOT::TPyBufferFactory::PyBuffer_FromMemory( type* address, Py_ssize_t size )\
365 size = size < 0 ? INT_MAX : size; \
366 PyObject* buf = PyBuffer_FromReadWriteMemory( (void*)address, size ); \
368 Py_INCREF( (PyObject*)(void*)&Py##name##Buffer_Type ); \
369 buf->ob_type = &Py##name##Buffer_Type; \
370 PYBUFFER_SETITEMSIZE(buf,type); \
371 PYBUFFER_SETFORMAT(buf, name); \
376 PyObject* PyROOT::TPyBufferFactory::PyBuffer_FromMemory( type* address, PyObject* scb )\
378 PyObject* buf = PyBuffer_FromMemory( address, Py_ssize_t(0) ); \
379 if ( buf != 0 && PyCallable_Check( scb ) ) { \
381 gSizeCallbacks[ buf ] = scb; \
386 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Bool, Bool_t )
387 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Char, Char_t )
388 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( UChar, UChar_t )
389 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Short, Short_t )
390 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( UShort, UShort_t )
391 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Int, Int_t )
392 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( UInt, UInt_t )
393 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Long, Long_t )
394 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( ULong, ULong_t )
395 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Float, Float_t )
396 PYROOT_IMPLEMENT_PYBUFFER_FROM_MEMORY( Double, Double_t )