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_;
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 } }
00234
00235 #endif