GNU libmicrohttpd  0.9.66
mhd_bithelpers.h
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2019 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_byteorder.h"
30 #include <stdint.h>
31 #if defined(_MSC_FULL_VER) && (!defined(__clang__) || (defined(__c2__) && defined(__OPTIMIZE__)))
32 /* Declarations for VC & Clang/C2 built-ins */
33 #include <intrin.h>
34 #endif /* _MSC_FULL_VER */
35 
36 #ifndef __has_builtin
37 /* Avoid precompiler errors with non-clang */
38 # define __has_builtin(x) 0
39 #endif
40 
41 
42 #ifdef MHD_HAVE___BUILTIN_BSWAP32
43 #define _MHD_BYTES_SWAP32(value32) \
44  ((uint32_t)__builtin_bswap32((uint32_t)value32))
45 #elif defined(_MSC_FULL_VER) && (!defined(__clang__) || (defined(__c2__) && defined(__OPTIMIZE__)))
46 /* Clang/C2 may not inline this function if optimizations are turned off. */
47 #ifndef __clang__
48 #pragma intrinsic(_byteswap_ulong)
49 #endif /* ! __clang__ */
50 #define _MHD_BYTES_SWAP32(value32) \
51  ((uint32_t)_byteswap_ulong((uint32_t)value32))
52 #elif __has_builtin(__builtin_bswap32)
53 #define _MHD_BYTES_SWAP32(value32) \
54  ((uint32_t)__builtin_bswap32((uint32_t)value32))
55 #else /* ! __has_builtin(__builtin_bswap32) */
56 #define _MHD_BYTES_SWAP32(value32) \
57  ( (((uint32_t)(value32)) << 24) | \
58  ((((uint32_t)(value32)) & ((uint32_t)0x0000FF00)) << 8) | \
59  ((((uint32_t)(value32)) & ((uint32_t)0x00FF0000)) >> 8) | \
60  (((uint32_t)(value32)) >> 24) )
61 #endif /* ! __has_builtin(__builtin_bswap32) */
62 
63 #ifdef MHD_HAVE___BUILTIN_BSWAP64
64 #define _MHD_BYTES_SWAP64(value64) \
65  ((uint64_t)__builtin_bswap64((uint64_t)value64))
66 #elif defined(_MSC_FULL_VER) && (!defined(__clang__) || (defined(__c2__) && defined(__OPTIMIZE__)))
67 /* Clang/C2 may not inline this function if optimizations are turned off. */
68 #ifndef __clang__
69 #pragma intrinsic(_byteswap_uint64)
70 #endif /* ! __clang__ */
71 #define _MHD_BYTES_SWAP64(value64) \
72  ((uint64_t)_byteswap_uint64((uint64_t)value64))
73 #elif __has_builtin(__builtin_bswap64)
74 #define _MHD_BYTES_SWAP64(value64) \
75  ((uint64_t)__builtin_bswap64((uint64_t)value64))
76 #else /* ! __has_builtin(__builtin_bswap64) */
77 #define _MHD_BYTES_SWAP64(value64) \
78  ( (((uint64_t)(value64)) << 56) | \
79  ((((uint64_t)(value64)) & ((uint64_t)0x000000000000FF00)) << 40) | \
80  ((((uint64_t)(value64)) & ((uint64_t)0x0000000000FF0000)) << 24) | \
81  ((((uint64_t)(value64)) & ((uint64_t)0x00000000FF000000)) << 8) | \
82  ((((uint64_t)(value64)) & ((uint64_t)0x000000FF00000000)) >> 8) | \
83  ((((uint64_t)(value64)) & ((uint64_t)0x0000FF0000000000)) >> 24) | \
84  ((((uint64_t)(value64)) & ((uint64_t)0x00FF000000000000)) >> 40) | \
85  (((uint64_t)(value64)) >> 56) )
86 #endif /* ! __has_builtin(__builtin_bswap64) */
87 
88 
89 /* _MHD_PUT_64BIT_LE (addr, value64)
90  * put native-endian 64-bit value64 to addr
91  * in little-endian mode.
92  */
93 #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
94 #define _MHD_PUT_64BIT_LE(addr, value64) \
95  ((*(uint64_t*)(addr)) = (uint64_t)(value64))
96 #elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
97 #define _MHD_PUT_64BIT_LE(addr, value64) \
98  ((*(uint64_t*)(addr)) = _MHD_BYTES_SWAP64(value64))
99 #else /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
100 /* Endianess was not detected or non-standard like PDP-endian */
101 #define _MHD_PUT_64BIT_LE(addr, value64) do { \
102  ((uint8_t*)(addr))[0] = (uint8_t)((uint64_t)(value64)); \
103  ((uint8_t*)(addr))[1] = (uint8_t)(((uint64_t)(value64)) >> 8); \
104  ((uint8_t*)(addr))[2] = (uint8_t)(((uint64_t)(value64)) >> 16); \
105  ((uint8_t*)(addr))[3] = (uint8_t)(((uint64_t)(value64)) >> 24); \
106  ((uint8_t*)(addr))[4] = (uint8_t)(((uint64_t)(value64)) >> 32); \
107  ((uint8_t*)(addr))[5] = (uint8_t)(((uint64_t)(value64)) >> 40); \
108  ((uint8_t*)(addr))[6] = (uint8_t)(((uint64_t)(value64)) >> 48); \
109  ((uint8_t*)(addr))[7] = (uint8_t)(((uint64_t)(value64)) >> 56); \
110  } while (0)
111 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
112 
113 /* _MHD_PUT_32BIT_LE (addr, value32)
114  * put native-endian 32-bit value32 to addr
115  * in little-endian mode.
116  */
117 #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
118 #define _MHD_PUT_32BIT_LE(addr,value32) \
119  ((*(uint32_t*)(addr)) = (uint32_t)(value32))
120 #elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
121 #define _MHD_PUT_32BIT_LE(addr, value32) \
122  ((*(uint32_t*)(addr)) = _MHD_BYTES_SWAP32(value32))
123 #else /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
124 /* Endianess was not detected or non-standard like PDP-endian */
125 #define _MHD_PUT_32BIT_LE(addr, value32) do { \
126  ((uint8_t*)(addr))[0] = (uint8_t)((uint32_t)(value32)); \
127  ((uint8_t*)(addr))[1] = (uint8_t)(((uint32_t)(value32)) >> 8); \
128  ((uint8_t*)(addr))[2] = (uint8_t)(((uint32_t)(value32)) >> 16); \
129  ((uint8_t*)(addr))[3] = (uint8_t)(((uint32_t)(value32)) >> 24); \
130  } while (0)
131 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
132 
133 /* _MHD_GET_32BIT_LE (addr)
134  * get little-endian 32-bit value storied at addr
135  * and return it in native-endian mode.
136  */
137 #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
138 #define _MHD_GET_32BIT_LE(addr) \
139  (*(const uint32_t*)(addr))
140 #elif _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
141 #define _MHD_GET_32BIT_LE(addr) \
142  _MHD_BYTES_SWAP32(*(const uint32_t*)(addr))
143 #else /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
144 /* Endianess was not detected or non-standard like PDP-endian */
145 #define _MHD_GET_32BIT_LE(addr) \
146  ( ( (uint32_t)(((const uint8_t*)addr)[0])) | \
147  (((uint32_t)(((const uint8_t*)addr)[1])) << 8) | \
148  (((uint32_t)(((const uint8_t*)addr)[2])) << 16) | \
149  (((uint32_t)(((const uint8_t*)addr)[3])) << 24) )
150 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
151 
152 
153 /* _MHD_PUT_64BIT_BE (addr, value64)
154  * put native-endian 64-bit value64 to addr
155  * in big-endian mode.
156  */
157 #if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
158 #define _MHD_PUT_64BIT_BE(addr, value64) \
159  ((*(uint64_t*)(addr)) = (uint64_t)(value64))
160 #elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
161 #define _MHD_PUT_64BIT_BE(addr, value64) \
162  ((*(uint64_t*)(addr)) = _MHD_BYTES_SWAP64(value64))
163 #else /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
164 /* Endianess was not detected or non-standard like PDP-endian */
165 #define _MHD_PUT_64BIT_BE(addr, value64) do { \
166  ((uint8_t*)(addr))[7] = (uint8_t)((uint64_t)(value64)); \
167  ((uint8_t*)(addr))[6] = (uint8_t)(((uint64_t)(value64)) >> 8); \
168  ((uint8_t*)(addr))[5] = (uint8_t)(((uint64_t)(value64)) >> 16); \
169  ((uint8_t*)(addr))[4] = (uint8_t)(((uint64_t)(value64)) >> 24); \
170  ((uint8_t*)(addr))[3] = (uint8_t)(((uint64_t)(value64)) >> 32); \
171  ((uint8_t*)(addr))[2] = (uint8_t)(((uint64_t)(value64)) >> 40); \
172  ((uint8_t*)(addr))[1] = (uint8_t)(((uint64_t)(value64)) >> 48); \
173  ((uint8_t*)(addr))[0] = (uint8_t)(((uint64_t)(value64)) >> 56); \
174  } while (0)
175 #endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
176 
177 /* _MHD_PUT_32BIT_BE (addr, value32)
178  * put native-endian 32-bit value32 to addr
179  * in big-endian mode.
180  */
181 #if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
182 #define _MHD_PUT_32BIT_BE(addr, value32) \
183  ((*(uint32_t*)(addr)) = (uint32_t)(value32))
184 #elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
185 #define _MHD_PUT_32BIT_BE(addr, value32) \
186  ((*(uint32_t*)(addr)) = _MHD_BYTES_SWAP32(value32))
187 #else /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
188 /* Endianess was not detected or non-standard like PDP-endian */
189 #define _MHD_PUT_32BIT_BE(addr, value32) do { \
190  ((uint8_t*)(addr))[3] = (uint8_t)((uint32_t)(value32)); \
191  ((uint8_t*)(addr))[2] = (uint8_t)(((uint32_t)(value32)) >> 8); \
192  ((uint8_t*)(addr))[1] = (uint8_t)(((uint32_t)(value32)) >> 16); \
193  ((uint8_t*)(addr))[0] = (uint8_t)(((uint32_t)(value32)) >> 24); \
194  } while (0)
195 #endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
196 
197 /* _MHD_GET_32BIT_BE (addr)
198  * get big-endian 32-bit value storied at addr
199  * and return it in native-endian mode.
200  */
201 #if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
202 #define _MHD_GET_32BIT_BE(addr) \
203  (*(const uint32_t*)(addr))
204 #elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
205 #define _MHD_GET_32BIT_BE(addr) \
206  _MHD_BYTES_SWAP32(*(const uint32_t*)(addr))
207 #else /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
208 /* Endianess was not detected or non-standard like PDP-endian */
209 #define _MHD_GET_32BIT_BE(addr) \
210  ( (((uint32_t)(((const uint8_t*)addr)[0])) << 24) | \
211  (((uint32_t)(((const uint8_t*)addr)[1])) << 16) | \
212  (((uint32_t)(((const uint8_t*)addr)[2])) << 8) | \
213  ((uint32_t) (((const uint8_t*)addr)[3])) )
214 #endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
215 
216 
221 #if defined(_MSC_FULL_VER) && (!defined(__clang__) || (defined(__c2__) && defined(__OPTIMIZE__)))
222 /* Clang/C2 do not inline this function if optimizations are turned off. */
223 #ifndef __clang__
224 #pragma intrinsic(_rotr)
225 #endif /* ! __clang__ */
226 #define _MHD_ROTR32(value32, bits) \
227  ((uint32_t)_rotr((uint32_t)(value32),(bits)))
228 #else /* ! _MSC_FULL_VER */
229 /* Defined in form which modern compiler could optimize. */
230 #define _MHD_ROTR32(value32, bits) \
231  (((uint32_t)(value32)) >> (bits) | ((uint32_t)(value32)) << (32 - bits))
232 #endif /* ! _MSC_FULL_VER */
233 
234 
235 #endif /* ! MHD_BITHELPERS_H */
macro definitions for host byte order