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