Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2acbd76c5a | |||
| 468f5ce8a0 |
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
74
src/sp/common/ByteSwapping.cpp
Normal file
74
src/sp/common/ByteSwapping.cpp
Normal 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
|
||||
Reference in New Issue
Block a user