multimap.hpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef MULTIMAP_HPP_
00013 #define MULTIMAP_HPP_
00014 
00015 #include <map>
00016 #include <list>
00017 
00018 template<typename KEY, typename VALUE, typename COMPARE>
00019 class MultiMap;
00020 
00021 template<class MAP_ITER, class LIST_ITER, class KEY, class VALUE, class COMPARE>
00022 class MultiMapIterator {
00023 protected:
00024   friend class MultiMap<KEY, VALUE, COMPARE>;
00025   typedef MultiMapIterator<MAP_ITER, LIST_ITER, KEY, VALUE, COMPARE> Self;
00026   LIST_ITER list_iter;
00027   MAP_ITER map_iter;
00028   bool list_valid;
00029 
00030 public:
00031   MultiMapIterator() : list_valid(false) {}
00032   template<class NONCONST>
00033   MultiMapIterator(NONCONST mi) : map_iter(mi), list_valid(false) {}
00034   MultiMapIterator(MAP_ITER mi, LIST_ITER li) : list_iter(li), map_iter(mi)
00035   {
00036     list_valid = (list_iter != map_iter->second.begin());
00037   }
00038 
00039   template<class NONCONST>
00040   Self &operator=(NONCONST mi)
00041   {
00042     map_iter = mi;
00043     list_valid = false;
00044   }
00045 
00046   VALUE &operator*() const
00047   {
00048     assert(!map_iter->second.empty());
00049     if (list_valid) {
00050       return list_iter.operator*();
00051     } else {
00052       return map_iter->second.begin().operator*();
00053     }
00054   }
00055 
00056   VALUE *operator->() const
00057   {
00058     assert(!map_iter->second.empty());
00059     if (list_valid) {
00060       return list_iter.operator->();
00061     } else {
00062       return map_iter->second.begin().operator->();
00063     }
00064   }
00065 
00066   FORCEINLINE const MAP_ITER &GetMapIter() const {return map_iter;}
00067   FORCEINLINE const LIST_ITER &GetListIter() const {return list_iter;}
00068   FORCEINLINE bool ListValid() const {return list_valid;}
00069 
00070   const KEY &GetKey() const {return map_iter->first;}
00071 
00072   Self &operator++()
00073   {
00074     assert(!map_iter->second.empty());
00075     if (list_valid) {
00076       if(++list_iter == map_iter->second.end()) {
00077         ++map_iter;
00078         list_valid = false;
00079       }
00080     } else {
00081       list_iter = ++(map_iter->second.begin());
00082       if (list_iter == map_iter->second.end()) {
00083         ++map_iter;
00084       } else {
00085         list_valid = true;
00086       }
00087     }
00088     return *this;
00089   }
00090 
00091   Self operator++(int)
00092   {
00093     Self tmp = *this;
00094     this->operator++();
00095     return tmp;
00096   }
00097 
00098   Self &operator--()
00099   {
00100     assert(!map_iter->second.empty());
00101     if (!list_valid) {
00102       --map_iter;
00103       list_iter = map_iter->second.end();
00104       assert(!map_iter->second.empty());
00105     }
00106 
00107     if(--list_iter == map_iter->second.begin()) {
00108       list_valid = false;
00109     } else {
00110       list_valid = true;
00111     }
00112 
00113     return *this;
00114   }
00115 
00116   Self operator--(int)
00117   {
00118     Self tmp = *this;
00119     this->operator--();
00120     return tmp;
00121   }
00122 };
00123 
00124 /* generic comparison functions for const/non-const multimap iterators and map iterators */
00125 
00126 template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class LIST_ITER2, class KEY, class VALUE1, class VALUE2, class COMPARE>
00127 bool operator==(const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE1, COMPARE> &iter1, const MultiMapIterator<MAP_ITER2, LIST_ITER2, KEY, VALUE2, COMPARE> &iter2)
00128 {
00129   if (iter1.ListValid()) {
00130     if (!iter2.ListValid()) {
00131       return false;
00132     } else if (iter1.GetListIter() != iter2.GetListIter()) {
00133       return false;
00134     }
00135   } else if (iter2.ListValid()) {
00136     return false;
00137   }
00138   return (iter1.GetMapIter() == iter2.GetMapIter());
00139 }
00140 
00141 template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class LIST_ITER2, class KEY, class VALUE1, class VALUE2, class COMPARE>
00142 bool operator!=(const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE1, COMPARE> &iter1, const MultiMapIterator<MAP_ITER2, LIST_ITER2, KEY, VALUE2, COMPARE> &iter2)
00143 {
00144   return !(iter1 == iter2);
00145 }
00146 
00147 template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class KEY, class VALUE, class COMPARE >
00148 bool operator==(const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE, COMPARE> &iter1, const MAP_ITER2 &iter2)
00149 {
00150   return !iter1.ListValid() && iter1.GetMapIter() == iter2;
00151 }
00152 
00153 template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class KEY, class VALUE, class COMPARE >
00154 bool operator!=(const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE, COMPARE> &iter1, const MAP_ITER2 &iter2)
00155 {
00156   return iter1.ListValid() || iter1.GetMapIter() != iter2;
00157 }
00158 
00159 template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class KEY, class VALUE, class COMPARE >
00160 bool operator==(const MAP_ITER2 &iter2, const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE, COMPARE> &iter1)
00161 {
00162   return !iter1.ListValid() && iter1.GetMapIter() == iter2;
00163 }
00164 
00165 template<class MAP_ITER1, class LIST_ITER1, class MAP_ITER2, class KEY, class VALUE, class COMPARE >
00166 bool operator!=(const MAP_ITER2 &iter2, const MultiMapIterator<MAP_ITER1, LIST_ITER1, KEY, VALUE, COMPARE> &iter1)
00167 {
00168   return iter1.ListValid() || iter1.GetMapIter() != iter2;
00169 }
00170 
00171 
00176 template<typename KEY, typename VALUE, typename COMPARE = std::less<KEY> >
00177 class MultiMap : public std::map<KEY, std::list<VALUE>, COMPARE > {
00178 public:
00179   typedef typename std::list<VALUE> List;
00180   typedef typename List::iterator ListIterator;
00181   typedef typename List::const_iterator ConstListIterator;
00182 
00183   typedef typename std::map<KEY, List, COMPARE > Map;
00184   typedef typename Map::iterator MapIterator;
00185   typedef typename Map::const_iterator ConstMapIterator;
00186 
00187   typedef MultiMapIterator<MapIterator, ListIterator, KEY, VALUE, COMPARE> iterator;
00188   typedef MultiMapIterator<ConstMapIterator, ConstListIterator, KEY, const VALUE, COMPARE> const_iterator;
00189 
00190   void erase(iterator it)
00191   {
00192     List &list = it.map_iter->second;
00193     assert(!list.empty());
00194     if (it.ListValid()) {
00195       list.erase(it.list_iter);
00196     } else {
00197       list.erase(list.begin());
00198     }
00199 
00200     if (list.empty()) {
00201       Map::erase(it.map_iter);
00202     }
00203   }
00204 
00205   void Insert(const KEY &key, const VALUE &val)
00206   {
00207     List &list = (*this)[key];
00208     list.push_back(val);
00209     assert(!list.empty());
00210   }
00211 
00212   size_t size() const
00213   {
00214     size_t ret = 0;
00215     for(ConstMapIterator it = Map::begin(); it != Map::end(); ++it) {
00216       ret += it->second.size();
00217     }
00218     return ret;
00219   }
00220 
00221   size_t MapSize() const
00222   {
00223     return Map::size();
00224   }
00225 
00226   std::pair<iterator, iterator> equal_range(const KEY &key)
00227   {
00228     MapIterator begin(lower_bound(key));
00229     if (begin != Map::end() && begin->first == key) {
00230       MapIterator end = begin;
00231       return std::make_pair(begin, ++end);
00232     } else {
00233       return std::make_pair(begin, begin);
00234     }
00235   }
00236 
00237   std::pair<const_iterator, const_iterator> equal_range(const KEY &key) const
00238   {
00239     ConstMapIterator begin(lower_bound(key));
00240     if (begin != Map::end() && begin->first == key) {
00241       ConstMapIterator end = begin;
00242       return std::make_pair(begin, ++end);
00243     } else {
00244       return std::make_pair(begin, begin);
00245     }
00246   }
00247 };
00248 
00249 #endif /* MULTIMAP_HPP_ */