sys_byteorder.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // This header defines cross-platform ByteSwap() implementations for 16, 32 and
  5. // 64-bit values, and NetToHostXX() / HostToNextXX() functions equivalent to
  6. // the traditional ntohX() and htonX() functions.
  7. // Use the functions defined here rather than using the platform-specific
  8. // functions directly.
  9. #ifndef BASE_SYS_BYTEORDER_H_
  10. #define BASE_SYS_BYTEORDER_H_
  11. #include <stdint.h>
  12. #include "build/build_config.h"
  13. #if defined(COMPILER_MSVC)
  14. #include <stdlib.h>
  15. #endif
  16. #if defined(COMPILER_MSVC) && !defined(__clang__)
  17. // TODO(pkasting): See
  18. // https://developercommunity.visualstudio.com/t/Mark-some-built-in-functions-as-constexp/362558
  19. // https://developercommunity.visualstudio.com/t/constexpr-byte-swapping-optimization/983963
  20. #define BASE_BYTESWAPS_CONSTEXPR
  21. #else
  22. #define BASE_BYTESWAPS_CONSTEXPR constexpr
  23. #endif
  24. namespace base {
  25. // Returns a value with all bytes in |x| swapped, i.e. reverses the endianness.
  26. // TODO(pkasting): Once C++23 is available, replace with std::byteswap.
  27. inline BASE_BYTESWAPS_CONSTEXPR uint16_t ByteSwap(uint16_t x) {
  28. #if defined(COMPILER_MSVC) && !defined(__clang__)
  29. return _byteswap_ushort(x);
  30. #else
  31. return __builtin_bswap16(x);
  32. #endif
  33. }
  34. inline BASE_BYTESWAPS_CONSTEXPR uint32_t ByteSwap(uint32_t x) {
  35. #if defined(COMPILER_MSVC) && !defined(__clang__)
  36. return _byteswap_ulong(x);
  37. #else
  38. return __builtin_bswap32(x);
  39. #endif
  40. }
  41. inline BASE_BYTESWAPS_CONSTEXPR uint64_t ByteSwap(uint64_t x) {
  42. // Per build/build_config.h, clang masquerades as MSVC on Windows. If we are
  43. // actually using clang, we can rely on the builtin.
  44. //
  45. // This matters in practice, because on x86(_64), this is a single "bswap"
  46. // instruction. MSVC correctly replaces the call with an inlined bswap at /O2
  47. // as of 2021, but clang as we use it in Chromium doesn't, keeping a function
  48. // call for a single instruction.
  49. #if defined(COMPILER_MSVC) && !defined(__clang__)
  50. return _byteswap_uint64(x);
  51. #else
  52. return __builtin_bswap64(x);
  53. #endif
  54. }
  55. inline BASE_BYTESWAPS_CONSTEXPR uintptr_t ByteSwapUintPtrT(uintptr_t x) {
  56. // We do it this way because some build configurations are ILP32 even when
  57. // defined(ARCH_CPU_64_BITS). Unfortunately, we can't use sizeof in #ifs. But,
  58. // because these conditionals are constexprs, the irrelevant branches will
  59. // likely be optimized away, so this construction should not result in code
  60. // bloat.
  61. static_assert(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8,
  62. "Unsupported uintptr_t size");
  63. if (sizeof(uintptr_t) == 4)
  64. return ByteSwap(static_cast<uint32_t>(x));
  65. return ByteSwap(static_cast<uint64_t>(x));
  66. }
  67. // Converts the bytes in |x| from host order (endianness) to little endian, and
  68. // returns the result.
  69. inline BASE_BYTESWAPS_CONSTEXPR uint16_t ByteSwapToLE16(uint16_t x) {
  70. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  71. return x;
  72. #else
  73. return ByteSwap(x);
  74. #endif
  75. }
  76. inline BASE_BYTESWAPS_CONSTEXPR uint32_t ByteSwapToLE32(uint32_t x) {
  77. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  78. return x;
  79. #else
  80. return ByteSwap(x);
  81. #endif
  82. }
  83. inline BASE_BYTESWAPS_CONSTEXPR uint64_t ByteSwapToLE64(uint64_t x) {
  84. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  85. return x;
  86. #else
  87. return ByteSwap(x);
  88. #endif
  89. }
  90. // Converts the bytes in |x| from network to host order (endianness), and
  91. // returns the result.
  92. inline BASE_BYTESWAPS_CONSTEXPR uint16_t NetToHost16(uint16_t x) {
  93. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  94. return ByteSwap(x);
  95. #else
  96. return x;
  97. #endif
  98. }
  99. inline BASE_BYTESWAPS_CONSTEXPR uint32_t NetToHost32(uint32_t x) {
  100. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  101. return ByteSwap(x);
  102. #else
  103. return x;
  104. #endif
  105. }
  106. inline BASE_BYTESWAPS_CONSTEXPR uint64_t NetToHost64(uint64_t x) {
  107. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  108. return ByteSwap(x);
  109. #else
  110. return x;
  111. #endif
  112. }
  113. // Converts the bytes in |x| from host to network order (endianness), and
  114. // returns the result.
  115. inline BASE_BYTESWAPS_CONSTEXPR uint16_t HostToNet16(uint16_t x) {
  116. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  117. return ByteSwap(x);
  118. #else
  119. return x;
  120. #endif
  121. }
  122. inline BASE_BYTESWAPS_CONSTEXPR uint32_t HostToNet32(uint32_t x) {
  123. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  124. return ByteSwap(x);
  125. #else
  126. return x;
  127. #endif
  128. }
  129. inline BASE_BYTESWAPS_CONSTEXPR uint64_t HostToNet64(uint64_t x) {
  130. #if defined(ARCH_CPU_LITTLE_ENDIAN)
  131. return ByteSwap(x);
  132. #else
  133. return x;
  134. #endif
  135. }
  136. } // namespace base
  137. #undef BASE_BYTESWAPS_CONSTEXPR
  138. #endif // BASE_SYS_BYTEORDER_H_