@@ -41,6 +41,7 @@ DEALINGS IN THE SOFTWARE.
4141#include < cassert>
4242#include < cstddef>
4343#include < cstdint>
44+ #include < limits>
4445#include < tuple>
4546#include < type_traits>
4647#include < utility>
@@ -137,8 +138,25 @@ namespace osmium {
137138 m_map.reserve (size);
138139 }
139140
141+ void clear () {
142+ m_map.clear ();
143+ m_map.shrink_to_fit ();
144+ }
145+
146+ typename std::vector<kv_pair>::const_iterator begin () const noexcept {
147+ return m_map.cbegin ();
148+ }
149+
150+ typename std::vector<kv_pair>::const_iterator end () const noexcept {
151+ return m_map.cend ();
152+ }
153+
140154 }; // class flat_map
141155
156+ template <typename VType>
157+ using rel_index_map_type = detail::flat_map<osmium::unsigned_object_id_type, VType,
158+ osmium::unsigned_object_id_type, VType>;
159+
142160 } // namespace detail
143161
144162 /* *
@@ -171,13 +189,17 @@ namespace osmium {
171189 friend class RelationsMapStash ;
172190 friend class RelationsMapIndexes ;
173191
174- using map_type = detail::flat_map<osmium::unsigned_object_id_type, uint32_t ,
175- osmium::unsigned_object_id_type, uint32_t > ;
192+ detail::rel_index_map_type< uint32_t > m_map32;
193+ detail::rel_index_map_type< uint64_t > m_map64 ;
176194
177- map_type m_map ;
195+ bool m_small ;
178196
179- explicit RelationsMapIndex (map_type&& map) :
180- m_map(std::move(map)) {
197+ explicit RelationsMapIndex (detail::rel_index_map_type<uint32_t >&& map) :
198+ m_map32(std::move(map)), m_small(true ) {
199+ }
200+
201+ explicit RelationsMapIndex (detail::rel_index_map_type<uint64_t >&& map) :
202+ m_map64(std::move(map)), m_small(false ) {
181203 }
182204
183205 public:
@@ -187,35 +209,11 @@ namespace osmium {
187209 RelationsMapIndex (const RelationsMapIndex&) = delete ;
188210 RelationsMapIndex& operator =(const RelationsMapIndex&) = delete ;
189211
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) ;
212+ RelationsMapIndex (RelationsMapIndex&& /* other*/ ) noexcept ;
213+ RelationsMapIndex& operator =(RelationsMapIndex&& /* other*/ ) noexcept ;
192214
193215 ~RelationsMapIndex () noexcept = default ;
194216
195- /* *
196- * Find the given relation id in the index and call the given
197- * function with all parent relation ids.
198- *
199- * @code
200- * osmium::unsigned_object_id_type member_id = 17;
201- * index.for_each_parent(member_id, [](osmium::unsigned_object_id_type id) {
202- * ...
203- * });
204- * @endcode
205- *
206- * @deprecated Use for_each() instead.
207- *
208- * Complexity: Logarithmic in the number of elements in the index.
209- * (Lookup uses binary search.)
210- */
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-
219217 /* *
220218 * Find the given relation id in the index and call the given
221219 * function with all related relation ids.
@@ -232,9 +230,16 @@ namespace osmium {
232230 */
233231 template <typename TFunc>
234232 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 );
233+ if (m_small) {
234+ const auto parents = m_map32.get (id);
235+ for (auto it = parents.first ; it != parents.second ; ++it) {
236+ func (it->value );
237+ }
238+ } else {
239+ const auto parents = m_map64.get (id);
240+ for (auto it = parents.first ; it != parents.second ; ++it) {
241+ func (it->value );
242+ }
238243 }
239244 }
240245
@@ -244,7 +249,7 @@ namespace osmium {
244249 * Complexity: Constant.
245250 */
246251 bool empty () const noexcept {
247- return m_map .empty ();
252+ return m_small ? m_map32. empty () : m_map64 .empty ();
248253 }
249254
250255 /* *
@@ -253,15 +258,15 @@ namespace osmium {
253258 * Complexity: Constant.
254259 */
255260 std::size_t size () const noexcept {
256- return m_map .size ();
261+ return m_small ? m_map32. size () : m_map64 .size ();
257262 }
258263
259264 }; // class RelationsMapIndex
260265
261266 // defined outside the class on purpose
262267 // 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; // NOLINT(readability-redundant-inline-specifier)
264- inline RelationsMapIndex& RelationsMapIndex::operator =(RelationsMapIndex&&) noexcept (std::is_nothrow_move_assignable<map_type>::value) = default ; // NOLINT(readability-redundant-inline-specifier)
268+ inline RelationsMapIndex::RelationsMapIndex (RelationsMapIndex&&) noexcept = default; // NOLINT(readability-redundant-inline-specifier)
269+ inline RelationsMapIndex& RelationsMapIndex::operator =(RelationsMapIndex&&) noexcept = default ; // NOLINT(readability-redundant-inline-specifier)
265270
266271 class RelationsMapIndexes {
267272
@@ -270,7 +275,12 @@ namespace osmium {
270275 RelationsMapIndex m_member_to_parent;
271276 RelationsMapIndex m_parent_to_member;
272277
273- RelationsMapIndexes (RelationsMapIndex::map_type&& map1, RelationsMapIndex::map_type&& map2) :
278+ RelationsMapIndexes (detail::rel_index_map_type<uint32_t >&& map1, detail::rel_index_map_type<uint32_t >&& map2) :
279+ m_member_to_parent (std::move(map1)),
280+ m_parent_to_member (std::move(map2)) {
281+ }
282+
283+ RelationsMapIndexes (detail::rel_index_map_type<uint64_t >&& map1, detail::rel_index_map_type<uint64_t >&& map2) :
274284 m_member_to_parent (std::move(map1)),
275285 m_parent_to_member (std::move(map2)) {
276286 }
@@ -312,24 +322,32 @@ namespace osmium {
312322 */
313323 class RelationsMapStash {
314324
315- using map_type = detail::flat_map<osmium::unsigned_object_id_type, uint32_t ,
316- osmium::unsigned_object_id_type, uint32_t >;
317-
318- map_type m_map;
325+ detail::rel_index_map_type<uint32_t > m_map32;
326+ detail::rel_index_map_type<uint64_t > m_map64;
319327
320328#ifndef NDEBUG
321329 bool m_valid = true ;
322330#endif
323331
332+ static void append32to64 (detail::rel_index_map_type<uint32_t >& map32, detail::rel_index_map_type<uint64_t >& map64) {
333+ map64.sort_unique ();
334+ map64.reserve (map64.size () + map32.size ());
335+ for (const auto & item : map32) {
336+ map64.set (item.key , item.value );
337+ }
338+ map64.sort_unique ();
339+ map32.clear ();
340+ }
341+
324342 public:
325343
326344 RelationsMapStash () = default ;
327345
328346 RelationsMapStash (const RelationsMapStash&) = delete ;
329347 RelationsMapStash& operator =(const RelationsMapStash&) = delete ;
330348
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) ;
349+ RelationsMapStash (RelationsMapStash&& /* other*/ ) noexcept ;
350+ RelationsMapStash& operator =(RelationsMapStash&& /* other*/ ) noexcept ;
333351
334352 ~RelationsMapStash () noexcept = default ;
335353
@@ -338,7 +356,12 @@ namespace osmium {
338356 */
339357 void add (const osmium::unsigned_object_id_type member_id, const osmium::unsigned_object_id_type relation_id) {
340358 assert (m_valid && " You can't use the RelationsMap any more after calling build_index()" );
341- m_map.set (member_id, relation_id);
359+ constexpr const osmium::unsigned_object_id_type max32 = std::numeric_limits<uint32_t >::max ();
360+ if (member_id <= max32 && relation_id <= max32) {
361+ m_map32.set (member_id, relation_id);
362+ } else {
363+ m_map64.set (member_id, relation_id);
364+ }
342365 }
343366
344367 /* *
@@ -348,7 +371,7 @@ namespace osmium {
348371 assert (m_valid && " You can't use the RelationsMap any more after calling build_index()" );
349372 for (const auto & member : relation.members ()) {
350373 if (member.type () == osmium::item_type::relation) {
351- m_map. set (member.positive_ref (), relation.positive_id ());
374+ add (member.positive_ref (), relation.positive_id ());
352375 }
353376 }
354377 }
@@ -360,7 +383,7 @@ namespace osmium {
360383 */
361384 bool empty () const noexcept {
362385 assert (m_valid && " You can't use the RelationsMap any more after calling build_index()" );
363- return m_map .empty ();
386+ return m_map32. empty () && m_map64 .empty ();
364387 }
365388
366389 /* *
@@ -370,24 +393,17 @@ namespace osmium {
370393 */
371394 std::size_t size () const noexcept {
372395 assert (m_valid && " You can't use the RelationsMap any more after calling build_index()" );
373- return m_map .size ();
396+ return m_map32. size () + m_map64 .size ();
374397 }
375398
376399 /* *
377- * Build an index for member to parent lookups from the contents
378- * of this stash and return it.
400+ * How many "small" and "large" entries are in this stash?
401+ * For tests and debugging only!
379402 *
380- * After you get the index you can not use the stash any more!
381- *
382- * @deprecated Use build_member_to_parent_index() instead.
403+ * Complexity: Constant.
383404 */
384- RelationsMapIndex build_index () {
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)};
405+ std::pair<std::size_t , std::size_t > sizes () const noexcept {
406+ return std::make_pair (m_map32.size (), m_map64.size ());
391407 }
392408
393409 /* *
@@ -398,11 +414,17 @@ namespace osmium {
398414 */
399415 RelationsMapIndex build_member_to_parent_index () {
400416 assert (m_valid && " You can't use the RelationsMap any more after calling build_member_to_parent_index()" );
401- m_map.sort_unique ();
402417#ifndef NDEBUG
403418 m_valid = false ;
404419#endif
405- return RelationsMapIndex{std::move (m_map)};
420+ m_map32.sort_unique ();
421+ if (m_map64.empty ()) {
422+ return RelationsMapIndex{std::move (m_map32)};
423+ }
424+
425+ append32to64 (m_map32, m_map64);
426+
427+ return RelationsMapIndex{std::move (m_map64)};
406428 }
407429
408430 /* *
@@ -413,12 +435,19 @@ namespace osmium {
413435 */
414436 RelationsMapIndex build_parent_to_member_index () {
415437 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 ();
418438#ifndef NDEBUG
419439 m_valid = false ;
420440#endif
421- return RelationsMapIndex{std::move (m_map)};
441+ m_map32.flip_in_place ();
442+ m_map32.sort_unique ();
443+ if (m_map64.empty ()) {
444+ return RelationsMapIndex{std::move (m_map32)};
445+ }
446+
447+ m_map64.flip_in_place ();
448+ append32to64 (m_map32, m_map64);
449+
450+ return RelationsMapIndex{std::move (m_map64)};
422451 }
423452
424453 /* *
@@ -429,21 +458,29 @@ namespace osmium {
429458 */
430459 RelationsMapIndexes build_indexes () {
431460 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 ();
435461#ifndef NDEBUG
436462 m_valid = false ;
437463#endif
438- return RelationsMapIndexes{std::move (m_map), std::move (reverse_map)};
464+ auto reverse_map32 = m_map32.flip_copy ();
465+ reverse_map32.sort_unique ();
466+ m_map32.sort_unique ();
467+ if (m_map64.empty ()) {
468+ return RelationsMapIndexes{std::move (m_map32), std::move (reverse_map32)};
469+ }
470+
471+ auto reverse_map64 = m_map64.flip_copy ();
472+ append32to64 (reverse_map32, reverse_map64);
473+ append32to64 (m_map32, m_map64);
474+
475+ return RelationsMapIndexes{std::move (m_map64), std::move (reverse_map64)};
439476 }
440477
441478 }; // class RelationsMapStash
442479
443480 // defined outside the class on purpose
444481 // 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; // NOLINT(readability-redundant-inline-specifier)
446- inline RelationsMapStash& RelationsMapStash::operator =(RelationsMapStash&&) noexcept (std::is_nothrow_move_assignable<map_type>::value) = default ; // NOLINT(readability-redundant-inline-specifier)
482+ inline RelationsMapStash::RelationsMapStash (RelationsMapStash&&) noexcept = default; // NOLINT(readability-redundant-inline-specifier)
483+ inline RelationsMapStash& RelationsMapStash::operator =(RelationsMapStash&&) noexcept = default ; // NOLINT(readability-redundant-inline-specifier)
447484
448485 } // namespace index
449486
0 commit comments