Coverage Report

Created: 2025-08-24 06:26

/src/mhd2/src/mhd2/mhd_bithelpers.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
  This file is part of GNU libmicrohttpd
3
  Copyright (C) 2019-2025 Karlson2k (Evgeny Grin)
4
5
  GNU libmicrohttpd 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
  GNU libmicrohttpd 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; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
19
*/
20
21
/**
22
 * @file src/mhd2/mhd_bithelpers.h
23
 * @brief  macros for bits manipulations
24
 * @author Karlson2k (Evgeny Grin)
25
 */
26
27
#ifndef MHD_BITHELPERS_H
28
#define MHD_BITHELPERS_H 1
29
30
#include "mhd_sys_options.h"
31
32
#include "sys_base_types.h"
33
34
#include "mhd_assert.h"
35
36
#if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
37
  defined(__OPTIMIZE__)))
38
/* Declarations for VC & Clang/C2 built-ins */
39
#include <intrin.h>
40
#endif /* _MSC_FULL_VER  */
41
#include "mhd_byteorder.h"
42
#if mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN || mhd_BYTE_ORDER == mhd_BIG_ENDIAN
43
#include "mhd_align.h"
44
#endif /* mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN ||
45
          mhd_BYTE_ORDER == mhd_BIG_ENDIAN */
46
47
#ifndef __has_builtin
48
#  define mhd_HAS_BUILTIN(x) (0)
49
#else
50
#  define mhd_HAS_BUILTIN(x) __has_builtin (x)
51
#endif
52
53
mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE
54
55
#ifdef MHD_HAVE___BUILTIN_BSWAP32
56
#  define mhd_BYTES_SWAP32(value32)  \
57
0
        ((uint32_t) __builtin_bswap32 ((uint32_t) value32))
58
#elif defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
59
  defined(__OPTIMIZE__)))
60
/* Clang/C2 may not inline this function if optimizations are turned off. */
61
#  ifndef __clang__
62
#    pragma intrinsic(_byteswap_ulong)
63
#  endif /* ! __clang__ */
64
#  define mhd_BYTES_SWAP32(value32)  \
65
        ((uint32_t) _byteswap_ulong ((uint32_t) value32))
66
#elif \
67
  mhd_HAS_BUILTIN (__builtin_bswap32)
68
#  define mhd_BYTES_SWAP32(value32)  \
69
        ((uint32_t)__builtin_bswap32 ((uint32_t) value32))
70
#else  /* ! mhd_HAS_BUILTIN(__builtin_bswap32) */
71
#  define mhd_BYTES_SWAP32(value32)                                  \
72
        ( (((uint32_t) (value32)) << 24)                                  \
73
          | ((((uint32_t) (value32)) & ((uint32_t) 0x0000FF00)) << 8)     \
74
          | ((((uint32_t) (value32)) & ((uint32_t) 0x00FF0000)) >> 8)     \
75
          | (((uint32_t) (value32))                           >> 24) )
76
#endif /* ! mhd_HAS_BUILTIN(__builtin_bswap32) */
77
78
#ifdef MHD_HAVE___BUILTIN_BSWAP64
79
#  define mhd_BYTES_SWAP64(value64) \
80
0
        ((uint64_t)__builtin_bswap64 ((uint64_t) value64))
81
#elif defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
82
  defined(__OPTIMIZE__)))
83
/* Clang/C2 may not inline this function if optimizations are turned off. */
84
#  ifndef __clang__
85
#    pragma intrinsic(_byteswap_uint64)
86
#  endif /* ! __clang__ */
87
#  define mhd_BYTES_SWAP64(value64)  \
88
        ((uint64_t)_byteswap_uint64 ((uint64_t) value64))
89
#elif \
90
  mhd_HAS_BUILTIN (__builtin_bswap64)
91
#  define mhd_BYTES_SWAP64(value64) \
92
        ((uint64_t)__builtin_bswap64 ((uint64_t) value64))
