Libosmium  2.20.0
Fast and flexible C++ library for working with OpenStreetMap data
relations_map.hpp
Go to the documentation of this file.
1#ifndef OSMIUM_INDEX_RELATIONS_MAP_HPP
2#define OSMIUM_INDEX_RELATIONS_MAP_HPP
3
4/*
5
6This file is part of Osmium (https://osmcode.org/libosmium).
7
8Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
9
10Boost Software License - Version 1.0 - August 17th, 2003
11
12Permission is hereby granted, free of charge, to any person or organization
13obtaining a copy of the software and accompanying documentation covered by
14this license (the "Software") to use, reproduce, display, distribute,
15execute, and transmit the Software, and to prepare derivative works of the
16Software, and to permit third-parties to whom the Software is furnished to
17do so, all subject to the following:
18
19The copyright notices in the Software and this entire statement, including
20the above license grant, this restriction and the following disclaimer,
21must be included in all copies of the Software, in whole or in part, and
22all derivative works of the Software, unless such copies or derivative
23works are solely in the form of machine-executable object code generated by
24a source language processor.
25
26THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32DEALINGS IN THE SOFTWARE.
33
34*/
35
38#include <osmium/osm/types.hpp>
39
40#include <algorithm>
41#include <cassert>
42#include <cstddef>
43#include <cstdint>
44#include <tuple>
45#include <type_traits>
46#include <utility>
47#include <vector>
48
49namespace osmium {
50
51 namespace index {
52
53 namespace detail {
54
55 template <typename TKey, typename TKeyInternal, typename TValue, typename TValueInternal>
56 class flat_map {
57
58 public:
59
60 using key_type = TKey;
61 using value_type = TValue;
62
63 private:
64
65 struct kv_pair {
66 TKeyInternal key;
67 TValueInternal value;
68
69 explicit kv_pair(const key_type key_id) :
70 key(static_cast<TKeyInternal>(key_id)),
71 value() {
72 }
73
74 kv_pair(const key_type key_id, const value_type value_id) :
75 key(static_cast<TKeyInternal>(key_id)),
76 value(static_cast<TValueInternal>(value_id)) {
77 }
78
79 bool operator<(const kv_pair& other) const noexcept {
80 return std::tie(key, value) < std::tie(other.key, other.value);
81 }
82
83 bool operator==(const kv_pair& other) const noexcept {
84 return std::tie(key, value) == std::tie(other.key, other.value);
85 }
86 }; // struct kv_pair
87
88 std::vector<kv_pair> m_map;
89
90 public:
91
92 using const_iterator = typename std::vector<kv_pair>::const_iterator;
93
94 void set(const key_type key, const value_type value) {
95 m_map.emplace_back(key, value);
96 }
97
98 typename std::enable_if<std::is_same<TKey, TValue>::value>::type flip_in_place() {
99 for (auto& p : m_map) {
100 using std::swap;
101 swap(p.key, p.value);
102 }
103 }
104
105 flat_map<TValue, TValueInternal, TKey, TKeyInternal> flip_copy() {
106 flat_map<TValue, TValueInternal, TKey, TKeyInternal> map;
107 map.reserve(m_map.size());
108
109 for (const auto& p : m_map) {
110 map.set(p.value, p.key);
111 }
112
113 return map;
114 }
115
116 void sort_unique() {
117 std::sort(m_map.begin(), m_map.end());
118 const auto last = std::unique(m_map.begin(), m_map.end());
119 m_map.erase(last, m_map.end());
120 }
121
122 std::pair<const_iterator, const_iterator> get(const key_type key) const noexcept {
123 return std::equal_range(m_map.begin(), m_map.end(), kv_pair{key}, [](const kv_pair& lhs, const kv_pair& rhs) {
124 return lhs.key < rhs.key;
125 });
126 }
127
128 bool empty() const noexcept {
129 return m_map.empty();
130 }
131
132 std::size_t size() const noexcept {
133 return m_map.size();
134 }
135
136 void reserve(const std::size_t size) {
137 m_map.reserve(size);
138 }
139
140 }; // class flat_map
141
142 } // namespace detail
143
170
171 friend class RelationsMapStash;
173
174 using map_type = detail::flat_map<osmium::unsigned_object_id_type, uint32_t,
176
178
179 explicit RelationsMapIndex(map_type&& map) :
180 m_map(std::move(map)) {
181 }
182
183 public:
184
186
189
190 RelationsMapIndex(RelationsMapIndex&& /*other*/) noexcept(std::is_nothrow_move_constructible<map_type>::value);
191 RelationsMapIndex& operator=(RelationsMapIndex&& /*other*/) noexcept(std::is_nothrow_move_assignable<map_type>::value);
192
193 ~RelationsMapIndex() noexcept = default;
194
211 template <typename TFunc>
212 void for_each_parent(const osmium::unsigned_object_id_type member_id, TFunc&& func) const {
213 const auto parents = m_map.get(member_id);
214 for (auto it = parents.first; it != parents.second; ++it) {
215 func(it->value);
216 }
217 }
218
233 template <typename TFunc>
234 void for_each(const osmium::unsigned_object_id_type id, TFunc&& func) const {
235 const auto parents = m_map.get(id);
236 for (auto it = parents.first; it != parents.second; ++it) {
237 func(it->value);
238 }
239 }
240
246 bool empty() const noexcept {
247 return m_map.empty();
248 }
249
255 std::size_t size() const noexcept {
256 return m_map.size();
257 }
258
259 }; // class RelationsMapIndex
260
261 // defined outside the class on purpose
262 // see https://akrzemi1.wordpress.com/2015/09/11/declaring-the-move-constructor/
263 inline RelationsMapIndex::RelationsMapIndex(RelationsMapIndex&&) noexcept(std::is_nothrow_move_constructible<map_type>::value) = default;
264 inline RelationsMapIndex& RelationsMapIndex::operator=(RelationsMapIndex&&) noexcept(std::is_nothrow_move_assignable<map_type>::value) = default;
265
267
268 friend class RelationsMapStash;
269
272
274 m_member_to_parent(std::move(map1)),
275 m_parent_to_member(std::move(map2)) {
276 }
277
278 public:
279
280 const RelationsMapIndex& member_to_parent() const noexcept {
281 return m_member_to_parent;
282 }
283
284 const RelationsMapIndex& parent_to_member() const noexcept {
285 return m_parent_to_member;
286 }
287
293 bool empty() const noexcept {
294 return m_member_to_parent.empty();
295 }
296
302 std::size_t size() const noexcept {
303 return m_member_to_parent.size();
304 }
305
306 }; // class RelationsMapIndexes
307
314
315 using map_type = detail::flat_map<osmium::unsigned_object_id_type, uint32_t,
317
319
320#ifndef NDEBUG
321 bool m_valid = true;
322#endif
323
324 public:
325
326 RelationsMapStash() = default;
327
330
331 RelationsMapStash(RelationsMapStash&& /*other*/) noexcept(std::is_nothrow_move_constructible<map_type>::value);
332 RelationsMapStash& operator=(RelationsMapStash&& /*other*/) noexcept(std::is_nothrow_move_assignable<map_type>::value);
333
334 ~RelationsMapStash() noexcept = default;
335
339 void add(const osmium::unsigned_object_id_type member_id, const osmium::unsigned_object_id_type relation_id) {
340 assert(m_valid && "You can't use the RelationsMap any more after calling build_index()");
341 m_map.set(member_id, relation_id);
342 }
343
347 void add_members(const osmium::Relation& relation) {
348 assert(m_valid && "You can't use the RelationsMap any more after calling build_index()");
349 for (const auto& member : relation.members()) {
350 if (member.type() == osmium::item_type::relation) {
351 m_map.set(member.positive_ref(), relation.positive_id());
352 }
353 }
354 }
355
361 bool empty() const noexcept {
362 assert(m_valid && "You can't use the RelationsMap any more after calling build_index()");
363 return m_map.empty();
364 }
365
371 std::size_t size() const noexcept {
372 assert(m_valid && "You can't use the RelationsMap any more after calling build_index()");
373 return m_map.size();
374 }
375
385 assert(m_valid && "You can't use the RelationsMap any more after calling build_index()");
386 m_map.sort_unique();
387#ifndef NDEBUG
388 m_valid = false;
389#endif
390 return RelationsMapIndex{std::move(m_map)};
391 }
392
400 assert(m_valid && "You can't use the RelationsMap any more after calling build_member_to_parent_index()");
401 m_map.sort_unique();
402#ifndef NDEBUG
403 m_valid = false;
404#endif
405 return RelationsMapIndex{std::move(m_map)};
406 }
407
415 assert(m_valid && "You can't use the RelationsMap any more after calling build_parent_to_member_index()");
416 m_map.flip_in_place();
417 m_map.sort_unique();
418#ifndef NDEBUG
419 m_valid = false;
420#endif
421 return RelationsMapIndex{std::move(m_map)};
422 }
423
431 assert(m_valid && "You can't use the RelationsMap any more after calling build_indexes()");
432 auto reverse_map = m_map.flip_copy();
433 reverse_map.sort_unique();
434 m_map.sort_unique();
435#ifndef NDEBUG
436 m_valid = false;
437#endif
438 return RelationsMapIndexes{std::move(m_map), std::move(reverse_map)};
439 }
440
441 }; // class RelationsMapStash
442
443 // defined outside the class on purpose
444 // see https://akrzemi1.wordpress.com/2015/09/11/declaring-the-move-constructor/
445 inline RelationsMapStash::RelationsMapStash(RelationsMapStash&&) noexcept(std::is_nothrow_move_constructible<map_type>::value) = default;
446 inline RelationsMapStash& RelationsMapStash::operator=(RelationsMapStash&&) noexcept(std::is_nothrow_move_assignable<map_type>::value) = default;
447
448 } // namespace index
449
450} // namespace osmium
451
452#endif // OSMIUM_INDEX_RELATIONS_MAP_HPP
Definition: relation.hpp:161
Definition: relations_map.hpp:169
RelationsMapIndex(const RelationsMapIndex &)=delete
std::size_t size() const noexcept
Definition: relations_map.hpp:255
void for_each(const osmium::unsigned_object_id_type id, TFunc &&func) const
Definition: relations_map.hpp:234
RelationsMapIndex(RelationsMapIndex &&) noexcept(std::is_nothrow_move_constructible< map_type >::value)
detail::flat_map< osmium::unsigned_object_id_type, uint32_t, osmium::unsigned_object_id_type, uint32_t > map_type
Definition: relations_map.hpp:175
map_type m_map
Definition: relations_map.hpp:177
RelationsMapIndex(map_type &&map)
Definition: relations_map.hpp:179
RelationsMapIndex & operator=(const RelationsMapIndex &)=delete
bool empty() const noexcept
Definition: relations_map.hpp:246
void for_each_parent(const osmium::unsigned_object_id_type member_id, TFunc &&func) const
Definition: relations_map.hpp:212
Definition: relations_map.hpp:266
const RelationsMapIndex & parent_to_member() const noexcept
Definition: relations_map.hpp:284
const RelationsMapIndex & member_to_parent() const noexcept
Definition: relations_map.hpp:280
std::size_t size() const noexcept
Definition: relations_map.hpp:302
bool empty() const noexcept
Definition: relations_map.hpp:293
RelationsMapIndex m_member_to_parent
Definition: relations_map.hpp:270
RelationsMapIndexes(RelationsMapIndex::map_type &&map1, RelationsMapIndex::map_type &&map2)
Definition: relations_map.hpp:273
RelationsMapIndex m_parent_to_member
Definition: relations_map.hpp:271
Definition: relations_map.hpp:313
RelationsMapIndex build_member_to_parent_index()
Definition: relations_map.hpp:399
RelationsMapStash(RelationsMapStash &&) noexcept(std::is_nothrow_move_constructible< map_type >::value)
bool m_valid
Definition: relations_map.hpp:321
detail::flat_map< osmium::unsigned_object_id_type, uint32_t, osmium::unsigned_object_id_type, uint32_t > map_type
Definition: relations_map.hpp:316
std::size_t size() const noexcept
Definition: relations_map.hpp:371
RelationsMapIndexes build_indexes()
Definition: relations_map.hpp:430
RelationsMapIndex build_parent_to_member_index()
Definition: relations_map.hpp:414
void add_members(const osmium::Relation &relation)
Definition: relations_map.hpp:347
RelationsMapStash & operator=(const RelationsMapStash &)=delete
map_type m_map
Definition: relations_map.hpp:318
bool empty() const noexcept
Definition: relations_map.hpp:361
RelationsMapStash(const RelationsMapStash &)=delete
void add(const osmium::unsigned_object_id_type member_id, const osmium::unsigned_object_id_type relation_id)
Definition: relations_map.hpp:339
RelationsMapIndex build_index()
Definition: relations_map.hpp:384
Definition: attr.hpp:342
type
Definition: entity_bits.hpp:63
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
bool operator==(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:440
uint64_t unsigned_object_id_type
Type for OSM object (node, way, or relation) IDs where we only allow positive IDs.
Definition: types.hpp:46
bool operator<(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:451
Definition: location.hpp:555