+2024-05-17 Paul Eggert <eggert@cs.ucla.edu>
+
+ byteswap: port better to limited platforms
+ POSIX does not require uint64_t, and the C standard
+ does not require uint16_t or uint32_t either, so port
+ to platforms that lack these types. The POSIX limitation
+ is the only significant one in practice. I ran into this
+ issue when updating Emacs, which still ports to platforms
+ lacking 64-bit types.
+ * lib/byteswap.in.h (bswap_16, bswap_32, bswap_64):
+ Accept and return uint_leastN_t instead of uintN_t,
+ for portability to non-POSIX hosts that lack uintN_t.
+ Almost no platforms these days lack the types, but
+ it’s easy to port so let’s do that. Also, redo to avoid
+ unnecssary parentheses, as these are now functions not macros.
+ (bswap_64): Define only if UINT_LEAST64_MAX, for benefit
+ of not-quite-C99 platforms. This is similar to what
+ bitrotate.h does.
+ * tests/test-byteswap.c (test_bswap_constant)
+ (test_bswap_eval_once, test_bswap_double) [!UINT_LEAST64_MAX]:
+ Do not test 64-bit swaps.
+
2024-05-17 Bruno Haible <bruno@clisp.org>
stdbit-h: Fix leading-zeros/ones functions on 64-bit MSVC.
/* Given an unsigned 16-bit argument X, return the value corresponding to
X with reversed byte order. */
-_GL_BYTESWAP_INLINE uint16_t
-bswap_16 (uint16_t x)
+_GL_BYTESWAP_INLINE uint_least16_t
+bswap_16 (uint_least16_t x)
{
#ifdef _GL_BYTESWAP_HAS_BUILTIN_BSWAP16
return __builtin_bswap16 (x);
#else
- return (((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)));
+ return ( (x & 0xff00) >> 8
+ | (x & 0x00ff) << 8);
#endif
}
/* Given an unsigned 32-bit argument X, return the value corresponding to
X with reversed byte order. */
-_GL_BYTESWAP_INLINE uint32_t
-bswap_32 (uint32_t x)
+_GL_BYTESWAP_INLINE uint_least32_t
+bswap_32 (uint_least32_t x)
{
#ifdef _GL_BYTESWAP_HAS_BUILTIN_BSWAP32
return __builtin_bswap32 (x);
#else
- return ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8)
- | (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24));
+ return ( (x & 0xff000000) >> 24
+ | (x & 0x00ff0000) >> 8
+ | (x & 0x0000ff00) << 8
+ | (x & 0x000000ff) << 24);
#endif
}
+#ifdef UINT_LEAST64_MAX
/* Given an unsigned 64-bit argument X, return the value corresponding to
X with reversed byte order. */
-_GL_BYTESWAP_INLINE uint64_t
-bswap_64 (uint64_t x)
+_GL_BYTESWAP_INLINE uint_least64_t
+bswap_64 (uint_least64_t x)
{
-#ifdef _GL_BYTESWAP_HAS_BUILTIN_BSWAP64
+# ifdef _GL_BYTESWAP_HAS_BUILTIN_BSWAP64
return __builtin_bswap64 (x);
-#else
- 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));
-#endif
+# else
+ return ( (x & 0xff00000000000000) >> 56
+ | (x & 0x00ff000000000000) >> 40
+ | (x & 0x0000ff0000000000) >> 24
+ | (x & 0x000000ff00000000) >> 8
+ | (x & 0x00000000ff000000) << 8
+ | (x & 0x0000000000ff0000) << 24
+ | (x & 0x000000000000ff00) << 40
+ | (x & 0x00000000000000ff) << 56);
+# endif
}
+#endif
#ifdef __cplusplus
}
{
ASSERT (bswap_16 (UINT16_C (0x1234)) == UINT16_C (0x3412));
ASSERT (bswap_32 (UINT32_C (0x12345678)) == UINT32_C (0x78563412));
+#ifdef UINT_LEAST64_MAX
ASSERT (bswap_64 (UINT64_C (0x1234567890ABCDEF))
== UINT64_C (0xEFCDAB9078563412));
+#endif
}
/* Test that the bswap functions evaluate their arguments once. */
static void
test_bswap_eval_once (void)
{
- uint16_t value_1 = 0;
- uint32_t value_2 = 0;
- uint64_t value_3 = 0;
-
+ uint_least16_t value_1 = 0;
ASSERT (bswap_16 (value_1++) == 0);
- ASSERT (bswap_32 (value_2++) == 0);
- ASSERT (bswap_64 (value_3++) == 0);
-
ASSERT (value_1 == 1);
+
+ uint_least32_t value_2 = 0;
+ ASSERT (bswap_32 (value_2++) == 0);
ASSERT (value_2 == 1);
+
+#ifdef UINT_LEAST64_MAX
+ uint_least64_t value_3 = 0;
+ ASSERT (bswap_64 (value_3++) == 0);
ASSERT (value_3 == 1);
+#endif
}
/* Test that the bswap functions accept floating-point arguments. */
{
ASSERT (bswap_16 (0.0) == 0);
ASSERT (bswap_32 (0.0) == 0);
+#ifdef UINT_LEAST64_MAX
ASSERT (bswap_64 (0.0) == 0);
+#endif
}
int