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 
00313   void erase(iterator it)
00314   {
00315     List &list = it.map_iter->second;
00316     assert(!list.empty());
00317     if (it.ListValid()) {
00318       list.erase(it.list_iter);
00319     } else {
00320       list.erase(list.begin());
00321     }
00322 
00323     if (list.empty()) this->Map::erase(it.map_iter);
00324   }
00325 
00331   void Insert(const Tkey &key, const Tvalue &val)
00332   {
00333     List &list = (*this)[key];
00334     list.push_back(val);
00335     assert(!list.empty());
00336   }
00337 
00342   size_t size() const
00343   {
00344     size_t ret = 0;
00345     for (ConstMapIterator it = this->Map::begin(); it != this->Map::end(); ++it) {
00346       ret += it->second.size();
00347     }
00348     return ret;
00349   }
00350 
00355   size_t MapSize() const
00356   {
00357     return this->Map::size();
00358   }
00359 
00365   std::pair<iterator, iterator> equal_range(const Tkey &key)
00366   {
00367     MapIterator begin(lower_bound(key));
00368     if (begin != this->Map::end() && begin->first == key) {
00369       MapIterator end = begin;
00370       return std::make_pair(begin, ++end);
00371     } else {
00372       return std::make_pair(begin, begin);
00373     }
00374   }
00375 
00381   std::pair<const_iterator, const_iterator> equal_range(const Tkey &key) const
00382   {
00383     ConstMapIterator begin(lower_bound(key));
00384     if (begin != this->Map::end() && begin->first == key) {
00385       ConstMapIterator end = begin;
00386       return std::make_pair(begin, ++end);
00387     } else {
00388       return std::make_pair(begin, begin);
00389     }
00390   }
00391 };
00392 
00393 #endif /* MULTIMAP_HPP_ */

Generated on Sun Jun 5 04:19:55 2011 for OpenTTD by  doxygen 1.6.1