blob: 480784ced410c73a59412e209d12a75504c440e7 [file] [log] [blame]
Victor Boiviefd954fc2021-06-29 09:21:11 +02001/*
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"
Victor Boiviefd954fc2021-06-29 09:21:11 +020024#include "rtc_base/system/no_unique_address.h"
25
26namespace 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.
30struct sorted_unique_t {
31 constexpr sorted_unique_t() = default;
32};
33extern sorted_unique_t sorted_unique;
34
35namespace 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.
39template <typename Range, typename Comp>
40constexpr 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.
Danil Chapovalov9ee752a2022-08-08 18:43:35 +020044 return absl::c_adjacent_find(range, std::not_fn(comp)) == std::end(range);
Victor Boiviefd954fc2021-06-29 09:21:11 +020045}
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.
49template <class Iterator>
50using 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.
55template <typename T, typename = void>
56struct IsTransparentCompare : std::false_type {};
57template <typename T>
Danil Chapovalov9ee752a2022-08-08 18:43:35 +020058struct IsTransparentCompare<T, std::void_t<typename T::is_transparent>>
Victor Boiviefd954fc2021-06-29 09:21:11 +020059 : 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
69template <typename U, typename T, size_t N, size_t... I>
70constexpr std::array<U, N> ToArrayImpl(const T (&data)[N],
71 std::index_sequence<I...>) {
72 return {{data[I]...}};
73}
74
75template <typename U, typename T, size_t N>
76constexpr 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.
82template <typename T>
83constexpr void Assign(T& lhs, T&& rhs) {
84 lhs = std::move(rhs);
85}
86
87template <typename T, typename U>
88constexpr 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.
94template <typename T>
95constexpr 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.
102template <typename BidirIt>
103constexpr BidirIt Prev(BidirIt it) {
104 return --it;
105}
106
107// constexpr next implementation. std::next is not constexpr prior to C++17.
108template <typename InputIt>
109constexpr 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.
117template <typename BidirIt, typename Compare>
118constexpr 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&).
141template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
142class 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
Artem Titov96e3b992021-07-26 16:03:14 +0200432 // 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
Victor Boiviefd954fc2021-06-29 09:21:11 +0200435 // insertion happened.
436 template <class K, class... Args>
437 std::pair<iterator, bool> emplace_key_args(const K& key, Args&&... args);
438
Artem Titov96e3b992021-07-26 16:03:14 +0200439 // Similar to `emplace_key_args`, but checks `hint` first as a possible
Victor Boiviefd954fc2021-06-29 09:21:11 +0200440 // 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.
Danil Chapovalov9ee752a2022-08-08 18:43:35 +0200543 auto equal_comp = std::not_fn(value_comp());
Victor Boiviefd954fc2021-06-29 09:21:11 +0200544 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_;
Artem Titov96e3b992021-07-26 16:03:14 +0200553 // Declare after `key_compare_comp_` to workaround GCC ICE. For details
Victor Boiviefd954fc2021-06-29 09:21:11 +0200554 // 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
566template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
567flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::flat_tree(
568 const KeyCompare& comp)
569 : comp_(comp) {}
570
571template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
572template <class InputIterator>
573flat_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
581template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
582flat_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
589template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
590flat_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
597template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
598flat_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
603template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
604template <class InputIterator>
605flat_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
614template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
615flat_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
623template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
624constexpr 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
632template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
633flat_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
642template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
643auto 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
653template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
654void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::reserve(
655 size_type new_capacity) {
656 body_.reserve(new_capacity);
657}
658
659template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
660auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::capacity() const
661 -> size_type {
662 return body_.capacity();
663}
664
665template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
666void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::shrink_to_fit() {
667 body_.shrink_to_fit();
668}
669
670// ----------------------------------------------------------------------------
671// Size management.
672
673template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
674void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::clear() {
675 body_.clear();
676}
677
678template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
679constexpr auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::size()
680 const -> size_type {
681 return body_.size();
682}
683
684template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
685constexpr auto
686flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::max_size() const
687 -> size_type {
688 return body_.max_size();
689}
690
691template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
692constexpr bool flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::empty()
693 const {
694 return body_.empty();
695}
696
697// ----------------------------------------------------------------------------
698// Iterators.
699
700template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
701auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::begin()
702 -> iterator {
703 return body_.begin();
704}
705
706template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
707constexpr auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::begin()
708 const -> const_iterator {
709 return std::begin(body_);
710}
711
712template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
713auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::cbegin() const
714 -> const_iterator {
715 return body_.cbegin();
716}
717
718template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
719auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::end() -> iterator {
720 return body_.end();
721}
722
723template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
724constexpr auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::end()
725 const -> const_iterator {
726 return std::end(body_);
727}
728
729template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
730auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::cend() const
731 -> const_iterator {
732 return body_.cend();
733}
734
735template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
736auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::rbegin()
737 -> reverse_iterator {
738 return body_.rbegin();
739}
740
741template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
742auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::rbegin() const
743 -> const_reverse_iterator {
744 return body_.rbegin();
745}
746
747template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
748auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::crbegin() const
749 -> const_reverse_iterator {
750 return body_.crbegin();
751}
752
753template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
754auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::rend()
755 -> reverse_iterator {
756 return body_.rend();
757}
758
759template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
760auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::rend() const
761 -> const_reverse_iterator {
762 return body_.rend();
763}
764
765template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
766auto 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
777template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
778auto 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
783template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
784auto 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
789template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
790auto 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
797template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
798auto 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
806template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
807template <class InputIterator>
808void 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
846template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
847template <class... Args>
848auto 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
853template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
854template <class... Args>
855auto 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
864template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
865auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::
866 extract() && -> container_type {
867 return std::exchange(body_, container_type());
868}
869
870template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
871void 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
882template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
883auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::erase(
884 iterator position) -> iterator {
885 RTC_CHECK(position != body_.end());
886 return body_.erase(position);
887}
888
889template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
890template <typename DummyT>
891auto 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
897template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
898template <typename K>
899auto 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
907template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
908auto 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
917template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
918constexpr auto
919flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::key_comp() const
920 -> key_compare {
921 return comp_;
922}
923
924template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
925constexpr auto
926flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::value_comp() const
927 -> value_compare {
928 return value_compare{comp_};
929}
930
931// ----------------------------------------------------------------------------
932// Search operations.
933
934template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
935template <typename K>
936auto 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
942template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
943template <typename K>
944auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::find(const K& key)
945 -> iterator {
Danil Chapovalov9ee752a2022-08-08 18:43:35 +0200946 return const_cast_it(std::as_const(*this).find(key));
Victor Boiviefd954fc2021-06-29 09:21:11 +0200947}
948
949template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
950template <typename K>
951auto 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
957template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
958template <typename K>
959bool 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
965template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
966template <typename K>
967auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::equal_range(
968 const K& key) -> std::pair<iterator, iterator> {
Danil Chapovalov9ee752a2022-08-08 18:43:35 +0200969 auto res = std::as_const(*this).equal_range(key);
Victor Boiviefd954fc2021-06-29 09:21:11 +0200970 return {const_cast_it(res.first), const_cast_it(res.second)};
971}
972
973template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
974template <typename K>
975auto 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
986template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
987template <typename K>
988auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::lower_bound(
989 const K& key) -> iterator {
Danil Chapovalov9ee752a2022-08-08 18:43:35 +0200990 return const_cast_it(std::as_const(*this).lower_bound(key));
Victor Boiviefd954fc2021-06-29 09:21:11 +0200991}
992
993template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
994template <typename K>
995auto 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
1007template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1008template <typename K>
1009auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::upper_bound(
1010 const K& key) -> iterator {
Danil Chapovalov9ee752a2022-08-08 18:43:35 +02001011 return const_cast_it(std::as_const(*this).upper_bound(key));
Victor Boiviefd954fc2021-06-29 09:21:11 +02001012}
1013
1014template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1015template <typename K>
1016auto 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
1031template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1032void flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::swap(
1033 flat_tree& other) noexcept {
1034 std::swap(*this, other);
1035}
1036
1037template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1038template <class... Args>
1039auto 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
1045template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1046template <class K, class... Args>
1047auto 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
1056template <class Key, class GetKeyFromValue, class KeyCompare, class Container>
1057template <class K, class... Args>
1058auto 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
Victor Boiviefd954fc2021-06-29 09:21:11 +02001076// ----------------------------------------------------------------------------
1077// Free functions.
1078
1079// Erases all elements that match predicate. It has O(size) complexity.
1080template <class Key,
1081 class GetKeyFromValue,
1082 class KeyCompare,
1083 class Container,
1084 typename Predicate>
1085size_t EraseIf(
1086 webrtc::flat_containers_internal::
1087 flat_tree<Key, GetKeyFromValue, KeyCompare, Container>& container,
1088 Predicate pred) {
Victor Boivie5900ba02021-07-07 10:48:28 +02001089 auto it = std::remove_if(container.begin(), container.end(),
1090 std::forward<Predicate>(pred));
Victor Boiviefd954fc2021-06-29 09:21:11 +02001091 size_t removed = std::distance(it, container.end());
1092 container.erase(it, container.end());
1093 return removed;
1094}
1095
Victor Boivie5900ba02021-07-07 10:48:28 +02001096} // namespace flat_containers_internal
Victor Boiviefd954fc2021-06-29 09:21:11 +02001097} // namespace webrtc
1098
1099#endif // RTC_BASE_CONTAINERS_FLAT_TREE_H_