C++ (Qt)struct A { int a; // 2 bits int b; // 15}; struct B { A a; int b; // 26 int c; // 1 int d; // 53}; struct C { int a; // 42 B b[]; int c; // 12};
C++ (Qt)template<N, S>struct Field { bool v // if N == 1 int8_t v // if N <= 8 && S=signed uint8_t v // if N <= 8 && S=unsigned ...};
C++ (Qt)// Схемы пакетовauto ShemaPacket1 = std::make_tuple( 3, 3, 10, 52 );auto ShemaPacket2 = std::make_tuple( 9, 11, 37, 60, 1, 1 ); // Возвращает упакованный bit_arrayauto bits1 = pack( ShemaPacket1, 1, 2, 8, 1024 );auto bits2 = pack( ShemaPacket1, data.val1, data.val2, data.val3, data.val4 );auto bits3 = pack( ShemaPacket2, 15, 0, 0, 1024, 1, 0 ); // Возвращает кортеж значений по указанной схеме или exceptionauto result1 = unpack( bits1, ShemaPacket1 )auto [val1, val2, val3, val4] = unpack( bits1, ShemaPacket1 )auto result3 = unpack( bits3, ShemaPacket2 )
// Packed datastruct A { int a; // 2 bits int b; // 15};// State less business-logic classclass UnpackedA{public: int a() const { return *reinterpret_cast<const int*>(buf()) & 0x3; } int b() const { return *reinterpret_cast<const int*>(buf() + sizeof(int)) & 0x7FFF; } private:// Returns buffer of packed data const char* buf() const { return reinterpret_cast<const char*>(this); }};int foo() { A a; // e.g. got from network auto ua = new (&a) UnpackedA;}
C++ (Qt)static const unsigned int BitsInByte = 8; unsigned long readBits(unsigned char bits, unsigned char *buf, unsigned int *pBufPos){ unsigned int bufPos = *pBufPos, newBufPos = bufPos + bits; unsigned int bufIndexOfFirstByte = bufPos / BitsInByte; unsigned int ignoreBitsInFirstByte = bufPos % BitsInByte; unsigned int fullByteStart = bufPos + (BitsInByte - ignoreBitsInFirstByte); unsigned int additionalBits = newBufPos - fullByteStart; unsigned int bitsInLastByte = additionalBits - (additionalBits / BitsInByte) * BitsInByte; unsigned int bufIndexOfLastByte = (newBufPos - 1) / BitsInByte + (bitsInLastByte ? 0 : 1); // start with remainder bits of the first byte unsigned long value = buf[bufIndexOfFirstByte] >> ignoreBitsInFirstByte; // add "full" bytes in between for (unsigned int fullByteIndex = fullByteStart / BitsInByte, lshiftBits = BitsInByte - ignoreBitsInFirstByte; fullByteIndex < bufIndexOfLastByte; ++fullByteIndex, lshiftBits += BitsInByte) value |= buf[fullByteIndex] << lshiftBits; // end with a piece of the last byte if (bitsInLastByte) value |= (buf[bufIndexOfLastByte] & ((1 << bitsInLastByte) - 1)) << (bits - bitsInLastByte); *pBufPos = newBufPos; return value;} int main(){ unsigned char buf[] = {0, 0x1E, 0x40}; unsigned int pos = 0; std::cout << readBits(9, buf, &pos) << ' ' << readBits(13, buf, &pos) << '\n'; // 0 15 return 0;}
C++ (Qt)int main(){ std::array c = {std::byte{0}, std::byte{0x78}, std::byte{0x2}}; // swapped auto u = bitpacker::unpack(BP_STRING("<u9u13"), c); // < означает LSB std::cout << std::get<0>(u) << ' ' << std::get<1>(u) << '\n'; return 0;}
C++ (Qt)// C++17#include <type_traits>#include <iostream> struct I{ virtual int64_t value() const = 0; virtual void print() const = 0;}; template<int N>struct A : public I{ static constexpr auto size = N; std::conditional_t<size == 1, bool, std::conditional_t<size <= 8, char, int> > v; A(decltype(v) vv) : v(vv) {} int64_t value() const override { return v; } void print() const override { std::cout << size << ' ' << std::boolalpha << v << '\n'; }}; int main(){ A<1> a{true}; A<8> b{'!'}; A<10> c{42}; static_assert(a.size == 1); static_assert(std::is_same_v<decltype(a.v), bool>); static_assert(std::is_same_v<decltype(b.v), char>); static_assert(std::is_same_v<decltype(c.v), int>); for (auto const i : std::initializer_list<I const *>{&a, &b, &c}) { std::cout << i->value() << '\t'; i->print(); } return 0;}
C++ (Qt) /// finds the smallest fixed width unsigned integer that can fit NumBits bits template <size_type NumBits> using unsigned_type = std::conditional_t<NumBits <= 8, uint8_t, std::conditional_t<NumBits <= 16, uint16_t, std::conditional_t<NumBits <= 32, uint32_t, std::conditional_t<NumBits <= 64, uint64_t, void >>>>; /// finds the smallest fixed width signed integer that can fit NumBits bits template <size_type NumBits> using signed_type = std::conditional_t<NumBits <= 8, int8_t, std::conditional_t<NumBits <= 16, int16_t, std::conditional_t<NumBits <= 32, int32_t, std::conditional_t<NumBits <= 64, int64_t, void >>>>;
C++ (Qt)std::array c = {std::byte{0}, std::byte{0x78}, std::byte{0x2}};
struct LCanOpen{ union { uint64_t data; struct { int16_t x; int16_t y; int16_t rezerv; struct { uint16_t nx :2; uint16_t ny :2; uint16_t rezerv1 :12; }; }; };};struct Bjm{ union { uint64_t data; struct { uint64_t neutralX :2; uint64_t left :2; uint64_t right :2; uint64_t x :10; uint64_t neutralY :2; uint64_t back :2; uint64_t forward :2; uint64_t y :10; uint64_t rezerv :8; uint64_t but4 :2; uint64_t but3 :2; uint64_t but2 :2; uint64_t but1 :2; uint64_t but8 :2; uint64_t but7 :2; uint64_t but6 :2; uint64_t but5 :2; uint64_t but12 :2; uint64_t but11 :2; uint64_t but10 :2; uint64_t but9 :2; }; };};
uint64_t recData;uint8_t recBuf[100];recive(port1, &recData);recive(port2, recBuf);struct Bjm bjm;struct LCanOpen can;bjm.data = recData;//заполенение структуры простым "="memcpy(&can.data, &recbuf[13], 8); //заполнение структуры, в случае, если принятые данные не выровнены.recive(port1, &can.data);//обратный процесс*(uint64_t*)recBuf = bjm.data;//опасно, но быстро.//илиmemcpy(recBuf+13, &bjm.data, 8);//безопасно
unsigned int x = bjm.x;unsigned int y = can.ny
C++ (Qt)struct A { int m_B; int m_C; ... qint64 m_bits;}
union S{ std::int32_t n; // occupies 4 bytes std::uint8_t c; // occupies 1 byte};
union S{ std::int32_t n; // occupies 4 bytes std::uint32_t c; // occupies 4 byte float m; // occupies 4 byte MyType g; // occupies 4 byte};