diff --git a/CMakeLists.txt b/CMakeLists.txt index e69de29..5d7b105 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.18..3.30) + +project(Endianness + VERSION 1.0 + LANGUAGES CXX) + +if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) + message(FATAL_ERROR "In-source builds are not allowed") +endif() + +set(CMAKE_CXX_STANDARD 20) + + +file(GLOB_RECURSE HEADERS "include/*.hpp") +file(GLOB_RECURSE SOURCES "src/*.cpp") + +if (UNIX) + add_library(Endianness SHARED ${SOURCES}) +endif() + +if (WIN32) + add_library(Endianness STATIC ${SOURCES}) +endif() + +set_target_properties(Endianness PROPERTIES LINKER_LANGUAGE CXX) +target_include_directories(Endianness PUBLIC ${PROJECT_SOURCE_DIR}/include) + + +add_executable(EndiannessTest main.cpp) + +target_link_libraries(EndiannessTest PUBLIC Endianness) diff --git a/include/Endianness.hpp b/include/Endianness.hpp index 30ec303..6a50907 100644 --- a/include/Endianness.hpp +++ b/include/Endianness.hpp @@ -96,7 +96,7 @@ namespace Endianness float HostToNetworkOrder(float host); double HostToNetworkOrder(double host); - template T HostToNetworkOrder(T host) { return HostToNetworkOrder(host);} + template T HostToNetworkOrder(T host) {throw;} template<> inline u16 HostToNetworkOrder(u16 host) { return HostToNetworkOrder(host);} template<> inline u32 HostToNetworkOrder(u32 host) { return HostToNetworkOrder(host);} diff --git a/main.cpp b/main.cpp index b9e80d1..19d7758 100644 --- a/main.cpp +++ b/main.cpp @@ -1,3 +1,91 @@ // // Created by josh on 6/4/2025. // + +#include +#include +#include + +// Template function to perform a round-trip test +template +void TestRoundTrip(const std::string& type_name, T original_value) { + T network_value = Endianness::HostToNetworkOrder(original_value); + T host_value = Endianness::NetworkToHostOrder(network_value); + + std::cout << "Testing " << type_name << ": " << std::endl; + + if constexpr (std::is_floating_point_v) { + std::cout << " Original: " << original_value << std::endl; + std::cout << " Network (raw bits): 0x" << std::hex << std::setw(sizeof(T) * 2) << std::setfill('0'); + if constexpr (std::is_same_v) { + std::cout << *reinterpret_cast(&network_value); + } else { // double + std::cout << *reinterpret_cast(&network_value); + } + std::cout << std::dec << std::endl; + std::cout << " Host: " << host_value << std::endl; + } else { + std::cout << " Original: 0x" << std::hex << original_value << std::dec << std::endl; + std::cout << " Network: 0x" << std::hex << network_value << std::dec << std::endl; + std::cout << " Host: 0x" << std::hex << host_value << std::dec << std::endl; + } + + + if (original_value == host_value) { + std::cout << " Result: SUCCESS" << std::endl; + } else { + std::cout << " Result: FAILED - Discrepancy found!" << std::endl; + } + std::cout << std::endl; +} + +// Template function to test ReverseByteOrder +template +void TestReverseByteOrder(const std::string& type_name, T original_value) { + T reversed_value = Endianness::ReverseByteOrder(original_value); + + std::cout << "Testing ReverseByteOrder for " << type_name << ": " << std::endl; + std::cout << " Original: 0x" << std::hex << original_value << std::dec << std::endl; + std::cout << " Reversed: 0x" << std::hex << reversed_value << std::dec << std::endl; + std::cout << std::endl; +} + +// Template function to test ReverseByteOrderIfLittleEndian +template +void TestReverseByteOrderIfLittleEndian(const std::string& type_name, T original_value) { + T conditional_reversed_value = Endianness::ReverseByteOrderIfLittleEndian(original_value); + + std::cout << "Testing ReverseByteOrderIfLittleEndian for " << type_name << ": " << std::endl; + std::cout << " Original: 0x" << std::hex << original_value << std::dec << std::endl; + std::cout << " Conditional Reversed: 0x" << std::hex << conditional_reversed_value << std::dec << std::endl; + + if (Endianness::IsLittleEndian()) { + T expected_reversed = Endianness::ReverseByteOrder(original_value); + if (conditional_reversed_value == expected_reversed) { + std::cout << " Result (Little Endian Host): SUCCESS (Bytes were reversed)" << std::endl; + } else { + std::cout << " Result (Little Endian Host): FAILED (Bytes were NOT reversed as expected)" << std::endl; + } + } else { // Big Endian + if (conditional_reversed_value == original_value) { + std::cout << " Result (Big Endian Host): SUCCESS (No reversal expected)" << std::endl; + } else { + std::cout << " Result (Big Endian Host): FAILED (Reversal happened unexpectedly)" << std::endl; + } + } + std::cout << std::endl; +} + +int main() +{ + for (int i = 0; i < 256; i++) + { + TestRoundTrip("u8", i); + TestRoundTrip("u16", i*i); + TestRoundTrip("u32", i*i*i); + TestRoundTrip("u64", i*i*i*i); + } + + return 0; + +} \ No newline at end of file diff --git a/src/Endianness.cpp b/src/Endianness.cpp index 202c5e8..4969cce 100644 --- a/src/Endianness.cpp +++ b/src/Endianness.cpp @@ -1,5 +1,5 @@ #ifdef WIN32 -#pragma comment(lib, "Ws2_32.lib") + #pragma comment(lib, "Ws2_32.lib") #define WIN32_LEAN_AND_MEAN #include @@ -9,20 +9,20 @@ #include #endif -#include +#include namespace Endianness { // TODO: Manually swap bytes so we can depend less on clunky include directives. - u16 HostToNetworkOrder(u16 host) { return htons(host); } - u16 NetworkToHostOrder(u16 network) { return ntohs(network); } - s16 HostToNetworkOrder(s16 host) { return htons( host); } - s16 NetworkToHostOrder(s16 network) { return ntohs(network);} - u32 HostToNetworkOrder(u32 host) { return htonl(host); } - u32 NetworkToHostOrder(u32 network) { return ntohl(network); } - s32 HostToNetworkOrder(s32 host) { return htonl(host);} - s32 NetworkToHostOrder(s32 network) { return ntohl(network);} + u16 HostToNetworkOrder(u16 host) { return ReverseByteOrderIfLittleEndian(host); } + u16 NetworkToHostOrder(u16 network) { return ReverseByteOrderIfLittleEndian(network); } + s16 HostToNetworkOrder(s16 host) { return ReverseByteOrderIfLittleEndian( host); } + s16 NetworkToHostOrder(s16 network) { return ReverseByteOrderIfLittleEndian(network);} + u32 HostToNetworkOrder(u32 host) { return ReverseByteOrderIfLittleEndian(host); } + u32 NetworkToHostOrder(u32 network) { return ReverseByteOrderIfLittleEndian(network); } + s32 HostToNetworkOrder(s32 host) { return ReverseByteOrderIfLittleEndian(host);} + s32 NetworkToHostOrder(s32 network) { return ReverseByteOrderIfLittleEndian(network);} u64 HostToNetworkOrder(u64 host) { return ReverseByteOrderIfLittleEndian(host); } u64 NetworkToHostOrder(u64 network) { return ReverseByteOrderIfLittleEndian(network); } s64 HostToNetworkOrder(s64 host) { return ReverseByteOrderIfLittleEndian(host); }