54#ifndef FASTLED_HASHMAP_INLINED_COUNT
55#define FASTLED_HASHMAP_INLINED_COUNT 8
58template <
typename Key,
typename T,
typename Hash = Hash<Key>,
59 typename KeyEqual = EqualTo<Key>,
60 int INLINED_COUNT = FASTLED_HASHMAP_INLINED_COUNT>
87 for (fl::size i = 0; i < other._buckets.size(); ++i) {
88 if (other.is_occupied(i)) {
89 insert(other._buckets[i].key, other._buckets[i].value);
102 other._tombstones = 0;
106 template<
typename InputIt>
128 if (
this != &other) {
133 if (
_buckets.size() != other._buckets.size()) {
135 _buckets.assign(other._buckets.size(), Entry{});
139 _deleted.resize(other._buckets.size());
143 for (fl::size i = 0; i < other._buckets.size(); ++i) {
144 if (other.is_occupied(i)) {
160 if (
this != &other) {
172 other._tombstones = 0;
227 return _map == o._map &&
_idx == o._idx;
234 fl::size cap =
_map->_buckets.size();
283 return _map == o._map &&
_idx == o._idx;
290 fl::size cap =
_map->_buckets.size();
308 return const_iterator(
this,
_buckets.size());
315 u32 lhs = (
size + tombstones) << 8;
349 FASTLED_ASSERT(idx !=
npos(),
"unordered_map::insert: invalid index");
352 return {iterator(
this, idx), is_new};
379 FASTLED_ASSERT(idx !=
npos(),
"unordered_map::insert: invalid index");
382 return {iterator(
this, idx), is_new};
388 return insert(kv.first, kv.second);
399 template<
typename InputIt>
401 for (; first != last; ++first) {
409 for (
const auto& kv :
init) {
436 FASTLED_ASSERT(idx !=
npos(),
"unordered_map::insert_or_assign: invalid index");
439 return {iterator(
this, idx), is_new};
463 FASTLED_ASSERT(idx !=
npos(),
"unordered_map::insert_or_assign: invalid index");
466 return {iterator(
this, idx), is_new};
471 template<
typename... Args>
481 template<
typename... Args>
489 template<
typename... Args>
512 return {iterator(
this, idx), is_new};
516 template<
typename... Args>
539 return {iterator(
this, idx), is_new};
557 if (it ==
end() || it._map !=
this) {
568 it.advance_to_occupied();
574 if (first._map !=
this || last._map !=
this) {
580 iterator current(
this, first._idx);
581 current.advance_to_occupied();
583 while (current !=
end() && current._idx < last._idx) {
584 fl::size idx_to_erase = current._idx;
586 current.advance_to_occupied();
630 return idx ==
npos() ?
end() : iterator(
this, idx);
635 return idx ==
npos() ?
end() : const_iterator(
this, idx);
640 return idx !=
npos();
646 FASTLED_ASSERT(
value !=
nullptr,
"unordered_map::at: key not found");
652 FASTLED_ASSERT(
value !=
nullptr,
"unordered_map::at: key not found");
663 iterator it =
find(key);
673 const_iterator it =
find(key);
677 const_iterator next = it;
715 static T default_value{};
716 FASTLED_ASSERT(
false,
"unordered_map::operator[]: Failed to allocate after rehash");
717 return default_value;
738 return static_cast<fl::size
>(-1) /
sizeof(Entry);
754 return static_cast<float>(
_size) /
static_cast<float>(
_buckets.size());
776 fl::size min_buckets =
_size;
777 if (n < min_buckets) {
792 if (max_lf <= 0.0f) {
796 fl::size required_buckets =
static_cast<fl::size
>(
797 static_cast<float>(n) / max_lf + 0.999999f
799 if (required_buckets >
_buckets.size()) {
806 return static_cast<fl::size
>(-1);
851 const fl::size cap =
_buckets.size();
852 const fl::size mask = cap - 1;
853 const fl::size h =
_hash(key) & mask;
854 fl::size first_tomb =
npos();
860 for (fl::size i = 0; i < cap; ++i) {
864 return {first_tomb !=
npos() ? first_tomb : idx,
true};
866 if (first_tomb ==
npos())
873 return {
npos(),
false};
884 const fl::size cap =
_buckets.size();
885 const fl::size mask = cap - 1;
886 const fl::size h =
_hash(key) & mask;
889 for (fl::size i = 0; i < cap; ++i) {
901 const Key &key,
const fl::bitset<1024> &occupied_set)
const FL_NO_EXCEPT {
902 const fl::size cap =
_buckets.size();
903 const fl::size mask = cap - 1;
904 const fl::size h =
_hash(key) & mask;
907 for (fl::size i = 0; i < cap; ++i) {
909 if (!occupied_set.test(idx)) {
918#if FL_PLATFORM_HAS_LARGE_MEMORY
921 fl::bitset<1024> old_occupied =
_occupied;
930 fl::bitset<1024> occupied;
933 if (resource ==
nullptr) {
936 void* mem = resource->
allocate(
sizeof(Scratch));
937 if (mem ==
nullptr) {
942 Scratch* scratch =
new (mem) Scratch(resource);
944 fl::bitset<1024>& old_occupied = scratch->occupied;
959 for (fl::size i = 0; i < old.
size(); i++) {
960 if (old_occupied.test(i))
963#if !FL_PLATFORM_HAS_LARGE_MEMORY
977 for (fl::size i = 0; i < cap; ++i) {
990 fl::bitset<1024> occupied;
995 for (fl::size i = 0; i <
_size; ++i) {
996 const bool already_finished = occupied.test(i);
997 if (already_finished) {
1006 if (idx ==
npos()) {
1009 false,
"unordered_map::rehash_inline_no_resize: invalid index");
1013 FASTLED_ASSERT(!tmp,
1014 "unordered_map::rehash_inline_no_resize: invalid tmp");
1023 while (!tmp.
empty()) {
1026 auto key = tmp.
ptr()->key;
1029 if (new_idx ==
npos()) {
1033 "unordered_map::rehash_inline_no_resize: invalid index");
1036 occupied.set(new_idx);
1037 if (new_idx <
_size) {
1050 "unordered_map::rehash_inline_no_resize: invalid occupied");
1052 tmp.
empty(),
"unordered_map::rehash_inline_no_resize: invalid tmp");
1062 if (
size() != other.size())
return false;
1063 for (
const auto& kv : *
this) {
1064 auto it = other.find(kv.first);
1065 if (it == other.end() || it->second != kv.second)
return false;
1072 return !(*
this == other);
1092template <
typename Key,
typename T,
typename Hash = Hash<Key>,
1093 typename KeyEqual = equal_to<Key>>
Alignment macros and utilities for FastLED.
void reset() FL_NO_EXCEPT
bool empty() const FL_NO_EXCEPT
void deallocate(void *p, fl::size bytes) FL_NO_EXCEPT
void * allocate(fl::size bytes) FL_NO_EXCEPT
Polymorphic memory resource base class (PMR-style).
iterator find(const Key &key) FL_NO_EXCEPT
void reserve(fl::size n) FL_NO_EXCEPT
bool erase(const Key &key) FL_NO_EXCEPT
iterator emplace_hint(const_iterator hint, Args &&... args) FL_NO_EXCEPT
unordered_map & operator=(fl::initializer_list< pair< Key, T > > init) FL_NO_EXCEPT
const T * find_value(const Key &key) const FL_NO_EXCEPT
Hash< vec2< u16 > > _hash
fl::bitset< 1024 > _occupied
unordered_map(InputIt first, InputIt last) FL_NO_EXCEPT
bool is_occupied(fl::size idx) const FL_NO_EXCEPT
fl::size max_size() const FL_NO_EXCEPT
unordered_map(fl::size n, const Hash &hf, const KeyEqual &eq) FL_NO_EXCEPT
const_iterator find(const Key &key) const FL_NO_EXCEPT
bool operator!=(const unordered_map &other) const FL_NO_EXCEPT
Inequality comparison.
bool is_deleted(fl::size idx) const FL_NO_EXCEPT
Hash hash_function() const FL_NO_EXCEPT
fl::size size() const FL_NO_EXCEPT
void swap(unordered_map &other) FL_NO_EXCEPT
unordered_map & operator=(unordered_map &&other) FL_NO_EXCEPT
bool contains(const Key &key) const FL_NO_EXCEPT
unordered_map() FL_NO_EXCEPT
unordered_map & operator=(const unordered_map &other) FL_NO_EXCEPT
bool remove(const Key &key) FL_NO_EXCEPT
void rehash_internal(fl::size new_cap) FL_NO_EXCEPT
void clear() FL_NO_EXCEPT
pair< iterator, iterator > equal_range(const Key &key) FL_NO_EXCEPT
pair< iterator, bool > insert_or_assign(const Key &key, T &&value) FL_NO_EXCEPT
bool needs_rehash() const FL_NO_EXCEPT
EqualTo< vec2< u16 > > _equal
float max_load_factor() const FL_NO_EXCEPT
static fl::size npos() FL_NO_EXCEPT
static bool NeedsRehash(fl::size size, fl::size bucket_size, fl::size tombstones, u8 load_factor) FL_NO_EXCEPT
fl::vector_inlined< Entry, FASTLED_HASHMAP_INLINED_COUNT > _buckets
float load_factor() const FL_NO_EXCEPT
pair< iterator, bool > insert(const vec2< u16 > &key, const u8 &value) FL_NO_EXCEPT
const T & at(const Key &key) const FL_NO_EXCEPT
pair< iterator, bool > insert(const pair< Key, T > &kv) FL_NO_EXCEPT
void insert(InputIt first, InputIt last) FL_NO_EXCEPT
void mark_occupied(fl::size idx) FL_NO_EXCEPT
pair< iterator, bool > emplace(Args &&... args) FL_NO_EXCEPT
iterator end() FL_NO_EXCEPT
KeyEqual key_eq() const FL_NO_EXCEPT
pair< iterator, bool > insert_or_assign(Key &&key, T &&value) FL_NO_EXCEPT
bool empty() const FL_NO_EXCEPT
const_iterator cend() const FL_NO_EXCEPT
unordered_map(fl::size initial_capacity, float max_load) FL_NO_EXCEPT
pair< iterator, bool > insert(pair< Key, T > &&kv) FL_NO_EXCEPT
iterator erase(iterator it) FL_NO_EXCEPT
unordered_map(memory_resource *resource) FL_NO_EXCEPT
pair< iterator, bool > try_emplace(const Key &k, Args &&... args) FL_NO_EXCEPT
void mark_empty(fl::size idx) FL_NO_EXCEPT
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_NULL_DEREFERENCE void rehash_inline_no_resize() FL_NO_EXCEPT
bool operator==(const unordered_map &other) const FL_NO_EXCEPT
Equality comparison (map equality: same key-value pairs, order-independent)
bool is_empty(fl::size idx) const FL_NO_EXCEPT
T * find_value(const Key &key) FL_NO_EXCEPT
struct FL_ALIGN_AS_T(EntryAlign::value) Entry
void mark_deleted(fl::size idx) FL_NO_EXCEPT
void setLoadFactor(float f) FL_NO_EXCEPT
void max_load_factor(float ml) FL_NO_EXCEPT
memory_resource * get_memory_resource() const FL_NO_EXCEPT
fl::size find_unoccupied_index_using_bitset(const Key &key, const fl::bitset< 1024 > &occupied_set) const FL_NO_EXCEPT
unordered_map(fl::initializer_list< pair< Key, T > > init) FL_NO_EXCEPT
max_align< vec2< u16 >, u8 > EntryAlign
const_iterator begin() const FL_NO_EXCEPT
const_iterator cbegin() const FL_NO_EXCEPT
iterator begin() FL_NO_EXCEPT
pair< iterator, bool > insert(Key &&key, T &&value) FL_NO_EXCEPT
fl::size bucket_count() const FL_NO_EXCEPT
pair< fl::size, bool > find_slot(const vec2< u16 > &key) const FL_NO_EXCEPT
void insert(fl::initializer_list< pair< Key, T > > init) FL_NO_EXCEPT
pair< iterator, bool > try_emplace(Key &&k, Args &&... args) FL_NO_EXCEPT
T & at(const Key &key) FL_NO_EXCEPT
void rehash(fl::size n) FL_NO_EXCEPT
T & operator[](const Key &key) FL_NO_EXCEPT
pair< const_iterator, const_iterator > equal_range(const Key &key) const FL_NO_EXCEPT
fl::size capacity() const FL_NO_EXCEPT
iterator erase(const_iterator first, const_iterator last) FL_NO_EXCEPT
fl::bitset< 1024 > _deleted
unordered_map(const unordered_map &other) FL_NO_EXCEPT
static fl::size next_power_of_two(fl::size n) FL_NO_EXCEPT
fl::size find_index(const vec2< u16 > &key) const FL_NO_EXCEPT
const_iterator end() const FL_NO_EXCEPT
unordered_map(fl::size initial_capacity) FL_NO_EXCEPT
unordered_map(unordered_map &&other) FL_NO_EXCEPT
fl::size count(const Key &key) const FL_NO_EXCEPT
fl::size size() const FL_NO_EXCEPT
PMR-style polymorphic memory resource for type-erased allocation.
constexpr remove_reference< T >::type && move(T &&t) FL_NO_EXCEPT
@ kUnorderedMapQuadraticProbingTries
@ kUnorderedMapLinearProbeOnlyThreshold
FL_NO_INLINE fl::size unordered_map_probe_idx(fl::size h, fl::size i, fl::size mask, fl::size cap) FL_NO_EXCEPT
constexpr remove_reference< T >::type && move(T &&t) FL_NO_EXCEPT
constexpr T && forward(typename remove_reference< T >::type &t) FL_NO_EXCEPT
void swap(array< T, N > &lhs, array< T, N > &rhs) FL_NO_EXCEPT
u8 u8 fract8 blur_amount FL_NO_EXCEPT
constexpr int type_rank< T >::value
unordered_map< Key, T, Hash, KeyEqual > hash_map
constexpr enable_if< is_fixed_point< T >::value, T >::type clamp(T x, T lo, T hi) FL_NO_EXCEPT
FASTLED_FORCE_INLINE U map_range(T value, T in_min, T in_max, U out_min, U out_max) FL_NO_EXCEPT
void init(Context &ctx, int w, int h) FL_NO_EXCEPT
memory_resource * default_memory_resource() FL_NO_EXCEPT
Get the default memory resource (wraps fl::Malloc / fl::Free / fl::realloc).
To bit_cast(const From &from) FL_NO_EXCEPT
VectorN< T, INLINED_SIZE > vector_inlined
Base definition for an LED controller.
#define FL_DISABLE_WARNING_PUSH
#define FL_DISABLE_WARNING_SHORTEN_64_TO_32
#define FL_DISABLE_WARNING_NULL_DEREFERENCE
#define FL_DISABLE_WARNING_POP
bool operator()(const T &a, const T &b) const FL_NO_EXCEPT
void advance_to_occupied() FL_NO_EXCEPT
pair< const Key, T > value_type
const value_type & reference
fl::forward_iterator_tag iterator_category
const_iterator(const unordered_map *m, fl::size idx) FL_NO_EXCEPT
reference operator*() const FL_NO_EXCEPT
bool operator!=(const const_iterator &o) const FL_NO_EXCEPT
bool operator==(const const_iterator &o) const FL_NO_EXCEPT
const value_type * pointer
pointer operator->() const FL_NO_EXCEPT
friend class unordered_map
const_iterator() FL_NO_EXCEPT
const_iterator(const iterator &it) FL_NO_EXCEPT
const unordered_map * _map
const_iterator & operator++() FL_NO_EXCEPT
const_iterator operator++(int) FL_NO_EXCEPT
iterator & operator++() FL_NO_EXCEPT
bool operator==(const iterator &o) const FL_NO_EXCEPT
fl::forward_iterator_tag iterator_category
pointer operator->() const FL_NO_EXCEPT
iterator operator++(int) FL_NO_EXCEPT
reference operator*() const FL_NO_EXCEPT
friend class unordered_map
bool operator!=(const iterator &o) const FL_NO_EXCEPT
void advance_to_occupied() FL_NO_EXCEPT
pair< const Key, T > value_type
iterator(unordered_map *m, fl::size idx) FL_NO_EXCEPT
#define FASTLED_HASHMAP_INLINED_COUNT