FastLED 3.9.12
Loading...
Searching...
No Matches
map.h
1#pragma once
2
3#include <stdint.h>
4#include <stddef.h>
5
6#include "fl/namespace.h"
7#include "fl/vector.h"
8#include "fl/template_magic.h"
9#include "fl/insert_result.h"
10#include "fl/pair.h"
11#include "fl/assert.h"
12
13namespace fl {
14
15template<typename T>
17 bool operator()(const T& a, const T& b) const {
18 return a < b;
19 }
20};
21
22
23// A simple unordered map implementation with a fixed size.
24// The user is responsible for making sure that the inserts
25// do not exceed the capacity of the set, otherwise they will
26// fail. Because of this limitation, this set is not a drop in
27// replacement for std::map.
28template<typename Key, typename Value, size_t N>
29class FixedMap {
30public:
32
34 typedef typename VectorType::iterator iterator;
35 typedef typename VectorType::const_iterator const_iterator;
36
37
38 // Constructor
39 constexpr FixedMap() = default;
40
41 iterator begin() {
42 return data.begin();
43 }
44 iterator end() {
45 return data.end();
46 }
47 const_iterator begin() const {
48 return data.begin();
49 }
50 const_iterator end() const {
51 return data.end();
52 }
53
54 iterator find(const Key& key) {
55 for (auto it = begin(); it != end(); ++it) {
56 if (it->first == key) {
57 return it;
58 }
59 }
60 return end();
61 }
62
63 const_iterator find(const Key& key) const {
64 for (auto it = begin(); it != end(); ++it) {
65 if (it->first == key) {
66 return it;
67 }
68 }
69 return end();
70 }
71
72 template<typename Less>
73 iterator lowest(Less less_than = Less()) {
74 iterator lowest = end();
75 for (iterator it = begin(); it != end(); ++it) {
76 if (lowest == end() || less_than(it->first, lowest->first)) {
77 lowest = it;
78 }
79 }
80 return lowest;
81 }
82
83 template<typename Less>
84 const_iterator lowest(Less less_than = Less()) const {
85 const_iterator lowest = end();
86 for (const_iterator it = begin(); it != end(); ++it) {
87 if (lowest == end() || less_than(it->first, lowest->first)) {
88 lowest = it;
89 }
90 }
91 return lowest;
92 }
93
94 template<typename Less>
95 iterator highest(Less less_than = Less()) {
96 iterator highest = end();
97 for (iterator it = begin(); it != end(); ++it) {
98 if (highest == end() || less_than(highest->first, it->first)) {
99 highest = it;
100 }
101 }
102 return highest;
103 }
104
105 template<typename Less>
106 const_iterator highest(Less less_than = Less()) const {
107 const_iterator highest = end();
108 for (const_iterator it = begin(); it != end(); ++it) {
109 if (highest == end() || less_than(highest->first, it->first)) {
110 highest = it;
111 }
112 }
113 return highest;
114 }
115
116 // We differ from the std standard here so that we don't allow
117 // dereferencing the end iterator.
118 bool get(const Key& key, Value* value) const {
119 const_iterator it = find(key);
120 if (it != end()) {
121 *value = it->second;
122 return true;
123 }
124 return false;
125 }
126
127 Value get(const Key& key, bool* has=nullptr) const {
128 const_iterator it = find(key);
129 if (it != end()) {
130 if (has) {
131 *has = true;
132 }
133 return it->second;
134 }
135 if (has) {
136 *has = false;
137 }
138 return Value();
139 }
140
141 Pair<bool, iterator> insert(const Key& key, const Value& value, InsertResult* result = nullptr) {
142 iterator it = find(key);
143 if (it != end()) {
144 if (result) {
145 *result = InsertResult::kExists;
146 }
147 // return false;
148 return {false, it};
149 }
150 if (data.size() < N) {
151 data.push_back(PairKV(key, value));
152 if (result) {
153 *result = InsertResult::kInserted;
154 }
155 // return true;
156 return {true, data.end() - 1};
157 }
158 if (result) {
159 *result = InsertResult::kMaxSize;
160 }
161 //return false;
162 return {false, end()};
163 }
164
165 bool update(const Key& key, const Value& value, bool insert_if_missing = true) {
166 iterator it = find(key);
167 if (it != end()) {
168 it->second = value;
169 return true;
170 } else if (insert_if_missing) {
171 return insert(key, value).first;
172 }
173 return false;
174 }
175
176 Value& operator[](const Key& key) {
177 iterator it = find(key);
178 if (it != end()) {
179 return it->second;
180 }
181 data.push_back(PairKV(key, Value()));
182 return data.back().second;
183 }
184
185 const Value& operator[](const Key& key) const {
186 const_iterator it = find(key);
187 if (it != end()) {
188 return it->second;
189 }
190 static Value default_value;
191 return default_value;
192 }
193
194 bool next(const Key& key, Key* next_key, bool allow_rollover = false) const {
195 const_iterator it = find(key);
196 if (it != end()) {
197 ++it;
198 if (it != end()) {
199 *next_key = it->first;
200 return true;
201 } else if (allow_rollover && !empty()) {
202 *next_key = begin()->first;
203 return true;
204 }
205 }
206 return false;
207 }
208
209 bool prev(const Key& key, Key* prev_key, bool allow_rollover = false) const {
210 const_iterator it = find(key);
211 if (it != end()) {
212 if (it != begin()) {
213 --it;
214 *prev_key = it->first;
215 return true;
216 } else if (allow_rollover && !empty()) {
217 *prev_key = data[data.size() - 1].first;
218 return true;
219 }
220 }
221 return false;
222 }
223
224
225 // Get the current size of the vector
226 constexpr size_t size() const {
227 return data.size();
228 }
229
230 constexpr bool empty() const {
231 return data.empty();
232 }
233
234 // Get the capacity of the vector
235 constexpr size_t capacity() const {
236 return N;
237 }
238
239 // Clear the vector
240 void clear() {
241 data.clear();
242 }
243
244 bool has(const Key& it) const {
245 return find(it) != end();
246 }
247
248 bool contains(const Key& key) const {
249 return has(key);
250 }
251private:
252 VectorType data;
253};
254
255
256template <typename Key, typename Value, typename Less = fl::DefaultLess<Key>>
258private:
259 struct Pair {
260 Key first;
261 Value second;
262
263 Pair(const Key& k = Key(), const Value& v = Value())
264 : first(k), second(v) {}
265 };
266
267 struct PairLess {
268 Less less;
269 bool operator()(const Pair& a, const Pair& b) const {
270 return less(a.first, b.first);
271 }
272 };
273
275
276public:
277
280 typedef Pair value_type;
281
282 SortedHeapMap(Less less = Less())
283 : data(PairLess{less}) {
284 }
285
286 void setMaxSize(size_t n) {
287 data.setMaxSize(n);
288 }
289
290 void reserve(size_t n) {
291 data.reserve(n);
292 }
293
294 bool insert(const Key& key, const Value& value, InsertResult* result = nullptr) {
295 return data.insert(Pair(key, value), result);
296 }
297
298 void update(const Key& key, const Value& value) {
299 if (!insert(key, value)) {
300 iterator it = find(key);
301 it->second = value;
302 }
303 }
304
305 void swap(SortedHeapMap& other) {
306 data.swap(other.data);
307 }
308
309 Value& at(const Key& key) {
310 iterator it = find(key);
311 return it->second;
312 }
313
314 bool has(const Key& key) const {
315 return data.has(Pair(key));
316 }
317
318 bool contains(const Key& key) const {
319 return has(key);
320 }
321
322 bool operator==(const SortedHeapMap& other) const {
323 if (size() != other.size()) {
324 return false;
325 }
326 for (const_iterator it = begin(), other_it = other.begin();
327 it != end(); ++it, ++other_it) {
328 if (it->first != other_it->first || it->second != other_it->second) {
329 return false;
330 }
331 }
332 return true;
333 }
334
335 bool operator!=(const SortedHeapMap& other) const {
336 return !(*this == other);
337 }
338
339 size_t size() const { return data.size(); }
340 bool empty() const { return data.empty(); }
341 bool full() const { return data.full(); }
342 size_t capacity() const { return data.capacity(); }
343 void clear() { data.clear(); }
344
345 // begin, dend
346 iterator begin() { return data.begin(); }
347 iterator end() { return data.end(); }
348 const_iterator begin() const { return data.begin(); }
349 const_iterator end() const { return data.end(); }
350
351 iterator find(const Key& key) {
352 return data.find(Pair(key));
353 }
354 const_iterator find(const Key& key) const {
355 return data.find(Pair(key));
356 }
357
358 bool erase(const Key& key) {
359 return data.erase(Pair(key));
360 }
361 bool erase(iterator it) {
362 return data.erase(it);
363 }
364
365 iterator lower_bound(const Key& key) {
366 return data.lower_bound(Pair(key));
367 }
368
369 const_iterator lower_bound(const Key& key) const {
370 return data.lower_bound(Pair(key));
371 }
372
373 iterator upper_bound(const Key& key) {
374 iterator it = lower_bound(key);
375 if (it != end() && it->first == key) {
376 ++it;
377 }
378 return it;
379 }
380
381 const_iterator upper_bound(const Key& key) const {
382 const_iterator it = lower_bound(key);
383 if (it != end() && it->first == key) {
384 ++it;
385 }
386 return it;
387 }
388
389 Pair& front() { return data.front(); }
390 const Pair& front() const { return data.front(); }
391 Pair& back() { return data.back(); }
392 const Pair& back() const { return data.back(); }
393
394
395 Value& operator[](const Key& key) {
396 iterator it = find(key);
397 if (it != end()) {
398 return it->second;
399 }
400 Pair pair(key, Value());
401 bool ok = data.insert(pair);
402 FASTLED_ASSERT(ok, "Failed to insert into SortedHeapMap");
403 return data.find(pair)->second; // TODO: optimize.
404 }
405};
406
407} // namespace fl
Implements the FastLED namespace macros.
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16
Definition Keyboard.h:22
Definition pair.h:6