Allow SwapBE to swap non-uint types

If we want to have more semantically meaningful types (like Direction), it's useful to be able to support those in the DataSerializer too. Swapping bytes for entire structures is probably never going to make sense, but for types that are pure wrappers around integer types, we want to be able to swap them as if they were the integer they wrap.
This commit is contained in:
Richard Fine 2019-08-26 14:15:44 +01:00
parent 5ff78e48c7
commit 0e04dbeea1
3 changed files with 51 additions and 1 deletions

View File

@ -17,6 +17,7 @@ template<size_t size> struct ByteSwapT
template<> struct ByteSwapT<1>
{
typedef uint8_t UIntType;
static uint8_t SwapBE(uint8_t value)
{
return value;
@ -25,6 +26,7 @@ template<> struct ByteSwapT<1>
template<> struct ByteSwapT<2>
{
typedef uint16_t UIntType;
static uint16_t SwapBE(uint16_t value)
{
return (uint16_t)((value << 8) | (value >> 8));
@ -33,6 +35,7 @@ template<> struct ByteSwapT<2>
template<> struct ByteSwapT<4>
{
typedef uint32_t UIntType;
static uint32_t SwapBE(uint32_t value)
{
return (uint32_t)(((value << 24) | ((value << 8) & 0x00FF0000) | ((value >> 8) & 0x0000FF00) | (value >> 24)));
@ -41,6 +44,7 @@ template<> struct ByteSwapT<4>
template<> struct ByteSwapT<8>
{
typedef uint64_t UIntType;
static uint64_t SwapBE(uint64_t value)
{
value = (value & 0x00000000FFFFFFFF) << 32 | (value & 0xFFFFFFFF00000000) >> 32;
@ -52,5 +56,7 @@ template<> struct ByteSwapT<8>
template<typename T> static T ByteSwapBE(const T& value)
{
return ByteSwapT<sizeof(T)>::SwapBE(value);
typedef ByteSwapT<sizeof(T)> ByteSwap;
typename ByteSwap::UIntType result = ByteSwap::SwapBE(reinterpret_cast<const typename ByteSwap::UIntType&>(value));
return *reinterpret_cast<T*>(&result);
}

43
test/tests/Endianness.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "openrct2/core/Endianness.h"
#include <gtest/gtest.h>
TEST(SwapBETest, ForUInt8_DoesNothing)
{
uint8_t before = 0x12;
uint8_t after = ByteSwapBE(before);
ASSERT_EQ(before, after);
}
TEST(SwapBETest, ForUInt16_SwapsBytes)
{
uint16_t before = 0x1234;
uint16_t after = ByteSwapBE(before);
ASSERT_EQ(0x3412u, after);
}
TEST(SwapBETest, ForUInt32_SwapsBytes)
{
uint32_t before = 0x12345678;
uint32_t after = ByteSwapBE(before);
ASSERT_EQ(0x78563412u, after);
}
TEST(SwapBETest, ForUInt64_SwapsBytes)
{
uint64_t before = 0x1234567887654321;
uint64_t after = ByteSwapBE(before);
ASSERT_EQ(0x2143658778563412u, after);
}
TEST(SwapBETest, ForCustomBlittableType_SwapsBytes)
{
struct MyStruct
{
uint16_t value;
};
MyStruct before = { 0x1234 };
MyStruct after = ByteSwapBE(before);
ASSERT_EQ(0x3412, after.value);
}

View File

@ -58,6 +58,7 @@
<ItemGroup>
<ClCompile Include="CircularBuffer.cpp" />
<ClCompile Include="CryptTests.cpp" />
<ClCompile Include="Endianness.cpp" />
<ClCompile Include="LanguagePackTest.cpp" />
<ClCompile Include="ImageImporterTests.cpp" />
<ClCompile Include="IniReaderTest.cpp" />