#include <stdio.h>
#include <assert.h>
enum struct Mask_Downshift_State{
Begin,
Bits,
After,
};
constexpr
size_t get_shift_verify_mask(size_t mask)
{
size_t shift_length = 0;
size_t mask_check = mask;
Mask_Downshift_State state = Mask_Downshift_State::Begin;
for(size_t i = 0; i < sizeof(size_t) * 8; ++i)
{
size_t current_bit_value = mask_check & 1;
if(state == Mask_Downshift_State::Begin && current_bit_value == 1)
{
shift_length = i;
state = Mask_Downshift_State::Bits;
}
else if(state == Mask_Downshift_State::Bits && current_bit_value == 0)
{
state = Mask_Downshift_State::After;
}
else if(state == Mask_Downshift_State::After && current_bit_value == 1)
{
assert(false && "Bit mask is not contiguous");
}
mask_check >>= 1;
}
return shift_length;
}
template<size_t mask> constexpr
size_t mask_downshift(size_t value)
{
assert(mask && "Mask can't be 0");
constexpr size_t shift_length = get_shift_verify_mask(mask);
size_t result = (value & mask) >> shift_length;
return result;
}
int main(void) {
volatile size_t value = 0x0FF0123400FFF000;
size_t result = mask_downshift<0x0000FFFF00000000>(value);
printf("%lx\n", result);
return 0;
}