endian_operations_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. // endian_operations_test.cpp --------------------------------------------------------//
  2. // Copyright Beman Dawes 2008
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // See library home page at http://www.boost.org/libs/endian
  6. //--------------------------------------------------------------------------------------//
  7. // This test probes operator overloading, including interaction between
  8. // operand types.
  9. // See endian_test for tests of endianness correctness, size, and value.
  10. #include <boost/endian/detail/disable_warnings.hpp>
  11. #ifdef _MSC_VER
  12. # pragma warning( disable : 4242 ) // conversion ..., possible loss of data
  13. # pragma warning( disable : 4244 ) // conversion ..., possible loss of data
  14. # pragma warning( disable : 4018 ) // signed/unsigned mismatch
  15. # pragma warning( disable : 4365 ) // signed/unsigned mismatch
  16. # pragma warning( disable : 4389 ) // signed/unsigned mismatch
  17. #elif defined(__GNUC__)
  18. # pragma GCC diagnostic ignored "-Wconversion"
  19. #endif
  20. #include <boost/endian/arithmetic.hpp>
  21. #include <boost/type_traits/is_signed.hpp>
  22. #include <boost/core/lightweight_test.hpp>
  23. #include <boost/detail/lightweight_main.hpp>
  24. #include <boost/cstdint.hpp>
  25. #include <cassert>
  26. #include <iostream>
  27. #include <sstream>
  28. namespace be = boost::endian;
  29. template <class T>
  30. struct value_type
  31. {
  32. typedef typename T::value_type type;
  33. };
  34. template<> struct value_type<char> { typedef char type; };
  35. template<> struct value_type<unsigned char> { typedef unsigned char type; };
  36. template<> struct value_type<signed char> { typedef signed char type; };
  37. template<> struct value_type<short> { typedef short type; };
  38. template<> struct value_type<unsigned short> { typedef unsigned short type; };
  39. template<> struct value_type<int> { typedef int type; };
  40. template<> struct value_type<unsigned int> { typedef unsigned int type; };
  41. template<> struct value_type<long> { typedef long type; };
  42. template<> struct value_type<unsigned long> { typedef unsigned long type; };
  43. template<> struct value_type<long long> { typedef long long type; };
  44. template<> struct value_type<unsigned long long> { typedef unsigned long long type; };
  45. template <class T1, class T2>
  46. struct default_construct
  47. {
  48. static void test()
  49. {
  50. T1 o1;
  51. o1 = 1; // quiet warnings
  52. if (o1) return; // quiet warnings
  53. }
  54. };
  55. template <class T1, class T2>
  56. struct construct
  57. {
  58. static void test()
  59. {
  60. T2 o2(1);
  61. T1 o1(static_cast<T1>(o2));
  62. ++o1; // quiet gcc unused variable warning
  63. }
  64. };
  65. template <class T1, class T2>
  66. struct initialize
  67. {
  68. static void test()
  69. {
  70. T1 o2(2);
  71. T1 o1 = o2;
  72. ++o1; // quiet gcc unused variable warning
  73. }
  74. };
  75. template <class T1, class T2>
  76. struct assign
  77. {
  78. static void test()
  79. {
  80. T2 o2;
  81. o2 = 1;
  82. T1 o1;
  83. o1 = o2;
  84. if (o1) return; // quiet warnings
  85. }
  86. };
  87. template <class T1, class T2, bool SameSignedness>
  88. struct do_relational
  89. {
  90. static void test()
  91. {
  92. T1 o1(1);
  93. T2 o2(2);
  94. BOOST_TEST( !(o1 == o2) );
  95. BOOST_TEST( o1 != o2 );
  96. BOOST_TEST( o1 < o2 );
  97. BOOST_TEST( o1 <= o2 );
  98. BOOST_TEST( !(o1 > o2) );
  99. BOOST_TEST( !(o1 >= o2 ) );
  100. }
  101. };
  102. template <class T1, class T2>
  103. struct do_relational<T1, T2, false>
  104. {
  105. static void test()
  106. {
  107. }
  108. };
  109. template <class T1, class T2>
  110. struct relational
  111. {
  112. static void test()
  113. {
  114. do_relational<T1, T2,
  115. boost::is_signed<typename value_type<T1>::type>::value
  116. == boost::is_signed<typename value_type<T2>::type>::value
  117. >::test();
  118. // do_relational<T1, T2, true>::test();
  119. }
  120. };
  121. template <class T1, class T2>
  122. struct op_plus
  123. {
  124. static void test()
  125. {
  126. T1 o1(1);
  127. T2 o2(2);
  128. T1 o3;
  129. o3 = +o1;
  130. o3 = o1 + o2;
  131. o1 += o2;
  132. if (o3) return; // quiet warnings
  133. }
  134. };
  135. template <class T1, class T2>
  136. struct op_star
  137. {
  138. static void test()
  139. {
  140. T1 o1(1);
  141. T2 o2(2);
  142. T1 o3;
  143. o3 = o1 * o2;
  144. o1 *= o2;
  145. if (o3) return; // quiet warnings
  146. }
  147. };
  148. template <template<class, class> class Test, class T1>
  149. void op_test_aux()
  150. {
  151. Test<T1, char>::test();
  152. Test<T1, unsigned char>::test();
  153. Test<T1, signed char>::test();
  154. Test<T1, short>::test();
  155. Test<T1, unsigned short>::test();
  156. Test<T1, int>::test();
  157. Test<T1, unsigned int>::test();
  158. Test<T1, long>::test();
  159. Test<T1, unsigned long>::test();
  160. Test<T1, long long>::test();
  161. Test<T1, unsigned long long>::test();
  162. Test<T1, be::big_int16_at>::test();
  163. Test<T1, be::big_int32_at>::test();
  164. Test<T1, be::big_int64_at>::test();
  165. Test<T1, be::big_uint16_at>::test();
  166. Test<T1, be::big_uint32_at>::test();
  167. Test<T1, be::big_uint64_at>::test();
  168. Test<T1, be::little_int16_at>::test();
  169. Test<T1, be::little_int32_at>::test();
  170. Test<T1, be::little_int64_at>::test();
  171. Test<T1, be::little_uint16_at>::test();
  172. Test<T1, be::little_uint32_at>::test();
  173. Test<T1, be::little_uint64_at>::test();
  174. Test<T1, be::big_int8_t>::test();
  175. Test<T1, be::big_int16_t>::test();
  176. Test<T1, be::big_int24_t>::test();
  177. Test<T1, be::big_int32_t>::test();
  178. Test<T1, be::big_int40_t>::test();
  179. Test<T1, be::big_int48_t>::test();
  180. Test<T1, be::big_int56_t>::test();
  181. Test<T1, be::big_int64_t>::test();
  182. Test<T1, be::big_uint8_t>::test();
  183. Test<T1, be::big_uint16_t>::test();
  184. Test<T1, be::big_uint24_t>::test();
  185. Test<T1, be::big_uint32_t>::test();
  186. Test<T1, be::big_uint40_t>::test();
  187. Test<T1, be::big_uint64_t>::test();
  188. Test<T1, be::little_int16_t>::test();
  189. Test<T1, be::little_int24_t>::test();
  190. Test<T1, be::little_int32_t>::test();
  191. Test<T1, be::little_int64_t>::test();
  192. Test<T1, be::little_uint16_t>::test();
  193. Test<T1, be::little_uint32_t>::test();
  194. Test<T1, be::little_uint56_t>::test();
  195. Test<T1, be::little_uint64_t>::test();
  196. Test<T1, be::native_int16_t>::test();
  197. Test<T1, be::native_int24_t>::test();
  198. Test<T1, be::native_int32_t>::test();
  199. Test<T1, be::native_int64_t>::test();
  200. #ifdef BOOST_LONG_ENDIAN_TEST
  201. Test<T1, be::native_uint16_t>::test();
  202. Test<T1, be::native_uint24_t>::test();
  203. Test<T1, be::native_uint32_t>::test();
  204. Test<T1, be::native_uint48_t>::test();
  205. Test<T1, be::native_uint64_t>::test();
  206. Test<T1, be::big_uint48_t>::test();
  207. Test<T1, be::big_uint56_t>::test();
  208. Test<T1, be::little_int8_t>::test();
  209. Test<T1, be::little_int56_t>::test();
  210. Test<T1, be::little_int40_t>::test();
  211. Test<T1, be::little_int48_t>::test();
  212. Test<T1, be::little_uint8_t>::test();
  213. Test<T1, be::little_uint24_t>::test();
  214. Test<T1, be::little_uint40_t>::test();
  215. Test<T1, be::little_uint48_t>::test();
  216. Test<T1, be::native_int8_t>::test();
  217. Test<T1, be::native_int40_t>::test();
  218. Test<T1, be::native_int48_t>::test();
  219. Test<T1, be::native_int56_t>::test();
  220. Test<T1, be::native_uint8_t>::test();
  221. Test<T1, be::native_uint40_t>::test();
  222. Test<T1, be::native_uint56_t>::test();
  223. #endif
  224. }
  225. template <template<class, class> class Test>
  226. void op_test()
  227. {
  228. op_test_aux<Test, char>();
  229. op_test_aux<Test, unsigned char>();
  230. op_test_aux<Test, signed char>();
  231. op_test_aux<Test, short>();
  232. op_test_aux<Test, unsigned short>();
  233. op_test_aux<Test, int>();
  234. op_test_aux<Test, unsigned int>();
  235. op_test_aux<Test, long>();
  236. op_test_aux<Test, unsigned long>();
  237. op_test_aux<Test, long long>();
  238. op_test_aux<Test, unsigned long long>();
  239. op_test_aux<Test, be::big_int16_at>();
  240. op_test_aux<Test, be::big_int32_at>();
  241. op_test_aux<Test, be::big_int64_at>();
  242. op_test_aux<Test, be::little_int16_at>();
  243. op_test_aux<Test, be::little_int32_at>();
  244. op_test_aux<Test, be::little_int64_at>();
  245. #ifdef BOOST_LONG_ENDIAN_TEST
  246. op_test_aux<Test, be::big_int8_t>();
  247. op_test_aux<Test, be::big_int16_t>();
  248. op_test_aux<Test, be::big_int24_t>();
  249. op_test_aux<Test, be::big_int32_t>();
  250. op_test_aux<Test, be::big_int40_t>();
  251. op_test_aux<Test, be::big_int48_t>();
  252. op_test_aux<Test, be::big_int56_t>();
  253. op_test_aux<Test, be::big_int64_t>();
  254. op_test_aux<Test, be::big_uint8_t>();
  255. op_test_aux<Test, be::big_uint16_t>();
  256. op_test_aux<Test, be::big_uint24_t>();
  257. op_test_aux<Test, be::big_uint32_t>();
  258. op_test_aux<Test, be::big_uint40_t>();
  259. op_test_aux<Test, be::big_uint48_t>();
  260. op_test_aux<Test, be::big_uint56_t>();
  261. op_test_aux<Test, be::big_uint64_t>();
  262. op_test_aux<Test, be::little_int8_t>();
  263. op_test_aux<Test, be::little_int16_t>();
  264. op_test_aux<Test, be::little_int24_t>();
  265. op_test_aux<Test, be::little_int32_t>();
  266. op_test_aux<Test, be::little_int40_t>();
  267. op_test_aux<Test, be::little_int48_t>();
  268. op_test_aux<Test, be::little_int56_t>();
  269. op_test_aux<Test, be::little_int64_t>();
  270. op_test_aux<Test, be::little_uint8_t>();
  271. op_test_aux<Test, be::little_uint16_t>();
  272. op_test_aux<Test, be::little_uint24_t>();
  273. op_test_aux<Test, be::little_uint32_t>();
  274. op_test_aux<Test, be::little_uint40_t>();
  275. op_test_aux<Test, be::little_uint48_t>();
  276. op_test_aux<Test, be::little_uint56_t>();
  277. op_test_aux<Test, be::little_uint64_t>();
  278. op_test_aux<Test, be::native_int8_t>();
  279. op_test_aux<Test, be::native_int16_t>();
  280. op_test_aux<Test, be::native_int24_t>();
  281. op_test_aux<Test, be::native_int32_t>();
  282. op_test_aux<Test, be::native_int40_t>();
  283. op_test_aux<Test, be::native_int48_t>();
  284. op_test_aux<Test, be::native_int56_t>();
  285. op_test_aux<Test, be::native_int64_t>();
  286. op_test_aux<Test, be::native_uint8_t>();
  287. op_test_aux<Test, be::native_uint16_t>();
  288. op_test_aux<Test, be::native_uint24_t>();
  289. op_test_aux<Test, be::native_uint32_t>();
  290. op_test_aux<Test, be::native_uint40_t>();
  291. op_test_aux<Test, be::native_uint48_t>();
  292. op_test_aux<Test, be::native_uint56_t>();
  293. op_test_aux<Test, be::native_uint64_t>();
  294. #endif
  295. }
  296. // test_inserter_and_extractor -----------------------------------------------------//
  297. void test_inserter_and_extractor()
  298. {
  299. std::cout << "test inserter and extractor..." << std::endl;
  300. be::big_uint64_t bu64(0x010203040506070ULL);
  301. be::little_uint64_t lu64(0x010203040506070ULL);
  302. boost::uint64_t x;
  303. std::stringstream ss;
  304. ss << bu64;
  305. ss >> x;
  306. BOOST_TEST_EQ(x, 0x010203040506070ULL);
  307. ss.clear();
  308. ss << lu64;
  309. ss >> x;
  310. BOOST_TEST_EQ(x, 0x010203040506070ULL);
  311. ss.clear();
  312. ss << 0x010203040506070ULL;
  313. be::big_uint64_t bu64z(0);
  314. ss >> bu64z;
  315. BOOST_TEST_EQ(bu64z, bu64);
  316. ss.clear();
  317. ss << 0x010203040506070ULL;
  318. be::little_uint64_t lu64z(0);
  319. ss >> lu64z;
  320. BOOST_TEST_EQ(lu64z, lu64);
  321. std::cout << "test inserter and extractor complete" << std::endl;
  322. }
  323. void f_big_int32_ut(be::big_int32_t) {}
  324. // main ------------------------------------------------------------------------------//
  325. int cpp_main(int, char * [])
  326. {
  327. // make sure some simple things work
  328. be::big_int32_t o1(1);
  329. be::big_int32_t o2(2L);
  330. be::big_int32_t o3(3LL);
  331. be::big_int64_t o4(1);
  332. std::clog << "set up test values\n";
  333. be::big_int32_t big(12345);
  334. be::little_uint16_t little_u(10);
  335. be::big_int64_t result;
  336. // this is the use case that is so irritating that it caused the endian
  337. // constructors to be made non-explicit
  338. std::clog << "\nf(1234) where f(big_int32_t)\n";
  339. f_big_int32_ut(1234);
  340. std::clog << "\nresult = big\n";
  341. result = big;
  342. std::clog << "\nresult = +big\n";
  343. result = +big;
  344. std::clog << "\nresult = -big\n";
  345. result = -big;
  346. std::clog << "\n++big\n";
  347. ++big;
  348. std::clog << "\nresult = big++\n";
  349. result = big++;
  350. std::clog << "\n--big\n";
  351. --big;
  352. std::clog << "\nbig--\n";
  353. big--;
  354. std::clog << "\nresult = big * big\n";
  355. result = big * big;
  356. std::clog << "\nresult = big * big\n";
  357. result = big * big;
  358. std::clog << "\nresult = big * little_u\n";
  359. result = big * little_u;
  360. std::clog << "\nbig *= little_u\n";
  361. big *= little_u;
  362. std::clog << "\nresult = little_u * big\n";
  363. result = little_u * big;
  364. std::clog << "\nresult = big * 5\n";
  365. result = big * 5;
  366. std::clog << "\nbig *= 5\n";
  367. big *= 5;
  368. std::clog << "\nresult = 5 * big\n";
  369. result = 5 * big;
  370. std::clog << "\nresult = little_u * 5\n";
  371. result = little_u * 5;
  372. std::clog << "\nresult = 5 * little_u\n";
  373. result = 5 * little_u;
  374. std::clog << "\nresult = 5 * 10\n";
  375. result = 5 * 10;
  376. std::clog << "\n";
  377. // test from Roland Schwarz that detected ambiguities; these ambiguities
  378. // were eliminated by BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
  379. unsigned u;
  380. be::little_uint32_t u1;
  381. be::little_uint32_t u2;
  382. u = 9;
  383. u1 = 1;
  384. std::clog << "\nu2 = u1 + u\n";
  385. u2 = u1 + u;
  386. std::clog << "\n";
  387. // variations to detect ambiguities
  388. be::little_uint32_t u3 = u1 + 5;
  389. u3 = u1 + 5u;
  390. if (u1 == 5)
  391. {}
  392. if (u1 == 5u)
  393. {}
  394. u1 += 5;
  395. u1 += 5u;
  396. u2 = u1 + 5;
  397. u2 = u1 + 5u;
  398. // one more wrinkle
  399. be::little_uint16_t u4(3);
  400. u4 = 3;
  401. std::clog << "\nu2 = u1 + u4\n";
  402. u2 = u1 + u4;
  403. std::clog << "\n";
  404. test_inserter_and_extractor();
  405. // perform the indicated test on ~60*60 operand types
  406. op_test<default_construct>();
  407. op_test<construct>(); // includes copy construction
  408. op_test<initialize>();
  409. op_test<assign>();
  410. op_test<relational>();
  411. op_test<op_plus>();
  412. op_test<op_star>();
  413. return boost::report_errors();
  414. }