feat: add support for all endianesses

This commit is contained in:
2025-02-08 13:44:04 +01:00
parent 5e89531508
commit 06d69fb976
2 changed files with 99 additions and 4 deletions

View File

@@ -0,0 +1,92 @@
#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() {
std::uint16_t test = 0;
reinterpret_cast<std::uint8_t*>(&test)[1] = 1;
return test == 1;
}
/**
* \brief Serialize value to (network byte order) big endian
*/
template <typename T>
void ToNetwork(T& value) {}
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);
}
/**
* \brief Deserialize value from (network byte order) big endian
*/
template <typename T>
void FromNetwork(T& 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);
}
/**
* \brief Swap bytes if the value is any kind of integer
*/
template <typename T>
void TrySwapBytes(T& 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

View File

@@ -1,6 +1,7 @@
#pragma once
#include <sp/protocol/Options.h>
#include <sp/common/ByteSwapping.h>
namespace sp {
namespace details {
@@ -83,13 +84,13 @@ class MessageInterfaceBigEndian : public TBase {
protected:
template <typename T>
void ReadData(T& value, DataBuffer& buffer) {
//TODO: use big endian
buffer >> value;
FromNetwork(value);
}
template <typename T>
void WriteData(T value, DataBuffer& buffer) {
//TODO: use big endian
ToNetwork(value);
buffer << value;
}
};
@@ -100,13 +101,15 @@ class MessageInterfaceLittleEndian : public TBase {
protected:
template <typename T>
void ReadData(T& value, DataBuffer& buffer) {
//TODO: use little endian
buffer >> value;
TrySwapBytes(value);
FromNetwork(value);
}
template <typename T>
void WriteData(const T& value, DataBuffer& buffer) {
//TODO: use little endian
ToNetwork(value);
TrySwapBytes(value);
buffer << value;
}
};