Pigweed
 
Loading...
Searching...
No Matches
intrusive_multiset.h
1// Copyright 2024 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include "pw_containers/internal/aa_tree.h"
17#include "pw_containers/internal/aa_tree_item.h"
18
19namespace pw {
20
55template <typename T>
57 private:
58 using GenericIterator = containers::internal::GenericAATree::iterator;
60 using Compare = typename Tree::Compare;
61 using GetKey = typename Tree::GetKey;
62
63 public:
65 using Item = typename Tree::Item;
66
67 using key_type = T;
68 using value_type = T;
69 using size_type = std::size_t;
70 using difference_type = std::ptrdiff_t;
71 using key_compare = Compare;
72 using value_compare = Compare;
73 using reference = value_type&;
74 using const_reference = const value_type&;
75 using pointer = value_type*;
76 using const_pointer = const value_type*;
77
78 public:
79 class iterator : public containers::internal::AATreeIterator<T> {
80 public:
81 constexpr iterator() = default;
82
83 private:
84 using Base = containers::internal::AATreeIterator<T>;
85 friend IntrusiveMultiSet;
86 constexpr explicit iterator(GenericIterator iter) : Base(iter) {}
87 };
88
90 : public containers::internal::AATreeIterator<std::add_const_t<T>> {
91 public:
92 constexpr const_iterator() = default;
93
94 private:
95 using Base = containers::internal::AATreeIterator<std::add_const_t<T>>;
96 friend IntrusiveMultiSet;
97 constexpr explicit const_iterator(GenericIterator iter) : Base(iter) {}
98 };
99
100 using reverse_iterator = std::reverse_iterator<iterator>;
101 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
102
104 constexpr explicit IntrusiveMultiSet() : IntrusiveMultiSet(std::less<>()) {}
105
113 template <typename Comparator>
114 constexpr explicit IntrusiveMultiSet(Comparator&& compare)
115 : tree_(false,
116 std::forward<Comparator>(compare),
117 [](const T& t) -> const T& { return t; }) {
118 CheckItemType();
119 }
120
125 template <typename Iterator, typename... Functors>
126 IntrusiveMultiSet(Iterator first, Iterator last, Functors&&... functors)
127 : IntrusiveMultiSet(std::forward<Functors>(functors)...) {
128 tree_.insert(first, last);
129 }
130
133 template <typename... Functors>
134 IntrusiveMultiSet(std::initializer_list<T*> items, Functors&&... functors)
136 items.begin(), items.end(), std::forward<Functors>(functors)...) {}
137
138 // Iterators
139
140 iterator begin() noexcept { return iterator(tree_.begin()); }
141 const_iterator begin() const noexcept {
142 return const_iterator(tree_.begin());
143 }
144 const_iterator cbegin() const noexcept { return begin(); }
145
146 iterator end() noexcept { return iterator(tree_.end()); }
147 const_iterator end() const noexcept { return const_iterator(tree_.end()); }
148 const_iterator cend() const noexcept { return end(); }
149
150 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
151 const_reverse_iterator rbegin() const noexcept {
152 return const_reverse_iterator(end());
153 }
154 const_reverse_iterator crbegin() const noexcept { return rbegin(); }
155
156 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
157 const_reverse_iterator rend() const noexcept {
158 return const_reverse_iterator(begin());
159 }
160 const_reverse_iterator crend() const noexcept { return rend(); }
161
162 // Capacity
163
165 [[nodiscard]] bool empty() const noexcept { return tree_.empty(); }
166
168 size_t size() const { return tree_.size(); }
169
173 constexpr size_t max_size() const noexcept { return tree_.max_size(); }
174
175 // Modifiers
176
180 void clear() { tree_.clear(); }
181
183 iterator insert(T& item) { return iterator(tree_.insert(item).first); }
184
185 iterator insert(iterator, T& item) {
186 // Disregard the hint.
187 return iterator(insert(item));
188 }
189
190 template <class Iterator>
191 void insert(Iterator first, Iterator last) {
192 tree_.insert(first, last);
193 }
194
195 void insert(std::initializer_list<T*> ilist) {
196 tree_.insert(ilist.begin(), ilist.end());
197 }
198
203 iterator erase(iterator pos) { return iterator(tree_.erase_one(*pos)); }
204
205 iterator erase(iterator first, iterator last) {
206 return iterator(tree_.erase_range(*first, *last));
207 }
208
209 size_t erase(const T& item) { return tree_.erase_all(item); }
210
212 void swap(IntrusiveMultiSet<T>& other) { tree_.swap(other.tree_); }
213
217 template <typename MapType>
218 void merge(MapType& other) {
219 tree_.merge(other.tree_);
220 }
221
223 size_t count(const T& item) const { return tree_.count(item); }
224
227 iterator find(const T& item) { return iterator(tree_.find(item)); }
228
229 const_iterator find(const T& item) const {
230 return const_iterator(tree_.find(item));
231 }
232
236 std::pair<iterator, iterator> equal_range(const T& item) {
237 auto result = tree_.equal_range(item);
238 return std::make_pair(iterator(result.first), iterator(result.second));
239 }
240 std::pair<const_iterator, const_iterator> equal_range(const T& item) const {
241 auto result = tree_.equal_range(item);
242 return std::make_pair(const_iterator(result.first),
243 const_iterator(result.second));
244 }
245
249 iterator lower_bound(const T& item) {
250 return iterator(tree_.lower_bound(item));
251 }
252 const_iterator lower_bound(const T& item) const {
253 return const_iterator(tree_.lower_bound(item));
254 }
255
259 iterator upper_bound(const T& item) {
260 return iterator(tree_.upper_bound(item));
261 }
262 const_iterator upper_bound(const T& item) const {
263 return const_iterator(tree_.upper_bound(item));
264 }
265
266 private:
267 // Check that T is an Item in a function, since the class T will not be fully
268 // defined when the IntrusiveList<T> class is instantiated.
269 static constexpr void CheckItemType() {
270 using ItemBase = containers::internal::AATreeItem;
271 using IntrusiveItemType =
272 typename containers::internal::IntrusiveItem<ItemBase, T>::Type;
273 static_assert(
274 std::is_base_of<IntrusiveItemType, T>(),
275 "IntrusiveMultiSet items must be derived from "
276 "IntrusiveMultiSet<T>::Item, where T is the item or one of its "
277 "bases.");
278 }
279
280 // Allow sets to access the tree for `merge`.
281 template <typename>
282 friend class IntrusiveSet;
283
284 // The AA tree that stores the set.
285 //
286 // This field is mutable so that it doesn't need const overloads.
287 mutable Tree tree_;
288};
289
290} // namespace pw
Definition: intrusive_multiset.h:90
Definition: intrusive_multiset.h:79
Definition: intrusive_multiset.h:56
void swap(IntrusiveMultiSet< T > &other)
Exchanges this multiset's items with the other multiset's items.
Definition: intrusive_multiset.h:212
iterator erase(iterator pos)
Definition: intrusive_multiset.h:203
constexpr IntrusiveMultiSet()
Constructs an empty set of items.
Definition: intrusive_multiset.h:104
IntrusiveMultiSet(std::initializer_list< T * > items, Functors &&... functors)
Definition: intrusive_multiset.h:134
constexpr IntrusiveMultiSet(Comparator &&compare)
Definition: intrusive_multiset.h:114
size_t size() const
Returns the number of items in the multiset.
Definition: intrusive_multiset.h:168
bool empty() const noexcept
Returns whether the multiset has zero items or not.
Definition: intrusive_multiset.h:165
iterator upper_bound(const T &item)
Definition: intrusive_multiset.h:259
void clear()
Definition: intrusive_multiset.h:180
iterator find(const T &item)
Definition: intrusive_multiset.h:227
typename Tree::Item Item
IntrusiveMultiSet items must derive from Item.
Definition: intrusive_multiset.h:65
iterator lower_bound(const T &item)
Definition: intrusive_multiset.h:249
std::pair< iterator, iterator > equal_range(const T &item)
Definition: intrusive_multiset.h:236
constexpr size_t max_size() const noexcept
Definition: intrusive_multiset.h:173
void merge(MapType &other)
Definition: intrusive_multiset.h:218
size_t count(const T &item) const
Returns the number of items in the multimap with the given key.
Definition: intrusive_multiset.h:223
iterator insert(T &item)
Adds the given item to the multiset.
Definition: intrusive_multiset.h:183
IntrusiveMultiSet(Iterator first, Iterator last, Functors &&... functors)
Definition: intrusive_multiset.h:126
iterator erase_range(AATreeItem &first, AATreeItem &last)
iterator find(Key key)
Definition: aa_tree.h:351
std::pair< iterator, bool > insert(AATreeItem &item)
Definition: aa_tree.h:272
size_t erase_all(Key key)
Definition: aa_tree.h:325
iterator upper_bound(Key key)
Definition: aa_tree.h:390
iterator erase_one(AATreeItem &item)
std::pair< iterator, iterator > equal_range(Key key)
Definition: aa_tree.h:361
iterator lower_bound(Key key)
Definition: aa_tree.h:366
void merge(AATree< K, V > &other)
Definition: aa_tree.h:336
size_t count(Key key)
Definition: aa_tree.h:346
constexpr iterator begin() noexcept
Returns a pointer to the first item, if any.
Definition: aa_tree.h:60
constexpr size_t max_size() const noexcept
Definition: aa_tree.h:81
void swap(GenericAATree &other)
Exchanges this tree's items with the other tree's items.
size_t size() const
Returns the number of items in the tree.
constexpr bool empty() const
Returns whether the tree has zero items or not.
Definition: aa_tree.h:73
constexpr iterator end() noexcept
Returns a pointer to the last item, if any.
Definition: aa_tree.h:65
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27