xref: /aosp_15_r20/external/webrtc/rtc_base/containers/flat_tree.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker // This implementation is borrowed from Chromium.
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #ifndef RTC_BASE_CONTAINERS_FLAT_TREE_H_
14*d9f75844SAndroid Build Coastguard Worker #define RTC_BASE_CONTAINERS_FLAT_TREE_H_
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
17*d9f75844SAndroid Build Coastguard Worker #include <iterator>
18*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker #include <vector>
21*d9f75844SAndroid Build Coastguard Worker 
22*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/no_unique_address.h"
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
27*d9f75844SAndroid Build Coastguard Worker // Tag type that allows skipping the sort_and_unique step when constructing a
28*d9f75844SAndroid Build Coastguard Worker // flat_tree in case the underlying container is already sorted and has no
29*d9f75844SAndroid Build Coastguard Worker // duplicate elements.
30*d9f75844SAndroid Build Coastguard Worker struct sorted_unique_t {
31*d9f75844SAndroid Build Coastguard Worker   constexpr sorted_unique_t() = default;
32*d9f75844SAndroid Build Coastguard Worker };
33*d9f75844SAndroid Build Coastguard Worker extern sorted_unique_t sorted_unique;
34*d9f75844SAndroid Build Coastguard Worker 
35*d9f75844SAndroid Build Coastguard Worker namespace flat_containers_internal {
36*d9f75844SAndroid Build Coastguard Worker 
37*d9f75844SAndroid Build Coastguard Worker // Helper functions used in RTC_DCHECKs below to make sure that inputs tagged
38*d9f75844SAndroid Build Coastguard Worker // with sorted_unique are indeed sorted and unique.
39*d9f75844SAndroid Build Coastguard Worker template <typename Range, typename Comp>
is_sorted_and_unique(const Range & range,Comp comp)40*d9f75844SAndroid Build Coastguard Worker constexpr bool is_sorted_and_unique(const Range& range, Comp comp) {
41*d9f75844SAndroid Build Coastguard Worker   // Being unique implies that there are no adjacent elements that
42*d9f75844SAndroid Build Coastguard Worker   // compare equal. So this checks that each element is strictly less
43*d9f75844SAndroid Build Coastguard Worker   // than the element after it.
44*d9f75844SAndroid Build Coastguard Worker   return absl::c_adjacent_find(range, std::not_fn(comp)) == std::end(range);
45*d9f75844SAndroid Build Coastguard Worker }
46*d9f75844SAndroid Build Coastguard Worker 
47*d9f75844SAndroid Build Coastguard Worker // This is a convenience trait inheriting from std::true_type if Iterator is at
48*d9f75844SAndroid Build Coastguard Worker // least a ForwardIterator and thus supports multiple passes over a range.
49*d9f75844SAndroid Build Coastguard Worker template <class Iterator>
50*d9f75844SAndroid Build Coastguard Worker using is_multipass =
51*d9f75844SAndroid Build Coastguard Worker     std::is_base_of<std::forward_iterator_tag,
52*d9f75844SAndroid Build Coastguard Worker                     typename std::iterator_traits<Iterator>::iterator_category>;
53*d9f75844SAndroid Build Coastguard Worker 
54*d9f75844SAndroid Build Coastguard Worker // Uses SFINAE to detect whether type has is_transparent member.
55*d9f75844SAndroid Build Coastguard Worker template <typename T, typename = void>
56*d9f75844SAndroid Build Coastguard Worker struct IsTransparentCompare : std::false_type {};
57*d9f75844SAndroid Build Coastguard Worker template <typename T>
58*d9f75844SAndroid Build Coastguard Worker struct IsTransparentCompare<T, std::void_t<typename T::is_transparent>>
59*d9f75844SAndroid Build Coastguard Worker     : std::true_type {};
60*d9f75844SAndroid Build Coastguard Worker 
61*d9f75844SAndroid Build Coastguard Worker // Helper inspired by C++20's std::to_array to convert a C-style array to a
62*d9f75844SAndroid Build Coastguard Worker // std::array. As opposed to the C++20 version this implementation does not
63*d9f75844SAndroid Build Coastguard Worker // provide an overload for rvalues and does not strip cv qualifers from the
64*d9f75844SAndroid Build Coastguard Worker // returned std::array::value_type. The returned value_type needs to be
65*d9f75844SAndroid Build Coastguard Worker // specified explicitly, allowing the construction of std::arrays with const
66*d9f75844SAndroid Build Coastguard Worker // elements.
67*d9f75844SAndroid Build Coastguard Worker //
68*d9f75844SAndroid Build Coastguard Worker // Reference: https://en.cppreference.com/w/cpp/container/array/to_array
69*d9f75844SAndroid Build Coastguard Worker template <typename U, typename T, size_t N, size_t... I>
70*d9f75844SAndroid Build Coastguard Worker constexpr std::array<U, N> ToArrayImpl(const T (&data)[N],
71*d9f75844SAndroid Build Coastguard Worker                                        std::index_sequence<I...>) {
72*d9f75844SAndroid Build Coastguard Worker   return {{data[I]...}};
73*d9f75844SAndroid Build Coastguard Worker }
74*d9f75844SAndroid Build Coastguard Worker 
75*d9f75844SAndroid Build Coastguard Worker template <typename U, typename T, size_t N>
76*d9f75844SAndroid Build Coastguard Worker constexpr std::array<U, N> ToArray(const T (&data)[N]) {
77*d9f75844SAndroid Build Coastguard Worker   return ToArrayImpl<U>(data, std::make_index_sequence<N>());
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker 
80*d9f75844SAndroid Build Coastguard Worker // std::pair's operator= is not constexpr prior to C++20. Thus we need this
81*d9f75844SAndroid Build Coastguard Worker // small helper to invoke operator= on the .first and .second member explicitly.
82*d9f75844SAndroid Build Coastguard Worker template <typename T>
83*d9f75844SAndroid Build Coastguard Worker constexpr void Assign(T& lhs, T&& rhs) {
84*d9f75844SAndroid Build Coastguard Worker   lhs = std::move(rhs);
85*d9f75844SAndroid Build Coastguard Worker }
86*d9f75844SAndroid Build Coastguard Worker 
87*d9f75844SAndroid Build Coastguard Worker template <typename T, typename U>
88*d9f75844SAndroid Build Coastguard Worker constexpr void Assign(std::pair<T, U>& lhs, std::pair<T, U>&& rhs) {
89*d9f75844SAndroid Build Coastguard Worker   Assign(lhs.first, std::move(rhs.first));
90*d9f75844SAndroid Build Coastguard Worker   Assign(lhs.second, std::move(rhs.second));
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker 
93*d9f75844SAndroid Build Coastguard Worker // constexpr swap implementation. std::swap is not constexpr prior to C++20.
94*d9f75844SAndroid Build Coastguard Worker template <typename T>
95*d9f75844SAndroid Build Coastguard Worker constexpr void Swap(T& lhs, T& rhs) {
96*d9f75844SAndroid Build Coastguard Worker   T tmp = std::move(lhs);
97*d9f75844SAndroid Build Coastguard Worker   Assign(lhs, std::move(rhs));
98*d9f75844SAndroid Build Coastguard Worker   Assign(rhs, std::move(tmp));
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker 
101*d9f75844SAndroid Build Coastguard Worker // constexpr prev implementation. std::prev is not constexpr prior to C++17.
102*d9f75844SAndroid Build Coastguard Worker template <typename BidirIt>
103*d9f75844SAndroid Build Coastguard Worker constexpr BidirIt Prev(BidirIt it) {
104*d9f75844SAndroid Build Coastguard Worker   return --it;
105*d9f75844SAndroid Build Coastguard Worker }
106*d9f75844SAndroid Build Coastguard Worker 
107*d9f75844SAndroid Build Coastguard Worker // constexpr next implementation. std::next is not constexpr prior to C++17.
108*d9f75844SAndroid Build Coastguard Worker template <typename InputIt>
109*d9f75844SAndroid Build Coastguard Worker constexpr InputIt Next(InputIt it) {
110*d9f75844SAndroid Build Coastguard Worker   return ++it;
111*d9f75844SAndroid Build Coastguard Worker }
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker // constexpr sort implementation. std::sort is not constexpr prior to C++20.
114*d9f75844SAndroid Build Coastguard Worker // While insertion sort has a quadratic worst case complexity, it was chosen
115*d9f75844SAndroid Build Coastguard Worker // because it has linear complexity for nearly sorted data, is stable, and
116*d9f75844SAndroid Build Coastguard Worker // simple to implement.
117*d9f75844SAndroid Build Coastguard Worker template <typename BidirIt, typename Compare>
118*d9f75844SAndroid Build Coastguard Worker constexpr void InsertionSort(BidirIt first, BidirIt last, const Compare& comp) {
119*d9f75844SAndroid Build Coastguard Worker   if (first == last)
120*d9f75844SAndroid Build Coastguard Worker     return;
121*d9f75844SAndroid Build Coastguard Worker 
122*d9f75844SAndroid Build Coastguard Worker   for (auto it = Next(first); it != last; ++it) {
123*d9f75844SAndroid Build Coastguard Worker     for (auto curr = it; curr != first && comp(*curr, *Prev(curr)); --curr)
124*d9f75844SAndroid Build Coastguard Worker       Swap(*curr, *Prev(curr));
125*d9f75844SAndroid Build Coastguard Worker   }
126*d9f75844SAndroid Build Coastguard Worker }
127*d9f75844SAndroid Build Coastguard Worker 
128*d9f75844SAndroid Build Coastguard Worker // Implementation -------------------------------------------------------------
129*d9f75844SAndroid Build Coastguard Worker 
130*d9f75844SAndroid Build Coastguard Worker // Implementation for the sorted associative flat_set and flat_map using a
131*d9f75844SAndroid Build Coastguard Worker // sorted vector as the backing store. Do not use directly.
132*d9f75844SAndroid Build Coastguard Worker //
133*d9f75844SAndroid Build Coastguard Worker // The use of "value" in this is like std::map uses, meaning it's the thing
134*d9f75844SAndroid Build Coastguard Worker // contained (in the case of map it's a <Kay, Mapped> pair). The Key is how
135*d9f75844SAndroid Build Coastguard Worker // things are looked up. In the case of a set, Key == Value. In the case of
136*d9f75844SAndroid Build Coastguard Worker // a map, the Key is a component of a Value.
137*d9f75844SAndroid Build Coastguard Worker //
138*d9f75844SAndroid Build Coastguard Worker // The helper class GetKeyFromValue provides the means to extract a key from a
139*d9f75844SAndroid Build Coastguard Worker // value for comparison purposes. It should implement:
140*d9f75844SAndroid Build Coastguard Worker //   const Key& operator()(const Value&).
141*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
142*d9f75844SAndroid Build Coastguard Worker class flat_tree {
143*d9f75844SAndroid Build Coastguard Worker  public:
144*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
145*d9f75844SAndroid Build Coastguard Worker   // Types.
146*d9f75844SAndroid Build Coastguard Worker   //
147*d9f75844SAndroid Build Coastguard Worker   using key_type = Key;
148*d9f75844SAndroid Build Coastguard Worker   using key_compare = KeyCompare;
149*d9f75844SAndroid Build Coastguard Worker   using value_type = typename Container::value_type;
150*d9f75844SAndroid Build Coastguard Worker 
151*d9f75844SAndroid Build Coastguard Worker   // Wraps the templated key comparison to compare values.
152*d9f75844SAndroid Build Coastguard Worker   struct value_compare {
153*d9f75844SAndroid Build Coastguard Worker     constexpr bool operator()(const value_type& left,
154*d9f75844SAndroid Build Coastguard Worker                               const value_type& right) const {
155*d9f75844SAndroid Build Coastguard Worker       GetKeyFromValue extractor;
156*d9f75844SAndroid Build Coastguard Worker       return comp(extractor(left), extractor(right));
157*d9f75844SAndroid Build Coastguard Worker     }
158*d9f75844SAndroid Build Coastguard Worker 
159*d9f75844SAndroid Build Coastguard Worker     RTC_NO_UNIQUE_ADDRESS key_compare comp;
160*d9f75844SAndroid Build Coastguard Worker   };
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker   using pointer = typename Container::pointer;
163*d9f75844SAndroid Build Coastguard Worker   using const_pointer = typename Container::const_pointer;
164*d9f75844SAndroid Build Coastguard Worker   using reference = typename Container::reference;
165*d9f75844SAndroid Build Coastguard Worker   using const_reference = typename Container::const_reference;
166*d9f75844SAndroid Build Coastguard Worker   using size_type = typename Container::size_type;
167*d9f75844SAndroid Build Coastguard Worker   using difference_type = typename Container::difference_type;
168*d9f75844SAndroid Build Coastguard Worker   using iterator = typename Container::iterator;
169*d9f75844SAndroid Build Coastguard Worker   using const_iterator = typename Container::const_iterator;
170*d9f75844SAndroid Build Coastguard Worker   using reverse_iterator = typename Container::reverse_iterator;
171*d9f75844SAndroid Build Coastguard Worker   using const_reverse_iterator = typename Container::const_reverse_iterator;
172*d9f75844SAndroid Build Coastguard Worker   using container_type = Container;
173*d9f75844SAndroid Build Coastguard Worker 
174*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
175*d9f75844SAndroid Build Coastguard Worker   // Lifetime.
176*d9f75844SAndroid Build Coastguard Worker   //
177*d9f75844SAndroid Build Coastguard Worker   // Constructors that take range guarantee O(N * log^2(N)) + O(N) complexity
178*d9f75844SAndroid Build Coastguard Worker   // and take O(N * log(N)) + O(N) if extra memory is available (N is a range
179*d9f75844SAndroid Build Coastguard Worker   // length).
180*d9f75844SAndroid Build Coastguard Worker   //
181*d9f75844SAndroid Build Coastguard Worker   // Assume that move constructors invalidate iterators and references.
182*d9f75844SAndroid Build Coastguard Worker   //
183*d9f75844SAndroid Build Coastguard Worker   // The constructors that take ranges, lists, and vectors do not require that
184*d9f75844SAndroid Build Coastguard Worker   // the input be sorted.
185*d9f75844SAndroid Build Coastguard Worker   //
186*d9f75844SAndroid Build Coastguard Worker   // When passing the webrtc::sorted_unique tag as the first argument no sort
187*d9f75844SAndroid Build Coastguard Worker   // and unique step takes places. This is useful if the underlying container
188*d9f75844SAndroid Build Coastguard Worker   // already has the required properties.
189*d9f75844SAndroid Build Coastguard Worker 
190*d9f75844SAndroid Build Coastguard Worker   flat_tree() = default;
191*d9f75844SAndroid Build Coastguard Worker   flat_tree(const flat_tree&) = default;
192*d9f75844SAndroid Build Coastguard Worker   flat_tree(flat_tree&&) = default;
193*d9f75844SAndroid Build Coastguard Worker 
194*d9f75844SAndroid Build Coastguard Worker   explicit flat_tree(const key_compare& comp);
195*d9f75844SAndroid Build Coastguard Worker 
196*d9f75844SAndroid Build Coastguard Worker   template <class InputIterator>
197*d9f75844SAndroid Build Coastguard Worker   flat_tree(InputIterator first,
198*d9f75844SAndroid Build Coastguard Worker             InputIterator last,
199*d9f75844SAndroid Build Coastguard Worker             const key_compare& comp = key_compare());
200*d9f75844SAndroid Build Coastguard Worker 
201*d9f75844SAndroid Build Coastguard Worker   flat_tree(const container_type& items,
202*d9f75844SAndroid Build Coastguard Worker             const key_compare& comp = key_compare());
203*d9f75844SAndroid Build Coastguard Worker 
204*d9f75844SAndroid Build Coastguard Worker   explicit flat_tree(container_type&& items,
205*d9f75844SAndroid Build Coastguard Worker                      const key_compare& comp = key_compare());
206*d9f75844SAndroid Build Coastguard Worker 
207*d9f75844SAndroid Build Coastguard Worker   flat_tree(std::initializer_list<value_type> ilist,
208*d9f75844SAndroid Build Coastguard Worker             const key_compare& comp = key_compare());
209*d9f75844SAndroid Build Coastguard Worker 
210*d9f75844SAndroid Build Coastguard Worker   template <class InputIterator>
211*d9f75844SAndroid Build Coastguard Worker   flat_tree(sorted_unique_t,
212*d9f75844SAndroid Build Coastguard Worker             InputIterator first,
213*d9f75844SAndroid Build Coastguard Worker             InputIterator last,
214*d9f75844SAndroid Build Coastguard Worker             const key_compare& comp = key_compare());
215*d9f75844SAndroid Build Coastguard Worker 
216*d9f75844SAndroid Build Coastguard Worker   flat_tree(sorted_unique_t,
217*d9f75844SAndroid Build Coastguard Worker             const container_type& items,
218*d9f75844SAndroid Build Coastguard Worker             const key_compare& comp = key_compare());
219*d9f75844SAndroid Build Coastguard Worker 
220*d9f75844SAndroid Build Coastguard Worker   constexpr flat_tree(sorted_unique_t,
221*d9f75844SAndroid Build Coastguard Worker                       container_type&& items,
222*d9f75844SAndroid Build Coastguard Worker                       const key_compare& comp = key_compare());
223*d9f75844SAndroid Build Coastguard Worker 
224*d9f75844SAndroid Build Coastguard Worker   flat_tree(sorted_unique_t,
225*d9f75844SAndroid Build Coastguard Worker             std::initializer_list<value_type> ilist,
226*d9f75844SAndroid Build Coastguard Worker             const key_compare& comp = key_compare());
227*d9f75844SAndroid Build Coastguard Worker 
228*d9f75844SAndroid Build Coastguard Worker   ~flat_tree() = default;
229*d9f75844SAndroid Build Coastguard Worker 
230*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
231*d9f75844SAndroid Build Coastguard Worker   // Assignments.
232*d9f75844SAndroid Build Coastguard Worker   //
233*d9f75844SAndroid Build Coastguard Worker   // Assume that move assignment invalidates iterators and references.
234*d9f75844SAndroid Build Coastguard Worker 
235*d9f75844SAndroid Build Coastguard Worker   flat_tree& operator=(const flat_tree&) = default;
236*d9f75844SAndroid Build Coastguard Worker   flat_tree& operator=(flat_tree&&) = default;
237*d9f75844SAndroid Build Coastguard Worker   // Takes the first if there are duplicates in the initializer list.
238*d9f75844SAndroid Build Coastguard Worker   flat_tree& operator=(std::initializer_list<value_type> ilist);
239*d9f75844SAndroid Build Coastguard Worker 
240*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
241*d9f75844SAndroid Build Coastguard Worker   // Memory management.
242*d9f75844SAndroid Build Coastguard Worker   //
243*d9f75844SAndroid Build Coastguard Worker   // Beware that shrink_to_fit() simply forwards the request to the
244*d9f75844SAndroid Build Coastguard Worker   // container_type and its implementation is free to optimize otherwise and
245*d9f75844SAndroid Build Coastguard Worker   // leave capacity() to be greater that its size.
246*d9f75844SAndroid Build Coastguard Worker   //
247*d9f75844SAndroid Build Coastguard Worker   // reserve() and shrink_to_fit() invalidate iterators and references.
248*d9f75844SAndroid Build Coastguard Worker 
249*d9f75844SAndroid Build Coastguard Worker   void reserve(size_type new_capacity);
250*d9f75844SAndroid Build Coastguard Worker   size_type capacity() const;
251*d9f75844SAndroid Build Coastguard Worker   void shrink_to_fit();
252*d9f75844SAndroid Build Coastguard Worker 
253*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
254*d9f75844SAndroid Build Coastguard Worker   // Size management.
255*d9f75844SAndroid Build Coastguard Worker   //
256*d9f75844SAndroid Build Coastguard Worker   // clear() leaves the capacity() of the flat_tree unchanged.
257*d9f75844SAndroid Build Coastguard Worker 
258*d9f75844SAndroid Build Coastguard Worker   void clear();
259*d9f75844SAndroid Build Coastguard Worker 
260*d9f75844SAndroid Build Coastguard Worker   constexpr size_type size() const;
261*d9f75844SAndroid Build Coastguard Worker   constexpr size_type max_size() const;
262*d9f75844SAndroid Build Coastguard Worker   constexpr bool empty() const;
263*d9f75844SAndroid Build Coastguard Worker 
264*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
265*d9f75844SAndroid Build Coastguard Worker   // Iterators.
266*d9f75844SAndroid Build Coastguard Worker   //
267*d9f75844SAndroid Build Coastguard Worker   // Iterators follow the ordering defined by the key comparator used in
268*d9f75844SAndroid Build Coastguard Worker   // construction of the flat_tree.
269*d9f75844SAndroid Build Coastguard Worker 
270*d9f75844SAndroid Build Coastguard Worker   iterator begin();
271*d9f75844SAndroid Build Coastguard Worker   constexpr const_iterator begin() const;
272*d9f75844SAndroid Build Coastguard Worker   const_iterator cbegin() const;
273*d9f75844SAndroid Build Coastguard Worker 
274*d9f75844SAndroid Build Coastguard Worker   iterator end();
275*d9f75844SAndroid Build Coastguard Worker   constexpr const_iterator end() const;
276*d9f75844SAndroid Build Coastguard Worker   const_iterator cend() const;
277*d9f75844SAndroid Build Coastguard Worker 
278*d9f75844SAndroid Build Coastguard Worker   reverse_iterator rbegin();
279*d9f75844SAndroid Build Coastguard Worker   const_reverse_iterator rbegin() const;
280*d9f75844SAndroid Build Coastguard Worker   const_reverse_iterator crbegin() const;
281*d9f75844SAndroid Build Coastguard Worker 
282*d9f75844SAndroid Build Coastguard Worker   reverse_iterator rend();
283*d9f75844SAndroid Build Coastguard Worker   const_reverse_iterator rend() const;
284*d9f75844SAndroid Build Coastguard Worker   const_reverse_iterator crend() const;
285*d9f75844SAndroid Build Coastguard Worker 
286*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
287*d9f75844SAndroid Build Coastguard Worker   // Insert operations.
288*d9f75844SAndroid Build Coastguard Worker   //
289*d9f75844SAndroid Build Coastguard Worker   // Assume that every operation invalidates iterators and references.
290*d9f75844SAndroid Build Coastguard Worker   // Insertion of one element can take O(size). Capacity of flat_tree grows in
291*d9f75844SAndroid Build Coastguard Worker   // an implementation-defined manner.
292*d9f75844SAndroid Build Coastguard Worker   //
293*d9f75844SAndroid Build Coastguard Worker   // NOTE: Prefer to build a new flat_tree from a std::vector (or similar)
294*d9f75844SAndroid Build Coastguard Worker   // instead of calling insert() repeatedly.
295*d9f75844SAndroid Build Coastguard Worker 
296*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> insert(const value_type& val);
297*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> insert(value_type&& val);
298*d9f75844SAndroid Build Coastguard Worker 
299*d9f75844SAndroid Build Coastguard Worker   iterator insert(const_iterator position_hint, const value_type& x);
300*d9f75844SAndroid Build Coastguard Worker   iterator insert(const_iterator position_hint, value_type&& x);
301*d9f75844SAndroid Build Coastguard Worker 
302*d9f75844SAndroid Build Coastguard Worker   // This method inserts the values from the range [first, last) into the
303*d9f75844SAndroid Build Coastguard Worker   // current tree.
304*d9f75844SAndroid Build Coastguard Worker   template <class InputIterator>
305*d9f75844SAndroid Build Coastguard Worker   void insert(InputIterator first, InputIterator last);
306*d9f75844SAndroid Build Coastguard Worker 
307*d9f75844SAndroid Build Coastguard Worker   template <class... Args>
308*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> emplace(Args&&... args);
309*d9f75844SAndroid Build Coastguard Worker 
310*d9f75844SAndroid Build Coastguard Worker   template <class... Args>
311*d9f75844SAndroid Build Coastguard Worker   iterator emplace_hint(const_iterator position_hint, Args&&... args);
312*d9f75844SAndroid Build Coastguard Worker 
313*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
314*d9f75844SAndroid Build Coastguard Worker   // Underlying type operations.
315*d9f75844SAndroid Build Coastguard Worker   //
316*d9f75844SAndroid Build Coastguard Worker   // Assume that either operation invalidates iterators and references.
317*d9f75844SAndroid Build Coastguard Worker 
318*d9f75844SAndroid Build Coastguard Worker   // Extracts the container_type and returns it to the caller. Ensures that
319*d9f75844SAndroid Build Coastguard Worker   // `this` is `empty()` afterwards.
320*d9f75844SAndroid Build Coastguard Worker   container_type extract() &&;
321*d9f75844SAndroid Build Coastguard Worker 
322*d9f75844SAndroid Build Coastguard Worker   // Replaces the container_type with `body`. Expects that `body` is sorted
323*d9f75844SAndroid Build Coastguard Worker   // and has no repeated elements with regard to value_comp().
324*d9f75844SAndroid Build Coastguard Worker   void replace(container_type&& body);
325*d9f75844SAndroid Build Coastguard Worker 
326*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
327*d9f75844SAndroid Build Coastguard Worker   // Erase operations.
328*d9f75844SAndroid Build Coastguard Worker   //
329*d9f75844SAndroid Build Coastguard Worker   // Assume that every operation invalidates iterators and references.
330*d9f75844SAndroid Build Coastguard Worker   //
331*d9f75844SAndroid Build Coastguard Worker   // erase(position), erase(first, last) can take O(size).
332*d9f75844SAndroid Build Coastguard Worker   // erase(key) may take O(size) + O(log(size)).
333*d9f75844SAndroid Build Coastguard Worker   //
334*d9f75844SAndroid Build Coastguard Worker   // Prefer webrtc::EraseIf() or some other variation on erase(remove(), end())
335*d9f75844SAndroid Build Coastguard Worker   // idiom when deleting multiple non-consecutive elements.
336*d9f75844SAndroid Build Coastguard Worker 
337*d9f75844SAndroid Build Coastguard Worker   iterator erase(iterator position);
338*d9f75844SAndroid Build Coastguard Worker   // Artificially templatized to break ambiguity if `iterator` and
339*d9f75844SAndroid Build Coastguard Worker   // `const_iterator` are the same type.
340*d9f75844SAndroid Build Coastguard Worker   template <typename DummyT = void>
341*d9f75844SAndroid Build Coastguard Worker   iterator erase(const_iterator position);
342*d9f75844SAndroid Build Coastguard Worker   iterator erase(const_iterator first, const_iterator last);
343*d9f75844SAndroid Build Coastguard Worker   template <typename K>
344*d9f75844SAndroid Build Coastguard Worker   size_type erase(const K& key);
345*d9f75844SAndroid Build Coastguard Worker 
346*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
347*d9f75844SAndroid Build Coastguard Worker   // Comparators.
348*d9f75844SAndroid Build Coastguard Worker 
349*d9f75844SAndroid Build Coastguard Worker   constexpr key_compare key_comp() const;
350*d9f75844SAndroid Build Coastguard Worker   constexpr value_compare value_comp() const;
351*d9f75844SAndroid Build Coastguard Worker 
352*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
353*d9f75844SAndroid Build Coastguard Worker   // Search operations.
354*d9f75844SAndroid Build Coastguard Worker   //
355*d9f75844SAndroid Build Coastguard Worker   // Search operations have O(log(size)) complexity.
356*d9f75844SAndroid Build Coastguard Worker 
357*d9f75844SAndroid Build Coastguard Worker   template <typename K>
358*d9f75844SAndroid Build Coastguard Worker   size_type count(const K& key) const;
359*d9f75844SAndroid Build Coastguard Worker 
360*d9f75844SAndroid Build Coastguard Worker   template <typename K>
361*d9f75844SAndroid Build Coastguard Worker   iterator find(const K& key);
362*d9f75844SAndroid Build Coastguard Worker 
363*d9f75844SAndroid Build Coastguard Worker   template <typename K>
364*d9f75844SAndroid Build Coastguard Worker   const_iterator find(const K& key) const;
365*d9f75844SAndroid Build Coastguard Worker 
366*d9f75844SAndroid Build Coastguard Worker   template <typename K>
367*d9f75844SAndroid Build Coastguard Worker   bool contains(const K& key) const;
368*d9f75844SAndroid Build Coastguard Worker 
369*d9f75844SAndroid Build Coastguard Worker   template <typename K>
370*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, iterator> equal_range(const K& key);
371*d9f75844SAndroid Build Coastguard Worker 
372*d9f75844SAndroid Build Coastguard Worker   template <typename K>
373*d9f75844SAndroid Build Coastguard Worker   std::pair<const_iterator, const_iterator> equal_range(const K& key) const;
374*d9f75844SAndroid Build Coastguard Worker 
375*d9f75844SAndroid Build Coastguard Worker   template <typename K>
376*d9f75844SAndroid Build Coastguard Worker   iterator lower_bound(const K& key);
377*d9f75844SAndroid Build Coastguard Worker 
378*d9f75844SAndroid Build Coastguard Worker   template <typename K>
379*d9f75844SAndroid Build Coastguard Worker   const_iterator lower_bound(const K& key) const;
380*d9f75844SAndroid Build Coastguard Worker 
381*d9f75844SAndroid Build Coastguard Worker   template <typename K>
382*d9f75844SAndroid Build Coastguard Worker   iterator upper_bound(const K& key);
383*d9f75844SAndroid Build Coastguard Worker 
384*d9f75844SAndroid Build Coastguard Worker   template <typename K>
385*d9f75844SAndroid Build Coastguard Worker   const_iterator upper_bound(const K& key) const;
386*d9f75844SAndroid Build Coastguard Worker 
387*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
388*d9f75844SAndroid Build Coastguard Worker   // General operations.
389*d9f75844SAndroid Build Coastguard Worker   //
390*d9f75844SAndroid Build Coastguard Worker   // Assume that swap invalidates iterators and references.
391*d9f75844SAndroid Build Coastguard Worker   //
392*d9f75844SAndroid Build Coastguard Worker   // Implementation note: currently we use operator==() and operator<() on
393*d9f75844SAndroid Build Coastguard Worker   // std::vector, because they have the same contract we need, so we use them
394*d9f75844SAndroid Build Coastguard Worker   // directly for brevity and in case it is more optimal than calling equal()
395*d9f75844SAndroid Build Coastguard Worker   // and lexicograhpical_compare(). If the underlying container type is changed,
396*d9f75844SAndroid Build Coastguard Worker   // this code may need to be modified.
397*d9f75844SAndroid Build Coastguard Worker 
398*d9f75844SAndroid Build Coastguard Worker   void swap(flat_tree& other) noexcept;
399*d9f75844SAndroid Build Coastguard Worker 
400*d9f75844SAndroid Build Coastguard Worker   friend bool operator==(const flat_tree& lhs, const flat_tree& rhs) {
401*d9f75844SAndroid Build Coastguard Worker     return lhs.body_ == rhs.body_;
402*d9f75844SAndroid Build Coastguard Worker   }
403*d9f75844SAndroid Build Coastguard Worker 
404*d9f75844SAndroid Build Coastguard Worker   friend bool operator!=(const flat_tree& lhs, const flat_tree& rhs) {
405*d9f75844SAndroid Build Coastguard Worker     return !(lhs == rhs);
406*d9f75844SAndroid Build Coastguard Worker   }
407*d9f75844SAndroid Build Coastguard Worker 
408*d9f75844SAndroid Build Coastguard Worker   friend bool operator<(const flat_tree& lhs, const flat_tree& rhs) {
409*d9f75844SAndroid Build Coastguard Worker     return lhs.body_ < rhs.body_;
410*d9f75844SAndroid Build Coastguard Worker   }
411*d9f75844SAndroid Build Coastguard Worker 
412*d9f75844SAndroid Build Coastguard Worker   friend bool operator>(const flat_tree& lhs, const flat_tree& rhs) {
413*d9f75844SAndroid Build Coastguard Worker     return rhs < lhs;
414*d9f75844SAndroid Build Coastguard Worker   }
415*d9f75844SAndroid Build Coastguard Worker 
416*d9f75844SAndroid Build Coastguard Worker   friend bool operator>=(const flat_tree& lhs, const flat_tree& rhs) {
417*d9f75844SAndroid Build Coastguard Worker     return !(lhs < rhs);
418*d9f75844SAndroid Build Coastguard Worker   }
419*d9f75844SAndroid Build Coastguard Worker 
420*d9f75844SAndroid Build Coastguard Worker   friend bool operator<=(const flat_tree& lhs, const flat_tree& rhs) {
421*d9f75844SAndroid Build Coastguard Worker     return !(lhs > rhs);
422*d9f75844SAndroid Build Coastguard Worker   }
423*d9f75844SAndroid Build Coastguard Worker 
424*d9f75844SAndroid Build Coastguard Worker   friend void swap(flat_tree& lhs, flat_tree& rhs) noexcept { lhs.swap(rhs); }
425*d9f75844SAndroid Build Coastguard Worker 
426*d9f75844SAndroid Build Coastguard Worker  protected:
427*d9f75844SAndroid Build Coastguard Worker   // Emplaces a new item into the tree that is known not to be in it. This
428*d9f75844SAndroid Build Coastguard Worker   // is for implementing map operator[].
429*d9f75844SAndroid Build Coastguard Worker   template <class... Args>
430*d9f75844SAndroid Build Coastguard Worker   iterator unsafe_emplace(const_iterator position, Args&&... args);
431*d9f75844SAndroid Build Coastguard Worker 
432*d9f75844SAndroid Build Coastguard Worker   // Attempts to emplace a new element with key `key`. Only if `key` is not yet
433*d9f75844SAndroid Build Coastguard Worker   // present, construct value_type from `args` and insert it. Returns an
434*d9f75844SAndroid Build Coastguard Worker   // iterator to the element with key `key` and a bool indicating whether an
435*d9f75844SAndroid Build Coastguard Worker   // insertion happened.
436*d9f75844SAndroid Build Coastguard Worker   template <class K, class... Args>
437*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> emplace_key_args(const K& key, Args&&... args);
438*d9f75844SAndroid Build Coastguard Worker 
439*d9f75844SAndroid Build Coastguard Worker   // Similar to `emplace_key_args`, but checks `hint` first as a possible
440*d9f75844SAndroid Build Coastguard Worker   // insertion position.
441*d9f75844SAndroid Build Coastguard Worker   template <class K, class... Args>
442*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> emplace_hint_key_args(const_iterator hint,
443*d9f75844SAndroid Build Coastguard Worker                                                   const K& key,
444*d9f75844SAndroid Build Coastguard Worker                                                   Args&&... args);
445*d9f75844SAndroid Build Coastguard Worker 
446*d9f75844SAndroid Build Coastguard Worker  private:
447*d9f75844SAndroid Build Coastguard Worker   // Helper class for e.g. lower_bound that can compare a value on the left
448*d9f75844SAndroid Build Coastguard Worker   // to a key on the right.
449*d9f75844SAndroid Build Coastguard Worker   struct KeyValueCompare {
450*d9f75844SAndroid Build Coastguard Worker     // The key comparison object must outlive this class.
451*d9f75844SAndroid Build Coastguard Worker     explicit KeyValueCompare(const key_compare& comp) : comp_(comp) {}
452*d9f75844SAndroid Build Coastguard Worker 
453*d9f75844SAndroid Build Coastguard Worker     template <typename T, typename U>
454*d9f75844SAndroid Build Coastguard Worker     bool operator()(const T& lhs, const U& rhs) const {
455*d9f75844SAndroid Build Coastguard Worker       return comp_(extract_if_value_type(lhs), extract_if_value_type(rhs));
456*d9f75844SAndroid Build Coastguard Worker     }
457*d9f75844SAndroid Build Coastguard Worker 
458*d9f75844SAndroid Build Coastguard Worker    private:
459*d9f75844SAndroid Build Coastguard Worker     const key_type& extract_if_value_type(const value_type& v) const {
460*d9f75844SAndroid Build Coastguard Worker       GetKeyFromValue extractor;
461*d9f75844SAndroid Build Coastguard Worker       return extractor(v);
462*d9f75844SAndroid Build Coastguard Worker     }
463*d9f75844SAndroid Build Coastguard Worker 
464*d9f75844SAndroid Build Coastguard Worker     template <typename K>
465*d9f75844SAndroid Build Coastguard Worker     const K& extract_if_value_type(const K& k) const {
466*d9f75844SAndroid Build Coastguard Worker       return k;
467*d9f75844SAndroid Build Coastguard Worker     }
468*d9f75844SAndroid Build Coastguard Worker 
469*d9f75844SAndroid Build Coastguard Worker     const key_compare& comp_;
470*d9f75844SAndroid Build Coastguard Worker   };
471*d9f75844SAndroid Build Coastguard Worker 
472*d9f75844SAndroid Build Coastguard Worker   iterator const_cast_it(const_iterator c_it) {
473*d9f75844SAndroid Build Coastguard Worker     auto distance = std::distance(cbegin(), c_it);
474*d9f75844SAndroid Build Coastguard Worker     return std::next(begin(), distance);
475*d9f75844SAndroid Build Coastguard Worker   }
476*d9f75844SAndroid Build Coastguard Worker 
477*d9f75844SAndroid Build Coastguard Worker   // This method is inspired by both std::map::insert(P&&) and
478*d9f75844SAndroid Build Coastguard Worker   // std::map::insert_or_assign(const K&, V&&). It inserts val if an equivalent
479*d9f75844SAndroid Build Coastguard Worker   // element is not present yet, otherwise it overwrites. It returns an iterator
480*d9f75844SAndroid Build Coastguard Worker   // to the modified element and a flag indicating whether insertion or
481*d9f75844SAndroid Build Coastguard Worker   // assignment happened.
482*d9f75844SAndroid Build Coastguard Worker   template <class V>
483*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> insert_or_assign(V&& val) {
484*d9f75844SAndroid Build Coastguard Worker     auto position = lower_bound(GetKeyFromValue()(val));
485*d9f75844SAndroid Build Coastguard Worker 
486*d9f75844SAndroid Build Coastguard Worker     if (position == end() || value_comp()(val, *position))
487*d9f75844SAndroid Build Coastguard Worker       return {body_.emplace(position, std::forward<V>(val)), true};
488*d9f75844SAndroid Build Coastguard Worker 
489*d9f75844SAndroid Build Coastguard Worker     *position = std::forward<V>(val);
490*d9f75844SAndroid Build Coastguard Worker     return {position, false};
491*d9f75844SAndroid Build Coastguard Worker   }
492*d9f75844SAndroid Build Coastguard Worker 
493*d9f75844SAndroid Build Coastguard Worker   // This method is similar to insert_or_assign, with the following differences:
494*d9f75844SAndroid Build Coastguard Worker   // - Instead of searching [begin(), end()) it only searches [first, last).
495*d9f75844SAndroid Build Coastguard Worker   // - In case no equivalent element is found, val is appended to the end of the
496*d9f75844SAndroid Build Coastguard Worker   //   underlying body and an iterator to the next bigger element in [first,
497*d9f75844SAndroid Build Coastguard Worker   //   last) is returned.
498*d9f75844SAndroid Build Coastguard Worker   template <class V>
499*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> append_or_assign(iterator first,
500*d9f75844SAndroid Build Coastguard Worker                                              iterator last,
501*d9f75844SAndroid Build Coastguard Worker                                              V&& val) {
502*d9f75844SAndroid Build Coastguard Worker     auto position = std::lower_bound(first, last, val, value_comp());
503*d9f75844SAndroid Build Coastguard Worker 
504*d9f75844SAndroid Build Coastguard Worker     if (position == last || value_comp()(val, *position)) {
505*d9f75844SAndroid Build Coastguard Worker       // emplace_back might invalidate position, which is why distance needs to
506*d9f75844SAndroid Build Coastguard Worker       // be cached.
507*d9f75844SAndroid Build Coastguard Worker       const difference_type distance = std::distance(begin(), position);
508*d9f75844SAndroid Build Coastguard Worker       body_.emplace_back(std::forward<V>(val));
509*d9f75844SAndroid Build Coastguard Worker       return {std::next(begin(), distance), true};
510*d9f75844SAndroid Build Coastguard Worker     }
511*d9f75844SAndroid Build Coastguard Worker 
512*d9f75844SAndroid Build Coastguard Worker     *position = std::forward<V>(val);
513*d9f75844SAndroid Build Coastguard Worker     return {position, false};
514*d9f75844SAndroid Build Coastguard Worker   }
515*d9f75844SAndroid Build Coastguard Worker 
516*d9f75844SAndroid Build Coastguard Worker   // This method is similar to insert, with the following differences:
517*d9f75844SAndroid Build Coastguard Worker   // - Instead of searching [begin(), end()) it only searches [first, last).
518*d9f75844SAndroid Build Coastguard Worker   // - In case no equivalent element is found, val is appended to the end of the
519*d9f75844SAndroid Build Coastguard Worker   //   underlying body and an iterator to the next bigger element in [first,
520*d9f75844SAndroid Build Coastguard Worker   //   last) is returned.
521*d9f75844SAndroid Build Coastguard Worker   template <class V>
522*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> append_unique(iterator first,
523*d9f75844SAndroid Build Coastguard Worker                                           iterator last,
524*d9f75844SAndroid Build Coastguard Worker                                           V&& val) {
525*d9f75844SAndroid Build Coastguard Worker     auto position = std::lower_bound(first, last, val, value_comp());
526*d9f75844SAndroid Build Coastguard Worker 
527*d9f75844SAndroid Build Coastguard Worker     if (position == last || value_comp()(val, *position)) {
528*d9f75844SAndroid Build Coastguard Worker       // emplace_back might invalidate position, which is why distance needs to
529*d9f75844SAndroid Build Coastguard Worker       // be cached.
530*d9f75844SAndroid Build Coastguard Worker       const difference_type distance = std::distance(begin(), position);
531*d9f75844SAndroid Build Coastguard Worker       body_.emplace_back(std::forward<V>(val));
532*d9f75844SAndroid Build Coastguard Worker       return {std::next(begin(), distance), true};
533*d9f75844SAndroid Build Coastguard Worker     }
534*d9f75844SAndroid Build Coastguard Worker 
535*d9f75844SAndroid Build Coastguard Worker     return {position, false};
536*d9f75844SAndroid Build Coastguard Worker   }
537*d9f75844SAndroid Build Coastguard Worker 
538*d9f75844SAndroid Build Coastguard Worker   void sort_and_unique(iterator first, iterator last) {
539*d9f75844SAndroid Build Coastguard Worker     // Preserve stability for the unique code below.
540*d9f75844SAndroid Build Coastguard Worker     std::stable_sort(first, last, value_comp());
541*d9f75844SAndroid Build Coastguard Worker 
542*d9f75844SAndroid Build Coastguard Worker     // lhs is already <= rhs due to sort, therefore !(lhs < rhs) <=> lhs == rhs.
543*d9f75844SAndroid Build Coastguard Worker     auto equal_comp = std::not_fn(value_comp());
544*d9f75844SAndroid Build Coastguard Worker     erase(std::unique(first, last, equal_comp), last);
545*d9f75844SAndroid Build Coastguard Worker   }
546*d9f75844SAndroid Build Coastguard Worker 
547*d9f75844SAndroid Build Coastguard Worker   void sort_and_unique() { sort_and_unique(begin(), end()); }
548*d9f75844SAndroid Build Coastguard Worker 
549*d9f75844SAndroid Build Coastguard Worker   // To support comparators that may not be possible to default-construct, we
550*d9f75844SAndroid Build Coastguard Worker   // have to store an instance of Compare. Since Compare commonly is stateless,
551*d9f75844SAndroid Build Coastguard Worker   // we use the RTC_NO_UNIQUE_ADDRESS attribute to save space.
552*d9f75844SAndroid Build Coastguard Worker   RTC_NO_UNIQUE_ADDRESS key_compare comp_;
553*d9f75844SAndroid Build Coastguard Worker   // Declare after `key_compare_comp_` to workaround GCC ICE. For details
554*d9f75844SAndroid Build Coastguard Worker   // see https://crbug.com/1156268
555*d9f75844SAndroid Build Coastguard Worker   container_type body_;
556*d9f75844SAndroid Build Coastguard Worker 
557*d9f75844SAndroid Build Coastguard Worker   // If the compare is not transparent we want to construct key_type once.
558*d9f75844SAndroid Build Coastguard Worker   template <typename K>
559*d9f75844SAndroid Build Coastguard Worker   using KeyTypeOrK = typename std::
560*d9f75844SAndroid Build Coastguard Worker       conditional<IsTransparentCompare<key_compare>::value, K, key_type>::type;
561*d9f75844SAndroid Build Coastguard Worker };
562*d9f75844SAndroid Build Coastguard Worker 
563*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
564*d9f75844SAndroid Build Coastguard Worker // Lifetime.
565*d9f75844SAndroid Build Coastguard Worker 
566*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
567*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
568*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
569*d9f75844SAndroid Build Coastguard Worker     : comp_(comp) {}
570*d9f75844SAndroid Build Coastguard Worker 
571*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
572*d9f75844SAndroid Build Coastguard Worker template <class InputIterator>
573*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
574*d9f75844SAndroid Build Coastguard Worker     InputIterator first,
575*d9f75844SAndroid Build Coastguard Worker     InputIterator last,
576*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
577*d9f75844SAndroid Build Coastguard Worker     : comp_(comp), body_(first, last) {
578*d9f75844SAndroid Build Coastguard Worker   sort_and_unique();
579*d9f75844SAndroid Build Coastguard Worker }
580*d9f75844SAndroid Build Coastguard Worker 
581*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
582*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
583*d9f75844SAndroid Build Coastguard Worker     const container_type& items,
584*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
585*d9f75844SAndroid Build Coastguard Worker     : comp_(comp), body_(items) {
586*d9f75844SAndroid Build Coastguard Worker   sort_and_unique();
587*d9f75844SAndroid Build Coastguard Worker }
588*d9f75844SAndroid Build Coastguard Worker 
589*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
590*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
591*d9f75844SAndroid Build Coastguard Worker     container_type&& items,
592*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
593*d9f75844SAndroid Build Coastguard Worker     : comp_(comp), body_(std::move(items)) {
594*d9f75844SAndroid Build Coastguard Worker   sort_and_unique();
595*d9f75844SAndroid Build Coastguard Worker }
596*d9f75844SAndroid Build Coastguard Worker 
597*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
598*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
599*d9f75844SAndroid Build Coastguard Worker     std::initializer_list<value_type> ilist,
600*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
601*d9f75844SAndroid Build Coastguard Worker     : flat_tree(std::begin(ilist), std::end(ilist), comp) {}
602*d9f75844SAndroid Build Coastguard Worker 
603*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
604*d9f75844SAndroid Build Coastguard Worker template <class InputIterator>
605*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
606*d9f75844SAndroid Build Coastguard Worker     sorted_unique_t,
607*d9f75844SAndroid Build Coastguard Worker     InputIterator first,
608*d9f75844SAndroid Build Coastguard Worker     InputIterator last,
609*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
610*d9f75844SAndroid Build Coastguard Worker     : comp_(comp), body_(first, last) {
611*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(is_sorted_and_unique(*this, value_comp()));
612*d9f75844SAndroid Build Coastguard Worker }
613*d9f75844SAndroid Build Coastguard Worker 
614*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
615*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
616*d9f75844SAndroid Build Coastguard Worker     sorted_unique_t,
617*d9f75844SAndroid Build Coastguard Worker     const container_type& items,
618*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
619*d9f75844SAndroid Build Coastguard Worker     : comp_(comp), body_(items) {
620*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(is_sorted_and_unique(*this, value_comp()));
621*d9f75844SAndroid Build Coastguard Worker }
622*d9f75844SAndroid Build Coastguard Worker 
623*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
624*d9f75844SAndroid Build Coastguard Worker constexpr flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
625*d9f75844SAndroid Build Coastguard Worker     sorted_unique_t,
626*d9f75844SAndroid Build Coastguard Worker     container_type&& items,
627*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
628*d9f75844SAndroid Build Coastguard Worker     : comp_(comp), body_(std::move(items)) {
629*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(is_sorted_and_unique(*this, value_comp()));
630*d9f75844SAndroid Build Coastguard Worker }
631*d9f75844SAndroid Build Coastguard Worker 
632*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
633*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
634*d9f75844SAndroid Build Coastguard Worker     sorted_unique_t,
635*d9f75844SAndroid Build Coastguard Worker     std::initializer_list<value_type> ilist,
636*d9f75844SAndroid Build Coastguard Worker     const KeyCompare& comp)
637*d9f75844SAndroid Build Coastguard Worker     : flat_tree(sorted_unique, std::begin(ilist), std::end(ilist), comp) {}
638*d9f75844SAndroid Build Coastguard Worker 
639*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
640*d9f75844SAndroid Build Coastguard Worker // Assignments.
641*d9f75844SAndroid Build Coastguard Worker 
642*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
643*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::operator=(
644*d9f75844SAndroid Build Coastguard Worker     std::initializer_list<value_type> ilist) -> flat_tree& {
645*d9f75844SAndroid Build Coastguard Worker   body_ = ilist;
646*d9f75844SAndroid Build Coastguard Worker   sort_and_unique();
647*d9f75844SAndroid Build Coastguard Worker   return *this;
648*d9f75844SAndroid Build Coastguard Worker }
649*d9f75844SAndroid Build Coastguard Worker 
650*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
651*d9f75844SAndroid Build Coastguard Worker // Memory management.
652*d9f75844SAndroid Build Coastguard Worker 
653*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
654*d9f75844SAndroid Build Coastguard Worker void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::reserve(
655*d9f75844SAndroid Build Coastguard Worker     size_type new_capacity) {
656*d9f75844SAndroid Build Coastguard Worker   body_.reserve(new_capacity);
657*d9f75844SAndroid Build Coastguard Worker }
658*d9f75844SAndroid Build Coastguard Worker 
659*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
660*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::capacity() const
661*d9f75844SAndroid Build Coastguard Worker     -> size_type {
662*d9f75844SAndroid Build Coastguard Worker   return body_.capacity();
663*d9f75844SAndroid Build Coastguard Worker }
664*d9f75844SAndroid Build Coastguard Worker 
665*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
666*d9f75844SAndroid Build Coastguard Worker void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::shrink_to_fit() {
667*d9f75844SAndroid Build Coastguard Worker   body_.shrink_to_fit();
668*d9f75844SAndroid Build Coastguard Worker }
669*d9f75844SAndroid Build Coastguard Worker 
670*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
671*d9f75844SAndroid Build Coastguard Worker // Size management.
672*d9f75844SAndroid Build Coastguard Worker 
673*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
674*d9f75844SAndroid Build Coastguard Worker void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::clear() {
675*d9f75844SAndroid Build Coastguard Worker   body_.clear();
676*d9f75844SAndroid Build Coastguard Worker }
677*d9f75844SAndroid Build Coastguard Worker 
678*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
679*d9f75844SAndroid Build Coastguard Worker constexpr auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::size()
680*d9f75844SAndroid Build Coastguard Worker     const -> size_type {
681*d9f75844SAndroid Build Coastguard Worker   return body_.size();
682*d9f75844SAndroid Build Coastguard Worker }
683*d9f75844SAndroid Build Coastguard Worker 
684*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
685*d9f75844SAndroid Build Coastguard Worker constexpr auto
686*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::max_size() const
687*d9f75844SAndroid Build Coastguard Worker     -> size_type {
688*d9f75844SAndroid Build Coastguard Worker   return body_.max_size();
689*d9f75844SAndroid Build Coastguard Worker }
690*d9f75844SAndroid Build Coastguard Worker 
691*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
692*d9f75844SAndroid Build Coastguard Worker constexpr bool flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::empty()
693*d9f75844SAndroid Build Coastguard Worker     const {
694*d9f75844SAndroid Build Coastguard Worker   return body_.empty();
695*d9f75844SAndroid Build Coastguard Worker }
696*d9f75844SAndroid Build Coastguard Worker 
697*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
698*d9f75844SAndroid Build Coastguard Worker // Iterators.
699*d9f75844SAndroid Build Coastguard Worker 
700*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
701*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::begin()
702*d9f75844SAndroid Build Coastguard Worker     -> iterator {
703*d9f75844SAndroid Build Coastguard Worker   return body_.begin();
704*d9f75844SAndroid Build Coastguard Worker }
705*d9f75844SAndroid Build Coastguard Worker 
706*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
707*d9f75844SAndroid Build Coastguard Worker constexpr auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::begin()
708*d9f75844SAndroid Build Coastguard Worker     const -> const_iterator {
709*d9f75844SAndroid Build Coastguard Worker   return std::begin(body_);
710*d9f75844SAndroid Build Coastguard Worker }
711*d9f75844SAndroid Build Coastguard Worker 
712*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
713*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::cbegin() const
714*d9f75844SAndroid Build Coastguard Worker     -> const_iterator {
715*d9f75844SAndroid Build Coastguard Worker   return body_.cbegin();
716*d9f75844SAndroid Build Coastguard Worker }
717*d9f75844SAndroid Build Coastguard Worker 
718*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
719*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::end() -> iterator {
720*d9f75844SAndroid Build Coastguard Worker   return body_.end();
721*d9f75844SAndroid Build Coastguard Worker }
722*d9f75844SAndroid Build Coastguard Worker 
723*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
724*d9f75844SAndroid Build Coastguard Worker constexpr auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::end()
725*d9f75844SAndroid Build Coastguard Worker     const -> const_iterator {
726*d9f75844SAndroid Build Coastguard Worker   return std::end(body_);
727*d9f75844SAndroid Build Coastguard Worker }
728*d9f75844SAndroid Build Coastguard Worker 
729*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
730*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::cend() const
731*d9f75844SAndroid Build Coastguard Worker     -> const_iterator {
732*d9f75844SAndroid Build Coastguard Worker   return body_.cend();
733*d9f75844SAndroid Build Coastguard Worker }
734*d9f75844SAndroid Build Coastguard Worker 
735*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
736*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::rbegin()
737*d9f75844SAndroid Build Coastguard Worker     -> reverse_iterator {
738*d9f75844SAndroid Build Coastguard Worker   return body_.rbegin();
739*d9f75844SAndroid Build Coastguard Worker }
740*d9f75844SAndroid Build Coastguard Worker 
741*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
742*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::rbegin() const
743*d9f75844SAndroid Build Coastguard Worker     -> const_reverse_iterator {
744*d9f75844SAndroid Build Coastguard Worker   return body_.rbegin();
745*d9f75844SAndroid Build Coastguard Worker }
746*d9f75844SAndroid Build Coastguard Worker 
747*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
748*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::crbegin() const
749*d9f75844SAndroid Build Coastguard Worker     -> const_reverse_iterator {
750*d9f75844SAndroid Build Coastguard Worker   return body_.crbegin();
751*d9f75844SAndroid Build Coastguard Worker }
752*d9f75844SAndroid Build Coastguard Worker 
753*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
754*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::rend()
755*d9f75844SAndroid Build Coastguard Worker     -> reverse_iterator {
756*d9f75844SAndroid Build Coastguard Worker   return body_.rend();
757*d9f75844SAndroid Build Coastguard Worker }
758*d9f75844SAndroid Build Coastguard Worker 
759*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
760*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::rend() const
761*d9f75844SAndroid Build Coastguard Worker     -> const_reverse_iterator {
762*d9f75844SAndroid Build Coastguard Worker   return body_.rend();
763*d9f75844SAndroid Build Coastguard Worker }
764*d9f75844SAndroid Build Coastguard Worker 
765*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
766*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::crend() const
767*d9f75844SAndroid Build Coastguard Worker     -> const_reverse_iterator {
768*d9f75844SAndroid Build Coastguard Worker   return body_.crend();
769*d9f75844SAndroid Build Coastguard Worker }
770*d9f75844SAndroid Build Coastguard Worker 
771*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
772*d9f75844SAndroid Build Coastguard Worker // Insert operations.
773*d9f75844SAndroid Build Coastguard Worker //
774*d9f75844SAndroid Build Coastguard Worker // Currently we use position_hint the same way as eastl or boost:
775*d9f75844SAndroid Build Coastguard Worker // https://github.com/electronicarts/EASTL/blob/master/include/EASTL/vector_set.h#L493
776*d9f75844SAndroid Build Coastguard Worker 
777*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
778*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::insert(
779*d9f75844SAndroid Build Coastguard Worker     const value_type& val) -> std::pair<iterator, bool> {
780*d9f75844SAndroid Build Coastguard Worker   return emplace_key_args(GetKeyFromValue()(val), val);
781*d9f75844SAndroid Build Coastguard Worker }
782*d9f75844SAndroid Build Coastguard Worker 
783*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
784*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::insert(
785*d9f75844SAndroid Build Coastguard Worker     value_type&& val) -> std::pair<iterator, bool> {
786*d9f75844SAndroid Build Coastguard Worker   return emplace_key_args(GetKeyFromValue()(val), std::move(val));
787*d9f75844SAndroid Build Coastguard Worker }
788*d9f75844SAndroid Build Coastguard Worker 
789*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
790*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::insert(
791*d9f75844SAndroid Build Coastguard Worker     const_iterator position_hint,
792*d9f75844SAndroid Build Coastguard Worker     const value_type& val) -> iterator {
793*d9f75844SAndroid Build Coastguard Worker   return emplace_hint_key_args(position_hint, GetKeyFromValue()(val), val)
794*d9f75844SAndroid Build Coastguard Worker       .first;
795*d9f75844SAndroid Build Coastguard Worker }
796*d9f75844SAndroid Build Coastguard Worker 
797*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
798*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::insert(
799*d9f75844SAndroid Build Coastguard Worker     const_iterator position_hint,
800*d9f75844SAndroid Build Coastguard Worker     value_type&& val) -> iterator {
801*d9f75844SAndroid Build Coastguard Worker   return emplace_hint_key_args(position_hint, GetKeyFromValue()(val),
802*d9f75844SAndroid Build Coastguard Worker                                std::move(val))
803*d9f75844SAndroid Build Coastguard Worker       .first;
804*d9f75844SAndroid Build Coastguard Worker }
805*d9f75844SAndroid Build Coastguard Worker 
806*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
807*d9f75844SAndroid Build Coastguard Worker template <class InputIterator>
808*d9f75844SAndroid Build Coastguard Worker void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::insert(
809*d9f75844SAndroid Build Coastguard Worker     InputIterator first,
810*d9f75844SAndroid Build Coastguard Worker     InputIterator last) {
811*d9f75844SAndroid Build Coastguard Worker   if (first == last)
812*d9f75844SAndroid Build Coastguard Worker     return;
813*d9f75844SAndroid Build Coastguard Worker 
814*d9f75844SAndroid Build Coastguard Worker   // Dispatch to single element insert if the input range contains a single
815*d9f75844SAndroid Build Coastguard Worker   // element.
816*d9f75844SAndroid Build Coastguard Worker   if (is_multipass<InputIterator>() && std::next(first) == last) {
817*d9f75844SAndroid Build Coastguard Worker     insert(end(), *first);
818*d9f75844SAndroid Build Coastguard Worker     return;
819*d9f75844SAndroid Build Coastguard Worker   }
820*d9f75844SAndroid Build Coastguard Worker 
821*d9f75844SAndroid Build Coastguard Worker   // Provide a convenience lambda to obtain an iterator pointing past the last
822*d9f75844SAndroid Build Coastguard Worker   // old element. This needs to be dymanic due to possible re-allocations.
823*d9f75844SAndroid Build Coastguard Worker   auto middle = [this, size = size()] { return std::next(begin(), size); };
824*d9f75844SAndroid Build Coastguard Worker 
825*d9f75844SAndroid Build Coastguard Worker   // For batch updates initialize the first insertion point.
826*d9f75844SAndroid Build Coastguard Worker   difference_type pos_first_new = size();
827*d9f75844SAndroid Build Coastguard Worker 
828*d9f75844SAndroid Build Coastguard Worker   // Loop over the input range while appending new values and overwriting
829*d9f75844SAndroid Build Coastguard Worker   // existing ones, if applicable. Keep track of the first insertion point.
830*d9f75844SAndroid Build Coastguard Worker   for (; first != last; ++first) {
831*d9f75844SAndroid Build Coastguard Worker     std::pair<iterator, bool> result = append_unique(begin(), middle(), *first);
832*d9f75844SAndroid Build Coastguard Worker     if (result.second) {
833*d9f75844SAndroid Build Coastguard Worker       pos_first_new =
834*d9f75844SAndroid Build Coastguard Worker           std::min(pos_first_new, std::distance(begin(), result.first));
835*d9f75844SAndroid Build Coastguard Worker     }
836*d9f75844SAndroid Build Coastguard Worker   }
837*d9f75844SAndroid Build Coastguard Worker 
838*d9f75844SAndroid Build Coastguard Worker   // The new elements might be unordered and contain duplicates, so post-process
839*d9f75844SAndroid Build Coastguard Worker   // the just inserted elements and merge them with the rest, inserting them at
840*d9f75844SAndroid Build Coastguard Worker   // the previously found spot.
841*d9f75844SAndroid Build Coastguard Worker   sort_and_unique(middle(), end());
842*d9f75844SAndroid Build Coastguard Worker   std::inplace_merge(std::next(begin(), pos_first_new), middle(), end(),
843*d9f75844SAndroid Build Coastguard Worker                      value_comp());
844*d9f75844SAndroid Build Coastguard Worker }
845*d9f75844SAndroid Build Coastguard Worker 
846*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
847*d9f75844SAndroid Build Coastguard Worker template <class... Args>
848*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::emplace(
849*d9f75844SAndroid Build Coastguard Worker     Args&&... args) -> std::pair<iterator, bool> {
850*d9f75844SAndroid Build Coastguard Worker   return insert(value_type(std::forward<Args>(args)...));
851*d9f75844SAndroid Build Coastguard Worker }
852*d9f75844SAndroid Build Coastguard Worker 
853*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
854*d9f75844SAndroid Build Coastguard Worker template <class... Args>
855*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::emplace_hint(
856*d9f75844SAndroid Build Coastguard Worker     const_iterator position_hint,
857*d9f75844SAndroid Build Coastguard Worker     Args&&... args) -> iterator {
858*d9f75844SAndroid Build Coastguard Worker   return insert(position_hint, value_type(std::forward<Args>(args)...));
859*d9f75844SAndroid Build Coastguard Worker }
860*d9f75844SAndroid Build Coastguard Worker 
861*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
862*d9f75844SAndroid Build Coastguard Worker // Underlying type operations.
863*d9f75844SAndroid Build Coastguard Worker 
864*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
865*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::
866*d9f75844SAndroid Build Coastguard Worker     extract() && -> container_type {
867*d9f75844SAndroid Build Coastguard Worker   return std::exchange(body_, container_type());
868*d9f75844SAndroid Build Coastguard Worker }
869*d9f75844SAndroid Build Coastguard Worker 
870*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
871*d9f75844SAndroid Build Coastguard Worker void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::replace(
872*d9f75844SAndroid Build Coastguard Worker     container_type&& body) {
873*d9f75844SAndroid Build Coastguard Worker   // Ensure that `body` is sorted and has no repeated elements according to
874*d9f75844SAndroid Build Coastguard Worker   // `value_comp()`.
875*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(is_sorted_and_unique(body, value_comp()));
876*d9f75844SAndroid Build Coastguard Worker   body_ = std::move(body);
877*d9f75844SAndroid Build Coastguard Worker }
878*d9f75844SAndroid Build Coastguard Worker 
879*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
880*d9f75844SAndroid Build Coastguard Worker // Erase operations.
881*d9f75844SAndroid Build Coastguard Worker 
882*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
883*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::erase(
884*d9f75844SAndroid Build Coastguard Worker     iterator position) -> iterator {
885*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(position != body_.end());
886*d9f75844SAndroid Build Coastguard Worker   return body_.erase(position);
887*d9f75844SAndroid Build Coastguard Worker }
888*d9f75844SAndroid Build Coastguard Worker 
889*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
890*d9f75844SAndroid Build Coastguard Worker template <typename DummyT>
891*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::erase(
892*d9f75844SAndroid Build Coastguard Worker     const_iterator position) -> iterator {
893*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(position != body_.end());
894*d9f75844SAndroid Build Coastguard Worker   return body_.erase(position);
895*d9f75844SAndroid Build Coastguard Worker }
896*d9f75844SAndroid Build Coastguard Worker 
897*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
898*d9f75844SAndroid Build Coastguard Worker template <typename K>
899*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::erase(const K& val)
900*d9f75844SAndroid Build Coastguard Worker     -> size_type {
901*d9f75844SAndroid Build Coastguard Worker   auto eq_range = equal_range(val);
902*d9f75844SAndroid Build Coastguard Worker   auto res = std::distance(eq_range.first, eq_range.second);
903*d9f75844SAndroid Build Coastguard Worker   erase(eq_range.first, eq_range.second);
904*d9f75844SAndroid Build Coastguard Worker   return res;
905*d9f75844SAndroid Build Coastguard Worker }
906*d9f75844SAndroid Build Coastguard Worker 
907*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
908*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::erase(
909*d9f75844SAndroid Build Coastguard Worker     const_iterator first,
910*d9f75844SAndroid Build Coastguard Worker     const_iterator last) -> iterator {
911*d9f75844SAndroid Build Coastguard Worker   return body_.erase(first, last);
912*d9f75844SAndroid Build Coastguard Worker }
913*d9f75844SAndroid Build Coastguard Worker 
914*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
915*d9f75844SAndroid Build Coastguard Worker // Comparators.
916*d9f75844SAndroid Build Coastguard Worker 
917*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
918*d9f75844SAndroid Build Coastguard Worker constexpr auto
919*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::key_comp() const
920*d9f75844SAndroid Build Coastguard Worker     -> key_compare {
921*d9f75844SAndroid Build Coastguard Worker   return comp_;
922*d9f75844SAndroid Build Coastguard Worker }
923*d9f75844SAndroid Build Coastguard Worker 
924*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
925*d9f75844SAndroid Build Coastguard Worker constexpr auto
926*d9f75844SAndroid Build Coastguard Worker flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::value_comp() const
927*d9f75844SAndroid Build Coastguard Worker     -> value_compare {
928*d9f75844SAndroid Build Coastguard Worker   return value_compare{comp_};
929*d9f75844SAndroid Build Coastguard Worker }
930*d9f75844SAndroid Build Coastguard Worker 
931*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
932*d9f75844SAndroid Build Coastguard Worker // Search operations.
933*d9f75844SAndroid Build Coastguard Worker 
934*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
935*d9f75844SAndroid Build Coastguard Worker template <typename K>
936*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::count(
937*d9f75844SAndroid Build Coastguard Worker     const K& key) const -> size_type {
938*d9f75844SAndroid Build Coastguard Worker   auto eq_range = equal_range(key);
939*d9f75844SAndroid Build Coastguard Worker   return std::distance(eq_range.first, eq_range.second);
940*d9f75844SAndroid Build Coastguard Worker }
941*d9f75844SAndroid Build Coastguard Worker 
942*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
943*d9f75844SAndroid Build Coastguard Worker template <typename K>
944*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::find(const K& key)
945*d9f75844SAndroid Build Coastguard Worker     -> iterator {
946*d9f75844SAndroid Build Coastguard Worker   return const_cast_it(std::as_const(*this).find(key));
947*d9f75844SAndroid Build Coastguard Worker }
948*d9f75844SAndroid Build Coastguard Worker 
949*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
950*d9f75844SAndroid Build Coastguard Worker template <typename K>
951*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::find(
952*d9f75844SAndroid Build Coastguard Worker     const K& key) const -> const_iterator {
953*d9f75844SAndroid Build Coastguard Worker   auto eq_range = equal_range(key);
954*d9f75844SAndroid Build Coastguard Worker   return (eq_range.first == eq_range.second) ? end() : eq_range.first;
955*d9f75844SAndroid Build Coastguard Worker }
956*d9f75844SAndroid Build Coastguard Worker 
957*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
958*d9f75844SAndroid Build Coastguard Worker template <typename K>
959*d9f75844SAndroid Build Coastguard Worker bool flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::contains(
960*d9f75844SAndroid Build Coastguard Worker     const K& key) const {
961*d9f75844SAndroid Build Coastguard Worker   auto lower = lower_bound(key);
962*d9f75844SAndroid Build Coastguard Worker   return lower != end() && !comp_(key, GetKeyFromValue()(*lower));
963*d9f75844SAndroid Build Coastguard Worker }
964*d9f75844SAndroid Build Coastguard Worker 
965*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
966*d9f75844SAndroid Build Coastguard Worker template <typename K>
967*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::equal_range(
968*d9f75844SAndroid Build Coastguard Worker     const K& key) -> std::pair<iterator, iterator> {
969*d9f75844SAndroid Build Coastguard Worker   auto res = std::as_const(*this).equal_range(key);
970*d9f75844SAndroid Build Coastguard Worker   return {const_cast_it(res.first), const_cast_it(res.second)};
971*d9f75844SAndroid Build Coastguard Worker }
972*d9f75844SAndroid Build Coastguard Worker 
973*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
974*d9f75844SAndroid Build Coastguard Worker template <typename K>
975*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::equal_range(
976*d9f75844SAndroid Build Coastguard Worker     const K& key) const -> std::pair<const_iterator, const_iterator> {
977*d9f75844SAndroid Build Coastguard Worker   auto lower = lower_bound(key);
978*d9f75844SAndroid Build Coastguard Worker 
979*d9f75844SAndroid Build Coastguard Worker   KeyValueCompare comp(comp_);
980*d9f75844SAndroid Build Coastguard Worker   if (lower == end() || comp(key, *lower))
981*d9f75844SAndroid Build Coastguard Worker     return {lower, lower};
982*d9f75844SAndroid Build Coastguard Worker 
983*d9f75844SAndroid Build Coastguard Worker   return {lower, std::next(lower)};
984*d9f75844SAndroid Build Coastguard Worker }
985*d9f75844SAndroid Build Coastguard Worker 
986*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
987*d9f75844SAndroid Build Coastguard Worker template <typename K>
988*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::lower_bound(
989*d9f75844SAndroid Build Coastguard Worker     const K& key) -> iterator {
990*d9f75844SAndroid Build Coastguard Worker   return const_cast_it(std::as_const(*this).lower_bound(key));
991*d9f75844SAndroid Build Coastguard Worker }
992*d9f75844SAndroid Build Coastguard Worker 
993*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
994*d9f75844SAndroid Build Coastguard Worker template <typename K>
995*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::lower_bound(
996*d9f75844SAndroid Build Coastguard Worker     const K& key) const -> const_iterator {
997*d9f75844SAndroid Build Coastguard Worker   static_assert(std::is_convertible<const KeyTypeOrK<K>&, const K&>::value,
998*d9f75844SAndroid Build Coastguard Worker                 "Requested type cannot be bound to the container's key_type "
999*d9f75844SAndroid Build Coastguard Worker                 "which is required for a non-transparent compare.");
1000*d9f75844SAndroid Build Coastguard Worker 
1001*d9f75844SAndroid Build Coastguard Worker   const KeyTypeOrK<K>& key_ref = key;
1002*d9f75844SAndroid Build Coastguard Worker 
1003*d9f75844SAndroid Build Coastguard Worker   KeyValueCompare comp(comp_);
1004*d9f75844SAndroid Build Coastguard Worker   return absl::c_lower_bound(*this, key_ref, comp);
1005*d9f75844SAndroid Build Coastguard Worker }
1006*d9f75844SAndroid Build Coastguard Worker 
1007*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1008*d9f75844SAndroid Build Coastguard Worker template <typename K>
1009*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::upper_bound(
1010*d9f75844SAndroid Build Coastguard Worker     const K& key) -> iterator {
1011*d9f75844SAndroid Build Coastguard Worker   return const_cast_it(std::as_const(*this).upper_bound(key));
1012*d9f75844SAndroid Build Coastguard Worker }
1013*d9f75844SAndroid Build Coastguard Worker 
1014*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1015*d9f75844SAndroid Build Coastguard Worker template <typename K>
1016*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::upper_bound(
1017*d9f75844SAndroid Build Coastguard Worker     const K& key) const -> const_iterator {
1018*d9f75844SAndroid Build Coastguard Worker   static_assert(std::is_convertible<const KeyTypeOrK<K>&, const K&>::value,
1019*d9f75844SAndroid Build Coastguard Worker                 "Requested type cannot be bound to the container's key_type "
1020*d9f75844SAndroid Build Coastguard Worker                 "which is required for a non-transparent compare.");
1021*d9f75844SAndroid Build Coastguard Worker 
1022*d9f75844SAndroid Build Coastguard Worker   const KeyTypeOrK<K>& key_ref = key;
1023*d9f75844SAndroid Build Coastguard Worker 
1024*d9f75844SAndroid Build Coastguard Worker   KeyValueCompare comp(comp_);
1025*d9f75844SAndroid Build Coastguard Worker   return absl::c_upper_bound(*this, key_ref, comp);
1026*d9f75844SAndroid Build Coastguard Worker }
1027*d9f75844SAndroid Build Coastguard Worker 
1028*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1029*d9f75844SAndroid Build Coastguard Worker // General operations.
1030*d9f75844SAndroid Build Coastguard Worker 
1031*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1032*d9f75844SAndroid Build Coastguard Worker void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::swap(
1033*d9f75844SAndroid Build Coastguard Worker     flat_tree& other) noexcept {
1034*d9f75844SAndroid Build Coastguard Worker   std::swap(*this, other);
1035*d9f75844SAndroid Build Coastguard Worker }
1036*d9f75844SAndroid Build Coastguard Worker 
1037*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1038*d9f75844SAndroid Build Coastguard Worker template <class... Args>
1039*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::unsafe_emplace(
1040*d9f75844SAndroid Build Coastguard Worker     const_iterator position,
1041*d9f75844SAndroid Build Coastguard Worker     Args&&... args) -> iterator {
1042*d9f75844SAndroid Build Coastguard Worker   return body_.emplace(position, std::forward<Args>(args)...);
1043*d9f75844SAndroid Build Coastguard Worker }
1044*d9f75844SAndroid Build Coastguard Worker 
1045*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1046*d9f75844SAndroid Build Coastguard Worker template <class K, class... Args>
1047*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::emplace_key_args(
1048*d9f75844SAndroid Build Coastguard Worker     const K& key,
1049*d9f75844SAndroid Build Coastguard Worker     Args&&... args) -> std::pair<iterator, bool> {
1050*d9f75844SAndroid Build Coastguard Worker   auto lower = lower_bound(key);
1051*d9f75844SAndroid Build Coastguard Worker   if (lower == end() || comp_(key, GetKeyFromValue()(*lower)))
1052*d9f75844SAndroid Build Coastguard Worker     return {unsafe_emplace(lower, std::forward<Args>(args)...), true};
1053*d9f75844SAndroid Build Coastguard Worker   return {lower, false};
1054*d9f75844SAndroid Build Coastguard Worker }
1055*d9f75844SAndroid Build Coastguard Worker 
1056*d9f75844SAndroid Build Coastguard Worker template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1057*d9f75844SAndroid Build Coastguard Worker template <class K, class... Args>
1058*d9f75844SAndroid Build Coastguard Worker auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::
1059*d9f75844SAndroid Build Coastguard Worker     emplace_hint_key_args(const_iterator hint, const K& key, Args&&... args)
1060*d9f75844SAndroid Build Coastguard Worker         -> std::pair<iterator, bool> {
1061*d9f75844SAndroid Build Coastguard Worker   KeyValueCompare comp(comp_);
1062*d9f75844SAndroid Build Coastguard Worker   if ((hint == begin() || comp(*std::prev(hint), key))) {
1063*d9f75844SAndroid Build Coastguard Worker     if (hint == end() || comp(key, *hint)) {
1064*d9f75844SAndroid Build Coastguard Worker       // *(hint - 1) < key < *hint => key did not exist and hint is correct.
1065*d9f75844SAndroid Build Coastguard Worker       return {unsafe_emplace(hint, std::forward<Args>(args)...), true};
1066*d9f75844SAndroid Build Coastguard Worker     }
1067*d9f75844SAndroid Build Coastguard Worker     if (!comp(*hint, key)) {
1068*d9f75844SAndroid Build Coastguard Worker       // key == *hint => no-op, return correct hint.
1069*d9f75844SAndroid Build Coastguard Worker       return {const_cast_it(hint), false};
1070*d9f75844SAndroid Build Coastguard Worker     }
1071*d9f75844SAndroid Build Coastguard Worker   }
1072*d9f75844SAndroid Build Coastguard Worker   // hint was not helpful, dispatch to hintless version.
1073*d9f75844SAndroid Build Coastguard Worker   return emplace_key_args(key, std::forward<Args>(args)...);
1074*d9f75844SAndroid Build Coastguard Worker }
1075*d9f75844SAndroid Build Coastguard Worker 
1076*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
1077*d9f75844SAndroid Build Coastguard Worker // Free functions.
1078*d9f75844SAndroid Build Coastguard Worker 
1079*d9f75844SAndroid Build Coastguard Worker // Erases all elements that match predicate. It has O(size) complexity.
1080*d9f75844SAndroid Build Coastguard Worker template <class Key,
1081*d9f75844SAndroid Build Coastguard Worker           class GetKeyFromValue,
1082*d9f75844SAndroid Build Coastguard Worker           class KeyCompare,
1083*d9f75844SAndroid Build Coastguard Worker           class Container,
1084*d9f75844SAndroid Build Coastguard Worker           typename Predicate>
1085*d9f75844SAndroid Build Coastguard Worker size_t EraseIf(
1086*d9f75844SAndroid Build Coastguard Worker     webrtc::flat_containers_internal::
1087*d9f75844SAndroid Build Coastguard Worker         flat_tree<Key, GetKeyFromValue, KeyCompare, Container>& container,
1088*d9f75844SAndroid Build Coastguard Worker     Predicate pred) {
1089*d9f75844SAndroid Build Coastguard Worker   auto it = std::remove_if(container.begin(), container.end(),
1090*d9f75844SAndroid Build Coastguard Worker                            std::forward<Predicate>(pred));
1091*d9f75844SAndroid Build Coastguard Worker   size_t removed = std::distance(it, container.end());
1092*d9f75844SAndroid Build Coastguard Worker   container.erase(it, container.end());
1093*d9f75844SAndroid Build Coastguard Worker   return removed;
1094*d9f75844SAndroid Build Coastguard Worker }
1095*d9f75844SAndroid Build Coastguard Worker 
1096*d9f75844SAndroid Build Coastguard Worker }  // namespace flat_containers_internal
1097*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
1098*d9f75844SAndroid Build Coastguard Worker 
1099*d9f75844SAndroid Build Coastguard Worker #endif  // RTC_BASE_CONTAINERS_FLAT_TREE_H_
1100