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