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_ */