Merge branch 'collectd-5.7' into collectd-5.8
[collectd.git] / src / libcollectdclient / collectd / stdendian.h
1 /*
2  *   stdendian.h
3  *
4  *   This header defines the following endian macros as defined here:
5  *   http://austingroupbugs.net/view.php?id=162
6  *
7  *     BYTE_ORDER         this macro shall have a value equal to one
8  *                        of the *_ENDIAN macros in this header.
9  *     LITTLE_ENDIAN      if BYTE_ORDER == LITTLE_ENDIAN, the host
10  *                        byte order is from least significant to
11  *                        most significant.
12  *     BIG_ENDIAN         if BYTE_ORDER == BIG_ENDIAN, the host byte
13  *                        order is from most significant to least
14  *                        significant.
15  *
16  *   The following are defined as macros:
17  *
18  *     uint16_t bswap16(uint16_t x);
19  *     uint32_t bswap32(uint32_t x);
20  *     uint64_t bswap64(uint64_t x);
21
22  *     uint16_t htobe16(uint16_t x);
23  *     uint16_t htole16(uint16_t x);
24  *     uint16_t be16toh(uint16_t x);
25  *     uint16_t le16toh(uint16_t x);
26  *
27  *     uint32_t htobe32(uint32_t x);
28  *     uint32_t htole32(uint32_t x);
29  *     uint32_t be32toh(uint32_t x);
30  *     uint32_t le32toh(uint32_t x);
31  *
32  *     uint64_t htobe64(uint64_t x);
33  *     uint64_t htole64(uint64_t x);
34  *     uint64_t be64toh(uint64_t x);
35  *     uint64_t le64toh(uint64_t x);
36  *
37  *   The header defines the following macro for OpenCL compatibility
38  *
39  https://www.khronos.org/registry/cl/sdk/2.0/docs/man/xhtml/preprocessorDirectives.html
40  *
41  *     __ENDIAN_LITTLE__  if BYTE_ORDER == LITTLE_ENDIAN then this
42  *                        macro is present for OpenCL compatibility
43  *
44  *   The implementation provides a uniform interface to endian macros using only
45  *   system headers on recent Linux, Darwin, FreeBSD, Solaris and Windows
46  systems.
47  *
48  *   This approach is intended to avoid the need for preflight configure
49  scripts.
50  *   An alternative approach would be to test compiler CPU architecture marcros.
51  *
52  *   This header has had *limited* testing on recent C11/C++11 compilers and is
53  *   based on the austin bug tracker interface, manpages, and headers present in
54  *   Linux, FreeBSD, Windows, Solaris and Darwin.
55  *
56  *   The header uses __builtin_bswapXX intrinsic with GCC/Clang (__GNUC__) on
57  *   platforms that do not provide bswap16, bswap32, bswap64 (Darwin)
58  *
59  *   Public Domain.
60  */
61
62 #if HAVE_STDINT_H
63 #include <stdint.h>
64 #endif
65
66 /* Linux / GLIBC */
67 #if defined(__linux__) || defined(__GLIBC__)
68 #include <byteswap.h>
69 #include <endian.h>
70 #define __ENDIAN_DEFINED 1
71 #define __BSWAP_DEFINED 1
72 #define __HOSTSWAP_DEFINED 1
73 #define _BYTE_ORDER __BYTE_ORDER
74 #define _LITTLE_ENDIAN __LITTLE_ENDIAN
75 #define _BIG_ENDIAN __BIG_ENDIAN
76 #define bswap16(x) bswap_16(x)
77 #define bswap32(x) bswap_32(x)
78 #define bswap64(x) bswap_64(x)
79 #endif /* __linux__ || __GLIBC__ */
80
81 /* BSD */
82 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) ||   \
83     defined(__OpenBSD__)
84 #include <sys/endian.h>
85 #define __ENDIAN_DEFINED 1
86 #define __BSWAP_DEFINED 1
87 #define __HOSTSWAP_DEFINED 1
88 #endif /* BSD */
89
90 /* Solaris */
91 #if defined(sun)
92 #include <sys/byteorder.h>
93 #include <sys/isa_defs.h>
94 #define bswap16(x) BSWAP_16(x)
95 #define bswap32(x) BSWAP_32(x)
96 #define bswap64(x) BSWAP_64(x)
97 /* sun headers don't set a value for _LITTLE_ENDIAN or _BIG_ENDIAN */
98 #if defined(_LITTLE_ENDIAN)
99 #undef _LITTLE_ENDIAN
100 #define _LITTLE_ENDIAN 1234
101 #define _BIG_ENDIAN 4321
102 #define _BYTE_ORDER _LITTLE_ENDIAN
103 #elif defined(_BIG_ENDIAN)
104 #undef _BIG_ENDIAN
105 #define _LITTLE_ENDIAN 1234
106 #define _BIG_ENDIAN 4321
107 #define _BYTE_ORDER _BIG_ENDIAN
108 #endif
109 #define __ENDIAN_DEFINED 1
110 #endif /* sun */
111
112 /* AIX */
113 #if defined(_AIX)
114 #include <sys/machine.h>
115 #if BYTE_ORDER == LITTLE_ENDIAN
116 #define _LITTLE_ENDIAN 1234
117 #define _BIG_ENDIAN 4321
118 #define _BYTE_ORDER _LITTLE_ENDIAN
119 #elif BYTE_ORDER == BIG_ENDIAN
120 #define _LITTLE_ENDIAN 1234
121 #define _BIG_ENDIAN 4321
122 #define _BYTE_ORDER _BIG_ENDIAN
123 #else
124 #error Could not determine CPU byte order for AIX
125 #endif
126 #define __ENDIAN_DEFINED 1
127 #endif /* AIX */
128
129 /* Windows */
130 #if defined(_WIN32) || defined(_MSC_VER)
131 /* assumes all Microsoft targets are little endian */
132 #define _LITTLE_ENDIAN 1234
133 #define _BIG_ENDIAN 4321
134 #define _BYTE_ORDER _LITTLE_ENDIAN
135 #define __ENDIAN_DEFINED 1
136 #endif /* _MSC_VER */
137
138 /* OS X */
139 #if defined(__APPLE__)
140 #include <machine/endian.h>
141 #define _BYTE_ORDER BYTE_ORDER
142 #define _LITTLE_ENDIAN LITTLE_ENDIAN
143 #define _BIG_ENDIAN BIG_ENDIAN
144 #define __ENDIAN_DEFINED 1
145 #endif /* __APPLE__ */
146
147 /* OpenCL */
148 #if defined(__OPENCL_VERSION__)
149 #define _LITTLE_ENDIAN 1234
150 #define __BIG_ENDIAN 4321
151 #if defined(__ENDIAN_LITTLE__)
152 #define _BYTE_ORDER _LITTLE_ENDIAN
153 #else
154 #define _BYTE_ORDER _BIG_ENDIAN
155 #endif
156 #define bswap16(x) as_ushort(as_uchar2(ushort(x)).s1s0)
157 #define bswap32(x) as_uint(as_uchar4(uint(x)).s3s2s1s0)
158 #define bswap64(x) as_ulong(as_uchar8(ulong(x)).s7s6s5s4s3s2s1s0)
159 #define __ENDIAN_DEFINED 1
160 #define __BSWAP_DEFINED 1
161 #endif
162
163 /* Unknown */
164 #if !__ENDIAN_DEFINED
165 #error Could not determine CPU byte order
166 #endif
167
168 /* POSIX - http://austingroupbugs.net/view.php?id=162 */
169 #ifndef BYTE_ORDER
170 #define BYTE_ORDER _BYTE_ORDER
171 #endif
172 #ifndef LITTLE_ENDIAN
173 #define LITTLE_ENDIAN _LITTLE_ENDIAN
174 #endif
175 #ifndef BIG_ENDIAN
176 #define BIG_ENDIAN _BIG_ENDIAN
177 #endif
178
179 /* OpenCL compatibility - define __ENDIAN_LITTLE__ on little endian systems */
180 #if _BYTE_ORDER == _LITTLE_ENDIAN
181 #if !defined(__ENDIAN_LITTLE__)
182 #define __ENDIAN_LITTLE__ 1
183 #endif
184 #endif
185
186 /* Byte swap macros */
187 #if !__BSWAP_DEFINED
188
189 #ifndef bswap16
190 /* handle missing __builtin_bswap16
191  * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 */
192 #if defined __GNUC__
193 #define bswap16(x) __builtin_bswap16(x)
194 #else
195 #define bswap16(x)                                                             \
196   ((uint16_t)((((uint16_t)(x)&0xff00) >> 8) | (((uint16_t)(x)&0x00ff) << 8)))
197 #endif
198 #endif
199
200 #ifndef bswap32
201 #if defined __GNUC__
202 #define bswap32(x) __builtin_bswap32(x)
203 #else
204 #define bswap32(x)                                                             \
205   ((uint32_t)(                                                                 \
206       (((uint32_t)(x)&0xff000000) >> 24) | (((uint32_t)(x)&0x00ff0000) >> 8) | \
207       (((uint32_t)(x)&0x0000ff00) << 8) | (((uint32_t)(x)&0x000000ff) << 24)))
208 #endif
209 #endif
210
211 #ifndef bswap64
212 #if defined __GNUC__
213 #define bswap64(x) __builtin_bswap64(x)
214 #else
215 #define bswap64(x)                                                             \
216   ((uint64_t)((((uint64_t)(x)&0xff00000000000000ull) >> 56) |                  \
217               (((uint64_t)(x)&0x00ff000000000000ull) >> 40) |                  \
218               (((uint64_t)(x)&0x0000ff0000000000ull) >> 24) |                  \
219               (((uint64_t)(x)&0x000000ff00000000ull) >> 8) |                   \
220               (((uint64_t)(x)&0x00000000ff000000ull) << 8) |                   \
221               (((uint64_t)(x)&0x0000000000ff0000ull) << 24) |                  \
222               (((uint64_t)(x)&0x000000000000ff00ull) << 40) |                  \
223               (((uint64_t)(x)&0x00000000000000ffull) << 56)))
224 #endif
225 #endif
226
227 #endif
228
229 /* Host swap macros */
230 #ifndef __HOSTSWAP_DEFINED
231 #if _BYTE_ORDER == _LITTLE_ENDIAN
232 #define htobe16(x) bswap16((x))
233 #define htole16(x) ((uint16_t)(x))
234 #define be16toh(x) bswap16((x))
235 #define le16toh(x) ((uint16_t)(x))
236
237 #define htobe32(x) bswap32((x))
238 #define htole32(x) ((uint32_t)(x))
239 #define be32toh(x) bswap32((x))
240 #define le32toh(x) ((uint32_t)(x))
241
242 #define htobe64(x) bswap64((x))
243 #define htole64(x) ((uint64_t)(x))
244 #define be64toh(x) bswap64((x))
245 #define le64toh(x) ((uint64_t)(x))
246 #elif _BYTE_ORDER == _BIG_ENDIAN
247 #define htobe16(x) ((uint16_t)(x))
248 #define htole16(x) bswap16((x))
249 #define be16toh(x) ((uint16_t)(x))
250 #define le16toh(x) bswap16((x))
251
252 #define htobe32(x) ((uint32_t)(x))
253 #define htole32(x) bswap32((x))
254 #define be32toh(x) ((uint32_t)(x))
255 #define le64toh(x) bswap64((x))
256
257 #define htobe64(x) ((uint64_t)(x))
258 #define htole64(x) bswap64((x))
259 #define be64toh(x) ((uint64_t)(x))
260 #define le32toh(x) bswap32((x))
261 #endif
262 #endif