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
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
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
00162 C tmp;
00163 for (typename mapType::iterator it = map_.begin(), itEnd = map_.end(); it != itEnd; it ++) {
00164 range r = get((*it).first);
00165
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
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
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