summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-05-16 10:48:50 -0400
committerTavian Barnes <tavianator@tavianator.com>2023-05-16 11:29:48 -0400
commitfe472f30e1b82f762993cbc5376ff9b25c605aa9 (patch)
treecd39f359cfc2f146d58ca06f196e6c76a9c90e30 /src
parent9ee1ca387d59a2d1281c310915a9853a57b11a1e (diff)
downloadbfs-fe472f30e1b82f762993cbc5376ff9b25c605aa9.tar.xz
int: Backport C23's endian utilities
Diffstat (limited to 'src')
-rw-r--r--src/int.h68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/int.h b/src/int.h
index 56fabee..1cd455a 100644
--- a/src/int.h
+++ b/src/int.h
@@ -11,6 +11,10 @@
#include <limits.h>
#include <stdint.h>
+#if __STDC_VERSION__ >= 202311L
+# include <stdbit.h>
+#endif
+
// C23 polyfill: _WIDTH macros
// The U*_MAX macros are of the form 2**n - 1, and we want to extract the n.
@@ -97,4 +101,68 @@
# define INTMAX_WIDTH UINTMAX_WIDTH
#endif
+// C23 polyfill: byte order
+
+#ifdef __STDC_ENDIAN_LITTLE__
+# define ENDIAN_LITTLE __STDC_ENDIAN_LITTLE__
+#elif defined(__ORDER_LITTLE_ENDIAN__)
+# define ENDIAN_LITTLE __ORDER_LITTLE_ENDIAN__
+#else
+# define ENDIAN_LITTLE 1234
+#endif
+
+#ifdef __STDC_ENDIAN_BIG__
+# define ENDIAN_BIG __STDC_ENDIAN_BIG__
+#elif defined(__ORDER_BIG_ENDIAN__)
+# define ENDIAN_BIG __ORDER_BIG_ENDIAN__
+#else
+# define ENDIAN_BIG 4321
+#endif
+
+#ifdef __STDC_ENDIAN_NATIVE__
+# define ENDIAN_NATIVE __STDC_ENDIAN_NATIVE__
+#elif defined(__ORDER_NATIVE_ENDIAN__)
+# define ENDIAN_NATIVE __ORDER_NATIVE_ENDIAN__
+#else
+# define ENDIAN_NATIVE 0
+#endif
+
+#if __STDC_VERSION__ >= 202311L
+# define bswap16 stdc_memreverse8u16
+# define bswap32 stdc_memreverse8u32
+# define bswap64 stdc_memreverse8u64
+#elif __GNUC__
+# define bswap16 __builtin_bswap16
+# define bswap32 __builtin_bswap32
+# define bswap64 __builtin_bswap64
+#else
+
+static inline uint16_t bswap16(uint16_t n) {
+ return (n << 8) | (n >> 8);
+}
+
+static inline uint32_t bswap32(uint32_t n) {
+ return ((uint32_t)bswap16(n) << 16) | bswap16(n >> 16);
+}
+
+static inline uint64_t bswap64(uint64_t n) {
+ return ((uint64_t)bswap32(n) << 32) | bswap32(n >> 32);
+}
+
+#endif
+
+static inline uint8_t bswap8(uint8_t n) {
+ return n;
+}
+
+/**
+ * Reverse the byte order of an integer.
+ */
+#define bswap(n) \
+ _Generic((n), \
+ uint8_t: bswap8, \
+ uint16_t: bswap16, \
+ uint32_t: bswap32, \
+ uint64_t: bswap64)(n)
+
#endif // BFS_INT_H