CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/DataFormats/PatCandidates/interface/EventHypothesisLooper.h

Go to the documentation of this file.
00001 #ifndef DataFormats_EventHypothesis_interface_EventHypothesisLooper_h
00002 #define DataFormats_EventHypothesis_interface_EventHypothesisLooper_h
00003 
00004 #include "DataFormats/Candidate/interface/CandidateFwd.h"
00005 #include <algorithm>
00006 
00007 namespace pat { namespace eventhypothesis {
00008         template<typename T>
00009         class DynCastCandPtr {
00010             public:
00011                 const T *get(const reco::Candidate *ptr) ;
00012                 void clearCache() { isPtrCached_ = false; }
00013                 bool typeOk(const reco::Candidate *ptr) { doPtr(ptr); return cachePtr_ != 0; }
00014             private:
00015                 void       doPtr(const reco::Candidate *ptr) ;
00016                 bool       isPtrCached_;
00017                 const T *  cachePtr_;
00018         };
00019         template<typename T>
00020         void DynCastCandPtr<T>::doPtr(const reco::Candidate *ptr) {
00021             if (!isPtrCached_) { 
00022                 cachePtr_    = dynamic_cast<const T *>(ptr); 
00023                 isPtrCached_ = true;
00024             }
00025         }
00026         template<typename T>
00027         const T * DynCastCandPtr<T>::get(const reco::Candidate *ptr) {
00028             doPtr(ptr);
00029             if ((ptr != 0) && (cachePtr_ == 0)) throw cms::Exception("Type Checking") <<
00030                 "You can't convert a " << typeid(*ptr).name() << " to a " << typeid(T).name() << "\n" <<
00031                 "note: you can use c++filt command to convert the above in human readable types.\n";
00032             return cachePtr_;
00033         }
00034 
00035         template<>
00036         struct DynCastCandPtr<reco::Candidate> {
00037             const reco::Candidate *get(const reco::Candidate *ptr) { return ptr; }
00038             void clearCache() {}
00039             bool typeOk(const reco::Candidate *ptr) { return true; }
00040         };
00041 
00042         template<typename T>
00043         class Looper {
00044             public:
00047                 Looper(const EventHypothesis &eh, const ParticleFilter &filter) ;
00048 
00051                 Looper(const EventHypothesis &eh, const ParticleFilter *filter) ;
00054                 Looper(const EventHypothesis &eh, const ParticleFilterPtr &filter) ;
00055                 ~Looper() {}
00056 
00058                 const T & operator*()  const { return ptr_.get(iter_->second.get()); }
00060                 const T * operator->() const { return ptr_.get(iter_->second.get()); }
00062                 const T * get()        const { return ptr_.get(iter_->second.get()); }
00063                 
00065                 bool  isTypeOk()       const { return ptr_.typeOk(iter_->second.get()); }
00066 
00068                 const std::string &     role()  const { return  iter_->first; }
00070                 const CandRefType &     ref ()  const { return  iter_->second; }
00072                 const reco::Candidate & cand () const { return *iter_->second; }
00073 
00075                 size_t globalIndex()  { return iter_ - eh_.begin(); }
00077                 size_t index() const { return num_; }
00079                 size_t size()  const { if (total_ < 0) realSize(); return total_; }
00080 
00082                 Looper & operator++() ;                    
00084                 Looper & operator--() ;                    
00086                 Looper & skip(int delta) ; 
00089                 Looper & reset(int item=0) ; 
00090 
00093                 operator bool() const ;
00094 
00096                 template<typename T2> bool operator==(const Looper<T2> &other) const { return iter_ == other.iter_; }
00097                 template<typename T2> bool operator!=(const Looper<T2> &other) const { return iter_ != other.iter_; }
00098                 template<typename T2> bool operator<=(const Looper<T2> &other) const { return iter_ <= other.iter_; }
00099                 template<typename T2> bool operator>=(const Looper<T2> &other) const { return iter_ >= other.iter_; }
00100                 template<typename T2> bool operator<(const Looper<T2> &other)  const { return iter_ < other.iter_; }
00101                 template<typename T2> bool operator>(const Looper<T2> &other)  const { return iter_ > other.iter_; }
00102 
00103             private:
00104                 struct null_deleter{  void operator()(void const *) const { } };
00105                 typedef typename EventHypothesis::const_iterator const_iterator;
00106 
00107                 void first() ;
00108                 void realSize() const ; 
00109                 bool assertOk() const;
00110 
00111                 const EventHypothesis   & eh_;
00112                 const ParticleFilterPtr   filter_;
00113                 const_iterator            iter_;
00114                 int                       num_;
00115                 mutable int               total_; // mutable as it is not computed unless needed
00116                 mutable DynCastCandPtr<T> ptr_;
00117         };
00118         typedef Looper<reco::Candidate> CandLooper;
00119 
00120         template<typename T>
00121         Looper<T>::Looper(const EventHypothesis &eh, const ParticleFilter &filter) :
00122             eh_(eh), filter_(ParticleFilterPtr(&filter, typename Looper<T>::null_deleter())), total_(-1)
00123         {
00124             first();
00125         }
00126 
00127         template<typename T>
00128         Looper<T>::Looper(const EventHypothesis &eh, const ParticleFilter *filter) :
00129             eh_(eh), filter_(filter), total_(-1)
00130         {
00131             first();
00132         }
00133 
00134        template<typename T>
00135         Looper<T>::Looper(const EventHypothesis &eh, const ParticleFilterPtr &filter) :
00136             eh_(eh), filter_(filter), total_(-1)
00137         {
00138             first();
00139         }
00140 
00141 
00142         template<typename T>
00143         bool Looper<T>::assertOk() const {
00144             assert(iter_ <= eh_.end());
00145             assert((iter_+1) >= eh_.begin());
00146             assert((iter_ < eh_.begin()) || (iter_ == eh_.end()) || ((*filter_)(*iter_)));
00147             return true;
00148         }
00149 
00150         template<typename T>
00151         Looper<T> & Looper<T>::operator++() { 
00152             ptr_.clearCache();
00153             assert(assertOk());
00154             if (iter_ == eh_.end()) return *this;
00155             do {
00156                 ++iter_; 
00157                 if (iter_ == eh_.end()) break;
00158                 if ((*filter_)(*iter_)) {
00159                     assert(assertOk());
00160                     ++num_; return *this;
00161                 }
00162             } while (true);
00163             assert(assertOk());
00164             return *this;
00165         }
00166         template<typename T>
00167         Looper<T> & Looper<T>::operator--() { 
00168             ptr_.clearCache();
00169             assert(assertOk());
00170             if (num_ < 0) return *this;
00171             do {
00172                 --iter_; 
00173                 if (iter_ < eh_.begin()) { num_ = -1; break; }
00174                 if ((*filter_)(*iter_)) {
00175                     assert(assertOk());
00176                     --num_; return *this;
00177                 }
00178             } while (true);
00179             assert(assertOk());
00180             return *this;
00181         }
00182 
00183         template<typename T>
00184         Looper<T> & Looper<T>::skip(int delta) {
00185             assert(assertOk());
00186             std::advance(this, delta);
00187             assert(assertOk());
00188             return *this;
00189         }
00190     
00191         template<typename T>
00192         Looper<T> & Looper<T>::reset(int item) {
00193             assert(assertOk());
00194             if (item >= 0) {
00195                 first();
00196                 std::advance(this, item);
00197             } else {
00198                 num_ = item + 1; iter_ = eh_.end();
00199                 std::advance(this, item);
00200             }
00201             assert(assertOk());
00202             return *this;
00203         }
00204 
00205         template<typename T>
00206         void Looper<T>::first() {
00207             num_ = 0; 
00208             iter_ = eh_.begin(); 
00209             ptr_.clearCache();
00210             for (; iter_ != eh_.end(); ++iter_) {
00211                 if ((*filter_)(*iter_)) break;
00212             }
00213             assert(assertOk());
00214         }
00215 
00216         template<typename T>
00217         Looper<T>::operator bool() const {
00218             return  (iter_ < eh_.end()) && (iter_ >= eh_.begin());
00219         }
00220 
00221         template<typename T>
00222         void Looper<T>::realSize() const {
00223             EventHypothesis::const_iterator it = iter_;
00224             if (it < eh_.begin()) { 
00225                 it = eh_.begin(); total_ = 0; 
00226             } else {
00227                 total_ = num_;
00228             }
00229             for (; it != eh_.end(); ++it) { 
00230                 if ((*filter_)(*it)) ++total_;
00231             }
00232         }
00233 } } // namespaces
00234 
00235 #endif