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