| Index: base/containers/flat_tree.h
|
| diff --git a/base/containers/flat_tree.h b/base/containers/flat_tree.h
|
| index 8e85f2377655f954c585be08bea9749edd79240c..d265d07230a857e242399d61b4bbe14f7a92a329 100644
|
| --- a/base/containers/flat_tree.h
|
| +++ b/base/containers/flat_tree.h
|
| @@ -8,6 +8,8 @@
|
| #include <algorithm>
|
| #include <vector>
|
|
|
| +#include "base/memory/ptr_util.h"
|
| +
|
| namespace base {
|
|
|
| enum FlatContainerDupes {
|
| @@ -15,6 +17,13 @@ enum FlatContainerDupes {
|
| KEEP_LAST_OF_DUPES,
|
| };
|
|
|
| +enum RangeInsertMethod {
|
| + ONE_BY_ONE,
|
| + STABLE_SORT_ALL,
|
| + STABLE_SORT_SMART,
|
| + STABLE_SORT_SMARTER,
|
| +};
|
| +
|
| namespace internal {
|
|
|
| // This algorithm is like unique() from the standard library except it
|
| @@ -200,6 +209,11 @@ class flat_tree {
|
| iterator insert(const_iterator position_hint, const value_type& x);
|
| iterator insert(const_iterator position_hint, value_type&& x);
|
|
|
| + template <class InputIterator>
|
| + void insert(InputIterator first,
|
| + InputIterator last,
|
| + RangeInsertMethod method);
|
| +
|
| template <class... Args>
|
| std::pair<iterator, bool> emplace(Args&&... args);
|
|
|
| @@ -556,7 +570,8 @@ auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::crend() const
|
| template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
|
| auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
|
| const value_type& val) -> std::pair<iterator, bool> {
|
| - auto position = lower_bound(val);
|
| + GetKeyFromValue extractor;
|
| + auto position = lower_bound(extractor(val));
|
|
|
| if (position == end() || impl_.get_value_comp()(val, *position))
|
| return {impl_.body_.insert(position, val), true};
|
| @@ -603,6 +618,67 @@ auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
|
| }
|
|
|
| template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
|
| +template <class InputIterator>
|
| +auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
|
| + InputIterator first,
|
| + InputIterator last,
|
| + RangeInsertMethod method) -> void {
|
| + switch (method) {
|
| + case ONE_BY_ONE:
|
| + for (; first != last; ++first) {
|
| + insert(*first);
|
| + }
|
| + return;
|
| +
|
| + case STABLE_SORT_ALL:
|
| + impl_.body_.insert(impl_.body_.end(), first, last);
|
| + sort_and_unique(KEEP_FIRST_OF_DUPES);
|
| + return;
|
| +
|
| + case STABLE_SORT_SMART: {
|
| + const size_type prev_size = size();
|
| + impl_.body_.insert(impl_.body_.end(), first, last);
|
| + std::stable_sort(std::next(begin(), prev_size), end(), value_comp());
|
| + std::inplace_merge(begin(), std::next(begin(), prev_size), end(),
|
| + value_comp());
|
| + erase(std::unique(begin(), end(),
|
| + [this](const value_type& lhs, const value_type& rhs) {
|
| + // lhs is already <= rhs due to sort, therefore
|
| + // !(lhs < rhs) <=> lhs == rhs.
|
| + return !value_comp()(lhs, rhs);
|
| + }),
|
| + end());
|
| + }
|
| +
|
| + case STABLE_SORT_SMARTER: {
|
| + size_type prev_size = size();
|
| + std::copy_if(first, last, std::back_inserter(impl_.body_),
|
| + [this, prev_size](const value_type& val) {
|
| + return !std::binary_search(begin(),
|
| + std::next(begin(), prev_size),
|
| + val, value_comp());
|
| + });
|
| +
|
| + iterator prev_end = begin() + prev_size;
|
| + std::stable_sort(prev_end, end(), value_comp());
|
| + erase(std::unique(prev_end, end(),
|
| + [this](const value_type& lhs, const value_type& rhs) {
|
| + // lhs is already <= rhs due to sort, therefore
|
| + // !(lhs < rhs) <=> lhs == rhs.
|
| + return !value_comp()(lhs, rhs);
|
| + }),
|
| + end());
|
| +
|
| + if (prev_end != end()) {
|
| + std::inplace_merge(
|
| + std::lower_bound(begin(), prev_end, *prev_end, value_comp()),
|
| + prev_end, end(), value_comp());
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
|
| template <class... Args>
|
| auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args)
|
| -> std::pair<iterator, bool> {
|
|
|