CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_6/src/DataFormats/Common/interface/RangeMap.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_RangeMap_h
00002 #define DataFormats_Common_RangeMap_h
00003 /* \class edm::RangeMap
00004  *
00005  * Generic container storing objects arranged according 
00006  * to a specified identifier. 
00007  *
00008  * The data content can be fetched either via
00009  * an iterator, or specifying user-defined identifier 
00010  * match criteria.
00011  *
00012  * The template parameters are:
00013  * - ID: identifier type
00014  * - C : underlying collection used to 
00015  * - P : policy to perform object cloning
00016  *
00017  * \author Tommaso Boccali, Luca Lista INFN
00018  *
00019  * \version $Revision: 1.39 $
00020  *
00021  *
00022  */
00023 #include <map>
00024 #include <vector>
00025 #include <ext/functional>
00026 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00027 #include "FWCore/Utilities/interface/Exception.h"
00028 #include "DataFormats/Common/interface/traits.h"
00029 #include "DataFormats/Common/interface/CloneTrait.h"
00030 
00031 namespace edm {
00032   
00033   template<typename ID, typename C, typename P = typename clonehelper::CloneTrait<C>::type >
00034   class RangeMap {
00035   public:
00037     typedef typename C::value_type value_type;
00039     typedef typename C::size_type size_type;
00041     typedef typename C::reference reference;
00043     typedef typename C::pointer pointer;
00045     typedef typename C::const_iterator const_iterator;
00047     //use unsigned int rather than C::size_type in order to avoid porting problems
00048     typedef std::pair<unsigned int, unsigned int> pairType;
00050     typedef std::map<ID, pairType> mapType;
00052     typedef std::pair<const_iterator, const_iterator> range;
00053     
00054   private:
00056     template<typename CMP> 
00057     struct comp {
00058       comp(const CMP  c) : cmp(c) { }
00059       bool operator()(ID id, const typename mapType::value_type & p) {
00060         return cmp(id, p.first);
00061       }
00062       bool operator()(const typename mapType::value_type & p, ID id) {
00063         return cmp(p.first, id);
00064       }
00065     private:
00066       CMP cmp;
00067       
00068     };
00069 
00070   public:
00072     RangeMap() { }
00080     template<typename CMP> 
00081     range get(ID id, CMP comparator) const {
00082       using namespace __gnu_cxx;
00083       std::pair<typename mapType::const_iterator,
00084         typename mapType::const_iterator> r =
00085         std::equal_range(map_.begin(), map_.end(), id, comp<CMP>(comparator));
00086       const_iterator begin, end;
00087       if ((r.first) == map_.end()){
00088         begin = end = collection_.end();
00089         return  std::make_pair(begin,end);
00090       } else {
00091         begin = collection_.begin() + (r.first)->second.first;
00092       }
00093       if ((r.second) == map_.end()){
00094         end = collection_.end();
00095       }else{
00096         end = collection_.begin() + (r.second)->second.first;
00097       }
00098       return  std::make_pair(begin,end);
00099     }
00101     template<typename CMP> 
00102     range get(std::pair<ID, CMP> p) const {
00103       return get(p.first, p.second); 
00104     }
00106     range get(ID id) const {
00107       const_iterator begin, end;
00108       typename mapType::const_iterator i = map_.find(id);
00109       if (i != map_.end()) { 
00110         begin = collection_.begin() + i->second.first;
00111         end = collection_.begin() + i->second.second;
00112       } else {
00113         begin = end = collection_.end();
00114       }
00115       return std::make_pair(begin, end);
00116     }
00118     template<typename CI>
00119     void put(ID id, CI begin, CI end) {
00120       typename mapType::const_iterator i = map_.find(id);
00121       if(i != map_.end()) {
00122         throw Exception(errors::LogicError, "trying to insert duplicate entry");
00123       }
00124       assert(i == map_.end());
00125       pairType & p = map_[ id ];
00126       p.first = collection_.size();
00127       for(CI i = begin; i != end; ++i)
00128         collection_.push_back(P::clone(*i));
00129       p.second = collection_.size();
00130     }
00132     size_t size() const { return collection_.size(); }
00134     typename C::const_iterator begin() const { return collection_.begin(); }
00136     typename C::const_iterator end() const { return collection_.end(); }
00138     struct id_iterator {
00139       typedef ID value_type;
00140       typedef ID * pointer;
00141       typedef ID & reference;
00142       typedef ptrdiff_t difference_type;
00143       typedef typename mapType::const_iterator::iterator_category iterator_category;
00144       typedef typename mapType::const_iterator const_iterator;
00145       id_iterator() { }
00146       id_iterator(const_iterator o) : i(o) { }
00147       id_iterator& operator++() { ++i; return *this; }
00148       id_iterator operator++(int) { id_iterator ci = *this; ++i; return ci; }
00149       id_iterator& operator--() { --i; return *this; }
00150       id_iterator operator--(int) { id_iterator ci = *this; --i; return ci; }
00151       bool operator==(const id_iterator& ci) const { return i == ci.i; }
00152       bool operator!=(const id_iterator& ci) const { return i != ci.i; }
00153       const ID operator * () const { return i->first; }      
00154     private:
00155       const_iterator i;
00156     };
00158     void post_insert() {
00159       // sorts the container via ID
00160       C tmp;
00161       for (typename mapType::iterator it = map_.begin(), itEnd = map_.end(); it != itEnd; it ++) {   
00162         range r = get((*it).first);
00163         //do cast to acknowledge that we may be going from a larger type to a smaller type but we are OK
00164         unsigned int begIt = static_cast<unsigned int>(tmp.size());
00165         for(const_iterator i = r.first; i != r.second; ++i)
00166           tmp.push_back(P::clone(*i));
00167         unsigned int endIt = static_cast<unsigned int>(tmp.size());
00168         it->second = pairType(begIt, endIt);
00169       }
00170       collection_ = tmp;
00171     }
00173     id_iterator id_begin() const { return id_iterator(map_.begin()); }
00175     id_iterator id_end() const { return id_iterator(map_.end()); }
00177     size_t id_size() const { return map_.size(); }
00179     std::vector<ID> ids() const {
00180       std::vector<ID> temp(id_size());
00181       std::copy(id_begin(), id_end(), temp.begin());
00182       return temp;
00183     }
00185     reference operator[](size_type i) { return collection_[ i ]; }
00186 
00188     void swap(RangeMap<ID, C, P> & other);
00189 
00191     RangeMap& operator=(RangeMap const& rhs);
00192 
00193     //Used by ROOT storage
00194     CMS_CLASS_VERSION(10)
00195 
00196   private:
00198     C collection_;
00200     mapType map_;
00201   };
00202 
00203   template <typename ID, typename C, typename P>
00204   inline
00205   void
00206   RangeMap<ID, C, P>::swap(RangeMap<ID, C, P> & other) {
00207     collection_.swap(other.collection_);
00208     map_.swap(other.map_);
00209   }
00210 
00211   template <typename ID, typename C, typename P>
00212   inline
00213   RangeMap<ID, C, P>&
00214   RangeMap<ID, C, P>::operator=(RangeMap<ID, C, P> const& rhs) {
00215     RangeMap<ID, C, P> temp(rhs);
00216     this->swap(temp);
00217     return *this;
00218   }
00219 
00220   // free swap function
00221   template <typename ID, typename C, typename P>
00222   inline
00223   void
00224   swap(RangeMap<ID, C, P> & a, RangeMap<ID, C, P> & b) {
00225     a.swap(b);
00226   }
00227 
00228 }
00229 
00230 #endif