Added functions to extract bits as integer values and updated comment about bit vector layout

This commit is contained in:
Bart Trzynadlowski 2017-09-24 18:40:58 +00:00
parent 3041ca1922
commit 1db2f6bb84
3 changed files with 59 additions and 14 deletions

View file

@ -4,12 +4,12 @@
namespace Util namespace Util
{ {
uint8_t BitRegister::GetLeftMost() const uint8_t BitRegister::GetLeftmost() const
{ {
return m_bits.empty() ? m_no_data : m_bits.front(); 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(); return m_bits.empty() ? m_no_data : m_bits.back();
} }
@ -42,6 +42,36 @@ namespace Util
return value.length() - startPos; 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 // Shift a bit into the right side, growing the vector by 1
void BitRegister::AddToRight(uint8_t bit) void BitRegister::AddToRight(uint8_t bit)
{ {
@ -59,7 +89,7 @@ namespace Util
// Shift left by 1, returning ejected bit (shrinks vector) // Shift left by 1, returning ejected bit (shrinks vector)
uint8_t BitRegister::RemoveFromLeft() uint8_t BitRegister::RemoveFromLeft()
{ {
uint8_t ejected = GetLeftMost(); uint8_t ejected = GetLeftmost();
RemoveFromLeft(1); RemoveFromLeft(1);
return ejected; return ejected;
} }
@ -82,7 +112,7 @@ namespace Util
// Shift right by 1, returning ejected bit (shrinks vector) // Shift right by 1, returning ejected bit (shrinks vector)
uint8_t BitRegister::RemoveFromRight() uint8_t BitRegister::RemoveFromRight()
{ {
uint8_t ejected = GetRightMost(); uint8_t ejected = GetRightmost();
RemoveFromRight(1); RemoveFromRight(1);
return ejected; return ejected;
} }
@ -100,7 +130,7 @@ namespace Util
m_bits.resize(m_bits.size() - count); 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 // preserve vector size
void BitRegister::ShiftRight(size_t count) void BitRegister::ShiftRight(size_t count)
{ {
@ -134,14 +164,14 @@ namespace Util
memset(m_bits.data() + m_bits.size() - count, m_no_data, count); 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 // preserve vector size
uint8_t BitRegister::ShiftOutRight(uint8_t bit) uint8_t BitRegister::ShiftOutRight(uint8_t bit)
{ {
if (Empty()) if (Empty())
return m_no_data; return m_no_data;
uint8_t ejected = GetRightMost(); uint8_t ejected = GetRightmost();
ShiftRight(1); ShiftRight(1);
m_bits[0] = !!bit; m_bits[0] = !!bit;
return ejected; return ejected;
@ -154,7 +184,7 @@ namespace Util
if (Empty()) if (Empty())
return m_no_data; return m_no_data;
uint8_t ejected = GetLeftMost(); uint8_t ejected = GetLeftmost();
ShiftLeft(1); ShiftLeft(1);
m_bits[m_bits.size() - 1] = !!bit; m_bits[m_bits.size() - 1] = !!bit;
return ejected; return ejected;

View file

@ -20,6 +20,11 @@ namespace Util
return m_bits.size(); 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 // Functions that grow/shrink the bit register
void AddToRight(uint8_t bit); void AddToRight(uint8_t bit);
void AddToLeft(uint8_t bit); void AddToLeft(uint8_t bit);
@ -74,16 +79,17 @@ namespace Util
* <-- left -- | 1 | 0 | 1 | 1 | ... | 1 | -- right --> * <-- left -- | 1 | 0 | 1 | 1 | ... | 1 | -- right -->
* +---+---+---+---+-...-+---+ * +---+---+---+---+-...-+---+
* *
* "Left" means lower indices in the array. To remain flexible and agnostic * "Left" means lower indices in the array and bits are numbered left to
* about MSB vs. LSB and bit numbers, all functions are explicit about * right (leftmost bit is bit 0). Insertions of values into the bit vector
* whether they are shifting in/out of the left/right side. It is up to the * place the MSB in a lower bit number than successive bits. For example,
* user to establish a consistent convention according to their use case. * 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<uint8_t> m_bits; std::vector<uint8_t> m_bits;
uint8_t m_no_data = 0; // by default, assume non-existent bits are 0 uint8_t m_no_data = 0; // by default, assume non-existent bits are 0
uint8_t GetLeftMost() const; uint8_t GetLeftmost() const;
uint8_t GetRightMost() const; uint8_t GetRightmost() const;
static size_t HexStart(const std::string &value); static size_t HexStart(const std::string &value);
static size_t BinStart(const std::string &value); static size_t BinStart(const std::string &value);
static size_t CountBitsHex(const std::string &value, size_t startPos); static size_t CountBitsHex(const std::string &value, size_t startPos);

View file

@ -292,6 +292,15 @@ int main(int argc, char **argv)
expected.push_back("0x179"); expected.push_back("0x179");
results.push_back(reg.ToHexString()); 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 // Check results
size_t num_failed = 0; size_t num_failed = 0;
for (size_t i = 0; i < expected.size(); i++) for (size_t i = 0; i < expected.size(); i++)