-
Notifications
You must be signed in to change notification settings - Fork 5
/
endian_compat.h
185 lines (161 loc) · 5.22 KB
/
endian_compat.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
* SPDX-License-Identifier: MIT
*/
#ifndef FAEST_COMPAT_ENDIAN_H
#define FAEST_COMPAT_ENDIAN_H
#include <stdint.h>
#include "macros.h"
#if defined(__GNUC__) || defined(__clang__)
#define bswap16(x) __builtin_bswap16(x)
#define bswap32(x) __builtin_bswap32(x)
#define bswap64(x) __builtin_bswap64(x)
#elif defined(_MSC_VER)
#include <stdlib.h>
#define bswap16(x) _byteswap_ushort(x)
#define bswap32(x) _byteswap_ulong(x)
#define bswap64(x) _byteswap_uint64(x)
#else
static inline uint16_t ATTR_CONST bswap16(uint16_t x) {
return ((x & 0xff00) >> 8) | ((x & 0x00ff) << 8);
}
static inline uint32_t ATTR_CONST bswap32(uint32_t x) {
return ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) | ((x & 0x0000ff00) << 8) |
((x & 0x000000ff) << 24);
}
static inline uint64_t ATTR_CONST bswap64(uint64_t x) {
return ((x & UINT64_C(0xff00000000000000)) >> 56) | ((x & UINT64_C(0x00ff000000000000)) >> 40) |
((x & UINT64_C(0x0000ff0000000000)) >> 24) | ((x & UINT64_C(0x000000ff00000000)) >> 8) |
((x & UINT64_C(0x00000000ff000000)) << 8) | ((x & UINT64_C(0x0000000000ff0000)) << 24) |
((x & UINT64_C(0x000000000000ff00)) << 40) | ((x & UINT64_C(0x00000000000000ff)) << 56);
}
#endif
/* Linux / GLIBC */
#if defined(__linux__) || defined(__GLIBC__)
#include <endian.h>
/* endian.h only provides conversion functions if built with one these defines. Android is also
* known to provide these functions. */
#if defined(_DEFAULT_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(__ANDROID__)
#define HAVE_HOSTSWAP
#endif
#endif
/* Windows */
#if defined(_WIN16) || defined(_WIN32) || defined(_WIN64)
#if defined(__MINGW32__) || defined(__MINGW64__)
#include <sys/param.h>
#else
#define FAEST_IS_LITTLE_ENDIAN
#endif
#endif
/* Cygwin */
#if defined(__CYGWIN__)
#include <endian.h>
#define HAVE_HOSTSWAP
#endif
/* OS X */
#if defined(__APPLE__)
#include <machine/endian.h>
#endif
/* OpenBSD */
#if defined(__OpenBSD__)
#include <machine/endian.h>
#define HAVE_HOSTSWAP
#endif
/* other BSDs */
#if defined(__FreeBSD__) || defined(__NETBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
#define HAVE_HOSTSWAP
#endif
#if !defined(FAEST_IS_LITTLE_ENDIAN) && !defined(FAEST_IS_BIG_ENDIAN)
#if defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN)
#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
#define FAEST_IS_BIG_ENDIAN
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
#define FAEST_IS_LITTLE_ENDIAN
#endif
#elif defined(BIG_ENDIAN)
#define FAEST_IS_BIG_ENDIAN
#elif defined(LITTLE_ENDIAN)
#define FAEST_IS_LITTLE_ENDIAN
#endif
#endif
#if !defined(FAEST_IS_LITTLE_ENDIAN) && !defined(FAEST_IS_BIG_ENDIAN)
#if defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
#if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN
#define FAEST_IS_BIG_ENDIAN
#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN
#define FAEST_IS_LITTLE_ENDIAN
#endif
#elif defined(_BIG_ENDIAN)
#define FAEST_IS_BIG_ENDIAN
#elif defined(_LITTLE_ENDIAN)
#define FAEST_IS_LITTLE_ENDIAN
#endif
#endif
#if !defined(FAEST_IS_LITTLE_ENDIAN) && !defined(FAEST_IS_BIG_ENDIAN)
#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
#define FAEST_IS_BIG_ENDIAN
#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
#define FAEST_IS_LITTLE_ENDIAN
#endif
#elif defined(__BIG_ENDIAN)
#define FAEST_IS_BIG_ENDIAN
#elif defined(__LITTLE_ENDIAN)
#define FAEST_IS_LITTLE_ENDIAN
#endif
#endif
#if !defined(FAEST_IS_LITTLE_ENDIAN) && !defined(FAEST_IS_BIG_ENDIAN)
#if defined(__BIG_ENDIAN__) && defined(__LITTLE_ENDIAN__)
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __BIG_ENDIAN__
#define FAEST_IS_BIG_ENDIAN
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
#define FAEST_IS_LITTLE_ENDIAN
#endif
#elif defined(__BIG_ENDIAN__)
#define FAEST_IS_BIG_ENDIAN
#elif defined(__LITTLE_ENDIAN__)
#define FAEST_IS_LITTLE_ENDIAN
#endif
#endif
#if !defined(FAEST_IS_LITTLE_ENDIAN) && !defined(FAEST_IS_BIG_ENDIAN)
#if defined(__ORDER_BIG_ENDIAN__) && defined(__ORDER_LITTLE_ENDIAN__)
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define FAEST_IS_BIG_ENDIAN
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define FAEST_IS_LITTLE_ENDIAN
#endif
#endif
#endif
#if !defined(FAEST_IS_LITTLE_ENDIAN) && !defined(FAEST_IS_BIG_ENDIAN)
#error "Unknown platform!"
#endif
#if !defined(HAVE_HOSTSWAP)
#if defined(FAEST_IS_LITTLE_ENDIAN)
#define htobe16(x) bswap16((x))
#define htole16(x) ((uint16_t)(x))
#define be16toh(x) bswap16((x))
#define le16toh(x) ((uint16_t)(x))
#define htobe32(x) bswap32((x))
#define htole32(x) ((uint32_t)(x))
#define be32toh(x) bswap32((x))
#define le32toh(x) ((uint32_t)(x))
#define htobe64(x) bswap64((x))
#define htole64(x) ((uint64_t)(x))
#define be64toh(x) bswap64((x))
#define le64toh(x) ((uint64_t)(x))
#elif defined(FAEST_IS_BIG_ENDIAN)
#define htobe16(x) ((uint16_t)(x))
#define htole16(x) bswap16((x))
#define be16toh(x) ((uint16_t)(x))
#define le16toh(x) bswap16((x))
#define htobe32(x) ((uint32_t)(x))
#define htole32(x) bswap32((x))
#define be32toh(x) ((uint32_t)(x))
#define le32toh(x) bswap32((x))
#define htobe64(x) ((uint64_t)(x))
#define htole64(x) bswap64((x))
#define be64toh(x) ((uint64_t)(x))
#define le64toh(x) bswap64((x))
#endif
#endif
#endif