feature: add endianness handling and byte swap macros for cross-platform compatibility

This commit is contained in:
MechSlayer 2025-09-09 03:57:43 +02:00
parent f3d307c03e
commit 0db765dc98

View file

@ -0,0 +1,139 @@
#pragma once
#include "platform.h"
#include <stdint.h>
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
# ifdef __has_include
# if __has_include(<endian.h>)
# include <endian.h> // gnu libc normally provides, linux
# elif __has_include(<machine/endian.h>)
# include <machine/endian.h> //open bsd, macos
# elif __has_include(<sys/param.h>)
# include <sys/param.h> // mingw, some bsd (not open/macos)
# elif __has_include(<sys/isadefs.h>)
# include <sys/isadefs.h> // 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 <stdlib.h>
# 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