OpenTTD Source  20240919-master-gdf0233f4c2
multimap.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * 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.
4  * 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.
5  * 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/>.
6  */
7 
10 #ifndef MULTIMAP_HPP
11 #define MULTIMAP_HPP
12 
13 template<typename Tkey, typename Tvalue, typename Tcompare>
14 class MultiMap;
15 
24 template<class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcompare>
26 protected:
27  friend class MultiMap<Tkey, Tvalue, Tcompare>;
29 
30  Tlist_iter list_iter;
31  Tmap_iter map_iter;
32 
42  bool list_valid;
43 
44 public:
49 
56  template<class Tnon_const>
57  MultiMapIterator(Tnon_const mi) : map_iter(mi), list_valid(false) {}
58 
66  MultiMapIterator(Tmap_iter mi, Tlist_iter li) : list_iter(li), map_iter(mi)
67  {
68  this->list_valid = (this->list_iter != this->map_iter->second.begin());
69  }
70 
77  template<class Tnon_const>
78  Self &operator=(Tnon_const mi)
79  {
80  this->map_iter = mi;
81  this->list_valid = false;
82  return *this;
83  }
84 
90  Tvalue &operator*() const
91  {
92  assert(!this->map_iter->second.empty());
93  return this->list_valid ?
94  this->list_iter.operator*() :
95  this->map_iter->second.begin().operator*();
96  }
97 
102  Tvalue *operator->() const
103  {
104  assert(!this->map_iter->second.empty());
105  return this->list_valid ?
106  this->list_iter.operator->() :
107  this->map_iter->second.begin().operator->();
108  }
109 
110  inline const Tmap_iter &GetMapIter() const { return this->map_iter; }
111  inline const Tlist_iter &GetListIter() const { return this->list_iter; }
112  inline bool ListValid() const { return this->list_valid; }
113 
114  const Tkey &GetKey() const { return this->map_iter->first; }
115 
123  {
124  assert(!this->map_iter->second.empty());
125  if (this->list_valid) {
126  if (++this->list_iter == this->map_iter->second.end()) {
127  ++this->map_iter;
128  this->list_valid = false;
129  }
130  } else {
131  this->list_iter = ++(this->map_iter->second.begin());
132  if (this->list_iter == this->map_iter->second.end()) {
133  ++this->map_iter;
134  } else {
135  this->list_valid = true;
136  }
137  }
138  return *this;
139  }
140 
148  {
149  Self tmp = *this;
150  this->operator++();
151  return tmp;
152  }
153 
160  {
161  assert(!this->map_iter->second.empty());
162  if (!this->list_valid) {
163  --this->map_iter;
164  this->list_iter = this->map_iter->second.end();
165  assert(!this->map_iter->second.empty());
166  }
167 
168  this->list_valid = (--this->list_iter != this->map_iter->second.begin());
169  return *this;
170  }
171 
179  {
180  Self tmp = *this;
181  this->operator--();
182  return tmp;
183  }
184 };
185 
186 /* Generic comparison functions for const/non-const MultiMap iterators and map iterators */
187 
199 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
201 {
202  if (iter1.GetMapIter() != iter2.GetMapIter()) return false;
203  if (!iter1.ListValid()) return !iter2.ListValid();
204  return iter2.ListValid() ?
205  iter1.GetListIter() == iter2.GetListIter() : false;
206 }
207 
216 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
218 {
219  return !(iter1 == iter2);
220 }
221 
230 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
232 {
233  return !iter1.ListValid() && iter1.GetMapIter() == iter2;
234 }
235 
242 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
244 {
245  return iter1.ListValid() || iter1.GetMapIter() != iter2;
246 }
247 
254 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
256 {
257  return !iter1.ListValid() && iter1.GetMapIter() == iter2;
258 }
259 
266 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
268 {
269  return iter1.ListValid() || iter1.GetMapIter() != iter2;
270 }
271 
272 
280 template<typename Tkey, typename Tvalue, typename Tcompare = std::less<Tkey> >
281 class MultiMap : public std::map<Tkey, std::list<Tvalue>, Tcompare > {
282 public:
283  typedef typename std::list<Tvalue> List;
284  typedef typename List::iterator ListIterator;
285  typedef typename List::const_iterator ConstListIterator;
286 
287  typedef typename std::map<Tkey, List, Tcompare > Map;
288  typedef typename Map::iterator MapIterator;
289  typedef typename Map::const_iterator ConstMapIterator;
290 
293 
300  {
301  List &list = it.map_iter->second;
302  assert(!list.empty());
303  if (it.list_valid) {
304  it.list_iter = list.erase(it.list_iter);
305  /* This can't be the first list element as otherwise list_valid would have
306  * to be false. So the list cannot be empty here. */
307  if (it.list_iter == list.end()) {
308  ++it.map_iter;
309  it.list_valid = false;
310  }
311  } else {
312  list.erase(list.begin());
313  if (list.empty()) this->Map::erase(it.map_iter++);
314  }
315  return it;
316  }
317 
323  void Insert(const Tkey &key, const Tvalue &val)
324  {
325  List &list = (*this)[key];
326  list.push_back(val);
327  assert(!list.empty());
328  }
329 
334  size_t size() const
335  {
336  size_t ret = 0;
337  for (ConstMapIterator it = this->Map::begin(); it != this->Map::end(); ++it) {
338  ret += it->second.size();
339  }
340  return ret;
341  }
342 
347  size_t MapSize() const
348  {
349  return this->Map::size();
350  }
351 
357  std::pair<iterator, iterator> equal_range(const Tkey &key)
358  {
359  MapIterator begin(this->lower_bound(key));
360  if (begin != this->Map::end() && begin->first == key) {
361  MapIterator end = begin;
362  return std::make_pair(begin, ++end);
363  }
364  return std::make_pair(begin, begin);
365  }
366 
372  std::pair<const_iterator, const_iterator> equal_range(const Tkey &key) const
373  {
374  ConstMapIterator begin(this->lower_bound(key));
375  if (begin != this->Map::end() && begin->first == key) {
376  ConstMapIterator end = begin;
377  return std::make_pair(begin, ++end);
378  }
379  return std::make_pair(begin, begin);
380  }
381 };
382 
383 #endif /* MULTIMAP_HPP */
MultiMap::size
size_t size() const
Count all items in this MultiMap.
Definition: multimap.hpp:334
Map
Size related data of the map.
Definition: map_func.h:206
MultiMapIterator::operator->
Tvalue * operator->() const
Same as operator*(), but returns a pointer.
Definition: multimap.hpp:102
MultiMapIterator::map_iter
Tmap_iter map_iter
Iterator pointing to the position of the current list of items with equal keys in the map.
Definition: multimap.hpp:31
MultiMapIterator::operator--
Self operator--(int)
Postfix decrement operator.
Definition: multimap.hpp:178
MultiMapIterator::list_iter
Tlist_iter list_iter
Iterator pointing to current position in the current list of items with equal keys.
Definition: multimap.hpp:30
MultiMapIterator::operator++
Self & operator++()
Prefix increment operator.
Definition: multimap.hpp:122
MultiMap::erase
iterator erase(iterator it)
Erase the value pointed to by an iterator.
Definition: multimap.hpp:299
MultiMapIterator::operator*
Tvalue & operator*() const
Dereference operator.
Definition: multimap.hpp:90
MultiMap::MapSize
size_t MapSize() const
Count the number of ranges with equal keys in this MultiMap.
Definition: multimap.hpp:347
MultiMapIterator::operator++
Self operator++(int)
Postfix increment operator.
Definition: multimap.hpp:147
operator==
bool operator==(const MultiMapIterator< Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare > &iter1, const MultiMapIterator< Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare > &iter2)
Compare two MultiMap iterators.
Definition: multimap.hpp:200
MultiMap::equal_range
std::pair< const_iterator, const_iterator > equal_range(const Tkey &key) const
Get a pair of constant iterators specifying a range of items with equal keys.
Definition: multimap.hpp:372
MultiMapIterator::MultiMapIterator
MultiMapIterator()
Simple, dangerous constructor to allow later assignment with operator=.
Definition: multimap.hpp:48
MultiMap::equal_range
std::pair< iterator, iterator > equal_range(const Tkey &key)
Get a pair of iterators specifying a range of items with equal keys.
Definition: multimap.hpp:357
MultiMapIterator
STL-style iterator for MultiMap.
Definition: multimap.hpp:25
MultiMapIterator::operator--
Self & operator--()
Prefix decrement operator.
Definition: multimap.hpp:159
MultiMapIterator::operator=
Self & operator=(Tnon_const mi)
Assignment iterator like constructor with the same signature.
Definition: multimap.hpp:78
MultiMapIterator::MultiMapIterator
MultiMapIterator(Tnon_const mi)
Constructor to allow possibly const iterators to be assigned from possibly non-const map iterators.
Definition: multimap.hpp:57
operator!=
bool operator!=(const MultiMapIterator< Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare > &iter1, const MultiMapIterator< Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare > &iter2)
Inverse of operator==().
Definition: multimap.hpp:217
MultiMapIterator::MultiMapIterator
MultiMapIterator(Tmap_iter mi, Tlist_iter li)
Constructor to allow specifying an exact position in map and list.
Definition: multimap.hpp:66
MultiMap
Hand-rolled multimap as map of lists.
Definition: multimap.hpp:14
MultiMap::Insert
void Insert(const Tkey &key, const Tvalue &val)
Insert a value at the end of the range with the specified key.
Definition: multimap.hpp:323
Map::size
static uint size
The number of tiles on the map.
Definition: map_func.h:240
MultiMapIterator::list_valid
bool list_valid
Flag to show that the iterator has just "walked" a step in the map.
Definition: multimap.hpp:42