# 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 */