Chromium Code Reviews| 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 <iterator> | |
| 9 #include <vector> | 10 #include <vector> |
| 10 | 11 |
| 11 namespace base { | 12 namespace base { |
| 12 | 13 |
| 13 enum FlatContainerDupes { | 14 enum FlatContainerDupes { |
| 14 KEEP_FIRST_OF_DUPES, | 15 KEEP_FIRST_OF_DUPES, |
| 15 KEEP_LAST_OF_DUPES, | 16 KEEP_LAST_OF_DUPES, |
| 16 }; | 17 }; |
| 17 | 18 |
| 18 namespace internal { | 19 namespace internal { |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 const_reverse_iterator crbegin() const; | 181 const_reverse_iterator crbegin() const; |
| 181 | 182 |
| 182 reverse_iterator rend(); | 183 reverse_iterator rend(); |
| 183 const_reverse_iterator rend() const; | 184 const_reverse_iterator rend() const; |
| 184 const_reverse_iterator crend() const; | 185 const_reverse_iterator crend() const; |
| 185 | 186 |
| 186 // -------------------------------------------------------------------------- | 187 // -------------------------------------------------------------------------- |
| 187 // Insert operations. | 188 // Insert operations. |
| 188 // | 189 // |
| 189 // Assume that every operation invalidates iterators and references. | 190 // Assume that every operation invalidates iterators and references. |
| 190 // Insertion of one element can take O(size). See the Notes section in the | 191 // Insertion of one element can take O(size). Capacity of flat_tree grows in |
| 191 // class comments on why we do not currently implement range insertion. | 192 // an implementation-defined manner. |
| 192 // Capacity of flat_tree grows in an implementation-defined manner. | |
| 193 // | 193 // |
| 194 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) | 194 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) |
| 195 // instead of calling insert() repeatedly. | 195 // instead of calling insert() repeatedly. |
| 196 | 196 |
| 197 std::pair<iterator, bool> insert(const value_type& val); | 197 std::pair<iterator, bool> insert(const value_type& val); |
| 198 std::pair<iterator, bool> insert(value_type&& val); | 198 std::pair<iterator, bool> insert(value_type&& val); |
| 199 | 199 |
| 200 iterator insert(const_iterator position_hint, const value_type& x); | 200 iterator insert(const_iterator position_hint, const value_type& x); |
| 201 iterator insert(const_iterator position_hint, value_type&& x); | 201 iterator insert(const_iterator position_hint, value_type&& x); |
| 202 | 202 |
| 203 template <class InputIterator> | |
| 204 void insert(InputIterator first, InputIterator last); | |
|
brettw
2017/05/09 20:25:45
I hate diverging from STL, but we've been consiste
dyaroshev
2017/05/09 21:37:19
I thought about that and I don't see how to do it
dyaroshev
2017/05/09 22:04:05
I thought about it a bit more - probably we can ma
jdoerrie
2017/05/10 15:39:18
Done.
| |
| 205 | |
| 203 template <class... Args> | 206 template <class... Args> |
| 204 std::pair<iterator, bool> emplace(Args&&... args); | 207 std::pair<iterator, bool> emplace(Args&&... args); |
| 205 | 208 |
| 206 template <class... Args> | 209 template <class... Args> |
| 207 iterator emplace_hint(const_iterator position_hint, Args&&... args); | 210 iterator emplace_hint(const_iterator position_hint, Args&&... args); |
| 208 | 211 |
| 209 // -------------------------------------------------------------------------- | 212 // -------------------------------------------------------------------------- |
| 210 // Erase operations. | 213 // Erase operations. |
| 211 // | 214 // |
| 212 // Assume that every operation invalidates iterators and references. | 215 // Assume that every operation invalidates iterators and references. |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 const key_compare& key_comp_; | 312 const key_compare& key_comp_; |
| 310 }; | 313 }; |
| 311 | 314 |
| 312 const flat_tree& as_const() { return *this; } | 315 const flat_tree& as_const() { return *this; } |
| 313 | 316 |
| 314 iterator const_cast_it(const_iterator c_it) { | 317 iterator const_cast_it(const_iterator c_it) { |
| 315 auto distance = std::distance(cbegin(), c_it); | 318 auto distance = std::distance(cbegin(), c_it); |
| 316 return std::next(begin(), distance); | 319 return std::next(begin(), distance); |
| 317 } | 320 } |
| 318 | 321 |
| 319 void sort_and_unique(FlatContainerDupes dupes) { | 322 void sort_and_unique(iterator first, |
| 323 iterator last, | |
| 324 FlatContainerDupes dupes) { | |
| 320 // Preserve stability for the unique code below. | 325 // Preserve stability for the unique code below. |
| 321 std::stable_sort(begin(), end(), impl_.get_value_comp()); | 326 std::stable_sort(first, last, impl_.get_value_comp()); |
| 322 | 327 |
| 323 auto comparator = [this](const value_type& lhs, const value_type& rhs) { | 328 auto comparator = [this](const value_type& lhs, const value_type& rhs) { |
| 324 // lhs is already <= rhs due to sort, therefore | 329 // lhs is already <= rhs due to sort, therefore |
| 325 // !(lhs < rhs) <=> lhs == rhs. | 330 // !(lhs < rhs) <=> lhs == rhs. |
| 326 return !impl_.get_value_comp()(lhs, rhs); | 331 return !impl_.get_value_comp()(lhs, rhs); |
| 327 }; | 332 }; |
| 328 | 333 |
| 329 iterator erase_after; | 334 iterator erase_after; |
| 330 switch (dupes) { | 335 switch (dupes) { |
| 331 case KEEP_FIRST_OF_DUPES: | 336 case KEEP_FIRST_OF_DUPES: |
| 332 erase_after = std::unique(begin(), end(), comparator); | 337 erase_after = std::unique(first, last, comparator); |
| 333 break; | 338 break; |
| 334 case KEEP_LAST_OF_DUPES: | 339 case KEEP_LAST_OF_DUPES: |
| 335 erase_after = LastUnique(begin(), end(), comparator); | 340 erase_after = LastUnique(first, last, comparator); |
| 336 break; | 341 break; |
| 337 } | 342 } |
| 338 erase(erase_after, end()); | 343 erase(erase_after, last); |
| 339 } | 344 } |
| 340 | 345 |
| 341 // To support comparators that may not be possible to default-construct, we | 346 // To support comparators that may not be possible to default-construct, we |
| 342 // have to store an instance of Compare. Using this to store all internal | 347 // have to store an instance of Compare. Using this to store all internal |
| 343 // state of flat_tree and using private inheritance to store compare lets us | 348 // state of flat_tree and using private inheritance to store compare lets us |
| 344 // take advantage of an empty base class optimization to avoid extra space in | 349 // take advantage of an empty base class optimization to avoid extra space in |
| 345 // the common case when Compare has no state. | 350 // the common case when Compare has no state. |
| 346 struct Impl : private value_compare { | 351 struct Impl : private value_compare { |
| 347 Impl() = default; | 352 Impl() = default; |
| 348 | 353 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 370 : impl_(comp) {} | 375 : impl_(comp) {} |
| 371 | 376 |
| 372 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 377 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 373 template <class InputIterator> | 378 template <class InputIterator> |
| 374 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 379 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 375 InputIterator first, | 380 InputIterator first, |
| 376 InputIterator last, | 381 InputIterator last, |
| 377 FlatContainerDupes dupe_handling, | 382 FlatContainerDupes dupe_handling, |
| 378 const KeyCompare& comp) | 383 const KeyCompare& comp) |
| 379 : impl_(comp, first, last) { | 384 : impl_(comp, first, last) { |
| 380 sort_and_unique(dupe_handling); | 385 sort_and_unique(begin(), end(), dupe_handling); |
| 381 } | 386 } |
| 382 | 387 |
| 383 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 388 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 384 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 389 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 385 const flat_tree&) = default; | 390 const flat_tree&) = default; |
| 386 | 391 |
| 387 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 392 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 388 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) = | 393 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) = |
| 389 default; | 394 default; |
| 390 | 395 |
| 391 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 396 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 392 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 397 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 393 std::vector<value_type> items, | 398 std::vector<value_type> items, |
| 394 FlatContainerDupes dupe_handling, | 399 FlatContainerDupes dupe_handling, |
| 395 const KeyCompare& comp) | 400 const KeyCompare& comp) |
| 396 : impl_(comp, std::move(items)) { | 401 : impl_(comp, std::move(items)) { |
| 397 sort_and_unique(dupe_handling); | 402 sort_and_unique(begin(), end(), dupe_handling); |
| 398 } | 403 } |
| 399 | 404 |
| 400 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 405 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 401 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 406 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
| 402 std::initializer_list<value_type> ilist, | 407 std::initializer_list<value_type> ilist, |
| 403 FlatContainerDupes dupe_handling, | 408 FlatContainerDupes dupe_handling, |
| 404 const KeyCompare& comp) | 409 const KeyCompare& comp) |
| 405 : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {} | 410 : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {} |
| 406 | 411 |
| 407 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 412 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 408 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default; | 413 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default; |
| 409 | 414 |
| 410 // ---------------------------------------------------------------------------- | 415 // ---------------------------------------------------------------------------- |
| 411 // Assignments. | 416 // Assignments. |
| 412 | 417 |
| 413 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 418 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 414 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( | 419 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( |
| 415 const flat_tree&) -> flat_tree& = default; | 420 const flat_tree&) -> flat_tree& = default; |
| 416 | 421 |
| 417 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 422 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 418 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&) | 423 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&) |
| 419 -> flat_tree& = default; | 424 -> flat_tree& = default; |
| 420 | 425 |
| 421 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 426 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 422 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( | 427 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( |
| 423 std::initializer_list<value_type> ilist) -> flat_tree& { | 428 std::initializer_list<value_type> ilist) -> flat_tree& { |
| 424 impl_.body_ = ilist; | 429 impl_.body_ = ilist; |
| 425 sort_and_unique(KEEP_FIRST_OF_DUPES); | 430 sort_and_unique(begin(), end(), KEEP_FIRST_OF_DUPES); |
| 426 return *this; | 431 return *this; |
| 427 } | 432 } |
| 428 | 433 |
| 429 // ---------------------------------------------------------------------------- | 434 // ---------------------------------------------------------------------------- |
| 430 // Memory management. | 435 // Memory management. |
| 431 | 436 |
| 432 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 437 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 433 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve( | 438 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve( |
| 434 size_type new_capacity) { | 439 size_type new_capacity) { |
| 435 impl_.body_.reserve(new_capacity); | 440 impl_.body_.reserve(new_capacity); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 596 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) { | 601 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) { |
| 597 if (position_hint == begin() || | 602 if (position_hint == begin() || |
| 598 impl_.get_value_comp()(*(position_hint - 1), val)) | 603 impl_.get_value_comp()(*(position_hint - 1), val)) |
| 599 // We have to cast away const because of crbug.com/677044. | 604 // We have to cast away const because of crbug.com/677044. |
| 600 return impl_.body_.insert(const_cast_it(position_hint), std::move(val)); | 605 return impl_.body_.insert(const_cast_it(position_hint), std::move(val)); |
| 601 } | 606 } |
| 602 return insert(std::move(val)).first; | 607 return insert(std::move(val)).first; |
| 603 } | 608 } |
| 604 | 609 |
| 605 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 610 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 611 template <class InputIterator> | |
| 612 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( | |
| 613 InputIterator first, | |
| 614 InputIterator last) -> void { | |
| 615 // Only add elements that are not already present. | |
| 616 size_type prev_size = size(); | |
| 617 std::copy_if(first, last, std::back_inserter(impl_.body_), | |
| 618 [this, prev_size](const value_type& val) { | |
| 619 return !std::binary_search( | |
| 620 begin(), std::next(begin(), prev_size), val, value_comp()); | |
| 621 }); | |
| 622 | |
| 623 // The new elements might be unordered and contain duplicates, so post-process | |
| 624 // the just inserted elements. | |
| 625 iterator middle = std::next(begin(), prev_size); | |
| 626 sort_and_unique(middle, end(), KEEP_FIRST_OF_DUPES); | |
| 627 | |
| 628 // Merge the old and new elements if necessary, do a binary search for the | |
| 629 // first inversion. | |
| 630 if (middle != begin() && middle != end() && | |
| 631 !value_comp()(*std::prev(middle), *middle)) { | |
| 632 std::inplace_merge(std::lower_bound(begin(), middle, *middle, value_comp()), | |
| 633 middle, end(), value_comp()); | |
| 634 } | |
| 635 } | |
| 636 | |
| 637 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | |
| 606 template <class... Args> | 638 template <class... Args> |
| 607 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) | 639 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) |
| 608 -> std::pair<iterator, bool> { | 640 -> std::pair<iterator, bool> { |
| 609 return insert(value_type(std::forward<Args>(args)...)); | 641 return insert(value_type(std::forward<Args>(args)...)); |
| 610 } | 642 } |
| 611 | 643 |
| 612 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 644 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 613 template <class... Args> | 645 template <class... Args> |
| 614 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( | 646 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( |
| 615 const_iterator position_hint, | 647 const_iterator position_hint, |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& | 800 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& |
| 769 container, | 801 container, |
| 770 Predicate pred) { | 802 Predicate pred) { |
| 771 container.erase(std::remove_if(container.begin(), container.end(), pred), | 803 container.erase(std::remove_if(container.begin(), container.end(), pred), |
| 772 container.end()); | 804 container.end()); |
| 773 } | 805 } |
| 774 | 806 |
| 775 } // namespace base | 807 } // namespace base |
| 776 | 808 |
| 777 #endif // BASE_CONTAINERS_FLAT_TREE_H_ | 809 #endif // BASE_CONTAINERS_FLAT_TREE_H_ |
| OLD | NEW |