2 Commits

Author SHA1 Message Date
2acbd76c5a byteswapping: move declaration into source file 2025-02-23 21:57:10 +01:00
468f5ce8a0 add const 2025-02-23 13:20:45 +01:00
4 changed files with 97 additions and 61 deletions

View File

@@ -1,26 +1,10 @@
#pragma once #pragma once
#ifdef _WIN32
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <cstdint> #include <cstdint>
namespace sp { namespace sp {
template <typename T> bool IsSystemBigEndian();
void SwapBytes(T& value) {
char* ptr = reinterpret_cast<char*>(&value);
std::reverse(ptr, ptr + sizeof(T));
}
bool IsSystemBigEndian() {
static constexpr std::uint16_t test = 10;
static const bool isBigEndian = reinterpret_cast<const std::uint8_t*>(&test)[1] == 10;
return isBigEndian;
}
/** /**
* \brief Serialize value to (network byte order) big endian * \brief Serialize value to (network byte order) big endian
@@ -29,21 +13,13 @@ template <typename T>
void ToNetwork(T& value) {} void ToNetwork(T& value) {}
template <> template <>
void ToNetwork<std::uint16_t>(std::uint16_t& value) { void ToNetwork<std::uint16_t>(std::uint16_t& value);
value = htons(value);
}
template <> template <>
void ToNetwork<std::uint32_t>(std::uint32_t& value) { void ToNetwork<std::uint32_t>(std::uint32_t& value);
value = htonl(value);
}
template <> template <>
void ToNetwork<std::uint64_t>(std::uint64_t& value) { void ToNetwork<std::uint64_t>(std::uint64_t& value);
if (IsSystemBigEndian())
return;
SwapBytes(value);
}
/** /**
* \brief Deserialize value from (network byte order) big endian * \brief Deserialize value from (network byte order) big endian
@@ -52,21 +28,13 @@ template <typename T>
void FromNetwork(T& value) {} void FromNetwork(T& value) {}
template <> template <>
void FromNetwork<std::uint16_t>(std::uint16_t& value) { void FromNetwork<std::uint16_t>(std::uint16_t& value);
value = ntohs(value);
}
template <> template <>
void FromNetwork<std::uint32_t>(std::uint32_t& value) { void FromNetwork<std::uint32_t>(std::uint32_t& value);
value = ntohl(value);
}
template <> template <>
void FromNetwork<std::uint64_t>(std::uint64_t& value) { void FromNetwork<std::uint64_t>(std::uint64_t& value);
if (IsSystemBigEndian())
return;
SwapBytes(value);
}
/** /**
* \brief Swap bytes if the value is any kind of integer * \brief Swap bytes if the value is any kind of integer
@@ -75,18 +43,12 @@ template <typename T>
void TrySwapBytes(T& value) {} void TrySwapBytes(T& value) {}
template <> template <>
void TrySwapBytes<std::uint16_t>(std::uint16_t& value) { void TrySwapBytes<std::uint16_t>(std::uint16_t& value);
SwapBytes(value);
}
template <> template <>
void TrySwapBytes<std::uint32_t>(std::uint32_t& value) { void TrySwapBytes<std::uint32_t>(std::uint32_t& value);
SwapBytes(value);
}
template <> template <>
void TrySwapBytes<std::uint64_t>(std::uint64_t& value) { void TrySwapBytes<std::uint64_t>(std::uint64_t& value);
SwapBytes(value);
}
} // namespace sp } // namespace sp

View File

@@ -30,7 +30,7 @@ class MessageInterfaceBigEndian : public TBase {
} }
template <typename T> template <typename T>
void WriteData(T value, DataBuffer& buffer) { void WriteData(T value, DataBuffer& buffer) const {
ToNetwork(value); ToNetwork(value);
buffer << value; buffer << value;
} }
@@ -71,12 +71,12 @@ class MessageInterfaceReadBase : public TBase {
template <typename TBase> template <typename TBase>
class MessageInterfaceWriteBase : public TBase { class MessageInterfaceWriteBase : public TBase {
public: public:
void Write(DataBuffer& buffer) { void Write(DataBuffer& buffer) const {
WriteImpl(buffer); WriteImpl(buffer);
} }
protected: protected:
virtual void WriteImpl(DataBuffer& buffer) = 0; virtual void WriteImpl(DataBuffer& buffer) const = 0;
}; };
// Handler functionality chunk // Handler functionality chunk
@@ -85,12 +85,12 @@ class MessageInterfaceHandlerBase : public TBase {
public: public:
using HandlerType = typename THandler::HandlerT; using HandlerType = typename THandler::HandlerT;
void Dispatch(HandlerType& handler) { void Dispatch(HandlerType& handler) const {
DispatchImpl(handler); DispatchImpl(handler);
} }
protected: protected:
virtual void DispatchImpl(HandlerType& handler) = 0; virtual void DispatchImpl(HandlerType& handler) const = 0;
}; };
// Validity functionality chunk // Validity functionality chunk
@@ -109,7 +109,7 @@ class MessageInterfaceValidityBase : public TBase {
template <typename TBase> template <typename TBase>
class MessageInterfaceWriteIdBase : public TBase { class MessageInterfaceWriteIdBase : public TBase {
public: public:
void Write(DataBuffer& buffer) { void Write(DataBuffer& buffer) const {
this->WriteData(this->GetId(), buffer); this->WriteData(this->GetId(), buffer);
this->WriteImpl(buffer); this->WriteImpl(buffer);
} }

View File

@@ -26,8 +26,8 @@ class MessageImplDispatchBase : public TBase {
using Handler = typename TBase::HandlerType; using Handler = typename TBase::HandlerType;
protected: protected:
virtual void DispatchImpl(Handler& handler) override { virtual void DispatchImpl(Handler& handler) const override {
handler.Handle(static_cast<TActual&>(*this)); handler.Handle(static_cast<const TActual&>(*this));
} }
}; };
@@ -113,13 +113,13 @@ class MessageImplFieldsWriteBase : public TBase {
private: private:
// normal writing // normal writing
template <typename TField> template <typename TField>
void WriteField(Field<TField, 0>& field, DataBuffer& buffer) { void WriteField(const Field<TField, 0>& field, DataBuffer& buffer) const {
this->WriteData(field.GetValue(), buffer); this->WriteData(field.GetValue(), buffer);
} }
// writing field in bitfield // writing field in bitfield
template <typename TFieldType, typename TField, int IAlignment> template <typename TFieldType, typename TField, int IAlignment>
void WriteField(Field<TField, IAlignment>& field, TFieldType& data, std::size_t offset) { void WriteField(const Field<TField, IAlignment>& field, TFieldType& data, std::size_t offset) const {
static constexpr std::size_t TotalBitCount = sizeof(TFieldType) * 8; static constexpr std::size_t TotalBitCount = sizeof(TFieldType) * 8;
// we suppose that the first element is at the highest bits // we suppose that the first element is at the highest bits
data |= (field.GetValue() & ((1 << IAlignment) - 1)) << TotalBitCount - IAlignment - offset; data |= (field.GetValue() & ((1 << IAlignment) - 1)) << TotalBitCount - IAlignment - offset;
@@ -127,7 +127,7 @@ class MessageImplFieldsWriteBase : public TBase {
// writing bitfield // writing bitfield
template <typename TContainer, typename TFirst, typename... TFields> template <typename TContainer, typename TFirst, typename... TFields>
void WriteField(Field<BitField<TContainer, TFirst, TFields...>, 0>& field, DataBuffer& buffer) { void WriteField(const Field<BitField<TContainer, TFirst, TFields...>, 0>& field, DataBuffer& buffer) const {
TContainer data = 0; TContainer data = 0;
std::size_t offset = 0; std::size_t offset = 0;
TupleForEach( TupleForEach(
@@ -139,9 +139,9 @@ class MessageImplFieldsWriteBase : public TBase {
this->WriteData(data, buffer); this->WriteData(data, buffer);
} }
void WriteImpl(DataBuffer& buffer) override { void WriteImpl(DataBuffer& buffer) const override {
auto& allFields = this->GetFields(); auto& allFields = this->GetFields();
TupleForEach([&buffer, this](auto& field) { this->WriteField(field, buffer); }, allFields); TupleForEach([&buffer, this](const auto& field) { this->WriteField(field, buffer); }, allFields);
} }
}; };

View File

@@ -0,0 +1,74 @@
#include <sp/common/ByteSwapping.h>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <algorithm>
namespace sp {
template <typename T>
void SwapBytes(T& value) {
char* ptr = reinterpret_cast<char*>(&value);
std::reverse(ptr, ptr + sizeof(T));
}
bool IsSystemBigEndian() {
static constexpr std::uint16_t test = 10;
static const bool isBigEndian = reinterpret_cast<const std::uint8_t*>(&test)[1] == 10;
return isBigEndian;
}
template <>
void ToNetwork<std::uint16_t>(std::uint16_t& value) {
value = htons(value);
}
template <>
void ToNetwork<std::uint32_t>(std::uint32_t& value) {
value = htonl(value);
}
template <>
void ToNetwork<std::uint64_t>(std::uint64_t& value) {
if (IsSystemBigEndian())
return;
SwapBytes(value);
}
template <>
void FromNetwork<std::uint16_t>(std::uint16_t& value) {
value = ntohs(value);
}
template <>
void FromNetwork<std::uint32_t>(std::uint32_t& value) {
value = ntohl(value);
}
template <>
void FromNetwork<std::uint64_t>(std::uint64_t& value) {
if (IsSystemBigEndian())
return;
SwapBytes(value);
}
template <>
void TrySwapBytes<std::uint16_t>(std::uint16_t& value) {
SwapBytes(value);
}
template <>
void TrySwapBytes<std::uint32_t>(std::uint32_t& value) {
SwapBytes(value);
}
template <>
void TrySwapBytes<std::uint64_t>(std::uint64_t& value) {
SwapBytes(value);
}
} // namespace sp