conversion_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. // conversion_test.cpp ---------------------------------------------------------------//
  2. // Copyright Beman Dawes 2010
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // See http://www.boost.org/LICENSE_1_0.txt
  5. //--------------------------------------------------------------------------------------//
  6. #include <boost/endian/detail/disable_warnings.hpp>
  7. #include <boost/endian/conversion.hpp>
  8. #include <boost/detail/lightweight_main.hpp>
  9. #include <boost/core/lightweight_test.hpp>
  10. #include <iostream>
  11. #include <cstring>
  12. #include <algorithm>
  13. namespace be = boost::endian;
  14. using std::cout;
  15. using std::endl;
  16. using boost::int8_t;
  17. using boost::uint8_t;
  18. using boost::int16_t;
  19. using boost::uint16_t;
  20. using boost::int32_t;
  21. using boost::uint32_t;
  22. using boost::int64_t;
  23. using boost::uint64_t;
  24. template <class T> inline T std_endian_reverse(T x) BOOST_NOEXCEPT
  25. {
  26. T tmp(x);
  27. std::reverse( reinterpret_cast<unsigned char*>(&tmp), reinterpret_cast<unsigned char*>(&tmp) + sizeof(T) );
  28. return tmp;
  29. }
  30. namespace
  31. {
  32. // values for tests
  33. void native_value(int8_t& x) {x = static_cast<int8_t>(0xF0U);}
  34. void native_value(uint8_t& x) {x = static_cast<uint8_t>(0xF0U);}
  35. # if BOOST_ENDIAN_BIG_BYTE
  36. void big_value(int8_t& x) {x = static_cast<int8_t>(0xF0U);}
  37. void big_value(uint8_t& x) {x = static_cast<uint8_t>(0xF0U);}
  38. void little_value(int8_t& x) {x = static_cast<int8_t>(0xF0U);}
  39. void little_value(uint8_t& x) {x = static_cast<uint8_t>(0xF0U);}
  40. # else
  41. void big_value(int8_t& x) {x = static_cast<int8_t>(0xF0U);}
  42. void big_value(uint8_t& x) {x = static_cast<uint8_t>(0xF0U);}
  43. void little_value(int8_t& x) {x = static_cast<int8_t>(0xF0U);}
  44. void little_value(uint8_t& x) {x = static_cast<uint8_t>(0xF0U);}
  45. # endif
  46. void native_value(int16_t& x) {x = static_cast<int16_t>(0xF102U);}
  47. void native_value(uint16_t& x) {x = static_cast<uint16_t>(0xF102U);}
  48. # if BOOST_ENDIAN_BIG_BYTE
  49. void big_value(int16_t& x) {x = static_cast<int16_t>(0xF102U);}
  50. void big_value(uint16_t& x) {x = static_cast<uint16_t>(0xF102U);}
  51. void little_value(int16_t& x) {x = static_cast<int16_t>(0x02F1U);}
  52. void little_value(uint16_t& x) {x = static_cast<uint16_t>(0x02F1U);}
  53. # else
  54. void big_value(int16_t& x) {x = static_cast<int16_t>(0x02F1U);}
  55. void big_value(uint16_t& x) {x = static_cast<uint16_t>(0x02F1U);}
  56. void little_value(int16_t& x) {x = static_cast<int16_t>(0xF102U);}
  57. void little_value(uint16_t& x) {x = static_cast<uint16_t>(0xF102U);}
  58. # endif
  59. void native_value(int32_t& x) {x = static_cast<int32_t>(0xF1E21304UL);}
  60. void native_value(uint32_t& x) {x = static_cast<uint32_t>(0xF1E21304UL);}
  61. # if BOOST_ENDIAN_BIG_BYTE
  62. void big_value(int32_t& x) {x = static_cast<int32_t>(0xF1E21304UL);}
  63. void big_value(uint32_t& x) {x = static_cast<uint32_t>(0xF1E21304UL);}
  64. void little_value(int32_t& x) {x = static_cast<int32_t>(0x0413E2F1UL);}
  65. void little_value(uint32_t& x) {x = static_cast<uint32_t>(0x0413E2F1UL);}
  66. # else
  67. void big_value(int32_t& x) {x = static_cast<int32_t>(0x0413E2F1UL);}
  68. void big_value(uint32_t& x) {x = static_cast<uint32_t>(0x0413E2F1UL);}
  69. void little_value(int32_t& x) {x = static_cast<int32_t>(0xF1E21304UL);}
  70. void little_value(uint32_t& x) {x = static_cast<uint32_t>(0xF1E21304UL);}
  71. # endif
  72. void native_value(int64_t& x) {x = static_cast<int64_t>(0xF1E2D3C444231201ULL);}
  73. void native_value(uint64_t& x) {x = static_cast<uint64_t>(0xF1E2D3C444231201ULL);}
  74. # if BOOST_ENDIAN_BIG_BYTE
  75. void big_value(int64_t& x) {x = static_cast<int64_t>(0xF1E2D3C444231201ULL);}
  76. void big_value(uint64_t& x) {x = static_cast<uint64_t>(0xF1E2D3C444231201ULL);}
  77. void little_value(int64_t& x) {x = static_cast<int64_t>(0x01122344C4D3E2F1ULL);}
  78. void little_value(uint64_t& x) {x = static_cast<uint64_t>(0x01122344C4D3E2F1ULL);}
  79. # else
  80. void big_value(int64_t& x) {x = static_cast<int64_t>(0x01122344C4D3E2F1ULL);}
  81. void big_value(uint64_t& x) {x = static_cast<uint64_t>(0x01122344C4D3E2F1ULL);}
  82. void little_value(int64_t& x) {x = static_cast<int64_t>(0xF1E2D3C444231201ULL);}
  83. void little_value(uint64_t& x) {x = static_cast<uint64_t>(0xF1E2D3C444231201ULL);}
  84. # endif
  85. template <class T>
  86. void test()
  87. {
  88. T native;
  89. T big;
  90. T little;
  91. native_value(native);
  92. big_value(big);
  93. little_value(little);
  94. // validate the values used by the tests below
  95. # if BOOST_ENDIAN_BIG_BYTE
  96. BOOST_TEST_EQ(native, big);
  97. BOOST_TEST_EQ(::std_endian_reverse(native), little);
  98. # else
  99. BOOST_TEST_EQ(::std_endian_reverse(native), big);
  100. BOOST_TEST_EQ(native, little);
  101. # endif
  102. // value-by-value tests
  103. // unconditional reverse
  104. BOOST_TEST_EQ(be::endian_reverse(big), little);
  105. BOOST_TEST_EQ(be::endian_reverse(little), big);
  106. // conditional reverse
  107. BOOST_TEST_EQ(be::native_to_big(native), big);
  108. BOOST_TEST_EQ(be::native_to_little(native), little);
  109. BOOST_TEST_EQ(be::big_to_native(big), native);
  110. BOOST_TEST_EQ(be::little_to_native(little), native);
  111. // generic conditional reverse
  112. BOOST_TEST_EQ((be::conditional_reverse<be::order::big, be::order::big>(big)), big);
  113. BOOST_TEST_EQ((be::conditional_reverse<be::order::little,
  114. be::order::little>(little)), little);
  115. BOOST_TEST_EQ((be::conditional_reverse<be::order::native,
  116. be::order::native>(native)), native);
  117. BOOST_TEST_EQ((be::conditional_reverse<be::order::big,
  118. be::order::little>(big)), little);
  119. BOOST_TEST_EQ((be::conditional_reverse<be::order::big,
  120. be::order::native>(big)), native);
  121. BOOST_TEST_EQ((be::conditional_reverse<be::order::little,
  122. be::order::big>(little)), big);
  123. BOOST_TEST_EQ((be::conditional_reverse<be::order::little,
  124. be::order::native>(little)), native);
  125. BOOST_TEST_EQ((be::conditional_reverse<be::order::native,
  126. be::order::big>(native)), big);
  127. BOOST_TEST_EQ((be::conditional_reverse<be::order::native,
  128. be::order::little>(native)), little);
  129. // runtime conditional reverse
  130. BOOST_TEST_EQ((be::conditional_reverse(big, be::order::big, be::order::big)),
  131. big);
  132. BOOST_TEST_EQ((be::conditional_reverse(little, be::order::little,
  133. be::order::little)), little);
  134. BOOST_TEST_EQ((be::conditional_reverse(native, be::order::native,
  135. be::order::native)), native);
  136. BOOST_TEST_EQ((be::conditional_reverse(big, be::order::big,
  137. be::order::little)), little);
  138. BOOST_TEST_EQ((be::conditional_reverse(big, be::order::big,
  139. be::order::native)), native);
  140. BOOST_TEST_EQ((be::conditional_reverse(little, be::order::little,
  141. be::order::big)), big);
  142. BOOST_TEST_EQ((be::conditional_reverse(little, be::order::little,
  143. be::order::native)), native);
  144. BOOST_TEST_EQ((be::conditional_reverse(native, be::order::native,
  145. be::order::big)), big);
  146. BOOST_TEST_EQ((be::conditional_reverse(native, be::order::native,
  147. be::order::little)), little);
  148. // modify-in-place tests
  149. T x;
  150. // unconditional reverse
  151. x = big; be::endian_reverse_inplace(x); BOOST_TEST_EQ(x, little);
  152. x = little; be::endian_reverse_inplace(x); BOOST_TEST_EQ(x, big);
  153. // conditional reverse
  154. x = native; be::native_to_big_inplace(x); BOOST_TEST_EQ(x, big);
  155. x = native; be::native_to_little_inplace(x); BOOST_TEST_EQ(x, little);
  156. x = big; be::big_to_native_inplace(x); BOOST_TEST_EQ(x, native);
  157. x = little; be::little_to_native_inplace(x); BOOST_TEST_EQ(x, native);
  158. // generic conditional reverse
  159. x = big; be::conditional_reverse_inplace<be::order::big, be::order::big>(x);
  160. BOOST_TEST_EQ(x, big);
  161. x = little; be::conditional_reverse_inplace<be::order::little, be::order::little>(x);
  162. BOOST_TEST_EQ(x, little);
  163. x = native; be::conditional_reverse_inplace<be::order::native, be::order::native>(x);
  164. BOOST_TEST_EQ(x, native);
  165. x = big; be::conditional_reverse_inplace<be::order::big, be::order::little>(x);
  166. BOOST_TEST_EQ(x, little);
  167. x = big; be::conditional_reverse_inplace<be::order::big, be::order::native>(x);
  168. BOOST_TEST_EQ(x, native);
  169. x = little; be::conditional_reverse_inplace<be::order::little, be::order::big>(x);
  170. BOOST_TEST_EQ(x, big);
  171. x = little; be::conditional_reverse_inplace<be::order::little, be::order::native>(x);
  172. BOOST_TEST_EQ(x, native);
  173. x = native; be::conditional_reverse_inplace<be::order::native, be::order::big>(x);
  174. BOOST_TEST_EQ(x, big);
  175. x = native; be::conditional_reverse_inplace<be::order::native, be::order::little>(x);
  176. BOOST_TEST_EQ(x, little);
  177. // runtime conditional reverse
  178. x = big;
  179. be::conditional_reverse_inplace(x, be::order::big, be::order::big);
  180. BOOST_TEST_EQ(x, big);
  181. x = little;
  182. be::conditional_reverse_inplace(x, be::order::little, be::order::little);
  183. BOOST_TEST_EQ(x, little);
  184. x = native;
  185. be::conditional_reverse_inplace(x, be::order::native, be::order::native);
  186. BOOST_TEST_EQ(x, native);
  187. x = big;
  188. be::conditional_reverse_inplace(x, be::order::big, be::order::little);
  189. BOOST_TEST_EQ(x, little);
  190. x = big;
  191. be::conditional_reverse_inplace(x, be::order::big, be::order::native);
  192. BOOST_TEST_EQ(x, native);
  193. x = little;
  194. be::conditional_reverse_inplace(x, be::order::little, be::order::big);
  195. BOOST_TEST_EQ(x, big);
  196. x = little;
  197. be::conditional_reverse_inplace(x, be::order::little, be::order::native);
  198. BOOST_TEST_EQ(x, native);
  199. x = native;
  200. be::conditional_reverse_inplace(x, be::order::native, be::order::big);
  201. BOOST_TEST_EQ(x, big);
  202. x = native;
  203. be::conditional_reverse_inplace(x, be::order::native, be::order::little);
  204. BOOST_TEST_EQ(x, little);
  205. }
  206. //--------------------------------------------------------------------------------------//
  207. template <class UDT>
  208. void udt_test()
  209. {
  210. UDT udt, tmp;
  211. int64_t big;
  212. int64_t little;
  213. int64_t native;
  214. big_value(big);
  215. little_value(little);
  216. native_value(native);
  217. udt.member1 = big;
  218. udt.member2 = little;
  219. udt.member3 = native;
  220. tmp = be::conditional_reverse<be::order::big, be::order::little>(udt);
  221. BOOST_TEST_EQ(tmp.member1, be::endian_reverse(big));
  222. BOOST_TEST_EQ(tmp.member2, be::endian_reverse(little));
  223. BOOST_TEST_EQ(tmp.member3, be::endian_reverse(native));
  224. be::conditional_reverse_inplace<be::order::big, be::order::little>(udt);
  225. BOOST_TEST_EQ(udt.member1, be::endian_reverse(big));
  226. BOOST_TEST_EQ(udt.member2, be::endian_reverse(little));
  227. BOOST_TEST_EQ(udt.member3, be::endian_reverse(native));
  228. udt.member1 = big;
  229. udt.member2 = little;
  230. udt.member3 = native;
  231. tmp.member1 = tmp.member2 = tmp.member3 = 0;
  232. tmp = be::conditional_reverse<be::order::big, be::order::big>(udt);
  233. BOOST_TEST_EQ(tmp.member1, big);
  234. BOOST_TEST_EQ(tmp.member2, little);
  235. BOOST_TEST_EQ(tmp.member3, native);
  236. be::conditional_reverse_inplace<be::order::big, be::order::big>(udt);
  237. BOOST_TEST_EQ(udt.member1, big);
  238. BOOST_TEST_EQ(udt.member2, little);
  239. BOOST_TEST_EQ(udt.member3, native);
  240. }
  241. } // unnamed namespace
  242. //--------------------------------------------------------------------------------------//
  243. // User-defined types
  244. namespace user
  245. {
  246. // UDT1 supplies both endian_reverse and endian_reverse_inplace
  247. struct UDT1
  248. {
  249. int64_t member1;
  250. int64_t member2;
  251. int64_t member3;
  252. };
  253. UDT1 endian_reverse(const UDT1& udt) BOOST_NOEXCEPT
  254. {
  255. UDT1 tmp;
  256. tmp.member1 = boost::endian::endian_reverse(udt.member1);
  257. tmp.member2 = boost::endian::endian_reverse(udt.member2);
  258. tmp.member3 = boost::endian::endian_reverse(udt.member3);
  259. return tmp;
  260. }
  261. void endian_reverse_inplace(UDT1& udt) BOOST_NOEXCEPT
  262. {
  263. boost::endian::endian_reverse_inplace(udt.member1);
  264. boost::endian::endian_reverse_inplace(udt.member2);
  265. boost::endian::endian_reverse_inplace(udt.member3);
  266. }
  267. // UDT2 supplies only endian_reverse
  268. struct UDT2
  269. {
  270. int64_t member1;
  271. int64_t member2;
  272. int64_t member3;
  273. };
  274. UDT2 endian_reverse(const UDT2& udt) BOOST_NOEXCEPT
  275. {
  276. UDT2 tmp;
  277. tmp.member1 = boost::endian::endian_reverse(udt.member1);
  278. tmp.member2 = boost::endian::endian_reverse(udt.member2);
  279. tmp.member3 = boost::endian::endian_reverse(udt.member3);
  280. return tmp;
  281. }
  282. // UDT3 supplies neither endian_reverse nor endian_reverse_inplace,
  283. // so udt_test<UDT3>() should fail to compile
  284. struct UDT3
  285. {
  286. int64_t member1;
  287. int64_t member2;
  288. int64_t member3;
  289. };
  290. } // namespace user
  291. //--------------------------------------------------------------------------------------//
  292. int cpp_main(int, char * [])
  293. {
  294. cout << "byte swap intrinsics: " BOOST_ENDIAN_INTRINSIC_MSG << endl;
  295. //std::cerr << std::hex;
  296. cout << "int8_t" << endl;
  297. test<int8_t>();
  298. cout << "uint8_t" << endl;
  299. test<uint8_t>();
  300. cout << "int16_t" << endl;
  301. test<int16_t>();
  302. cout << "uint16_t" << endl;
  303. test<uint16_t>();
  304. cout << "int32_t" << endl;
  305. test<int32_t>();
  306. cout << "uint32_t" << endl;
  307. test<uint32_t>();
  308. cout << "int64_t" << endl;
  309. test<int64_t>();
  310. cout << "uint64_t" << endl;
  311. test<uint64_t>();
  312. cout << "UDT 1" << endl;
  313. udt_test<user::UDT1>();
  314. cout << "UDT 2" << endl;
  315. udt_test<user::UDT2>();
  316. #ifdef BOOST_ENDIAN_COMPILE_FAIL
  317. cout << "UDT 3" << endl;
  318. udt_test<user::UDT3>(); // should fail to compile since has not endian_reverse()
  319. #endif
  320. return ::boost::report_errors();
  321. }
  322. #include <boost/endian/detail/disable_warnings_pop.hpp>