93
#else  /* ! mhd_HAS_BUILTIN(__builtin_bswap64) */
94
#  define mhd_BYTES_SWAP64(value64)                                         \
95
        ( (((uint64_t) (value64)) << 56)                                          \
96
          | ((((uint64_t) (value64)) & ((uint64_t) 0x000000000000FF00)) << 40)    \
97
          | ((((uint64_t) (value64)) & ((uint64_t) 0x0000000000FF0000)) << 24)    \
98
          | ((((uint64_t) (value64)) & ((uint64_t) 0x00000000FF000000)) << 8)     \
99
          | ((((uint64_t) (value64)) & ((uint64_t) 0x000000FF00000000)) >> 8)     \
100
          | ((((uint64_t) (value64)) & ((uint64_t) 0x0000FF0000000000)) >> 24)    \
101
          | ((((uint64_t) (value64)) & ((uint64_t) 0x00FF000000000000)) >> 40)    \
102
          | (((uint64_t) (value64))                                   >> 56) )
103
#endif /* ! mhd_HAS_BUILTIN(__builtin_bswap64) */
104
105
106
/* mhd_PUT_64BIT_LE (addr, value64)
107
 * put native-endian 64-bit value64 to addr
108
 * in little-endian mode.
109
 */
110
/* Slow version that works with unaligned addr and with any bytes order */
111
0
#define mhd_PUT_64BIT_LE_SLOW(addr, value64) do {                       \
112
0
          ((uint8_t*) (addr))[0] = (uint8_t) ((uint64_t) (value64));           \
113
0
          ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 8);    \
114
0
          ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 16);   \
115
0
          ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 24);   \
116
0
          ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 32);   \
117
0
          ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 40);   \
118
0
          ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48);   \
119
0
          ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56);   \
120
0
} while (0)
121
#if mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
122
#  define mhd_PUT_64BIT_LE(addr, value64)             \
123
0
        ((*(uint64_t*) (addr)) = (uint64_t) (value64))
124
#elif mhd_BYTE_ORDER == mhd_BIG_ENDIAN
125
#  define mhd_PUT_64BIT_LE(addr, value64)             \
126
        ((*(uint64_t*) (addr)) = mhd_BYTES_SWAP64 (value64))
127
#else  /* mhd_BYTE_ORDER != mhd_BIG_ENDIAN */
128
/* Endianness was not detected or non-standard like PDP-endian */
129
#  define mhd_PUT_64BIT_LE(addr, value64) \
130
        mhd_PUT_64BIT_LE_SLOW ((addr),(value64))
131
/* Indicate that mhd_PUT_64BIT_LE does not need aligned pointer */
132
#  define mhd_PUT_64BIT_LE_UNALIGNED 1
133
#endif /* mhd_BYTE_ORDER != mhd_BIG_ENDIAN */
134
135
/* Put result safely to unaligned address */
136
MHD_static_inline_ void
137
mhd_PUT_64BIT_LE_UNALIGN (void *dst, uint64_t value)
138
0
{
139
0
#ifndef mhd_PUT_64BIT_LE_UNALIGNED
140
0
  if (0 != ((uintptr_t) dst) % (mhd_UINT64_ALIGN))
141
0
    mhd_PUT_64BIT_LE_SLOW (dst, value);
142
0
  else
143
0
#endif /* ! mhd_PUT_64BIT_LE_UNALIGNED */
144
0
  mhd_PUT_64BIT_LE (dst, value);
145
0
}
Unexecuted instantiation: auth_digest.c:mhd_PUT_64BIT_LE_UNALIGN
Unexecuted instantiation: md5_int.c:mhd_PUT_64BIT_LE_UNALIGN
Unexecuted instantiation: sha256_int.c:mhd_PUT_64BIT_LE_UNALIGN
Unexecuted instantiation: sha512_256_int.c:mhd_PUT_64BIT_LE_UNALIGN
146
147
148
/* mhd_PUT_32BIT_LE (addr, value32)
149
 * put native-endian 32-bit value32 to addr
150
 * in little-endian mode.
151
 */
152
/* Slow version that works with unaligned addr and with any bytes order */
153
0
#define mhd_PUT_32BIT_LE_SLOW(addr, value32) do {                            \
154
0
          ((uint8_t*) (addr))[0] = (uint8_t) ((uint32_t) (value32));           \
