File indexing completed on 2023-03-17 10:49:23
0001 #ifndef DataFormats_Common_MultiAssociation_h
0002 #define DataFormats_Common_MultiAssociation_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
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 #include <vector>
0052 #include <map>
0053 #include <memory>
0054 #include <boost/range.hpp>
0055 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0056 #include "DataFormats/Provenance/interface/ProductID.h"
0057
0058 namespace edm {
0059 namespace helper {
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 class IndexRangeAssociation {
0072 public:
0073 typedef std::pair<unsigned int, unsigned int> range;
0074
0075 IndexRangeAssociation() : isFilling_(false) {}
0076
0077
0078
0079 template <typename RefKey>
0080 range operator[](const RefKey &r) const {
0081 return get(r.id(), r.key());
0082 }
0083
0084
0085
0086 range get(const edm::ProductID &id, unsigned int t) const;
0087
0088
0089 bool contains(ProductID id) const;
0090
0091
0092 unsigned int size() const { return ref_offsets_.empty() ? 0 : ref_offsets_.size() - 1; }
0093
0094
0095 bool empty() const { return ref_offsets_.empty(); }
0096
0097
0098
0099
0100
0101 class FastFiller {
0102 public:
0103 FastFiller(const FastFiller &) = delete;
0104 FastFiller &operator=(const FastFiller &) = delete;
0105
0106
0107 FastFiller(IndexRangeAssociation &assoc, ProductID id, unsigned int size);
0108
0109
0110 ~FastFiller();
0111
0112
0113 template <typename RefKey>
0114 void insert(const RefKey &r, unsigned int startingOffset, unsigned int size) {
0115 insert(r.id(), r.key(), startingOffset, size);
0116 }
0117
0118
0119 void insert(edm::ProductID id, unsigned int key, unsigned int startingOffset, unsigned int size);
0120
0121 private:
0122 IndexRangeAssociation &assoc_;
0123 const ProductID id_;
0124 unsigned int start_, end_;
0125
0126 int lastKey_;
0127 };
0128 friend class FastFiller;
0129
0130 void swap(IndexRangeAssociation &other);
0131
0132 static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where);
0133
0134 private:
0135 typedef std::pair<edm::ProductID, unsigned int> id_off_pair;
0136 typedef std::vector<id_off_pair> id_offset_vector;
0137 typedef std::vector<int> offset_vector;
0138 id_offset_vector id_offsets_;
0139 offset_vector ref_offsets_;
0140
0141 bool isFilling_;
0142 struct IDComparator {
0143 bool operator()(const id_off_pair &p, const edm::ProductID &id) const { return p.first < id; }
0144 };
0145 };
0146
0147
0148 inline void swap(IndexRangeAssociation &lhs, IndexRangeAssociation &rhs) { lhs.swap(rhs); }
0149
0150 }
0151
0152 template <typename C>
0153 class MultiAssociation {
0154 public:
0155 typedef C Collection;
0156 typedef boost::sub_range<const Collection> const_range;
0157 typedef boost::sub_range<Collection> range;
0158
0159 MultiAssociation() {}
0160
0161
0162 template <typename RefKey>
0163 const_range operator[](const RefKey &r) const {
0164 return get(r.id(), r.key());
0165 }
0166
0167
0168 template <typename RefKey>
0169 range operator[](const RefKey &r) {
0170 return get(r.id(), r.key());
0171 }
0172
0173
0174 template <typename RefKey>
0175 Collection getValues(const RefKey &r) const {
0176 return getValues(r.id(), r.key());
0177 }
0178
0179
0180 bool contains(const edm::ProductID &id) const { return indices_.contains(id); }
0181
0182
0183 const_range get(const edm::ProductID &id, unsigned int t) const;
0184
0185
0186 range get(const edm::ProductID &id, unsigned int t);
0187
0188
0189 Collection getValues(const edm::ProductID &id, unsigned int t) const;
0190
0191 void swap(MultiAssociation &other) {
0192 indices_.swap(other.indices_);
0193 data_.swap(other.data_);
0194 }
0195
0196
0197 unsigned int dataSize() const { return data_.size(); }
0198
0199
0200 unsigned int size() const { return indices_.size(); }
0201
0202
0203 bool empty() const { return indices_.empty(); }
0204
0205
0206
0207
0208
0209 class FastFiller {
0210 public:
0211 template <typename HandleType>
0212 FastFiller(MultiAssociation &assoc, const HandleType &handle)
0213 : assoc_(assoc), indexFiller_(new IndexFiller(assoc_.indices_, handle.id(), handle->size())) {}
0214
0215 FastFiller(MultiAssociation &assoc, edm::ProductID id, unsigned int size)
0216 : assoc_(assoc), indexFiller_(new IndexFiller(assoc_.indices_, id, size)) {}
0217
0218 ~FastFiller() {}
0219
0220
0221 template <typename KeyRef>
0222 void setValues(const KeyRef &k, const Collection &refs) {
0223 setValues(k.id(), k.key(), refs);
0224 }
0225
0226
0227 void setValues(const edm::ProductID &id, unsigned int key, const Collection &refs);
0228
0229 private:
0230 MultiAssociation &assoc_;
0231 typedef edm::helper::IndexRangeAssociation::FastFiller IndexFiller;
0232 std::shared_ptr<IndexFiller> indexFiller_;
0233
0234 };
0235 friend class FastFiller;
0236
0237 template <typename HandleType>
0238 FastFiller fastFiller(const HandleType &handle) {
0239 return FastFiller(*this, handle);
0240 }
0241
0242
0243
0244
0245
0246
0247 class LazyFiller {
0248 public:
0249 template <typename HandleType>
0250 LazyFiller(MultiAssociation &assoc, const HandleType &handle, bool fillOnExit = false)
0251 : assoc_(assoc),
0252 id_(handle.id()),
0253 size_(handle->size()),
0254 tempValues_(new TempValues()),
0255 fillOnExit_(fillOnExit) {}
0256 ~LazyFiller() noexcept(false) {
0257 if (fillOnExit_)
0258 fill();
0259 }
0260
0261
0262
0263
0264
0265 void fill() noexcept(false);
0266
0267
0268 void setFillOnExit(bool fillOnExit) { fillOnExit_ = fillOnExit; }
0269
0270
0271 template <typename KeyRef>
0272 void setValues(const KeyRef &k, const Collection &refs);
0273
0274
0275
0276 template <typename KeyRef>
0277 void swapValues(const KeyRef &k, Collection &refs);
0278
0279 private:
0280 typedef std::map<unsigned int, Collection> TempValues;
0281 MultiAssociation &assoc_;
0282 ProductID id_;
0283 unsigned int size_;
0284 std::shared_ptr<TempValues> tempValues_;
0285 bool fillOnExit_;
0286 };
0287 friend class LazyFiller;
0288
0289 template <typename HandleType>
0290 LazyFiller lazyFiller(const HandleType &h, bool fillOnExit = false) {
0291 return LazyFiller(*this, h, fillOnExit);
0292 }
0293
0294
0295 CMS_CLASS_VERSION(10)
0296
0297 private:
0298 typedef helper::IndexRangeAssociation Indices;
0299 Indices indices_;
0300 Collection data_;
0301
0302 };
0303
0304
0305 template <typename C>
0306 inline void swap(MultiAssociation<C> &lhs, MultiAssociation<C> &rhs) {
0307 lhs.swap(rhs);
0308 }
0309
0310
0311 template <typename C>
0312 typename MultiAssociation<C>::const_range MultiAssociation<C>::get(const edm::ProductID &id, unsigned int key) const {
0313 Indices::range idxrange = indices_.get(id, key);
0314 return const_range(data_.begin() + idxrange.first, data_.begin() + idxrange.second);
0315 }
0316
0317 template <typename C>
0318 typename MultiAssociation<C>::range MultiAssociation<C>::get(const edm::ProductID &id, unsigned int key) {
0319 Indices::range idxrange = indices_.get(id, key);
0320 return range(data_.begin() + idxrange.first, data_.begin() + idxrange.second);
0321 }
0322
0323 template <typename C>
0324 typename MultiAssociation<C>::Collection MultiAssociation<C>::getValues(const edm::ProductID &id,
0325 unsigned int key) const {
0326 Collection ret;
0327 const_range values = get(id, key);
0328 for (typename const_range::const_iterator it = values.begin(), ed = values.end(); it != ed; ++it) {
0329 ret.push_back(*it);
0330 }
0331 return ret;
0332 }
0333
0334 template <typename C>
0335 void MultiAssociation<C>::FastFiller::setValues(const edm::ProductID &id, unsigned int key, const Collection &vals) {
0336 indexFiller_->insert(id, key, assoc_.data_.size(), vals.size());
0337 for (typename Collection::const_iterator it = vals.begin(), ed = vals.end(); it != ed; ++it) {
0338 assoc_.data_.push_back(*it);
0339 }
0340 }
0341
0342 template <typename C>
0343 template <typename KeyRef>
0344 void MultiAssociation<C>::LazyFiller::setValues(const KeyRef &k, const Collection &vals) {
0345 if (k.id() != id_)
0346 Indices::throwUnexpectedProductID(k.id(), id_, "LazyFiller::insert");
0347 (*tempValues_)[k.key()] = vals;
0348 }
0349
0350 template <typename C>
0351 template <typename KeyRef>
0352 void MultiAssociation<C>::LazyFiller::swapValues(const KeyRef &k, Collection &vals) {
0353 if (k.id() != id_)
0354 Indices::throwUnexpectedProductID(k.id(), id_, "LazyFiller::insert");
0355 vals.swap((*tempValues_)[k.key()]);
0356 }
0357
0358 template <typename C>
0359 void MultiAssociation<C>::LazyFiller::fill() {
0360 if (id_ != ProductID()) {
0361 typename MultiAssociation<C>::FastFiller filler(assoc_, id_, size_);
0362 for (typename TempValues::const_iterator it = tempValues_->begin(), ed = tempValues_->end(); it != ed; ++it) {
0363 filler.setValues(id_, it->first, it->second);
0364 }
0365 id_ = ProductID();
0366 }
0367 }
0368
0369 }
0370
0371 #endif