C/C++ API Reference
Loading...
Searching...
No Matches
intrusive_map.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
21template <typename Key, typename Value>
22class DynamicMap;
23
25
28
70template <typename Key, typename T>
72 private:
73 using GenericIterator = containers::internal::GenericAATree::iterator;
75 using Compare = typename Tree::Compare;
76 using GetKey = typename Tree::GetKey;
77
78 public:
83 using Item = typename Tree::Item;
84 using Pair = typename Tree::Pair;
85
86 using key_type = Key;
87 using mapped_type = std::remove_cv_t<T>;
88 using value_type = Item;
89 using size_type = std::size_t;
90 using difference_type = std::ptrdiff_t;
91 using key_compare = Compare;
92 using reference = value_type&;
93 using const_reference = const value_type&;
94 using pointer = value_type*;
95 using const_pointer = const value_type*;
96
97 public:
99 : public containers::internal::AATreeIterator<std::add_const_t<T>> {
100 public:
101 constexpr const_iterator() = default;
102
103 private:
104 friend IntrusiveMap;
105 constexpr explicit const_iterator(GenericIterator iter)
106 : containers::internal::AATreeIterator<std::add_const_t<T>>(iter) {}
107 };
108
109 class iterator : public containers::internal::AATreeIterator<T> {
110 public:
111 constexpr iterator() = default;
112
113 private:
114 friend IntrusiveMap;
115 template <typename, typename>
116 friend class DynamicMap;
117
118 constexpr explicit iterator(GenericIterator iter)
119 : containers::internal::AATreeIterator<T>(iter) {}
120
121 constexpr explicit iterator(const_iterator other)
122 : containers::internal::AATreeIterator<T>(other) {}
123 };
124
125 using reverse_iterator = std::reverse_iterator<iterator>;
126 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
127
129 constexpr explicit IntrusiveMap() : IntrusiveMap(std::less<Key>()) {}
130
138 template <typename Comparator>
139 constexpr explicit IntrusiveMap(Comparator compare)
140 : IntrusiveMap(std::move(compare), [](const T& t) { return t.key(); }) {}
141
148 template <typename Comparator, typename KeyRetriever>
149 constexpr IntrusiveMap(Comparator&& compare, KeyRetriever&& get_key)
150 : tree_(true,
151 std::forward<Comparator>(compare),
152 std::forward<KeyRetriever>(get_key)) {
153 CheckItemType();
154 }
155
160 template <typename Iterator, typename... Functors>
161 IntrusiveMap(Iterator first, Iterator last, Functors&&... functors)
162 : IntrusiveMap(std::forward<Functors>(functors)...) {
163 tree_.insert(first, last);
164 }
165
168 template <typename... Functors>
169 explicit IntrusiveMap(std::initializer_list<T*> items, Functors&&... functors)
170 : IntrusiveMap(
171 items.begin(), items.end(), std::forward<Functors>(functors)...) {}
172
173 // Element access
174
178 T& at(const key_type& key) {
179 auto iter = tree_.find(key);
180 PW_DASSERT(iter != tree_.end());
181 return static_cast<T&>(*iter);
182 }
183
184 const T& at(const key_type& key) const {
185 auto iter = tree_.find(key);
186 PW_DASSERT(iter != tree_.end());
187 return static_cast<const T&>(*iter);
188 }
189
190 // Iterators
191
192 iterator begin() noexcept { return iterator(tree_.begin()); }
193 const_iterator begin() const noexcept {
194 return const_iterator(tree_.begin());
195 }
196 const_iterator cbegin() const noexcept { return begin(); }
197
198 iterator end() noexcept { return iterator(tree_.end()); }
199 const_iterator end() const noexcept { return const_iterator(tree_.end()); }
200 const_iterator cend() const noexcept { return end(); }
201
202 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
203 const_reverse_iterator rbegin() const noexcept {
204 return const_reverse_iterator(end());
205 }
206 const_reverse_iterator crbegin() const noexcept { return rbegin(); }
207
208 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
209 const_reverse_iterator rend() const noexcept {
210 return const_reverse_iterator(begin());
211 }
212 const_reverse_iterator crend() const noexcept { return rend(); }
213
214 // Capacity
215
217 [[nodiscard]] bool empty() const noexcept { return tree_.empty(); }
218
220 size_t size() const { return tree_.size(); }
221
225 constexpr size_t max_size() const noexcept { return tree_.max_size(); }
226
227 // Modifiers
228
232 void clear() { tree_.clear(); }
233
241 std::pair<iterator, bool> insert(T& item) {
242 auto result = tree_.insert(item);
243 return std::make_pair(iterator(result.first), result.second);
244 }
245
246 iterator insert(iterator, T& item) {
247 // Disregard the hint.
248 return insert(item).first;
249 }
250
251 template <class Iterator>
252 void insert(Iterator first, Iterator last) {
253 tree_.insert(first, last);
254 }
255
256 void insert(std::initializer_list<T*> ilist) {
257 tree_.insert(ilist.begin(), ilist.end());
258 }
259
264 iterator erase(T& item) { return iterator(tree_.erase_one(item)); }
265
266 iterator erase(iterator pos) { return iterator(tree_.erase_one(*pos)); }
267
268 iterator erase(iterator first, iterator last) {
269 return iterator(tree_.erase_range(first, last));
270 }
271
272 size_t erase(const key_type& key) { return tree_.erase_all(key); }
273
275 void swap(IntrusiveMap<Key, T>& other) { tree_.swap(other.tree_); }
276
278 template <typename MapType>
279 void merge(MapType& other) {
280 tree_.merge(other.tree_);
281 }
282
286 size_t count(const key_type& key) const { return tree_.count(key); }
287
290 iterator find(const key_type& key) { return iterator(tree_.find(key)); }
291
292 const_iterator find(const key_type& key) const {
293 return const_iterator(tree_.find(key));
294 }
295
299 std::pair<iterator, iterator> equal_range(const key_type& key) {
300 auto result = tree_.equal_range(key);
301 return std::make_pair(iterator(result.first), iterator(result.second));
302 }
303 std::pair<const_iterator, const_iterator> equal_range(
304 const key_type& key) const {
305 auto result = tree_.equal_range(key);
306 return std::make_pair(const_iterator(result.first),
307 const_iterator(result.second));
308 }
309
312 iterator lower_bound(const key_type& key) {
313 return iterator(tree_.lower_bound(key));
314 }
315 const_iterator lower_bound(const key_type& key) const {
316 return const_iterator(tree_.lower_bound(key));
317 }
318
321 iterator upper_bound(const key_type& key) {
322 return iterator(tree_.upper_bound(key));
323 }
324 const_iterator upper_bound(const key_type& key) const {
325 return const_iterator(tree_.upper_bound(key));
326 }
327
328 private:
329 // Check that T is an Item in a function, since the class T will not be fully
330 // defined when the IntrusiveList<T> class is instantiated.
331 static constexpr void CheckItemType() {
332 using ItemBase = containers::internal::AATreeItem;
333 using IntrusiveItemType =
334 typename containers::internal::IntrusiveItem<ItemBase, T>::Type;
335 static_assert(
336 std::is_base_of<IntrusiveItemType, T>(),
337 "IntrusiveMap items must be derived from IntrusiveMap<Key, T>::Item, "
338 "where T is the item or one of its bases.");
339 }
340
341 // Allow multimaps to access the tree for `merge`.
342 template <typename, typename>
343 friend class IntrusiveMultiMap;
344
345 // The AA tree that stores the map.
346 //
347 // This field is mutable so that it doesn't need const overloads.
348 mutable Tree tree_;
349};
350
351} // namespace pw
Definition: dynamic_map.h:46
Definition: intrusive_map.h:99
Definition: intrusive_map.h:109
Definition: intrusive_map.h:71
iterator erase_range(AATreeItem &first, AATreeItem &last)
iterator erase_one(AATreeItem &item)
void swap(IntrusiveMap< Key, T > &other)
Exchanges this map's items with the other map's items.
Definition: intrusive_map.h:275
T & at(const key_type &key)
Definition: intrusive_map.h:178
std::pair< iterator, iterator > equal_range(const key_type &key)
Definition: intrusive_map.h:299
IntrusiveMap(Iterator first, Iterator last, Functors &&... functors)
Definition: intrusive_map.h:161
iterator lower_bound(const key_type &key)
Definition: intrusive_map.h:312
size_t count(const key_type &key) const
Definition: intrusive_map.h:286
constexpr IntrusiveMap(Comparator &&compare, KeyRetriever &&get_key)
Definition: intrusive_map.h:149
iterator upper_bound(const key_type &key)
Definition: intrusive_map.h:321
constexpr IntrusiveMap(Comparator compare)
Definition: intrusive_map.h:139
typename Tree::Item Item
Definition: intrusive_map.h:83
std::pair< iterator, bool > insert(T &item)
Definition: intrusive_map.h:241
iterator erase(T &item)
Definition: intrusive_map.h:264
size_t size() const
Returns the number of items in the map.
Definition: intrusive_map.h:220
iterator find(const key_type &key)
Definition: intrusive_map.h:290
constexpr size_t max_size() const noexcept
Definition: intrusive_map.h:225
IntrusiveMap(std::initializer_list< T * > items, Functors &&... functors)
Definition: intrusive_map.h:169
bool empty() const noexcept
Returns whether the map has zero items or not.
Definition: intrusive_map.h:217
void clear()
Definition: intrusive_map.h:232
constexpr IntrusiveMap()
Constructs an empty map of items.
Definition: intrusive_map.h:129
void merge(MapType &other)
Splices items from the other map into this one.
Definition: intrusive_map.h:279
iterator lower_bound(Key key)
Definition: aa_tree.h:407
constexpr iterator begin() noexcept
Returns a pointer to the first item, if any.
Definition: aa_tree.h:62
constexpr size_t max_size() const noexcept
Definition: aa_tree.h:83
std::pair< iterator, iterator > equal_range(Key key)
Definition: aa_tree.h:402
iterator upper_bound(Key key)
Definition: aa_tree.h:431
void merge(KeyedAATree< K > &other)
Definition: aa_tree.h:377
iterator find(Key key)
Definition: aa_tree.h:392
std::pair< iterator, bool > insert(AATreeItem &item)
Definition: aa_tree.h:313
size_t erase_all(Key key)
Definition: aa_tree.h:366
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:75
size_t count(Key key)
Definition: aa_tree.h:387
constexpr iterator end() noexcept
Returns a pointer to the last item, if any.
Definition: aa_tree.h:67
The Pigweed namespace.
Definition: alignment.h:27