16#include <initializer_list>
23#include "pw_allocator/allocator.h"
24#include "pw_assert/assert.h"
25#include "pw_containers/internal/traits.h"
26#include "pw_containers/intrusive_map.h"
45template <
typename Key,
typename Value>
51 class MapItem :
public IntrusiveMap<Key, MapItem>::Item {
57 template <
typename K,
typename... Args>
60 key_value(std::piecewise_construct,
61 std::forward_as_tuple(std::forward<K>(key)),
62 std::forward_as_tuple(std::forward<Args>(args)...)) {}
64 const Key& key()
const {
return key_value.first; }
65 Value& value() {
return key_value.second; }
66 const Value& value()
const {
return key_value.second; }
69 std::pair<const Key, Value> key_value;
70 friend class DynamicMap;
72 using Map = IntrusiveMap<Key, MapItem>;
77 template <
bool kIsConst>
80 using iterator_category = std::bidirectional_iterator_tag;
81 using value_type = std::pair<const Key, Value>;
82 using difference_type = std::ptrdiff_t;
84 std::conditional_t<kIsConst, const value_type&, value_type&>;
86 std::conditional_t<kIsConst, const value_type*, value_type*>;
88 constexpr Iterator() =
default;
90 constexpr reference operator*()
const {
return it_->key_value; }
91 constexpr pointer operator->()
const {
return &it_->key_value; }
93 constexpr Iterator operator++() {
97 constexpr Iterator operator++(
int) {
98 Iterator result = *
this;
102 constexpr Iterator operator--() {
106 constexpr Iterator operator--(
int) {
107 Iterator result = *
this;
112 constexpr friend bool operator==(Iterator lhs, Iterator rhs) {
113 return lhs.it_ == rhs.it_;
115 constexpr friend bool operator!=(Iterator lhs, Iterator rhs) {
116 return lhs.it_ != rhs.it_;
120 using BaseIterator = std::conditional_t<kIsConst,
121 typename Map::const_iterator,
122 typename Map::iterator>;
124 constexpr explicit Iterator(BaseIterator it) : it_(it) {}
127 friend class Iterator;
128 friend class DynamicMap;
134 using key_type = Key;
135 using mapped_type = Value;
136 using value_type = std::pair<const Key, Value>;
137 using size_type =
typename Map::size_type;
138 using difference_type =
typename Map::difference_type;
139 using key_compare =
typename Map::key_compare;
140 using allocator_type = Allocator;
141 using reference = value_type&;
142 using const_reference =
const value_type&;
143 using pointer = value_type*;
144 using const_pointer =
const value_type*;
145 using iterator = Iterator<false>;
146 using const_iterator = Iterator<true>;
147 using reverse_iterator = std::reverse_iterator<iterator>;
148 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
149 using insert_return_type = std::pair<iterator, bool>;
156 : allocator_(&allocator), map_() {}
166 allocator_ = other.allocator_;
167 map_.
swap(other.map_);
173 if (&other ==
this) {
177 allocator_ = other.allocator_;
178 map_.
swap(other.map_);
189 iterator begin() noexcept {
return iterator(map_.begin()); }
190 const_iterator begin() const noexcept {
return const_iterator(map_.begin()); }
191 const_iterator cbegin() const noexcept {
return begin(); }
192 iterator end() noexcept {
return iterator(map_.end()); }
193 const_iterator end() const noexcept {
return const_iterator(map_.end()); }
194 const_iterator cend() const noexcept {
return end(); }
195 reverse_iterator rbegin() noexcept {
return reverse_iterator(end()); }
196 const_reverse_iterator rbegin() const noexcept {
197 return const_reverse_iterator(end());
199 const_reverse_iterator crbegin() const noexcept {
return rbegin(); }
200 reverse_iterator rend() noexcept {
return reverse_iterator(begin()); }
201 const_reverse_iterator rend() const noexcept {
202 return const_reverse_iterator(begin());
204 const_reverse_iterator crend() const noexcept {
return rend(); }
210 mapped_type&
at(
const key_type& key) {
return map_.
at(key).value(); }
212 const mapped_type&
at(
const key_type& key)
const {
213 return map_.
at(key).value();
220 template <
typename U = mapped_type,
221 typename = std::enable_if_t<std::is_default_constructible_v<U>>>
223 return emplace(key).first->second;
228 [[nodiscard]]
bool empty()
const {
return map_.
empty(); }
229 size_type size()
const {
return map_.
size(); }
230 constexpr size_type max_size() const noexcept {
return map_.
max_size(); }
245 const value_type& value) {
252 std::optional<insert_return_type>
try_insert(value_type&&) =
delete;
255 insert_return_type
insert(
const value_type& value) {
256 return emplace(value.first, value.second);
259 insert_return_type
insert(value_type&& value) {
260 return emplace(std::move(value.first), std::move(value.second));
264 template <
typename InputIt,
265 typename = containers::internal::EnableIfInputIterator<InputIt>>
266 void insert(InputIt first, InputIt last) {
267 for (
auto it = first; it != last; ++it) {
268 emplace(it->first, it->second);
272 void insert(std::initializer_list<value_type> ilist) {
273 insert(ilist.begin(), ilist.end());
281 template <
typename K,
typename... Args>
282 [[nodiscard]] std::optional<std::pair<iterator, bool>>
try_emplace(
283 K&& key, Args&&... args) {
284 return TryEmplaceImpl(std::forward<K>(key), std::forward<Args>(args)...);
288 template <
typename K,
typename... Args>
289 std::pair<iterator, bool>
emplace(K&& key, Args&&... args) {
291 try_emplace(std::forward<K>(key), std::forward<Args>(args)...);
292 PW_ASSERT(result.has_value());
293 return result.value();
298 MapItem* item = &(*pos.it_);
299 auto next_it = map_.
erase(pos.it_);
301 return iterator(next_it);
304 iterator
erase(const_iterator pos) {
305 return erase(iterator(
typename Map::iterator(pos.it_)));
309 iterator
erase(iterator first, iterator last) {
310 while (first != last) {
311 first =
erase(first);
318 template <
typename K>
330 std::swap(allocator_, other.allocator_);
331 map_.
swap(other.map_);
337 for (
auto it = other.begin(); it != other.end();) {
338 auto result =
try_emplace(std::move(it->first), std::move(it->second));
339 if (result.has_value() && result.value().second) {
340 it = other.
erase(it);
351 size_type count(
const key_type& key) {
return contains(key) ? 1 : 0; }
353 iterator find(
const key_type& key) {
return iterator(map_.
find(key)); }
355 const_iterator find(
const key_type& key)
const {
356 return const_iterator(map_.
find(key));
359 [[nodiscard]]
bool contains(
const key_type& key)
const {
360 return find(key) != end();
363 std::pair<iterator, iterator> equal_range(
const key_type& key) {
365 return std::make_pair(iterator(result.first), iterator(result.second));
368 std::pair<const_iterator, const_iterator> equal_range(
369 const key_type& key)
const {
371 return std::make_pair(const_iterator(result.first),
372 const_iterator(result.second));
375 iterator lower_bound(
const key_type& key) {
379 const_iterator lower_bound(
const key_type& key)
const {
383 iterator upper_bound(
const key_type& key) {
387 const_iterator upper_bound(
const key_type& key)
const {
394 template <
typename K,
typename... Args>
395 [[nodiscard]] std::optional<std::pair<iterator, bool>> TryEmplaceImpl(
396 K&& key, Args&&... args) {
398 if (
auto it = map_.
find(key); it != map_.end()) {
399 return std::make_pair(iterator(it),
false);
401 MapItem* item = allocator_->template New<MapItem>(
402 std::forward<K>(key), std::forward<Args>(args)...);
403 if (item ==
nullptr) {
406 auto [item_it, inserted] = map_.
insert(*item);
408 return std::make_pair(iterator(item_it),
true);
411 Allocator* allocator_;
Definition: allocator.h:45
Definition: dynamic_map.h:46
Definition: intrusive_map.h:71
void Delete(T *ptr)
Definition: deallocator.h:99
MapItem(K &&key, Args &&... args)
Definition: dynamic_map.h:58
iterator erase(iterator pos)
Removes the element at pos and deallocates the node.
Definition: dynamic_map.h:297
constexpr allocator_type & get_allocator() const
Returns the allocator used by this map.
Definition: dynamic_map.h:185
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:222
constexpr DynamicMap(Allocator &allocator) noexcept
Definition: dynamic_map.h:155
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:336
iterator upper_bound(const key_type &key)
Definition: intrusive_map.h:321
mapped_type & at(const key_type &key)
Definition: dynamic_map.h:210
std::pair< iterator, bool > insert(T &item)
Definition: intrusive_map.h:241
DynamicMap & operator=(DynamicMap &&other) noexcept
Definition: dynamic_map.h:172
iterator erase(T &item)
Definition: intrusive_map.h:264
DynamicMap(DynamicMap &&other) noexcept
Definition: dynamic_map.h:165
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:319
void swap(DynamicMap &other)
Swaps the contents and allocators of two maps. No allocations occur.
Definition: dynamic_map.h:329
constexpr size_t max_size() const noexcept
Definition: intrusive_map.h:225
std::optional< insert_return_type > try_insert(const value_type &value)
Definition: dynamic_map.h:244
std::optional< std::pair< iterator, bool > > try_emplace(K &&key, Args &&... args)
Definition: dynamic_map.h:282
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:289
void clear()
Removes all elements from the map and deallocates each node.
Definition: dynamic_map.h:233
iterator erase(iterator first, iterator last)
Removes elements in the range [first, last).
Definition: dynamic_map.h:309
insert_return_type insert(const value_type &value)
Inserts a value into the map. Crashes on allocation failure.
Definition: dynamic_map.h:255
void insert(InputIt first, InputIt last)
Inserts a range of elements. Crashes on allocation failure.
Definition: dynamic_map.h:266
DynamicMap(const DynamicMap &)=delete
The Pigweed namespace.
Definition: alignment.h:27