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
#ifdef _WIN32
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <cstdint>
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;
}
bool IsSystemBigEndian();
/**
* \brief Serialize value to (network byte order) big endian
@@ -29,21 +13,13 @@ template <typename T>
void ToNetwork(T& value) {}
template <>
void ToNetwork<std::uint16_t>(std::uint16_t& value) {
value = htons(value);
}
void ToNetwork<std::uint16_t>(std::uint16_t& value);
template <>
void ToNetwork<std::uint32_t>(std::uint32_t& value) {
value = htonl(value);
}
void ToNetwork<std::uint32_t>(std::uint32_t& value);
template <>
void ToNetwork<std::uint64_t>(std::uint64_t& value) {
if (IsSystemBigEndian())
return;
SwapBytes(value);
}
void ToNetwork<std::uint64_t>(std::uint64_t& value);
/**
* \brief Deserialize value from (network byte order) big endian
@@ -52,21 +28,13 @@ template <typename T>
void FromNetwork(T& value) {}
template <>
void FromNetwork<std::uint16_t>(std::uint16_t& value) {
value = ntohs(value);
}
void FromNetwork<std::uint16_t>(std::uint16_t& value);
template <>
void FromNetwork<std::uint32_t>(std::uint32_t& value) {
value = ntohl(value);
}
void FromNetwork<std::uint32_t>(std::uint32_t& value);
template <>
void FromNetwork<std::uint64_t>(std::uint64_t& value) {
if (IsSystemBigEndian())
return;
SwapBytes(value);
}
void FromNetwork<std::uint64_t>(std::uint64_t& value);
/**
* \brief Swap bytes if the value is any kind of integer
@@ -75,18 +43,12 @@ template <typename T>
void TrySwapBytes(T& value) {}
template <>
void TrySwapBytes<std::uint16_t>(std::uint16_t& value) {
SwapBytes(value);
}
void TrySwapBytes<std::uint16_t>(std::uint16_t& value);
template <>
void TrySwapBytes<std::uint32_t>(std::uint32_t& value) {
SwapBytes(value);
}
void TrySwapBytes<std::uint32_t>(std::uint32_t& value);
template <>
void TrySwapBytes<std::uint64_t>(std::uint64_t& value) {
SwapBytes(value);
}
void TrySwapBytes<std::uint64_t>(std::uint64_t& value);
} // namespace sp

View File

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

View File

@@ -26,8 +26,8 @@ class MessageImplDispatchBase : public TBase {
using Handler = typename TBase::HandlerType;
protected:
virtual void DispatchImpl(Handler& handler) override {
handler.Handle(static_cast<TActual&>(*this));
virtual void DispatchImpl(Handler& handler) const override {
handler.Handle(static_cast<const TActual&>(*this));
}
};
@@ -113,13 +113,13 @@ class MessageImplFieldsWriteBase : public TBase {
private:
// normal writing
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);
}
// writing field in bitfield
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;
// we suppose that the first element is at the highest bits
data |= (field.GetValue() & ((1 << IAlignment) - 1)) << TotalBitCount - IAlignment - offset;
@@ -127,7 +127,7 @@ class MessageImplFieldsWriteBase : public TBase {
// writing bitfield
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;
std::size_t offset = 0;
TupleForEach(
@@ -139,9 +139,9 @@ class MessageImplFieldsWriteBase : public TBase {
this->WriteData(data, buffer);
}
void WriteImpl(DataBuffer& buffer) override {
void WriteImpl(DataBuffer& buffer) const override {
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