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/Provenance/interface/ProductID.h"
00058
00059 namespace edm {
00060 namespace helper {
00065
00072 class IndexRangeAssociation {
00073 public:
00074 typedef std::pair<unsigned int, unsigned int> range;
00075
00076 IndexRangeAssociation() : isFilling_(false) {}
00077
00080 template<typename RefKey>
00081 range operator[](const RefKey &r) const {
00082 return get(r.id(), r.key());
00083 }
00084
00087 range get(const edm::ProductID & id, unsigned int t) const ;
00088
00090 bool contains(ProductID id) const ;
00091
00093 unsigned int size() const { return ref_offsets_.empty() ? 0 : ref_offsets_.size() - 1; }
00094
00096 bool empty() const { return ref_offsets_.empty(); }
00097
00102 class FastFiller : boost::noncopyable {
00103 public:
00105 FastFiller(IndexRangeAssociation &assoc, ProductID id, unsigned int size) ;
00106
00108 ~FastFiller() ;
00109
00111 template<typename RefKey>
00112 void insert(const RefKey &r, unsigned int startingOffset, unsigned int size) {
00113 insert(r.id(), r.key(), startingOffset, size);
00114 }
00115
00117 void insert(edm::ProductID id, unsigned int key, unsigned int startingOffset, unsigned int size) ;
00118 private:
00119 IndexRangeAssociation & assoc_;
00120 const ProductID id_;
00121 unsigned int start_, end_;
00123 int lastKey_;
00124 };
00125 friend class FastFiller;
00126
00127 void swap(IndexRangeAssociation &other) ;
00128
00129 static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where) ;
00130 private:
00131 typedef std::pair<edm::ProductID,unsigned int> id_off_pair;
00132 typedef std::vector<id_off_pair> id_offset_vector;
00133 typedef std::vector<int> offset_vector;
00134 id_offset_vector id_offsets_;
00135 offset_vector ref_offsets_;
00136
00137 bool isFilling_;
00138 struct IDComparator {
00139 bool operator()(const id_off_pair &p, const edm::ProductID &id) const { return p.first < id; }
00140 };
00141
00142
00143 };
00144
00145
00146 inline void swap(IndexRangeAssociation& lhs, IndexRangeAssociation& rhs) { lhs.swap(rhs); }
00147
00148 }
00149
00150 template<typename C>
00151 class MultiAssociation {
00152 public:
00153 typedef C Collection;
00154 typedef boost::sub_range<const Collection> const_range;
00155 typedef boost::sub_range<Collection> range;
00156
00157 MultiAssociation() {}
00158
00160 template<typename RefKey>
00161 const_range operator[](const RefKey &r) const {
00162 return get(r.id(), r.key());
00163 }
00164
00166 template<typename RefKey>
00167 range operator[](const RefKey &r) {
00168 return get(r.id(), r.key());
00169 }
00170
00172 template<typename RefKey>
00173 Collection getValues(const RefKey &r) const {
00174 return getValues(r.id(), r.key());
00175 }
00176
00178 bool contains(const edm::ProductID &id) const { return indices_.contains(id); }
00179
00181 const_range get(const edm::ProductID &id, unsigned int t) const ;
00182
00184 range get(const edm::ProductID &id, unsigned int t) ;
00185
00187 Collection getValues(const edm::ProductID &id, unsigned int t) const ;
00188
00189 void swap(MultiAssociation &other) {
00190 indices_.swap(other.indices_);
00191 data_.swap(other.data_);
00192 }
00193
00195 unsigned int dataSize() const { return data_.size(); }
00196
00198 unsigned int size() const { return indices_.size(); }
00199
00201 bool empty() const { return indices_.empty(); }
00202
00207 class FastFiller {
00208 public:
00209 template<typename HandleType>
00210 FastFiller(MultiAssociation &assoc, const HandleType &handle) :
00211 assoc_(assoc), indexFiller_(new IndexFiller(assoc_.indices_, handle.id(), handle->size())) {}
00212
00213 FastFiller(MultiAssociation &assoc, edm::ProductID id, unsigned int size) :
00214 assoc_(assoc), indexFiller_(new IndexFiller(assoc_.indices_, id, size)) {}
00215
00216 ~FastFiller() {}
00217
00219 template<typename KeyRef>
00220 void setValues(const KeyRef &k, const Collection &refs) { setValues(k.id(), k.key(), refs); }
00221
00223 void setValues(const edm::ProductID &id, unsigned int key, const Collection &refs);
00224 private:
00225 MultiAssociation & assoc_;
00226 typedef edm::helper::IndexRangeAssociation::FastFiller IndexFiller;
00227 boost::shared_ptr<IndexFiller> indexFiller_;
00228
00229 };
00230 friend class FastFiller;
00231
00232 template<typename HandleType>
00233 FastFiller fastFiller(const HandleType &handle) { return FastFiller(*this, handle); }
00234
00240 class LazyFiller {
00241 public:
00242 template<typename HandleType>
00243 LazyFiller(MultiAssociation &assoc, const HandleType &handle, bool fillOnExit=false) :
00244 assoc_(assoc),
00245 id_(handle.id()), size_(handle->size()),
00246 tempValues_(new TempValues()), fillOnExit_(fillOnExit) {}
00247 ~LazyFiller() { if (fillOnExit_) fill(); }
00248
00253 void fill();
00254
00256 void setFillOnExit(bool fillOnExit) { fillOnExit_ = fillOnExit; }
00257
00259 template<typename KeyRef>
00260 void setValues(const KeyRef &k, const Collection &refs) ;
00261
00264 template<typename KeyRef>
00265 void swapValues(const KeyRef &k, Collection &refs) ;
00266 private:
00267 typedef std::map<unsigned int, Collection> TempValues;
00268 MultiAssociation & assoc_;
00269 ProductID id_;
00270 unsigned int size_;
00271 boost::shared_ptr<TempValues> tempValues_;
00272 bool fillOnExit_;
00273 };
00274 friend class LazyFiller;
00275
00276 template<typename HandleType>
00277 LazyFiller lazyFiller(const HandleType &h, bool fillOnExit=false) { return LazyFiller(*this, h, fillOnExit); }
00278
00279 private:
00280 typedef helper::IndexRangeAssociation Indices;
00281 Indices indices_;
00282 Collection data_;
00283
00284 };
00285
00286
00287 template <typename C>
00288 inline void swap(MultiAssociation<C>& lhs, MultiAssociation<C>& rhs) { lhs.swap(rhs); }
00289
00290
00291 template<typename C>
00292 typename MultiAssociation<C>::const_range
00293 MultiAssociation<C>::get(const edm::ProductID & id, unsigned int key) const {
00294 Indices::range idxrange = indices_.get(id,key);
00295 return const_range(data_.begin()+idxrange.first, data_.begin()+idxrange.second);
00296 }
00297
00298 template<typename C>
00299 typename MultiAssociation<C>::range
00300 MultiAssociation<C>::get(const edm::ProductID & id, unsigned int key) {
00301 Indices::range idxrange = indices_.get(id,key);
00302 return range(data_.begin()+idxrange.first, data_.begin()+idxrange.second);
00303 }
00304
00305
00306 template<typename C>
00307 typename MultiAssociation<C>::Collection
00308 MultiAssociation<C>::getValues(const edm::ProductID & id, unsigned int key) const {
00309 Collection ret;
00310 const_range values = get(id,key);
00311 for (typename const_range::const_iterator it = values.begin(), ed = values.end(); it != ed; ++it) {
00312 ret.push_back(*it);
00313 }
00314 return ret;
00315 }
00316
00317 template<typename C>
00318 void MultiAssociation<C>::FastFiller::setValues(const edm::ProductID & id, unsigned int key, const Collection &vals) {
00319 indexFiller_->insert(id, key, assoc_.data_.size(), vals.size());
00320 for (typename Collection::const_iterator it = vals.begin(), ed = vals.end(); it != ed; ++it) {
00321 assoc_.data_.push_back(*it);
00322 }
00323 }
00324
00325 template<typename C>
00326 template<typename KeyRef>
00327 void MultiAssociation<C>::LazyFiller::setValues(const KeyRef &k, const Collection &vals) {
00328 if (k.id() != id_) Indices::throwUnexpectedProductID(k.id(),id_,"LazyFiller::insert");
00329 (*tempValues_)[k.key()] = vals;
00330 }
00331
00332 template<typename C>
00333 template<typename KeyRef>
00334 void MultiAssociation<C>::LazyFiller::swapValues(const KeyRef &k, Collection &vals) {
00335 if (k.id() != id_) Indices::throwUnexpectedProductID(k.id(),id_,"LazyFiller::insert");
00336 vals.swap((*tempValues_)[k.key()]);
00337 }
00338
00339
00340 template<typename C>
00341 void MultiAssociation<C>::LazyFiller::fill() {
00342 if (id_ != ProductID()) {
00343 typename MultiAssociation<C>::FastFiller filler(assoc_, id_, size_);
00344 for (typename TempValues::const_iterator it = tempValues_->begin(), ed = tempValues_->end(); it != ed; ++it) {
00345 filler.setValues(id_, it->first, it->second);
00346 }
00347 id_ = ProductID();
00348 }
00349 }
00350
00351
00352 }
00353
00354 #endif