16#include <initializer_list>
23#include "pw_allocator/allocator.h"
24#include "pw_allocator/unique_ptr.h"
25#include "pw_assert/assert.h"
26#include "pw_containers/internal/traits.h"
27#include "pw_containers/intrusive_map.h"
46template <
typename Key,
typename Value>
58 using mapped_type = Value;
61 Node& operator=(
const Node&) =
delete;
63 template <
typename K,
typename... Args>
64 explicit Node(K&& key, Args&&... args)
65 : key_value_(std::piecewise_construct,
66 std::forward_as_tuple(std::forward<K>(key)),
67 std::forward_as_tuple(std::forward<Args>(args)...)) {}
69 const key_type& key()
const {
return key_value_.first; }
71 mapped_type& mapped() {
return key_value_.second; }
72 const mapped_type& mapped()
const {
return key_value_.second; }
77 std::pair<const key_type, mapped_type> key_value_;
87 template <
bool kIsConst>
90 using iterator_category = std::bidirectional_iterator_tag;
91 using value_type = std::pair<const Key, Value>;
92 using difference_type = std::ptrdiff_t;
94 std::conditional_t<kIsConst, const value_type&, value_type&>;
96 std::conditional_t<kIsConst, const value_type*, value_type*>;
98 constexpr Iterator() =
default;
100 constexpr reference operator*()
const {
return it_->key_value_; }
101 constexpr pointer operator->()
const {
return &it_->key_value_; }
103 constexpr Iterator operator++() {
107 constexpr Iterator operator++(
int) {
108 Iterator result = *
this;
112 constexpr Iterator operator--() {
116 constexpr Iterator operator--(
int) {
117 Iterator result = *
this;
122 constexpr friend bool operator==(Iterator lhs, Iterator rhs) {
123 return lhs.it_ == rhs.it_;
125 constexpr friend bool operator!=(Iterator lhs, Iterator rhs) {
126 return lhs.it_ != rhs.it_;
130 using BaseIterator = std::conditional_t<kIsConst,
131 typename Map::const_iterator,
132 typename Map::iterator>;
134 constexpr explicit Iterator(BaseIterator it) : it_(it) {}
137 friend class Iterator;
138 friend class DynamicMap;
144 using key_type = Key;
145 using mapped_type = Value;
146 using value_type = std::pair<const Key, Value>;
147 using size_type =
typename Map::size_type;
148 using difference_type =
typename Map::difference_type;
149 using key_compare =
typename Map::key_compare;
150 using allocator_type = Allocator;
151 using reference = value_type&;
152 using const_reference =
const value_type&;
153 using pointer = value_type*;
154 using const_pointer =
const value_type*;
155 using iterator = Iterator<false>;
156 using const_iterator = Iterator<true>;
157 using reverse_iterator = std::reverse_iterator<iterator>;
158 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
159 using node_type = Node;
173 : allocator_(&allocator), map_() {}
183 allocator_ = other.allocator_;
184 map_.
swap(other.map_);
190 if (&other ==
this) {
194 allocator_ = other.allocator_;
195 map_.
swap(other.map_);
206 iterator begin() noexcept {
return iterator(map_.begin()); }
207 const_iterator begin() const noexcept {
return const_iterator(map_.begin()); }
208 const_iterator cbegin() const noexcept {
return begin(); }
209 iterator end() noexcept {
return iterator(map_.end()); }
210 const_iterator end() const noexcept {
return const_iterator(map_.end()); }
211 const_iterator cend() const noexcept {
return end(); }
212 reverse_iterator rbegin() noexcept {
return reverse_iterator(end()); }
213 const_reverse_iterator rbegin() const noexcept {
214 return const_reverse_iterator(end());
216 const_reverse_iterator crbegin() const noexcept {
return rbegin(); }
217 reverse_iterator rend() noexcept {
return reverse_iterator(begin()); }
218 const_reverse_iterator rend() const noexcept {
219 return const_reverse_iterator(begin());
221 const_reverse_iterator crend() const noexcept {
return rend(); }
227 mapped_type&
at(
const key_type& key) {
return map_.
at(key).mapped(); }
229 const mapped_type&
at(
const key_type& key)
const {
230 return map_.
at(key).mapped();
237 template <
typename U = mapped_type,
238 typename = std::enable_if_t<std::is_default_constructible_v<U>>>
240 return emplace(key).first->second;
245 [[nodiscard]]
bool empty()
const {
return map_.
empty(); }
246 size_type size()
const {
return map_.
size(); }
247 constexpr size_type max_size() const noexcept {
return map_.
max_size(); }
261 [[nodiscard]] std::optional<std::pair<iterator, bool>>
try_insert(
262 const value_type& value) {
269 std::optional<std::pair<iterator, bool>>
try_insert(value_type&&) =
delete;
272 std::pair<iterator, bool>
insert(
const value_type& value) {
273 return emplace(value.first, value.second);
276 std::pair<iterator, bool>
insert(value_type&& value) {
277 return emplace(std::move(value.first), std::move(value.second));
281 template <
typename InputIt,
282 typename = containers::internal::EnableIfInputIterator<InputIt>>
283 void insert(InputIt first, InputIt last) {
284 for (
auto it = first; it != last; ++it) {
285 emplace(it->first, it->second);
289 void insert(std::initializer_list<value_type> ilist) {
290 insert(ilist.begin(), ilist.end());
297 if (node ==
nullptr) {
298 return {end(),
false,
nullptr};
300 PW_ASSERT(node.deallocator() == allocator_);
301 auto [node_it, inserted] = map_.
insert(*node);
304 return {iterator(node_it),
true,
nullptr};
306 return {iterator(node_it),
false, std::move(node)};
314 template <
typename K,
typename... Args>
315 [[nodiscard]] std::optional<std::pair<iterator, bool>>
try_emplace(
316 K&& key, Args&&... args) {
317 return TryEmplaceImpl(std::forward<K>(key), std::forward<Args>(args)...);
321 template <
typename K,
typename... Args>
322 std::pair<iterator, bool>
emplace(K&& key, Args&&... args) {
324 try_emplace(std::forward<K>(key), std::forward<Args>(args)...);
325 PW_ASSERT(result.has_value());
326 return result.value();
332 auto next_it = map_.
erase(pos.it_);
334 return iterator(next_it);
337 iterator
erase(const_iterator pos) {
338 return erase(iterator(
typename Map::iterator(pos.it_)));
342 iterator
erase(iterator first, iterator last) {
343 while (first != last) {
344 first =
erase(first);
351 template <
typename K>
369 return take(iterator(
typename Map::iterator(pos.it_)));
373 template <
typename K>
384 std::swap(allocator_, other.allocator_);
385 map_.
swap(other.map_);
392 if (
this == &other) {
395 PW_ASSERT(allocator_ == other.allocator_);
400 for (
auto it = other.begin(); it != other.end();) {
401 if (contains(it->first)) {
413 size_type count(
const key_type& key) {
return contains(key) ? 1 : 0; }
415 iterator find(
const key_type& key) {
return iterator(map_.
find(key)); }
417 const_iterator find(
const key_type& key)
const {
418 return const_iterator(map_.
find(key));
421 [[nodiscard]]
bool contains(
const key_type& key)
const {
422 return find(key) != end();
425 std::pair<iterator, iterator> equal_range(
const key_type& key) {
427 return std::make_pair(iterator(result.first), iterator(result.second));
430 std::pair<const_iterator, const_iterator> equal_range(
431 const key_type& key)
const {
433 return std::make_pair(const_iterator(result.first),
434 const_iterator(result.second));
437 iterator lower_bound(
const key_type& key) {
441 const_iterator lower_bound(
const key_type& key)
const {
445 iterator upper_bound(
const key_type& key) {
449 const_iterator upper_bound(
const key_type& key)
const {
456 template <
typename K,
typename... Args>
457 [[nodiscard]] std::optional<std::pair<iterator, bool>> TryEmplaceImpl(
458 K&& key, Args&&... args) {
460 if (
auto it = map_.
find(key); it != map_.end()) {
461 return std::make_pair(iterator(it),
false);
463 node_type* node = allocator_->template New<node_type>(
464 std::forward<K>(key), std::forward<Args>(args)...);
465 if (node ==
nullptr) {
468 auto [node_it, inserted] = map_.
insert(*node);
470 return std::make_pair(iterator(node_it),
true);
473 Allocator* allocator_;
Definition: allocator.h:42
void Delete(T *ptr)
Definition: deallocator.h:325
Definition: dynamic_map.h:55
Definition: dynamic_map.h:47
Definition: intrusive_map.h:71
Definition: unique_ptr.h:44
std::optional< std::pair< iterator, bool > > try_insert(const value_type &value)
Definition: dynamic_map.h:261
iterator erase(iterator pos)
Removes the element at pos and deallocates the node.
Definition: dynamic_map.h:330
constexpr allocator_type & get_allocator() const
Returns the allocator used by this map.
Definition: dynamic_map.h:202
void swap(IntrusiveMap< Key, T > &other)
Exchanges this map's items with the other map's items.
Definition: intrusive_map.h:275
mapped_type & operator[](const key_type &key)
Definition: dynamic_map.h:239
constexpr DynamicMap(Allocator &allocator) noexcept
Definition: dynamic_map.h:172
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
iterator lower_bound(const key_type &key)
Definition: intrusive_map.h:312
void merge(DynamicMap &other)
Definition: dynamic_map.h:391
iterator upper_bound(const key_type &key)
Definition: intrusive_map.h:321
mapped_type & at(const key_type &key)
Definition: dynamic_map.h:227
std::pair< iterator, bool > insert(T &item)
Definition: intrusive_map.h:241
DynamicMap & operator=(DynamicMap &&other) noexcept
Definition: dynamic_map.h:189
insert_return_type insert(UniquePtr< node_type > &&node)
Definition: dynamic_map.h:296
iterator erase(T &item)
Definition: intrusive_map.h:264
DynamicMap(DynamicMap &&other) noexcept
Definition: dynamic_map.h:182
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
size_type erase(K &&key)
Definition: dynamic_map.h:352
std::pair< iterator, bool > insert(const value_type &value)
Inserts a value into the map. Crashes on allocation failure.
Definition: dynamic_map.h:272
void swap(DynamicMap &other)
Swaps the contents and allocators of two maps. No allocations occur.
Definition: dynamic_map.h:383
UniquePtr< node_type > take(K &&key)
Removes the element with matching key and returns it as a UniquePtr.
Definition: dynamic_map.h:374
constexpr size_t max_size() const noexcept
Definition: intrusive_map.h:225
std::optional< std::pair< iterator, bool > > try_emplace(K &&key, Args &&... args)
Definition: dynamic_map.h:315
bool empty() const noexcept
Returns whether the map has zero items or not.
Definition: intrusive_map.h:217
std::pair< iterator, bool > emplace(K &&key, Args &&... args)
Constructs an element in-place. Crashes on allocation failure.
Definition: dynamic_map.h:322
void clear()
Removes all elements from the map and deallocates each node.
Definition: dynamic_map.h:250
UniquePtr< node_type > take(iterator pos)
Removes the element at pos and returns it as a UniquePtr.
Definition: dynamic_map.h:362
iterator erase(iterator first, iterator last)
Removes elements in the range [first, last).
Definition: dynamic_map.h:342
void insert(InputIt first, InputIt last)
Inserts a range of elements. Crashes on allocation failure.
Definition: dynamic_map.h:283
DynamicMap(const DynamicMap &)=delete
The Pigweed namespace.
Definition: alignment.h:27
Return type for node-based insertion.
Definition: dynamic_map.h:162