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