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     return this->list_valid ?
00099         this->list_iter.operator*() :
00100         this->map_iter->second.begin().operator*();
00101   }
00102 
00107   Tvalue *operator->() const
00108   {
00109     assert(!this->map_iter->second.empty());
00110     return this->list_valid ?
00111         this->list_iter.operator->() :
00112         this->map_iter->second.begin().operator->();
00113   }
00114 
00115   inline const Tmap_iter &GetMapIter() const { return this->map_iter; }
00116   inline const Tlist_iter &GetListIter() const { return this->list_iter; }
00117   inline bool ListValid() const { return this->list_valid; }
00118 
00119   const Tkey &GetKey() const { return this->map_iter->first; }
00120 
00127   Self &operator++()
00128   {
00129     assert(!this->map_iter->second.empty());
00130     if (this->list_valid) {
00131       if (++this->list_iter == this->map_iter->second.end()) {
00132         ++this->map_iter;
00133         this->list_valid = false;
00134       }
00135     } else {
00136       this->list_iter = ++(this->map_iter->second.begin());
00137       if (this->list_iter == this->map_iter->second.end()) {
00138         ++this->map_iter;
00139       } else {
00140         this->list_valid = true;
00141       }
00142     }
00143     return *this;
00144   }
00145 
00152   Self operator++(int)
00153   {
00154     Self tmp = *this;
00155     this->operator++();
00156     return tmp;
00157   }
00158 
00164   Self &operator--()
00165   {
00166     assert(!this->map_iter->second.empty());
00167     if (!this->list_valid) {
00168       --this->map_iter;
00169       this->list_iter = this->map_iter->second.end();
00170       assert(!this->map_iter->second.empty());
00171     }
00172 
00173     this->list_valid = (--this->list_iter != this->map_iter->second.begin());
00174     return *this;
00175   }
00176 
00183   Self operator--(int)
00184   {
00185     Self tmp = *this;
00186     this->operator--();
00187     return tmp;
00188   }
00189 };
00190 
00191 /* Generic comparison functions for const/non-const MultiMap iterators and map iterators */
00192 
00204 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
00205 bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
00206 {
00207   if (iter1.GetMapIter() != iter2.GetMapIter()) return false;
00208   if (!iter1.ListValid()) return !iter2.ListValid();
00209   return iter2.ListValid() ?
00210       iter1.GetListIter() == iter2.GetListIter() : false;
00211 }
00212 
00221 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
00222 bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
00223 {
00224   return !(iter1 == iter2);
00225 }
00226 
00235 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
00236 bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
00237 {
00238   return !iter1.ListValid() && iter1.GetMapIter() == iter2;
00239 }
00240 
00247 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
00248 bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
00249 {
00250   return iter1.ListValid() || iter1.GetMapIter() != iter2;
00251 }
00252 
00259 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
00260 bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
00261 {
00262   return !iter1.ListValid() && iter1.GetMapIter() == iter2;
00263 }
00264 
00271 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
00272 bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
00273 {
00274   return iter1.ListValid() || iter1.GetMapIter() != iter2;
00275 }
00276 
00277 
00285 template<typename Tkey, typename Tvalue, typename Tcompare = std::less<Tkey> >
00286 class MultiMap : public std::map<Tkey, std::list<Tvalue>, Tcompare > {
00287 public:
00288   typedef typename std::list<Tvalue> List;
00289   typedef typename List::iterator ListIterator;
00290   typedef typename List::const_iterator ConstListIterator;
00291 
00292   typedef typename std::map<Tkey, List, Tcompare > Map;
00293   typedef typename Map::iterator MapIterator;
00294   typedef typename Map::const_iterator ConstMapIterator;
00295 
00296   typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcompare> iterator;
00297   typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcompare> const_iterator;
00298 
00304   iterator erase(iterator it)
00305   {
00306     List &list = it.map_iter->second;
00307     assert(!list.empty());
00308     if (it.list_valid) {
00309       it.list_iter = list.erase(it.list_iter);
00310       /* This can't be the first list element as otherwise list_valid would have
00311        * to be false. So the list cannot be empty here. */
00312       if (it.list_iter == list.end()) {
00313         ++it.map_iter;
00314         it.list_valid = false;
00315       }
00316     } else {
00317       list.erase(list.begin());
00318       if (list.empty()) this->Map::erase(it.map_iter++);
00319     }
00320     return it;
00321   }
00322 
00328   void Insert(const Tkey &key, const Tvalue &val)
00329   {
00330     List &list = (*this)[key];
00331     list.push_back(val);
00332     assert(!list.empty());
00333   }
00334 
00339   size_t size() const
00340   {
00341     size_t ret = 0;
00342     for (ConstMapIterator it = this->Map::begin(); it != this->Map::end(); ++it) {
00343       ret += it->second.size();
00344     }
00345     return ret;
00346   }
00347 
00352   size_t MapSize() const
00353   {
00354     return this->Map::size();
00355   }
00356 
00362   std::pair<iterator, iterator> equal_range(const Tkey &key)
00363   {
00364     MapIterator begin(this->lower_bound(key));
00365     if (begin != this->Map::end() && begin->first == key) {
00366       MapIterator end = begin;
00367       return std::make_pair(begin, ++end);
00368     }
00369     return std::make_pair(begin, begin);
00370   }
00371 
00377   std::pair<const_iterator, const_iterator> equal_range(const Tkey &key) const
00378   {
00379     ConstMapIterator begin(this->lower_bound(key));
00380     if (begin != this->Map::end() && begin->first == key) {
00381       ConstMapIterator end = begin;
00382       return std::make_pair(begin, ++end);
00383     }
00384     return std::make_pair(begin, begin);
00385   }
00386 };
00387 
00388 #endif /* MULTIMAP_HPP */