File indexing completed on 2024-04-06 12:03:55
0001 #include <algorithm>
0002 #include "DataFormats/Common/interface/MultiAssociation.h"
0003 #include "DataFormats/Provenance/interface/ProductID.h"
0004 #include "FWCore/Utilities/interface/Exception.h"
0005
0006 using edm::ProductID;
0007 using edm::helper::IndexRangeAssociation;
0008
0009 IndexRangeAssociation::range IndexRangeAssociation::get(const ProductID &id, unsigned int key) const {
0010 typedef IndexRangeAssociation::id_offset_vector::const_iterator iter;
0011 iter pos = std::lower_bound(id_offsets_.begin(), id_offsets_.end(), id, IDComparator());
0012 if ((pos == id_offsets_.end()) || (pos->first != id)) {
0013 throw cms::Exception("Bad Key") << "Product ID " << id << " not found in this IndexRangeAssociation\n";
0014 }
0015
0016 if ((pos + 1 != id_offsets_.end()) && (pos->second + key >= (pos + 1)->second)) {
0017 throw cms::Exception("Bad Offset") << "Key " << key << " goes beyond bounds " << ((pos + 1)->second - pos->second)
0018 << " of this key collection within IndexRangeAssociation\n";
0019 }
0020
0021 offset_vector::const_iterator offs = ref_offsets_.begin() + pos->second + key;
0022 if (offs >= ref_offsets_.end() - 1) {
0023 throw cms::Exception("Bad Offset") << "Key " << key << " goes beyond bounds " << ref_offsets_.size() - 1
0024 << " of this IndexRangeAssociation\n";
0025 }
0026 return range(*offs, *(offs + 1));
0027 }
0028
0029 bool IndexRangeAssociation::contains(ProductID id) const {
0030 typedef IndexRangeAssociation::id_offset_vector::const_iterator iter;
0031 iter pos = std::lower_bound(id_offsets_.begin(), id_offsets_.end(), id, IDComparator());
0032 return (pos != id_offsets_.end()) && (pos->first == id);
0033 }
0034
0035 void IndexRangeAssociation::swap(IndexRangeAssociation &other) {
0036 if (isFilling_ || other.isFilling_)
0037 throw cms::Exception("Busy") << "Can't swap an IndexRangeAssociation while it's being filled!\n";
0038 id_offsets_.swap(other.id_offsets_);
0039 ref_offsets_.swap(other.ref_offsets_);
0040 }
0041
0042 IndexRangeAssociation::FastFiller::FastFiller(IndexRangeAssociation &assoc, ProductID id, unsigned int size)
0043 : assoc_(assoc),
0044 id_(id),
0045 start_(assoc.ref_offsets_.empty() ? 0 : assoc.ref_offsets_.size() - 1),
0046 end_(start_ + size),
0047 lastKey_(-1) {
0048 if (assoc_.isFilling_)
0049 throw cms::Exception("Unsupported Operation")
0050 << "IndexRangeAssociation::FastFiller: you already have one active filler for this map.\n";
0051
0052
0053 typedef IndexRangeAssociation::id_offset_vector::iterator iter;
0054 iter pos =
0055 std::lower_bound(assoc_.id_offsets_.begin(), assoc_.id_offsets_.end(), id, IndexRangeAssociation::IDComparator());
0056
0057
0058 if ((pos != assoc_.id_offsets_.end()) && (pos->first == id))
0059 throw cms::Exception("Duplicated Key")
0060 << "IndexRangeAssociation::FastFiller: there is already an entry for ProductID " << id << " in this map.\n";
0061
0062
0063 assoc_.isFilling_ = true;
0064
0065
0066 assoc_.id_offsets_.insert(pos, IndexRangeAssociation::id_off_pair(id, start_));
0067
0068 int lastEnd = (assoc_.ref_offsets_.empty() ? 0 : assoc_.ref_offsets_.back());
0069 assoc_.ref_offsets_.resize(end_ + 1, -1);
0070 assoc_.ref_offsets_.back() = lastEnd;
0071 }
0072
0073 IndexRangeAssociation::FastFiller::~FastFiller() {
0074
0075
0076 typedef IndexRangeAssociation::offset_vector::iterator IT;
0077
0078
0079 IT top = assoc_.ref_offsets_.begin() + start_;
0080 IT it = assoc_.ref_offsets_.begin() + end_;
0081 int offset = *it;
0082 for (--it; it >= top; --it) {
0083 if (*it == -1) {
0084
0085 *it = offset;
0086 } else {
0087
0088 offset = *it;
0089 }
0090 }
0091 assoc_.isFilling_ = false;
0092
0093
0094 }
0095
0096 void IndexRangeAssociation::FastFiller::insert(edm::ProductID id,
0097 unsigned int key,
0098 unsigned int startingOffset,
0099 unsigned int size) {
0100 if (id != id_)
0101 IndexRangeAssociation::throwUnexpectedProductID(id, id_, "FastFiller::insert");
0102 if (int(key) <= lastKey_)
0103 throw cms::Exception("Bad Key") << "IndexRangeAssociation::FastFiller: you must fill this in strict key order\n"
0104 << "\tLast key = " << lastKey_ << ", this key = " << key << "\n";
0105 if (key >= end_)
0106 throw cms::Exception("Bad Key")
0107 << "IndexRangeAssociation::FastFiller: key index out of bounds for this collection\n"
0108 << "\tKey = " << key << ", bound = " << end_ << "\n";
0109 if ((assoc_.ref_offsets_.back() != 0) && (int(startingOffset) != assoc_.ref_offsets_.back()))
0110 throw cms::Exception("Bad Offset")
0111 << "IndexRangeAssociation::FastFiller: The start for this key is not the end of the preceding key.\n"
0112 << "\tThis offset = " << startingOffset << ", last key = " << lastKey_
0113 << ", last end offset = " << assoc_.ref_offsets_.back() << "\n";
0114 assoc_.ref_offsets_[start_ + key] = startingOffset;
0115 lastKey_ = key;
0116 assoc_.ref_offsets_.back() += size;
0117 }
0118
0119 void IndexRangeAssociation::throwUnexpectedProductID(ProductID found, ProductID expected, const char *where) {
0120 throw cms::Exception("Unexpected ProductID")
0121 << where << ": found product id " << found << ", while expecting " << expected << ".\n"
0122 << "Make sure you're not mismatching references from different collections.\n";
0123 }