155
0
          ((uint8_t*) (addr))[1] = (uint8_t) (((uint32_t) (value32)) >> 8);    \
156
0
          ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 16);   \
157
0
          ((uint8_t*) (addr))[3] = (uint8_t) (((uint32_t) (value32)) >> 24);   \
158
0
} while (0)
159
#if mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
160
#  define mhd_PUT_32BIT_LE(addr,value32)             \
161
0
        ((*(uint32_t*) (addr)) = (uint32_t) (value32))
162
#elif mhd_BYTE_ORDER == mhd_BIG_ENDIAN
163
#  define mhd_PUT_32BIT_LE(addr, value32)            \
164
        ((*(uint32_t*) (addr)) = mhd_BYTES_SWAP32 (value32))
165
#else  /* mhd_BYTE_ORDER != mhd_BIG_ENDIAN */
166
/* Endianness was not detected or non-standard like PDP-endian */
167
#  define mhd_PUT_32BIT_LE(addr, value32) \
168
        mhd_PUT_32BIT_LE_SLOW ((addr),(value32))
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
/* Put result safely to unaligned address */
174
MHD_static_inline_ void
175
mhd_PUT_32BIT_LE_UNALIGN (void *dst, uint32_t value)
176
0
{
177
0
#ifndef mhd_PUT_32BIT_LE_UNALIGNED
178
0
  if (0 != ((uintptr_t) dst) % (mhd_UINT32_ALIGN))
179
0
    mhd_PUT_32BIT_LE_SLOW (dst, value);
180
0
  else
181
0
#endif /* ! mhd_PUT_64BIT_LE_UNALIGNED */
182
0
  mhd_PUT_32BIT_LE (dst, value);
183
0
}
Unexecuted instantiation: auth_digest.c:mhd_PUT_32BIT_LE_UNALIGN
Unexecuted instantiation: md5_int.c:mhd_PUT_32BIT_LE_UNALIGN
Unexecuted instantiation: sha256_int.c:mhd_PUT_32BIT_LE_UNALIGN
Unexecuted instantiation: sha512_256_int.c:mhd_PUT_32BIT_LE_UNALIGN
184
185
186
/* mhd_GET_32BIT_LE (addr)
187
 * get little-endian 32-bit value storied at addr
188
 * and return it in native-endian mode.
189
 */
190
/* Slow version that works with unaligned addr and with any bytes order */
191
#define mhd_GET_32BIT_LE_SLOW(addr)                             \
192
0
        ( ( (uint32_t) (((const uint8_t*) addr)[0]))            \
193
0
          | (((uint32_t) (((const uint8_t*) addr)[1])) << 8)    \
194
0
          | (((uint32_t) (((const uint8_t*) addr)[2])) << 16)   \
195
0
          | (((uint32_t) (((const uint8_t*) addr)[3])) << 24) )
196
#if mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
197
#  define mhd_GET_32BIT_LE(addr)             \
198
0
        (*(const uint32_t*) (addr))
199
#elif mhd_BYTE_ORDER == mhd_BIG_ENDIAN
200
#  define mhd_GET_32BIT_LE(addr)             \
201
        mhd_BYTES_SWAP32 (*(const uint32_t*) (addr))
202
#else  /* mhd_BYTE_ORDER != mhd_BIG_ENDIAN */
203
/* Endianness was not detected or non-standard like PDP-endian */
204
#  define mhd_GET_32BIT_LE(addr)                          \
205
        ( ( (uint32_t) (((const uint8_t*) addr)[0]))            \
206
          | (((uint32_t) (((const uint8_t*) addr)[1])) << 8)    \
207
          | (((uint32_t) (((const uint8_t*) addr)[2])) << 16)   \
208
          | (((uint32_t) (((const uint8_t*) addr)[3])) << 24) )
