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