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