1 /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
2 Licensed under the Apache 2.0 License. */
3
4 #ifndef __KREMLIN_ENDIAN_H
5 #define __KREMLIN_ENDIAN_H
6
7 #include <string.h>
8 #include <inttypes.h>
9
10 /******************************************************************************/
11 /* Implementing C.fst (part 2: endian-ness macros) */
12 /******************************************************************************/
13
14 /* ... for Linux */
15 #if defined(__linux__) || defined(__CYGWIN__)
16 # include <endian.h>
17
18 /* ... for OSX */
19 #elif defined(__APPLE__)
20 # include <libkern/OSByteOrder.h>
21 # define htole64(x) OSSwapHostToLittleInt64(x)
22 # define le64toh(x) OSSwapLittleToHostInt64(x)
23 # define htobe64(x) OSSwapHostToBigInt64(x)
24 # define be64toh(x) OSSwapBigToHostInt64(x)
25
26 # define htole16(x) OSSwapHostToLittleInt16(x)
27 # define le16toh(x) OSSwapLittleToHostInt16(x)
28 # define htobe16(x) OSSwapHostToBigInt16(x)
29 # define be16toh(x) OSSwapBigToHostInt16(x)
30
31 # define htole32(x) OSSwapHostToLittleInt32(x)
32 # define le32toh(x) OSSwapLittleToHostInt32(x)
33 # define htobe32(x) OSSwapHostToBigInt32(x)
34 # define be32toh(x) OSSwapBigToHostInt32(x)
35
36 /* ... for Solaris */
37 #elif defined(__sun__)
38 # include <sys/byteorder.h>
39 # define htole64(x) LE_64(x)
40 # define le64toh(x) LE_64(x)
41 # define htobe64(x) BE_64(x)
42 # define be64toh(x) BE_64(x)
43
44 # define htole16(x) LE_16(x)
45 # define le16toh(x) LE_16(x)
46 # define htobe16(x) BE_16(x)
47 # define be16toh(x) BE_16(x)
48
49 # define htole32(x) LE_32(x)
50 # define le32toh(x) LE_32(x)
51 # define htobe32(x) BE_32(x)
52 # define be32toh(x) BE_32(x)
53
54 /* ... for the BSDs */
55 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
56 # include <sys/endian.h>
57 #elif defined(__OpenBSD__)
58 # include <endian.h>
59
60 /* ... for Windows (MSVC)... not targeting XBOX 360! */
61 #elif defined(_MSC_VER)
62
63 # include <stdlib.h>
64 # define htobe16(x) _byteswap_ushort(x)
65 # define htole16(x) (x)
66 # define be16toh(x) _byteswap_ushort(x)
67 # define le16toh(x) (x)
68
69 # define htobe32(x) _byteswap_ulong(x)
70 # define htole32(x) (x)
71 # define be32toh(x) _byteswap_ulong(x)
72 # define le32toh(x) (x)
73
74 # define htobe64(x) _byteswap_uint64(x)
75 # define htole64(x) (x)
76 # define be64toh(x) _byteswap_uint64(x)
77 # define le64toh(x) (x)
78
79 /* ... for Windows (GCC-like, e.g. mingw or clang) */
80 #elif (defined(_WIN32) || defined(_WIN64)) && \
81 (defined(__GNUC__) || defined(__clang__))
82
83 # define htobe16(x) __builtin_bswap16(x)
84 # define htole16(x) (x)
85 # define be16toh(x) __builtin_bswap16(x)
86 # define le16toh(x) (x)
87
88 # define htobe32(x) __builtin_bswap32(x)
89 # define htole32(x) (x)
90 # define be32toh(x) __builtin_bswap32(x)
91 # define le32toh(x) (x)
92
93 # define htobe64(x) __builtin_bswap64(x)
94 # define htole64(x) (x)
95 # define be64toh(x) __builtin_bswap64(x)
96 # define le64toh(x) (x)
97
98 /* ... generic big-endian fallback code */
99 #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
100
101 /* byte swapping code inspired by:
102 * https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h
103 * */
104
105 # define htobe32(x) (x)
106 # define be32toh(x) (x)
107 # define htole32(x) \
108 (__extension__({ \
109 uint32_t _temp = (x); \
110 ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \
111 ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \
112 }))
113 # define le32toh(x) (htole32((x)))
114
115 # define htobe64(x) (x)
116 # define be64toh(x) (x)
117 # define htole64(x) \
118 (__extension__({ \
119 uint64_t __temp = (x); \
120 uint32_t __low = htobe32((uint32_t)__temp); \
121 uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
122 (((uint64_t)__low) << 32) | __high; \
123 }))
124 # define le64toh(x) (htole64((x)))
125
126 /* ... generic little-endian fallback code */
127 #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
128
129 # define htole32(x) (x)
130 # define le32toh(x) (x)
131 # define htobe32(x) \
132 (__extension__({ \
133 uint32_t _temp = (x); \
134 ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \
135 ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \
136 }))
137 # define be32toh(x) (htobe32((x)))
138
139 # define htole64(x) (x)
140 # define le64toh(x) (x)
141 # define htobe64(x) \
142 (__extension__({ \
143 uint64_t __temp = (x); \
144 uint32_t __low = htobe32((uint32_t)__temp); \
145 uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
146 (((uint64_t)__low) << 32) | __high; \
147 }))
148 # define be64toh(x) (htobe64((x)))
149
150 /* ... couldn't determine endian-ness of the target platform */
151 #else
152 # error "Please define __BYTE_ORDER__!"
153
154 #endif /* defined(__linux__) || ... */
155
156 /* Loads and stores. These avoid undefined behavior due to unaligned memory
157 * accesses, via memcpy. */
158
load16(uint8_t * b)159 inline static uint16_t load16(uint8_t *b) {
160 uint16_t x;
161 memcpy(&x, b, 2);
162 return x;
163 }
164
load32(uint8_t * b)165 inline static uint32_t load32(uint8_t *b) {
166 uint32_t x;
167 memcpy(&x, b, 4);
168 return x;
169 }
170
load64(uint8_t * b)171 inline static uint64_t load64(uint8_t *b) {
172 uint64_t x;
173 memcpy(&x, b, 8);
174 return x;
175 }
176
store16(uint8_t * b,uint16_t i)177 inline static void store16(uint8_t *b, uint16_t i) {
178 memcpy(b, &i, 2);
179 }
180
store32(uint8_t * b,uint32_t i)181 inline static void store32(uint8_t *b, uint32_t i) {
182 memcpy(b, &i, 4);
183 }
184
store64(uint8_t * b,uint64_t i)185 inline static void store64(uint8_t *b, uint64_t i) {
186 memcpy(b, &i, 8);
187 }
188
189 #define load16_le(b) (le16toh(load16(b)))
190 #define store16_le(b, i) (store16(b, htole16(i)))
191 #define load16_be(b) (be16toh(load16(b)))
192 #define store16_be(b, i) (store16(b, htobe16(i)))
193
194 #define load32_le(b) (le32toh(load32(b)))
195 #define store32_le(b, i) (store32(b, htole32(i)))
196 #define load32_be(b) (be32toh(load32(b)))
197 #define store32_be(b, i) (store32(b, htobe32(i)))
198
199 #define load64_le(b) (le64toh(load64(b)))
200 #define store64_le(b, i) (store64(b, htole64(i)))
201 #define load64_be(b) (be64toh(load64(b)))
202 #define store64_be(b, i) (store64(b, htobe64(i)))
203
204 #endif
205