endian_store.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. #ifndef BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
  2. #define BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED
  3. // Copyright 2019 Peter Dimov
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. #include <boost/endian/detail/endian_reverse.hpp>
  8. #include <boost/endian/detail/order.hpp>
  9. #include <boost/endian/detail/integral_by_size.hpp>
  10. #include <boost/endian/detail/is_trivially_copyable.hpp>
  11. #include <boost/type_traits/is_integral.hpp>
  12. #include <boost/type_traits/is_enum.hpp>
  13. #include <boost/static_assert.hpp>
  14. #include <cstddef>
  15. #include <cstring>
  16. namespace boost
  17. {
  18. namespace endian
  19. {
  20. namespace detail
  21. {
  22. template<class T, std::size_t N1, BOOST_SCOPED_ENUM(order) O1, std::size_t N2, BOOST_SCOPED_ENUM(order) O2> struct endian_store_impl
  23. {
  24. };
  25. } // namespace detail
  26. // Requires:
  27. //
  28. // sizeof(T) must be 1, 2, 4, or 8
  29. // 1 <= N <= sizeof(T)
  30. // T is TriviallyCopyable
  31. // if N < sizeof(T), T is integral or enum
  32. template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) Order>
  33. inline void endian_store( unsigned char * p, T const & v ) BOOST_NOEXCEPT
  34. {
  35. BOOST_STATIC_ASSERT( sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8 );
  36. BOOST_STATIC_ASSERT( N >= 1 && N <= sizeof(T) );
  37. return detail::endian_store_impl<T, sizeof(T), order::native, N, Order>()( p, v );
  38. }
  39. namespace detail
  40. {
  41. // same endianness, same size
  42. template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O> struct endian_store_impl<T, N, O, N, O>
  43. {
  44. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  45. {
  46. BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
  47. std::memcpy( p, &v, N );
  48. }
  49. };
  50. // same size, reverse endianness
  51. template<class T, std::size_t N, BOOST_SCOPED_ENUM(order) O1, BOOST_SCOPED_ENUM(order) O2> struct endian_store_impl<T, N, O1, N, O2>
  52. {
  53. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  54. {
  55. BOOST_STATIC_ASSERT( is_trivially_copyable<T>::value );
  56. typename integral_by_size<N>::type tmp;
  57. std::memcpy( &tmp, &v, N );
  58. endian_reverse_inplace( tmp );
  59. std::memcpy( p, &tmp, N );
  60. }
  61. };
  62. // truncating store 2 -> 1
  63. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 2, Order, 1, order::little>
  64. {
  65. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  66. {
  67. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  68. unsigned char tmp[ 2 ];
  69. boost::endian::endian_store<T, 2, order::little>( tmp, v );
  70. p[0] = tmp[0];
  71. }
  72. };
  73. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 2, Order, 1, order::big>
  74. {
  75. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  76. {
  77. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  78. unsigned char tmp[ 2 ];
  79. boost::endian::endian_store<T, 2, order::big>( tmp, v );
  80. p[0] = tmp[1];
  81. }
  82. };
  83. // truncating store 4 -> 1
  84. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 1, order::little>
  85. {
  86. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  87. {
  88. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  89. unsigned char tmp[ 4 ];
  90. boost::endian::endian_store<T, 4, order::little>( tmp, v );
  91. p[0] = tmp[0];
  92. }
  93. };
  94. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 1, order::big>
  95. {
  96. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  97. {
  98. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  99. unsigned char tmp[ 4 ];
  100. boost::endian::endian_store<T, 4, order::big>( tmp, v );
  101. p[0] = tmp[3];
  102. }
  103. };
  104. // truncating store 4 -> 2
  105. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 2, order::little>
  106. {
  107. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  108. {
  109. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  110. unsigned char tmp[ 4 ];
  111. boost::endian::endian_store<T, 4, order::little>( tmp, v );
  112. p[0] = tmp[0];
  113. p[1] = tmp[1];
  114. }
  115. };
  116. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 2, order::big>
  117. {
  118. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  119. {
  120. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  121. unsigned char tmp[ 4 ];
  122. boost::endian::endian_store<T, 4, order::big>( tmp, v );
  123. p[0] = tmp[2];
  124. p[1] = tmp[3];
  125. }
  126. };
  127. // truncating store 4 -> 3
  128. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 3, order::little>
  129. {
  130. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  131. {
  132. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  133. unsigned char tmp[ 4 ];
  134. boost::endian::endian_store<T, 4, order::little>( tmp, v );
  135. p[0] = tmp[0];
  136. p[1] = tmp[1];
  137. p[2] = tmp[2];
  138. }
  139. };
  140. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 4, Order, 3, order::big>
  141. {
  142. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  143. {
  144. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  145. unsigned char tmp[ 4 ];
  146. boost::endian::endian_store<T, 4, order::big>( tmp, v );
  147. p[0] = tmp[1];
  148. p[1] = tmp[2];
  149. p[2] = tmp[3];
  150. }
  151. };
  152. // truncating store 8 -> 1
  153. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 1, order::little>
  154. {
  155. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  156. {
  157. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  158. unsigned char tmp[ 8 ];
  159. boost::endian::endian_store<T, 8, order::little>( tmp, v );
  160. p[0] = tmp[0];
  161. }
  162. };
  163. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 1, order::big>
  164. {
  165. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  166. {
  167. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  168. unsigned char tmp[ 8 ];
  169. boost::endian::endian_store<T, 8, order::big>( tmp, v );
  170. p[0] = tmp[7];
  171. }
  172. };
  173. // truncating store 8 -> 2
  174. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 2, order::little>
  175. {
  176. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  177. {
  178. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  179. unsigned char tmp[ 8 ];
  180. boost::endian::endian_store<T, 8, order::little>( tmp, v );
  181. p[0] = tmp[0];
  182. p[1] = tmp[1];
  183. }
  184. };
  185. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 2, order::big>
  186. {
  187. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  188. {
  189. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  190. unsigned char tmp[ 8 ];
  191. boost::endian::endian_store<T, 8, order::big>( tmp, v );
  192. p[0] = tmp[6];
  193. p[1] = tmp[7];
  194. }
  195. };
  196. // truncating store 8 -> 3
  197. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 3, order::little>
  198. {
  199. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  200. {
  201. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  202. unsigned char tmp[ 8 ];
  203. boost::endian::endian_store<T, 8, order::little>( tmp, v );
  204. p[0] = tmp[0];
  205. p[1] = tmp[1];
  206. p[2] = tmp[2];
  207. }
  208. };
  209. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 3, order::big>
  210. {
  211. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  212. {
  213. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  214. unsigned char tmp[ 8 ];
  215. boost::endian::endian_store<T, 8, order::big>( tmp, v );
  216. p[0] = tmp[5];
  217. p[1] = tmp[6];
  218. p[2] = tmp[7];
  219. }
  220. };
  221. // truncating store 8 -> 4
  222. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 4, order::little>
  223. {
  224. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  225. {
  226. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  227. unsigned char tmp[ 8 ];
  228. boost::endian::endian_store<T, 8, order::little>( tmp, v );
  229. p[0] = tmp[0];
  230. p[1] = tmp[1];
  231. p[2] = tmp[2];
  232. p[3] = tmp[3];
  233. }
  234. };
  235. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 4, order::big>
  236. {
  237. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  238. {
  239. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  240. unsigned char tmp[ 8 ];
  241. boost::endian::endian_store<T, 8, order::big>( tmp, v );
  242. p[0] = tmp[4];
  243. p[1] = tmp[5];
  244. p[2] = tmp[6];
  245. p[3] = tmp[7];
  246. }
  247. };
  248. // truncating store 8 -> 5
  249. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 5, order::little>
  250. {
  251. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  252. {
  253. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  254. unsigned char tmp[ 8 ];
  255. boost::endian::endian_store<T, 8, order::little>( tmp, v );
  256. p[0] = tmp[0];
  257. p[1] = tmp[1];
  258. p[2] = tmp[2];
  259. p[3] = tmp[3];
  260. p[4] = tmp[4];
  261. }
  262. };
  263. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 5, order::big>
  264. {
  265. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  266. {
  267. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  268. unsigned char tmp[ 8 ];
  269. boost::endian::endian_store<T, 8, order::big>( tmp, v );
  270. p[0] = tmp[3];
  271. p[1] = tmp[4];
  272. p[2] = tmp[5];
  273. p[3] = tmp[6];
  274. p[4] = tmp[7];
  275. }
  276. };
  277. // truncating store 8 -> 6
  278. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 6, order::little>
  279. {
  280. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  281. {
  282. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  283. unsigned char tmp[ 8 ];
  284. boost::endian::endian_store<T, 8, order::little>( tmp, v );
  285. p[0] = tmp[0];
  286. p[1] = tmp[1];
  287. p[2] = tmp[2];
  288. p[3] = tmp[3];
  289. p[4] = tmp[4];
  290. p[5] = tmp[5];
  291. }
  292. };
  293. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 6, order::big>
  294. {
  295. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  296. {
  297. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  298. unsigned char tmp[ 8 ];
  299. boost::endian::endian_store<T, 8, order::big>( tmp, v );
  300. p[0] = tmp[2];
  301. p[1] = tmp[3];
  302. p[2] = tmp[4];
  303. p[3] = tmp[5];
  304. p[4] = tmp[6];
  305. p[5] = tmp[7];
  306. }
  307. };
  308. // truncating store 8 -> 7
  309. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 7, order::little>
  310. {
  311. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  312. {
  313. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  314. unsigned char tmp[ 8 ];
  315. boost::endian::endian_store<T, 8, order::little>( tmp, v );
  316. p[0] = tmp[0];
  317. p[1] = tmp[1];
  318. p[2] = tmp[2];
  319. p[3] = tmp[3];
  320. p[4] = tmp[4];
  321. p[5] = tmp[5];
  322. p[6] = tmp[6];
  323. }
  324. };
  325. template<class T, BOOST_SCOPED_ENUM(order) Order> struct endian_store_impl<T, 8, Order, 7, order::big>
  326. {
  327. inline void operator()( unsigned char * p, T const & v ) const BOOST_NOEXCEPT
  328. {
  329. BOOST_STATIC_ASSERT( is_integral<T>::value || is_enum<T>::value );
  330. unsigned char tmp[ 8 ];
  331. boost::endian::endian_store<T, 8, order::big>( tmp, v );
  332. p[0] = tmp[1];
  333. p[1] = tmp[2];
  334. p[2] = tmp[3];
  335. p[3] = tmp[4];
  336. p[4] = tmp[5];
  337. p[5] = tmp[6];
  338. p[6] = tmp[7];
  339. }
  340. };
  341. } // namespace detail
  342. } // namespace endian
  343. } // namespace boost
  344. #endif // BOOST_ENDIAN_DETAIL_ENDIAN_STORE_HPP_INCLUDED