]>
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> | |
32 | #include <boost/detail/lightweight_main.hpp> | |
33 | #include <boost/cstdint.hpp> | |
34 | #include <cassert> | |
35 | #include <iostream> | |
36 | #include <sstream> | |
37 | ||
38 | namespace be = boost::endian; | |
39 | ||
40 | template <class T> | |
41 | struct value_type | |
42 | { | |
43 | typedef typename T::value_type type; | |
44 | }; | |
45 | ||
46 | template<> struct value_type<char> { typedef char type; }; | |
47 | template<> struct value_type<unsigned char> { typedef unsigned char type; }; | |
48 | template<> struct value_type<signed char> { typedef signed char type; }; | |
49 | template<> struct value_type<short> { typedef short type; }; | |
50 | template<> struct value_type<unsigned short> { typedef unsigned short type; }; | |
51 | template<> struct value_type<int> { typedef int type; }; | |
52 | template<> struct value_type<unsigned int> { typedef unsigned int type; }; | |
53 | template<> struct value_type<long> { typedef long type; }; | |
54 | template<> struct value_type<unsigned long> { typedef unsigned long type; }; | |
55 | template<> struct value_type<long long> { typedef long long type; }; | |
56 | template<> struct value_type<unsigned long long> { typedef unsigned long long type; }; | |
57 | ||
58 | template <class T1, class T2> | |
59 | struct default_construct | |
60 | { | |
61 | static void test() | |
62 | { | |
63 | T1 o1; | |
64 | o1 = 1; // quiet warnings | |
65 | if (o1) return; // quiet warnings | |
66 | } | |
67 | }; | |
68 | ||
69 | template <class T1, class T2> | |
70 | struct construct | |
71 | { | |
72 | static void test() | |
73 | { | |
74 | T2 o2(1); | |
75 | T1 o1(static_cast<T1>(o2)); | |
76 | ++o1; // quiet gcc unused variable warning | |
77 | } | |
78 | }; | |
79 | ||
80 | template <class T1, class T2> | |
81 | struct initialize | |
82 | { | |
83 | static void test() | |
84 | { | |
85 | T1 o2(2); | |
86 | T1 o1 = o2; | |
87 | ++o1; // quiet gcc unused variable warning | |
88 | } | |
89 | }; | |
90 | ||
91 | template <class T1, class T2> | |
92 | struct assign | |
93 | { | |
94 | static void test() | |
95 | { | |
96 | T2 o2; | |
97 | o2 = 1; | |
98 | T1 o1; | |
99 | o1 = o2; | |
100 | if (o1) return; // quiet warnings | |
101 | } | |
102 | }; | |
103 | ||
104 | template <class T1, class T2, bool SameSignedness> | |
105 | struct do_relational | |
106 | { | |
107 | static void test() | |
108 | { | |
109 | T1 o1(1); | |
110 | T2 o2(2); | |
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 | BOOST_TEST( !(o1 >= o2 ) ); | |
117 | } | |
118 | }; | |
119 | ||
120 | template <class T1, class T2> | |
121 | struct do_relational<T1, T2, false> | |
122 | { | |
123 | static void test() | |
124 | { | |
125 | } | |
126 | }; | |
127 | ||
128 | template <class T1, class T2> | |
129 | struct relational | |
130 | { | |
131 | static void test() | |
132 | { | |
133 | do_relational<T1, T2, | |
134 | boost::is_signed<typename value_type<T1>::type>::value | |
135 | == boost::is_signed<typename value_type<T2>::type>::value | |
136 | >::test(); | |
137 | // do_relational<T1, T2, true>::test(); | |
138 | } | |
139 | }; | |
140 | ||
141 | template <class T1, class T2> | |
142 | struct op_plus | |
143 | { | |
144 | static void test() | |
145 | { | |
146 | T1 o1(1); | |
147 | T2 o2(2); | |
148 | T1 o3; | |
149 | ||
150 | o3 = +o1; | |
151 | ||
152 | o3 = o1 + o2; | |
153 | ||
154 | o1 += o2; | |
155 | ||
156 | if (o3) return; // quiet warnings | |
157 | } | |
158 | }; | |
159 | ||
160 | template <class T1, class T2> | |
161 | struct op_star | |
162 | { | |
163 | static void test() | |
164 | { | |
165 | T1 o1(1); | |
166 | T2 o2(2); | |
167 | T1 o3; | |
168 | ||
169 | o3 = o1 * o2; | |
170 | ||
171 | o1 *= o2; | |
172 | ||
173 | if (o3) return; // quiet warnings | |
174 | } | |
175 | }; | |
176 | ||
177 | template <template<class, class> class Test, class T1> | |
178 | void op_test_aux() | |
179 | { | |
180 | Test<T1, char>::test(); | |
181 | Test<T1, unsigned char>::test(); | |
182 | Test<T1, signed char>::test(); | |
183 | Test<T1, short>::test(); | |
184 | Test<T1, unsigned short>::test(); | |
185 | Test<T1, int>::test(); | |
186 | Test<T1, unsigned int>::test(); | |
187 | Test<T1, long>::test(); | |
188 | Test<T1, unsigned long>::test(); | |
189 | Test<T1, long long>::test(); | |
190 | Test<T1, unsigned long long>::test(); | |
191 | Test<T1, be::big_int16_at>::test(); | |
192 | Test<T1, be::big_int32_at>::test(); | |
193 | Test<T1, be::big_int64_at>::test(); | |
194 | Test<T1, be::big_uint16_at>::test(); | |
195 | Test<T1, be::big_uint32_at>::test(); | |
196 | Test<T1, be::big_uint64_at>::test(); | |
197 | Test<T1, be::little_int16_at>::test(); | |
198 | Test<T1, be::little_int32_at>::test(); | |
199 | Test<T1, be::little_int64_at>::test(); | |
200 | Test<T1, be::little_uint16_at>::test(); | |
201 | Test<T1, be::little_uint32_at>::test(); | |
202 | Test<T1, be::little_uint64_at>::test(); | |
203 | Test<T1, be::big_int8_t>::test(); | |
204 | Test<T1, be::big_int16_t>::test(); | |
205 | Test<T1, be::big_int24_t>::test(); | |
206 | Test<T1, be::big_int32_t>::test(); | |
207 | Test<T1, be::big_int40_t>::test(); | |
208 | Test<T1, be::big_int48_t>::test(); | |
209 | Test<T1, be::big_int56_t>::test(); | |
210 | Test<T1, be::big_int64_t>::test(); | |
211 | Test<T1, be::big_uint8_t>::test(); | |
212 | Test<T1, be::big_uint16_t>::test(); | |
213 | Test<T1, be::big_uint24_t>::test(); | |
214 | Test<T1, be::big_uint32_t>::test(); | |
215 | Test<T1, be::big_uint40_t>::test(); | |
216 | Test<T1, be::big_uint64_t>::test(); | |
217 | Test<T1, be::little_int16_t>::test(); | |
218 | Test<T1, be::little_int24_t>::test(); | |
219 | Test<T1, be::little_int32_t>::test(); | |
220 | Test<T1, be::little_int64_t>::test(); | |
221 | Test<T1, be::little_uint16_t>::test(); | |
222 | Test<T1, be::little_uint32_t>::test(); | |
223 | Test<T1, be::little_uint56_t>::test(); | |
224 | Test<T1, be::little_uint64_t>::test(); | |
225 | Test<T1, be::native_int16_t>::test(); | |
226 | Test<T1, be::native_int24_t>::test(); | |
227 | Test<T1, be::native_int32_t>::test(); | |
228 | Test<T1, be::native_int64_t>::test(); | |
229 | #ifdef BOOST_LONG_ENDIAN_TEST | |
230 | Test<T1, be::native_uint16_t>::test(); | |
231 | Test<T1, be::native_uint24_t>::test(); | |
232 | Test<T1, be::native_uint32_t>::test(); | |
233 | Test<T1, be::native_uint48_t>::test(); | |
234 | Test<T1, be::native_uint64_t>::test(); | |
235 | Test<T1, be::big_uint48_t>::test(); | |
236 | Test<T1, be::big_uint56_t>::test(); | |
237 | Test<T1, be::little_int8_t>::test(); | |
238 | Test<T1, be::little_int56_t>::test(); | |
239 | Test<T1, be::little_int40_t>::test(); | |
240 | Test<T1, be::little_int48_t>::test(); | |
241 | Test<T1, be::little_uint8_t>::test(); | |
242 | Test<T1, be::little_uint24_t>::test(); | |
243 | Test<T1, be::little_uint40_t>::test(); | |
244 | Test<T1, be::little_uint48_t>::test(); | |
245 | Test<T1, be::native_int8_t>::test(); | |
246 | Test<T1, be::native_int40_t>::test(); | |
247 | Test<T1, be::native_int48_t>::test(); | |
248 | Test<T1, be::native_int56_t>::test(); | |
249 | Test<T1, be::native_uint8_t>::test(); | |
250 | Test<T1, be::native_uint40_t>::test(); | |
251 | Test<T1, be::native_uint56_t>::test(); | |
252 | #endif | |
253 | } | |
254 | ||
255 | template <template<class, class> class Test> | |
256 | void op_test() | |
257 | { | |
258 | op_test_aux<Test, char>(); | |
259 | op_test_aux<Test, unsigned char>(); | |
260 | op_test_aux<Test, signed char>(); | |
261 | op_test_aux<Test, short>(); | |
262 | op_test_aux<Test, unsigned short>(); | |
263 | op_test_aux<Test, int>(); | |
264 | op_test_aux<Test, unsigned int>(); | |
265 | op_test_aux<Test, long>(); | |
266 | op_test_aux<Test, unsigned long>(); | |
267 | op_test_aux<Test, long long>(); | |
268 | op_test_aux<Test, unsigned long long>(); | |
269 | op_test_aux<Test, be::big_int16_at>(); | |
270 | op_test_aux<Test, be::big_int32_at>(); | |
271 | op_test_aux<Test, be::big_int64_at>(); | |
272 | op_test_aux<Test, be::little_int16_at>(); | |
273 | op_test_aux<Test, be::little_int32_at>(); | |
274 | op_test_aux<Test, be::little_int64_at>(); | |
275 | #ifdef BOOST_LONG_ENDIAN_TEST | |
276 | op_test_aux<Test, be::big_int8_t>(); | |
277 | op_test_aux<Test, be::big_int16_t>(); | |
278 | op_test_aux<Test, be::big_int24_t>(); | |
279 | op_test_aux<Test, be::big_int32_t>(); | |
280 | op_test_aux<Test, be::big_int40_t>(); | |
281 | op_test_aux<Test, be::big_int48_t>(); | |
282 | op_test_aux<Test, be::big_int56_t>(); | |
283 | op_test_aux<Test, be::big_int64_t>(); | |
284 | op_test_aux<Test, be::big_uint8_t>(); | |
285 | op_test_aux<Test, be::big_uint16_t>(); | |
286 | op_test_aux<Test, be::big_uint24_t>(); | |
287 | op_test_aux<Test, be::big_uint32_t>(); | |
288 | op_test_aux<Test, be::big_uint40_t>(); | |
289 | op_test_aux<Test, be::big_uint48_t>(); | |
290 | op_test_aux<Test, be::big_uint56_t>(); | |
291 | op_test_aux<Test, be::big_uint64_t>(); | |
292 | op_test_aux<Test, be::little_int8_t>(); | |
293 | op_test_aux<Test, be::little_int16_t>(); | |
294 | op_test_aux<Test, be::little_int24_t>(); | |
295 | op_test_aux<Test, be::little_int32_t>(); | |
296 | op_test_aux<Test, be::little_int40_t>(); | |
297 | op_test_aux<Test, be::little_int48_t>(); | |
298 | op_test_aux<Test, be::little_int56_t>(); | |
299 | op_test_aux<Test, be::little_int64_t>(); | |
300 | op_test_aux<Test, be::little_uint8_t>(); | |
301 | op_test_aux<Test, be::little_uint16_t>(); | |
302 | op_test_aux<Test, be::little_uint24_t>(); | |
303 | op_test_aux<Test, be::little_uint32_t>(); | |
304 | op_test_aux<Test, be::little_uint40_t>(); | |
305 | op_test_aux<Test, be::little_uint48_t>(); | |
306 | op_test_aux<Test, be::little_uint56_t>(); | |
307 | op_test_aux<Test, be::little_uint64_t>(); | |
308 | op_test_aux<Test, be::native_int8_t>(); | |
309 | op_test_aux<Test, be::native_int16_t>(); | |
310 | op_test_aux<Test, be::native_int24_t>(); | |
311 | op_test_aux<Test, be::native_int32_t>(); | |
312 | op_test_aux<Test, be::native_int40_t>(); | |
313 | op_test_aux<Test, be::native_int48_t>(); | |
314 | op_test_aux<Test, be::native_int56_t>(); | |
315 | op_test_aux<Test, be::native_int64_t>(); | |
316 | op_test_aux<Test, be::native_uint8_t>(); | |
317 | op_test_aux<Test, be::native_uint16_t>(); | |
318 | op_test_aux<Test, be::native_uint24_t>(); | |
319 | op_test_aux<Test, be::native_uint32_t>(); | |
320 | op_test_aux<Test, be::native_uint40_t>(); | |
321 | op_test_aux<Test, be::native_uint48_t>(); | |
322 | op_test_aux<Test, be::native_uint56_t>(); | |
323 | op_test_aux<Test, be::native_uint64_t>(); | |
324 | #endif | |
325 | } | |
326 | ||
327 | // test_inserter_and_extractor -----------------------------------------------------// | |
328 | ||
329 | void test_inserter_and_extractor() | |
330 | { | |
331 | std::cout << "test inserter and extractor..." << std::endl; | |
332 | ||
333 | be::big_uint64_t bu64(0x010203040506070ULL); | |
334 | be::little_uint64_t lu64(0x010203040506070ULL); | |
335 | ||
336 | boost::uint64_t x; | |
337 | ||
338 | std::stringstream ss; | |
339 | ||
340 | ss << bu64; | |
341 | ss >> x; | |
342 | BOOST_TEST_EQ(x, 0x010203040506070ULL); | |
343 | ||
344 | ss.clear(); | |
345 | ss << lu64; | |
346 | ss >> x; | |
347 | BOOST_TEST_EQ(x, 0x010203040506070ULL); | |
348 | ||
349 | ss.clear(); | |
350 | ss << 0x010203040506070ULL; | |
351 | be::big_uint64_t bu64z(0); | |
352 | ss >> bu64z; | |
353 | BOOST_TEST_EQ(bu64z, bu64); | |
354 | ||
355 | ss.clear(); | |
356 | ss << 0x010203040506070ULL; | |
357 | be::little_uint64_t lu64z(0); | |
358 | ss >> lu64z; | |
359 | BOOST_TEST_EQ(lu64z, lu64); | |
360 | ||
361 | std::cout << "test inserter and extractor complete" << std::endl; | |
362 | ||
363 | } | |
364 | ||
365 | void f_big_int32_ut(be::big_int32_t) {} | |
366 | ||
367 | // main ------------------------------------------------------------------------------// | |
368 | ||
369 | int cpp_main(int, char * []) | |
370 | { | |
7c673cae FG |
371 | // make sure some simple things work |
372 | ||
373 | be::big_int32_t o1(1); | |
374 | be::big_int32_t o2(2L); | |
375 | be::big_int32_t o3(3LL); | |
376 | be::big_int64_t o4(1); | |
377 | ||
7c673cae FG |
378 | std::clog << "set up test values\n"; |
379 | be::big_int32_t big(12345); | |
380 | be::little_uint16_t little_u(10); | |
381 | be::big_int64_t result; | |
382 | ||
383 | // this is the use case that is so irritating that it caused the endian | |
384 | // constructors to be made non-explicit | |
385 | std::clog << "\nf(1234) where f(big_int32_t)\n"; | |
386 | f_big_int32_ut(1234); | |
387 | ||
388 | std::clog << "\nresult = big\n"; | |
389 | result = big; | |
390 | ||
391 | std::clog << "\nresult = +big\n"; | |
392 | result = +big; | |
393 | ||
394 | std::clog << "\nresult = -big\n"; | |
395 | result = -big; | |
396 | ||
397 | std::clog << "\n++big\n"; | |
398 | ++big; | |
399 | ||
400 | std::clog << "\nresult = big++\n"; | |
401 | result = big++; | |
402 | ||
403 | std::clog << "\n--big\n"; | |
404 | --big; | |
405 | ||
406 | std::clog << "\nbig--\n"; | |
407 | big--; | |
408 | ||
409 | std::clog << "\nresult = big * big\n"; | |
410 | result = big * big; | |
411 | ||
412 | std::clog << "\nresult = big * big\n"; | |
413 | result = big * big; | |
414 | ||
415 | std::clog << "\nresult = big * little_u\n"; | |
416 | result = big * little_u; | |
417 | ||
418 | std::clog << "\nbig *= little_u\n"; | |
419 | big *= little_u; | |
420 | ||
421 | std::clog << "\nresult = little_u * big\n"; | |
422 | result = little_u * big; | |
423 | ||
424 | std::clog << "\nresult = big * 5\n"; | |
425 | result = big * 5; | |
426 | ||
427 | std::clog << "\nbig *= 5\n"; | |
428 | big *= 5; | |
429 | ||
430 | std::clog << "\nresult = 5 * big\n"; | |
431 | result = 5 * big; | |
432 | ||
433 | std::clog << "\nresult = little_u * 5\n"; | |
434 | result = little_u * 5; | |
435 | ||
436 | std::clog << "\nresult = 5 * little_u\n"; | |
437 | result = 5 * little_u; | |
438 | ||
439 | std::clog << "\nresult = 5 * 10\n"; | |
440 | result = 5 * 10; | |
441 | std::clog << "\n"; | |
442 | ||
443 | // test from Roland Schwarz that detected ambiguities; these ambiguities | |
444 | // were eliminated by BOOST_ENDIAN_MINIMAL_COVER_OPERATORS | |
445 | unsigned u; | |
446 | be::little_uint32_t u1; | |
447 | be::little_uint32_t u2; | |
448 | ||
449 | u = 9; | |
450 | u1 = 1; | |
451 | std::clog << "\nu2 = u1 + u\n"; | |
452 | u2 = u1 + u; | |
453 | std::clog << "\n"; | |
454 | ||
455 | // variations to detect ambiguities | |
456 | ||
457 | be::little_uint32_t u3 = u1 + 5; | |
458 | u3 = u1 + 5u; | |
459 | ||
460 | if (u1 == 5) | |
461 | {} | |
462 | if (u1 == 5u) | |
463 | {} | |
464 | ||
465 | u1 += 5; | |
466 | u1 += 5u; | |
467 | ||
468 | u2 = u1 + 5; | |
469 | u2 = u1 + 5u; | |
470 | ||
471 | // one more wrinkle | |
472 | be::little_uint16_t u4(3); | |
473 | u4 = 3; | |
474 | std::clog << "\nu2 = u1 + u4\n"; | |
475 | u2 = u1 + u4; | |
476 | std::clog << "\n"; | |
477 | ||
7c673cae | 478 | test_inserter_and_extractor(); |
11fdf7f2 | 479 | |
7c673cae FG |
480 | // perform the indicated test on ~60*60 operand types |
481 | ||
482 | op_test<default_construct>(); | |
483 | op_test<construct>(); // includes copy construction | |
484 | op_test<initialize>(); | |
485 | op_test<assign>(); | |
486 | op_test<relational>(); | |
487 | op_test<op_plus>(); | |
488 | op_test<op_star>(); | |
489 | ||
490 | return boost::report_errors(); | |
491 | } |