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 Tkey, typename Tvalue, typename Tcompare>
00019 class MultiMap;
00020 
00029 template<class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcompare>
00030 class MultiMapIterator {
00031 protected:
00032   friend class MultiMap<Tkey, Tvalue, Tcompare>;
00033   typedef MultiMapIterator<Tmap_iter, Tlist_iter, Tkey, Tvalue, Tcompare> Self;
00034 
00035   Tlist_iter list_iter; 
00036   Tmap_iter map_iter;   
00037 
00047   bool list_valid;
00048 
00049 public:
00053   MultiMapIterator() : list_valid(false) {}
00054 
00061   template<class Tnon_const>
00062   MultiMapIterator(Tnon_const mi) : map_iter(mi), list_valid(false) {}
00063 
00071   MultiMapIterator(Tmap_iter mi, Tlist_iter li) : list_iter(li), map_iter(mi)
00072   {
00073     this->list_valid = (this->list_iter != this->map_iter->second.begin());
00074   }
00075 
00082   template<class Tnon_const>
00083   Self &operator=(Tnon_const mi)
00084   {
00085     this->map_iter = mi;
00086     this->list_valid = false;
00087     return *this;
00088   }
00089 
00095   Tvalue &operator*() const
00096   {
00097     assert(!this->map_iter->second.empty());
00098     if (this->list_valid) {
00099       return this->list_iter.operator*();
00100     } else {
00101       return this->map_iter->second.begin().operator*();
00102     }
00103   }
00104 
00109   Tvalue *operator->() const
00110   {
00111     assert(!this->map_iter->second.empty());
00112     if (this->list_valid) {
00113       return this->list_iter.operator->();
00114     } else {
00115       return this->map_iter->second.begin().operator->();
00116     }
00117   }
00118 
00119   inline const Tmap_iter &GetMapIter() const {return this->map_iter;}
00120   inline const Tlist_iter &GetListIter() const {return this->list_iter;}
00121   inline bool ListValid() const {return this->list_valid;}
00122 
00123   const Tkey &GetKey() const {return this->map_iter->first;}
00124 
00131   Self &operator++()
00132   {
00133     assert(!this->map_iter->second.empty());
00134     if (this->list_valid) {
00135       if(++this->list_iter == this->map_iter->second.end()) {
00136         ++this->map_iter;
00137         this->list_valid = false;
00138       }
00139     } else {
00140       this->list_iter = ++(this->map_iter->second.begin());
00141       if (this->list_iter == this->map_iter->second.end()) {
00142         ++this->map_iter;
00143       } else {
00144         this->list_valid = true;
00145       }
00146     }
00147     return *this;
00148   }
00149 
00156   Self operator++(int)
00157   {
00158     Self tmp = *this;
00159     this->operator++();
00160     return tmp;
00161   }
00162 
00168   Self &operator--()
00169   {
00170     assert(!this->map_iter->second.empty());
00171     if (!this->list_valid) {
00172       --this->map_iter;
00173       this->list_iter = this->map_iter->second.end();
00174       assert(!this->map_iter->second.empty());
00175     }
00176 
00177     this->list_valid = (--this->list_iter != this->map_iter->second.begin());
00178     return *this;
00179   }
00180 
00187   Self operator--(int)
00188   {
00189     Self tmp = *this;
00190     this->operator--();
00191     return tmp;
00192   }
00193 };
00194 
00195 /* generic comparison functions for const/non-const MultiMap iterators and map iterators */
00196 
00208 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
00209 bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
00210 {
00211   if (iter1.GetMapIter() != iter2.GetMapIter()) return false;
00212   if (iter1.ListValid()) {
00213     if (!iter2.ListValid()) {
00214       return false;
00215     } else {
00216       return iter1.GetListIter() == iter2.GetListIter();
00217     }
00218   } else {
00219     return !iter2.ListValid();
00220   }
00221 }
00222 
00231 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
00232 bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
00233 {
00234   return !(iter1 == iter2);
00235 }
00236 
00245 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
00246 bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
00247 {
00248   return !iter1.ListValid() && iter1.GetMapIter() == iter2;
00249 }
00250 
00257 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
00258 bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
00259 {
00260   return iter1.ListValid() || iter1.GetMapIter() != iter2;
00261 }
00262 
00269 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
00270 bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
00271 {
00272   return !iter1.ListValid() && iter1.GetMapIter() == iter2;
00273 }
00274 
00281 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
00282 bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
00283 {
00284   return iter1.ListValid() || iter1.GetMapIter() != iter2;
00285 }
00286 
00287 
00295 template<typename Tkey, typename Tvalue, typename Tcompare = std::less<Tkey> >
00296 class MultiMap : public std::map<Tkey, std::list<Tvalue>, Tcompare > {
00297 public:
00298   typedef typename std::list<Tvalue> List;
00299   typedef typename List::iterator ListIterator;
00300   typedef typename List::const_iterator ConstListIterator;
00301 
00302   typedef typename std::map<Tkey, List, Tcompare > Map;
00303   typedef typename Map::iterator MapIterator;
00304   typedef typename Map::const_iterator ConstMapIterator;
00305 
00306   typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcompare> iterator;
00307   typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcompare> const_iterator;
00308 
00314   iterator erase(iterator it)
00315   {
00316     List &list = it.map_iter->second;
00317     assert(!list.empty());
00318     if (it.list_valid) {
00319       it.list_iter = list.erase(it.list_iter);
00320       /* This can't be the first list element as otherwise list_valid would have
00321        * to be false. So the list cannot be empty here.
00322        */
00323       if (it.list_iter == list.end()) {
00324         ++it.map_iter;
00325         it.list_valid = false;
00326       }
00327     } else {
00328       list.erase(list.begin());
00329       if (list.empty()) this->Map::erase(it.map_iter++);
00330     }
00331     return it;
00332   }
00333 
00339   void Insert(const Tkey &key, const Tvalue &val)
00340   {
00341     List &list = (*this)[key];
00342     list.push_back(val);
00343     assert(!list.empty());
00344   }
00345 
00350   size_t size() const
00351   {
00352     size_t ret = 0;
00353     for (ConstMapIterator it = this->Map::begin(); it != this->Map::end(); ++it) {
00354       ret += it->second.size();
00355     }
00356     return ret;
00357   }
00358 
00363   size_t MapSize() const
00364   {
00365     return this->Map::size();
00366   }
00367 
00373   std::pair<iterator, iterator> equal_range(const Tkey &key)
00374   {
00375     MapIterator begin(this->lower_bound(key));
00376     if (begin != this->Map::end() && begin->first == key) {
00377       MapIterator end = begin;
00378       return std::make_pair(begin, ++end);
00379     } else {
00380       return std::make_pair(begin, begin);
00381     }
00382   }
00383 
00389   std::pair<const_iterator, const_iterator> equal_range(const Tkey &key) const
00390   {
00391     ConstMapIterator begin(this->lower_bound(key));
00392     if (begin != this->Map::end() && begin->first == key) {
00393       ConstMapIterator end = begin;
00394       return std::make_pair(begin, ++end);
00395     } else {
00396       return std::make_pair(begin, begin);
00397     }
00398   }
00399 };
00400 
00401 #endif /* MULTIMAP_HPP_ */