OpenTTD Source: src/core/multimap.hpp Source File

OpenTTD Source 14.0-beta3

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>
25 class MultiMapIterator {
26 protected:
27 friend class MultiMap<Tkey, Tvalue, Tcompare>;
28 typedef MultiMapIterator<Tmap_iter, Tlist_iter, Tkey, Tvalue, Tcompare> Self;
29
30 Tlist_iter list_iter;
31 Tmap_iter map_iter;
32
42 bool list_valid;
43
44 public:
48 MultiMapIterator() : list_valid(false) {}
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
122 Self &operator++()
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
147 Self operator++(int)
148 {
149 Self tmp = *this;
150 this->operator++();
151 return tmp;
152 }
153
159 Self &operator--()
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
178 Self operator--(int)
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>
200 bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
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>
217 bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
218 {
219 return !(iter1 == iter2);
220 }
221
230 template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
231 bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
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 >
243 bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
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 >
255 bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
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 >
267 bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
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
291 typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcompare> iterator;
292 typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcompare> const_iterator;
293
299 iterator erase(iterator it)
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