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