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