• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
2    Licensed under the Apache 2.0 License. */
3 
4 #ifndef __LOWSTAR_ENDIANNESS_H
5 #define __LOWSTAR_ENDIANNESS_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__) || defined (__USE_SYSTEM_ENDIAN_H__) || defined(__GLIBC__)
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) || defined(__EMSCRIPTEN__)) &&       \
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 /* ... AIX doesn't have __BYTE_ORDER__ (with XLC compiler) & is always big-endian */
100 #elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || defined(_AIX)
101 
102 /* byte swapping code inspired by:
103  * https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h
104  * */
105 
106 #  define htobe32(x) (x)
107 #  define be32toh(x) (x)
108 #  define htole32(x)                                                           \
109     (__extension__({                                                           \
110       uint32_t _temp = (x);                                                    \
111       ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) |             \
112           ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000);          \
113     }))
114 #  define le32toh(x) (htole32((x)))
115 
116 #  define htobe64(x) (x)
117 #  define be64toh(x) (x)
118 #  define htole64(x)                                                           \
119     (__extension__({                                                           \
120       uint64_t __temp = (x);                                                   \
121       uint32_t __low = htobe32((uint32_t)__temp);                              \
122       uint32_t __high = htobe32((uint32_t)(__temp >> 32));                     \
123       (((uint64_t)__low) << 32) | __high;                                      \
124     }))
125 #  define le64toh(x) (htole64((x)))
126 
127 /* ... generic little-endian fallback code */
128 #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
129 
130 #  define htole32(x) (x)
131 #  define le32toh(x) (x)
132 #  define htobe32(x)                                                           \
133     (__extension__({                                                           \
134       uint32_t _temp = (x);                                                    \
135       ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) |             \
136           ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000);          \
137     }))
138 #  define be32toh(x) (htobe32((x)))
139 
140 #  define htole64(x) (x)
141 #  define le64toh(x) (x)
142 #  define htobe64(x)                                                           \
143     (__extension__({                                                           \
144       uint64_t __temp = (x);                                                   \
145       uint32_t __low = htobe32((uint32_t)__temp);                              \
146       uint32_t __high = htobe32((uint32_t)(__temp >> 32));                     \
147       (((uint64_t)__low) << 32) | __high;                                      \
148     }))
149 #  define be64toh(x) (htobe64((x)))
150 
151 /* ... couldn't determine endian-ness of the target platform */
152 #else
153 #  error "Please define __BYTE_ORDER__!"
154 
155 #endif /* defined(__linux__) || ... */
156 
157 /* Loads and stores. These avoid undefined behavior due to unaligned memory
158  * accesses, via memcpy. */
159 
load16(uint8_t * b)160 inline static uint16_t load16(uint8_t *b) {
161   uint16_t x;
162   memcpy(&x, b, 2);
163   return x;
164 }
165 
load32(uint8_t * b)166 inline static uint32_t load32(uint8_t *b) {
167   uint32_t x;
168   memcpy(&x, b, 4);
169   return x;
170 }
171 
load64(uint8_t * b)172 inline static uint64_t load64(uint8_t *b) {
173   uint64_t x;
174   memcpy(&x, b, 8);
175   return x;
176 }
177 
store16(uint8_t * b,uint16_t i)178 inline static void store16(uint8_t *b, uint16_t i) {
179   memcpy(b, &i, 2);
180 }
181 
store32(uint8_t * b,uint32_t i)182 inline static void store32(uint8_t *b, uint32_t i) {
183   memcpy(b, &i, 4);
184 }
185 
store64(uint8_t * b,uint64_t i)186 inline static void store64(uint8_t *b, uint64_t i) {
187   memcpy(b, &i, 8);
188 }
189 
190 /* Legacy accessors so that this header can serve as an implementation of
191  * C.Endianness */
192 #define load16_le(b) (le16toh(load16(b)))
193 #define store16_le(b, i) (store16(b, htole16(i)))
194 #define load16_be(b) (be16toh(load16(b)))
195 #define store16_be(b, i) (store16(b, htobe16(i)))
196 
197 #define load32_le(b) (le32toh(load32(b)))
198 #define store32_le(b, i) (store32(b, htole32(i)))
199 #define load32_be(b) (be32toh(load32(b)))
200 #define store32_be(b, i) (store32(b, htobe32(i)))
201 
202 #define load64_le(b) (le64toh(load64(b)))
203 #define store64_le(b, i) (store64(b, htole64(i)))
204 #define load64_be(b) (be64toh(load64(b)))
205 #define store64_be(b, i) (store64(b, htobe64(i)))
206 
207 /* Co-existence of LowStar.Endianness and FStar.Endianness generates name
208  * conflicts, because of course both insist on having no prefixes. Until a
209  * prefix is added, or until we truly retire FStar.Endianness, solve this issue
210  * in an elegant way. */
211 #define load16_le0 load16_le
212 #define store16_le0 store16_le
213 #define load16_be0 load16_be
214 #define store16_be0 store16_be
215 
216 #define load32_le0 load32_le
217 #define store32_le0 store32_le
218 #define load32_be0 load32_be
219 #define store32_be0 store32_be
220 
221 #define load64_le0 load64_le
222 #define store64_le0 store64_le
223 #define load64_be0 load64_be
224 #define store64_be0 store64_be
225 
226 #define load128_le0 load128_le
227 #define store128_le0 store128_le
228 #define load128_be0 load128_be
229 #define store128_be0 store128_be
230 
231 #endif
232