CMS 3D CMS Logo

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.36 $
00020  *
00021  * $Id: RangeMap.h,v 1.36 2008/07/23 22:50:16 wmtan Exp $
00022  *
00023  */
00024 #include <map>
00025 #include <vector>
00026 #include <ext/functional>
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 cms::Exception("Error") << "trying to insert duplicate entry";
00123       assert(i == map_.end());
00124       pairType & p = map_[ id ];
00125       p.first = collection_.size();
00126       for(CI i = begin; i != end; ++i)
00127         collection_.push_back(P::clone(*i));
00128       p.second = collection_.size();
00129     }
00131     size_t size() const { return collection_.size(); }
00133     typename C::const_iterator begin() const { return collection_.begin(); }
00135     typename C::const_iterator end() const { return collection_.end(); }
00137     struct id_iterator {
00138       typedef ID value_type;
00139       typedef ID * pointer;
00140       typedef ID & reference;
00141       typedef ptrdiff_t difference_type;
00142       typedef typename mapType::const_iterator::iterator_category iterator_category;
00143       typedef typename mapType::const_iterator const_iterator;
00144       id_iterator() { }
00145       id_iterator(const_iterator o) : i(o) { }
00146       id_iterator & operator=(const id_iterator & it) { i = it.i; return *this; }
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   private:
00195     C collection_;
00197     mapType map_;
00198   };
00199 
00200   template <typename ID, typename C, typename P>
00201   inline
00202   void
00203   RangeMap<ID, C, P>::swap(RangeMap<ID, C, P> & other) {
00204     collection_.swap(other.collection_);
00205     map_.swap(other.map_);
00206   }
00207 
00208   template <typename ID, typename C, typename P>
00209   inline
00210   RangeMap<ID, C, P>&
00211   RangeMap<ID, C, P>::operator=(RangeMap<ID, C, P> const& rhs) {
00212     RangeMap<ID, C, P> temp(rhs);
00213     this->swap(temp);
00214     return *this;
00215   }
00216 
00217   // free swap function
00218   template <typename ID, typename C, typename P>
00219   inline
00220   void
00221   swap(RangeMap<ID, C, P> & a, RangeMap<ID, C, P> & b) {
00222     a.swap(b);
00223   }
00224 
00225 }
00226 
00227 #endif

Generated on Tue Jun 9 17:29:47 2009 for CMSSW by  doxygen 1.5.4