From 1db2f6bb847840b91ba858bde5cd2e309ef0321d Mon Sep 17 00:00:00 2001 From: Bart Trzynadlowski Date: Sun, 24 Sep 2017 18:40:58 +0000 Subject: [PATCH] Added functions to extract bits as integer values and updated comment about bit vector layout --- Src/Util/BitRegister.cpp | 46 +++++++++++++++++++++++++++++------ Src/Util/BitRegister.h | 18 +++++++++----- Src/Util/Test_BitRegister.cpp | 9 +++++++ 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/Src/Util/BitRegister.cpp b/Src/Util/BitRegister.cpp index c37f7d7..5a65235 100644 --- a/Src/Util/BitRegister.cpp +++ b/Src/Util/BitRegister.cpp @@ -4,12 +4,12 @@ namespace Util { - uint8_t BitRegister::GetLeftMost() const + uint8_t BitRegister::GetLeftmost() const { return m_bits.empty() ? m_no_data : m_bits.front(); } - uint8_t BitRegister::GetRightMost() const + uint8_t BitRegister::GetRightmost() const { return m_bits.empty() ? m_no_data : m_bits.back(); } @@ -42,6 +42,36 @@ namespace Util return value.length() - startPos; } + uint8_t BitRegister::GetBit(size_t pos) const + { + if (pos < Size()) + return m_bits[pos]; + return m_no_data; + } + + // Convert entire bit vector into a 64-bit integer. If bit register is larger + // than 64 bits, only least significant bits will be present. + uint64_t BitRegister::GetBits() const + { + return GetBits(0, Size()); + } + + // Convert a subset of the bit vector into a 64-bit integer. If the data does + // not fit into 64 bits, only the least significant (rightmost) bits. Result + // undefined if range falls outside of vector. + uint64_t BitRegister::GetBits(size_t from, size_t count) const + { + uint64_t value = 0; + if (from + count > Size()) + return value; + for (size_t i = from; i < from + count; i++) + { + value <<= 1; + value |= GetBit(i); + } + return value; + } + // Shift a bit into the right side, growing the vector by 1 void BitRegister::AddToRight(uint8_t bit) { @@ -59,7 +89,7 @@ namespace Util // Shift left by 1, returning ejected bit (shrinks vector) uint8_t BitRegister::RemoveFromLeft() { - uint8_t ejected = GetLeftMost(); + uint8_t ejected = GetLeftmost(); RemoveFromLeft(1); return ejected; } @@ -82,7 +112,7 @@ namespace Util // Shift right by 1, returning ejected bit (shrinks vector) uint8_t BitRegister::RemoveFromRight() { - uint8_t ejected = GetRightMost(); + uint8_t ejected = GetRightmost(); RemoveFromRight(1); return ejected; } @@ -100,7 +130,7 @@ namespace Util m_bits.resize(m_bits.size() - count); } - // Shift right and lose right-most bits, shifting in new bits from left to + // Shift right and lose Rightmost bits, shifting in new bits from left to // preserve vector size void BitRegister::ShiftRight(size_t count) { @@ -134,14 +164,14 @@ namespace Util memset(m_bits.data() + m_bits.size() - count, m_no_data, count); } - // Shift right and eject right-most bit, shifting new bit into left side to + // Shift right and eject Rightmost bit, shifting new bit into left side to // preserve vector size uint8_t BitRegister::ShiftOutRight(uint8_t bit) { if (Empty()) return m_no_data; - uint8_t ejected = GetRightMost(); + uint8_t ejected = GetRightmost(); ShiftRight(1); m_bits[0] = !!bit; return ejected; @@ -154,7 +184,7 @@ namespace Util if (Empty()) return m_no_data; - uint8_t ejected = GetLeftMost(); + uint8_t ejected = GetLeftmost(); ShiftLeft(1); m_bits[m_bits.size() - 1] = !!bit; return ejected; diff --git a/Src/Util/BitRegister.h b/Src/Util/BitRegister.h index 549e2a8..6fc9162 100644 --- a/Src/Util/BitRegister.h +++ b/Src/Util/BitRegister.h @@ -20,6 +20,11 @@ namespace Util return m_bits.size(); } + // Functions that return all or part of the bit register as an integer + uint8_t GetBit(size_t pos) const; + uint64_t GetBits() const; + uint64_t GetBits(size_t from, size_t count) const; + // Functions that grow/shrink the bit register void AddToRight(uint8_t bit); void AddToLeft(uint8_t bit); @@ -74,16 +79,17 @@ namespace Util * <-- left -- | 1 | 0 | 1 | 1 | ... | 1 | -- right --> * +---+---+---+---+-...-+---+ * - * "Left" means lower indices in the array. To remain flexible and agnostic - * about MSB vs. LSB and bit numbers, all functions are explicit about - * whether they are shifting in/out of the left/right side. It is up to the - * user to establish a consistent convention according to their use case. + * "Left" means lower indices in the array and bits are numbered left to + * right (leftmost bit is bit 0). Insertions of values into the bit vector + * place the MSB in a lower bit number than successive bits. For example, + * insertion of the 8-bit value 0xe2 at bit position 2 places the MSB (1) + * in bit 2, 0 in bit 3, 1 in bit 4, 0 in bit 5, etc. */ std::vector m_bits; uint8_t m_no_data = 0; // by default, assume non-existent bits are 0 - uint8_t GetLeftMost() const; - uint8_t GetRightMost() const; + uint8_t GetLeftmost() const; + uint8_t GetRightmost() const; static size_t HexStart(const std::string &value); static size_t BinStart(const std::string &value); static size_t CountBitsHex(const std::string &value, size_t startPos); diff --git a/Src/Util/Test_BitRegister.cpp b/Src/Util/Test_BitRegister.cpp index e8b78f0..5eb3b9a 100644 --- a/Src/Util/Test_BitRegister.cpp +++ b/Src/Util/Test_BitRegister.cpp @@ -292,6 +292,15 @@ int main(int argc, char **argv) expected.push_back("0x179"); results.push_back(reg.ToHexString()); + // Test + reg.Set("0x12345678"); + expected.push_back("ok"); + results.push_back(reg.GetBits() == 0x12345678 ? "ok" : "bad"); + expected.push_back("ok"); + results.push_back(reg.GetBits(0, 8) == 0x12 ? "ok" : "bad"); + expected.push_back("ok"); + results.push_back(reg.GetBits(26, 6) == 0x38 ? "ok" : "bad"); + // Check results size_t num_failed = 0; for (size_t i = 0; i < expected.size(); i++)