From 0db765dc98a7f2c3580218e6e537febff0e866ea Mon Sep 17 00:00:00 2001 From: MechSlayer <0jcrespo1996@gmail.com> Date: Tue, 9 Sep 2025 03:57:43 +0200 Subject: [PATCH] feature: add endianness handling and byte swap macros for cross-platform compatibility --- .../DrangPlatform/Include/drang/endianness.h | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 Source/DrangPlatform/Include/drang/endianness.h diff --git a/Source/DrangPlatform/Include/drang/endianness.h b/Source/DrangPlatform/Include/drang/endianness.h new file mode 100644 index 0000000..572a93d --- /dev/null +++ b/Source/DrangPlatform/Include/drang/endianness.h @@ -0,0 +1,139 @@ +#pragma once +#include "platform.h" +#include +#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# ifdef __has_include +# if __has_include() +# include // gnu libc normally provides, linux +# elif __has_include() +# include //open bsd, macos +# elif __has_include() +# include // mingw, some bsd (not open/macos) +# elif __has_include() +# include // solaris +# endif +# endif +#endif + +#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) \ + || (defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN) || (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) \ + || (defined(__sun) && defined(__SVR4) && defined(_BIG_ENDIAN)) || defined(__ARMEB__) || defined(__THUMBEB__) \ + || defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) || defined(_M_PPC) +# define __BIG_ENDIAN__ +# elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || /* gcc */ \ + (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) /* linux header */ \ + || (defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN) \ + || (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) /* mingw header */ \ + || (defined(__sun) && defined(__SVR4) && defined(_LITTLE_ENDIAN)) || /* solaris */ \ + defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || defined(__MIPSEL) \ + || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64) \ + || /* msvc for intel processors */ \ + defined(_M_ARM) /* msvc code on arm executes in little endian mode */ +# define __LITTLE_ENDIAN__ +# endif +#endif + +#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# error "Unknown endianness" +#endif + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || defined(__clang__) +# define DRANG_BSWAP8(_X_) (_X_) +# define DRANG_BSWAP16(_X_) (__builtin_bswap16(_X_)) +# define DRANG_BSWAP32(_X_) (__builtin_bswap32(_X_)) +# define DRANG_BSWAP64(_X_) (__builtin_bswap64(_X_)) + +#elif defined(_MSC_VER) +# include +# define DRANG_BSWAP8(_X_) (_X_) +# define DRANG_BSWAP16(_X_) (_byteswap_ushort(_X_)) +# define DRANG_BSWAP32(_X_) (_byteswap_ulong(_X_)) +# define DRANG_BSWAP64(_X_) (_byteswap_uint64(_X_)) +#else +static inline uint16 drang_bswap16_impl(const uint16_t x) +{ + return (((x >> 8) & 0xFFu) | ((x & 0xFFu) << 8)); +} +static inline uint32_t drang_bswap32_impl(const uint32_t x) +{ + return (((x & 0xFF000000u) >> 24) | ((x & 0x00FF0000u) >> 8) | ((x & 0x0000FF00u) << 8) | ((x & 0x000000FFu) << 24)); +} + +static inline uint64_t drang_bswap64_impl(const uint64_t x) +{ + return (((x & 0xFF00000000000000ull) >> 56) | ((x & 0x00FF000000000000ull) >> 40) + | ((x & 0x0000FF0000000000ull) >> 24) | ((x & 0x000000FF00000000ull) >> 8) + | ((x & 0x00000000FF000000ull) << 8) | ((x & 0x0000000000FF0000ull) << 24) + | ((x & 0x000000000000FF00ull) << 40) | ((x & 0x00000000000000FFull) << 56)); +} +# define DRANG_BSWAP16(_X_) (drang_bswap16_impl(_X_)) +# define DRANG_BSWAP32(_X_) (drang_bswap32_impl(_X_)) +# define DRANG_BSWAP64(_X_) (drang_bswap64_impl(_X_)) +#endif + +#define DRANG_BSWAPF(_X_) DRANG_BIT_CAST(DRANG_BSWAP32(DRANG_BIT_CAST(_X_, float, uint32_t)), uint32_t, float) +#define DRANG_BSWAPD(_X_) DRANG_BIT_CAST(DRANG_BSWAP64(DRANG_BIT_CAST(_X_, double, uint64_t)), uint64_t, double) + +#if defined(__LITTLE_ENDIAN__) +# define DRANG_NE_TO_LE8(_X_) (_X_) +# define DRANG_NE_TO_LE16(_X_) (_X_) +# define DRANG_NE_TO_LE32(_X_) (_X_) +# define DRANG_NE_TO_LE64(_X_) (_X_) +# define DRANG_NE_TO_LEF(_X_) (_X_) +# define DRANG_NE_TO_LED(_X_) (_X_) + +# define DRANG_LE_TO_NE8(_X_) (_X_) +# define DRANG_LE_TO_NE16(_X_) (_X_) +# define DRANG_LE_TO_NE32(_X_) (_X_) +# define DRANG_LE_TO_NE64(_X_) (_X_) +# define DRANG_LE_TO_NEF(_X_) (_X_) +# define DRANG_LE_TO_NED(_X_) (_X_) + +# define DRANG_NE_TO_BE8(_X_) DRANG_BSWAP8(_X_) +# define DRANG_NE_TO_BE16(_X_) DRANG_BSWAP16(_X_) +# define DRANG_NE_TO_BE32(_X_) DRANG_BSWAP32(_X_) +# define DRANG_NE_TO_BE64(_X_) DRANG_BSWAP64(_X_) +# define DRANG_NE_TO_BEF(_X_) DRANG_BSWAPF(_X_) +# define DRANG_NE_TO_BED(_X_) DRANG_BSWAPD(_X_ + +# define DRANG_BE_TO_NE8(_X_) DRANG_BSWAP8(_X_) +# define DRANG_BE_TO_NE16(_X_) DRANG_BSWAP16(_X_) +# define DRANG_BE_TO_NE32(_X_) DRANG_BSWAP32(_X_) +# define DRANG_BE_TO_NE64(_X_) DRANG_BSWAP64(_X_) +# define DRANG_BE_TO_NEF(_X_) DRANG_BSWAPF(_X_) +# define DRANG_BE_TO_NED(_X_) DRANG_BSWAPD(_X_ + +#elif defined(__BIG_ENDIAN__) +# define DRANG_NE_TO_LE8(_X_) DRANG_BSWAP8(_X_) +# define DRANG_NE_TO_LE16(_X_) DRANG_BSWAP16(_X_) +# define DRANG_NE_TO_LE32(_X_) DRANG_BSWAP32(_X_) +# define DRANG_NE_TO_LE64(_X_) DRANG_BSWAP64(_X_) +# define DRANG_NE_TO_LEF(_X_) DRANG_BSWAPF(_X_) +# define DRANG_NE_TO_LED(_X_) DRANG_BSWAPD(_X_) + +# define DRANG_LE_TO_NE8(_X_) DRANG_BSWAP8(_X_) +# define DRANG_LE_TO_NE16(_X_) DRANG_BSWAP16(_X_) +# define DRANG_LE_TO_NE32(_X_) DRANG_BSWAP32(_X_) +# define DRANG_LE_TO_NE64(_X_) DRANG_BSWAP64(_X_) +# define DRANG_LE_TO_NEF(_X_) DRANG_BSWAPF(_X_) +# define DRANG_LE_TO_NED(_X_) DRANG_BSWAPD(_X_ + +# define DRANG_NE_TO_BE8(_X_) (_X_) +# define DRANG_NE_TO_BE16(_X_) (_X_) +# define DRANG_NE_TO_BE32(_X_) (_X_) +# define DRANG_NE_TO_BE64(_X_) (_X_) +# define DRANG_NE_TO_BEF(_X_) (_X_) +# define DRANG_NE_TO_BED(_X_) (_X_) + +# define DRANG_BE_TO_NE8(_X_) (_X_) +# define DRANG_BE_TO_NE16(_X_) (_X_) +# define DRANG_BE_TO_NE32(_X_) (_X_) +# define DRANG_BE_TO_NE64(_X_) (_X_) +# define DRANG_BE_TO_NEF(_X_) (_X_) +# define DRANG_BE_TO_NED(_X_) (_X_) + +#else +# error "Unknown endianness" +#endif