diff --git a/include/sp/io/MessageIO.h b/include/sp/io/MessageIO.h index 9dc5440..6d7b596 100644 --- a/include/sp/io/MessageIO.h +++ b/include/sp/io/MessageIO.h @@ -3,19 +3,51 @@ #include #include #include +#include namespace sp { namespace details { +template +void WriteField(DataBuffer& a_Buffer, const BitField& a_Data, std::uint64_t& a_DataRaw, std::size_t& a_Offset) { + T cut = *a_Data & ((1 << a_Data.GetBitSize()) - 1); + std::size_t pushCount = sizeof(T) * 8 - a_Offset - a_Data.GetBitSize(); + a_DataRaw |= cut << pushCount; + a_Offset += a_Data.GetBitSize(); + if (a_Offset == sizeof(T) * 8) { + T filled = static_cast(a_DataRaw); + ToNetwork(filled); + a_Buffer << filled; + a_Offset = 0; + a_DataRaw = 0; + } +} + template -void WriteField(DataBuffer& a_Buffer, const T& a_Data) { +void WriteField(DataBuffer& a_Buffer, const T& a_Data, std::uint64_t& a_DataRaw, std::size_t& a_Offset) { T swapped = a_Data; ToNetwork(swapped); a_Buffer << swapped; } +template +void ReadField(DataBuffer& a_Buffer, BitField& a_Data, std::size_t& a_Offset) { + a_Buffer >> *a_Data; + FromNetwork(*a_Data); + + *a_Data >>= sizeof(T) * 8 - a_Offset - a_Data.GetBitSize(); + *a_Data &= (1 << a_Data.GetBitSize()) - 1; + + if (a_Offset != sizeof(T) * 8) { + a_Buffer.SetReadOffset(a_Buffer.GetReadOffset() - sizeof(T)); + a_Offset += a_Data.GetBitSize(); + } else { + a_Offset = 0; + } +} + template -void ReadField(DataBuffer& a_Buffer, T& a_Data) { +void ReadField(DataBuffer& a_Buffer, T& a_Data, std::size_t& a_Offset) { a_Buffer >> a_Data; FromNetwork(a_Data); } @@ -23,13 +55,17 @@ void ReadField(DataBuffer& a_Buffer, T& a_Data) { template DataBuffer WriteMessage(const TData& a_MessageData) { DataBuffer buffer; - boost::pfr::for_each_field(a_MessageData, [&buffer](const auto& a_Field) { WriteField(buffer, a_Field); }); + std::size_t currentOffset = 0; + std::uint64_t dataRaw = 0; + boost::pfr::for_each_field(a_MessageData, + [&buffer, &dataRaw, ¤tOffset](const auto& a_Field) { WriteField(buffer, a_Field, dataRaw, currentOffset); }); return buffer; } template void ReadMessage(DataBuffer& a_Buffer, TData& a_MessageData) { - boost::pfr::for_each_field(a_MessageData, [&a_Buffer](auto& a_Field) { ReadField(a_Buffer, a_Field); }); + std::size_t currentOffset = 0; + boost::pfr::for_each_field(a_MessageData, [&a_Buffer, ¤tOffset](auto& a_Field) { ReadField(a_Buffer, a_Field, currentOffset); }); } } // namespace details diff --git a/include/sp/protocol/BitField.h b/include/sp/protocol/BitField.h new file mode 100644 index 0000000..5d13434 --- /dev/null +++ b/include/sp/protocol/BitField.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +namespace sp { + +template +class BitField { + private: + static constexpr int BITS_IN_CHAR = 8; + static_assert(sizeof(T) * BITS_IN_CHAR > BitSize, "The bit count must be lower than the actual type size !"); + + T m_Data; + + public: + BitField() : m_Data{} {}; + BitField(T a_Data) : m_Data(a_Data) {} + + BitField& operator=(T a_Data) { + m_Data = a_Data; + return *this; + } + + constexpr std::size_t GetBitSize() const { + return BitSize; + } + + T& operator*() { + return m_Data; + } + + const T& operator*() const { + return m_Data; + } +}; + +} // namespace sp diff --git a/test/test_message.cpp b/test/test_message.cpp index fadd268..f16993a 100644 --- a/test/test_message.cpp +++ b/test/test_message.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -21,8 +22,8 @@ template using Message = sp::ConcreteMessage; struct KeepAlivePacket { - std::uint64_t m_KeepAlive; - std::string mdc; + sp::BitField one; + sp::BitField two; }; using KeepAliveMessage = Message; @@ -34,7 +35,7 @@ class PacketHandler : public sp::MessageHandler {}; class MyHandler : public PacketHandler { public: virtual void Handle(const KeepAlivePacket& msg) { - std::cout << "I recieved a keep alive : " << msg.m_KeepAlive << " : " << msg.mdc << "\n"; + std::cout << "I recieved a keep alive : " << *msg.one << " : " << *msg.two << "\n"; } }; @@ -45,7 +46,7 @@ using PacketFactory = sp::MessageFactory; using PacketStream = sp::MessageStream; int main() { - KeepAliveMessage m{69UL, "ceci est une mdc aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}; + KeepAliveMessage m{69, 5}; // dispatch tests @@ -79,6 +80,8 @@ int main() { d.Dispatch(*message2); + // Todo : verify bitfields + // message->Write(file); // file << std::endl; // m.Write(file);