Commits

bi...@4525493e-7705-40b1-a816-d608a930855b  committed d452939

added needed methods to get py-thinning working

  • Participants
  • Parent commits 847ec8e

Comments (0)

Files changed (4)

+2008-01-16  Sebastien Binet  <binet@lblbox>
+
+	* tagging StoreGateBindings-00-00-04
+	* added needed methods to get py-thinning working
+	* M StoreGateBindings/selection.xml
+	* M src/StoreGateBindingsDict.h
+	* M src/StoreGatePyExt.cxx
+
 2008-01-15  Sebastien Binet  <binet@lblbox>
 
 	* tagging StoreGateBindings-00-00-03

File StoreGateBindings/selection.xml

    <function name="AthenaInternal::retrieveObjectFromStore"/>
    <function name="AthenaInternal::recordObjectToStore"/>
    <function name="AthenaInternal::thinContainer" />
+   <function name="AthenaInternal::thinIdxContainer" />
+   <function name="AthenaInternal::thinRemovedIdx" />
 
 </lcgdict>

File src/StoreGateBindingsDict.h

 			   PyObject* container,
 			   PyObject* filter,
 			   int op );
+
+  std::size_t thinIdxContainer( IThinningSvc*,
+				PyObject* container, 
+				std::size_t idx );
+
+  std::size_t thinRemovedIdx();
 }
 
 #endif // not STOREGATEBINDINGS_STOREGATEBINDINGSDICT_H 

File src/StoreGatePyExt.cxx

 #include "Api.h"
 
 #include <string>
+#include <vector>
+#include <algorithm> // for stable_partition
+
+typedef std::vector<char*> bytes_t;
 
 // temporaryly duplicate PyROOT's API...
 // Wim will fix that up
   
     /** @brief Constructor to handle thinning of a python object
      */
-    PyThinningHdlr( PyROOT::ObjectProxy* obj );
+    PyThinningHdlr( bytes_t& container );
 
     /** @brief remove an element from the proxied @c DataVector
      */
      */
     virtual void unpack();
   private:
-    /// Pointer to the held pyroot object.
-    PyROOT::ObjectProxy* m_container;
+
+    /** Vector holding the pointers to the elements of @c DataVector, before
+     *  any thinning took place
+     */
+    const bytes_t m_backup;
+
+    /** Reference to the actual underlying std::vector backing the 
+     *  @c DataVector being thinned
+     */
+    bytes_t& m_container;
   };
 } //> end namespace SG
 
       return 0;
    }
 
+   if ( ! PyROOT::ObjectProxy_Check( container_ ) ) {
+     PyErr_SetString( PyExc_TypeError,
+		      "filter() argument 2 must be a PyROOT object" );
+     return 0;
+   }
    PyROOT::ObjectProxy* container = (PyROOT::ObjectProxy*)container_;
+   const int nElements = PySequence_Size( container_ );
+   if ( -1 == nElements ) {
+     PyErr_SetString
+       ( PyExc_TypeError,
+	 "filter() argument 2 must be a non zero-length sequence" );
+   }
+
+   // right now the python layer should give us an array of 'PyBools'
+   // -> massage this into a std::vector<bool>
    typedef IThinningSvc::Filter_t Filter_t;
+   Filter_t filter( nElements, false );
+   if ( PySequence_Check( filter_ ) ) {
+     for ( std::size_t i = 0, iMax = filter.size(); i != iMax; ++i ) {
+       PyObject* iFilter = PySequence_GetItem( filter_, i );
+       if ( iFilter == Py_True ) { filter[i] = true;
+       } else                    { filter[i] = false;
+       }
+       Py_DECREF(iFilter);
+     }
+   } else {
+     PyErr_SetString( PyExc_TypeError,
+		      "filter() argument 3 must a sequence" );
+     return 0;
+   }
+
    // FIXME: won't work b/c of damn specialization of std::vector<bool> !!
    // -> change IThinningSvc::filter interface or,
    // -> copy the python array of booleans into a temporary vector<bool>
