endian.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Copyright 2017 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //
  15. #ifndef ABSL_BASE_INTERNAL_ENDIAN_H_
  16. #define ABSL_BASE_INTERNAL_ENDIAN_H_
  17. #include <cstdint>
  18. #include <cstdlib>
  19. #include "absl/base/casts.h"
  20. #include "absl/base/config.h"
  21. #include "absl/base/internal/unaligned_access.h"
  22. #include "absl/base/nullability.h"
  23. #include "absl/base/port.h"
  24. namespace absl {
  25. ABSL_NAMESPACE_BEGIN
  26. inline uint64_t gbswap_64(uint64_t host_int) {
  27. #if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)
  28. return __builtin_bswap64(host_int);
  29. #elif defined(_MSC_VER)
  30. return _byteswap_uint64(host_int);
  31. #else
  32. return (((host_int & uint64_t{0xFF}) << 56) |
  33. ((host_int & uint64_t{0xFF00}) << 40) |
  34. ((host_int & uint64_t{0xFF0000}) << 24) |
  35. ((host_int & uint64_t{0xFF000000}) << 8) |
  36. ((host_int & uint64_t{0xFF00000000}) >> 8) |
  37. ((host_int & uint64_t{0xFF0000000000}) >> 24) |
  38. ((host_int & uint64_t{0xFF000000000000}) >> 40) |
  39. ((host_int & uint64_t{0xFF00000000000000}) >> 56));
  40. #endif
  41. }
  42. inline uint32_t gbswap_32(uint32_t host_int) {
  43. #if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)
  44. return __builtin_bswap32(host_int);
  45. #elif defined(_MSC_VER)
  46. return _byteswap_ulong(host_int);
  47. #else
  48. return (((host_int & uint32_t{0xFF}) << 24) |
  49. ((host_int & uint32_t{0xFF00}) << 8) |
  50. ((host_int & uint32_t{0xFF0000}) >> 8) |
  51. ((host_int & uint32_t{0xFF000000}) >> 24));
  52. #endif
  53. }
  54. inline uint16_t gbswap_16(uint16_t host_int) {
  55. #if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)
  56. return __builtin_bswap16(host_int);
  57. #elif defined(_MSC_VER)
  58. return _byteswap_ushort(host_int);
  59. #else
  60. return (((host_int & uint16_t{0xFF}) << 8) |
  61. ((host_int & uint16_t{0xFF00}) >> 8));
  62. #endif
  63. }
  64. #ifdef ABSL_IS_LITTLE_ENDIAN
  65. // Portable definitions for htonl (host-to-network) and friends on little-endian
  66. // architectures.
  67. inline uint16_t ghtons(uint16_t x) { return gbswap_16(x); }
  68. inline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); }
  69. inline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); }
  70. #elif defined ABSL_IS_BIG_ENDIAN
  71. // Portable definitions for htonl (host-to-network) etc on big-endian
  72. // architectures. These definitions are simpler since the host byte order is the
  73. // same as network byte order.
  74. inline uint16_t ghtons(uint16_t x) { return x; }
  75. inline uint32_t ghtonl(uint32_t x) { return x; }
  76. inline uint64_t ghtonll(uint64_t x) { return x; }
  77. #else
  78. #error \
  79. "Unsupported byte order: Either ABSL_IS_BIG_ENDIAN or " \
  80. "ABSL_IS_LITTLE_ENDIAN must be defined"
  81. #endif // byte order
  82. inline uint16_t gntohs(uint16_t x) { return ghtons(x); }
  83. inline uint32_t gntohl(uint32_t x) { return ghtonl(x); }
  84. inline uint64_t gntohll(uint64_t x) { return ghtonll(x); }
  85. // Utilities to convert numbers between the current hosts's native byte
  86. // order and little-endian byte order
  87. //
  88. // Load/Store methods are alignment safe
  89. namespace little_endian {
  90. // Conversion functions.
  91. #ifdef ABSL_IS_LITTLE_ENDIAN
  92. inline uint16_t FromHost16(uint16_t x) { return x; }
  93. inline uint16_t ToHost16(uint16_t x) { return x; }
  94. inline uint32_t FromHost32(uint32_t x) { return x; }
  95. inline uint32_t ToHost32(uint32_t x) { return x; }
  96. inline uint64_t FromHost64(uint64_t x) { return x; }
  97. inline uint64_t ToHost64(uint64_t x) { return x; }
  98. inline constexpr bool IsLittleEndian() { return true; }
  99. #elif defined ABSL_IS_BIG_ENDIAN
  100. inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }
  101. inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }
  102. inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }
  103. inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }
  104. inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }
  105. inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }
  106. inline constexpr bool IsLittleEndian() { return false; }
  107. #endif /* ENDIAN */
  108. inline uint8_t FromHost(uint8_t x) { return x; }
  109. inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
  110. inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
  111. inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
  112. inline uint8_t ToHost(uint8_t x) { return x; }
  113. inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
  114. inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
  115. inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
  116. inline int8_t FromHost(int8_t x) { return x; }
  117. inline int16_t FromHost(int16_t x) {
  118. return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
  119. }
  120. inline int32_t FromHost(int32_t x) {
  121. return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
  122. }
  123. inline int64_t FromHost(int64_t x) {
  124. return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
  125. }
  126. inline int8_t ToHost(int8_t x) { return x; }
  127. inline int16_t ToHost(int16_t x) {
  128. return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
  129. }
  130. inline int32_t ToHost(int32_t x) {
  131. return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
  132. }
  133. inline int64_t ToHost(int64_t x) {
  134. return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
  135. }
  136. // Functions to do unaligned loads and stores in little-endian order.
  137. inline uint16_t Load16(absl::Nonnull<const void *> p) {
  138. return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
  139. }
  140. inline void Store16(absl::Nonnull<void *> p, uint16_t v) {
  141. ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
  142. }
  143. inline uint32_t Load32(absl::Nonnull<const void *> p) {
  144. return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
  145. }
  146. inline void Store32(absl::Nonnull<void *> p, uint32_t v) {
  147. ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
  148. }
  149. inline uint64_t Load64(absl::Nonnull<const void *> p) {
  150. return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
  151. }
  152. inline void Store64(absl::Nonnull<void *> p, uint64_t v) {
  153. ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
  154. }
  155. } // namespace little_endian
  156. // Utilities to convert numbers between the current hosts's native byte
  157. // order and big-endian byte order (same as network byte order)
  158. //
  159. // Load/Store methods are alignment safe
  160. namespace big_endian {
  161. #ifdef ABSL_IS_LITTLE_ENDIAN
  162. inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }
  163. inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }
  164. inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }
  165. inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }
  166. inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }
  167. inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }
  168. inline constexpr bool IsLittleEndian() { return true; }
  169. #elif defined ABSL_IS_BIG_ENDIAN
  170. inline uint16_t FromHost16(uint16_t x) { return x; }
  171. inline uint16_t ToHost16(uint16_t x) { return x; }
  172. inline uint32_t FromHost32(uint32_t x) { return x; }
  173. inline uint32_t ToHost32(uint32_t x) { return x; }
  174. inline uint64_t FromHost64(uint64_t x) { return x; }
  175. inline uint64_t ToHost64(uint64_t x) { return x; }
  176. inline constexpr bool IsLittleEndian() { return false; }
  177. #endif /* ENDIAN */
  178. inline uint8_t FromHost(uint8_t x) { return x; }
  179. inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
  180. inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
  181. inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
  182. inline uint8_t ToHost(uint8_t x) { return x; }
  183. inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
  184. inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
  185. inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
  186. inline int8_t FromHost(int8_t x) { return x; }
  187. inline int16_t FromHost(int16_t x) {
  188. return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
  189. }
  190. inline int32_t FromHost(int32_t x) {
  191. return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
  192. }
  193. inline int64_t FromHost(int64_t x) {
  194. return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
  195. }
  196. inline int8_t ToHost(int8_t x) { return x; }
  197. inline int16_t ToHost(int16_t x) {
  198. return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
  199. }
  200. inline int32_t ToHost(int32_t x) {
  201. return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
  202. }
  203. inline int64_t ToHost(int64_t x) {
  204. return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
  205. }
  206. // Functions to do unaligned loads and stores in big-endian order.
  207. inline uint16_t Load16(absl::Nonnull<const void *> p) {
  208. return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
  209. }
  210. inline void Store16(absl::Nonnull<void *> p, uint16_t v) {
  211. ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
  212. }
  213. inline uint32_t Load32(absl::Nonnull<const void *> p) {
  214. return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
  215. }
  216. inline void Store32(absl::Nonnull<void *>p, uint32_t v) {
  217. ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
  218. }
  219. inline uint64_t Load64(absl::Nonnull<const void *> p) {
  220. return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
  221. }
  222. inline void Store64(absl::Nonnull<void *> p, uint64_t v) {
  223. ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
  224. }
  225. } // namespace big_endian
  226. ABSL_NAMESPACE_END
  227. } // namespace absl
  228. #endif // ABSL_BASE_INTERNAL_ENDIAN_H_