/src/contrib/boost/spirit/home/support/detail/integer/endian.hpp

http://pythonocc.googlecode.com/ · C++ Header · 426 lines · 330 code · 56 blank · 40 comment · 21 complexity · f62f013424dbac334546abdf5660782d MD5 · raw file

  1. // Boost endian.hpp header file -------------------------------------------------------//
  2. // (C) Copyright Darin Adler 2000
  3. // (C) Copyright Beman Dawes 2006, 2009
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // See http://www.boost.org/LICENSE_1_0.txt
  6. // See library home page at http://www.boost.org/libs/endian
  7. //--------------------------------------------------------------------------------------//
  8. // Original design developed by Darin Adler based on classes developed by Mark
  9. // Borgerding. Four original class templates were combined into a single endian
  10. // class template by Beman Dawes, who also added the unrolled_byte_loops sign
  11. // partial specialization to correctly extend the sign when cover integer size
  12. // differs from endian representation size.
  13. // TODO: When a compiler supporting constexpr becomes available, try possible uses.
  14. #ifndef BOOST_SPIRIT_ENDIAN_HPP
  15. #define BOOST_SPIRIT_ENDIAN_HPP
  16. #if defined(_MSC_VER)
  17. #pragma once
  18. #endif
  19. #ifdef BOOST_ENDIAN_LOG
  20. # include <iostream>
  21. #endif
  22. #if defined(__BORLANDC__) || defined( __CODEGEARC__)
  23. # pragma pack(push, 1)
  24. #endif
  25. #include <boost/config.hpp>
  26. #include <boost/detail/endian.hpp>
  27. #define BOOST_MINIMAL_INTEGER_COVER_OPERATORS
  28. #define BOOST_NO_IO_COVER_OPERATORS
  29. #include <boost/spirit/home/support/detail/integer/cover_operators.hpp>
  30. #undef BOOST_NO_IO_COVER_OPERATORS
  31. #undef BOOST_MINIMAL_INTEGER_COVER_OPERATORS
  32. #include <boost/type_traits/is_signed.hpp>
  33. #include <boost/cstdint.hpp>
  34. #include <boost/static_assert.hpp>
  35. #include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
  36. #include <iosfwd>
  37. #include <climits>
  38. # if CHAR_BIT != 8
  39. # error Platforms with CHAR_BIT != 8 are not supported
  40. # endif
  41. # define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03
  42. # if defined(BOOST_ENDIAN_FORCE_PODNESS)
  43. # define BOOST_ENDIAN_NO_CTORS
  44. # endif
  45. namespace boost
  46. {
  47. namespace detail
  48. {
  49. // Unrolled loops for loading and storing streams of bytes.
  50. template <typename T, std::size_t n_bytes,
  51. bool sign=boost::is_signed<T>::value >
  52. struct unrolled_byte_loops
  53. {
  54. typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
  55. static T load_big(const unsigned char* bytes)
  56. { return *(bytes - 1) | (next::load_big(bytes - 1) << 8); }
  57. static T load_little(const unsigned char* bytes)
  58. { return *bytes | (next::load_little(bytes + 1) << 8); }
  59. static void store_big(char* bytes, T value)
  60. {
  61. *(bytes - 1) = static_cast<char>(value);
  62. next::store_big(bytes - 1, value >> 8);
  63. }
  64. static void store_little(char* bytes, T value)
  65. {
  66. *bytes = static_cast<char>(value);
  67. next::store_little(bytes + 1, value >> 8);
  68. }
  69. };
  70. template <typename T>
  71. struct unrolled_byte_loops<T, 1, false>
  72. {
  73. static T load_big(const unsigned char* bytes)
  74. { return *(bytes - 1); }
  75. static T load_little(const unsigned char* bytes)
  76. { return *bytes; }
  77. static void store_big(char* bytes, T value)
  78. { *(bytes - 1) = static_cast<char>(value); }
  79. static void store_little(char* bytes, T value)
  80. { *bytes = static_cast<char>(value); }
  81. };
  82. template <typename T>
  83. struct unrolled_byte_loops<T, 1, true>
  84. {
  85. static T load_big(const unsigned char* bytes)
  86. { return *reinterpret_cast<const signed char*>(bytes - 1); }
  87. static T load_little(const unsigned char* bytes)
  88. { return *reinterpret_cast<const signed char*>(bytes); }
  89. static void store_big(char* bytes, T value)
  90. { *(bytes - 1) = static_cast<char>(value); }
  91. static void store_little(char* bytes, T value)
  92. { *bytes = static_cast<char>(value); }
  93. };
  94. template <typename T, std::size_t n_bytes>
  95. inline
  96. T load_big_endian(const void* bytes)
  97. {
  98. return unrolled_byte_loops<T, n_bytes>::load_big
  99. (static_cast<const unsigned char*>(bytes) + n_bytes);
  100. }
  101. template <typename T, std::size_t n_bytes>
  102. inline
  103. T load_little_endian(const void* bytes)
  104. {
  105. return unrolled_byte_loops<T, n_bytes>::load_little
  106. (static_cast<const unsigned char*>(bytes));
  107. }
  108. template <typename T, std::size_t n_bytes>
  109. inline
  110. void store_big_endian(void* bytes, T value)
  111. {
  112. unrolled_byte_loops<T, n_bytes>::store_big
  113. (static_cast<char*>(bytes) + n_bytes, value);
  114. }
  115. template <typename T, std::size_t n_bytes>
  116. inline
  117. void store_little_endian(void* bytes, T value)
  118. {
  119. unrolled_byte_loops<T, n_bytes>::store_little
  120. (static_cast<char*>(bytes), value);
  121. }
  122. } // namespace detail
  123. namespace integer
  124. {
  125. # ifdef BOOST_ENDIAN_LOG
  126. bool endian_log(true);
  127. # endif
  128. // endian class template and specializations ---------------------------------------//
  129. BOOST_SCOPED_ENUM_START(endianness) { big, little, native }; BOOST_SCOPED_ENUM_END
  130. BOOST_SCOPED_ENUM_START(alignment) { unaligned, aligned }; BOOST_SCOPED_ENUM_END
  131. template <BOOST_SCOPED_ENUM(endianness) E, typename T, std::size_t n_bits,
  132. BOOST_SCOPED_ENUM(alignment) A = alignment::unaligned>
  133. class endian;
  134. // Specializations that represent unaligned bytes.
  135. // Taking an integer type as a parameter provides a nice way to pass both
  136. // the size and signedness of the desired integer and get the appropriate
  137. // corresponding integer type for the interface.
  138. // unaligned big endian specialization
  139. template <typename T, std::size_t n_bits>
  140. class endian< endianness::big, T, n_bits, alignment::unaligned >
  141. : cover_operators< endian< endianness::big, T, n_bits >, T >
  142. {
  143. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  144. public:
  145. typedef T value_type;
  146. # ifndef BOOST_ENDIAN_NO_CTORS
  147. endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
  148. explicit endian(T val)
  149. {
  150. # ifdef BOOST_ENDIAN_LOG
  151. if ( endian_log )
  152. std::clog << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
  153. # endif
  154. detail::store_big_endian<T, n_bits/8>(m_value, val);
  155. }
  156. # endif
  157. endian & operator=(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); return *this; }
  158. operator T() const
  159. {
  160. # ifdef BOOST_ENDIAN_LOG
  161. if ( endian_log )
  162. std::clog << "big, unaligned, " << n_bits << "-bits, convert(" << detail::load_big_endian<T, n_bits/8>(m_value) << ")\n";
  163. # endif
  164. return detail::load_big_endian<T, n_bits/8>(m_value);
  165. }
  166. private:
  167. char m_value[n_bits/8];
  168. };
  169. // unaligned little endian specialization
  170. template <typename T, std::size_t n_bits>
  171. class endian< endianness::little, T, n_bits, alignment::unaligned >
  172. : cover_operators< endian< endianness::little, T, n_bits >, T >
  173. {
  174. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  175. public:
  176. typedef T value_type;
  177. # ifndef BOOST_ENDIAN_NO_CTORS
  178. endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
  179. explicit endian(T val)
  180. {
  181. # ifdef BOOST_ENDIAN_LOG
  182. if ( endian_log )
  183. std::clog << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
  184. # endif
  185. detail::store_little_endian<T, n_bits/8>(m_value, val);
  186. }
  187. # endif
  188. endian & operator=(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
  189. operator T() const
  190. {
  191. # ifdef BOOST_ENDIAN_LOG
  192. if ( endian_log )
  193. std::clog << "little, unaligned, " << n_bits << "-bits, convert(" << detail::load_little_endian<T, n_bits/8>(m_value) << ")\n";
  194. # endif
  195. return detail::load_little_endian<T, n_bits/8>(m_value);
  196. }
  197. private:
  198. char m_value[n_bits/8];
  199. };
  200. // unaligned native endian specialization
  201. template <typename T, std::size_t n_bits>
  202. class endian< endianness::native, T, n_bits, alignment::unaligned >
  203. : cover_operators< endian< endianness::native, T, n_bits >, T >
  204. {
  205. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  206. public:
  207. typedef T value_type;
  208. # ifndef BOOST_ENDIAN_NO_CTORS
  209. endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
  210. # ifdef BOOST_BIG_ENDIAN
  211. explicit endian(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); }
  212. # else
  213. explicit endian(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); }
  214. # endif
  215. # endif
  216. # ifdef BOOST_BIG_ENDIAN
  217. endian & operator=(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); return *this; }
  218. operator T() const { return detail::load_big_endian<T, n_bits/8>(m_value); }
  219. # else
  220. endian & operator=(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
  221. operator T() const { return detail::load_little_endian<T, n_bits/8>(m_value); }
  222. # endif
  223. private:
  224. char m_value[n_bits/8];
  225. };
  226. // Specializations that mimic built-in integer types.
  227. // These typically have the same alignment as the underlying types.
  228. // aligned big endian specialization
  229. template <typename T, std::size_t n_bits>
  230. class endian< endianness::big, T, n_bits, alignment::aligned >
  231. : cover_operators< endian< endianness::big, T, n_bits, alignment::aligned >, T >
  232. {
  233. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  234. BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
  235. public:
  236. typedef T value_type;
  237. # ifndef BOOST_ENDIAN_NO_CTORS
  238. endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
  239. # ifdef BOOST_BIG_ENDIAN
  240. endian(T val) : m_value(val) { }
  241. # else
  242. explicit endian(T val) { detail::store_big_endian<T, sizeof(T)>(&m_value, val); }
  243. # endif
  244. # endif
  245. # ifdef BOOST_BIG_ENDIAN
  246. endian & operator=(T val) { m_value = val; return *this; }
  247. operator T() const { return m_value; }
  248. # else
  249. endian & operator=(T val) { detail::store_big_endian<T, sizeof(T)>(&m_value, val); return *this; }
  250. operator T() const { return detail::load_big_endian<T, sizeof(T)>(&m_value); }
  251. # endif
  252. private:
  253. T m_value;
  254. };
  255. // aligned little endian specialization
  256. template <typename T, std::size_t n_bits>
  257. class endian< endianness::little, T, n_bits, alignment::aligned >
  258. : cover_operators< endian< endianness::little, T, n_bits, alignment::aligned >, T >
  259. {
  260. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  261. BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
  262. public:
  263. typedef T value_type;
  264. # ifndef BOOST_ENDIAN_NO_CTORS
  265. endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
  266. # ifdef BOOST_LITTLE_ENDIAN
  267. endian(T val) : m_value(val) { }
  268. # else
  269. explicit endian(T val) { detail::store_little_endian<T, sizeof(T)>(&m_value, val); }
  270. # endif
  271. # endif
  272. # ifdef BOOST_LITTLE_ENDIAN
  273. endian & operator=(T val) { m_value = val; return *this; }
  274. operator T() const { return m_value; }
  275. #else
  276. endian & operator=(T val) { detail::store_little_endian<T, sizeof(T)>(&m_value, val); return *this; }
  277. operator T() const { return detail::load_little_endian<T, sizeof(T)>(&m_value); }
  278. #endif
  279. private:
  280. T m_value;
  281. };
  282. // naming convention typedefs ------------------------------------------------------//
  283. // unaligned big endian signed integer types
  284. typedef endian< endianness::big, int_least8_t, 8 > big8_t;
  285. typedef endian< endianness::big, int_least16_t, 16 > big16_t;
  286. typedef endian< endianness::big, int_least32_t, 24 > big24_t;
  287. typedef endian< endianness::big, int_least32_t, 32 > big32_t;
  288. typedef endian< endianness::big, int_least64_t, 40 > big40_t;
  289. typedef endian< endianness::big, int_least64_t, 48 > big48_t;
  290. typedef endian< endianness::big, int_least64_t, 56 > big56_t;
  291. typedef endian< endianness::big, int_least64_t, 64 > big64_t;
  292. // unaligned big endian unsigned integer types
  293. typedef endian< endianness::big, uint_least8_t, 8 > ubig8_t;
  294. typedef endian< endianness::big, uint_least16_t, 16 > ubig16_t;
  295. typedef endian< endianness::big, uint_least32_t, 24 > ubig24_t;
  296. typedef endian< endianness::big, uint_least32_t, 32 > ubig32_t;
  297. typedef endian< endianness::big, uint_least64_t, 40 > ubig40_t;
  298. typedef endian< endianness::big, uint_least64_t, 48 > ubig48_t;
  299. typedef endian< endianness::big, uint_least64_t, 56 > ubig56_t;
  300. typedef endian< endianness::big, uint_least64_t, 64 > ubig64_t;
  301. // unaligned little endian signed integer types
  302. typedef endian< endianness::little, int_least8_t, 8 > little8_t;
  303. typedef endian< endianness::little, int_least16_t, 16 > little16_t;
  304. typedef endian< endianness::little, int_least32_t, 24 > little24_t;
  305. typedef endian< endianness::little, int_least32_t, 32 > little32_t;
  306. typedef endian< endianness::little, int_least64_t, 40 > little40_t;
  307. typedef endian< endianness::little, int_least64_t, 48 > little48_t;
  308. typedef endian< endianness::little, int_least64_t, 56 > little56_t;
  309. typedef endian< endianness::little, int_least64_t, 64 > little64_t;
  310. // unaligned little endian unsigned integer types
  311. typedef endian< endianness::little, uint_least8_t, 8 > ulittle8_t;
  312. typedef endian< endianness::little, uint_least16_t, 16 > ulittle16_t;
  313. typedef endian< endianness::little, uint_least32_t, 24 > ulittle24_t;
  314. typedef endian< endianness::little, uint_least32_t, 32 > ulittle32_t;
  315. typedef endian< endianness::little, uint_least64_t, 40 > ulittle40_t;
  316. typedef endian< endianness::little, uint_least64_t, 48 > ulittle48_t;
  317. typedef endian< endianness::little, uint_least64_t, 56 > ulittle56_t;
  318. typedef endian< endianness::little, uint_least64_t, 64 > ulittle64_t;
  319. // unaligned native endian signed integer types
  320. typedef endian< endianness::native, int_least8_t, 8 > native8_t;
  321. typedef endian< endianness::native, int_least16_t, 16 > native16_t;
  322. typedef endian< endianness::native, int_least32_t, 24 > native24_t;
  323. typedef endian< endianness::native, int_least32_t, 32 > native32_t;
  324. typedef endian< endianness::native, int_least64_t, 40 > native40_t;
  325. typedef endian< endianness::native, int_least64_t, 48 > native48_t;
  326. typedef endian< endianness::native, int_least64_t, 56 > native56_t;
  327. typedef endian< endianness::native, int_least64_t, 64 > native64_t;
  328. // unaligned native endian unsigned integer types
  329. typedef endian< endianness::native, uint_least8_t, 8 > unative8_t;
  330. typedef endian< endianness::native, uint_least16_t, 16 > unative16_t;
  331. typedef endian< endianness::native, uint_least32_t, 24 > unative24_t;
  332. typedef endian< endianness::native, uint_least32_t, 32 > unative32_t;
  333. typedef endian< endianness::native, uint_least64_t, 40 > unative40_t;
  334. typedef endian< endianness::native, uint_least64_t, 48 > unative48_t;
  335. typedef endian< endianness::native, uint_least64_t, 56 > unative56_t;
  336. typedef endian< endianness::native, uint_least64_t, 64 > unative64_t;
  337. #define BOOST_HAS_INT16_T
  338. #define BOOST_HAS_INT32_T
  339. #define BOOST_HAS_INT64_T
  340. // These types only present if platform has exact size integers:
  341. // aligned big endian signed integer types
  342. // aligned big endian unsigned integer types
  343. // aligned little endian signed integer types
  344. // aligned little endian unsigned integer types
  345. // aligned native endian typedefs are not provided because
  346. // <cstdint> types are superior for this use case
  347. # if defined(BOOST_HAS_INT16_T)
  348. typedef endian< endianness::big, int16_t, 16, alignment::aligned > aligned_big16_t;
  349. typedef endian< endianness::big, uint16_t, 16, alignment::aligned > aligned_ubig16_t;
  350. typedef endian< endianness::little, int16_t, 16, alignment::aligned > aligned_little16_t;
  351. typedef endian< endianness::little, uint16_t, 16, alignment::aligned > aligned_ulittle16_t;
  352. # endif
  353. # if defined(BOOST_HAS_INT32_T)
  354. typedef endian< endianness::big, int32_t, 32, alignment::aligned > aligned_big32_t;
  355. typedef endian< endianness::big, uint32_t, 32, alignment::aligned > aligned_ubig32_t;
  356. typedef endian< endianness::little, int32_t, 32, alignment::aligned > aligned_little32_t;
  357. typedef endian< endianness::little, uint32_t, 32, alignment::aligned > aligned_ulittle32_t;
  358. # endif
  359. # if defined(BOOST_HAS_INT64_T)
  360. typedef endian< endianness::big, int64_t, 64, alignment::aligned > aligned_big64_t;
  361. typedef endian< endianness::big, uint64_t, 64, alignment::aligned > aligned_ubig64_t;
  362. typedef endian< endianness::little, int64_t, 64, alignment::aligned > aligned_little64_t;
  363. typedef endian< endianness::little, uint64_t, 64, alignment::aligned > aligned_ulittle64_t;
  364. # endif
  365. } // namespace integer
  366. } // namespace boost
  367. #if defined(__BORLANDC__) || defined( __CODEGEARC__)
  368. # pragma pack(pop)
  369. #endif
  370. #endif // BOOST_SPIRIT_ENDIAN_HPP