bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] byteswap: port better to limited platforms


From: Paul Eggert
Subject: [PATCH] byteswap: port better to limited platforms
Date: Fri, 17 May 2024 15:49:32 -0700

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.
---
 ChangeLog             | 22 +++++++++++++++++++++
 lib/byteswap.in.h     | 45 ++++++++++++++++++++++++-------------------
 tests/test-byteswap.c | 20 ++++++++++++-------
 3 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5207f25b3a..078aea49cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+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.
diff --git a/lib/byteswap.in.h b/lib/byteswap.in.h
index ae05d59441..0e760005c2 100644
--- a/lib/byteswap.in.h
+++ b/lib/byteswap.in.h
@@ -56,47 +56,52 @@ extern "C" {
 
 /* 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
 }
diff --git a/tests/test-byteswap.c b/tests/test-byteswap.c
index 60b3ea31e2..475a655a13 100644
--- a/tests/test-byteswap.c
+++ b/tests/test-byteswap.c
@@ -29,25 +29,29 @@ test_bswap_constant (void)
 {
   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.  */
@@ -56,7 +60,9 @@ test_bswap_double (void)
 {
   ASSERT (bswap_16 (0.0) == 0);
   ASSERT (bswap_32 (0.0) == 0);
+#ifdef UINT_LEAST64_MAX
   ASSERT (bswap_64 (0.0) == 0);
+#endif
 }
 
 int
-- 
2.40.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]