| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_ | 5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_ |
| 6 #define BASE_CONTAINERS_FLAT_TREE_H_ | 6 #define BASE_CONTAINERS_FLAT_TREE_H_ |
| 7 | 7 |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 namespace base { | 11 namespace base { |
| 12 |
| 13 enum FlatContainerDupes { |
| 14 KEEP_FIRST_OF_DUPES, |
| 15 KEEP_LAST_OF_DUPES, |
| 16 }; |
| 17 |
| 12 namespace internal { | 18 namespace internal { |
| 13 | 19 |
| 20 // This algorithm is like unique() from the standard library except it |
| 21 // selects only the last of consecutive values instead of the first. |
| 22 template <class Iterator, class BinaryPredicate> |
| 23 Iterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) { |
| 24 if (first == last) |
| 25 return last; |
| 26 |
| 27 Iterator dest = first; |
| 28 Iterator cur = first; |
| 29 Iterator prev = cur; |
| 30 while (++cur != last) { |
| 31 if (!compare(*prev, *cur)) { |
| 32 // Non-identical one. |
| 33 if (dest != prev) |
| 34 *dest = std::move(*prev); |
| 35 ++dest; |
| 36 } |
| 37 prev = cur; |
| 38 } |
| 39 |
| 40 if (dest != prev) |
| 41 *dest = std::move(*prev); |
| 42 return ++dest; |
| 43 } |
| 44 |
| 14 // Implementation of a sorted vector for backing flat_set and flat_map. Do not | 45 // Implementation of a sorted vector for backing flat_set and flat_map. Do not |
| 15 // use directly. | 46 // use directly. |
| 16 // | 47 // |
| 17 // The use of "value" in this is like std::map uses, meaning it's the thing | 48 // The use of "value" in this is like std::map uses, meaning it's the thing |
| 18 // contained (in the case of map it's a <Kay, Mapped> pair). The Key is how | 49 // contained (in the case of map it's a <Kay, Mapped> pair). The Key is how |
| 19 // things are looked up. In the case of a set, Key == Value. In the case of | 50 // things are looked up. In the case of a set, Key == Value. In the case of |
| 20 // a map, the Key is a component of a Value. | 51 // a map, the Key is a component of a Value. |
| 21 // | 52 // |
| 22 // The helper class GetKeyFromValue provides the means to extract a key from a | 53 // The helper class GetKeyFromValue provides the means to extract a key from a |
| 23 // value for comparison purposes. It should implement: | 54 // value for comparison purposes. It should implement: |
| 24 // const Key& operator()(const Value&). | 55 // const Key& operator()(const Value&). |
| 25 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 56 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 26 class flat_tree { | 57 class flat_tree { |
| 27 public: | |
| 28 private: | 58 private: |
| 29 using underlying_type = std::vector<Value>; | 59 using underlying_type = std::vector<Value>; |
| 30 | 60 |
| 31 public: | 61 public: |
| 32 // -------------------------------------------------------------------------- | 62 // -------------------------------------------------------------------------- |
| 33 // Types. | 63 // Types. |
| 34 // | 64 // |
| 35 using key_type = Key; | 65 using key_type = Key; |
| 36 using key_compare = KeyCompare; | 66 using key_compare = KeyCompare; |
| 37 using value_type = Value; | 67 using value_type = Value; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 64 typename underlying_type::const_reverse_iterator; | 94 typename underlying_type::const_reverse_iterator; |
| 65 | 95 |
| 66 // -------------------------------------------------------------------------- | 96 // -------------------------------------------------------------------------- |
| 67 // Lifetime. | 97 // Lifetime. |
| 68 // | 98 // |
| 69 // Constructors that take range guarantee O(N * log^2(N)) + O(N) complexity | 99 // Constructors that take range guarantee O(N * log^2(N)) + O(N) complexity |
| 70 // and take O(N * log(N)) + O(N) if extra memory is available (N is a range | 100 // and take O(N * log(N)) + O(N) if extra memory is available (N is a range |
| 71 // length). | 101 // length). |
| 72 // | 102 // |
| 73 // Assume that move constructors invalidate iterators and references. | 103 // Assume that move constructors invalidate iterators and references. |
| 104 // |
| 105 // The constructors that take ranges, lists, and vectors do not require that |
| 106 // the input be sorted. |
| 74 | 107 |
| 75 flat_tree(); | 108 flat_tree(); |
| 76 explicit flat_tree(const key_compare& comp); | 109 explicit flat_tree(const key_compare& comp); |
| 77 | 110 |
| 78 // Not stable in the presence of duplicates in the initializer list. | |
| 79 template <class InputIterator> | 111 template <class InputIterator> |
| 80 flat_tree(InputIterator first, | 112 flat_tree(InputIterator first, |
| 81 InputIterator last, | 113 InputIterator last, |
| 114 FlatContainerDupes dupe_handling, |
| 82 const key_compare& comp = key_compare()); | 115 const key_compare& comp = key_compare()); |
| 83 | 116 |
| 84 flat_tree(const flat_tree&); | 117 flat_tree(const flat_tree&); |
| 85 flat_tree(flat_tree&&); | 118 flat_tree(flat_tree&&); |
| 86 | 119 |
| 87 // Not stable in the presence of duplicates in the initializer list. | 120 flat_tree(std::vector<value_type> items, |
| 121 FlatContainerDupes dupe_handling, |
| 122 const key_compare& comp = key_compare()); |
| 123 |
| 88 flat_tree(std::initializer_list<value_type> ilist, | 124 flat_tree(std::initializer_list<value_type> ilist, |
| 125 FlatContainerDupes dupe_handling, |
| 89 const key_compare& comp = key_compare()); | 126 const key_compare& comp = key_compare()); |
| 90 | 127 |
| 91 ~flat_tree(); | 128 ~flat_tree(); |
| 92 | 129 |
| 93 // -------------------------------------------------------------------------- | 130 // -------------------------------------------------------------------------- |
| 94 // Assignments. | 131 // Assignments. |
| 95 // | 132 // |
| 96 // Assume that move assignment invalidates iterators and references. | 133 // Assume that move assignment invalidates iterators and references. |
| 97 | 134 |
| 98 flat_tree& operator=(const flat_tree&); | 135 flat_tree& operator=(const flat_tree&); |
| 99 flat_tree& operator=(flat_tree&&); | 136 flat_tree& operator=(flat_tree&&); |
| 100 // Not stable in the presence of duplicates in the initializer list. | 137 // Takes the first if there are duplicates in the initializer list. |
| 101 flat_tree& operator=(std::initializer_list<value_type> ilist); | 138 flat_tree& operator=(std::initializer_list<value_type> ilist); |
| 102 | 139 |
| 103 // -------------------------------------------------------------------------- | 140 // -------------------------------------------------------------------------- |
| 104 // Memory management. | 141 // Memory management. |
| 105 // | 142 // |
| 106 // Beware that shrink_to_fit() simply forwards the request to the | 143 // Beware that shrink_to_fit() simply forwards the request to the |
| 107 // underlying_type and its implementation is free to optimize otherwise and | 144 // underlying_type and its implementation is free to optimize otherwise and |
| 108 // leave capacity() to be greater that its size. | 145 // leave capacity() to be greater that its size. |
| 109 // | 146 // |
| 110 // reserve() and shrink_to_fit() invalidate iterators and references. | 147 // reserve() and shrink_to_fit() invalidate iterators and references. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 const key_compare& key_comp_; | 306 const key_compare& key_comp_; |
| 270 }; | 307 }; |
| 271 | 308 |
| 272 const flat_tree& as_const() { return *this; } | 309 const flat_tree& as_const() { return *this; } |
| 273 | 310 |
| 274 iterator const_cast_it(const_iterator c_it) { | 311 iterator const_cast_it(const_iterator c_it) { |
| 275 auto distance = std::distance(cbegin(), c_it); | 312 auto distance = std::distance(cbegin(), c_it); |
| 276 return std::next(begin(), distance); | 313 return std::next(begin(), distance); |
| 277 } | 314 } |
| 278 | 315 |
| 279 void sort_and_unique() { | 316 void sort_and_unique(FlatContainerDupes dupes) { |
| 280 // std::set sorts elements preserving stability because it doesn't have any | 317 // Preserve stability for the unique code below. |
| 281 // performance wins in not doing that. We do, so we use an unstable sort. | 318 std::stable_sort(begin(), end(), impl_.get_value_comp()); |
| 282 std::sort(begin(), end(), impl_.get_value_comp()); | 319 |
| 283 erase(std::unique(begin(), end(), | 320 auto comparator = [this](const value_type& lhs, const value_type& rhs) { |
| 284 [this](const value_type& lhs, const value_type& rhs) { | 321 // lhs is already <= rhs due to sort, therefore |
| 285 // lhs is already <= rhs due to sort, therefore | 322 // !(lhs < rhs) <=> lhs == rhs. |
| 286 // !(lhs < rhs) <=> lhs == rhs. | 323 return !impl_.get_value_comp()(lhs, rhs); |
| 287 return !impl_.get_value_comp()(lhs, rhs); | 324 }; |
| 288 }), | 325 |
| 289 end()); | 326 iterator erase_after; |
| 327 switch (dupes) { |
| 328 case KEEP_FIRST_OF_DUPES: |
| 329 erase_after = std::unique(begin(), end(), comparator); |
| 330 break; |
| 331 case KEEP_LAST_OF_DUPES: |
| 332 erase_after = LastUnique(begin(), end(), comparator); |
| 333 break; |
| 334 } |
| 335 erase(erase_after, end()); |
| 290 } | 336 } |
| 291 | 337 |
| 292 // To support comparators that may not be possible to default-construct, we | 338 // To support comparators that may not be possible to default-construct, we |
| 293 // have to store an instance of Compare. Using this to store all internal | 339 // have to store an instance of Compare. Using this to store all internal |
| 294 // state of flat_tree and using private inheritance to store compare lets us | 340 // state of flat_tree and using private inheritance to store compare lets us |
| 295 // take advantage of an empty base class optimization to avoid extra space in | 341 // take advantage of an empty base class optimization to avoid extra space in |
| 296 // the common case when Compare has no state. | 342 // the common case when Compare has no state. |
| 297 struct Impl : private value_compare { | 343 struct Impl : private value_compare { |
| 298 Impl() = default; | 344 Impl() = default; |
| 299 | 345 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 318 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 364 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 319 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 365 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 320 const KeyCompare& comp) | 366 const KeyCompare& comp) |
| 321 : impl_(comp) {} | 367 : impl_(comp) {} |
| 322 | 368 |
| 323 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 369 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 324 template <class InputIterator> | 370 template <class InputIterator> |
| 325 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 371 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 326 InputIterator first, | 372 InputIterator first, |
| 327 InputIterator last, | 373 InputIterator last, |
| 374 FlatContainerDupes dupe_handling, |
| 328 const KeyCompare& comp) | 375 const KeyCompare& comp) |
| 329 : impl_(comp, first, last) { | 376 : impl_(comp, first, last) { |
| 330 sort_and_unique(); | 377 sort_and_unique(dupe_handling); |
| 331 } | 378 } |
| 332 | 379 |
| 333 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 380 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 334 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 381 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 335 const flat_tree&) = default; | 382 const flat_tree&) = default; |
| 336 | 383 |
| 337 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 384 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 338 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) = | 385 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) = |
| 339 default; | 386 default; |
| 340 | 387 |
| 341 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 388 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 342 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 389 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 390 std::vector<value_type> items, |
| 391 FlatContainerDupes dupe_handling, |
| 392 const KeyCompare& comp) |
| 393 : impl_(comp, std::move(items)) { |
| 394 sort_and_unique(dupe_handling); |
| 395 } |
| 396 |
| 397 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 398 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 343 std::initializer_list<value_type> ilist, | 399 std::initializer_list<value_type> ilist, |
| 400 FlatContainerDupes dupe_handling, |
| 344 const KeyCompare& comp) | 401 const KeyCompare& comp) |
| 345 : flat_tree(std::begin(ilist), std::end(ilist), comp) {} | 402 : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {} |
| 346 | 403 |
| 347 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 404 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 348 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default; | 405 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default; |
| 349 | 406 |
| 350 // ---------------------------------------------------------------------------- | 407 // ---------------------------------------------------------------------------- |
| 351 // Assignments. | 408 // Assignments. |
| 352 | 409 |
| 353 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 410 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 354 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( | 411 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( |
| 355 const flat_tree&) -> flat_tree& = default; | 412 const flat_tree&) -> flat_tree& = default; |
| 356 | 413 |
| 357 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 414 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 358 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&) | 415 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&) |
| 359 -> flat_tree& = default; | 416 -> flat_tree& = default; |
| 360 | 417 |
| 361 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 418 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 362 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( | 419 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( |
| 363 std::initializer_list<value_type> ilist) -> flat_tree& { | 420 std::initializer_list<value_type> ilist) -> flat_tree& { |
| 364 impl_.body_ = ilist; | 421 impl_.body_ = ilist; |
| 365 sort_and_unique(); | 422 sort_and_unique(KEEP_FIRST_OF_DUPES); |
| 366 return *this; | 423 return *this; |
| 367 } | 424 } |
| 368 | 425 |
| 369 // ---------------------------------------------------------------------------- | 426 // ---------------------------------------------------------------------------- |
| 370 // Memory management. | 427 // Memory management. |
| 371 | 428 |
| 372 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 429 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 373 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve( | 430 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve( |
| 374 size_type new_capacity) { | 431 size_type new_capacity) { |
| 375 impl_.body_.reserve(new_capacity); | 432 impl_.body_.reserve(new_capacity); |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& | 765 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& |
| 709 container, | 766 container, |
| 710 Predicate pred) { | 767 Predicate pred) { |
| 711 container.erase(std::remove_if(container.begin(), container.end(), pred), | 768 container.erase(std::remove_if(container.begin(), container.end(), pred), |
| 712 container.end()); | 769 container.end()); |
| 713 } | 770 } |
| 714 | 771 |
| 715 } // namespace base | 772 } // namespace base |
| 716 | 773 |
| 717 #endif // BASE_CONTAINERS_FLAT_TREE_H_ | 774 #endif // BASE_CONTAINERS_FLAT_TREE_H_ |
| OLD | NEW |