libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

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:
Mconfigure.ac | 3+++
Msrc/mhd2/mhd_bithelpers.h | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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. */