209
/* Indicate that mhd_GET_32BIT_LE does not need aligned pointer */
210
#  define mhd_GET_32BIT_LE_UNALIGNED 1
211
#endif /* mhd_BYTE_ORDER != mhd_BIG_ENDIAN */
212
213
/* Get value safely from an unaligned address */
214
MHD_static_inline_ MHD_FN_PAR_NONNULL_ALL_ uint32_t
215
mhd_GET_32BIT_LE_UNALIGN (const void *addr)
216
0
{
217
0
#ifndef mhd_GET_32BIT_LE_UNALIGNED
218
0
  if (0 != ((uintptr_t) addr) % (mhd_UINT32_ALIGN))
219
0
    return mhd_GET_32BIT_LE_SLOW (addr);
220
0
#endif /* ! mhd_PUT_64BIT_LE_UNALIGNED */
221
0
  return mhd_GET_32BIT_LE (addr);
222
0
}
Unexecuted instantiation: auth_digest.c:mhd_GET_32BIT_LE_UNALIGN
Unexecuted instantiation: md5_int.c:mhd_GET_32BIT_LE_UNALIGN
Unexecuted instantiation: sha256_int.c:mhd_GET_32BIT_LE_UNALIGN
Unexecuted instantiation: sha512_256_int.c:mhd_GET_32BIT_LE_UNALIGN
223
224
225
/* mhd_PUT_64BIT_BE (addr, value64)
226
 * put native-endian 64-bit value64 to addr
227
 * in big-endian mode.
228
 */
229
/* Slow version that works with unaligned addr and with any bytes order */
230
0
#define mhd_PUT_64BIT_BE_SLOW(addr, value64) do {                       \
231
0
          ((uint8_t*) (addr))[7] = (uint8_t) ((uint64_t) (value64));           \
232
0
          ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 8);    \
233
0
          ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 16);   \
234
0
          ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 24);   \
235
0
          ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 32);   \
236
0
          ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 40);   \
237
0
          ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 48);   \
238
0
          ((uint8_t*) (addr))[0] = (uint8_t) (((uint64_t) (value64)) >> 56);   \
239
0
} while (0)
240
#if mhd_BYTE_ORDER == mhd_BIG_ENDIAN
241
#  define mhd_PUT_64BIT_BE(addr, value64)             \
242
        ((*(uint64_t*) (addr)) = (uint64_t) (value64))
243
#elif mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
244
#  define mhd_PUT_64BIT_BE(addr, value64)             \
245
0
        ((*(uint64_t*) (addr)) = mhd_BYTES_SWAP64 (value64))
246
#else  /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
247
/* Endianness was not detected or non-standard like PDP-endian */
248
#  define mhd_PUT_64BIT_BE(addr, value64) mhd_PUT_64BIT_BE_SLOW (addr, value64)
249
/* Indicate that mhd_PUT_64BIT_BE does not need aligned pointer */
250
#  define mhd_PUT_64BIT_BE_UNALIGNED 1
251
#endif /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
252
253
/* Put result safely to unaligned address */
254
MHD_static_inline_ void
255
mhd_PUT_64BIT_BE_UNALIGN (void *dst, uint64_t value)
256
0
{
257
0
#ifndef mhd_PUT_64BIT_BE_UNALIGNED
258
0
  if (0 != ((uintptr_t) dst) % (mhd_UINT64_ALIGN))
259
0
    mhd_PUT_64BIT_BE_SLOW (dst, value);
260
0
  else
261
0
#endif /* ! mhd_PUT_64BIT_BE_UNALIGNED */
262
0
  mhd_PUT_64BIT_BE (dst, value);
263
0
}
Unexecuted instantiation: auth_digest.c:mhd_PUT_64BIT_BE_UNALIGN
Unexecuted instantiation: md5_int.c:mhd_PUT_64BIT_BE_UNALIGN
Unexecuted instantiation: sha256_int.c:mhd_PUT_64BIT_BE_UNALIGN
Unexecuted instantiation: sha512_256_int.c:mhd_PUT_64BIT_BE_UNALIGN
264
265
266
/* mhd_GET_64BIT_BE (addr)
267
 * load 64-bit value located at addr in big endian mode.
268
 */
269
#if mhd_BYTE_ORDER == mhd_BIG_ENDIAN
270
#  define mhd_GET_64BIT_BE(addr)             \
271
        (*(const uint64_t*) (addr))
