1 // Copyright 2019 Peter Dimov
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5
6 #if defined(_MSC_VER)
7 # pragma warning( disable: 4309 ) // static_cast: truncation of constant value
8 #endif
9
10 #include <boost/endian/conversion.hpp>
11 #include <boost/core/lightweight_test.hpp>
12 #include <boost/config.hpp>
13 #include <cstddef>
14
15 template<class T, std::size_t N = sizeof(T)> struct test_value
16 {
17 };
18
19 template<class T> struct test_value<T, 1>
20 {
21 static const T v1 = static_cast<T>( 0x1F );
22 static const T w1 = static_cast<T>( 0x1F );
23
24 static const T v2 = static_cast<T>( 0xF1 );
25 static const T w2 = static_cast<T>( 0xF1 );
26 };
27
28 template<class T> T const test_value<T, 1>::v1;
29 template<class T> T const test_value<T, 1>::w1;
30 template<class T> T const test_value<T, 1>::v2;
31 template<class T> T const test_value<T, 1>::w2;
32
33 template<class T> struct test_value<T, 2>
34 {
35 static const T v1 = static_cast<T>( 0x1F2E );
36 static const T w1 = static_cast<T>( 0x2E1F );
37
38 static const T v2 = static_cast<T>( 0xF1E2 );
39 static const T w2 = static_cast<T>( 0xE2F1 );
40 };
41
42 template<class T> T const test_value<T, 2>::v1;
43 template<class T> T const test_value<T, 2>::w1;
44 template<class T> T const test_value<T, 2>::v2;
45 template<class T> T const test_value<T, 2>::w2;
46
47 template<class T> struct test_value<T, 4>
48 {
49 static const T v1 = static_cast<T>( 0x1F2E3D4C );
50 static const T w1 = static_cast<T>( 0x4C3D2E1F );
51
52 static const T v2 = static_cast<T>( 0xF1E2D3C4 );
53 static const T w2 = static_cast<T>( 0xC4D3E2F1 );
54 };
55
56 template<class T> T const test_value<T, 4>::v1;
57 template<class T> T const test_value<T, 4>::w1;
58 template<class T> T const test_value<T, 4>::v2;
59 template<class T> T const test_value<T, 4>::w2;
60
61 template<class T> struct test_value<T, 8>
62 {
63 static const T v1 = static_cast<T>( 0x1F2E3D4C5B6A7988ull );
64 static const T w1 = static_cast<T>( 0x88796A5B4C3D2E1Full );
65
66 static const T v2 = static_cast<T>( 0xF1E2D3C4B5A69788ull );
67 static const T w2 = static_cast<T>( 0x8897A6B5C4D3E2F1ull );
68 };
69
70 template<class T> T const test_value<T, 8>::v1;
71 template<class T> T const test_value<T, 8>::w1;
72 template<class T> T const test_value<T, 8>::v2;
73 template<class T> T const test_value<T, 8>::w2;
74
75 #if defined(BOOST_HAS_INT128)
76
77 template<class T> struct test_value<T, 16>
78 {
79 static const T v1 = static_cast<T>( 0x1F2E3D4C5B6A7988ull ) << 64 | static_cast<T>( 0xF1E2D3C4B5A69780ull );
80 static const T w1 = static_cast<T>( 0x8097A6B5C4D3E2F1ull ) << 64 | static_cast<T>( 0x88796A5B4C3D2E1Full );
81
82 static const T v2 = static_cast<T>( 0xF1E2D3C4B5A69788ull ) << 64 | static_cast<T>( 0x1F2E3D4C5B6A7980ull );
83 static const T w2 = static_cast<T>( 0x80796A5B4C3D2E1Full ) << 64 | static_cast<T>( 0x8897A6B5C4D3E2F1ull );
84 };
85
86 template<class T> T const test_value<T, 16>::v1;
87 template<class T> T const test_value<T, 16>::w1;
88 template<class T> T const test_value<T, 16>::v2;
89 template<class T> T const test_value<T, 16>::w2;
90
91 #endif // #if defined(BOOST_HAS_INT128)
92
test()93 template<class T> void test()
94 {
95 using boost::endian::endian_reverse;
96 using boost::endian::endian_reverse_inplace;
97
98 {
99 T t1 = test_value<T>::v1;
100
101 T t2 = endian_reverse( t1 );
102 BOOST_TEST_EQ( t2, test_value<T>::w1 );
103
104 T t3 = endian_reverse( t2 );
105 BOOST_TEST_EQ( t3, t1 );
106
107 T t4 = t1;
108
109 endian_reverse_inplace( t4 );
110 BOOST_TEST_EQ( t4, test_value<T>::w1 );
111
112 endian_reverse_inplace( t4 );
113 BOOST_TEST_EQ( t4, t1 );
114 }
115
116 {
117 T t1 = test_value<T>::v2;
118
119 T t2 = endian_reverse( t1 );
120 BOOST_TEST_EQ( t2, test_value<T>::w2 );
121
122 T t3 = endian_reverse( t2 );
123 BOOST_TEST_EQ( t3, t1 );
124
125 T t4 = t1;
126
127 endian_reverse_inplace( t4 );
128 BOOST_TEST_EQ( t4, test_value<T>::w2 );
129
130 endian_reverse_inplace( t4 );
131 BOOST_TEST_EQ( t4, t1 );
132 }
133 }
134
test_np()135 template<class T> void test_np()
136 {
137 using boost::endian::endian_reverse;
138 using boost::endian::endian_reverse_inplace;
139
140 {
141 T t1 = test_value<T>::v1;
142
143 T t2 = endian_reverse( t1 );
144 BOOST_TEST( t2 == test_value<T>::w1 );
145
146 T t3 = endian_reverse( t2 );
147 BOOST_TEST( t3 == t1 );
148
149 T t4 = t1;
150
151 endian_reverse_inplace( t4 );
152 BOOST_TEST( t4 == test_value<T>::w1 );
153
154 endian_reverse_inplace( t4 );
155 BOOST_TEST( t4 == t1 );
156 }
157
158 {
159 T t1 = test_value<T>::v2;
160
161 T t2 = endian_reverse( t1 );
162 BOOST_TEST( t2 == test_value<T>::w2 );
163
164 T t3 = endian_reverse( t2 );
165 BOOST_TEST( t3 == t1 );
166
167 T t4 = t1;
168
169 endian_reverse_inplace( t4 );
170 BOOST_TEST( t4 == test_value<T>::w2 );
171
172 endian_reverse_inplace( t4 );
173 BOOST_TEST( t4 == t1 );
174 }
175 }
176
main()177 int main()
178 {
179 test<boost::int8_t>();
180 test<boost::uint8_t>();
181
182 test<boost::int16_t>();
183 test<boost::uint16_t>();
184
185 test<boost::int32_t>();
186 test<boost::uint32_t>();
187
188 test<boost::int64_t>();
189 test<boost::uint64_t>();
190
191 test<char>();
192 test<unsigned char>();
193 test<signed char>();
194
195 test<short>();
196 test<unsigned short>();
197
198 test<int>();
199 test<unsigned int>();
200
201 test<long>();
202 test<unsigned long>();
203
204 test<long long>();
205 test<unsigned long long>();
206
207 #if !defined(BOOST_NO_CXX11_CHAR16_T)
208 test<char16_t>();
209 #endif
210
211 #if !defined(BOOST_NO_CXX11_CHAR32_T)
212 test<char32_t>();
213 #endif
214
215 #if defined(BOOST_HAS_INT128)
216
217 test_np<boost::int128_type>();
218 test_np<boost::uint128_type>();
219
220 #endif
221
222 return boost::report_errors();
223 }
224