Mercurial > minori
diff include/core/endian.h @ 351:c844f8bb87ce
gui/theme: add xsettings backend
this also adds newly-necessary endianness methods in core/endian.h
which just so happen to be constexpr as well
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Sun, 14 Jul 2024 23:23:56 -0400 |
parents | |
children | 9aaf1e788896 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/core/endian.h Sun Jul 14 23:23:56 2024 -0400 @@ -0,0 +1,121 @@ +#ifndef MINORI_CORE_ENDIAN_H_ +#define MINORI_CORE_ENDIAN_H_ + +/* definition of endian-related stuff. primarily used for*/ + +#include <cstdint> +#include <type_traits> + +class Endian { +private: + static constexpr uint32_t uint32_ = 0x01020304; + static constexpr uint8_t magic_ = static_cast<const uint8_t&>(uint32_); + + /* check for compiler builtins for byteswapping */ +#ifdef __has_builtin +# if __has_builtin(__builtin_bswap16) +# define COMPILER_BUILTIN_BSWAP16(x) __builtin_bswap16(x) +# endif +# if __has_builtin(__builtin_bswap32) +# define COMPILER_BUILTIN_BSWAP32(x) __builtin_bswap32(x) +# endif +# if __has_builtin(__builtin_bswap64) +# define COMPILER_BUILTIN_BSWAP64(x) __builtin_bswap64(x) +# endif +#endif + + static constexpr uint16_t byteswap_16(uint16_t x) { +#ifdef COMPILER_BUILTIN_BSWAP16 + return COMPILER_BUILTIN_BSWAP16(x); +#else + return ( + ((x & UINT16_C(0x00FF)) << 8) + | ((x & UINT16_C(0xFF00)) >> 8) + ); +#endif + } + + static constexpr uint32_t byteswap_32(uint32_t x) { +#ifdef COMPILER_BUILTIN_BSWAP32 + return COMPILER_BUILTIN_BSWAP32(x); +#else + return ( + ((x & UINT32_C(0x000000FF)) << 24) + | ((x & UINT32_C(0x0000FF00)) << 8) + | ((x & UINT32_C(0x00FF0000)) >> 8) + | ((x & UINT32_C(0xFF000000)) >> 24) + ); +#endif + } + + static constexpr uint64_t byteswap_64(uint64_t x) { +#ifdef COMPILER_BUILTIN_BSWAP64 + return COMPILER_BUILTIN_BSWAP64(x); +#else + return ( + ((x & UINT64_C(0x00000000000000FF)) << 56) + | ((x & UINT64_C(0x000000000000FF00)) << 40) + | ((x & UINT64_C(0x0000000000FF0000)) << 24) + | ((x & UINT64_C(0x00000000FF000000)) << 8) + | ((x & UINT64_C(0x000000FF00000000)) >> 8) + | ((x & UINT64_C(0x0000FF0000000000)) >> 24) + | ((x & UINT64_C(0x00FF000000000000)) >> 40) + | ((x & UINT64_C(0xFF00000000000000)) >> 56) + ); +#endif + } + +#ifdef COMPILER_BUILTIN_BSWAP16 +# undef COMPILER_BUILTIN_BSWAP16 +#endif +#ifdef COMPILER_BUILTIN_BSWAP32 +# undef COMPILER_BUILTIN_BSWAP32 +#endif +#ifdef COMPILER_BUILTIN_BSWAP64 +# undef COMPILER_BUILTIN_BSWAP64 +#endif +public: + static constexpr bool little = magic_ == 0x04; + static constexpr bool big = magic_ == 0x01; + static_assert(little || big, "unsupported endianness"); + + template<typename T> + static constexpr T byteswap(T x) { + static_assert(std::is_integral<T>::value); + static_assert(std::is_unsigned<T>::value); + + if constexpr (std::is_same<T, uint8_t>::value) { + return x; + } else if constexpr (std::is_same<T, uint16_t>::value) { + return byteswap_16(x); + } else if constexpr (std::is_same<T, uint32_t>::value) { + return byteswap_32(x); + } else if constexpr (std::is_same<T, uint64_t>::value) { + return byteswap_64(x); + } else { + static_assert(false, "byteswapping with unknown integer type"); + } + } + + template<typename T> + static constexpr T byteswap_little_to_host(T x) { + if constexpr (little) { + return x; + } else if constexpr (big) { + return byteswap(x); + } + } + + template<typename T> + static constexpr T byteswap_big_to_host(T x) { + if constexpr (big) { + return x; + } else if constexpr (little) { + return byteswap(x); + } + } +private: + Endian() = delete; +}; + +#endif /* MINORI_CORE_ENDIAN_H_ */