272
#elif mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
273
#  define mhd_GET_64BIT_BE(addr)             \
274
        mhd_BYTES_SWAP64 (*(const uint64_t*) (addr))
275
#else  /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
276
/* Endianness was not detected or non-standard like PDP-endian */
277
#  define mhd_GET_64BIT_BE(addr)                          \
278
        ( (((uint64_t) (((const uint8_t*) addr)[0])) << 56)   \
279
          | (((uint64_t) (((const uint8_t*) addr)[1])) << 48)   \
280
          | (((uint64_t) (((const uint8_t*) addr)[2])) << 40)   \
281
          | (((uint64_t) (((const uint8_t*) addr)[3])) << 32)   \
282
          | (((uint64_t) (((const uint8_t*) addr)[4])) << 24)   \
283
          | (((uint64_t) (((const uint8_t*) addr)[5])) << 16)   \
284
          | (((uint64_t) (((const uint8_t*) addr)[6])) << 8)    \
285
          | ((uint64_t)  (((const uint8_t*) addr)[7])) )
286
/* Indicate that mhd_GET_64BIT_BE does not need aligned pointer */
287
#  define mhd_GET_64BIT_BE_ALLOW_UNALIGNED 1
288
#endif /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
289
290
291
/* mhd_PUT_32BIT_BE (addr, value32)
292
 * put native-endian 32-bit value32 to addr
293
 * in big-endian mode.
294
 */
295
#if mhd_BYTE_ORDER == mhd_BIG_ENDIAN
296
#  define mhd_PUT_32BIT_BE(addr, value32)             \
297
        ((*(uint32_t*) (addr)) = (uint32_t) (value32))
298
#elif mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
299
#  define mhd_PUT_32BIT_BE(addr, value32)             \
300
0
        ((*(uint32_t*) (addr)) = mhd_BYTES_SWAP32 (value32))
301
#else  /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
302
/* Endianness was not detected or non-standard like PDP-endian */
303
#  define mhd_PUT_32BIT_BE(addr, value32) do {                           \
304
          ((uint8_t*) (addr))[3] = (uint8_t) ((uint32_t) (value32));           \
305
          ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 8);    \
306
          ((uint8_t*) (addr))[1] = (uint8_t) (((uint32_t) (value32)) >> 16);   \
307
          ((uint8_t*) (addr))[0] = (uint8_t) (((uint32_t) (value32)) >> 24);   \
308
} while (0)
309
/* Indicate that mhd_PUT_32BIT_BE does not need aligned pointer */
310
#  define mhd_PUT_32BIT_BE_UNALIGNED 1
311
#endif /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
312
313
/* mhd_GET_32BIT_BE (addr)
314
 * get big-endian 32-bit value storied at addr
315
 * and return it in native-endian mode.
316
 */
317
#if mhd_BYTE_ORDER == mhd_BIG_ENDIAN
318
#  define mhd_GET_32BIT_BE(addr)             \
319
        (*(const uint32_t*) (addr))
320
#elif mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN
321
#  define mhd_GET_32BIT_BE(addr)             \
322
        mhd_BYTES_SWAP32 (*(const uint32_t*) (addr))
323
#else  /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
324
/* Endianness was not detected or non-standard like PDP-endian */
325
#  define mhd_GET_32BIT_BE(addr)                          \
326
        ( (((uint32_t) (((const uint8_t*) addr)[0])) << 24)     \
327
          | (((uint32_t) (((const uint8_t*) addr)[1])) << 16)   \
328
          | (((uint32_t) (((const uint8_t*) addr)[2])) << 8)    \
329
          | ((uint32_t) (((const uint8_t*) addr)[3])) )
330
/* Indicate that mhd_GET_32BIT_BE does not need aligned pointer */
331
#  define mhd_GET_32BIT_BE_UNALIGNED 1
332
#endif /* mhd_BYTE_ORDER != mhd_LITTLE_ENDIAN */
333
334
335
/**
336
 * Rotate right 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(_rotr)
344
#  endif /* ! __clang__ */
345
#  define mhd_ROTR32(value32, bits) \
346
        ((uint32_t) _rotr ((uint32_t) (value32), (int) (bits)))
