diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a8427309..db9d3dc4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2745,6 +2745,7 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST) serverinfo.cpp str.cpp strip_path_and_extension.cpp + swap_endian.cpp teehistorian.cpp test.cpp test.h diff --git a/src/base/system.h b/src/base/system.h index ef9527f84..ba1518c15 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -2210,6 +2210,15 @@ int open_link(const char *link); */ int open_file(const char *path); +/** + * Swaps the endianness of data. Each element is swapped individually by reversing its bytes. + * + * @param data Pointer to data to be swapped. + * @param elem_size Size in bytes of each element. + * @param num Number of elements. + * + * @remark The caller must ensure that the data is at least `elem_size * num` bytes in size. + */ void swap_endian(void *data, unsigned elem_size, unsigned num); typedef struct diff --git a/src/test/swap_endian.cpp b/src/test/swap_endian.cpp new file mode 100644 index 000000000..4a65f52c0 --- /dev/null +++ b/src/test/swap_endian.cpp @@ -0,0 +1,45 @@ +#include "test.h" +#include + +#include + +#include + +TEST(SwapEndian, Generic) +{ + const std::array aOriginalData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + const std::array aExpectedDataInt16 = {2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11}; + const std::array aExpectedDataInt32 = {4, 3, 2, 1, 8, 7, 6, 5, 12, 11, 10, 9}; + + std::array aData = aOriginalData; + swap_endian(aData.data(), sizeof(char), aData.size() / sizeof(char)); + EXPECT_EQ(aData, aOriginalData); + + aData = aOriginalData; + swap_endian(aData.data(), sizeof(int16_t), aData.size() / sizeof(int16_t)); + EXPECT_EQ(aData, aExpectedDataInt16); + + aData = aOriginalData; + swap_endian(aData.data(), sizeof(int32_t), aData.size() / sizeof(int32_t)); + EXPECT_EQ(aData, aExpectedDataInt32); +} + +static int SwapEndianInt(int Number) +{ + swap_endian(&Number, sizeof(Number), 1); + return Number; +} + +TEST(SwapEndian, Int) +{ + EXPECT_EQ(SwapEndianInt(0x00000000), 0x00000000); + EXPECT_EQ(SwapEndianInt(0xFFFFFFFF), 0xFFFFFFFF); + EXPECT_EQ(SwapEndianInt(0x7FFFFFFF), 0xFFFFFF7F); + EXPECT_EQ(SwapEndianInt(0xFFFFFF7F), 0x7FFFFFFF); + EXPECT_EQ(SwapEndianInt(0x80000000), 0x00000080); + EXPECT_EQ(SwapEndianInt(0x00000080), 0x80000000); + EXPECT_EQ(SwapEndianInt(0x12345678), 0x78563412); + EXPECT_EQ(SwapEndianInt(0x78563412), 0x12345678); + EXPECT_EQ(SwapEndianInt(0x87654321), 0x21436587); + EXPECT_EQ(SwapEndianInt(0x21436587), 0x87654321); +}