Branch data Line data Source code
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)) && \ 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 : : 159 : : inline static uint16_t load16(uint8_t *b) { 160 : : uint16_t x; 161 : : memcpy(&x, b, 2); 162 : : return x; 163 : : } 164 : : 165 : 0 : inline static uint32_t load32(uint8_t *b) { 166 : : uint32_t x; 167 : 0 : memcpy(&x, b, 4); 168 : 0 : return x; 169 : : } 170 : : 171 : 0 : inline static uint64_t load64(uint8_t *b) { 172 : : uint64_t x; 173 : 0 : memcpy(&x, b, 8); 174 : 0 : return x; 175 : : } 176 : : 177 : : inline static void store16(uint8_t *b, uint16_t i) { 178 : : memcpy(b, &i, 2); 179 : : } 180 : : 181 : 0 : inline static void store32(uint8_t *b, uint32_t i) { 182 : 0 : memcpy(b, &i, 4); 183 : 0 : } 184 : : 185 : 0 : inline static void store64(uint8_t *b, uint64_t i) { 186 : 0 : memcpy(b, &i, 8); 187 : 0 : } 188 : : 189 : : /* Legacy accessors so that this header can serve as an implementation of 190 : : * C.Endianness */ 191 : : #define load16_le(b) (le16toh(load16(b))) 192 : : #define store16_le(b, i) (store16(b, htole16(i))) 193 : : #define load16_be(b) (be16toh(load16(b))) 194 : : #define store16_be(b, i) (store16(b, htobe16(i))) 195 : : 196 : : #define load32_le(b) (le32toh(load32(b))) 197 : : #define store32_le(b, i) (store32(b, htole32(i))) 198 : : #define load32_be(b) (be32toh(load32(b))) 199 : : #define store32_be(b, i) (store32(b, htobe32(i))) 200 : : 201 : : #define load64_le(b) (le64toh(load64(b))) 202 : : #define store64_le(b, i) (store64(b, htole64(i))) 203 : : #define load64_be(b) (be64toh(load64(b))) 204 : : #define store64_be(b, i) (store64(b, htobe64(i))) 205 : : 206 : : /* Co-existence of LowStar.Endianness and FStar.Endianness generates name 207 : : * conflicts, because of course both insist on having no prefixes. Until a 208 : : * prefix is added, or until we truly retire FStar.Endianness, solve this issue 209 : : * in an elegant way. */ 210 : : #define load16_le0 load16_le 211 : : #define store16_le0 store16_le 212 : : #define load16_be0 load16_be 213 : : #define store16_be0 store16_be 214 : : 215 : : #define load32_le0 load32_le 216 : : #define store32_le0 store32_le 217 : : #define load32_be0 load32_be 218 : : #define store32_be0 store32_be 219 : : 220 : : #define load64_le0 load64_le 221 : : #define store64_le0 store64_le 222 : : #define load64_be0 load64_be 223 : : #define store64_be0 store64_be 224 : : 225 : : #define load128_le0 load128_le 226 : : #define store128_le0 store128_le 227 : : #define load128_be0 load128_be 228 : : #define store128_be0 store128_be 229 : : 230 : : #endif