]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
7c673cae FG |
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 | ||
7c673cae FG |
29 | #include <boost/endian/arithmetic.hpp> |
30 | #include <boost/type_traits/is_signed.hpp> | |
31 | #include <boost/core/lightweight_test.hpp> | |
7c673cae FG |
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 | { | |
60 | 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 | { | |
71 | 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 | { | |
82 | 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 | { | |
93 | 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 | { | |
106 | 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 | { | |
122 | static void test() | |
123 | { | |
124 | } | |
125 | }; | |
126 | ||
127 | template <class T1, class T2> | |
128 | struct relational | |
129 | { | |
130 | 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 | { | |
143 | 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 | { | |
162 | 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> | |
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> | |
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 | ||
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 | ||
364 | void f_big_int32_ut(be::big_int32_t) {} | |
365 | ||
366 | // main ------------------------------------------------------------------------------// | |
367 | ||
368 | int cpp_main(int, char * []) | |
369 | { | |
7c673cae FG |
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 | ||
7c673cae FG |
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 | ||
7c673cae | 477 | test_inserter_and_extractor(); |
11fdf7f2 | 478 | |
7c673cae FG |
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 | } | |
f67539c2 TL |
491 | |
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 | } |