CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:30:33 2009 for CMSSW by  doxygen 1.5.4