CryEndian.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <BaseTypes.h>
  10. //////////////////////////////////////////////////////////////////////////
  11. // Endian support
  12. //////////////////////////////////////////////////////////////////////////
  13. /////////////////////////////////////////////////////////////////////////////////////
  14. // NEED_ENDIAN_SWAP is an older define still used in several places to toggle endian swapping.
  15. // It is only used when reading files which are assumed to be little-endian.
  16. // For legacy support, define it to swap on big endian platforms.
  17. /////////////////////////////////////////////////////////////////////////////////////
  18. typedef bool EEndian;
  19. #if defined(SYSTEM_IS_LITTLE_ENDIAN)
  20. # undef SYSTEM_IS_LITTLE_ENDIAN
  21. #endif
  22. #if defined(SYSTEM_IS_BIG_ENDIAN)
  23. # undef SYSTEM_IS_BIG_ENDIAN
  24. #endif
  25. #if 0 // no big-endian platforms right now, but keep the code
  26. // Big-endian platform
  27. # define SYSTEM_IS_LITTLE_ENDIAN 0
  28. # define SYSTEM_IS_BIG_ENDIAN 1
  29. #else
  30. // Little-endian platform
  31. # define SYSTEM_IS_LITTLE_ENDIAN 1
  32. # define SYSTEM_IS_BIG_ENDIAN 0
  33. #endif
  34. #if SYSTEM_IS_BIG_ENDIAN
  35. // Big-endian platform. Swap to/from little.
  36. #define eBigEndian false
  37. #define eLittleEndian true
  38. #define NEED_ENDIAN_SWAP
  39. #else
  40. // Little-endian platform. Swap to/from big.
  41. #define eLittleEndian false
  42. #define eBigEndian true
  43. #undef NEED_ENDIAN_SWAP
  44. #endif
  45. enum EEndianness
  46. {
  47. eEndianness_Little,
  48. eEndianness_Big,
  49. #if SYSTEM_IS_BIG_ENDIAN
  50. eEndianness_Native = eEndianness_Big,
  51. eEndianness_NonNative = eEndianness_Little,
  52. #else
  53. eEndianness_Native = eEndianness_Little,
  54. eEndianness_NonNative = eEndianness_Big,
  55. #endif
  56. };
  57. /////////////////////////////////////////////////////////////////////////////////////
  58. // SwapEndian function, using TypeInfo.
  59. struct CTypeInfo;
  60. void SwapEndian(const CTypeInfo& Info, size_t nSizeCheck, void* pData, size_t nCount = 1, bool bWriting = false);
  61. // Default template utilizes TypeInfo.
  62. template<class T>
  63. inline void SwapEndianBase(T* t, size_t nCount = 1, bool bWriting = false)
  64. {
  65. SwapEndian(TypeInfo(t), sizeof(T), t, nCount, bWriting);
  66. }
  67. /////////////////////////////////////////////////////////////////////////////////////
  68. // SwapEndianBase functions.
  69. // Always swap the data (the functions named SwapEndian swap based on an optional bSwapEndian parameter).
  70. // The bWriting parameter must be specified in general when the output is for writing,
  71. // but it matters only for types with bitfields.
  72. // Overrides for base types.
  73. template<>
  74. inline void SwapEndianBase(char* p, size_t nCount, bool bWriting)
  75. {
  76. (void)p;
  77. (void)nCount;
  78. (void)bWriting;
  79. }
  80. template<>
  81. inline void SwapEndianBase(uint8* p, size_t nCount, bool bWriting)
  82. {
  83. (void)p;
  84. (void)nCount;
  85. (void)bWriting;
  86. }
  87. template<>
  88. inline void SwapEndianBase(int8* p, size_t nCount, bool bWriting)
  89. {
  90. (void)p;
  91. (void)nCount;
  92. (void)bWriting;
  93. }
  94. template<>
  95. inline void SwapEndianBase(uint16* p, size_t nCount, bool bWriting)
  96. {
  97. (void)bWriting;
  98. for (; nCount-- > 0; p++)
  99. {
  100. *p = (uint16) (((*p >> 8) + (*p << 8)) & 0xFFFF);
  101. }
  102. }
  103. template<>
  104. inline void SwapEndianBase(int16* p, size_t nCount, bool bWriting)
  105. {
  106. (void)bWriting;
  107. SwapEndianBase((uint16*)p, nCount);
  108. }
  109. template<>
  110. inline void SwapEndianBase(uint32* p, size_t nCount, bool bWriting)
  111. {
  112. (void)bWriting;
  113. for (; nCount-- > 0; p++)
  114. {
  115. *p = (*p >> 24) + ((*p >> 8) & 0xFF00) + ((*p & 0xFF00) << 8) + (*p << 24);
  116. }
  117. }
  118. template<>
  119. inline void SwapEndianBase(int32* p, size_t nCount, bool bWriting)
  120. {
  121. (void)bWriting;
  122. SwapEndianBase((uint32*)p, nCount);
  123. }
  124. template<>
  125. inline void SwapEndianBase(float* p, size_t nCount, bool bWriting)
  126. {
  127. (void)bWriting;
  128. SwapEndianBase((uint32*)p, nCount);
  129. }
  130. template<>
  131. inline void SwapEndianBase(uint64* p, size_t nCount, bool bWriting)
  132. {
  133. (void)bWriting;
  134. for (; nCount-- > 0; p++)
  135. {
  136. *p = (*p >> 56) + ((*p >> 40) & 0xFF00) + ((*p >> 24) & 0xFF0000) + ((*p >> 8) & 0xFF000000)
  137. + ((*p & 0xFF000000) << 8) + ((*p & 0xFF0000) << 24) + ((*p & 0xFF00) << 40) + (*p << 56);
  138. }
  139. }
  140. template<>
  141. inline void SwapEndianBase(int64* p, size_t nCount, bool bWriting)
  142. {
  143. (void)bWriting;
  144. SwapEndianBase((uint64*)p, nCount);
  145. }
  146. template<>
  147. inline void SwapEndianBase(double* p, size_t nCount, bool bWriting)
  148. {
  149. (void)bWriting;
  150. SwapEndianBase((uint64*)p, nCount);
  151. }
  152. //---------------------------------------------------------------------------
  153. // SwapEndian functions.
  154. // bSwapEndian argument optional, and defaults to swapping from LittleEndian format.
  155. template<class T>
  156. inline void SwapEndian(T* t, size_t nCount, bool bSwapEndian = eLittleEndian)
  157. {
  158. if (bSwapEndian)
  159. {
  160. SwapEndianBase(t, nCount);
  161. }
  162. }
  163. // Specify int and uint as well as size_t, to resolve overload ambiguities.
  164. template<class T>
  165. inline void SwapEndian(T* t, int nCount, bool bSwapEndian = eLittleEndian)
  166. {
  167. if (bSwapEndian)
  168. {
  169. SwapEndianBase(t, nCount);
  170. }
  171. }
  172. #if defined(PLATFORM_64BIT)
  173. template<class T>
  174. inline void SwapEndian(T* t, unsigned int nCount, bool bSwapEndian = eLittleEndian)
  175. {
  176. if (bSwapEndian)
  177. {
  178. SwapEndianBase(t, nCount);
  179. }
  180. }
  181. #endif
  182. template<class T>
  183. inline void SwapEndian(T& t, bool bSwapEndian = eLittleEndian)
  184. {
  185. if (bSwapEndian)
  186. {
  187. SwapEndianBase(&t, 1);
  188. }
  189. }