summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bit.h43
-rw-r--r--tests/bit.c7
2 files changed, 41 insertions, 9 deletions
diff --git a/src/bit.h b/src/bit.h
index c7530f1..73a80dc 100644
--- a/src/bit.h
+++ b/src/bit.h
@@ -198,15 +198,35 @@ static inline uint8_t bswap_u8(uint8_t n) {
return n;
}
-/**
- * Reverse the byte order of an integer.
- */
-#define bswap(n) \
- _Generic((n), \
- uint8_t: bswap_u8, \
- uint16_t: bswap_u16, \
- uint32_t: bswap_u32, \
- uint64_t: bswap_u64)(n)
+#if UCHAR_WIDTH == 8
+# define bswap_uc bswap_u8
+#endif
+
+#if USHRT_WIDTH == 16
+# define bswap_us bswap_u16
+#elif USHRT_WIDTH == 32
+# define bswap_us bswap_u32
+#elif USHRT_WIDTH == 64
+# define bswap_us bswap_u64
+#endif
+
+#if UINT_WIDTH == 16
+# define bswap_ui bswap_u16
+#elif UINT_WIDTH == 32
+# define bswap_ui bswap_u32
+#elif UINT_WIDTH == 64
+# define bswap_ui bswap_u64
+#endif
+
+#if ULONG_WIDTH == 32
+# define bswap_ul bswap_u32
+#elif ULONG_WIDTH == 64
+# define bswap_ul bswap_u64
+#endif
+
+#if ULLONG_WIDTH == 64
+# define bswap_ull bswap_u64
+#endif
// Define an overload for each unsigned type
#define UINT_OVERLOADS(macro) \
@@ -225,6 +245,11 @@ static inline uint8_t bswap_u8(uint8_t n) {
unsigned long: name##_ul, \
unsigned long long: name##_ull)
+/**
+ * Reverse the byte order of an integer.
+ */
+#define bswap(n) UINT_SELECT(n, bswap)(n)
+
// C23 polyfill: bit utilities
#if __STDC_VERSION_STDBIT_H__ >= C23
diff --git a/tests/bit.c b/tests/bit.c
index cc95785..5a3871d 100644
--- a/tests/bit.c
+++ b/tests/bit.c
@@ -81,6 +81,13 @@ void check_bit(void) {
check_eq(bswap((uint32_t)0x12345678), 0x78563412);
check_eq(bswap((uint64_t)0x1234567812345678), 0x7856341278563412);
+ // Make sure we can bswap() every unsigned type
+ (void)bswap((unsigned char)0);
+ (void)bswap((unsigned short)0);
+ (void)bswap(0U);
+ (void)bswap(0UL);
+ (void)bswap(0ULL);
+
check_eq(count_ones(0x0U), 0);
check_eq(count_ones(0x1U), 1);
check_eq(count_ones(0x2U), 1);