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
{
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;

View file

@ -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<uint8_t> 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);

View file

@ -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++)