00001 #ifndef DataFormats_Common_RangeMap_h
00002 #define DataFormats_Common_RangeMap_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
00160 C tmp;
00161 for (typename mapType::iterator it = map_.begin(), itEnd = map_.end(); it != itEnd; it ++) {
00162 range r = get((*it).first);
00163
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
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
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