CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/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.38 $
00020  *
00021  * $Id: RangeMap.h,v 1.38 2011/03/08 18:47:15 chrjones Exp $
00022  *
00023  */
00024 #include <map>
00025 #include <vector>
00026 #include <ext/functional>
00027 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00028 #include "FWCore/Utilities/interface/Exception.h"
00029 #include "DataFormats/Common/interface/traits.h"
00030 #include "DataFormats/Common/interface/CloneTrait.h"
00031 
00032 namespace edm {
00033   
00034   template<typename ID, typename C, typename P = typename clonehelper::CloneTrait<C>::type >
00035   class RangeMap {
00036   public:
00038     typedef typename C::value_type value_type;
00040     typedef typename C::size_type size_type;
00042     typedef typename C::reference reference;
00044     typedef typename C::pointer pointer;
00046     typedef typename C::const_iterator const_iterator;
00048     //use unsigned int rather than C::size_type in order to avoid porting problems
00049     typedef std::pair<unsigned int, unsigned int> pairType;
00051     typedef std::map<ID, pairType> mapType;
00053     typedef std::pair<const_iterator, const_iterator> range;
00054     
00055   private:
00057     template<typename CMP> 
00058     struct comp {
00059       comp(const CMP  c) : cmp(c) { }
00060       bool operator()(ID id, const typename mapType::value_type & p) {
00061         return cmp(id, p.first);
00062       }
00063       bool operator()(const typename mapType::value_type & p, ID id) {
00064         return cmp(p.first, id);
00065       }
00066     private:
00067       CMP cmp;
00068       
00069     };
00070 
00071   public:
00073     RangeMap() { }
00081     template<typename CMP> 
00082     range get(ID id, CMP comparator) const {
00083       using namespace __gnu_cxx;
00084       std::pair<typename mapType::const_iterator,
00085         typename mapType::const_iterator> r =
00086         std::equal_range(map_.begin(), map_.end(), id, comp<CMP>(comparator));
00087       const_iterator begin, end;
00088       if ((r.first) == map_.end()){
00089         begin = end = collection_.end();
00090         return  std::make_pair(begin,end);
00091       } else {
00092         begin = collection_.begin() + (r.first)->second.first;
00093       }
00094       if ((r.second) == map_.end()){
00095         end = collection_.end();
00096       }else{
00097         end = collection_.begin() + (r.second)->second.first;
00098       }
00099       return  std::make_pair(begin,end);
00100     }
00102     template<typename CMP> 
00103     range get(std::pair<ID, CMP> p) const {
00104       return get(p.first, p.second); 
00105     }
00107     range get(ID id) const {
00108       const_iterator begin, end;
00109       typename mapType::const_iterator i = map_.find(id);
00110       if (i != map_.end()) { 
00111         begin = collection_.begin() + i->second.first;
00112         end = collection_.begin() + i->second.second;
00113       } else {
00114         begin = end = collection_.end();
00115       }
00116       return std::make_pair(begin, end);
00117     }
00119     template<typename CI>
00120     void put(ID id, CI begin, CI end) {
00121       typename mapType::const_iterator i = map_.find(id);
00122       if(i != map_.end()) {
00123         throw Exception(errors::LogicError, "trying to insert duplicate entry");
00124       }
00125       assert(i == map_.end());
00126       pairType & p = map_[ id ];
00127       p.first = collection_.size();
00128       for(CI i = begin; i != end; ++i)
00129         collection_.push_back(P::clone(*i));
00130       p.second = collection_.size();
00131     }
00133     size_t size() const { return collection_.size(); }
00135     typename C::const_iterator begin() const { return collection_.begin(); }
00137     typename C::const_iterator end() const { return collection_.end(); }
00139     struct id_iterator {
00140       typedef ID value_type;
00141       typedef ID * pointer;
00142       typedef ID & reference;
00143       typedef ptrdiff_t difference_type;
00144       typedef typename mapType::const_iterator::iterator_category iterator_category;
00145       typedef typename mapType::const_iterator const_iterator;
00146       id_iterator() { }
00147       id_iterator(const_iterator o) : i(o) { }
00148       id_iterator & operator=(const id_iterator & it) { i = it.i; return *this; }
00149       id_iterator& operator++() { ++i; return *this; }
00150       id_iterator operator++(int) { id_iterator ci = *this; ++i; return ci; }
00151       id_iterator& operator--() { --i; return *this; }
00152       id_iterator operator--(int) { id_iterator ci = *this; --i; return ci; }
00153       bool operator==(const id_iterator& ci) const { return i == ci.i; }
00154       bool operator!=(const id_iterator& ci) const { return i != ci.i; }
00155       const ID operator * () const { return i->first; }      
00156     private:
00157       const_iterator i;
00158     };
00160     void post_insert() {
00161       // sorts the container via ID
00162       C tmp;
00163       for (typename mapType::iterator it = map_.begin(), itEnd = map_.end(); it != itEnd; it ++) {   
00164         range r = get((*it).first);
00165         //do cast to acknowledge that we may be going from a larger type to a smaller type but we are OK
00166         unsigned int begIt = static_cast<unsigned int>(tmp.size());
00167         for(const_iterator i = r.first; i != r.second; ++i)
00168           tmp.push_back(P::clone(*i));
00169         unsigned int endIt = static_cast<unsigned int>(tmp.size());
00170         it->second = pairType(begIt, endIt);
00171       }
00172       collection_ = tmp;
00173     }
00175     id_iterator id_begin() const { return id_iterator(map_.begin()); }
00177     id_iterator id_end() const { return id_iterator(map_.end()); }
00179     size_t id_size() const { return map_.size(); }
00181     std::vector<ID> ids() const {
00182       std::vector<ID> temp(id_size());
00183       std::copy(id_begin(), id_end(), temp.begin());
00184       return temp;
00185     }
00187     reference operator[](size_type i) { return collection_[ i ]; }
00188 
00190     void swap(RangeMap<ID, C, P> & other);
00191 
00193     RangeMap& operator=(RangeMap const& rhs);
00194 
00195     //Used by ROOT storage
00196     CMS_CLASS_VERSION(10)
00197 
00198   private:
00200     C collection_;
00202     mapType map_;
00203   };
00204 
00205   template <typename ID, typename C, typename P>
00206   inline
00207   void
00208   RangeMap<ID, C, P>::swap(RangeMap<ID, C, P> & other) {
00209     collection_.swap(other.collection_);
00210     map_.swap(other.map_);
00211   }
00212 
00213   template <typename ID, typename C, typename P>
00214   inline
00215   RangeMap<ID, C, P>&
00216   RangeMap<ID, C, P>::operator=(RangeMap<ID, C, P> const& rhs) {
00217     RangeMap<ID, C, P> temp(rhs);
00218     this->swap(temp);
00219     return *this;
00220   }
00221 
00222   // free swap function
00223   template <typename ID, typename C, typename P>
00224   inline
00225   void
00226   swap(RangeMap<ID, C, P> & a, RangeMap<ID, C, P> & b) {
00227     a.swap(b);
00228   }
00229 
00230 }
00231 
00232 #endif