lib: bit manipulation functions

Functions for hiding all the masking and shifting required for accessing
bit ranges within an integer type.

Signed-off-by: Rick Altherr <kc8apf@kc8apf.net>
Signed-off-by: Tim 'mithro' Ansell <mithro@mithis.com>
This commit is contained in:
Rick Altherr 2017-12-01 08:47:21 -08:00 committed by Tim 'mithro' Ansell
parent 4d556f9112
commit f65ee46f7c
3 changed files with 84 additions and 0 deletions

View File

@ -6,6 +6,11 @@ target_include_directories(libprjxray PUBLIC "include")
target_link_libraries(libprjxray absl::strings)
if (PRJXRAY_BUILD_TESTING)
add_executable(bit_ops_test bit_ops_test.cc)
target_link_libraries(bit_ops_test libprjxray gtest_main)
add_test(NAME bit_ops_test
COMMAND bit_ops_test)
add_executable(memory_mapped_file_test memory_mapped_file_test.cc)
target_link_libraries(memory_mapped_file_test libprjxray gtest_main)
add_test(NAME memory_mapped_file_test

43
lib/bit_ops_test.cc Normal file
View File

@ -0,0 +1,43 @@
#include <prjxray/bit_ops.h>
#include <gtest/gtest.h>
TEST(BitMaskTest, Bit0) {
uint32_t expected = prjxray::bit_mask<uint32_t>(0);
EXPECT_EQ(static_cast<uint32_t>(0x1), expected);
}
TEST(BitMaskTest, Bit3) {
uint32_t expected = prjxray::bit_mask<uint32_t>(3);
EXPECT_EQ(static_cast<uint32_t>(0x8), expected);
}
TEST(BitMaskRange, SingleBit) {
uint32_t expected = prjxray::bit_mask_range<uint32_t>(23, 23);
EXPECT_EQ(static_cast<uint32_t>(0x800000), expected);
}
TEST(BitMaskRange, DownToZero) {
uint32_t expected = prjxray::bit_mask_range<uint32_t>(7, 0);
EXPECT_EQ(static_cast<uint32_t>(0xFF), expected);
}
TEST(BitMaskRange, MiddleBits) {
uint32_t expected = prjxray::bit_mask_range<uint32_t>(18, 8);
EXPECT_EQ(static_cast<uint32_t>(0x7FF00), expected);
}
TEST(BitFieldGetTest, OneSelectedBit) {
uint32_t expected = prjxray::bit_field_get(0xFFFFFFFF, 23, 23);
EXPECT_EQ(static_cast<uint32_t>(1), expected);
}
TEST(BitFieldGetTest, SelectDownToZero) {
uint32_t expected = prjxray::bit_field_get(0xFFCCBBAA, 7, 0);
EXPECT_EQ(static_cast<uint32_t>(0xAA), expected);
}
TEST(BitFieldGetTest, SelectMidway) {
uint32_t expected = prjxray::bit_field_get(0xFFCCBBAA, 18, 8);
EXPECT_EQ(static_cast<uint32_t>(0x4BB), expected);
}

View File

@ -0,0 +1,36 @@
#ifndef PRJXRAY_LIB_BIT_OPS_H
#define PRJXRAY_LIB_BIT_OPS_H
namespace prjxray {
template<typename UInt>
constexpr UInt bit_mask(int bit) {
return (static_cast<UInt>(1) << bit);
}
template<typename UInt>
constexpr UInt bit_sizeof() {
return sizeof(UInt) * 8;
}
template<typename UInt>
constexpr UInt bit_all_ones() {
return ~static_cast<UInt>(0);
}
template<typename UInt>
constexpr UInt bit_mask_range(int top_bit, int bottom_bit) {
return ((bit_all_ones<UInt>() >> (bit_sizeof<UInt>() - 1 - top_bit)) &
(bit_all_ones<UInt>() - bit_mask<UInt>(bottom_bit) +
static_cast<UInt>(1)));
}
template<typename UInt>
constexpr UInt bit_field_get(UInt value, int top_bit, int bottom_bit) {
return (value & bit_mask_range<UInt>(top_bit, bottom_bit)) >> bottom_bit;
}
} // namespace prjxray
#endif // PRJXRAY_LIB_BIT_OPS_H