| 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 #include "base/memory/ptr_util.h" |
| 12 |
| 11 namespace base { | 13 namespace base { |
| 12 | 14 |
| 13 enum FlatContainerDupes { | 15 enum FlatContainerDupes { |
| 14 KEEP_FIRST_OF_DUPES, | 16 KEEP_FIRST_OF_DUPES, |
| 15 KEEP_LAST_OF_DUPES, | 17 KEEP_LAST_OF_DUPES, |
| 16 }; | 18 }; |
| 17 | 19 |
| 20 enum RangeInsertMethod { |
| 21 ONE_BY_ONE, |
| 22 STABLE_SORT_ALL, |
| 23 STABLE_SORT_SMART, |
| 24 STABLE_SORT_SMARTER, |
| 25 }; |
| 26 |
| 18 namespace internal { | 27 namespace internal { |
| 19 | 28 |
| 20 // This algorithm is like unique() from the standard library except it | 29 // This algorithm is like unique() from the standard library except it |
| 21 // selects only the last of consecutive values instead of the first. | 30 // selects only the last of consecutive values instead of the first. |
| 22 template <class Iterator, class BinaryPredicate> | 31 template <class Iterator, class BinaryPredicate> |
| 23 Iterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) { | 32 Iterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) { |
| 24 Iterator replacable = std::adjacent_find(first, last, compare); | 33 Iterator replacable = std::adjacent_find(first, last, compare); |
| 25 | 34 |
| 26 // No duplicate elements found. | 35 // No duplicate elements found. |
| 27 if (replacable == last) | 36 if (replacable == last) |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 // | 202 // |
| 194 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) | 203 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) |
| 195 // instead of calling insert() repeatedly. | 204 // instead of calling insert() repeatedly. |
| 196 | 205 |
| 197 std::pair<iterator, bool> insert(const value_type& val); | 206 std::pair<iterator, bool> insert(const value_type& val); |
| 198 std::pair<iterator, bool> insert(value_type&& val); | 207 std::pair<iterator, bool> insert(value_type&& val); |
| 199 | 208 |
| 200 iterator insert(const_iterator position_hint, const value_type& x); | 209 iterator insert(const_iterator position_hint, const value_type& x); |
| 201 iterator insert(const_iterator position_hint, value_type&& x); | 210 iterator insert(const_iterator position_hint, value_type&& x); |
| 202 | 211 |
| 212 template <class InputIterator> |
| 213 void insert(InputIterator first, |
| 214 InputIterator last, |
| 215 RangeInsertMethod method); |
| 216 |
| 203 template <class... Args> | 217 template <class... Args> |
| 204 std::pair<iterator, bool> emplace(Args&&... args); | 218 std::pair<iterator, bool> emplace(Args&&... args); |
| 205 | 219 |
| 206 template <class... Args> | 220 template <class... Args> |
| 207 iterator emplace_hint(const_iterator position_hint, Args&&... args); | 221 iterator emplace_hint(const_iterator position_hint, Args&&... args); |
| 208 | 222 |
| 209 // -------------------------------------------------------------------------- | 223 // -------------------------------------------------------------------------- |
| 210 // Erase operations. | 224 // Erase operations. |
| 211 // | 225 // |
| 212 // Assume that every operation invalidates iterators and references. | 226 // Assume that every operation invalidates iterators and references. |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 // | 563 // |
| 550 // Currently we use position_hint the same way as eastl or boost: | 564 // Currently we use position_hint the same way as eastl or boost: |
| 551 // https://github.com/electronicarts/EASTL/blob/master/include/EASTL/vector_set.
h#L493 | 565 // https://github.com/electronicarts/EASTL/blob/master/include/EASTL/vector_set.
h#L493 |
| 552 // | 566 // |
| 553 // We duplicate code between copy and move version so that we can avoid | 567 // We duplicate code between copy and move version so that we can avoid |
| 554 // creating a temporary value. | 568 // creating a temporary value. |
| 555 | 569 |
| 556 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 570 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 557 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( | 571 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( |
| 558 const value_type& val) -> std::pair<iterator, bool> { | 572 const value_type& val) -> std::pair<iterator, bool> { |
| 559 auto position = lower_bound(val); | 573 GetKeyFromValue extractor; |
| 574 auto position = lower_bound(extractor(val)); |
| 560 | 575 |
| 561 if (position == end() || impl_.get_value_comp()(val, *position)) | 576 if (position == end() || impl_.get_value_comp()(val, *position)) |
| 562 return {impl_.body_.insert(position, val), true}; | 577 return {impl_.body_.insert(position, val), true}; |
| 563 | 578 |
| 564 return {position, false}; | 579 return {position, false}; |
| 565 } | 580 } |
| 566 | 581 |
| 567 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 582 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 568 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( | 583 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( |
| 569 value_type&& val) -> std::pair<iterator, bool> { | 584 value_type&& val) -> std::pair<iterator, bool> { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 596 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) { | 611 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) { |
| 597 if (position_hint == begin() || | 612 if (position_hint == begin() || |
| 598 impl_.get_value_comp()(*(position_hint - 1), val)) | 613 impl_.get_value_comp()(*(position_hint - 1), val)) |
| 599 // We have to cast away const because of crbug.com/677044. | 614 // We have to cast away const because of crbug.com/677044. |
| 600 return impl_.body_.insert(const_cast_it(position_hint), std::move(val)); | 615 return impl_.body_.insert(const_cast_it(position_hint), std::move(val)); |
| 601 } | 616 } |
| 602 return insert(std::move(val)).first; | 617 return insert(std::move(val)).first; |
| 603 } | 618 } |
| 604 | 619 |
| 605 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 620 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 621 template <class InputIterator> |
| 622 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( |
| 623 InputIterator first, |
| 624 InputIterator last, |
| 625 RangeInsertMethod method) -> void { |
| 626 switch (method) { |
| 627 case ONE_BY_ONE: |
| 628 for (; first != last; ++first) { |
| 629 insert(*first); |
| 630 } |
| 631 return; |
| 632 |
| 633 case STABLE_SORT_ALL: |
| 634 impl_.body_.insert(impl_.body_.end(), first, last); |
| 635 sort_and_unique(KEEP_FIRST_OF_DUPES); |
| 636 return; |
| 637 |
| 638 case STABLE_SORT_SMART: { |
| 639 const size_type prev_size = size(); |
| 640 impl_.body_.insert(impl_.body_.end(), first, last); |
| 641 std::stable_sort(std::next(begin(), prev_size), end(), value_comp()); |
| 642 std::inplace_merge(begin(), std::next(begin(), prev_size), end(), |
| 643 value_comp()); |
| 644 erase(std::unique(begin(), end(), |
| 645 [this](const value_type& lhs, const value_type& rhs) { |
| 646 // lhs is already <= rhs due to sort, therefore |
| 647 // !(lhs < rhs) <=> lhs == rhs. |
| 648 return !value_comp()(lhs, rhs); |
| 649 }), |
| 650 end()); |
| 651 } |
| 652 |
| 653 case STABLE_SORT_SMARTER: { |
| 654 reserve(size() + std::distance(first, last)); |
| 655 auto prev_end = end(); |
| 656 std::copy_if(first, last, std::back_inserter(impl_.body_), |
| 657 [this, prev_end](const value_type& val) { |
| 658 return !std::binary_search(begin(), prev_end, val, |
| 659 value_comp()); |
| 660 }); |
| 661 |
| 662 std::stable_sort(prev_end, end(), value_comp()); |
| 663 erase(std::unique(prev_end, end(), |
| 664 [this](const value_type& lhs, const value_type& rhs) { |
| 665 // lhs is already <= rhs due to sort, therefore |
| 666 // !(lhs < rhs) <=> lhs == rhs. |
| 667 return !value_comp()(lhs, rhs); |
| 668 }), |
| 669 end()); |
| 670 |
| 671 if (prev_end != begin() && prev_end != end() && |
| 672 !value_comp()(*std::prev(prev_end), *prev_end)) { |
| 673 std::inplace_merge(begin(), prev_end, end(), value_comp()); |
| 674 } |
| 675 } |
| 676 } |
| 677 } |
| 678 |
| 679 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 606 template <class... Args> | 680 template <class... Args> |
| 607 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) | 681 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) |
| 608 -> std::pair<iterator, bool> { | 682 -> std::pair<iterator, bool> { |
| 609 return insert(value_type(std::forward<Args>(args)...)); | 683 return insert(value_type(std::forward<Args>(args)...)); |
| 610 } | 684 } |
| 611 | 685 |
| 612 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 686 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
| 613 template <class... Args> | 687 template <class... Args> |
| 614 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( | 688 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( |
| 615 const_iterator position_hint, | 689 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>& | 842 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& |
| 769 container, | 843 container, |
| 770 Predicate pred) { | 844 Predicate pred) { |
| 771 container.erase(std::remove_if(container.begin(), container.end(), pred), | 845 container.erase(std::remove_if(container.begin(), container.end(), pred), |
| 772 container.end()); | 846 container.end()); |
| 773 } | 847 } |
| 774 | 848 |
| 775 } // namespace base | 849 } // namespace base |
| 776 | 850 |
| 777 #endif // BASE_CONTAINERS_FLAT_TREE_H_ | 851 #endif // BASE_CONTAINERS_FLAT_TREE_H_ |
| OLD | NEW |