CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/DataFormats/Common/interface/ValueMap.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_ValueMap_h
00002 #define DataFormats_Common_ValueMap_h
00003 /* \class ValueMap<T>
00004  *
00005  * \author Luca Lista, INFN
00006  *
00007  * \version $Id: ValueMap.h,v 1.20 2011/05/07 15:21:37 innocent Exp $
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         // std::pair<ProductID, offset> id = *j;
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     // raw index of a given (id,key) pair
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     //Used by ROOT storage
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   // Free swap function
00249   template <typename T>
00250   inline
00251   void swap(ValueMap<T>& lhs, ValueMap<T>& rhs) {
00252     lhs.swap(rhs);
00253   }
00254 
00255 }
00256 #endif