libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

mhd_bithelpers.h (16542B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2019-2023 Karlson2k (Evgeny Grin)
      4 
      5   This library is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU Lesser General Public
      7   License as published by the Free Software Foundation; either
      8   version 2.1 of the License, or (at your option) any later version.
      9 
     10   This library is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13   Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General Public
     16   License along with this library.
     17   If not, see <http://www.gnu.org/licenses/>.
     18 */
     19 
     20 /**
     21  * @file microhttpd/mhd_bithelpers.h
     22  * @brief  macros for bits manipulations
     23  * @author Karlson2k (Evgeny Grin)
     24  */
     25 
     26 #ifndef MHD_BITHELPERS_H
     27 #define MHD_BITHELPERS_H 1
     28 
     29 #include "mhd_options.h"
     30 #include <stdint.h>
     31 #if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
     32   defined(__OPTIMIZE__)))
     33 /* Declarations for VC & Clang/C2 built-ins */
     34 #include <intrin.h>
     35 #endif /* _MSC_FULL_VER  */
     36 #include "mhd_byteorder.h"
     37 #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN || _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
     38 #include "mhd_align.h"
     39 #endif /* _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN ||
     40           _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN */
     41 
     42 #ifndef __has_builtin
     43 /* Avoid precompiler errors with non-clang */
     44 #  define __has_builtin(x) 0
     45 #  define _MHD_has_builtin_dummy 1
     46 #endif
     47 
     48 MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_
     49 
     50 #ifdef MHD_HAVE___BUILTIN_BSWAP32
     51 #define _MHD_BYTES_SWAP32(value32)  \
     52   ((uint32_t) __builtin_bswap32 ((uint32_t) value32))
     53 #elif defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
     54   defined(__OPTIMIZE__)))
     55 /* Clang/C2 may not inline this function if optimizations are turned off. */
     56 #ifndef __clang__
     57 #pragma intrinsic(_byteswap_ulong)
     58 #endif /* ! __clang__ */
     59 #define _MHD_BYTES_SWAP32(value32)  \
     60   ((uint32_t) _byteswap_ulong ((uint32_t) value32))
     61 #elif \
     62   __has_builtin (__builtin_bswap32)
     63 #define _MHD_BYTES_SWAP32(value32)  \
     64   ((uint32_t) __builtin_bswap32 ((uint32_t) value32))
     65 #else  /* ! __has_builtin(__builtin_bswap32) */
     66 #define _MHD_BYTES_SWAP32(value32)                                  \
     67   ( (((uint32_t) (value32)) << 24)                                  \
     68     | ((((uint32_t) (value32)) & ((uint32_t) 0x0000FF00)) << 8)     \
     69     | ((((uint32_t) (value32)) & ((uint32_t) 0x00FF0000)) >> 8)     \
     70     | (((uint32_t) (value32))                           >> 24) )
     71 #endif /* ! __has_builtin(__builtin_bswap32) */
     72 
     73 #ifdef MHD_HAVE___BUILTIN_BSWAP64
     74 #define _MHD_BYTES_SWAP64(value64) \
     75   ((uint64_t) __builtin_bswap64 ((uint64_t) value64))
     76 #elif defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
     77   defined(__OPTIMIZE__)))
     78 /* Clang/C2 may not inline this function if optimizations are turned off. */
     79 #ifndef __clang__
     80 #pragma intrinsic(_byteswap_uint64)
     81 #endif /* ! __clang__ */
     82 #define _MHD_BYTES_SWAP64(value64)  \
     83   ((uint64_t) _byteswap_uint64 ((uint64_t) value64))
     84 #elif \
     85   __has_builtin (__builtin_bswap64)
     86 #define _MHD_BYTES_SWAP64(value64) \
     87   ((uint64_t) __builtin_bswap64 ((uint64_t) value64))
     88 #else  /* ! __has_builtin(__builtin_bswap64) */
     89 #define _MHD_BYTES_SWAP64(value64)                                          \
     90   ( (((uint64_t) (value64)) << 56)                                          \
     91     | ((((uint64_t) (value64)) & ((uint64_t) 0x000000000000FF00)) << 40)    \
     92     | ((((uint64_t) (value64)) & ((uint64_t) 0x0000000000FF0000)) << 24)    \
     93     | ((((uint64_t) (value64)) & ((uint64_t) 0x00000000FF000000)) << 8)     \
     94     | ((((uint64_t) (value64)) & ((uint64_t) 0x000000FF00000000)) >> 8)     \
     95     | ((((uint64_t) (value64)) & ((uint64_t) 0x0000FF0000000000)) >> 24)    \
     96     | ((((uint64_t) (value64)) & ((uint64_t) 0x00FF000000000000)) >> 40)    \
     97     | (((uint64_t) (value64))                                   >> 56) )
     98 #endif /* ! __has_builtin(__builtin_bswap64) */
     99 
    100 
    101 /* _MHD_PUT_64BIT_LE (addr, value64)
    102  * put native-endian 64-bit value64 to addr
    103  * in little-endian mode.
    104  */
    105 /* Slow version that works with unaligned addr and with any bytes order */
    106 #define _MHD_PUT_64BIT_LE_SLOW(addr, value64) do {                       \
    107     ((uint8_t*) (addr))[0] = (uint8_t) ((uint64_t) (value64));           \
    108     ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 8);    \
    109     ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 16);   \
    110     ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 24);   \
    111     ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 32);   \
    112     ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 40);   \
    113     ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48);   \
    114     ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56);   \
    115 } while (0)
    116 #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
    117 #define _MHD_PUT_64BIT_LE(addr, value64)             \
    118   ((*(uint64_t*) (addr)) = (uint64_t) (value64))
    119 #elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
    120 #define _MHD_PUT_64BIT_LE(addr, value64)             \
    121   ((*(uint64_t*) (addr)) = _MHD_BYTES_SWAP64 (value64))
    122 #else  /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
    123 /* Endianness was not detected or non-standard like PDP-endian */
    124 #define _MHD_PUT_64BIT_LE(addr, value64) do {                            \
    125     ((uint8_t*) (addr))[0] = (uint8_t) ((uint64_t) (value64));           \
    126     ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 8);    \
    127     ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 16);   \
    128     ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 24);   \
    129     ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 32);   \
    130     ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 40);   \
    131     ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48);   \
    132     ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56);   \
    133 } while (0)
    134 /* Indicate that _MHD_PUT_64BIT_LE does not need aligned pointer */
    135 #define _MHD_PUT_64BIT_LE_UNALIGNED 1
    136 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
    137 
    138 /* Put result safely to unaligned address */
    139 _MHD_static_inline void
    140 _MHD_PUT_64BIT_LE_SAFE (void *dst, uint64_t value)
    141 {
    142 #ifndef _MHD_PUT_64BIT_LE_UNALIGNED
    143   if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN))
    144     _MHD_PUT_64BIT_LE_SLOW (dst, value);
    145   else
    146 #endif /* ! _MHD_PUT_64BIT_LE_UNALIGNED */
    147   _MHD_PUT_64BIT_LE (dst, value);
    148 }
    149 
    150 
    151 /* _MHD_PUT_32BIT_LE (addr, value32)
    152  * put native-endian 32-bit value32 to addr
    153  * in little-endian mode.
    154  */
    155 #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
    156 #define _MHD_PUT_32BIT_LE(addr,value32)             \
    157   ((*(uint32_t*) (addr)) = (uint32_t) (value32))
    158 #elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
    159 #define _MHD_PUT_32BIT_LE(addr, value32)            \
    160   ((*(uint32_t*) (addr)) = _MHD_BYTES_SWAP32 (value32))
    161 #else  /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
    162 /* Endianness was not detected or non-standard like PDP-endian */
    163 #define _MHD_PUT_32BIT_LE(addr, value32) do {                            \
    164     ((uint8_t*) (addr))[0] = (uint8_t) ((uint32_t) (value32));           \
    165     ((uint8_t*) (addr))[1] = (uint8_t) (((uint32_t) (value32)) >> 8);    \
    166     ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 16);   \
    167     ((uint8_t*) (addr))[3] = (uint8_t) (((uint32_t) (value32)) >> 24);   \
    168 } while (0)
    169 /* Indicate that _MHD_PUT_32BIT_LE does not need aligned pointer */
    170 #define _MHD_PUT_32BIT_LE_UNALIGNED 1
    171 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
    172 
    173 /* _MHD_GET_32BIT_LE (addr)
    174  * get little-endian 32-bit value storied at addr
    175  * and return it in native-endian mode.
    176  */
    177 #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
    178 #define _MHD_GET_32BIT_LE(addr)             \
    179   (*(const uint32_t*) (addr))
    180 #elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
    181 #define _MHD_GET_32BIT_LE(addr)             \
    182   _MHD_BYTES_SWAP32 (*(const uint32_t*) (addr))
    183 #else  /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
    184 /* Endianness was not detected or non-standard like PDP-endian */
    185 #define _MHD_GET_32BIT_LE(addr)                           \
    186   ( ( (uint32_t) (((const uint8_t*) addr)[0]))            \
    187     | (((uint32_t) (((const uint8_t*) addr)[1])) << 8)    \
    188     | (((uint32_t) (((const uint8_t*) addr)[2])) << 16)   \
    189     | (((uint32_t) (((const uint8_t*) addr)[3])) << 24) )
    190 /* Indicate that _MHD_GET_32BIT_LE does not need aligned pointer */
    191 #define _MHD_GET_32BIT_LE_UNALIGNED 1
    192 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
    193 
    194 
    195 /* _MHD_PUT_64BIT_BE (addr, value64)
    196  * put native-endian 64-bit value64 to addr
    197  * in big-endian mode.
    198  */
    199 /* Slow version that works with unaligned addr and with any bytes order */
    200 #define _MHD_PUT_64BIT_BE_SLOW(addr, value64) do {                       \
    201     ((uint8_t*) (addr))[7] = (uint8_t) ((uint64_t) (value64));           \
    202     ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 8);    \
    203     ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 16);   \
    204     ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 24);   \
    205     ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 32);   \
    206     ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 40);   \
    207     ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 48);   \
    208     ((uint8_t*) (addr))[0] = (uint8_t) (((uint64_t) (value64)) >> 56);   \
    209 } while (0)
    210 #if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
    211 #define _MHD_PUT_64BIT_BE(addr, value64)             \
    212   ((*(uint64_t*) (addr)) = (uint64_t) (value64))
    213 #elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
    214 #define _MHD_PUT_64BIT_BE(addr, value64)             \
    215   ((*(uint64_t*) (addr)) = _MHD_BYTES_SWAP64 (value64))
    216 #else  /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
    217 /* Endianness was not detected or non-standard like PDP-endian */
    218 #define _MHD_PUT_64BIT_BE(addr, value64) _MHD_PUT_64BIT_BE_SLOW(addr, value64)
    219 /* Indicate that _MHD_PUT_64BIT_BE does not need aligned pointer */
    220 #define _MHD_PUT_64BIT_BE_UNALIGNED 1
    221 #endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
    222 
    223 /* Put result safely to unaligned address */
    224 _MHD_static_inline void
    225 _MHD_PUT_64BIT_BE_SAFE (void *dst, uint64_t value)
    226 {
    227 #ifndef _MHD_PUT_64BIT_BE_UNALIGNED
    228   if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN))
    229     _MHD_PUT_64BIT_BE_SLOW (dst, value);
    230   else
    231 #endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */
    232   _MHD_PUT_64BIT_BE (dst, value);
    233 }
    234 
    235 
    236 /* _MHD_GET_64BIT_BE (addr)
    237  * load 64-bit value located at addr in big endian mode.
    238  */
    239 #if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
    240 #define _MHD_GET_64BIT_BE(addr)             \
    241   (*(const uint64_t*) (addr))
    242 #elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
    243 #define _MHD_GET_64BIT_BE(addr)             \
    244   _MHD_BYTES_SWAP64 (*(const uint64_t*) (addr))
    245 #else  /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
    246 /* Endianness was not detected or non-standard like PDP-endian */
    247 #define _MHD_GET_64BIT_BE(addr)                           \
    248   (   (((uint64_t) (((const uint8_t*) addr)[0])) << 56)   \
    249     | (((uint64_t) (((const uint8_t*) addr)[1])) << 48)   \
    250     | (((uint64_t) (((const uint8_t*) addr)[2])) << 40)   \
    251     | (((uint64_t) (((const uint8_t*) addr)[3])) << 32)   \
    252     | (((uint64_t) (((const uint8_t*) addr)[4])) << 24)   \
    253     | (((uint64_t) (((const uint8_t*) addr)[5])) << 16)   \
    254     | (((uint64_t) (((const uint8_t*) addr)[6])) << 8)    \
    255     | ((uint64_t)  (((const uint8_t*) addr)[7])) )
    256 /* Indicate that _MHD_GET_64BIT_BE does not need aligned pointer */
    257 #define _MHD_GET_64BIT_BE_ALLOW_UNALIGNED 1
    258 #endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
    259 
    260 
    261 /* _MHD_PUT_32BIT_BE (addr, value32)
    262  * put native-endian 32-bit value32 to addr
    263  * in big-endian mode.
    264  */
    265 #if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
    266 #define _MHD_PUT_32BIT_BE(addr, value32)             \
    267   ((*(uint32_t*) (addr)) = (uint32_t) (value32))
    268 #elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
    269 #define _MHD_PUT_32BIT_BE(addr, value32)             \
    270   ((*(uint32_t*) (addr)) = _MHD_BYTES_SWAP32 (value32))
    271 #else  /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
    272 /* Endianness was not detected or non-standard like PDP-endian */
    273 #define _MHD_PUT_32BIT_BE(addr, value32) do {                            \
    274     ((uint8_t*) (addr))[3] = (uint8_t) ((uint32_t) (value32));           \
    275     ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 8);    \
    276     ((uint8_t*) (addr))[1] = (uint8_t) (((uint32_t) (value32)) >> 16);   \
    277     ((uint8_t*) (addr))[0] = (uint8_t) (((uint32_t) (value32)) >> 24);   \
    278 } while (0)
    279 /* Indicate that _MHD_PUT_32BIT_BE does not need aligned pointer */
    280 #define _MHD_PUT_32BIT_BE_UNALIGNED 1
    281 #endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
    282 
    283 /* _MHD_GET_32BIT_BE (addr)
    284  * get big-endian 32-bit value storied at addr
    285  * and return it in native-endian mode.
    286  */
    287 #if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
    288 #define _MHD_GET_32BIT_BE(addr)             \
    289   (*(const uint32_t*) (addr))
    290 #elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
    291 #define _MHD_GET_32BIT_BE(addr)             \
    292   _MHD_BYTES_SWAP32 (*(const uint32_t*) (addr))
    293 #else  /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
    294 /* Endianness was not detected or non-standard like PDP-endian */
    295 #define _MHD_GET_32BIT_BE(addr)                           \
    296   ( (((uint32_t) (((const uint8_t*) addr)[0])) << 24)     \
    297     | (((uint32_t) (((const uint8_t*) addr)[1])) << 16)   \
    298     | (((uint32_t) (((const uint8_t*) addr)[2])) << 8)    \
    299     | ((uint32_t) (((const uint8_t*) addr)[3])) )
    300 /* Indicate that _MHD_GET_32BIT_BE does not need aligned pointer */
    301 #define _MHD_GET_32BIT_BE_UNALIGNED 1
    302 #endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
    303 
    304 
    305 /**
    306  * Rotate right 32-bit value by number of bits.
    307  * bits parameter must be more than zero and must be less than 32.
    308  */
    309 #if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
    310   defined(__OPTIMIZE__)))
    311 /* Clang/C2 do not inline this function if optimizations are turned off. */
    312 #ifndef __clang__
    313 #pragma intrinsic(_rotr)
    314 #endif /* ! __clang__ */
    315 #define _MHD_ROTR32(value32, bits) \
    316   ((uint32_t) _rotr ((uint32_t) (value32),(bits)))
    317 #elif __has_builtin (__builtin_rotateright32)
    318 #define _MHD_ROTR32(value32, bits) \
    319   ((uint32_t) __builtin_rotateright32 ((value32), (bits)))
    320 #else  /* ! __builtin_rotateright32 */
    321 _MHD_static_inline uint32_t
    322 _MHD_ROTR32 (uint32_t value32, int bits)
    323 {
    324   bits %= 32;
    325   if (0 == bits)
    326     return value32;
    327   /* Defined in form which modern compiler could optimize. */
    328   return (value32 >> bits) | (value32 << (32 - bits));
    329 }
    330 
    331 
    332 #endif /* ! __builtin_rotateright32 */
    333 
    334 
    335 /**
    336  * Rotate left 32-bit value by number of bits.
    337  * bits parameter must be more than zero and must be less than 32.
    338  */
    339 #if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
    340   defined(__OPTIMIZE__)))
    341 /* Clang/C2 do not inline this function if optimizations are turned off. */
    342 #ifndef __clang__
    343 #pragma intrinsic(_rotl)
    344 #endif /* ! __clang__ */
    345 #define _MHD_ROTL32(value32, bits) \
    346   ((uint32_t) _rotl ((uint32_t) (value32),(bits)))
    347 #elif __has_builtin (__builtin_rotateleft32)
    348 #define _MHD_ROTL32(value32, bits) \
    349   ((uint32_t) __builtin_rotateleft32 ((value32), (bits)))
    350 #else  /* ! __builtin_rotateleft32 */
    351 _MHD_static_inline uint32_t
    352 _MHD_ROTL32 (uint32_t value32, int bits)
    353 {
    354   bits %= 32;
    355   if (0 == bits)
    356     return value32;
    357   /* Defined in form which modern compiler could optimize. */
    358   return (value32 << bits) | (value32 >> (32 - bits));
    359 }
    360 
    361 
    362 #endif /* ! __builtin_rotateleft32 */
    363 
    364 
    365 /**
    366  * Rotate right 64-bit value by number of bits.
    367  * bits parameter must be more than zero and must be less than 64.
    368  */
    369 #if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
    370   defined(__OPTIMIZE__)))
    371 /* Clang/C2 do not inline this function if optimisations are turned off. */
    372 #ifndef __clang__
    373 #pragma intrinsic(_rotr64)
    374 #endif /* ! __clang__ */
    375 #define _MHD_ROTR64(value64, bits) \
    376   ((uint64_t) _rotr64 ((uint64_t) (value64),(bits)))
    377 #elif __has_builtin (__builtin_rotateright64)
    378 #define _MHD_ROTR64(value64, bits) \
    379   ((uint64_t) __builtin_rotateright64 ((value64), (bits)))
    380 #else  /* ! __builtin_rotateright64 */
    381 _MHD_static_inline uint64_t
    382 _MHD_ROTR64 (uint64_t value64, int bits)
    383 {
    384   bits %= 64;
    385   if (0 == bits)
    386     return value64;
    387   /* Defined in form which modern compiler could optimise. */
    388   return (value64 >> bits) | (value64 << (64 - bits));
    389 }
    390 
    391 
    392 #endif /* ! __builtin_rotateright64 */
    393 
    394 MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_
    395 
    396 #ifdef _MHD_has_builtin_dummy
    397 /* Remove macro function replacement to avoid misdetection in files which
    398  * include this header */
    399 #  undef __has_builtin
    400 #endif
    401 
    402 #endif /* ! MHD_BITHELPERS_H */