Go to the documentation of this file.00001 #ifndef DataFormats_Common_ValueMap_h
00002 #define DataFormats_Common_ValueMap_h
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00012 #include "DataFormats/Provenance/interface/ProductID.h"
00013 #include "FWCore/Utilities/interface/EDMException.h"
00014 #include <vector>
00015 #include <map>
00016 #include <iterator>
00017 #include <algorithm>
00018
00019 namespace edm {
00020 namespace helper {
00021 template<typename Map>
00022 class Filler {
00023 private:
00024 typedef std::vector<size_t> index_vector;
00025 typedef std::vector<typename Map::value_type> value_vector;
00026 typedef std::map<ProductID, value_vector> value_map;
00027 typedef typename Map::offset offset;
00028 typedef typename Map::id_offset_vector id_offset_vector;
00029 public:
00030 explicit Filler(Map & map) :
00031 map_(map) {
00032 add(map);
00033 }
00034 void add(const Map & map) {
00035 if (map.empty()) return;
00036 typename id_offset_vector::const_iterator j = map.ids_.begin();
00037 const typename id_offset_vector::const_iterator end = map.ids_.end();
00038 size_t i = 0;
00039 const size_t size = map.values_.size();
00040
00041 do {
00042 ProductID id = j->first;
00043 ++j;
00044 size_t max = (j == end ? size : j->second);
00045 typename value_map::iterator f = values_.find(id);
00046 if(f!=values_.end()) throwAdd();
00047 value_vector & values = values_.insert(std::make_pair(id, value_vector())).first->second;
00048 while(i!=max)
00049 values.push_back( map.values_[i++] );
00050 } while(j != end);
00051 }
00052 template<typename H, typename I>
00053 void insert(const H & h, I begin, I end) {
00054 ProductID id = h.id();
00055 size_t size = h->size(), sizeIt = end - begin;
00056 if(sizeIt!=size) throwFillSize();
00057 typename value_map::const_iterator f = values_.find(id);
00058 if(f != values_.end()) throwFillID(id);
00059 value_vector & values = values_.insert(make_pair(id, value_vector(size))).first->second;
00060 std::copy(begin, end, values.begin());
00061 }
00062 void fill() {
00063 map_.clear();
00064 offset off = 0;
00065 for(typename value_map::const_iterator i = values_.begin(); i != values_.end(); ++i) {
00066 ProductID id = i->first;
00067 map_.ids_.push_back(std::make_pair(id, off));
00068 const value_vector & values = i->second;
00069 for(typename value_vector::const_iterator j = values.begin(); j != values.end(); ++j) {
00070 map_.values_.push_back( *j );
00071 ++off;
00072 }
00073 }
00074 }
00075
00076 protected:
00077 Map & map_;
00078
00079 private:
00080 value_map values_;
00081 void throwFillSize() const {
00082 Exception::throwThis(errors::InvalidReference,
00083 "ValueMap::Filler: handle and reference "
00084 "collections should the same size\n");
00085 }
00086 void throwFillID(ProductID id) const {
00087 Exception e(errors::InvalidReference);
00088 e << "index map has already been filled for id: " << id << "\n";
00089 e.raise();
00090 }
00091 void throwAdd() const {
00092 Exception::throwThis(errors::InvalidReference,
00093 "ValueMap: trying to add entries for an already existing product\n");
00094 }
00095 };
00096 }
00097
00098 template<typename T>
00099 class ValueMap {
00100 public:
00101 typedef T value_type;
00102 typedef std::vector<value_type> container;
00103 typedef unsigned int offset;
00104 typedef std::vector<std::pair<ProductID, offset> > id_offset_vector;
00105 typedef typename container::reference reference_type;
00106 typedef typename container::const_reference const_reference_type;
00107
00108 ValueMap() { }
00109
00110 void swap(ValueMap& other) {
00111 values_.swap(other.values_);
00112 ids_.swap(other.ids_);
00113 }
00114
00115 ValueMap& operator=(ValueMap const& rhs) {
00116 ValueMap temp(rhs);
00117 this->swap(temp);
00118 return *this;
00119 }
00120
00121 template<typename RefKey>
00122 const_reference_type operator[](const RefKey & r) const {
00123 return get(r.id(), r.key());
00124 }
00125
00126 size_t rawIndexOf(ProductID id, size_t idx) const {
00127 typename id_offset_vector::const_iterator f = getIdOffset(id);
00128 if(f==ids_.end()) throwNotExisting();
00129 offset off = f->second;
00130 size_t j = off+idx;
00131 if(j >= values_.size()) throwIndexBound();
00132 return j;
00133 }
00134 const_reference_type get(ProductID id, size_t idx) const {
00135 return values_[rawIndexOf(id,idx)];
00136 }
00137 template<typename RefKey>
00138 reference_type operator[](const RefKey & r) {
00139 return get(r.id(), r.key());
00140 }
00141 reference_type get(ProductID id, size_t idx) {
00142 return values_[rawIndexOf(id,idx)];
00143 }
00144
00145 ValueMap<T> & operator+=(const ValueMap<T> & o) {
00146 add(o);
00147 return *this;
00148 }
00149 bool contains(ProductID id) const {
00150 return getIdOffset(id) != ids_.end();
00151 }
00152 size_t size() const { return values_.size(); }
00153 size_t idSize() const { return ids_.size(); }
00154 bool empty() const { return values_.empty(); }
00155 void clear() { values_.clear(); ids_.clear(); }
00156
00157 typedef helper::Filler<ValueMap<T> > Filler;
00158
00159 struct const_iterator {
00160 typedef ptrdiff_t difference_type;
00161 const_iterator():values_(0) {}
00162 ProductID id() const { return i_->first; }
00163 typename container::const_iterator begin() const {
00164 return values_->begin() + i_->second;
00165 }
00166 typename container::const_iterator end() const {
00167 if(i_ == end_) return values_->end();
00168 id_offset_vector::const_iterator end = i_; ++end;
00169 if(end == end_) return values_->end();
00170 return values_->begin() + end->second;
00171 }
00172 size_t size() const { return end() - begin(); }
00173 const T & operator[](size_t i) { return *(begin()+i); }
00174 const_iterator& operator++() { ++i_; return *this; }
00175 const_iterator operator++(int) { const_iterator ci = *this; ++i_; return ci; }
00176 const_iterator& operator--() { --i_; return *this; }
00177 const_iterator operator--(int) { const_iterator ci = *this; --i_; return ci; }
00178 difference_type operator-(const const_iterator & o) const { return i_ - o.i_; }
00179 const_iterator operator+(difference_type n) const { return const_iterator(i_ + n, end_, values_); }
00180 const_iterator operator-(difference_type n) const { return const_iterator(i_ - n, end_, values_); }
00181 bool operator<(const const_iterator & o) const { return i_ < o.i_; }
00182 bool operator==(const const_iterator& ci) const { return i_ == ci.i_; }
00183 bool operator!=(const const_iterator& ci) const { return i_ != ci.i_; }
00184 const_iterator & operator +=(difference_type d) { i_ += d; return *this; }
00185 const_iterator & operator -=(difference_type d) { i_ -= d; return *this; }
00186 private:
00187 const_iterator(const id_offset_vector::const_iterator & i_,
00188 const id_offset_vector::const_iterator & end,
00189 const container * values) :
00190 values_(values), i_(i_), end_(end) { }
00191 const container * values_;
00192 id_offset_vector::const_iterator i_, end_;
00193 friend class ValueMap<T>;
00194 };
00195
00196 const_iterator begin() const { return const_iterator(ids_.begin(), ids_.end(), &values_); }
00197 const_iterator end() const { return const_iterator(ids_.end(), ids_.end(), &values_); }
00198
00200 const id_offset_vector & ids() const { return ids_; }
00202 const_reference_type get(size_t idx) const { return values_[idx]; }
00203
00204
00205 CMS_CLASS_VERSION(10)
00206
00207 protected:
00208 container values_;
00209 id_offset_vector ids_;
00210
00211 typename id_offset_vector::const_iterator getIdOffset(ProductID id) const {
00212 typename id_offset_vector::const_iterator i = std::lower_bound(ids_.begin(), ids_.end(), id, IDComparator());
00213 if(i==ids_.end()) return i;
00214 return i->first == id ? i : ids_.end();
00215 }
00216
00217 void throwIndexBound() const {
00218 Exception::throwThis(errors::InvalidReference, "ValueMap: index out of upper boundary\n");
00219 }
00220
00221 private:
00222 struct IDComparator {
00223 bool operator()(const std::pair<ProductID, offset> & p, const ProductID & id) {
00224 return p.first < id;
00225 }
00226 };
00227 void throwNotExisting() const {
00228 Exception::throwThis(errors::InvalidReference, "ValueMap: no associated value for given product and index\n");
00229 }
00230
00231 void add( const ValueMap<T> & o ) {
00232 Filler filler(*this);
00233 filler.add(o);
00234 filler.fill();
00235 }
00236
00237 friend class helper::Filler<ValueMap<T> >;
00238 };
00239
00240 template<typename T>
00241 inline ValueMap<T> operator+( const ValueMap<T> & a1,
00242 const ValueMap<T> & a2 ) {
00243 ValueMap<T> a = a1;
00244 a += a2;
00245 return a;
00246 }
00247
00248
00249 template <typename T>
00250 inline
00251 void swap(ValueMap<T>& lhs, ValueMap<T>& rhs) {
00252 lhs.swap(rhs);
00253 }
00254
00255 }
00256 #endif