mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-29 17:15:40 +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
|
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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
Loading…
Reference in a new issue