Skip to content

Instantly share code, notes, and snippets.

@Yangff
Created April 17, 2019 20:22
Show Gist options
  • Save Yangff/9a8816b9a9f45fcb8af30f8991b02b2d to your computer and use it in GitHub Desktop.
Save Yangff/9a8816b9a9f45fcb8af30f8991b02b2d to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <cstddef>
#include <type_traits>
#include <cstring>
#include <cstdio>
template <size_t Size>
struct MinimumTypeHelper {
typedef
typename std::conditional<Size == 0 , void,
typename std::conditional<Size <= 8 , uint8_t,
typename std::conditional<Size <= 16, uint16_t,
typename std::conditional<Size <= 32, uint32_t,
typename std::conditional<Size <= 64, uint64_t,
void>::type>::type>::type>::type>::type type;
};
template<int firstBit, int bitSize>
struct BitFieldMember
{
using self_t = BitFieldMember<firstBit, bitSize>;
using T = typename MinimumTypeHelper<bitSize>::type;
static constexpr size_t firstByte = firstBit / 8;
static constexpr size_t lastByte = (firstBit + bitSize - 1) / 8;
static constexpr size_t tail = ((-(firstBit + bitSize)) % 8 + 8) % 8;
static constexpr size_t mask = (T(1) << bitSize) - 1;
uint8_t *_this()
{
return reinterpret_cast<uint8_t *>(this);
}
operator T() const {
T ret = 0;
for (size_t ii = firstByte; ii <= lastByte; ++ii ) {
ret = (ret << 8) | _this()[ii];
}
return (ret >> tail) & mask;
}
self_t& operator = (T m) {
m = (m & mask);
T write_mask = mask;
int ii = lastByte;
if (tail) { // take care of wrapping
uint8_t m1 = (m << tail) & 0xff;
uint8_t wm1 = (write_mask << tail) & 0xff;
uint8_t* ref = _this() + ii;
(*ref) &= (~wm1) & 0xff;
(*ref) |= (m1 & 0xff);
m >>= (8-tail);
write_mask >>= (8-tail);
ii--;
}
for (; ii >= 0 && 0 != write_mask; ii--) {
uint8_t* ref = _this() + ii;
(*ref) &= (~write_mask) & 0xff;
(*ref) |= (m & 0xff);
m >>= 8;
write_mask >>= 8;
}
return *this;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment