Pigweed
 
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
62template <typename Key, typename T>
64 private:
65 using GenericIterator = containers::internal::GenericAATree::iterator;
67 using Compare = typename Tree::Compare;
68 using GetKey = typename Tree::GetKey;
69
70 public:
75 using Item = typename Tree::Item;
76 using Pair = typename Tree::Pair;
77
78 using key_type = Key;
79 using mapped_type = std::remove_cv_t<T>;
80 using value_type = Item;
81 using size_type = std::size_t;
82 using difference_type = std::ptrdiff_t;
83 using key_compare = Compare;
84 using reference = value_type&;
85 using const_reference = const value_type&;
86 using pointer = value_type*;
87 using const_pointer = const value_type*;
88
89 public:
90 class iterator : public containers::internal::AATreeIterator<T> {
91 public:
92 constexpr iterator() = default;
93
94 private:
95 friend IntrusiveMap;
96 constexpr explicit iterator(GenericIterator iter)
97 : containers::internal::AATreeIterator<T>(iter) {}
98 };
99
101 : public containers::internal::AATreeIterator<std::add_const_t<T>> {
102 public:
103 constexpr const_iterator() = default;
104
105 private:
106 friend IntrusiveMap;
107 constexpr explicit const_iterator(GenericIterator iter)
108 : containers::internal::AATreeIterator<std::add_const_t<T>>(iter) {}
109 };
110
111 using reverse_iterator = std::reverse_iterator<iterator>;
112 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
113
115 constexpr explicit IntrusiveMap() : IntrusiveMap(std::less<Key>()) {}
116
124 template <typename Comparator>
125 constexpr explicit IntrusiveMap(Comparator&& compare)
126 : IntrusiveMap(std::forward<Comparator>(compare),
127 [](const T& t) { return t.key(); }) {}
128
135 template <typename Comparator, typename KeyRetriever>
136 constexpr IntrusiveMap(Comparator&& compare, KeyRetriever&& get_key)
137 : tree_(true,
138 std::forward<Comparator>(compare),
139 std::forward<KeyRetriever>(get_key)) {
140 CheckItemType();
141 }
142
147 template <typename Iterator, typename... Functors>
148 IntrusiveMap(Iterator first, Iterator last, Functors&&... functors)
149 : IntrusiveMap(std::forward<Functors>(functors)...) {
150 tree_.insert(first, last);
151 }
152
155 template <typename... Functors>
156 explicit IntrusiveMap(std::initializer_list<T*> items, Functors&&... functors)
157 : IntrusiveMap(
158 items.begin(), items.end(), std::forward<Functors>(functors)...) {}
159
160 // Element access
161
165 T& at(const key_type& key) {
166 auto iter = tree_.find(key);
167 PW_DASSERT(iter != tree_.end());
168 return static_cast<T&>(*iter);
169 }
170
171 const T& at(const key_type& key) const {
172 auto iter = tree_.find(key);
173 PW_DASSERT(iter != tree_.end());
174 return static_cast<const T&>(*iter);
175 }
176
177 // Iterators
178
179 iterator begin() noexcept { return iterator(tree_.begin()); }
180 const_iterator begin() const noexcept {
181 return const_iterator(tree_.begin());
182 }
183 const_iterator cbegin() const noexcept { return begin(); }
184
185 iterator end() noexcept { return iterator(tree_.end()); }
186 const_iterator end() const noexcept { return const_iterator(tree_.end()); }
187 const_iterator cend() const noexcept { return end(); }
188
189 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
190 const_reverse_iterator rbegin() const noexcept {
191 return const_reverse_iterator(end());
192 }
193 const_reverse_iterator crbegin() const noexcept { return rbegin(); }
194
195 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
196 const_reverse_iterator rend() const noexcept {
197 return const_reverse_iterator(begin());
198 }
199 const_reverse_iterator crend() const noexcept { return rend(); }
200
201 // Capacity
202
204 [[nodiscard]] bool empty() const noexcept { return tree_.empty(); }
205
207 size_t size() const { return tree_.size(); }
208
212 constexpr size_t max_size() const noexcept { return tree_.max_size(); }
213
214 // Modifiers
215
219 void clear() { tree_.clear(); }
220
228 std::pair<iterator, bool> insert(T& item) {
229 auto result = tree_.insert(item);
230 return std::make_pair(iterator(result.first), result.second);
231 }
232
233 iterator insert(iterator, T& item) {
234 // Disregard the hint.
235 return insert(item).first;
236 }
237
238 template <class Iterator>
239 void insert(Iterator first, Iterator last) {
240 tree_.insert(first, last);
241 }
242
243 void insert(std::initializer_list<T*> ilist) {
244 tree_.insert(ilist.begin(), ilist.end());
245 }
246
251 iterator erase(T& item) { return iterator(tree_.erase_one(item)); }
252
253 iterator erase(iterator pos) { return iterator(tree_.erase_one(*pos)); }
254
255 iterator erase(iterator first, iterator last) {
256 return iterator(tree_.erase_range(*first, *last));
257 }
258
259 size_t erase(const key_type& key) { return tree_.erase_all(key); }
260
262 void swap(IntrusiveMap<Key, T>& other) { tree_.swap(other.tree_); }
263
265 template <typename MapType>
266 void merge(MapType& other) {
267 tree_.merge(other.tree_);
268 }
269
273 size_t count(const key_type& key) const { return tree_.count(key); }
274
277 iterator find(const key_type& key) { return iterator(tree_.find(key)); }
278
279 const_iterator find(const key_type& key) const {
280 return const_iterator(tree_.find(key));
281 }
282
286 std::pair<iterator, iterator> equal_range(const key_type& key) {
287 auto result = tree_.equal_range(key);
288 return std::make_pair(iterator(result.first), iterator(result.second));
289 }
290 std::pair<const_iterator, const_iterator> equal_range(
291 const key_type& key) const {
292 auto result = tree_.equal_range(key);
293 return std::make_pair(const_iterator(result.first),
294 const_iterator(result.second));
295 }
296
299 iterator lower_bound(const key_type& key) {
300 return iterator(tree_.lower_bound(key));
301 }
302 const_iterator lower_bound(const key_type& key) const {
303 return const_iterator(tree_.lower_bound(key));
304 }
305
308 iterator upper_bound(const key_type& key) {
309 return iterator(tree_.upper_bound(key));
310 }
311 const_iterator upper_bound(const key_type& key) const {
312 return const_iterator(tree_.upper_bound(key));
313 }
314
315 private:
316 // Check that T is an Item in a function, since the class T will not be fully
317 // defined when the IntrusiveList<T> class is instantiated.
318 static constexpr void CheckItemType() {
319 using ItemBase = containers::internal::AATreeItem;
320 using IntrusiveItemType =
321 typename containers::internal::IntrusiveItem<ItemBase, T>::Type;
322 static_assert(
323 std::is_base_of<IntrusiveItemType, T>(),
324 "IntrusiveMap items must be derived from IntrusiveMap<Key, T>::Item, "
325 "where T is the item or one of its bases.");
326 }
327
328 // Allow multimaps to access the tree for `merge`.
329 template <typename, typename>
330 friend class IntrusiveMultiMap;
331
332 // The AA tree that stores the map.
333 //
334 // This field is mutable so that it doesn't need const overloads.
335 mutable Tree tree_;
336};
337
338} // namespace pw
Definition: intrusive_map.h:101
Definition: intrusive_map.h:90
Definition: intrusive_map.h:63
void swap(IntrusiveMap< Key, T > &other)
Exchanges this map's items with the other map's items.
Definition: intrusive_map.h:262
T & at(const key_type &key)
Definition: intrusive_map.h:165
std::pair< iterator, iterator > equal_range(const key_type &key)
Definition: intrusive_map.h:286
IntrusiveMap(Iterator first, Iterator last, Functors &&... functors)
Definition: intrusive_map.h:148
iterator lower_bound(const key_type &key)
Definition: intrusive_map.h:299
size_t count(const key_type &key) const
Definition: intrusive_map.h:273
constexpr IntrusiveMap(Comparator &&compare, KeyRetriever &&get_key)
Definition: intrusive_map.h:136
iterator upper_bound(const key_type &key)
Definition: intrusive_map.h:308
typename Tree::Item Item
Definition: intrusive_map.h:75
std::pair< iterator, bool > insert(T &item)
Definition: intrusive_map.h:228
iterator erase(T &item)
Definition: intrusive_map.h:251
size_t size() const
Returns the number of items in the map.
Definition: intrusive_map.h:207
iterator find(const key_type &key)
Definition: intrusive_map.h:277
constexpr size_t max_size() const noexcept
Definition: intrusive_map.h:212
constexpr IntrusiveMap(Comparator &&compare)
Definition: intrusive_map.h:125
IntrusiveMap(std::initializer_list< T * > items, Functors &&... functors)
Definition: intrusive_map.h:156
bool empty() const noexcept
Returns whether the map has zero items or not.
Definition: intrusive_map.h:204
void clear()
Definition: intrusive_map.h:219
constexpr IntrusiveMap()
Constructs an empty map of items.
Definition: intrusive_map.h:115
void merge(MapType &other)
Splices items from the other map into this one.
Definition: intrusive_map.h:266
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