mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 05:45:38 +00:00
Added functions to extract bits as integer values and updated comment about bit vector layout
This commit is contained in:
parent
3041ca1922
commit
1db2f6bb84
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++)
|
||||
|
|
Loading…
Reference in a new issue