00001 #ifndef DataFormats_Common_MultiAssociation_h
00002 #define DataFormats_Common_MultiAssociation_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include <vector>
00053 #include <map>
00054 #include <boost/shared_ptr.hpp>
00055 #include <boost/utility.hpp>
00056 #include <boost/range.hpp>
00057 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00058 #include "DataFormats/Provenance/interface/ProductID.h"
00059 #include "FWCore/Utilities/interface/GCC11Compatibility.h"
00060
00061 namespace edm {
00062 namespace helper {
00067
00074 class IndexRangeAssociation {
00075 public:
00076 typedef std::pair<unsigned int, unsigned int> range;
00077
00078 IndexRangeAssociation() : isFilling_(false) {}
00079
00082 template<typename RefKey>
00083 range operator[](const RefKey &r) const {
00084 return get(r.id(), r.key());
00085 }
00086
00089 range get(const edm::ProductID & id, unsigned int t) const ;
00090
00092 bool contains(ProductID id) const ;
00093
00095 unsigned int size() const { return ref_offsets_.empty() ? 0 : ref_offsets_.size() - 1; }
00096
00098 bool empty() const { return ref_offsets_.empty(); }
00099
00104 class FastFiller : boost::noncopyable {
00105 public:
00107 FastFiller(IndexRangeAssociation &assoc, ProductID id, unsigned int size) ;
00108
00110 ~FastFiller() ;
00111
00113 template<typename RefKey>
00114 void insert(const RefKey &r, unsigned int startingOffset, unsigned int size) {
00115 insert(r.id(), r.key(), startingOffset, size);
00116 }
00117
00119 void insert(edm::ProductID id, unsigned int key, unsigned int startingOffset, unsigned int size) ;
00120 private:
00121 IndexRangeAssociation & assoc_;
00122 const ProductID id_;
00123 unsigned int start_, end_;
00125 int lastKey_;
00126 };
00127 friend class FastFiller;
00128
00129 void swap(IndexRangeAssociation &other) ;
00130
00131 static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where) ;
00132 private:
00133 typedef std::pair<edm::ProductID,unsigned int> id_off_pair;
00134 typedef std::vector<id_off_pair> id_offset_vector;
00135 typedef std::vector<int> offset_vector;
00136 id_offset_vector id_offsets_;
00137 offset_vector ref_offsets_;
00138
00139 bool isFilling_;
00140 struct IDComparator {
00141 bool operator()(const id_off_pair &p, const edm::ProductID &id) const { return p.first < id; }
00142 };
00143
00144
00145 };
00146
00147
00148 inline void swap(IndexRangeAssociation& lhs, IndexRangeAssociation& rhs) { lhs.swap(rhs); }
00149
00150 }
00151
00152 template<typename C>
00153 class MultiAssociation {
00154 public:
00155 typedef C Collection;
00156 typedef boost::sub_range<const Collection> const_range;
00157 typedef boost::sub_range<Collection> range;
00158
00159 MultiAssociation() {}
00160
00162 template<typename RefKey>
00163 const_range operator[](const RefKey &r) const {
00164 return get(r.id(), r.key());
00165 }
00166
00168 template<typename RefKey>
00169 range operator[](const RefKey &r) {
00170 return get(r.id(), r.key());
00171 }
00172
00174 template<typename RefKey>
00175 Collection getValues(const RefKey &r) const {
00176 return getValues(r.id(), r.key());
00177 }
00178
00180 bool contains(const edm::ProductID &id) const { return indices_.contains(id); }
00181
00183 const_range get(const edm::ProductID &id, unsigned int t) const ;
00184
00186 range get(const edm::ProductID &id, unsigned int t) ;
00187
00189 Collection getValues(const edm::ProductID &id, unsigned int t) const ;
00190
00191 void swap(MultiAssociation &other) {
00192 indices_.swap(other.indices_);
00193 data_.swap(other.data_);
00194 }
00195
00197 unsigned int dataSize() const { return data_.size(); }
00198
00200 unsigned int size() const { return indices_.size(); }
00201
00203 bool empty() const { return indices_.empty(); }
00204
00209 class FastFiller {
00210 public:
00211 template<typename HandleType>
00212 FastFiller(MultiAssociation &assoc, const HandleType &handle) :
00213 assoc_(assoc), indexFiller_(new IndexFiller(assoc_.indices_, handle.id(), handle->size())) {}
00214
00215 FastFiller(MultiAssociation &assoc, edm::ProductID id, unsigned int size) :
00216 assoc_(assoc), indexFiller_(new IndexFiller(assoc_.indices_, id, size)) {}
00217
00218 ~FastFiller() {}
00219
00221 template<typename KeyRef>
00222 void setValues(const KeyRef &k, const Collection &refs) { setValues(k.id(), k.key(), refs); }
00223
00225 void setValues(const edm::ProductID &id, unsigned int key, const Collection &refs);
00226 private:
00227 MultiAssociation & assoc_;
00228 typedef edm::helper::IndexRangeAssociation::FastFiller IndexFiller;
00229 boost::shared_ptr<IndexFiller> indexFiller_;
00230
00231 };
00232 friend class FastFiller;
00233
00234 template<typename HandleType>
00235 FastFiller fastFiller(const HandleType &handle) { return FastFiller(*this, handle); }
00236
00242 class LazyFiller {
00243 public:
00244 template<typename HandleType>
00245 LazyFiller(MultiAssociation &assoc, const HandleType &handle, bool fillOnExit=false) :
00246 assoc_(assoc),
00247 id_(handle.id()), size_(handle->size()),
00248 tempValues_(new TempValues()), fillOnExit_(fillOnExit) {}
00249 ~LazyFiller() noexcept(false) { if (fillOnExit_) fill(); }
00250
00255 void fill() noexcept(false);
00256
00258 void setFillOnExit(bool fillOnExit) { fillOnExit_ = fillOnExit; }
00259
00261 template<typename KeyRef>
00262 void setValues(const KeyRef &k, const Collection &refs) ;
00263
00266 template<typename KeyRef>
00267 void swapValues(const KeyRef &k, Collection &refs) ;
00268 private:
00269 typedef std::map<unsigned int, Collection> TempValues;
00270 MultiAssociation & assoc_;
00271 ProductID id_;
00272 unsigned int size_;
00273 boost::shared_ptr<TempValues> tempValues_;
00274 bool fillOnExit_;
00275 };
00276 friend class LazyFiller;
00277
00278 template<typename HandleType>
00279 LazyFiller lazyFiller(const HandleType &h, bool fillOnExit=false) { return LazyFiller(*this, h, fillOnExit); }
00280
00281
00282 CMS_CLASS_VERSION(10)
00283
00284 private:
00285 typedef helper::IndexRangeAssociation Indices;
00286 Indices indices_;
00287 Collection data_;
00288
00289 };
00290
00291
00292 template <typename C>
00293 inline void swap(MultiAssociation<C>& lhs, MultiAssociation<C>& rhs) { lhs.swap(rhs); }
00294
00295
00296 template<typename C>
00297 typename MultiAssociation<C>::const_range
00298 MultiAssociation<C>::get(const edm::ProductID & id, unsigned int key) const {
00299 Indices::range idxrange = indices_.get(id,key);
00300 return const_range(data_.begin()+idxrange.first, data_.begin()+idxrange.second);
00301 }
00302
00303 template<typename C>
00304 typename MultiAssociation<C>::range
00305 MultiAssociation<C>::get(const edm::ProductID & id, unsigned int key) {
00306 Indices::range idxrange = indices_.get(id,key);
00307 return range(data_.begin()+idxrange.first, data_.begin()+idxrange.second);
00308 }
00309
00310
00311 template<typename C>
00312 typename MultiAssociation<C>::Collection
00313 MultiAssociation<C>::getValues(const edm::ProductID & id, unsigned int key) const {
00314 Collection ret;
00315 const_range values = get(id,key);
00316 for (typename const_range::const_iterator it = values.begin(), ed = values.end(); it != ed; ++it) {
00317 ret.push_back(*it);
00318 }
00319 return ret;
00320 }
00321
00322 template<typename C>
00323 void MultiAssociation<C>::FastFiller::setValues(const edm::ProductID & id, unsigned int key, const Collection &vals) {
00324 indexFiller_->insert(id, key, assoc_.data_.size(), vals.size());
00325 for (typename Collection::const_iterator it = vals.begin(), ed = vals.end(); it != ed; ++it) {
00326 assoc_.data_.push_back(*it);
00327 }
00328 }
00329
00330 template<typename C>
00331 template<typename KeyRef>
00332 void MultiAssociation<C>::LazyFiller::setValues(const KeyRef &k, const Collection &vals) {
00333 if (k.id() != id_) Indices::throwUnexpectedProductID(k.id(),id_,"LazyFiller::insert");
00334 (*tempValues_)[k.key()] = vals;
00335 }
00336
00337 template<typename C>
00338 template<typename KeyRef>
00339 void MultiAssociation<C>::LazyFiller::swapValues(const KeyRef &k, Collection &vals) {
00340 if (k.id() != id_) Indices::throwUnexpectedProductID(k.id(),id_,"LazyFiller::insert");
00341 vals.swap((*tempValues_)[k.key()]);
00342 }
00343
00344
00345 template<typename C>
00346 void MultiAssociation<C>::LazyFiller::fill() {
00347 if (id_ != ProductID()) {
00348 typename MultiAssociation<C>::FastFiller filler(assoc_, id_, size_);
00349 for (typename TempValues::const_iterator it = tempValues_->begin(), ed = tempValues_->end(); it != ed; ++it) {
00350 filler.setValues(id_, it->first, it->second);
00351 }
00352 id_ = ProductID();
00353 }
00354 }
00355
00356
00357 }
00358
00359 #endif