ESPHome 2025.12.0-dev
Loading...
Searching...
No Matches
finite_set_mask.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <initializer_list>
6#include <iterator>
7#include <type_traits>
8
9namespace esphome {
10
13template<typename ValueType, int MaxBits> struct DefaultBitPolicy {
14 // Automatic bitmask type selection based on MaxBits
15 // ≤8 bits: uint8_t, ≤16 bits: uint16_t, otherwise: uint32_t
16 using mask_t = typename std::conditional<(MaxBits <= 8), uint8_t,
17 typename std::conditional<(MaxBits <= 16), uint16_t, uint32_t>::type>::type;
18
19 static constexpr int MAX_BITS = MaxBits;
20
21 static constexpr unsigned to_bit(ValueType value) { return static_cast<unsigned>(value); }
22
23 static constexpr ValueType from_bit(unsigned bit) { return static_cast<ValueType>(bit); }
24};
25
56template<typename ValueType, typename BitPolicy = DefaultBitPolicy<ValueType, 16>> class FiniteSetMask {
57 public:
58 using bitmask_t = typename BitPolicy::mask_t;
59
60 constexpr FiniteSetMask() = default;
61
63 constexpr FiniteSetMask(std::initializer_list<ValueType> values) {
64 for (auto value : values) {
65 this->insert(value);
66 }
67 }
68
70 constexpr void insert(ValueType value) { this->mask_ |= (static_cast<bitmask_t>(1) << BitPolicy::to_bit(value)); }
71
73 constexpr void insert(std::initializer_list<ValueType> values) {
74 for (auto value : values) {
75 this->insert(value);
76 }
77 }
78
80 constexpr void erase(ValueType value) { this->mask_ &= ~(static_cast<bitmask_t>(1) << BitPolicy::to_bit(value)); }
81
83 constexpr void clear() { this->mask_ = 0; }
84
87 constexpr size_t count(ValueType value) const {
88 return (this->mask_ & (static_cast<bitmask_t>(1) << BitPolicy::to_bit(value))) != 0 ? 1 : 0;
89 }
90
92 constexpr size_t size() const {
93 // Brian Kernighan's algorithm - efficient for sparse bitmasks
94 // Typical case: 2-4 modes out of 10 possible
95 bitmask_t n = this->mask_;
96 size_t count = 0;
97 while (n) {
98 n &= n - 1; // Clear the least significant set bit
99 count++;
100 }
101 return count;
102 }
103
105 constexpr bool empty() const { return this->mask_ == 0; }
106
110 class Iterator {
111 public:
112 using iterator_category = std::forward_iterator_tag;
113 using value_type = ValueType;
114 using difference_type = std::ptrdiff_t;
115 using pointer = const ValueType *;
116 using reference = ValueType;
117
118 constexpr explicit Iterator(bitmask_t mask) : mask_(mask) {}
119
120 constexpr ValueType operator*() const {
121 // Return value for the first set bit
122 return BitPolicy::from_bit(find_next_set_bit(mask_, 0));
123 }
124
125 constexpr Iterator &operator++() {
126 // Clear the lowest set bit (Brian Kernighan's algorithm)
127 mask_ &= mask_ - 1;
128 return *this;
129 }
130
131 constexpr bool operator==(const Iterator &other) const { return mask_ == other.mask_; }
132
133 constexpr bool operator!=(const Iterator &other) const { return !(*this == other); }
134
135 private:
136 bitmask_t mask_;
137 };
138
139 constexpr Iterator begin() const { return Iterator(mask_); }
140 constexpr Iterator end() const { return Iterator(0); }
141
143 constexpr bitmask_t get_mask() const { return this->mask_; }
144
147 static constexpr bool mask_contains(bitmask_t mask, ValueType value) {
148 return (mask & (static_cast<bitmask_t>(1) << BitPolicy::to_bit(value))) != 0;
149 }
150
153 static constexpr ValueType first_value_from_mask(bitmask_t mask) {
154 return BitPolicy::from_bit(find_next_set_bit(mask, 0));
155 }
156
159 static constexpr int find_next_set_bit(bitmask_t mask, int start_bit) {
160 int bit = start_bit;
161 while (bit < BitPolicy::MAX_BITS && !(mask & (static_cast<bitmask_t>(1) << bit))) {
162 ++bit;
163 }
164 return bit;
165 }
166
167 protected:
169};
170
171} // namespace esphome
Iterator support for range-based for loops and API encoding Iterates over set bits and converts bit p...
constexpr ValueType operator*() const
constexpr bool operator!=(const Iterator &other) const
constexpr Iterator(bitmask_t mask)
constexpr Iterator & operator++()
std::forward_iterator_tag iterator_category
constexpr bool operator==(const Iterator &other) const
Generic bitmask for storing a finite set of discrete values efficiently.
static constexpr ValueType first_value_from_mask(bitmask_t mask)
Get the first value from a raw bitmask Used for optimizing intersection logic (e.g....
constexpr size_t count(ValueType value) const
Check if the set contains a specific value (std::set compatibility) Returns 1 if present,...
constexpr void clear()
Clear all values from the set.
constexpr Iterator end() const
constexpr void insert(std::initializer_list< ValueType > values)
Add multiple values from initializer list.
constexpr bitmask_t get_mask() const
Get the raw bitmask value for optimized operations.
constexpr void insert(ValueType value)
Add a single value to the set (std::set compatibility)
constexpr FiniteSetMask()=default
constexpr void erase(ValueType value)
Remove a value from the set (std::set compatibility)
constexpr bool empty() const
Check if the set is empty.
static constexpr int find_next_set_bit(bitmask_t mask, int start_bit)
Find the next set bit in a bitmask starting from a given position Returns the bit position,...
constexpr FiniteSetMask(std::initializer_list< ValueType > values)
Construct from initializer list: {VALUE1, VALUE2, ...}.
constexpr size_t size() const
Count the number of values in the set.
static constexpr bool mask_contains(bitmask_t mask, ValueType value)
Check if a specific value is present in a raw bitmask Useful for checking intersection results withou...
typename BitPolicy::mask_t bitmask_t
constexpr Iterator begin() const
uint16_t type
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
Default bit mapping policy for contiguous enums starting at 0 Provides 1:1 mapping where enum value e...
typename std::conditional<(MaxBits<=8), uint8_t, typename std::conditional<(MaxBits<=16), uint16_t, uint32_t >::type >::type mask_t
static constexpr unsigned to_bit(ValueType value)
static constexpr int MAX_BITS
static constexpr ValueType from_bit(unsigned bit)