Skip to content

Commit 8ad0566

Browse files
authored
[bit-utils] add MaskForBitSize() helper function (openthread#13295)
This commit adds `MaskForBitSize<UintType>(uint8_t aBitSize)` as a `constexpr inline` template helper function in `bit_utils.hpp`. It generates an unsigned integer bit-mask with the specified number of lowest bits set to 1. Key changes: - Adds `MaskForBitSize<UintType>(aBitSize)` in `bit_utils.hpp`. - Adds runtime (`VerifyOrQuit`) and compile-time (`static_assert`) unit tests in `test_bit_utils.cpp`.
1 parent b678a4f commit 8ad0566

2 files changed

Lines changed: 81 additions & 0 deletions

File tree

src/core/common/bit_utils.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,23 @@ uint16_t CountMatchingBits(const uint8_t *aFirst, const uint8_t *aSecond, uint16
9898
*/
9999
uint8_t DetermineMinBitSizeFor(uint32_t aValue);
100100

101+
/**
102+
* Generates an unsigned integer bit-mask with a specified number of lowest bits set to 1.
103+
*
104+
* @tparam UintType The value type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
105+
*
106+
* @param[in] aBitSize The number of lowest bits to set to 1.
107+
*
108+
* @returns The generated bit-mask.
109+
*/
110+
template <typename UintType> constexpr inline UintType MaskForBitSize(uint8_t aBitSize)
111+
{
112+
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
113+
114+
return (aBitSize >= BitSizeOf(UintType)) ? NumericLimits<UintType>::kMax
115+
: static_cast<UintType>((static_cast<UintType>(1) << aBitSize) - 1);
116+
}
117+
101118
/**
102119
* Sets the specified bit in a given integer to 1.
103120
*

tests/unit/test_bit_utils.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,69 @@ void TestDetermineMinBitSize(void)
176176
printf("TestDetermineMinBitSize() passed\n");
177177
}
178178

179+
void TestMaskForBitSize(void)
180+
{
181+
VerifyOrQuit(MaskForBitSize<uint8_t>(0) == 0);
182+
VerifyOrQuit(MaskForBitSize<uint8_t>(1) == 0x01);
183+
VerifyOrQuit(MaskForBitSize<uint8_t>(2) == 0x03);
184+
VerifyOrQuit(MaskForBitSize<uint8_t>(3) == 0x07);
185+
VerifyOrQuit(MaskForBitSize<uint8_t>(4) == 0x0f);
186+
VerifyOrQuit(MaskForBitSize<uint8_t>(7) == 0x7f);
187+
VerifyOrQuit(MaskForBitSize<uint8_t>(8) == 0xff);
188+
VerifyOrQuit(MaskForBitSize<uint8_t>(9) == 0xff);
189+
190+
VerifyOrQuit(MaskForBitSize<uint16_t>(0) == 0);
191+
VerifyOrQuit(MaskForBitSize<uint16_t>(7) == 0x007f);
192+
VerifyOrQuit(MaskForBitSize<uint16_t>(8) == 0x00ff);
193+
VerifyOrQuit(MaskForBitSize<uint16_t>(11) == 0x07ff);
194+
VerifyOrQuit(MaskForBitSize<uint16_t>(16) == 0xffff);
195+
VerifyOrQuit(MaskForBitSize<uint16_t>(20) == 0xffff);
196+
197+
VerifyOrQuit(MaskForBitSize<uint32_t>(0) == 0);
198+
VerifyOrQuit(MaskForBitSize<uint32_t>(16) == 0x0000ffff);
199+
VerifyOrQuit(MaskForBitSize<uint32_t>(31) == 0x7fffffff);
200+
VerifyOrQuit(MaskForBitSize<uint32_t>(32) == 0xffffffff);
201+
VerifyOrQuit(MaskForBitSize<uint32_t>(33) == 0xffffffff);
202+
203+
VerifyOrQuit(MaskForBitSize<uint64_t>(0) == 0);
204+
VerifyOrQuit(MaskForBitSize<uint64_t>(32) == 0xffffffffULL);
205+
VerifyOrQuit(MaskForBitSize<uint64_t>(63) == 0x7fffffffffffffffULL);
206+
VerifyOrQuit(MaskForBitSize<uint64_t>(64) == 0xffffffffffffffffULL);
207+
VerifyOrQuit(MaskForBitSize<uint64_t>(65) == 0xffffffffffffffffULL);
208+
209+
// Compile-time checks
210+
211+
static_assert(MaskForBitSize<uint8_t>(0) == 0, "MaskForBitSize<uint8_t>(0) failed");
212+
static_assert(MaskForBitSize<uint8_t>(1) == 0x01, "MaskForBitSize<uint8_t>(1) failed");
213+
static_assert(MaskForBitSize<uint8_t>(2) == 0x03, "MaskForBitSize<uint8_t>(2) failed");
214+
static_assert(MaskForBitSize<uint8_t>(3) == 0x07, "MaskForBitSize<uint8_t>(3) failed");
215+
static_assert(MaskForBitSize<uint8_t>(4) == 0x0f, "MaskForBitSize<uint8_t>(4) failed");
216+
static_assert(MaskForBitSize<uint8_t>(7) == 0x7f, "MaskForBitSize<uint8_t>(7) failed");
217+
static_assert(MaskForBitSize<uint8_t>(8) == 0xff, "MaskForBitSize<uint8_t>(8) failed");
218+
static_assert(MaskForBitSize<uint8_t>(9) == 0xff, "MaskForBitSize<uint8_t>(9) failed");
219+
220+
static_assert(MaskForBitSize<uint16_t>(0) == 0, "MaskForBitSize<uint16_t>(0) failed");
221+
static_assert(MaskForBitSize<uint16_t>(7) == 0x007f, "MaskForBitSize<uint16_t>(7) failed");
222+
static_assert(MaskForBitSize<uint16_t>(8) == 0x00ff, "MaskForBitSize<uint16_t>(8) failed");
223+
static_assert(MaskForBitSize<uint16_t>(11) == 0x07ff, "MaskForBitSize<uint16_t>(11) failed");
224+
static_assert(MaskForBitSize<uint16_t>(16) == 0xffff, "MaskForBitSize<uint16_t>(16) failed");
225+
static_assert(MaskForBitSize<uint16_t>(20) == 0xffff, "MaskForBitSize<uint16_t>(20) failed");
226+
227+
static_assert(MaskForBitSize<uint32_t>(0) == 0, "MaskForBitSize<uint32_t>(0) failed");
228+
static_assert(MaskForBitSize<uint32_t>(16) == 0x0000ffff, "MaskForBitSize<uint32_t>(16) failed");
229+
static_assert(MaskForBitSize<uint32_t>(31) == 0x7fffffff, "MaskForBitSize<uint32_t>(31) failed");
230+
static_assert(MaskForBitSize<uint32_t>(32) == 0xffffffff, "MaskForBitSize<uint32_t>(32) failed");
231+
static_assert(MaskForBitSize<uint32_t>(33) == 0xffffffff, "MaskForBitSize<uint32_t>(33) failed");
232+
233+
static_assert(MaskForBitSize<uint64_t>(0) == 0, "MaskForBitSize<uint64_t>(0) failed");
234+
static_assert(MaskForBitSize<uint64_t>(32) == 0xffffffffULL, "MaskForBitSize<uint64_t>(32) failed");
235+
static_assert(MaskForBitSize<uint64_t>(63) == 0x7fffffffffffffffULL, "MaskForBitSize<uint64_t>(63) failed");
236+
static_assert(MaskForBitSize<uint64_t>(64) == 0xffffffffffffffffULL, "MaskForBitSize<uint64_t>(64) failed");
237+
static_assert(MaskForBitSize<uint64_t>(65) == 0xffffffffffffffffULL, "MaskForBitSize<uint64_t>(65) failed");
238+
239+
printf("TestMaskForBitSize() passed\n");
240+
}
241+
179242
} // namespace ot
180243

181244
int main(void)
@@ -184,6 +247,7 @@ int main(void)
184247
ot::TestCountMatchingBitsAllCombinations();
185248
ot::TestCountMatchingBitsExamples();
186249
ot::TestDetermineMinBitSize();
250+
ot::TestMaskForBitSize();
187251

188252
printf("All tests passed\n");
189253
return 0;

0 commit comments

Comments
 (0)