CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/DataFormats/Common/interface/AssociativeIterator.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_AssociativeIterator_h
00002 #define DataFormats_Common_AssociativeIterator_h
00003 
00042 #include "DataFormats/Provenance/interface/ProductID.h"
00043 #include <DataFormats/Common/interface/EDProductGetter.h>
00044 
00045 namespace edm {
00046     struct Event;
00047     template <class T> struct View;
00048     template <class T> struct Handle;
00049     template <class T> struct Association;
00050     template <class T> struct RefToBase;
00051     template <class T> struct Ptr;
00052     template <class C, class T, class F> struct Ref;
00053 }
00054 
00055 namespace edm {
00056 
00057     // Helper classes to convert one ref type to another.
00058     // Now it's able to convert anything to itself, and RefToBase to anything else
00059     // This won't be needed if we used Ptr
00060     namespace helper {
00061         template<typename RefFrom, typename RefTo>
00062         struct RefConverter {
00063             static RefTo convert(const RefFrom &ref) { return RefTo(ref); }
00064         };
00065         template<typename T>
00066         struct RefConverter<RefToBase<T>, Ptr<T> > {
00067             static Ptr<T> convert(const RefToBase<T> &ref) { return Ptr<T>(ref.id(), ref.isAvailable() ? ref.get() : 0, ref.key()); }
00068         };
00069         template<typename T, typename C, typename V, typename F>
00070         struct RefConverter<RefToBase<T>, Ref<C,V,F> > {
00071             static Ref<C,V,F> convert(const RefToBase<T> &ref) { return ref.template castTo<Ref<C,V,F> >(); }
00072         };
00073     }
00074 
00076     //  the implementation uses View, and works for RefType = Ref, RefToBase and Ptr
00077     template<typename RefType>
00078     class EdmEventItemGetter {
00079         public: 
00080             typedef typename RefType::value_type element_type;
00081             EdmEventItemGetter(const edm::Event &iEvent) : iEvent_(iEvent) { }
00082             ~EdmEventItemGetter() { }
00083 
00084             RefType get(const ProductID &id, size_t idx) const {
00085                 typedef typename edm::RefToBase<element_type> BaseRefType; // could also use Ptr, but then I can't do Ptr->RefToBase
00086                 if (id_ != id) {
00087                     id_ = id;
00088                     iEvent_.get(id_, view_);
00089                 }
00090                 BaseRefType ref = view_->refAt(idx);
00091                 typedef typename helper::RefConverter<BaseRefType, RefType> conv; 
00092                 return conv::convert(ref);
00093             }
00094         private:
00095             mutable Handle<View<element_type> > view_;
00096             mutable ProductID id_;
00097             const edm::Event &iEvent_;
00098     };
00099 
00100     // unfortunately it's not possible to define value_type of an Association<C> correctly
00101     // so we need yet another template trick
00102     namespace helper {
00103         template<typename AC> 
00104         struct AssociativeCollectionValueType {
00105             typedef typename AC::value_type type;
00106         };
00107 
00108         template<typename C>
00109         struct AssociativeCollectionValueType< Association<C> > {
00110             typedef typename Association<C>::reference_type type;
00111         };
00112     }
00113 
00114 template<typename KeyRefType, typename AssociativeCollection, 
00115             typename ItemGetter = EdmEventItemGetter<KeyRefType> >
00116 class AssociativeIterator {
00117     public:
00118         typedef KeyRefType                                  key_type;
00119         typedef typename KeyRefType::value_type             key_val_type;
00120         typedef typename helper::AssociativeCollectionValueType<AssociativeCollection>::type  val_type;
00121         typedef typename std::pair<key_type, val_type>      value_type;
00122 
00123         typedef AssociativeIterator<KeyRefType,AssociativeCollection,ItemGetter>   self_type;
00124 
00126         AssociativeIterator(const AssociativeCollection &map, const ItemGetter &getter) ;
00127 
00128         self_type & operator++() ;
00129         self_type & operator--() ;
00130         self_type & nextProductID() ;
00131         // self_type & skipTo(const ProductID &id, size_t offs = 0) ; // to be implemented one day
00132 
00133         const value_type & operator*()  const { return *(this->get()); }
00134         const value_type * operator->() const { return  (this->get()); }
00135         const value_type * get()        const { chkPair(); return & pair_; }
00136 
00137         const key_type   & key() const { chkPair(); return pair_.first; }
00138         const val_type   & val() const { return map_.get(idx_);         }
00139         const ProductID  & id()  const { return ioi_->first; }
00140         
00141         operator bool() const { return idx_ < map_.size(); }
00142         self_type end() const ;
00143     
00144         bool operator==(const self_type &other) const { return other.idx_ == idx_; }
00145         bool operator!=(const self_type &other) const { return other.idx_ != idx_; }
00146         bool operator<( const self_type &other) const { return other.idx_  < idx_; }
00147 
00148     private:
00149         typedef typename AssociativeCollection::id_offset_vector  id_offset_vector;
00150         typedef typename id_offset_vector::const_iterator         id_offset_iterator;
00151         const AssociativeCollection & map_;
00152         id_offset_iterator   ioi_, ioi2_;
00153         size_t               idx_; 
00154 
00155         ItemGetter           getter_;
00156 
00157         mutable bool         pairOk_;
00158         mutable value_type   pair_;
00159                 
00160         void chkPair() const ;
00161 
00162     };
00163 
00164     template<typename KeyRefType, typename AC, typename IG>
00165     AssociativeIterator<KeyRefType,AC,IG>::AssociativeIterator(const AC &map, const IG &getter) :
00166         map_(map), ioi_(map_.ids().begin()), ioi2_(ioi_+1), idx_(0), 
00167         getter_(getter),
00168         pairOk_(false)
00169     {
00170     }
00171 
00172     template<typename KeyRefType, typename AC, typename IG>
00173     AssociativeIterator<KeyRefType,AC,IG> & AssociativeIterator<KeyRefType,AC,IG>::operator++() {
00174         pairOk_ = false;
00175         idx_++;
00176         if (ioi2_ < map_.ids().end()) {
00177             if (ioi2_->second == idx_) {
00178                 ++ioi_; ++ioi2_;
00179             }
00180         }
00181         return *this;
00182     }
00183 
00184     template<typename KeyRefType, typename AC, typename IG>
00185     AssociativeIterator<KeyRefType,AC,IG> & AssociativeIterator<KeyRefType,AC,IG>::operator--() {
00186         pairOk_ = false;
00187         idx_--;
00188         if (ioi_->second < idx_) {
00189             --ioi_; --ioi2_;
00190         }
00191         return *this;
00192 
00193     }
00194 
00195     template<typename KeyRefType, typename AC, typename IG>
00196     AssociativeIterator<KeyRefType,AC,IG> & AssociativeIterator<KeyRefType,AC,IG>::nextProductID() {
00197         pairOk_ = false;
00198         ioi_++; ioi2_++;
00199         if (ioi_ == map_.ids().end()) {
00200             idx_ = map_.size();
00201         } else {
00202             idx_ = ioi_->second;
00203         }
00204     }
00205 
00206     /*
00207     template<typename KeyRefType, typename AC, typename IG>
00208     AssociativeIterator<KeyRefType,AC,IG> & AssociativeIterator<KeyRefType,AC,IG>::skipTo(const ProductID &id, size_t offs) {
00209         pairOk_ = false;
00210         throw Exception(errors::UnimplementedFeature);
00211     }
00212     */
00213 
00214     template<typename KeyRefType, typename AC, typename IG>
00215     AssociativeIterator<KeyRefType,AC,IG> AssociativeIterator<KeyRefType,AC,IG>::end() const {
00216         self_type ret(map_, getter_);
00217         ret.ioi_  = map_.ids().end();
00218         ret.ioi2_ = ret.ioi_ + 1;
00219         ret.idx_  = map_.size(); 
00220         return ret;
00221     }
00222    
00223     template<typename KeyRefType, typename AC, typename IG>
00224     void AssociativeIterator<KeyRefType,AC,IG>::chkPair() const {
00225         if (pairOk_) return;
00226         pair_.first = getter_.get(id(), idx_ - ioi_->second);
00227         pair_.second = map_.get(idx_);
00228         pairOk_ = true;
00229     }
00230 
00231 }
00232 
00233 #endif
00234