Skip to content

Commit 9568ce5

Browse files
committed
optimal specialization
1 parent b3ead0a commit 9568ce5

File tree

2 files changed

+72
-3
lines changed

2 files changed

+72
-3
lines changed

Marlin/src/core/types.h

+43-3
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,53 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
159159
#define FI FORCE_INLINE
160160

161161
// Define types based on largest bit width stored value required
162-
#define bits_t(W) typename IF<((W)> 16), uint32_t, typename IF<((W)> 8), uint16_t, uint8_t>::type>::type
162+
#define bits_t(W) typename IF<((W)>32), uint64_t, typename IF<((W)>16), uint32_t, typename IF<((W)>8), uint16_t, uint8_t>::type>::type>::type
163163
#define uvalue_t(V) typename IF<((V)>65535), uint32_t, typename IF<((V)>255), uint16_t, uint8_t>::type>::type
164164
#define value_t(V) typename IF<((V)>32767), int32_t, typename IF<((V)>127), int16_t, int8_t>::type>::type
165165

166-
// General Flags for some number of states
166+
// Define a template for a bit field of N bits, using the smallest type that can hold N bits
167+
template<size_t N, bool UseArray = (N > 64)>
168+
struct Flags;
169+
170+
// Flag bits for <= 64 states
171+
template<size_t N>
172+
struct Flags<N, false> {
173+
typedef bits_t(N) flagbits_t;
174+
flagbits_t b;
175+
176+
class BitProxy {
177+
public:
178+
BitProxy(flagbits_t& data, int bit) : data_(data), bit_(bit) {}
179+
180+
BitProxy& operator=(const bool value) {
181+
if (value)
182+
data_ |= _BV(bit_);
183+
else
184+
data_ &= ~_BV(bit_);
185+
return *this;
186+
}
187+
188+
operator bool() const { return TEST(data_, bit_); }
189+
190+
private:
191+
flagbits_t& data_;
192+
uint8_t bit_;
193+
};
194+
195+
FI void reset() { b = 0; }
196+
FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); }
197+
FI void set(const int n) { b |= _BV(n); }
198+
FI void clear(const int n) { b &= ~_BV(n); }
199+
FI bool test(const int n) const { return TEST(b, n); }
200+
FI BitProxy operator[](const int n) { return BitProxy(b, n); }
201+
FI bool operator[](const int n) const { return test(n); }
202+
FI int size() const { return sizeof(b); }
203+
FI operator bool() const { return b != 0; }
204+
};
205+
206+
// Flag bits for more than 64 states
167207
template<size_t N>
168-
struct Flags {
208+
struct Flags<N, true> {
169209
uint8_t bitmask[(N+7)>>3];
170210
// Proxy class for handling bit assignment
171211
class BitProxy {

Marlin/tests/core/test_types.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,35 @@ MARLIN_TEST(types, Flags_32) {
532532
TEST_ASSERT_EQUAL(4, flags.size());
533533
}
534534

535+
MARLIN_TEST(types, Flags_64) {
536+
Flags<64> flags;
537+
538+
flags.reset();
539+
TEST_ASSERT_EQUAL(0, flags.b);
540+
541+
flags.set(0, true);
542+
flags.set(63, true);
543+
TEST_ASSERT_EQUAL(9223372036854775809ULL, flags.b);
544+
545+
flags.clear(0);
546+
flags.clear(63);
547+
TEST_ASSERT_EQUAL(0, flags.b);
548+
549+
flags.set(0, true);
550+
flags.set(63, true);
551+
TEST_ASSERT_EQUAL(true, flags.test(0));
552+
TEST_ASSERT_EQUAL(true, flags.test(63));
553+
TEST_ASSERT_EQUAL(false, flags.test(1));
554+
TEST_ASSERT_EQUAL(false, flags.test(62));
555+
556+
TEST_ASSERT_EQUAL(true, flags[0]);
557+
TEST_ASSERT_EQUAL(true, flags[63]);
558+
TEST_ASSERT_EQUAL(false, flags[1]);
559+
TEST_ASSERT_EQUAL(false, flags[62]);
560+
561+
TEST_ASSERT_EQUAL(4, flags.size());
562+
}
563+
535564
MARLIN_TEST(types, AxisFlags_const_as_bools) {
536565
const AxisFlags axis_flags_const_false = {0};
537566
TEST_ASSERT_FALSE(axis_flags_const_false);

0 commit comments

Comments
 (0)