endian.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Byte order-related utilities
  2. //
  3. // Platform: ISO C++ 98/11
  4. // $Id$
  5. //
  6. // (c) __vic 2016
  7. #ifndef __VIC_ENDIAN_H
  8. #define __VIC_ENDIAN_H
  9. #include<__vic/defs.h>
  10. #include<__vic/stdint.h>
  11. namespace __vic {
  12. //----------------------------------------------------------------------------
  13. __VIC_NODISCARD __VIC_CONSTEXPR_FUNC uint16_t swab16(uint16_t v)
  14. {
  15. #if defined(__GNUC__) && !defined(__VIC_NO_BUILTINS) && \
  16. (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)
  17. return __builtin_bswap16(v);
  18. #else
  19. return (v << 8) | (v >> 8);
  20. #endif
  21. }
  22. //----------------------------------------------------------------------------
  23. __VIC_NODISCARD __VIC_CONSTEXPR_FUNC uint32_t swab32(uint32_t v)
  24. {
  25. #if defined(__GNUC__) && !defined(__VIC_NO_BUILTINS)
  26. return __builtin_bswap32(v);
  27. #else
  28. return (v >> 24) | ((v & uint32_t(0x00FF0000)) >> 8) |
  29. ((v & uint32_t(0x0000FF00)) << 8) | (v << 24);
  30. #endif
  31. }
  32. //----------------------------------------------------------------------------
  33. __VIC_NODISCARD __VIC_CONSTEXPR_FUNC uint64_t swab64(uint64_t v)
  34. {
  35. #if defined(__GNUC__) && !defined(__VIC_NO_BUILTINS)
  36. return __builtin_bswap64(v);
  37. #else
  38. return (v >> 56) |
  39. ((v >> 40) & (uint64_t(0xFF) << 8)) |
  40. ((v >> 24) & (uint64_t(0xFF) << 16)) |
  41. ((v >> 8 ) & (uint64_t(0xFF) << 24)) |
  42. ((v << 8 ) & (uint64_t(0xFF) << 32)) |
  43. ((v << 24) & (uint64_t(0xFF) << 40)) |
  44. ((v << 40) & (uint64_t(0xFF) << 48)) |
  45. (v << 56);
  46. #endif
  47. }
  48. //----------------------------------------------------------------------------
  49. //----------------------------------------------------------------------------
  50. template<class T, size_t = sizeof(T)>
  51. struct bytes_inverter; // not defined
  52. //----------------------------------------------------------------------------
  53. template<class T>
  54. struct bytes_inverter<T,1>
  55. {
  56. static __VIC_CONSTEXPR_FUNC T value(T v)
  57. {
  58. return v;
  59. }
  60. };
  61. //----------------------------------------------------------------------------
  62. template<class T>
  63. struct bytes_inverter<T,2>
  64. {
  65. static __VIC_CONSTEXPR_FUNC T value(T v)
  66. {
  67. return static_cast<T>(swab16(static_cast<uint16_t>(v)));
  68. }
  69. };
  70. //----------------------------------------------------------------------------
  71. template<class T>
  72. struct bytes_inverter<T,4>
  73. {
  74. static __VIC_CONSTEXPR_FUNC T value(T v)
  75. {
  76. return static_cast<T>(swab32(static_cast<uint32_t>(v)));
  77. }
  78. };
  79. //----------------------------------------------------------------------------
  80. template<class T>
  81. struct bytes_inverter<T,8>
  82. {
  83. static __VIC_CONSTEXPR_FUNC T value(T v)
  84. {
  85. return static_cast<T>(swab64(static_cast<uint64_t>(v)));
  86. }
  87. };
  88. //----------------------------------------------------------------------------
  89. namespace endian {
  90. //////////////////////////////////////////////////////////////////////////////
  91. enum endianness
  92. {
  93. unknown = 0,
  94. little = 1234,
  95. big = 4321,
  96. pdp = 3412,
  97. native =
  98. #ifdef __BYTE_ORDER__
  99. #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  100. little
  101. #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  102. big
  103. //#elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
  104. // there are no such platforms anymore
  105. #endif // __BYTE_ORDER__
  106. #elif defined(_WIN32)
  107. little
  108. #else
  109. unknown
  110. #endif
  111. };
  112. //////////////////////////////////////////////////////////////////////////////
  113. //----------------------------------------------------------------------------
  114. template<endianness From, endianness To>
  115. struct transformer; // not defined
  116. //----------------------------------------------------------------------------
  117. template<endianness E>
  118. struct transformer<E,E> // same endianness
  119. {
  120. template<class T> static __VIC_CONSTEXPR_FUNC T value(T v)
  121. {
  122. return v;
  123. }
  124. };
  125. //----------------------------------------------------------------------------
  126. template<>
  127. struct transformer<little,big>
  128. {
  129. template<class T> static __VIC_CONSTEXPR_FUNC T value(T v)
  130. {
  131. return bytes_inverter<T>::value(v);
  132. }
  133. };
  134. //----------------------------------------------------------------------------
  135. template<>
  136. struct transformer<big,little>
  137. {
  138. template<class T> static __VIC_CONSTEXPR_FUNC T value(T v)
  139. {
  140. return bytes_inverter<T>::value(v);
  141. }
  142. };
  143. //----------------------------------------------------------------------------
  144. //----------------------------------------------------------------------------
  145. template<class T>
  146. __VIC_NODISCARD __VIC_CONSTEXPR_FUNC T from_big(T v)
  147. {
  148. return transformer<big,native>::value(v);
  149. }
  150. //----------------------------------------------------------------------------
  151. template<class T>
  152. __VIC_NODISCARD __VIC_CONSTEXPR_FUNC T from_little(T v)
  153. {
  154. return transformer<little,native>::value(v);
  155. }
  156. //----------------------------------------------------------------------------
  157. template<class T>
  158. __VIC_NODISCARD __VIC_CONSTEXPR_FUNC T to_big(T v)
  159. {
  160. return transformer<native,big>::value(v);
  161. }
  162. //----------------------------------------------------------------------------
  163. template<class T>
  164. __VIC_NODISCARD __VIC_CONSTEXPR_FUNC T to_little(T v)
  165. {
  166. return transformer<native,little>::value(v);
  167. }
  168. //----------------------------------------------------------------------------
  169. } // namespace
  170. using endian::endianness;
  171. } // namespace
  172. #endif // header guard