CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/DataFormats/Common/interface/MapOfVectors.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_MapOfVectors_h
00002 #define DataFormats_Common_MapOfVectors_h
00003 
00004 #include <vector>
00005 #include <map>
00006 
00007 #include <boost/range/iterator_range.hpp>
00008 #include <boost/iterator/iterator_facade.hpp>
00009 
00010 namespace edm {
00011 
00012   /* a linearized read-only map-of vectors
00013 
00014    */
00015   template<typename K, typename T>
00016   class MapOfVectors {
00017   public:
00018 
00019     typedef MapOfVectors<K,T> self;
00020     typedef std::map<K,std::vector<T> > TheMap;
00021 
00022     typedef unsigned int size_type;
00023 
00024     typedef std::vector<K> Keys;
00025     typedef std::vector<size_type> Offsets;
00026     typedef std::vector<T> Data;
00027 
00028     typedef typename Keys::const_iterator key_iterator;
00029     typedef Offsets::const_iterator offset_iterator;
00030     typedef typename Data::const_iterator data_iterator;
00031    
00032     typedef boost::iterator_range<data_iterator> range;
00033 
00034     typedef std::pair<K , range> Pair;
00035 
00036     class Iter
00037       : public boost::iterator_facade<Iter,
00038                                       Pair const, 
00039                                       boost::forward_traversal_tag >
00040     {
00041       
00042     public:
00043       typedef Iter self;
00044       Iter() {}
00045       
00046       explicit Iter(key_iterator k, offset_iterator o, std::vector<T> const & d )
00047         : key(k), 
00048           off(o),
00049           data(d.begin())
00050       {}
00051       
00052     private:
00053       friend class boost::iterator_core_access;
00054       
00055       void increment() {
00056         ++key; ++off; 
00057       }
00058       
00059       bool equal(self const& other) const {
00060         return this->key == other.key;
00061       }
00062       
00063       Pair const & dereference() const {
00064         // FIXME can be optimized...
00065         cache.first = *key;
00066         cache.second = range(data+(*off),data+(*(off+1)));
00067         return cache;
00068       }
00069           
00070           
00071       key_iterator key;
00072       offset_iterator off;
00073       data_iterator data;
00074       mutable Pair cache;
00075       };
00076 
00077     typedef Iter const_iterator;
00078 
00079 
00080     range emptyRange() const { return range(m_data.end(),m_data.end());}
00081 
00082     MapOfVectors() :  m_offsets(1,0) {}
00083 
00084     MapOfVectors(TheMap const & it) {
00085       m_keys.reserve(it.size());
00086       m_offsets.reserve(it.size()+1);
00087       m_offsets.push_back(0);
00088       size_type tot=0;
00089       for(typename TheMap::const_iterator p=it.begin(); p!=it.end();++p)
00090         tot += (*p).second.size();
00091       m_data.reserve(tot);
00092       for(typename TheMap::const_iterator p=it.begin(); p!=it.end();++p)
00093         loadNext((*p).first,(*p).second);
00094 
00095     }
00096     
00097     void loadNext(K const & k, std::vector<T> const & v) {
00098       m_keys.push_back(k);
00099       m_data.resize(m_offsets.back()+v.size());
00100       std::copy(v.begin(),v.end(),m_data.begin()+m_offsets.back());
00101       m_offsets.push_back(m_data.size());
00102     }
00103 
00104     size_type size() const { return m_keys.size();}
00105 
00106     bool empty() const { return m_keys.empty();}
00107 
00108     key_iterator findKey(K const & k) const {
00109       std::pair<key_iterator,key_iterator> p =
00110         std::equal_range(m_keys.begin(), m_keys.end(), k);
00111       return (p.first!=p.second) ? p.first : m_keys.end();
00112     }
00113     
00114     size_type offset(K const & k) const {
00115       key_iterator p = findKey(k);
00116       if (p==m_keys.end()) return m_data.size();
00117       return m_offsets[p-m_keys.begin()];
00118     }
00119 
00120     range find(K const & k) const  {
00121       key_iterator p = findKey(k);
00122       if (p==m_keys.end()) return emptyRange();
00123       size_type loc = p-m_keys.begin();
00124       data_iterator b = m_data.begin()+m_offsets[loc];
00125       data_iterator e = m_data.begin()+m_offsets[loc+1];
00126       return range(b,e);
00127     }
00128     
00129     const_iterator begin() const {
00130       return const_iterator(m_keys.begin(),m_offsets.begin(),m_data);
00131     }
00132 
00133     const_iterator end() const {
00134       return const_iterator(m_keys.end(),m_offsets.begin()+m_keys.size(),m_data);
00135     }
00136 
00137     void swap(MapOfVectors& other) {
00138       m_keys.swap(other.m_keys);
00139       m_offsets.swap(other.m_offsets);
00140       m_data.swap(other.m_data);
00141     }
00142 
00143     MapOfVectors& operator=(MapOfVectors const& rhs) {
00144       MapOfVectors temp(rhs);
00145       this->swap(temp);
00146       return *this;
00147     }
00148 
00149   private:
00150     std::vector<K> m_keys;
00151     std::vector<size_type> m_offsets;
00152     std::vector<T> m_data;
00153 
00154   };
00155 
00156   // Free swap function
00157   template <typename K, typename T>
00158   inline
00159   void
00160   swap(MapOfVectors<K, T>& lhs, MapOfVectors<K, T>& rhs) {
00161     lhs.swap(rhs);
00162   }
00163 
00164 }
00165 
00166 #endif // DatFormats_Common_MapOfVectors_h