347
#elif mhd_HAS_BUILTIN (__builtin_stdc_rotate_right)
348
#  define mhd_ROTR32(value32, bits) \
349
        (__builtin_stdc_rotate_right ((uint32_t) (value32), (bits)))
350
#elif mhd_HAS_BUILTIN (__builtin_rotateright32)
351
#  define mhd_ROTR32(value32, bits) \
352
0
        ((uint32_t) __builtin_rotateright32 ((value32), (bits)))
353
#else  /* ! __builtin_rotateright32 */
354
MHD_static_inline_ uint32_t
355
mhd_ROTR32 (uint32_t value32, unsigned int bits)
356
{
357
  mhd_assert (32 > bits);
358
  /* Defined in form which modern compiler could optimize. */
359
  return (value32 >> bits) | (value32 << (32 - bits));
360
}
361
362
363
#endif /* ! __builtin_rotateright32 */
364
365
366
/**
367
 * Rotate left 32-bit value by number of bits.
368
 * bits parameter must be more than zero and must be less than 32.
369
 */
370
#if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
371
  defined(__OPTIMIZE__)))
372
/* Clang/C2 do not inline this function if optimizations are turned off. */
373
#  ifndef __clang__
374
#    pragma intrinsic(_rotl)
375
#  endif /* ! __clang__ */
376
#  define mhd_ROTL32(value32, bits) \
377
        ((uint32_t) _rotl ((uint32_t) (value32), (int) (bits)))
378
#elif mhd_HAS_BUILTIN (__builtin_stdc_rotate_left)
379
#  define mhd_ROTL32(value32, bits) \
380
        (__builtin_stdc_rotate_left ((uint32_t) (value32), (bits)))
381
#elif mhd_HAS_BUILTIN (__builtin_rotateleft32)
382
#  define mhd_ROTL32(value32, bits) \
383
0
        ((uint32_t) __builtin_rotateleft32 ((value32), (bits)))
384
#else  /* ! __builtin_rotateleft32 */
385
MHD_static_inline_ uint32_t
386
mhd_ROTL32 (uint32_t value32, unsigned int bits)
387
{
388
  mhd_assert (32 > bits);
389
  /* Defined in form which modern compiler could optimize. */
390
  return (value32 << bits) | (value32 >> (32 - bits));
391
}
392
393
394
#endif /* ! __builtin_rotateleft32 */
395
396
397
/**
398
 * Rotate right 64-bit value by number of bits.
399
 * bits parameter must be more than zero and must be less than 64.
400
 */
401
#if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
402
  defined(__OPTIMIZE__)))
403
/* Clang/C2 do not inline this function if optimisations are turned off. */
404
#  ifndef __clang__
405
#    pragma intrinsic(_rotr64)
406
#  endif /* ! __clang__ */
407
#  define mhd_ROTR64(value64, bits) \
408
        ((uint64_t) _rotr64 ((uint64_t) (value64), (int) (bits)))
409
#elif mhd_HAS_BUILTIN (__builtin_stdc_rotate_right)
410
#  define mhd_ROTR64(value64, bits) \
411
        (__builtin_stdc_rotate_right ((uint64_t) (value64), (bits)))
412
#elif mhd_HAS_BUILTIN (__builtin_rotateright64)
413
#  define mhd_ROTR64(value64, bits) \
414
0
        ((uint64_t) __builtin_rotateright64 ((value64), (bits)))
415
#else  /* ! __builtin_rotateright64 */
416
MHD_static_inline_ uint64_t
417
mhd_ROTR64 (uint64_t value64, unsigned int bits)
418
{
419
  mhd_assert (64 > bits);
420
  /* Defined in form which modern compiler could optimise. */
421
  return (value64 >> bits) | (value64 << (64 - bits));
422
}
423
424
425
#endif /* ! __builtin_rotateright64 */
426
427
mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE
428
429
#endif /* ! MHD_BITHELPERS_H */