OpenTTD Source 20260206-master-g4d4e37dbf1
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#ifndef MULTIMAP_HPP
11#define MULTIMAP_HPP
12
13template <typename Tkey, typename Tvalue, typename Tcompare>
14class MultiMap;
15
24template <class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcompare>
26protected:
27 friend class MultiMap<Tkey, Tvalue, Tcompare>;
29
30 Tlist_iter list_iter;
31 Tmap_iter map_iter;
32
43
44public:
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
146 Self operator++(int)
147 {
148 Self tmp = *this;
149 this->operator++();
150 return tmp;
151 }
152
159 {
160 assert(!this->map_iter->second.empty());
161 if (!this->list_valid) {
162 --this->map_iter;
163 this->list_iter = this->map_iter->second.end();
164 assert(!this->map_iter->second.empty());
165 }
166
167 this->list_valid = (--this->list_iter != this->map_iter->second.begin());
168 return *this;
169 }
170
176 Self operator--(int)
177 {
178 Self tmp = *this;
179 this->operator--();
180 return tmp;
181 }
182
192 template <class Tmap_iter_other, class Tlist_iter_other, class Tvalue_other>
194 {
195 if (this->GetMapIter() != other.GetMapIter()) return false;
196 if (!this->ListValid()) return !other.ListValid();
197 return other.ListValid() ?
198 this->GetListIter() == other.GetListIter() : false;
199 }
200
208 template <class Titer>
209 bool operator==(const Titer &iter) const
210 {
211 return !this->ListValid() && this->GetMapIter() == iter;
212 }
213};
214
222template <typename Tkey, typename Tvalue, typename Tcompare = std::less<Tkey> >
223class MultiMap : public std::map<Tkey, std::list<Tvalue>, Tcompare > {
224public:
225 typedef typename std::list<Tvalue> List;
226 typedef typename List::iterator ListIterator;
227 typedef typename List::const_iterator ConstListIterator;
228
229 typedef typename std::map<Tkey, List, Tcompare > Map;
230 typedef typename Map::iterator MapIterator;
231 typedef typename Map::const_iterator ConstMapIterator;
232
235
241 iterator erase(iterator it)
242 {
243 List &list = it.map_iter->second;
244 assert(!list.empty());
245 if (it.list_valid) {
246 it.list_iter = list.erase(it.list_iter);
247 /* This can't be the first list element as otherwise list_valid would have
248 * to be false. So the list cannot be empty here. */
249 if (it.list_iter == list.end()) {
250 ++it.map_iter;
251 it.list_valid = false;
252 }
253 } else {
254 list.erase(list.begin());
255 if (list.empty()) this->Map::erase(it.map_iter++);
256 }
257 return it;
258 }
259
265 void Insert(const Tkey &key, const Tvalue &val)
266 {
267 List &list = (*this)[key];
268 list.push_back(val);
269 assert(!list.empty());
270 }
271
276 size_t size() const
277 {
278 size_t ret = 0;
279 for (ConstMapIterator it = this->Map::begin(); it != this->Map::end(); ++it) {
280 ret += it->second.size();
281 }
282 return ret;
283 }
284
289 size_t MapSize() const
290 {
291 return this->Map::size();
292 }
293
299 std::pair<iterator, iterator> equal_range(const Tkey &key)
300 {
301 MapIterator begin(this->lower_bound(key));
302 if (begin != this->Map::end() && begin->first == key) {
303 MapIterator end = begin;
304 return std::make_pair(begin, ++end);
305 }
306 return std::make_pair(begin, begin);
307 }
308
314 std::pair<const_iterator, const_iterator> equal_range(const Tkey &key) const
315 {
316 ConstMapIterator begin(this->lower_bound(key));
317 if (begin != this->Map::end() && begin->first == key) {
318 ConstMapIterator end = begin;
319 return std::make_pair(begin, ++end);
320 }
321 return std::make_pair(begin, begin);
322 }
323};
324
325#endif /* MULTIMAP_HPP */
STL-style iterator for MultiMap.
Definition multimap.hpp:25
Self & operator++()
Prefix increment operator.
Definition multimap.hpp:122
MultiMapIterator(Tnon_const mi)
Constructor to allow possibly const iterators to be assigned from possibly non-const map iterators.
Definition multimap.hpp:57
MultiMapIterator()
Simple, dangerous constructor to allow later assignment with operator=.
Definition multimap.hpp:48
Self & operator=(Tnon_const mi)
Assignment iterator like constructor with the same signature.
Definition multimap.hpp:78
MultiMapIterator(Tmap_iter mi, Tlist_iter li)
Constructor to allow specifying an exact position in map and list.
Definition multimap.hpp:66
bool operator==(const MultiMapIterator< Tmap_iter_other, Tlist_iter_other, Tkey, Tvalue_other, Tcompare > &other) const
Compare two MultiMap iterators.
Definition multimap.hpp:193
bool operator==(const Titer &iter) const
Check if a MultiMap iterator is at the begin of a list pointed to by the given map iterator.
Definition multimap.hpp:209
Self & operator--()
Prefix decrement operator.
Definition multimap.hpp:158
Tvalue * operator->() const
Same as operator*(), but returns a pointer.
Definition multimap.hpp:102
Self operator++(int)
Postfix increment operator.
Definition multimap.hpp:146
Tvalue & operator*() const
Dereference operator.
Definition multimap.hpp:90
Self operator--(int)
Postfix decrement operator.
Definition multimap.hpp:176
Hand-rolled multimap as map of lists.
Definition multimap.hpp:223
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:314
size_t MapSize() const
Count the number of ranges with equal keys in this MultiMap.
Definition multimap.hpp:289
size_t size() const
Count all items in this MultiMap.
Definition multimap.hpp:276
iterator erase(iterator it)
Erase the value pointed to by an iterator.
Definition multimap.hpp:241
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:299
void Insert(const Tkey &key, const Tvalue &val)
Insert a value at the end of the range with the specified key.
Definition multimap.hpp:265
static uint size
The number of tiles on the map.
Definition map_func.h:229