GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
mhd_bithelpers.h
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2019-2021 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
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#endif
46
47
48#ifdef MHD_HAVE___BUILTIN_BSWAP32
49#define _MHD_BYTES_SWAP32(value32) \
50 ((uint32_t) __builtin_bswap32 ((uint32_t) value32))
51#elif defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
52 defined(__OPTIMIZE__)))
53/* Clang/C2 may not inline this function if optimizations are turned off. */
54#ifndef __clang__
55#pragma intrinsic(_byteswap_ulong)
56#endif /* ! __clang__ */
57#define _MHD_BYTES_SWAP32(value32) \
58 ((uint32_t) _byteswap_ulong ((uint32_t) value32))
59#elif __has_builtin (__builtin_bswap32)
60#define _MHD_BYTES_SWAP32(value32) \
61 ((uint32_t) __builtin_bswap32 ((uint32_t) value32))
62#else /* ! __has_builtin(__builtin_bswap32) */
63#define _MHD_BYTES_SWAP32(value32) \
64 ( (((uint32_t) (value32)) << 24) \
65 | ((((uint32_t) (value32)) & ((uint32_t) 0x0000FF00)) << 8) \
66 | ((((uint32_t) (value32)) & ((uint32_t) 0x00FF0000)) >> 8) \
67 | (((uint32_t) (value32)) >> 24) )
68#endif /* ! __has_builtin(__builtin_bswap32) */
69
70#ifdef MHD_HAVE___BUILTIN_BSWAP64
71#define _MHD_BYTES_SWAP64(value64) \
72 ((uint64_t) __builtin_bswap64 ((uint64_t) value64))
73#elif defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
74 defined(__OPTIMIZE__)))
75/* Clang/C2 may not inline this function if optimizations are turned off. */
76#ifndef __clang__
77#pragma intrinsic(_byteswap_uint64)
78#endif /* ! __clang__ */
79#define _MHD_BYTES_SWAP64(value64) \
80 ((uint64_t) _byteswap_uint64 ((uint64_t) value64))
81#elif __has_builtin (__builtin_bswap64)
82#define _MHD_BYTES_SWAP64(value64) \
83 ((uint64_t) __builtin_bswap64 ((uint64_t) value64))
84#else /* ! __has_builtin(__builtin_bswap64) */
85#define _MHD_BYTES_SWAP64(value64) \
86 ( (((uint64_t) (value64)) << 56) \
87 | ((((uint64_t) (value64)) & ((uint64_t) 0x000000000000FF00)) << 40) \
88 | ((((uint64_t) (value64)) & ((uint64_t) 0x0000000000FF0000)) << 24) \
89 | ((((uint64_t) (value64)) & ((uint64_t) 0x00000000FF000000)) << 8) \
90 | ((((uint64_t) (value64)) & ((uint64_t) 0x000000FF00000000)) >> 8) \
91 | ((((uint64_t) (value64)) & ((uint64_t) 0x0000FF0000000000)) >> 24) \
92 | ((((uint64_t) (value64)) & ((uint64_t) 0x00FF000000000000)) >> 40) \
93 | (((uint64_t) (value64)) >> 56) )
94#endif /* ! __has_builtin(__builtin_bswap64) */
95
96
97/* _MHD_PUT_64BIT_LE (addr, value64)
98 * put native-endian 64-bit value64 to addr
99 * in little-endian mode.
100 */
101/* Slow version that works with unaligned addr and with any bytes order */
102#define _MHD_PUT_64BIT_LE_SLOW(addr, value64) do { \
103 ((uint8_t*) (addr))[0] = (uint8_t) ((uint64_t) (value64)); \
104 ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 8); \
105 ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 16); \
106 ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 24); \
107 ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 32); \
108 ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 40); \
109 ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48); \
110 ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56); \
111} while (0)
112#if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
113#define _MHD_PUT_64BIT_LE(addr, value64) \
114 ((*(uint64_t*) (addr)) = (uint64_t) (value64))
115#elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
116#define _MHD_PUT_64BIT_LE(addr, value64) \
117 ((*(uint64_t*) (addr)) = _MHD_BYTES_SWAP64 (value64))
118#else /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
119/* Endianness was not detected or non-standard like PDP-endian */
120#define _MHD_PUT_64BIT_LE(addr, value64) do { \
121 ((uint8_t*) (addr))[0] = (uint8_t) ((uint64_t) (value64)); \
122 ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 8); \
123 ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 16); \
124 ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 24); \
125 ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 32); \
126 ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 40); \
127 ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48); \
128 ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56); \
129} while (0)
130/* Indicate that _MHD_PUT_64BIT_LE does not need aligned pointer */
131#define _MHD_PUT_64BIT_LE_UNALIGNED 1
132#endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
133
134/* Put result safely to unaligned address */
135_MHD_static_inline void
136_MHD_PUT_64BIT_LE_SAFE (void *dst, uint64_t value)
137{
138#ifndef _MHD_PUT_64BIT_LE_UNALIGNED
139 if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN))
140 _MHD_PUT_64BIT_LE_SLOW (dst, value);
141 else
142#endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */
143 _MHD_PUT_64BIT_LE (dst, value);
144}
145
146
147/* _MHD_PUT_32BIT_LE (addr, value32)
148 * put native-endian 32-bit value32 to addr
149 * in little-endian mode.
150 */
151#if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
152#define _MHD_PUT_32BIT_LE(addr,value32) \
153 ((*(uint32_t*) (addr)) = (uint32_t) (value32))
154#elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
155#define _MHD_PUT_32BIT_LE(addr, value32) \
156 ((*(uint32_t*) (addr)) = _MHD_BYTES_SWAP32 (value32))
157#else /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
158/* Endianness was not detected or non-standard like PDP-endian */
159#define _MHD_PUT_32BIT_LE(addr, value32) do { \
160 ((uint8_t*) (addr))[0] = (uint8_t) ((uint32_t) (value32)); \
161 ((uint8_t*) (addr))[1] = (uint8_t) (((uint32_t) (value32)) >> 8); \
162 ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 16); \
163 ((uint8_t*) (addr))[3] = (uint8_t) (((uint32_t) (value32)) >> 24); \
164} while (0)
165/* Indicate that _MHD_PUT_32BIT_LE does not need aligned pointer */
166#define _MHD_PUT_32BIT_LE_UNALIGNED 1
167#endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
168
169/* _MHD_GET_32BIT_LE (addr)
170 * get little-endian 32-bit value storied at addr
171 * and return it in native-endian mode.
172 */
173#if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
174#define _MHD_GET_32BIT_LE(addr) \
175 (*(const uint32_t*) (addr))
176#elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
177#define _MHD_GET_32BIT_LE(addr) \
178 _MHD_BYTES_SWAP32 (*(const uint32_t*) (addr))
179#else /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
180/* Endianness was not detected or non-standard like PDP-endian */
181#define _MHD_GET_32BIT_LE(addr) \
182 ( ( (uint32_t) (((const uint8_t*) addr)[0])) \
183 | (((uint32_t) (((const uint8_t*) addr)[1])) << 8) \
184 | (((uint32_t) (((const uint8_t*) addr)[2])) << 16) \
185 | (((uint32_t) (((const uint8_t*) addr)[3])) << 24) )
186/* Indicate that _MHD_GET_32BIT_LE does not need aligned pointer */
187#define _MHD_GET_32BIT_LE_UNALIGNED 1
188#endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
189
190
191/* _MHD_PUT_64BIT_BE (addr, value64)
192 * put native-endian 64-bit value64 to addr
193 * in big-endian mode.
194 */
195/* Slow version that works with unaligned addr and with any bytes order */
196#define _MHD_PUT_64BIT_BE_SLOW(addr, value64) do { \
197 ((uint8_t*) (addr))[7] = (uint8_t) ((uint64_t) (value64)); \
198 ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 8); \
199 ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 16); \
200 ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 24); \
201 ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 32); \
202 ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 40); \
203 ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 48); \
204 ((uint8_t*) (addr))[0] = (uint8_t) (((uint64_t) (value64)) >> 56); \
205} while (0)
206#if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
207#define _MHD_PUT_64BIT_BE(addr, value64) \
208 ((*(uint64_t*) (addr)) = (uint64_t) (value64))
209#elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
210#define _MHD_PUT_64BIT_BE(addr, value64) \
211 ((*(uint64_t*) (addr)) = _MHD_BYTES_SWAP64 (value64))
212#else /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
213/* Endianness was not detected or non-standard like PDP-endian */
214#define _MHD_PUT_64BIT_BE(addr, value64) _MHD_PUT_64BIT_BE_SLOW(addr, value64)
215/* Indicate that _MHD_PUT_64BIT_BE does not need aligned pointer */
216#define _MHD_PUT_64BIT_BE_UNALIGNED 1
217#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
218
219/* Put result safely to unaligned address */
220_MHD_static_inline void
221_MHD_PUT_64BIT_BE_SAFE (void *dst, uint64_t value)
222{
223#ifndef _MHD_PUT_64BIT_BE_UNALIGNED
224 if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN))
225 _MHD_PUT_64BIT_BE_SLOW (dst, value);
226 else
227#endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */
228 _MHD_PUT_64BIT_BE (dst, value);
229}
230
231
232/* _MHD_PUT_32BIT_BE (addr, value32)
233 * put native-endian 32-bit value32 to addr
234 * in big-endian mode.
235 */
236#if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
237#define _MHD_PUT_32BIT_BE(addr, value32) \
238 ((*(uint32_t*) (addr)) = (uint32_t) (value32))
239#elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
240#define _MHD_PUT_32BIT_BE(addr, value32) \
241 ((*(uint32_t*) (addr)) = _MHD_BYTES_SWAP32 (value32))
242#else /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
243/* Endianness was not detected or non-standard like PDP-endian */
244#define _MHD_PUT_32BIT_BE(addr, value32) do { \
245 ((uint8_t*) (addr))[3] = (uint8_t) ((uint32_t) (value32)); \
246 ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 8); \
247 ((uint8_t*) (addr))[1] = (uint8_t) (((uint32_t) (value32)) >> 16); \
248 ((uint8_t*) (addr))[0] = (uint8_t) (((uint32_t) (value32)) >> 24); \
249} while (0)
250/* Indicate that _MHD_PUT_32BIT_BE does not need aligned pointer */
251#define _MHD_PUT_32BIT_BE_UNALIGNED 1
252#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
253
254/* _MHD_GET_32BIT_BE (addr)
255 * get big-endian 32-bit value storied at addr
256 * and return it in native-endian mode.
257 */
258#if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
259#define _MHD_GET_32BIT_BE(addr) \
260 (*(const uint32_t*) (addr))
261#elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
262#define _MHD_GET_32BIT_BE(addr) \
263 _MHD_BYTES_SWAP32 (*(const uint32_t*) (addr))
264#else /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
265/* Endianness was not detected or non-standard like PDP-endian */
266#define _MHD_GET_32BIT_BE(addr) \
267 ( (((uint32_t) (((const uint8_t*) addr)[0])) << 24) \
268 | (((uint32_t) (((const uint8_t*) addr)[1])) << 16) \
269 | (((uint32_t) (((const uint8_t*) addr)[2])) << 8) \
270 | ((uint32_t) (((const uint8_t*) addr)[3])) )
271/* Indicate that _MHD_GET_32BIT_BE does not need aligned pointer */
272#define _MHD_GET_32BIT_BE_UNALIGNED 1
273#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
274
275
280#if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
281 defined(__OPTIMIZE__)))
282/* Clang/C2 do not inline this function if optimizations are turned off. */
283#ifndef __clang__
284#pragma intrinsic(_rotr)
285#endif /* ! __clang__ */
286#define _MHD_ROTR32(value32, bits) \
287 ((uint32_t) _rotr ((uint32_t) (value32),(bits)))
288#elif __has_builtin (__builtin_rotateright32)
289#define _MHD_ROTR32(value32, bits) \
290 ((uint32_t) __builtin_rotateright32 ((value32), (bits)))
291#else /* ! __builtin_rotateright32 */
292_MHD_static_inline uint32_t
293_MHD_ROTR32 (uint32_t value32, int bits)
294{
295 bits %= 32;
296 /* Defined in form which modern compiler could optimize. */
297 return (value32 >> bits) | (value32 << (32 - bits));
298}
299
300
301#endif /* ! __builtin_rotateright32 */
302
303
308#if defined(_MSC_FULL_VER) && (! defined(__clang__) || (defined(__c2__) && \
309 defined(__OPTIMIZE__)))
310/* Clang/C2 do not inline this function if optimizations are turned off. */
311#ifndef __clang__
312#pragma intrinsic(_rotl)
313#endif /* ! __clang__ */
314#define _MHD_ROTL32(value32, bits) \
315 ((uint32_t) _rotl ((uint32_t) (value32),(bits)))
316#elif __has_builtin (__builtin_rotateleft32)
317#define _MHD_ROTL32(value32, bits) \
318 ((uint32_t) __builtin_rotateleft32 ((value32), (bits)))
319#else /* ! __builtin_rotateleft32 */
320_MHD_static_inline uint32_t
321_MHD_ROTL32 (uint32_t value32, int bits)
322{
323 bits %= 32;
324 /* Defined in form which modern compiler could optimize. */
325 return (value32 << bits) | (value32 >> (32 - bits));
326}
327
328
329#endif /* ! __builtin_rotateleft32 */
330
331
332#endif /* ! MHD_BITHELPERS_H */
types alignment macros
#define _MHD_UINT64_ALIGN
Definition mhd_align.h:93
#define _MHD_PUT_64BIT_BE(addr, value64)
#define _MHD_PUT_64BIT_LE_SLOW(addr, value64)
_MHD_static_inline uint32_t _MHD_ROTR32(uint32_t value32, int bits)
_MHD_static_inline void _MHD_PUT_64BIT_BE_SAFE(void *dst, uint64_t value)
#define _MHD_PUT_64BIT_LE(addr, value64)
#define _MHD_PUT_64BIT_BE_SLOW(addr, value64)
_MHD_static_inline uint32_t _MHD_ROTL32(uint32_t value32, int bits)
_MHD_static_inline void _MHD_PUT_64BIT_LE_SAFE(void *dst, uint64_t value)
additional automatic macros for MHD_config.h
macro definitions for host byte order