Commit a6363bab authored by Joshua's avatar Joshua

Add Iterator for Bitfields

parent a55d5366
......@@ -17,40 +17,10 @@
#include <Endians.h>
#include <Error.h>
#include <array>
#include <iterator>
namespace Endians
{
/**
* @brief anonymous namespace to hide internal workings of this lib.
*
*/
namespace
{
/**
* @brief copies the source bit from source byte to destination bit in destination byte
*
* @param dest
* @param destPosition
* @param src
* @param srcPosition
*/
void copyBit(uint8_t& dest,
size_t destPosition,
uint8_t src,
size_t srcPosition)
{
if ((src & (1u << srcPosition)) != 0) {
// bit set in src, set in dest
dest |= (1u << destPosition);
} else {
// bit not set in src, unset in dest
dest &= ~(1u << destPosition);
}
}
} // namespace
/**
* @brief Order of bits in bytes.
*
......@@ -81,6 +51,124 @@ enum class BitOrder {
MSBAtZero
};
/**
* @brief anonymous namespace to hide internal workings of this lib.
*
*/
namespace
{
/**
* @brief represents a bit and exposes operations for getting and setting
*
*/
template <BitOrder bitOrder, size_t arraySize>
class Bit {};
template <size_t arraySize>
class Bit : public Bit<BitOrder::LSBAtZero, arraySize> {
private:
uint8_t* array;
size_t position;
constexpr size_t getByte() { return position / 8; }
constexpr uint8_t getBit() { return position % 8; }
public:
constexpr Bit(uint8_t* array, size_t position)
: array(array), position(position)
{
static_assert(position < (8 * arraySize), "out of bounds");
}
bool operator=() {return ((array[getByte()] & (1u << getBit()) != 0u); }
Bit& operator(bool value)
{
if (value) {
array[getByte] |= (1u << getBit());
} else {
array[getByte] &= ~(1u << getBit());
}
}
};
template <size_t arraySize>
class Bit : public Bit<BitOrder::MSBAtZero, arraySize> {
private:
uint8_t* array;
size_t position;
constexpr size_t getByte() { return position / 8; }
constexpr uint8_t getBit() { return 7 - position % 8; }
public:
constexpr Bit(uint8_t* array, size_t position)
: array(array), position(position)
{
static_assert(position < (8 * arraySize), "out of bounds");
}
bool operator=() {return ((array[getByte()] & (1u << getBit()) != 0u); }
Bit& operator(bool value)
{
if (value) {
array[getByte] |= (1u << getBit());
} else {
array[getByte] &= ~(1u << getBit());
}
}
};
/**
* @brief bit iterator.
*
* @tparam order
*/
template <BitOrder bitOrder, size_t arraySize>
class BitIterator : public std::iterator<std::forward_iterator_tag, Bit> {
size_t position;
bool end;
uint8_t* array;
public:
constexpr BitIterator(uint8_t* array, size_t position)
: array(array), position(position), end(false)
{}
constexpr BitIterator() : array(nullptr), position(0), end(true) {}
constexpr BitIterator& operator++()
{
++position;
if (position >= 8 * arraySize) {
array = nullptr;
end = true;
}
return *this;
}
constexpr bool operator==(const BitIterator& rhs) const
{
if (end && rhs.end) {
return true;
}
if (end != rhs.end) {
return false;
}
return (array == rhs.array) && (position == rhs.position);
}
constexpr bool operator!=(const BitIterator& rhs) const
{
return !(*this == rhs);
}
constexpr Bit operator*()
{
return Bit<bitOrder, arraySize>{array, position};
}
};
} // namespace
/**
* @brief Template class to hold information about a single bitfield.
*
......@@ -169,9 +257,9 @@ struct Bitfield {
T bitCheck{value};
Endians::machineToBig(bitCheck);
auto ref = reinterpret_cast<const uint8_t*>(&bitCheck);
auto ref = reinterpret_cast<uint8_t*>(&bitCheck);
// check for highest bit in value
for (size_t iByte = size - 1; iByte >= size / 8; --iByte ) {
for (size_t iByte = size - 1; iByte >= size / 8; --iByte) {
uint8_t maxVal = 0u;
if (size % 8 > 0) {
maxVal = 1u << size % 8;
......@@ -182,20 +270,10 @@ struct Bitfield {
}
}
// copy bitwise
constexpr auto startBitSrc = position + (8 * byteOffset);
constexpr auto endBitSrc = startBitSrc + size;
for (size_t srcBit = 0; srcBit < size; ++srcBit) {
size_t desBit;
// srcBit counts left to right when fieldOrder is inversed
if (fieldOrder == BitOrder::LSBAtZero) {
desBit = srcBit + startBitSrc;
} else {
desBit = endBitSrc - srcBit - 1;
}
}
auto desIter = BitIterator<
for (auto srcIter = BitIterator<fieldOrder, sizeof(T)>{ref, 0}; srcIter != BitIterator<fieldOrder, sizeof(T)>{}; ++srcIter) {
return Error::None;
}
}
// specializations for more restricted cases
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment