lowstar_endianness.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
  2. Licensed under the Apache 2.0 License. */
  3. #ifndef __LOWSTAR_ENDIANNESS_H
  4. #define __LOWSTAR_ENDIANNESS_H
  5. #include <string.h>
  6. #include <inttypes.h>
  7. /******************************************************************************/
  8. /* Implementing C.fst (part 2: endian-ness macros) */
  9. /******************************************************************************/
  10. /* ... for Linux */
  11. #if defined(__linux__) || defined(__CYGWIN__) || defined (__USE_SYSTEM_ENDIAN_H__) || defined(__GLIBC__)
  12. # include <endian.h>
  13. /* ... for OSX */
  14. #elif defined(__APPLE__)
  15. # include <libkern/OSByteOrder.h>
  16. # define htole64(x) OSSwapHostToLittleInt64(x)
  17. # define le64toh(x) OSSwapLittleToHostInt64(x)
  18. # define htobe64(x) OSSwapHostToBigInt64(x)
  19. # define be64toh(x) OSSwapBigToHostInt64(x)
  20. # define htole16(x) OSSwapHostToLittleInt16(x)
  21. # define le16toh(x) OSSwapLittleToHostInt16(x)
  22. # define htobe16(x) OSSwapHostToBigInt16(x)
  23. # define be16toh(x) OSSwapBigToHostInt16(x)
  24. # define htole32(x) OSSwapHostToLittleInt32(x)
  25. # define le32toh(x) OSSwapLittleToHostInt32(x)
  26. # define htobe32(x) OSSwapHostToBigInt32(x)
  27. # define be32toh(x) OSSwapBigToHostInt32(x)
  28. /* ... for Solaris */
  29. #elif defined(__sun__)
  30. # error #include <sys/byteorder.h>
  31. # define htole64(x) LE_64(x)
  32. # define le64toh(x) LE_64(x)
  33. # define htobe64(x) BE_64(x)
  34. # define be64toh(x) BE_64(x)
  35. # define htole16(x) LE_16(x)
  36. # define le16toh(x) LE_16(x)
  37. # define htobe16(x) BE_16(x)
  38. # define be16toh(x) BE_16(x)
  39. # define htole32(x) LE_32(x)
  40. # define le32toh(x) LE_32(x)
  41. # define htobe32(x) BE_32(x)
  42. # define be32toh(x) BE_32(x)
  43. /* ... for the BSDs */
  44. #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
  45. # include <sys/endian.h>
  46. #elif defined(__OpenBSD__)
  47. # include <endian.h>
  48. /* ... for Windows (MSVC)... not targeting XBOX 360! */
  49. #elif defined(_MSC_VER)
  50. # include <stdlib.h>
  51. # define htobe16(x) _byteswap_ushort(x)
  52. # define htole16(x) (x)
  53. # define be16toh(x) _byteswap_ushort(x)
  54. # define le16toh(x) (x)
  55. # define htobe32(x) _byteswap_ulong(x)
  56. # define htole32(x) (x)
  57. # define be32toh(x) _byteswap_ulong(x)
  58. # define le32toh(x) (x)
  59. # define htobe64(x) _byteswap_uint64(x)
  60. # define htole64(x) (x)
  61. # define be64toh(x) _byteswap_uint64(x)
  62. # define le64toh(x) (x)
  63. /* ... for Windows (GCC-like, e.g. mingw or clang) */
  64. #elif (defined(_WIN32) || defined(_WIN64) || defined(__EMSCRIPTEN__)) && \
  65. (defined(__GNUC__) || defined(__clang__))
  66. # define htobe16(x) __builtin_bswap16(x)
  67. # define htole16(x) (x)
  68. # define be16toh(x) __builtin_bswap16(x)
  69. # define le16toh(x) (x)
  70. # define htobe32(x) __builtin_bswap32(x)
  71. # define htole32(x) (x)
  72. # define be32toh(x) __builtin_bswap32(x)
  73. # define le32toh(x) (x)
  74. # define htobe64(x) __builtin_bswap64(x)
  75. # define htole64(x) (x)
  76. # define be64toh(x) __builtin_bswap64(x)
  77. # define le64toh(x) (x)
  78. /* ... generic big-endian fallback code */
  79. /* ... AIX doesn't have __BYTE_ORDER__ (with XLC compiler) & is always big-endian */
  80. #elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || defined(_AIX)
  81. /* byte swapping code inspired by:
  82. * https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h
  83. * */
  84. # define htobe32(x) (x)
  85. # define be32toh(x) (x)
  86. # define htole32(x) \
  87. (__extension__({ \
  88. uint32_t _temp = (x); \
  89. ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \
  90. ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \
  91. }))
  92. # define le32toh(x) (htole32((x)))
  93. # define htobe64(x) (x)
  94. # define be64toh(x) (x)
  95. # define htole64(x) \
  96. (__extension__({ \
  97. uint64_t __temp = (x); \
  98. uint32_t __low = htobe32((uint32_t)__temp); \
  99. uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
  100. (((uint64_t)__low) << 32) | __high; \
  101. }))
  102. # define le64toh(x) (htole64((x)))
  103. /* ... generic little-endian fallback code */
  104. #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  105. # define htole32(x) (x)
  106. # define le32toh(x) (x)
  107. # define htobe32(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 be32toh(x) (htobe32((x)))
  114. # define htole64(x) (x)
  115. # define le64toh(x) (x)
  116. # define htobe64(x) \
  117. (__extension__({ \
  118. uint64_t __temp = (x); \
  119. uint32_t __low = htobe32((uint32_t)__temp); \
  120. uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
  121. (((uint64_t)__low) << 32) | __high; \
  122. }))
  123. # define be64toh(x) (htobe64((x)))
  124. /* ... couldn't determine endian-ness of the target platform */
  125. #else
  126. # error "Please define __BYTE_ORDER__!"
  127. #endif /* defined(__linux__) || ... */
  128. /* Loads and stores. These avoid undefined behavior due to unaligned memory
  129. * accesses, via memcpy. */
  130. inline static uint16_t load16(uint8_t *b) {
  131. uint16_t x;
  132. memcpy(&x, b, 2);
  133. return x;
  134. }
  135. inline static uint32_t load32(uint8_t *b) {
  136. uint32_t x;
  137. memcpy(&x, b, 4);
  138. return x;
  139. }
  140. inline static uint64_t load64(uint8_t *b) {
  141. uint64_t x;
  142. memcpy(&x, b, 8);
  143. return x;
  144. }
  145. inline static void store16(uint8_t *b, uint16_t i) {
  146. memcpy(b, &i, 2);
  147. }
  148. inline static void store32(uint8_t *b, uint32_t i) {
  149. memcpy(b, &i, 4);
  150. }
  151. inline static void store64(uint8_t *b, uint64_t i) {
  152. memcpy(b, &i, 8);
  153. }
  154. /* Legacy accessors so that this header can serve as an implementation of
  155. * C.Endianness */
  156. #define load16_le(b) (le16toh(load16(b)))
  157. #define store16_le(b, i) (store16(b, htole16(i)))
  158. #define load16_be(b) (be16toh(load16(b)))
  159. #define store16_be(b, i) (store16(b, htobe16(i)))
  160. #define load32_le(b) (le32toh(load32(b)))
  161. #define store32_le(b, i) (store32(b, htole32(i)))
  162. #define load32_be(b) (be32toh(load32(b)))
  163. #define store32_be(b, i) (store32(b, htobe32(i)))
  164. #define load64_le(b) (le64toh(load64(b)))
  165. #define store64_le(b, i) (store64(b, htole64(i)))
  166. #define load64_be(b) (be64toh(load64(b)))
  167. #define store64_be(b, i) (store64(b, htobe64(i)))
  168. /* Co-existence of LowStar.Endianness and FStar.Endianness generates name
  169. * conflicts, because of course both insist on having no prefixes. Until a
  170. * prefix is added, or until we truly retire FStar.Endianness, solve this issue
  171. * in an elegant way. */
  172. #define load16_le0 load16_le
  173. #define store16_le0 store16_le
  174. #define load16_be0 load16_be
  175. #define store16_be0 store16_be
  176. #define load32_le0 load32_le
  177. #define store32_le0 store32_le
  178. #define load32_be0 load32_be
  179. #define store32_be0 store32_be
  180. #define load64_le0 load64_le
  181. #define store64_le0 store64_le
  182. #define load64_be0 load64_be
  183. #define store64_be0 store64_be
  184. #define load128_le0 load128_le
  185. #define store128_le0 store128_le
  186. #define load128_be0 load128_be
  187. #define store128_be0 store128_be
  188. #endif