XML <DataItem id="020"> <DataItemName>Target Report Descriptor</DataItemName> <DataItemDefinition>Type and characteristics of the radar data as transmitted by a radar station.</DataItemDefinition> <DataItemFormat desc="Variable length Data Item comprising a first part of oneoctet, followed by one-octet extents as necessary."> <Variable> <Fixed length="1"> <Bits bit="8"> <BitsShortName>TYP</BitsShortName> <BitsValue val="0">Plot</BitsValue> <BitsValue val="1">Track</BitsValue> </Bits> <Bits bit="7"> <BitsShortName>SIM</BitsShortName> <BitsValue val="0">Actual plot or track</BitsValue> <BitsValue val="1">Simulated plot or track</BitsValue> </Bits> <Bits from="6" to="5"> <BitsShortName>SSRPSR</BitsShortName> <BitsValue val="0">No detection</BitsValue> <BitsValue val="1">Sole primary detection</BitsValue> <BitsValue val="2">Sole secondary detection</BitsValue> <BitsValue val="3">Combined primary and secondary detection</BitsValue> </Bits> <Bits bit="4"> <BitsShortName>ANT</BitsShortName> <BitsValue val="0">Target report from antenna 1</BitsValue> <BitsValue val="1">Target report from antenna 2</BitsValue> </Bits> <Bits bit="3"> <BitsShortName>SPI</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Special Position Identification</BitsValue> </Bits> <Bits bit="2"> <BitsShortName>RAB</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Plot or track from a fixed transponder</BitsValue> </Bits> <Bits bit="1" fx="1"> <BitsShortName>FX</BitsShortName> <BitsValue val="0">End of Data Item</BitsValue> <BitsValue val="1">Extension into first extent</BitsValue> </Bits> </Fixed> <Fixed length="1"> <Bits bit="8"> <BitsShortName>TST</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Test target indicator</BitsValue> </Bits> <Bits from="7" to="6"> <BitsShortName>DS1DS2</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Unlawful interference (code 7500)</BitsValue> <BitsValue val="2">Radio-communication failure (code 7600)</BitsValue> <BitsValue val="3">Emergency (code 7700)</BitsValue> </Bits> <Bits bit="5"> <BitsShortName>ME</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Military emergency</BitsValue> </Bits> <Bits bit="4"> <BitsShortName>MI</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Military identification</BitsValue> </Bits> <Bits from="3" to="2"> <BitsShortName>spare</BitsShortName> <BitsName>spare bits set to 0</BitsName> <BitsConst>0</BitsConst> </Bits> <Bits bit="1" fx="1"> <BitsShortName>FX</BitsShortName> <BitsValue val="0">End of Data Item</BitsValue> <BitsValue val="1">Extension into next extent</BitsValue> </Bits> </Fixed> </Variable> </DataItemFormat> </DataItem> <DataItem id="040"> <DataItemName>Measured Position in Polar Coordinates</DataItemName> <DataItemDefinition>Measured position of an aircraft in local polar coordinates.</DataItemDefinition> <DataItemFormat desc="Four-octet fixed length Data Item."> <Fixed length="4"> <Bits from="32" to="17"> <BitsShortName>RHO</BitsShortName> <BitsUnit max="512" scale="0.0078125">NM</BitsUnit> </Bits> <Bits from="16" to="1"> <BitsShortName>THETA</BitsShortName> <BitsUnit scale="0.0054931640625">deg</BitsUnit> </Bits> </Fixed> </DataItemFormat> </DataItem>
C++ (Qt)record.item( "040" ).field( "RHO" );
C++ (Qt) struct Record{ Bytes m_bytes; // BitField< Byte number, First bit, Last bit > BitField<0, 0, 1> flag; BitField<0, 1, 5> mode; BitField<0, 5, 14> address; Record () : flag( m_bytes ), mode( m_bytes ), address( m_bytes ) {}};
C++ (Qt)void A::Read( Stream & strem ){ int version = stream.ReadInt(); m_A = stream.ReadInt(); m_B = stream.ReadInt(); if (version > 1) { ...
C++ (Qt) struct record { bit_field<1> flag; bit_field<4> mode; bit_field<9> address; bit_array pack() const { return ::pack( flag, mode, address ); } static record unpack( const bit_array &src ) { record result; ::unpack( src, result.flag, result.mode, result.address ); return result; } };
C++ (Qt)class bit_field_base; class bit_record{public: void reg_field( bit_field_base *field ) { assert( field ); m_orderedFields.push_back( field ); } private: std::list<bit_field_base*> m_orderedFields;}; class bit_field_base{public: bit_field_base( bit_record &record ) { record.reg_field( this ); }} // ================================================= class DataRecord : public bit_record{public: DataRecord() : m_fld1( *this ), m_fld2( *this ), m_fld3( *this ) {} private: bit_field<1> m_fld1; bit_field<2> m_fld2; bit_field<3> m_fld3;};
C++ (Qt)using BitFieldSizeType = uint8_t; template<typename T>T parseNumber(gsl::span<uint8_t> const& sp, uint64_t& offset, BitFieldSizeType size){ /* auto value = bitpacker::extract<T>(sp, offset, size); offset += size; return value; */ return readBits(size, sp.data(), &offset); // own impl} template<BitFieldSizeType Bits>struct BitField{ static constexpr auto size = Bits; std::conditional_t<size == 1, bool, std::conditional_t<size <= 8, uint8_t, std::conditional_t<size <= 16, uint16_t, std::conditional_t<size <= 32, uint32_t, uint64_t> > > > v; BitField() { static_assert(size <= 64); } auto parse(gsl::span<uint8_t> const& sp, uint64_t& offset) { v = parseNumber<decltype(v)>(sp, offset, size); return v; } operator auto() const { return v; }}; template<std::size_t Size, BitFieldSizeType Bits>struct BitArray{ std::array<BitField<Bits>, Size> arr; auto parse(gsl::span<uint8_t> const& sp, uint64_t& offset) { for (auto& el : arr) el.parse(sp, offset); return arr; }}; // helper typesusing BitFieldBool1 = BitField<1>; template<std::size_t Size, BitFieldSizeType Bits = 8>using BitString = BitArray<Size, Bits>;
C++ (Qt)// helper typesstruct NarrowString{ std::string string; uint8_t maxCharacters; NarrowString(uint8_t maxCharacters_) : maxCharacters{maxCharacters_} { assert(maxCharacters > 0); string.reserve(maxCharacters - 1); } auto parse(gsl::span<uint8_t> const& sp, uint64_t& offset) { for (decltype(maxCharacters) j = 0; j < maxCharacters; ++j) { auto c = BitField<7>{}.parse(sp, offset); if (c == 0) break; string += c; } return string; } operator auto() const { return string; }}; template<BitFieldSizeType N>struct ConditionalBitField{ BitField<N> _value; std::optional<bool> condition; ConditionalBitField(decltype(condition) condition_ = std::nullopt) : condition{condition_} {} std::optional<decltype(_value.v)> parse(gsl::span<uint8_t> const& sp, uint64_t& offset) { bool shouldReadField = condition ? *condition : BitFieldBool1{}.parse(sp, offset); if (!shouldReadField) return std::nullopt; return _value.parse(sp, offset); }}; // bit structsstruct BasicBitItem{ BitField<16> header; BitFieldBool1 isQuest; BitField<3> _1; BitFieldBool1 isIdentified; BitField<5+1> _2; BitFieldBool1 isSocketed; BitField<2+1+1> _3; BitFieldBool1 isEar; BitFieldBool1 isStarter; BitField<2+1> _4; BitFieldBool1 isSimple; BitFieldBool1 isEthereal; BitFieldBool1 _5; BitFieldBool1 isPersonalized; BitFieldBool1 _6; BitFieldBool1 isRW; BitField<5+8+2> _7; BitField<3> location; BitField<4> whereEquipped; BitField<4> column; BitField<4> row; BitField<3> storage;}; struct ExtendedBitItem{ BitField<3> socketablesNumber; BitField<32> guid; BitField<7> ilvl; BitField<4> quality; ConditionalBitField<3> variableGraphics; ConditionalBitField<11> autoprefix;}; template <typename F>void parseField(F& field, gsl::span<uint8_t> const& sp, uint64_t& i){ field.parse(sp, i);} template <typename T>T parse(gsl::span<uint8_t> const& sp, uint64_t& i){ T t; boost::pfr::for_each_field(t, [&sp, &i](auto& f) { parseField(f, sp, i); }); return t;} int main(){ // read file... gsl::span sp{buf, fileSize}; uint64_t offset = 0; auto base = parse<BasicBitItem>(sp, offset); if (base.isSimple) return 0; auto extended = parse<ExtendedBitItem>(sp, offset); auto someField = ConditionalBitField<16>{base.isRW}.parse(sp, offset); if (base.isPersonalized) auto inscribedName = NarrowString{16}.parse(sp, offset); // further conditions... return 0;}
C++ (Qt)void A::ReadWrite( CBitStream & stream, TMode mode ) { stream.ReadWriteInt(&m_B, 4, mode); ...}
C++ (Qt)usiing TBitKey = std::pair<const std::type_info *, size_t>; template<class Owner, class Member>int GetBitCount( const Owner & owner, const Member & member ){// offsetof ? char * base = (char *) &owner; char * addr = (char *) &member; assert(addr >= base); assert(adrr <= base + sizeof(base); auto it = theGlobalBitsMap.find(TBitKey(&std::typeid(Owner), addr - base)); assert(it != theGlobalBitsMap.end()); return it->second; } // usagevoid A::ReadWrite( CBitStream & stream, TMode mode ) { stream.ReadWriteBits(&m_B, GetBitCount(*this, m_B), mode); ...}
C++ (Qt)A a;auto t = std::type_index(std::typeid(A));theGlobalBitsMap[{t, &a.m_B - &a}] = 6;
C++ (Qt)stream.ReadWriteBits(&m_B, GetBitCount(*this, m_B), mode);
C++ (Qt)template<class Owner, class Member>void SetBitsCount( const Owner & owner, const Member & member, int bitsCount );
C++ (Qt)const std::type_info& ti1 = typeid(A);const std::type_info& ti2 = typeid(A); assert(&ti1 == &ti2); // not guaranteedassert(ti1.hash_code() == ti2.hash_code()); // guaranteedassert(std::type_index(ti1) == std::type_index(ti2)); // guaranteed
C++ (Qt) boost::pfr::for_each_field(some_struct, [](auto const& f) { // делаем с полем f что хотим std::cout << f.size; });
C++ (Qt)std::cout << boost::pfr::io(some_struct);
C++ (Qt)union CFlag { uint32 m_value; struct { uint32 m_A : 1; uint32 m_B : 2; ... }; };