FastLED 3.9.15
Loading...
Searching...
No Matches
map.h
Go to the documentation of this file.
1#pragma once
2
3//#include <stddef.h>
4#include "fl/stdint.h"
5
6#include "fl/assert.h"
7#include "fl/comparators.h"
8#include "fl/insert_result.h"
9#include "fl/namespace.h"
10#include "fl/pair.h"
11#include "fl/type_traits.h"
12#include "fl/type_traits.h"
13#include "fl/vector.h"
14#include "fl/rbtree.h"
15#include "fl/allocator.h"
16
17namespace fl {
18
19// A simple unordered map implementation with a fixed size.
20// The user is responsible for making sure that the inserts
21// do not exceed the capacity of the set, otherwise they will
22// fail. Because of this limitation, this set is not a drop in
23// replacement for std::map.
24template <typename Key, typename Value, fl::size N> class FixedMap {
25 public:
27
31
32 // Constructor
33 constexpr FixedMap() = default;
34
35 iterator begin() { return data.begin(); }
36 iterator end() { return data.end(); }
37 const_iterator begin() const { return data.begin(); }
38 const_iterator end() const { return data.end(); }
39
40 iterator find(const Key &key) {
41 for (auto it = begin(); it != end(); ++it) {
42 if (it->first == key) {
43 return it;
44 }
45 }
46 return end();
47 }
48
49 const_iterator find(const Key &key) const {
50 for (auto it = begin(); it != end(); ++it) {
51 if (it->first == key) {
52 return it;
53 }
54 }
55 return end();
56 }
57
58 template <typename Less> iterator lowest(Less less_than = Less()) {
60 for (iterator it = begin(); it != end(); ++it) {
61 if (lowest == end() || less_than(it->first, lowest->first)) {
62 lowest = it;
63 }
64 }
65 return lowest;
66 }
67
68 template <typename Less>
69 const_iterator lowest(Less less_than = Less()) const {
71 for (const_iterator it = begin(); it != end(); ++it) {
72 if (lowest == end() || less_than(it->first, lowest->first)) {
73 lowest = it;
74 }
75 }
76 return lowest;
77 }
78
79 template <typename Less> iterator highest(Less less_than = Less()) {
81 for (iterator it = begin(); it != end(); ++it) {
82 if (highest == end() || less_than(highest->first, it->first)) {
83 highest = it;
84 }
85 }
86 return highest;
87 }
88
89 template <typename Less>
90 const_iterator highest(Less less_than = Less()) const {
92 for (const_iterator it = begin(); it != end(); ++it) {
93 if (highest == end() || less_than(highest->first, it->first)) {
94 highest = it;
95 }
96 }
97 return highest;
98 }
99
100 // We differ from the std standard here so that we don't allow
101 // dereferencing the end iterator.
102 bool get(const Key &key, Value *value) const {
103 const_iterator it = find(key);
104 if (it != end()) {
105 *value = it->second;
106 return true;
107 }
108 return false;
109 }
110
111 Value get(const Key &key, bool *has = nullptr) const {
112 const_iterator it = find(key);
113 if (it != end()) {
114 if (has) {
115 *has = true;
116 }
117 return it->second;
118 }
119 if (has) {
120 *has = false;
121 }
122 return Value();
123 }
124
125 pair<bool, iterator> insert(const Key &key, const Value &value,
126 InsertResult *result = nullptr) {
127 iterator it = find(key);
128 if (it != end()) {
129 if (result) {
131 }
132 // return false;
133 return {false, it};
134 }
135 if (data.size() < N) {
136 data.push_back(PairKV(key, value));
137 if (result) {
139 }
140 // return true;
141 return {true, data.end() - 1};
142 }
143 if (result) {
145 }
146 // return false;
147 return {false, end()};
148 }
149
150 // Move version of insert
151 pair<bool, iterator> insert(Key &&key, Value &&value,
152 InsertResult *result = nullptr) {
153 iterator it = find(key);
154 if (it != end()) {
155 if (result) {
157 }
158 return {false, it};
159 }
160 if (data.size() < N) {
161 data.push_back(PairKV(fl::move(key), fl::move(value)));
162 if (result) {
164 }
165 return {true, data.end() - 1};
166 }
167 if (result) {
169 }
170 return {false, end()};
171 }
172
173 bool update(const Key &key, const Value &value,
174 bool insert_if_missing = true) {
175 iterator it = find(key);
176 if (it != end()) {
177 it->second = value;
178 return true;
179 } else if (insert_if_missing) {
180 return insert(key, value).first;
181 }
182 return false;
183 }
184
185 // Move version of update
186 bool update(const Key &key, Value &&value,
187 bool insert_if_missing = true) {
188 iterator it = find(key);
189 if (it != end()) {
190 it->second = fl::move(value);
191 return true;
192 } else if (insert_if_missing) {
193 return insert(key, fl::move(value)).first;
194 }
195 return false;
196 }
197
198 Value &operator[](const Key &key) {
199 iterator it = find(key);
200 if (it != end()) {
201 return it->second;
202 }
203 data.push_back(PairKV(key, Value()));
204 return data.back().second;
205 }
206
207 const Value &operator[](const Key &key) const {
208 const_iterator it = find(key);
209 if (it != end()) {
210 return it->second;
211 }
212 static Value default_value;
213 return default_value;
214 }
215
216 bool next(const Key &key, Key *next_key,
217 bool allow_rollover = false) const {
218 const_iterator it = find(key);
219 if (it != end()) {
220 ++it;
221 if (it != end()) {
222 *next_key = it->first;
223 return true;
224 } else if (allow_rollover && !empty()) {
225 *next_key = begin()->first;
226 return true;
227 }
228 }
229 return false;
230 }
231
232 bool prev(const Key &key, Key *prev_key,
233 bool allow_rollover = false) const {
234 const_iterator it = find(key);
235 if (it != end()) {
236 if (it != begin()) {
237 --it;
238 *prev_key = it->first;
239 return true;
240 } else if (allow_rollover && !empty()) {
241 *prev_key = data[data.size() - 1].first;
242 return true;
243 }
244 }
245 return false;
246 }
247
248 // Get the current size of the vector
249 constexpr fl::size size() const { return data.size(); }
250
251 constexpr bool empty() const { return data.empty(); }
252
253 // Get the capacity of the vector
254 constexpr fl::size capacity() const { return N; }
255
256 // Clear the vector
257 void clear() { data.clear(); }
258
259 bool has(const Key &it) const { return find(it) != end(); }
260
261 bool contains(const Key &key) const { return has(key); }
262
263 private:
265};
266
267// Closest data structure to an std::map. Always sorted.
268// O(n + log(n)) for insertions, O(log(n)) for searches, O(n) for iteration.
269template <typename Key, typename Value, typename Less = fl::less<Key>>
271 public:
272 // Standard typedefs to match std::map interface
273 using key_type = Key;
274 using mapped_type = Value;
276 using size_type = fl::size;
278 using key_compare = Less;
282 using const_pointer = const value_type*;
283
284 private:
285 struct PairLess {
286 Less less;
287 bool operator()(const value_type &a, const value_type &b) const {
288 return less(a.first, b.first);
289 }
290 };
291
293
294 // Value comparison class for std::map compatibility
296 friend class SortedHeapMap;
297 Less comp_;
298 value_compare(Less c) : comp_(c) {}
299 public:
300 bool operator()(const value_type& x, const value_type& y) const {
301 return comp_(x.first, y.first);
302 }
303 };
304
305 public:
308
309 // Constructors
310 SortedHeapMap(Less less = Less()) : data(PairLess{less}) {}
311 SortedHeapMap(const SortedHeapMap& other) = default;
312 SortedHeapMap& operator=(const SortedHeapMap& other) = default;
313
314 // Iterators
315 iterator begin() { return data.begin(); }
316 iterator end() { return data.end(); }
317 const_iterator begin() const { return data.begin(); }
318 const_iterator end() const { return data.end(); }
319 const_iterator cbegin() const { return data.begin(); }
320 const_iterator cend() const { return data.end(); }
321
322 // Capacity
323 fl::size size() const { return data.size(); }
324 bool empty() const { return data.empty(); }
325 bool full() const { return data.full(); }
326 fl::size capacity() const { return data.capacity(); }
327 fl::size max_size() const { return data.capacity(); }
328
329 // FastLED specific methods
330 void setMaxSize(fl::size n) { data.setMaxSize(n); }
331 void reserve(fl::size n) { data.reserve(n); }
332
333 // Element access
334 Value &operator[](const Key &key) {
335 iterator it = find(key);
336 if (it != end()) {
337 return it->second;
338 }
339 value_type pair(key, Value());
340 bool ok = data.insert(pair);
341 FASTLED_ASSERT(ok, "Failed to insert into SortedHeapMap");
342 return data.find(pair)->second; // TODO: optimize.
343 }
344
345 Value &at(const Key &key) {
346 iterator it = find(key);
347 FASTLED_ASSERT(it != end(), "SortedHeapMap::at: key not found");
348 return it->second;
349 }
350
351 const Value &at(const Key &key) const {
352 const_iterator it = find(key);
353 FASTLED_ASSERT(it != end(), "SortedHeapMap::at: key not found");
354 return it->second;
355 }
356
357 // Modifiers
358 void clear() { data.clear(); }
359
362 bool success = data.insert(value, &result);
363 iterator it = success ? data.find(value) : data.end();
364 return fl::pair<iterator, bool>(it, success);
365 }
366
367 // Move version of insert
370 bool success = data.insert(fl::move(value), &result);
371 iterator it = success ? data.find(value) : data.end();
372 return fl::pair<iterator, bool>(it, success);
373 }
374
375 bool insert(const Key &key, const Value &value, InsertResult *result = nullptr) {
376 return data.insert(value_type(key, value), result);
377 }
378
379 // Move version of insert with key and value
380 bool insert(Key &&key, Value &&value, InsertResult *result = nullptr) {
381 return data.insert(value_type(fl::move(key), fl::move(value)), result);
382 }
383
384 template<class... Args>
388 bool success = data.insert(pair, &result);
389 iterator it = success ? data.find(pair) : data.end();
390 return fl::pair<iterator, bool>(it, success);
391 }
392
394 Key key = pos->first;
395 data.erase(*pos);
396 return upper_bound(key);
397 }
398
399 fl::size erase(const Key& key) {
400 return data.erase(value_type(key, Value())) ? 1 : 0;
401 }
402
403 bool erase(iterator it) {
404 return data.erase(it);
405 }
406
407 void swap(SortedHeapMap &other) {
408 data.swap(other.data);
409 }
410
411 // Lookup
412 fl::size count(const Key& key) const {
413 return contains(key) ? 1 : 0;
414 }
415
416 iterator find(const Key &key) {
417 return data.find(value_type(key, Value()));
418 }
419
420 const_iterator find(const Key &key) const {
421 return data.find(value_type(key, Value()));
422 }
423
424 bool contains(const Key &key) const {
425 return has(key);
426 }
427
428 bool has(const Key &key) const {
429 return data.has(value_type(key, Value()));
430 }
431
433 iterator lower = lower_bound(key);
434 iterator upper = upper_bound(key);
435 return fl::pair<iterator, iterator>(lower, upper);
436 }
437
443
444 iterator lower_bound(const Key &key) {
445 return data.lower_bound(value_type(key, Value()));
446 }
447
448 const_iterator lower_bound(const Key &key) const {
449 return data.lower_bound(value_type(key, Value()));
450 }
451
453 iterator it = lower_bound(key);
454 if (it != end() && it->first == key) {
455 ++it;
456 }
457 return it;
458 }
459
460 const_iterator upper_bound(const Key &key) const {
461 const_iterator it = lower_bound(key);
462 if (it != end() && it->first == key) {
463 ++it;
464 }
465 return it;
466 }
467
468 // Observers
470 return key_compare();
471 }
472
473 value_compare value_comp() const {
474 return value_compare(key_comp());
475 }
476
477 // Additional methods
478 value_type &front() { return data.front(); }
479 const value_type &front() const { return data.front(); }
480 value_type &back() { return data.back(); }
481 const value_type &back() const { return data.back(); }
482
483 void update(const Key &key, const Value &value) {
484 if (!insert(key, value)) {
485 iterator it = find(key);
486 it->second = value;
487 }
488 }
489
490 // Move version of update
491 void update(const Key &key, Value &&value) {
492 if (!insert(key, fl::move(value))) {
493 iterator it = find(key);
494 it->second = fl::move(value);
495 }
496 }
497
498 // Matches FixedMap<>::get(...).
499 bool get(const Key &key, Value *value) const {
500 const_iterator it = find(key);
501 if (it != end()) {
502 *value = it->second;
503 return true;
504 }
505 return false;
506 }
507
508 // Comparison operators
509 bool operator==(const SortedHeapMap &other) const {
510 if (size() != other.size()) {
511 return false;
512 }
513 for (const_iterator it = begin(), other_it = other.begin(); it != end();
514 ++it, ++other_it) {
515 if (it->first != other_it->first ||
516 it->second != other_it->second) {
517 return false;
518 }
519 }
520 return true;
521 }
522
523 bool operator!=(const SortedHeapMap &other) const {
524 return !(*this == other);
525 }
526};
527
528} // namespace fl
529
530// Drop-in replacement for std::map
531// Note: We use "fl_map" instead of "map" because Arduino.h defines a map() function
532// which would conflict with fl::map usage in sketches that include Arduino.h and
533// are using `using namespace fl`
534namespace fl {
535
536// Default map uses slab allocator for better performance
537// Can't use fl::map because it conflicts with Arduino.h's map() function when
538// the user is using `using namespace fl`
539template <typename Key, typename T, typename Compare = fl::less<Key>>
541
542
543} // namespace fl
int y
Definition simple.h:93
int x
Definition simple.h:92
uint8_t pos
Definition Blur.ino:11
bool contains(const Key &key) const
Definition map.h:261
constexpr fl::size size() const
Definition map.h:249
VectorType::iterator iterator
Definition map.h:29
iterator end()
Definition map.h:36
const_iterator begin() const
Definition map.h:37
bool prev(const Key &key, Key *prev_key, bool allow_rollover=false) const
Definition map.h:232
iterator lowest(Less less_than=Less())
Definition map.h:58
pair< bool, iterator > insert(Key &&key, Value &&value, InsertResult *result=nullptr)
Definition map.h:151
pair< bool, iterator > insert(const Key &key, const Value &value, InsertResult *result=nullptr)
Definition map.h:125
fl::pair< Key, Value > PairKV
Definition map.h:26
iterator begin()
Definition map.h:35
Value & operator[](const Key &key)
Definition map.h:198
bool update(const Key &key, Value &&value, bool insert_if_missing=true)
Definition map.h:186
const_iterator lowest(Less less_than=Less()) const
Definition map.h:69
const_iterator highest(Less less_than=Less()) const
Definition map.h:90
iterator find(const Key &key)
Definition map.h:40
bool next(const Key &key, Key *next_key, bool allow_rollover=false) const
Definition map.h:216
const_iterator find(const Key &key) const
Definition map.h:49
iterator highest(Less less_than=Less())
Definition map.h:79
bool update(const Key &key, const Value &value, bool insert_if_missing=true)
Definition map.h:173
const Value & operator[](const Key &key) const
Definition map.h:207
constexpr bool empty() const
Definition map.h:251
Value get(const Key &key, bool *has=nullptr) const
Definition map.h:111
FixedVector< PairKV, N > VectorType
Definition map.h:28
VectorType::const_iterator const_iterator
Definition map.h:30
void clear()
Definition map.h:257
constexpr FixedMap()=default
bool get(const Key &key, Value *value) const
Definition map.h:102
constexpr fl::size capacity() const
Definition map.h:254
const_iterator end() const
Definition map.h:38
const PairKV * const_iterator
Definition vector.h:88
bool operator()(const value_type &x, const value_type &y) const
Definition map.h:300
void update(const Key &key, Value &&value)
Definition map.h:491
iterator upper_bound(const Key &key)
Definition map.h:452
const value_type * const_pointer
Definition map.h:282
bool full() const
Definition map.h:325
const_iterator begin() const
Definition map.h:317
const_iterator end() const
Definition map.h:318
void update(const Key &key, const Value &value)
Definition map.h:483
value_compare value_comp() const
Definition map.h:473
fl::size size_type
Definition map.h:276
bool has(const Key &key) const
Definition map.h:428
bool erase(iterator it)
Definition map.h:403
iterator begin()
Definition map.h:315
value_type & reference
Definition map.h:279
fl::pair< iterator, bool > insert(value_type &&value)
Definition map.h:368
void swap(SortedHeapMap &other)
Definition map.h:407
iterator end()
Definition map.h:316
ptrdiff_t difference_type
Definition map.h:277
const value_type & const_reference
Definition map.h:280
const_iterator lower_bound(const Key &key) const
Definition map.h:448
const value_type & back() const
Definition map.h:481
SortedHeapMap(Less less=Less())
Definition map.h:310
fl::size count(const Key &key) const
Definition map.h:412
const value_type & front() const
Definition map.h:479
void reserve(fl::size n)
Definition map.h:331
fl::pair< iterator, bool > insert(const value_type &value)
Definition map.h:360
bool contains(const Key &key) const
Definition map.h:424
iterator lower_bound(const Key &key)
Definition map.h:444
bool operator!=(const SortedHeapMap &other) const
Definition map.h:523
fl::pair< const_iterator, const_iterator > equal_range(const Key &key) const
Definition map.h:438
SortedHeapVector< value_type, PairLess >::iterator iterator
Definition map.h:306
fl::size capacity() const
Definition map.h:326
fl::pair< Key, Value > value_type
Definition map.h:275
key_compare key_comp() const
Definition map.h:469
bool get(const Key &key, Value *value) const
Definition map.h:499
fl::size erase(const Key &key)
Definition map.h:399
const_iterator upper_bound(const Key &key) const
Definition map.h:460
SortedHeapVector< value_type, PairLess > data
Definition map.h:292
bool insert(const Key &key, const Value &value, InsertResult *result=nullptr)
Definition map.h:375
bool insert(Key &&key, Value &&value, InsertResult *result=nullptr)
Definition map.h:380
SortedHeapMap(const SortedHeapMap &other)=default
Value & operator[](const Key &key)
Definition map.h:334
const_iterator find(const Key &key) const
Definition map.h:420
Value mapped_type
Definition map.h:274
iterator find(const Key &key)
Definition map.h:416
const_iterator cbegin() const
Definition map.h:319
const_iterator cend() const
Definition map.h:320
void setMaxSize(fl::size n)
Definition map.h:330
value_type & back()
Definition map.h:480
Value & at(const Key &key)
Definition map.h:345
fl::size max_size() const
Definition map.h:327
SortedHeapVector< value_type, PairLess >::const_iterator const_iterator
Definition map.h:307
value_type * pointer
Definition map.h:281
fl::size size() const
Definition map.h:323
void clear()
Definition map.h:358
value_type & front()
Definition map.h:478
bool empty() const
Definition map.h:324
bool operator==(const SortedHeapMap &other) const
Definition map.h:509
Less key_compare
Definition map.h:278
const Value & at(const Key &key) const
Definition map.h:351
fl::pair< iterator, iterator > equal_range(const Key &key)
Definition map.h:432
SortedHeapMap & operator=(const SortedHeapMap &other)=default
iterator erase(const_iterator pos)
Definition map.h:393
fl::pair< iterator, bool > emplace(Args &&... args)
Definition map.h:385
HeapVector< T >::const_iterator const_iterator
Definition vector.h:755
HeapVector< T >::iterator iterator
Definition vector.h:754
Result type for promise operations.
Implements the FastLED namespace macros.
constexpr remove_reference< T >::type && move(T &&t) noexcept
Definition move.h:27
__PTRDIFF_TYPE__ ptrdiff_t
Definition cstddef.h:22
MapRedBlackTree< Key, T, Compare, fl::allocator_slab< char > > fl_map
Definition map.h:540
InsertResult
@ kMaxSize
@ kExists
@ kInserted
constexpr T && forward(typename remove_reference< T >::type &t) noexcept
IMPORTANT!
Definition crgb.h:20
corkscrew_args args
Definition old.h:150
Definition Keyboard.h:22
bool operator()(const value_type &a, const value_type &b) const
Definition map.h:287
Binary function object that returns whether the first argument is less than the second.
Definition utility.h:14
T1 first
Definition pair.h:14
Definition pair.h:9