git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/1] compat: modernize and simplify byte swapping functions

From
RKRostislav Krasny <rostiprodev@gmail.com>
Date
Jan 2, 2026, 00:27 UTC
Message-ID
<20260102002735.31390-2-rostiprodev@gmail.com>
In-Reply-To
<20260102002735.31390-1-rostiprodev@gmail.com>

Replace manual bit operations with memcpy + network functions for better maintainability. Add missing 16-bit network byte order conversion.

Key improvements:
- Simplify the get_be*() and put_be*() functions
- Add bswap16() macro with automatic compiler optimization:
  * GCC/Clang: __builtin_bswap16() intrinsic
  * MSVC: _byteswap_ushort() intrinsic
- Add default_bswap16() static inline function with manual fallback implementation
- Rename default_swab32() to default_bswap32() for naming consistency
- Add ntohs() and htons() macros for complete 16/32/64-bit network conversion
- Add put_be16() function for API completeness alongside existing put_be*() and
  get_be*() functions
- Performance improvements (GCC 15.2.1, Clang 21.1.7):
  * on x86-64 with -O0 4.2x faster (GCC), 3.7x faster (Clang)
  * on x86-64 with -O1 4x faster (GCC), identical (Clang)
  * on x86-64 with -O2 identical (GCC), 1.8x faster (Clang)
Signed-off-by: Rostislav Krasny <rostiprodev@gmail.com>
---
 compat/bswap.h | 74 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 44 insertions(+), 30 deletions(-)
diff --git a/compat/bswap.h b/compat/bswap.h
index 28635ebc69..f9954ef090 100644
--- a/compat/bswap.h
+++ b/compat/bswap.h
@@ -9,10 +9,15 @@
  */
 
 /*
- * Default version that the compiler ought to optimize properly with
+ * Default versions that the compiler ought to optimize properly with
  * constant values.
  */
-static inline uint32_t default_swab32(uint32_t val)
+static inline uint16_t default_bswap16(uint16_t val)
+{
+	return ((val & 0xff00) >> 8) | ((val & 0x00ff) << 8);
+}
+
+static inline uint32_t default_bswap32(uint32_t val)
 {
 	return (((val & 0xff000000) >> 24) |
 		((val & 0x00ff0000) >>  8) |
@@ -40,6 +45,7 @@ static inline uint64_t default_bswap64(uint64_t val)
 # define __has_builtin(x) 0
 #endif
 
+#undef bswap16
 #undef bswap32
 #undef bswap64
 
@@ -47,6 +53,7 @@ static inline uint64_t default_bswap64(uint64_t val)
 
 #include <stdlib.h>
 
+#define bswap16(x) _byteswap_ushort(x)
 #define bswap32(x) _byteswap_ulong(x)
 #define bswap64(x) _byteswap_uint64(x)
 
@@ -54,8 +61,9 @@ static inline uint64_t default_bswap64(uint64_t val)
 #define GIT_BIG_ENDIAN 4321
 #define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN
 
-#elif __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)
+#elif __has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)
 
+#define bswap16(x) __builtin_bswap16((x))
 #define bswap32(x) __builtin_bswap32((x))
 #define bswap64(x) __builtin_bswap64((x))
 
@@ -98,24 +106,36 @@ static inline uint64_t default_bswap64(uint64_t val)
 
 #endif
 
+#undef ntohs
+#undef htons
 #undef ntohl
 #undef htonl
 #undef ntohll
 #undef htonll
 
 #if GIT_BYTE_ORDER == GIT_BIG_ENDIAN
+# define ntohs(x) (x)
+# define htons(x) (x)
 # define ntohl(x) (x)
 # define htonl(x) (x)
 # define ntohll(x) (x)
 # define htonll(x) (x)
 #else
 
+# if defined(bswap16)
+#  define ntohs(x) bswap16(x)
+#  define htons(x) bswap16(x)
+# else
+#  define ntohs(x) default_bswap16(x)
+#  define htons(x) default_bswap16(x)
+# endif
+
 # if defined(bswap32)
 #  define ntohl(x) bswap32(x)
 #  define htonl(x) bswap32(x)
 # else
-#  define ntohl(x) default_swab32(x)
-#  define htonl(x) default_swab32(x)
+#  define ntohl(x) default_bswap32(x)
+#  define htonl(x) default_bswap32(x)
 # endif
 
 # if defined(bswap64)
@@ -129,47 +149,41 @@ static inline uint64_t default_bswap64(uint64_t val)
 
 static inline uint16_t get_be16(const void *ptr)
 {
-	const unsigned char *p = ptr;
-	return	(uint16_t)p[0] << 8 |
-		(uint16_t)p[1] << 0;
+	uint16_t n;
+	memcpy(&n, ptr, sizeof n);
+	return ntohs(n);
 }
 
 static inline uint32_t get_be32(const void *ptr)
 {
-	const unsigned char *p = ptr;
-	return	(uint32_t)p[0] << 24 |
-		(uint32_t)p[1] << 16 |
-		(uint32_t)p[2] <<  8 |
-		(uint32_t)p[3] <<  0;
+	uint32_t n;
+	memcpy(&n, ptr, sizeof n);
+	return ntohl(n);
 }
 
 static inline uint64_t get_be64(const void *ptr)
 {
-	const unsigned char *p = ptr;
-	return	(uint64_t)get_be32(&p[0]) << 32 |
-		(uint64_t)get_be32(&p[4]) <<  0;
+	uint64_t n;
+	memcpy(&n, ptr, sizeof n);
+	return ntohll(n);
+}
+
+static inline void put_be16(void *ptr, uint16_t value)
+{
+	uint16_t n = htons(value);
+	memcpy(ptr, &n, sizeof n);
 }
 
 static inline void put_be32(void *ptr, uint32_t value)
 {
-	unsigned char *p = ptr;
-	p[0] = (value >> 24) & 0xff;
-	p[1] = (value >> 16) & 0xff;
-	p[2] = (value >>  8) & 0xff;
-	p[3] = (value >>  0) & 0xff;
+	uint32_t n = htonl(value);
+	memcpy(ptr, &n, sizeof n);
 }
 
 static inline void put_be64(void *ptr, uint64_t value)
 {
-	unsigned char *p = ptr;
-	p[0] = (value >> 56) & 0xff;
-	p[1] = (value >> 48) & 0xff;
-	p[2] = (value >> 40) & 0xff;
-	p[3] = (value >> 32) & 0xff;
-	p[4] = (value >> 24) & 0xff;
-	p[5] = (value >> 16) & 0xff;
-	p[6] = (value >>  8) & 0xff;
-	p[7] = (value >>  0) & 0xff;
+	uint64_t n = htonll(value);
+	memcpy(ptr, &n, sizeof n);
 }
 
 #endif /* COMPAT_BSWAP_H */
-- 
2.52.0
Previous: Rostislav KrasnyNext: Jeff King
Message 2 of 7 in “compat: modernize and simplify byte swapping functions”
  1. 0/1 compat: modernize and simplify byte swapping functionsRostislav Krasny, Jan 2, 2026
  2. 1/1 compat: modernize and simplify byte swapping functionsRostislav Krasny, Jan 2, 2026
  3. Jeff KingJan 2, 2026
  4. Rostislav KrasnyJan 2, 2026
  5. Rostislav KrasnyJan 11, 2026
  6. Jeff KingJan 14, 2026
  7. Jeff KingJan 2, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.