@@ -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,11 @@ 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+ if (member_id <= std::numeric_limits<uint32_t >::max () && relation_id <= std::numeric_limits<uint32_t >::max ()) {
360+ m_map32.set (member_id, relation_id);
361+ } else {
362+ m_map64.set (member_id, relation_id);
363+ }
342364 }
343365
344366 /* *
@@ -348,7 +370,7 @@ namespace osmium {
348370 assert (m_valid && " You can't use the RelationsMap any more after calling build_index()" );
349371 for (const auto & member : relation.members ()) {
350372 if (member.type () == osmium::item_type::relation) {
351- m_map. set (member.positive_ref (), relation.positive_id ());
373+ add (member.positive_ref (), relation.positive_id ());
352374 }
353375 }
354376 }
@@ -360,7 +382,7 @@ namespace osmium {
360382 */
361383 bool empty () const noexcept {
362384 assert (m_valid && " You can't use the RelationsMap any more after calling build_index()" );
363- return m_map .empty ();
385+ return m_map32. empty () && m_map64 .empty ();
364386 }
365387
366388 /* *
@@ -370,24 +392,17 @@ namespace osmium {
370392 */
371393 std::size_t size () const noexcept {
372394 assert (m_valid && " You can't use the RelationsMap any more after calling build_index()" );
373- return m_map .size ();
395+ return m_map32. size () + m_map64 .size ();
374396 }
375397
376398 /* *
377- * Build an index for member to parent lookups from the contents
378- * of this stash and return it.
399+ * How many "small" and "large" entries are in this stash?
400+ * For tests and debugging only!
379401 *
380- * After you get the index you can not use the stash any more!
381- *
382- * @deprecated Use build_member_to_parent_index() instead.
402+ * Complexity: Constant.
383403 */
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)};
404+ std::pair<std::size_t , std::size_t > sizes () const noexcept {
405+ return std::make_pair (m_map32.size (), m_map64.size ());
391406 }
392407
393408 /* *
@@ -398,11 +413,17 @@ namespace osmium {
398413 */
399414 RelationsMapIndex build_member_to_parent_index () {
400415 assert (m_valid && " You can't use the RelationsMap any more after calling build_member_to_parent_index()" );
401- m_map.sort_unique ();
402416#ifndef NDEBUG
403417 m_valid = false ;
404418#endif
405- return RelationsMapIndex{std::move (m_map)};
419+ m_map32.sort_unique ();
420+ if (m_map64.empty ()) {
421+ return RelationsMapIndex{std::move (m_map32)};
422+ }
423+
424+ append32to64 (m_map32, m_map64);
425+
426+ return RelationsMapIndex{std::move (m_map64)};
406427 }
407428
408429 /* *
@@ -413,12 +434,19 @@ namespace osmium {
413434 */
414435 RelationsMapIndex build_parent_to_member_index () {
415436 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 ();
418437#ifndef NDEBUG
419438 m_valid = false ;
420439#endif
421- return RelationsMapIndex{std::move (m_map)};
440+ m_map32.flip_in_place ();
441+ m_map32.sort_unique ();
442+ if (m_map64.empty ()) {
443+ return RelationsMapIndex{std::move (m_map32)};
444+ }
445+
446+ m_map64.flip_in_place ();
447+ append32to64 (m_map32, m_map64);
448+
449+ return RelationsMapIndex{std::move (m_map64)};
422450 }
423451
424452 /* *
@@ -429,21 +457,29 @@ namespace osmium {
429457 */
430458 RelationsMapIndexes build_indexes () {
431459 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 ();
435460#ifndef NDEBUG
436461 m_valid = false ;
437462#endif
438- return RelationsMapIndexes{std::move (m_map), std::move (reverse_map)};
463+ auto reverse_map32 = m_map32.flip_copy ();
464+ reverse_map32.sort_unique ();
465+ m_map32.sort_unique ();
466+ if (m_map64.empty ()) {
467+ return RelationsMapIndexes{std::move (m_map32), std::move (reverse_map32)};
468+ }
469+
470+ auto reverse_map64 = m_map64.flip_copy ();
471+ append32to64 (reverse_map32, reverse_map64);
472+ append32to64 (m_map32, m_map64);
473+
474+ return RelationsMapIndexes{std::move (m_map64), std::move (reverse_map64)};
439475 }
440476
441477 }; // class RelationsMapStash
442478
443479 // defined outside the class on purpose
444480 // 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)
481+ inline RelationsMapStash::RelationsMapStash (RelationsMapStash&&) noexcept = default; // NOLINT(readability-redundant-inline-specifier)
482+ inline RelationsMapStash& RelationsMapStash::operator =(RelationsMapStash&&) noexcept = default ; // NOLINT(readability-redundant-inline-specifier)
447483
448484 } // namespace index
449485
0 commit comments