@@ -41,6 +41,7 @@ DEALINGS IN THE SOFTWARE.
41
41
#include < cassert>
42
42
#include < cstddef>
43
43
#include < cstdint>
44
+ #include < limits>
44
45
#include < tuple>
45
46
#include < type_traits>
46
47
#include < utility>
@@ -137,8 +138,25 @@ namespace osmium {
137
138
m_map.reserve (size);
138
139
}
139
140
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
+
140
154
}; // class flat_map
141
155
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
+
142
160
} // namespace detail
143
161
144
162
/* *
@@ -171,13 +189,17 @@ namespace osmium {
171
189
friend class RelationsMapStash ;
172
190
friend class RelationsMapIndexes ;
173
191
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 ;
176
194
177
- map_type m_map ;
195
+ bool m_small ;
178
196
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 ) {
181
203
}
182
204
183
205
public:
@@ -187,35 +209,11 @@ namespace osmium {
187
209
RelationsMapIndex (const RelationsMapIndex&) = delete ;
188
210
RelationsMapIndex& operator =(const RelationsMapIndex&) = delete ;
189
211
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 ;
192
214
193
215
~RelationsMapIndex () noexcept = default ;
194
216
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
-
219
217
/* *
220
218
* Find the given relation id in the index and call the given
221
219
* function with all related relation ids.
@@ -232,9 +230,16 @@ namespace osmium {
232
230
*/
233
231
template <typename TFunc>
234
232
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
+ std::forward<TFunc>(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
+ std::forward<TFunc>(func)(it->value );
242
+ }
238
243
}
239
244
}
240
245
@@ -244,7 +249,7 @@ namespace osmium {
244
249
* Complexity: Constant.
245
250
*/
246
251
bool empty () const noexcept {
247
- return m_map .empty ();
252
+ return m_small ? m_map32. empty () : m_map64 .empty ();
248
253
}
249
254
250
255
/* *
@@ -253,15 +258,15 @@ namespace osmium {
253
258
* Complexity: Constant.
254
259
*/
255
260
std::size_t size () const noexcept {
256
- return m_map .size ();
261
+ return m_small ? m_map32. size () : m_map64 .size ();
257
262
}
258
263
259
264
}; // class RelationsMapIndex
260
265
261
266
// defined outside the class on purpose
262
267
// 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)
265
270
266
271
class RelationsMapIndexes {
267
272
@@ -270,7 +275,12 @@ namespace osmium {
270
275
RelationsMapIndex m_member_to_parent;
271
276
RelationsMapIndex m_parent_to_member;
272
277
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) :
274
284
m_member_to_parent (std::move(map1)),
275
285
m_parent_to_member (std::move(map2)) {
276
286
}
@@ -312,24 +322,32 @@ namespace osmium {
312
322
*/
313
323
class RelationsMapStash {
314
324
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;
319
327
320
328
#ifndef NDEBUG
321
329
bool m_valid = true ;
322
330
#endif
323
331
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
+
324
342
public:
325
343
326
344
RelationsMapStash () = default ;
327
345
328
346
RelationsMapStash (const RelationsMapStash&) = delete ;
329
347
RelationsMapStash& operator =(const RelationsMapStash&) = delete ;
330
348
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 ;
333
351
334
352
~RelationsMapStash () noexcept = default ;
335
353
@@ -338,7 +356,12 @@ namespace osmium {
338
356
*/
339
357
void add (const osmium::unsigned_object_id_type member_id, const osmium::unsigned_object_id_type relation_id) {
340
358
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
+ }
342
365
}
343
366
344
367
/* *
@@ -348,7 +371,7 @@ namespace osmium {
348
371
assert (m_valid && " You can't use the RelationsMap any more after calling build_index()" );
349
372
for (const auto & member : relation .members ()) {
350
373
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 ());
352
375
}
353
376
}
354
377
}
@@ -360,7 +383,7 @@ namespace osmium {
360
383
*/
361
384
bool empty () const noexcept {
362
385
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 ();
364
387
}
365
388
366
389
/* *
@@ -370,24 +393,17 @@ namespace osmium {
370
393
*/
371
394
std::size_t size () const noexcept {
372
395
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 ();
374
397
}
375
398
376
399
/* *
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!
379
402
*
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.
383
404
*/
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 ());
391
407
}
392
408
393
409
/* *
@@ -398,11 +414,17 @@ namespace osmium {
398
414
*/
399
415
RelationsMapIndex build_member_to_parent_index () {
400
416
assert (m_valid && " You can't use the RelationsMap any more after calling build_member_to_parent_index()" );
401
- m_map.sort_unique ();
402
417
#ifndef NDEBUG
403
418
m_valid = false ;
404
419
#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)};
406
428
}
407
429
408
430
/* *
@@ -413,12 +435,19 @@ namespace osmium {
413
435
*/
414
436
RelationsMapIndex build_parent_to_member_index () {
415
437
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
438
#ifndef NDEBUG
419
439
m_valid = false ;
420
440
#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)};
422
451
}
423
452
424
453
/* *
@@ -429,21 +458,29 @@ namespace osmium {
429
458
*/
430
459
RelationsMapIndexes build_indexes () {
431
460
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
461
#ifndef NDEBUG
436
462
m_valid = false ;
437
463
#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)};
439
476
}
440
477
441
478
}; // class RelationsMapStash
442
479
443
480
// defined outside the class on purpose
444
481
// 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)
447
484
448
485
} // namespace index
449
486
0 commit comments