File indexing completed on 2024-04-06 12:03:50
0001 #ifndef DataFormats_Common_AssociativeIterator_h
0002 #define DataFormats_Common_AssociativeIterator_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #include "DataFormats/Provenance/interface/ProductID.h"
0042 #include "DataFormats/Common/interface/EDProductGetter.h"
0043 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0044
0045 namespace edm {
0046 class Event;
0047 template <class T>
0048 class View;
0049 template <class T>
0050 class Handle;
0051 template <class T>
0052 class Association;
0053 template <class T>
0054 class RefToBase;
0055 template <class T>
0056 class Ptr;
0057 template <class C, class T, class F>
0058 class Ref;
0059 }
0060
0061 namespace edm {
0062
0063
0064
0065
0066 namespace helper {
0067 template <typename RefFrom, typename RefTo>
0068 struct RefConverter {
0069 static RefTo convert(const RefFrom &ref) { return RefTo(ref); }
0070 };
0071 template <typename T>
0072 struct RefConverter<RefToBase<T>, Ptr<T> > {
0073 static Ptr<T> convert(const RefToBase<T> &ref) {
0074 return Ptr<T>(ref.id(), ref.isAvailable() ? ref.get() : 0, ref.key());
0075 }
0076 };
0077 template <typename T, typename C, typename V, typename F>
0078 struct RefConverter<RefToBase<T>, Ref<C, V, F> > {
0079 static Ref<C, V, F> convert(const RefToBase<T> &ref) { return ref.template castTo<Ref<C, V, F> >(); }
0080 };
0081 }
0082
0083
0084
0085 template <typename RefType, typename EventType>
0086 class EventItemGetter {
0087 public:
0088 typedef typename RefType::value_type element_type;
0089 EventItemGetter(const EventType &iEvent) : iEvent_(iEvent) {}
0090 ~EventItemGetter() {}
0091
0092 RefType get(const ProductID &id, size_t idx) const {
0093 typedef typename edm::RefToBase<element_type>
0094 BaseRefType;
0095 if (id_ != id) {
0096 id_ = id;
0097 iEvent_.get(id_, view_);
0098 }
0099 BaseRefType ref = view_->refAt(idx);
0100 typedef typename helper::RefConverter<BaseRefType, RefType> conv;
0101 return conv::convert(ref);
0102 }
0103
0104 private:
0105
0106 CMS_SA_ALLOW mutable Handle<View<element_type> > view_;
0107 CMS_SA_ALLOW mutable ProductID id_;
0108 const EventType &iEvent_;
0109 };
0110
0111
0112
0113 namespace helper {
0114 template <typename AC>
0115 struct AssociativeCollectionValueType {
0116 typedef typename AC::value_type type;
0117 };
0118
0119 template <typename C>
0120 struct AssociativeCollectionValueType<Association<C> > {
0121 typedef typename Association<C>::reference_type type;
0122 };
0123 }
0124
0125 template <typename KeyRefType, typename AssociativeCollection, typename ItemGetter>
0126 class AssociativeIterator {
0127 public:
0128 typedef KeyRefType key_type;
0129 typedef typename KeyRefType::value_type key_val_type;
0130 typedef typename helper::AssociativeCollectionValueType<AssociativeCollection>::type val_type;
0131 typedef typename std::pair<key_type, val_type> value_type;
0132
0133 typedef AssociativeIterator<KeyRefType, AssociativeCollection, ItemGetter> self_type;
0134
0135
0136 AssociativeIterator(const AssociativeCollection &map, const ItemGetter &getter);
0137
0138 self_type &operator++();
0139 self_type &operator--();
0140 self_type &nextProductID();
0141
0142
0143 const value_type &operator*() const { return *(this->get()); }
0144 const value_type *operator->() const { return (this->get()); }
0145 const value_type *get() const {
0146 chkPair();
0147 return &pair_;
0148 }
0149
0150 const key_type &key() const {
0151 chkPair();
0152 return pair_.first;
0153 }
0154 const val_type &val() const { return map_.get(idx_); }
0155 const ProductID &id() const { return ioi_->first; }
0156
0157 operator bool() const { return idx_ < map_.size(); }
0158 self_type end() const;
0159
0160 bool operator==(const self_type &other) const { return other.idx_ == idx_; }
0161 bool operator!=(const self_type &other) const { return other.idx_ != idx_; }
0162 bool operator<(const self_type &other) const { return other.idx_ < idx_; }
0163
0164 private:
0165 typedef typename AssociativeCollection::id_offset_vector id_offset_vector;
0166 typedef typename id_offset_vector::const_iterator id_offset_iterator;
0167 const AssociativeCollection &map_;
0168 id_offset_iterator ioi_, ioi2_;
0169 size_t idx_;
0170
0171 ItemGetter getter_;
0172
0173
0174 CMS_SA_ALLOW mutable bool pairOk_;
0175 CMS_SA_ALLOW mutable value_type pair_;
0176
0177 void chkPair() const;
0178 };
0179
0180 template <typename KeyRefType, typename AC, typename IG>
0181 AssociativeIterator<KeyRefType, AC, IG>::AssociativeIterator(const AC &map, const IG &getter)
0182 : map_(map), ioi_(map_.ids().begin()), ioi2_(ioi_ + 1), idx_(0), getter_(getter), pairOk_(false) {}
0183
0184 template <typename KeyRefType, typename AC, typename IG>
0185 AssociativeIterator<KeyRefType, AC, IG> &AssociativeIterator<KeyRefType, AC, IG>::operator++() {
0186 pairOk_ = false;
0187 idx_++;
0188 if (ioi2_ < map_.ids().end()) {
0189 if (ioi2_->second == idx_) {
0190 ++ioi_;
0191 ++ioi2_;
0192 }
0193 }
0194 return *this;
0195 }
0196
0197 template <typename KeyRefType, typename AC, typename IG>
0198 AssociativeIterator<KeyRefType, AC, IG> &AssociativeIterator<KeyRefType, AC, IG>::operator--() {
0199 pairOk_ = false;
0200 idx_--;
0201 if (ioi_->second < idx_) {
0202 --ioi_;
0203 --ioi2_;
0204 }
0205 return *this;
0206 }
0207
0208 template <typename KeyRefType, typename AC, typename IG>
0209 AssociativeIterator<KeyRefType, AC, IG> &AssociativeIterator<KeyRefType, AC, IG>::nextProductID() {
0210 pairOk_ = false;
0211 ioi_++;
0212 ioi2_++;
0213 if (ioi_ == map_.ids().end()) {
0214 idx_ = map_.size();
0215 } else {
0216 idx_ = ioi_->second;
0217 }
0218 }
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228 template <typename KeyRefType, typename AC, typename IG>
0229 AssociativeIterator<KeyRefType, AC, IG> AssociativeIterator<KeyRefType, AC, IG>::end() const {
0230 self_type ret(map_, getter_);
0231 ret.ioi_ = map_.ids().end();
0232 ret.ioi2_ = ret.ioi_ + 1;
0233 ret.idx_ = map_.size();
0234 return ret;
0235 }
0236
0237 template <typename KeyRefType, typename AC, typename IG>
0238 void AssociativeIterator<KeyRefType, AC, IG>::chkPair() const {
0239 if (pairOk_)
0240 return;
0241 pair_.first = getter_.get(id(), idx_ - ioi_->second);
0242 pair_.second = map_.get(idx_);
0243 pairOk_ = true;
0244 }
0245
0246 template <typename KeyRefType, typename AC, typename EventType>
0247 AssociativeIterator<KeyRefType, AC, edm::EventItemGetter<KeyRefType, EventType> > makeAssociativeIterator(
0248 const AC &map, const EventType &event) {
0249 using Getter = edm::EventItemGetter<KeyRefType, EventType>;
0250 return AssociativeIterator<KeyRefType, AC, Getter>(map, Getter{event});
0251 }
0252 }
0253
0254 #endif