commit 91915af50bb56b9d496d4026323ba2d10905b827
parent 4b834afcd19940420d11d3d609e11c787cf11a4f
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Sun, 2 Nov 2025 19:18:59 +0100
mhd_bithelpers.h: added 16-bit BE get/put
Diffstat:
2 files changed, 102 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
@@ -3169,6 +3169,14 @@ AS_VAR_IF([mhd_cv_macro___func___avail], ["yes"],
)
]
)
+AC_CACHE_CHECK([[whether __builtin_bswap16() is available]],
+ [[mhd_cv_func___builtin_bswap16_avail]], [dnl
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include<stdint.h>]], [[uint_least16_t a = 1; uint_least16_t b = __builtin_bswap16(a); a = b; (void) a;]])],
+ [[mhd_cv_func___builtin_bswap16_avail="yes"]],[[mhd_cv_func___builtin_bswap16_avail="no"]])
+])
+AS_IF([[test "x$mhd_cv_func___builtin_bswap16_avail" = "xyes"]],
+ [AC_DEFINE([[MHD_HAVE___BUILTIN_BSWAP16]], [[1]], [Define to 1 if you have __builtin_bswap16() builtin function])])
+
AC_CACHE_CHECK([[whether __builtin_bswap32() is available]],
[[mhd_cv_func___builtin_bswap32_avail]], [dnl
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include<stdint.h>]], [[uint_least32_t a = 1; uint_least32_t b = __builtin_bswap32(a); a = b; (void) a;]])],
diff --git a/src/mhd2/mhd_bithelpers.h b/src/mhd2/mhd_bithelpers.h
@@ -83,6 +83,27 @@
mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE
+#if defined(MHD_HAVE___BUILTIN_BSWAP16) || \
+ mhd_HAS_BUILTIN (__builtin_bswap16)
+# define mhd_BYTES_SWAP16(value16) \
+ ((uint16_t)__builtin_bswap16 ((uint16_t) value16))
+#elif defined(mhd_HAS_VC_INTRINSICS)
+# ifndef __clang__
+# pragma intrinsic(_byteswap_ushort)
+# endif /* ! __clang__ */
+# define mhd_BYTES_SWAP16(value16) \
+ ((uint16_t)_byteswap_ushort ((uint16_t) value16))
+#else /* ! mhd_HAS_BUILTIN(__builtin_bswap32) */
+mhd_static_inline uint16_t
+mhd_BYTES_SWAP16 (uint16_t value16)
+{
+ return (uint16_t) ((value16 << 8u) | (value16 >> 8u));
+}
+
+
+#endif /* mhd_BYTES_SWAP16 */
+
+
#ifdef MHD_HAVE___BUILTIN_BSWAP32
# define mhd_BYTES_SWAP32(value32) \
((uint32_t) __builtin_bswap32 ((uint32_t) value32))
@@ -95,7 +116,7 @@ mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE
#elif \
mhd_HAS_BUILTIN (__builtin_bswap32)
# define mhd_BYTES_SWAP32(value32) \
- ((uint32_t)__builtin_bswap32 ((uint32_t) value32))
+ ((uint32_t) __builtin_bswap32 ((uint32_t) value32))
#else /* ! mhd_HAS_BUILTIN(__builtin_bswap32) */
mhd_static_inline uint32_t
mhd_BYTES_SWAP32 (uint32_t value32)
@@ -568,6 +589,78 @@ mhd_GET_UINTFAST32_BE(const void *addr)
#endif
+/* mhd_PUT_16BIT_BE (addr, value16)
+ * put 16-bit value16 to addr
+ * in big-endian mode.
+ */
+#if mhd_BYTE_ORDER == mhd_BIG_ENDIAN
+# define mhd_PUT_16BIT_BE(addr, value16) \
+ ((*(uint16_t*) (addr)) = (uint16_t) (value16))
+#elif mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
+# define mhd_PUT_16BIT_BE(addr, value16) \
+ ((*(uint16_t*) (addr)) = mhd_BYTES_SWAP16 (value16))
+#else /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
+/* Endianness was not detected or non-standard like PDP-endian */
+mhd_static_inline void
+mhd_PUT_16BIT_BE(void *addr, uint16_t value16)
+{
+ uint8_t *const dst = (uint8_t *) addr;
+ dst[0] = (uint8_t) (value16 >> 8u);
+ dst[1] = (uint8_t) (value16 >> 0u);
+}
+/* Indicate that mhd_PUT_16BIT_BE does not need aligned pointer */
+# define mhd_PUT_16BIT_BE_ALLOW_UNALIGNED 1
+#endif /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
+
+/* Put result safely to unaligned address */
+#ifdef mhd_PUT_16BIT_BE_ALLOW_UNALIGNED
+# define mhd_PUT_16BIT_BE_UNALIGN(addr, value16) \
+ mhd_PUT_16BIT_BE ((addr),(value16))
+#else /* ! mhd_PUT_16BIT_BE_ALLOW_UNALIGNED */
+# define mhd_PUT_16BIT_BE_UNALIGN(addr, value16) \
+ do { uint16_t mhd__aligned_dst; \
+ mhd_PUT_16BIT_BE (&mhd__aligned_dst, (value16)); \
+ memcpy ((addr), &mhd__aligned_dst, \
+ sizeof(mhd__aligned_dst)); } while (0)
+#endif /* ! mhd_PUT_16BIT_BE_ALLOW_UNALIGNED */
+
+
+/* mhd_GET_16BIT_BE (addr)
+ * get big-endian 16-bit value stored at addr
+ */
+#if mhd_BYTE_ORDER == mhd_BIG_ENDIAN
+# define mhd_GET_16BIT_BE(addr) \
+ (*(const uint16_t*) (addr))
+#elif mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
+# define mhd_GET_16BIT_BE(addr) \
+ mhd_BYTES_SWAP16 (*(const uint16_t*) (addr))
+#else /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
+/* Endianness was not detected or non-standard like PDP-endian */
+mhd_static_inline uint16_t
+mhd_GET_16BIT_BE(const void *addr)
+{
+ const uint8_t *const src = (const uint8_t *) addr;
+ return (uint16_t) ((((uint16_t) src[0]) << 8u) | ((uint16_t) src[1]));
+}
+/* Indicate that mhd_GET_16BIT_BE does not need aligned pointer */
+# define mhd_GET_16BIT_BE_ALLOW_UNALIGNED 1
+#endif /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
+
+#ifdef mhd_GET_16BIT_BE_ALLOW_UNALIGNED
+# define mhd_GET_16BIT_BE_UNALIGN(addr) mhd_GET_16BIT_BE ((addr))
+#else /* ! mhd_GET_16BIT_LE_ALLOW_UNALIGNED */
+/* Get value safely from an unaligned address */
+mhd_static_inline MHD_FN_PAR_NONNULL_ALL_ uint16_t
+mhd_GET_16BIT_BE_UNALIGN (const void *addr)
+{
+ uint16_t aligned_src;
+ memcpy (&aligned_src,
+ addr,
+ sizeof(aligned_src));
+ return mhd_GET_16BIT_BE (&aligned_src);
+}
+#endif /* ! mhd_GET_16BIT_BE_ALLOW_UNALIGNED */
+
/**
* Rotate right 32-bit value by number of bits.
*/