commit 6bbfcf648d40c3752890d3b366b4fde83f5543ad
parent 5bcf255f3daa77171ee29e298119e394cab65e19
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Sun, 24 Aug 2025 00:53:21 +0200
mhd_bithelpers.h: added new helpers
Diffstat:
2 files changed, 144 insertions(+), 0 deletions(-)
diff --git a/configure.ac b/configure.ac
@@ -3504,6 +3504,9 @@ struct timeval test_var = {0, 0}; /* Definition */
)
AC_DEFINE_UNQUOTED([SIZEOF_STRUCT_TIMEVAL_TV_SEC], [$mhd_cv_size_timeval_tv_sec],
[The size of `tv_sec' member of `struct timeval', as computed by sizeof])
+AC_CHECK_SIZEOF([uint_least8_t], [], [[#include <stdint.h>]])
+AC_CHECK_SIZEOF([uint_least16_t], [], [[#include <stdint.h>]])
+AC_CHECK_SIZEOF([uint_fast32_t], [], [[#include <stdint.h>]])
AC_CHECK_SIZEOF([int_fast64_t], [], [[#include <stdint.h>]])
AC_CHECK_SIZEOF([uint_fast64_t], [], [[#include <stdint.h>]])
AC_CHECK_SIZEOF([int], [], [[#include <stdint.h>]])
diff --git a/src/mhd2/mhd_bithelpers.h b/src/mhd2/mhd_bithelpers.h
@@ -130,6 +130,31 @@ mhd_BYTES_SWAP64(uint64_t value64)
}
#endif /* ! mhd_HAS_BUILTIN(__builtin_bswap64) */
+#if defined(__SIZEOF_INT128__) || \
+ (defined(BITINT_MAXWIDTH) && (BITINT_MAXWIDTH >= 128))
+/* swap 128-bit value if supported by compiler.
+ * Parameter value128 must be unsigned 128-bit constant or variable, otherwise
+ * macro will not work properly.
+ * Warning: evaluate arguments multiple times!
+ */
+# define mhd_BYTES_SWAP128(value128) \
+ (((((value128) >> 0u) & 0xFFu) << 120u) | \
+ ((((value128) >> 8u) & 0xFFu) << 112u) | \
+ ((((value128) >> 16u) & 0xFFu) << 104u) | \
+ ((((value128) >> 24u) & 0xFFu) << 96u) | \
+ ((((value128) >> 32u) & 0xFFu) << 88u) | \
+ ((((value128) >> 40u) & 0xFFu) << 80u) | \
+ ((((value128) >> 48u) & 0xFFu) << 72u) | \
+ ((((value128) >> 56u) & 0xFFu) << 64u) | \
+ ((((value128) >> 64u) & 0xFFu) << 56u) | \
+ ((((value128) >> 72u) & 0xFFu) << 48u) | \
+ ((((value128) >> 80u) & 0xFFu) << 40u) | \
+ ((((value128) >> 88u) & 0xFFu) << 32u) | \
+ ((((value128) >> 96u) & 0xFFu) << 24u) | \
+ ((((value128) >> 104u) & 0xFFu) << 16u) | \
+ ((((value128) >> 112u) & 0xFFu) << 8u) | \
+ ((((value128) >> 120u) & 0xFFu) << 0u))
+#endif
/* mhd_PUT_64BIT_LE (addr, value64)
* put 64-bit value64 to addr in little-endian mode.
@@ -259,6 +284,74 @@ mhd_GET_32BIT_LE_UNALIGN (const void *addr)
#endif /* ! mhd_GET_32BIT_LE_ALLOW_UNALIGNED */
+/* mhd_GET_64BIT_LE (addr)
+ * get little-endian 64-bit value stored at addr
+ * and return it in native-endian mode.
+ */
+/* Slow version that works with unaligned addr and with any byte order */
+MHD_static_inline_ uint64_t
+mhd_GET_64BIT_LE_SLOW (const void *addr)
+{
+ const uint8_t *const src = (const uint8_t *) addr;
+ uint64_t ret;
+ ret = (uint64_t) src[0];
+ ret |= (uint64_t) src[1] << 8u;
+ ret |= (uint64_t) src[2] << 16u;
+ ret |= (uint64_t) src[3] << 24u;
+ ret |= (uint64_t) src[4] << 32u;
+ ret |= (uint64_t) src[5] << 40u;
+ ret |= (uint64_t) src[6] << 48u;
+ ret |= (uint64_t) src[7] << 56u;
+ return ret;
+}
+#if mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
+# define mhd_GET_64BIT_LE(addr) \
+ (*(const uint64_t*) (addr))
+#elif mhd_BYTE_ORDER == mhd_BIG_ENDIAN
+# define mhd_GET_64BIT_LE(addr) \
+ mhd_BYTES_SWAP64 (*(const uint64_t*) (addr))
+#else /* mhd_BYTE_ORDER != mhd_BIG_ENDIAN */
+/* Endianness was not detected or non-standard like PDP-endian */
+# define mhd_GET_64BIT_LE(addr) mhd_GET_64BIT_LE_SLOW ((addr))
+/* Indicate that mhd_GET_64BIT_LE does not need aligned pointer */
+# define mhd_GET_64BIT_LE_ALLOW_UNALIGNED 1
+#endif /* mhd_BYTE_ORDER != mhd_BIG_ENDIAN */
+#ifdef mhd_GET_64BIT_LE_ALLOW_UNALIGNED
+# define mhd_GET_64BIT_LE_UNALIGN(addr) mhd_GET_64BIT_LE (addr)
+#else /* !mhd_GET_64BIT_LE_ALLOW_UNALIGNED */
+MHD_static_inline_ MHD_FN_PAR_NONNULL_ALL_ uint64_t
+mhd_GET_64BIT_LE_UNALIGN (const void *addr)
+{
+ uint64_t aligned_src;
+ memcpy(&aligned_src, addr, sizeof(aligned_src));
+ return mhd_GET_64BIT_LE(&aligned_src);
+}
+#endif
+
+
+/* mhd_GET_UINTFAST32_LE(addr)
+ * Get uint_fast32_t value at the addr as little endian.
+ */
+#if SIZEOF_UINT_FAST32_T == 4
+# define mhd_GET_UINTFAST32_LE(addr) \
+ mhd_GET_32BIT_LE ((addr))
+#elif SIZEOF_UINT_FAST32_T == 8
+# define mhd_GET_UINTFAST32_LE(addr) \
+ mhd_GET_64BIT_LE ((addr))
+#else /* future-proof */
+MHD_static_inline_ uint_fast32_t
+mhd_GET_UINTFAST32_LE(const void *addr)
+{
+ const uint8_t *const src = (const uint8_t *) addr;
+ size_t i;
+ uint_fast32_t ret = 0;
+ for (i = 0; i < sizeof(ret); ++i)
+ ret |= (uint_fast32_t) (((uint_fast32_t) src[i]) << (8u * i));
+ return ret;
+}
+#endif
+
+
/* mhd_PUT_64BIT_BE (addr, value64)
* put native-endian 64-bit value64 to addr
* in big-endian mode.
@@ -387,6 +480,54 @@ mhd_GET_32BIT_BE(const void *addr)
#endif /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
+/* mhd_PUT_UINTFAST32_BE(addr, uif32)
+ * Put uint_fast32_t value to the addr in big endian mode.
+ * Complete uint_fast32_t value is written, regardless the number of bits
+ * in this uint_fast32_t (it can be more than 32 bits).
+ */
+#if SIZEOF_UINT_FAST32_T == 4
+# define mhd_PUT_UINTFAST32_BE(addr, uif32) \
+ mhd_PUT_32BIT_BE ((addr),(uif32))
+#elif SIZEOF_UINT_FAST32_T == 8
+# define mhd_PUT_UINTFAST32_BE(addr, uif32) \
+ mhd_PUT_64BIT_BE ((addr),(uif32))
+#else /* future-proof */
+MHD_static_inline_ void
+mhd_PUT_UINTFAST32_BE(void *addr, uint_fast32_t uif32)
+{
+ uint8_t *const dst = (uint8_t *) addr;
+ size_t i;
+ for (i = 0; i < sizeof(uif32); ++i)
+ dst[i] = (uint8_t) (uif32 >> ((sizeof(uif32) - 1 - i) * 8));
+}
+#endif
+
+/* mhd_GET_UINTFAST32_BE(addr)
+ * Get uint_fast32_t value at the addr as big endian.
+ */
+#if SIZEOF_UINT_FAST32_T == 4
+# define mhd_GET_UINTFAST32_BE(addr) \
+ mhd_GET_32BIT_BE ((addr))
+#elif SIZEOF_UINT_FAST32_T == 8
+# define mhd_GET_UINTFAST32_BE(addr) \
+ mhd_GET_64BIT_BE ((addr))
+#else /* future-proof */
+MHD_static_inline_ uint_fast32_t
+mhd_GET_UINTFAST32_BE(const void *addr)
+{
+ size_t i;
+ uint_fast32_t ret = 0;
+
+ for (i = 0; i < sizeof(ret); ++i)
+ {
+ ret <<= 8u;
+ ret |= (uint_fast32_t) (((const uint8_t*) addr)[i]);
+ }
+ return ret;
+}
+#endif
+
+
/**
* Rotate right 32-bit value by number of bits.
*/