-   Filter_t& filter = 
-     *(Filter_t*)(((PyROOT::ObjectProxy*)filter_)->GetObject());
+//    Filter_t& filter = 
+//      *(Filter_t*)(((PyROOT::ObjectProxy*)filter_)->GetObject());
 
    SG::DataProxy* proxy = self->deep_proxy( container->GetObject() );
    if ( !proxy ) {
+       PyErr_SetString( PyExc_RuntimeError,
+			"could not manage to find a deep_proxy" );
      return 0;
    }
 
    IThinningHdlr* hdlr = self->handler(proxy);
    if ( 0 == hdlr ) {
-     hdlr = new SG::PyThinningHdlr( container );
+     PyObject* stdcont_ = PyObject_CallMethod
+       ( (PyObject*)container, 
+	 const_cast<char*>("stdcont"), const_cast<char*>("") );
+     if ( ! PyROOT::ObjectProxy_Check( stdcont_ ) ) {
+       PyErr_SetString( PyExc_RuntimeError,
+			"could not access stdcont() method from DataVector" );
+       return 0;
+     } else {
+       PyROOT::ObjectProxy* pystdcont = (PyROOT::ObjectProxy*)stdcont_;
+       bytes_t& stdcont = *reinterpret_cast<bytes_t*>( pystdcont->GetObject() );
+       hdlr = new SG::PyThinningHdlr( stdcont );
+     }
    }
 
-//    const IThinningSvc::Operator::Type op = op_ == 0 
-//      ? IThinningSvc::Operator::
    int sc = self->filter_impl( hdlr, proxy, filter, 
 			       (IThinningSvc::Operator::Type)op ).isSuccess()
 	      ? 1
    return Py_BuildValue( const_cast<char*>("i"), sc );
 }
 
+std::size_t 
+AthenaInternal::thinIdxContainer( IThinningSvc* self,
+				  PyObject* container_, 
+				  std::size_t idx )
+{
+  // unlikely to happen, but checking is cheap
+   if ( ! self ) {
+      PyErr_SetString( PyExc_RuntimeError, 
+		       "no thinning svc available, is Athena initialized?" );
+      return 0;
+   }
+
+   if ( ! PyROOT::ObjectProxy_Check( container_ ) ) {
+     PyErr_SetString( PyExc_TypeError,
+		      "index() argument 2 must be a PyROOT object" );
+     return 0;
+   }
+   PyROOT::ObjectProxy* container = (PyROOT::ObjectProxy*)container_;
+
+   SG::DataProxy* proxy = self->deep_proxy( container->GetObject() );
+   if ( 0 == proxy ) {
+     PyErr_SetString( PyExc_RuntimeError,
+		      "could not manage to find a deep_proxy" );
+     return 0;
+   }
+   return self->index( proxy, idx );
+}
+
+std::size_t AthenaInternal::thinRemovedIdx() 
+{ return IThinningSvc::RemovedIdx; }
+
+namespace {
+  /** @brief Predicate to spot non NULL pointers
+   */
+  struct IsNonNullPtr
+  {
+    template <typename Element>
+    bool operator()( Element* f ) const
+    { return f != 0; }
+  };
+}
+
 //
 namespace SG {
   IClassIDSvc* PyDataBucket::s_clidSvc = 0;
   /////////////////////////////////////////////////////////////////////////////
   // PyThinningHdlr implementation
 
-  PyThinningHdlr::PyThinningHdlr( PyROOT::ObjectProxy* obj ) :
-    IThinningHdlr(     ),
-    m_container  ( obj )
+  PyThinningHdlr::PyThinningHdlr( bytes_t& container ) :
+    IThinningHdlr(      ),
+    m_backup     ( container.begin(), container.end() ),
+    m_container  ( container )
   {}
 
   /** @brief remove an element from the proxied @c DataVector
    */
-  void PyThinningHdlr::remove( const std::size_t /*idx*/ )
-  {}
+  void PyThinningHdlr::remove( const std::size_t idx )
+  {
+    m_container[idx] = 0;
+  }
   
   /** @brief pack the proxied @c DataVector
    *         This is needed in order to keep element link indices consistent
    *         and T/P converters unchanged.
    */
   void PyThinningHdlr::pack()
-  {}
+  {
+    typedef bytes_t::iterator  Iter;
+    // move non NULL pointers at the begin of the vector, 
+    // preserving relative order...
+    Iter itr = std::stable_partition( m_container.begin(), 
+				      m_container.end(), 
+				      IsNonNullPtr() );
+    // nicely truncate our container: removes the NULL elements
+    m_container.resize( std::distance( m_container.begin(), itr ) );
+  }
   
   /** @brief unpack the proxied @c DataVector ie: restore it as it was 
    *         *before* any thinning took place
    */
   void PyThinningHdlr::unpack()
-  {}
+  {
+    typedef bytes_t::iterator   Iter;
+    typedef bytes_t::value_type Value;
+    const std::size_t size = m_backup.size();
+      
+    m_container.resize( size );
+    for ( std::size_t i = 0; i != size; ++i ) {
+      m_container[i] = m_backup[i];
+    }
+  }
 
 } //< end namespace SG