2
0

Endian.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. //===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file declares generic functions to read and write endian specific data.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_SUPPORT_ENDIAN_H
  14. #define LLVM_SUPPORT_ENDIAN_H
  15. #include "llvm/Support/AlignOf.h"
  16. #include "llvm/Support/Host.h"
  17. #include "llvm/Support/SwapByteOrder.h"
  18. #pragma warning( push ) // HLSL Change - constant comparisons are done for portability
  19. #pragma warning( disable : 6326 ) // 'Potential comparison of a constant with another constant.'
  20. namespace llvm {
  21. namespace support {
  22. enum endianness {big, little, native};
  23. // These are named values for common alignments.
  24. enum {aligned = 0, unaligned = 1};
  25. namespace detail {
  26. /// \brief ::value is either alignment, or alignof(T) if alignment is 0.
  27. template<class T, int alignment>
  28. struct PickAlignment {
  29. enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment};
  30. };
  31. } // end namespace detail
  32. namespace endian {
  33. /// Swap the bytes of value to match the given endianness.
  34. template<typename value_type, endianness endian>
  35. inline value_type byte_swap(value_type value) {
  36. if (endian != native && sys::IsBigEndianHost != (endian == big))
  37. sys::swapByteOrder(value);
  38. return value;
  39. }
  40. /// Read a value of a particular endianness from memory.
  41. template<typename value_type,
  42. endianness endian,
  43. std::size_t alignment>
  44. inline value_type read(const void *memory) {
  45. value_type ret;
  46. memcpy(&ret,
  47. LLVM_ASSUME_ALIGNED(memory,
  48. (detail::PickAlignment<value_type, alignment>::value)),
  49. sizeof(value_type));
  50. return byte_swap<value_type, endian>(ret);
  51. }
  52. /// Read a value of a particular endianness from a buffer, and increment the
  53. /// buffer past that value.
  54. template<typename value_type, endianness endian, std::size_t alignment,
  55. typename CharT>
  56. inline value_type readNext(const CharT *&memory) {
  57. value_type ret = read<value_type, endian, alignment>(memory);
  58. memory += sizeof(value_type);
  59. return ret;
  60. }
  61. /// Write a value to memory with a particular endianness.
  62. template<typename value_type,
  63. endianness endian,
  64. std::size_t alignment>
  65. inline void write(void *memory, value_type value) {
  66. value = byte_swap<value_type, endian>(value);
  67. memcpy(LLVM_ASSUME_ALIGNED(memory,
  68. (detail::PickAlignment<value_type, alignment>::value)),
  69. &value,
  70. sizeof(value_type));
  71. }
  72. } // end namespace endian
  73. namespace detail {
  74. template<typename value_type,
  75. endianness endian,
  76. std::size_t alignment>
  77. struct packed_endian_specific_integral {
  78. operator value_type() const {
  79. return endian::read<value_type, endian, alignment>(
  80. (const void*)Value.buffer);
  81. }
  82. void operator=(value_type newValue) {
  83. endian::write<value_type, endian, alignment>(
  84. (void*)Value.buffer, newValue);
  85. }
  86. packed_endian_specific_integral &operator+=(value_type newValue) {
  87. *this = *this + newValue;
  88. return *this;
  89. }
  90. packed_endian_specific_integral &operator-=(value_type newValue) {
  91. *this = *this - newValue;
  92. return *this;
  93. }
  94. packed_endian_specific_integral &operator|=(value_type newValue) {
  95. *this = *this | newValue;
  96. return *this;
  97. }
  98. packed_endian_specific_integral &operator&=(value_type newValue) {
  99. *this = *this & newValue;
  100. return *this;
  101. }
  102. private:
  103. AlignedCharArray<PickAlignment<value_type, alignment>::value,
  104. sizeof(value_type)> Value;
  105. public:
  106. struct ref {
  107. explicit ref(void *Ptr) : Ptr(Ptr) {}
  108. operator value_type() const {
  109. return endian::read<value_type, endian, alignment>(Ptr);
  110. }
  111. void operator=(value_type NewValue) {
  112. endian::write<value_type, endian, alignment>(Ptr, NewValue);
  113. }
  114. private:
  115. void *Ptr;
  116. };
  117. };
  118. } // end namespace detail
  119. typedef detail::packed_endian_specific_integral
  120. <uint16_t, little, unaligned> ulittle16_t;
  121. typedef detail::packed_endian_specific_integral
  122. <uint32_t, little, unaligned> ulittle32_t;
  123. typedef detail::packed_endian_specific_integral
  124. <uint64_t, little, unaligned> ulittle64_t;
  125. typedef detail::packed_endian_specific_integral
  126. <int16_t, little, unaligned> little16_t;
  127. typedef detail::packed_endian_specific_integral
  128. <int32_t, little, unaligned> little32_t;
  129. typedef detail::packed_endian_specific_integral
  130. <int64_t, little, unaligned> little64_t;
  131. typedef detail::packed_endian_specific_integral
  132. <uint16_t, little, aligned> aligned_ulittle16_t;
  133. typedef detail::packed_endian_specific_integral
  134. <uint32_t, little, aligned> aligned_ulittle32_t;
  135. typedef detail::packed_endian_specific_integral
  136. <uint64_t, little, aligned> aligned_ulittle64_t;
  137. typedef detail::packed_endian_specific_integral
  138. <int16_t, little, aligned> aligned_little16_t;
  139. typedef detail::packed_endian_specific_integral
  140. <int32_t, little, aligned> aligned_little32_t;
  141. typedef detail::packed_endian_specific_integral
  142. <int64_t, little, aligned> aligned_little64_t;
  143. typedef detail::packed_endian_specific_integral
  144. <uint16_t, big, unaligned> ubig16_t;
  145. typedef detail::packed_endian_specific_integral
  146. <uint32_t, big, unaligned> ubig32_t;
  147. typedef detail::packed_endian_specific_integral
  148. <uint64_t, big, unaligned> ubig64_t;
  149. typedef detail::packed_endian_specific_integral
  150. <int16_t, big, unaligned> big16_t;
  151. typedef detail::packed_endian_specific_integral
  152. <int32_t, big, unaligned> big32_t;
  153. typedef detail::packed_endian_specific_integral
  154. <int64_t, big, unaligned> big64_t;
  155. typedef detail::packed_endian_specific_integral
  156. <uint16_t, big, aligned> aligned_ubig16_t;
  157. typedef detail::packed_endian_specific_integral
  158. <uint32_t, big, aligned> aligned_ubig32_t;
  159. typedef detail::packed_endian_specific_integral
  160. <uint64_t, big, aligned> aligned_ubig64_t;
  161. typedef detail::packed_endian_specific_integral
  162. <int16_t, big, aligned> aligned_big16_t;
  163. typedef detail::packed_endian_specific_integral
  164. <int32_t, big, aligned> aligned_big32_t;
  165. typedef detail::packed_endian_specific_integral
  166. <int64_t, big, aligned> aligned_big64_t;
  167. typedef detail::packed_endian_specific_integral
  168. <uint16_t, native, unaligned> unaligned_uint16_t;
  169. typedef detail::packed_endian_specific_integral
  170. <uint32_t, native, unaligned> unaligned_uint32_t;
  171. typedef detail::packed_endian_specific_integral
  172. <uint64_t, native, unaligned> unaligned_uint64_t;
  173. typedef detail::packed_endian_specific_integral
  174. <int16_t, native, unaligned> unaligned_int16_t;
  175. typedef detail::packed_endian_specific_integral
  176. <int32_t, native, unaligned> unaligned_int32_t;
  177. typedef detail::packed_endian_specific_integral
  178. <int64_t, native, unaligned> unaligned_int64_t;
  179. namespace endian {
  180. inline uint16_t read16le(const void *p) { return *(const ulittle16_t *)p; }
  181. inline uint32_t read32le(const void *p) { return *(const ulittle32_t *)p; }
  182. inline uint64_t read64le(const void *p) { return *(const ulittle64_t *)p; }
  183. inline uint16_t read16be(const void *p) { return *(const ubig16_t *)p; }
  184. inline uint32_t read32be(const void *p) { return *(const ubig32_t *)p; }
  185. inline uint64_t read64be(const void *p) { return *(const ubig64_t *)p; }
  186. inline void write16le(void *p, uint16_t v) { *(ulittle16_t *)p = v; }
  187. inline void write32le(void *p, uint32_t v) { *(ulittle32_t *)p = v; }
  188. inline void write64le(void *p, uint64_t v) { *(ulittle64_t *)p = v; }
  189. inline void write16be(void *p, uint16_t v) { *(ubig16_t *)p = v; }
  190. inline void write32be(void *p, uint32_t v) { *(ubig32_t *)p = v; }
  191. inline void write64be(void *p, uint64_t v) { *(ubig64_t *)p = v; }
  192. } // end namespace endian
  193. } // end namespace support
  194. } // end namespace llvm
  195. #pragma warning( pop ) // HLSL Change - pop warning level
  196. #endif