]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Unit test for boost::lexical_cast. |
2 | // | |
3 | // See http://www.boost.org for most recent version, including documentation. | |
4 | // | |
5 | // Copyright Terje Sletteb and Kevlin Henney, 2005. | |
6 | // Copyright Alexander Nasonov, 2006. | |
92f5a8d4 | 7 | // Copyright Antony Polukhin, 2011-2019. |
7c673cae FG |
8 | // |
9 | // Distributed under the Boost | |
10 | // Software License, Version 1.0. (See accompanying file | |
11 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). | |
12 | // | |
13 | // Note: The unit test no longer compile on MSVC 6, but lexical_cast itself works for it. | |
14 | ||
15 | // | |
16 | // We need this #define before any #includes: otherwise msvc will emit warnings | |
17 | // deep within std::string, resulting from our (perfectly legal) use of basic_string | |
18 | // with a custom traits class: | |
19 | // | |
20 | #define _SCL_SECURE_NO_WARNINGS | |
21 | ||
22 | #include <boost/config.hpp> | |
23 | ||
24 | #if defined(__INTEL_COMPILER) | |
25 | #pragma warning(disable: 193 383 488 981 1418 1419) | |
26 | #elif defined(BOOST_MSVC) | |
27 | #pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) | |
28 | #endif | |
29 | ||
30 | #include <boost/lexical_cast.hpp> | |
31 | ||
32 | #include <boost/cstdint.hpp> | |
33 | #include <boost/test/unit_test.hpp> | |
34 | #include <boost/test/floating_point_comparison.hpp> | |
35 | ||
36 | #include <boost/type_traits/integral_promotion.hpp> | |
37 | #include <string> | |
38 | #include <vector> | |
39 | #include <algorithm> // std::transform | |
40 | #include <memory> | |
41 | ||
42 | #if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \ | |
43 | && !(defined(BOOST_MSVC) && BOOST_MSVC < 1300) | |
44 | #define LCAST_TEST_LONGLONG | |
45 | #endif | |
46 | ||
47 | #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) | |
48 | #define BOOST_LCAST_NO_WCHAR_T | |
49 | #endif | |
50 | ||
51 | template<class CharT> | |
52 | struct my_traits : std::char_traits<CharT> | |
53 | { | |
54 | }; | |
55 | ||
56 | template<class CharT> | |
57 | struct my_allocator : std::allocator<CharT> | |
58 | { | |
59 | typedef std::allocator<CharT> base_t; | |
60 | ||
61 | my_allocator(){} | |
62 | template <class U> my_allocator(const my_allocator<U>& v) : base_t(v) {} | |
63 | ||
64 | template <class U> struct rebind { typedef my_allocator<U> other; }; | |
65 | }; | |
66 | ||
67 | using namespace boost; | |
68 | ||
69 | void test_conversion_to_char(); | |
70 | void test_conversion_to_int(); | |
71 | void test_conversion_to_double(); | |
72 | void test_conversion_to_bool(); | |
73 | void test_conversion_with_nonconst_char(); | |
74 | void test_conversion_to_string(); | |
75 | void test_conversion_from_to_wchar_t_alias(); | |
76 | void test_conversion_from_wchar_t(); | |
77 | void test_conversion_to_wchar_t(); | |
78 | void test_conversion_from_wstring(); | |
79 | void test_conversion_to_wstring(); | |
80 | void test_bad_lexical_cast(); | |
81 | void test_no_whitespace_stripping(); | |
82 | void test_volatile_types_conversions(); | |
83 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
84 | void test_traits(); | |
85 | void test_wtraits(); | |
86 | void test_allocator(); | |
87 | void test_wallocator(); | |
88 | #endif | |
89 | void test_char_types_conversions(); | |
90 | void operators_overload_test(); | |
91 | #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) | |
92 | void test_char16_conversions(); | |
93 | #endif | |
94 | #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) | |
95 | void test_char32_conversions(); | |
96 | #endif | |
97 | void test_getting_pointer_to_function(); | |
98 | ||
99 | unit_test::test_suite *init_unit_test_suite(int, char *[]) | |
100 | { | |
101 | unit_test::test_suite *suite = | |
102 | BOOST_TEST_SUITE("lexical_cast unit test"); | |
103 | suite->add(BOOST_TEST_CASE(test_conversion_to_char)); | |
104 | suite->add(BOOST_TEST_CASE(test_conversion_to_int)); | |
105 | suite->add(BOOST_TEST_CASE(test_conversion_to_double)); | |
106 | suite->add(BOOST_TEST_CASE(test_conversion_to_bool)); | |
107 | suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias)); | |
108 | suite->add(BOOST_TEST_CASE(test_conversion_to_string)); | |
109 | suite->add(BOOST_TEST_CASE(test_conversion_with_nonconst_char)); | |
110 | #ifndef BOOST_LCAST_NO_WCHAR_T | |
111 | suite->add(BOOST_TEST_CASE(test_conversion_from_wchar_t)); | |
112 | suite->add(BOOST_TEST_CASE(test_conversion_to_wchar_t)); | |
113 | suite->add(BOOST_TEST_CASE(test_conversion_from_wstring)); | |
114 | suite->add(BOOST_TEST_CASE(test_conversion_to_wstring)); | |
115 | #endif | |
116 | suite->add(BOOST_TEST_CASE(test_bad_lexical_cast)); | |
117 | suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping)); | |
118 | suite->add(BOOST_TEST_CASE(test_volatile_types_conversions)); | |
119 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
120 | suite->add(BOOST_TEST_CASE(&test_traits)); | |
121 | suite->add(BOOST_TEST_CASE(&test_wtraits)); | |
122 | suite->add(BOOST_TEST_CASE(&test_allocator)); | |
123 | suite->add(BOOST_TEST_CASE(&test_wallocator)); | |
124 | #endif | |
125 | ||
126 | suite->add(BOOST_TEST_CASE(&test_char_types_conversions)); | |
127 | suite->add(BOOST_TEST_CASE(&operators_overload_test)); | |
128 | #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) | |
129 | suite->add(BOOST_TEST_CASE(&test_char16_conversions)); | |
130 | #endif | |
131 | #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) | |
132 | suite->add(BOOST_TEST_CASE(&test_char32_conversions)); | |
133 | #endif | |
134 | suite->add(BOOST_TEST_CASE(&test_getting_pointer_to_function)); | |
135 | ||
136 | return suite; | |
137 | } | |
138 | ||
139 | void test_conversion_to_char() | |
140 | { | |
141 | BOOST_CHECK_EQUAL('A', lexical_cast<char>('A')); | |
142 | BOOST_CHECK_EQUAL(' ', lexical_cast<char>(' ')); | |
143 | BOOST_CHECK_EQUAL('1', lexical_cast<char>(1)); | |
144 | BOOST_CHECK_EQUAL('0', lexical_cast<char>(0)); | |
145 | BOOST_CHECK_THROW(lexical_cast<char>(123), bad_lexical_cast); | |
146 | BOOST_CHECK_EQUAL('1', lexical_cast<char>(1.0)); | |
147 | BOOST_CHECK_EQUAL('1', lexical_cast<char>(true)); | |
148 | BOOST_CHECK_EQUAL('0', lexical_cast<char>(false)); | |
149 | BOOST_CHECK_EQUAL('A', lexical_cast<char>("A")); | |
150 | BOOST_CHECK_EQUAL(' ', lexical_cast<char>(" ")); | |
151 | BOOST_CHECK_THROW(lexical_cast<char>(""), bad_lexical_cast); | |
152 | BOOST_CHECK_THROW(lexical_cast<char>("Test"), bad_lexical_cast); | |
153 | BOOST_CHECK_EQUAL('A', lexical_cast<char>(std::string("A"))); | |
154 | BOOST_CHECK_EQUAL(' ', lexical_cast<char>(std::string(" "))); | |
155 | BOOST_CHECK_THROW( | |
156 | lexical_cast<char>(std::string("")), bad_lexical_cast); | |
157 | BOOST_CHECK_THROW( | |
158 | lexical_cast<char>(std::string("Test")), bad_lexical_cast); | |
159 | } | |
160 | ||
161 | void test_conversion_to_int() | |
162 | { | |
163 | BOOST_CHECK_EQUAL(1, lexical_cast<int>('1')); | |
164 | BOOST_CHECK_EQUAL(0, lexical_cast<int>('0')); | |
165 | BOOST_CHECK_THROW(lexical_cast<int>('A'), bad_lexical_cast); | |
166 | BOOST_CHECK_EQUAL(1, lexical_cast<int>(1)); | |
167 | BOOST_CHECK_EQUAL(1, lexical_cast<int>(1.0)); | |
168 | ||
169 | BOOST_CHECK_EQUAL( | |
170 | (std::numeric_limits<int>::max)(), | |
171 | lexical_cast<int>((std::numeric_limits<int>::max)())); | |
172 | ||
173 | BOOST_CHECK_EQUAL( | |
174 | (std::numeric_limits<int>::min)(), | |
175 | lexical_cast<int>((std::numeric_limits<int>::min)())); | |
176 | ||
177 | BOOST_CHECK_THROW(lexical_cast<int>(1.23), bad_lexical_cast); | |
178 | ||
179 | BOOST_CHECK_THROW(lexical_cast<int>(1e20), bad_lexical_cast); | |
180 | BOOST_CHECK_EQUAL(1, lexical_cast<int>(true)); | |
181 | BOOST_CHECK_EQUAL(0, lexical_cast<int>(false)); | |
182 | BOOST_CHECK_EQUAL(123, lexical_cast<int>("123")); | |
183 | BOOST_CHECK_THROW( | |
184 | lexical_cast<int>(" 123"), bad_lexical_cast); | |
185 | BOOST_CHECK_THROW(lexical_cast<int>(""), bad_lexical_cast); | |
186 | BOOST_CHECK_THROW(lexical_cast<int>("Test"), bad_lexical_cast); | |
187 | BOOST_CHECK_EQUAL(123, lexical_cast<int>("123")); | |
188 | BOOST_CHECK_EQUAL(123, lexical_cast<int>(std::string("123"))); | |
189 | BOOST_CHECK_THROW( | |
190 | lexical_cast<int>(std::string(" 123")), bad_lexical_cast); | |
191 | BOOST_CHECK_THROW( | |
192 | lexical_cast<int>(std::string("")), bad_lexical_cast); | |
193 | BOOST_CHECK_THROW( | |
194 | lexical_cast<int>(std::string("Test")), bad_lexical_cast); | |
195 | } | |
196 | ||
197 | void test_conversion_with_nonconst_char() | |
198 | { | |
199 | std::vector<char> buffer; | |
200 | buffer.push_back('1'); | |
201 | buffer.push_back('\0'); | |
202 | BOOST_CHECK_EQUAL(boost::lexical_cast<int>(&buffer[0]), 1); | |
203 | ||
204 | std::vector<unsigned char> buffer2; | |
205 | buffer2.push_back('1'); | |
206 | buffer2.push_back('\0'); | |
207 | BOOST_CHECK_EQUAL(boost::lexical_cast<int>(&buffer2[0]), 1); | |
208 | ||
209 | std::vector<unsigned char> buffer3; | |
210 | buffer3.push_back('1'); | |
211 | buffer3.push_back('\0'); | |
212 | BOOST_CHECK_EQUAL(boost::lexical_cast<int>(&buffer3[0]), 1); | |
213 | ||
214 | #ifndef BOOST_LCAST_NO_WCHAR_T | |
215 | std::vector<wchar_t> buffer4; | |
216 | buffer4.push_back(L'1'); | |
217 | buffer4.push_back(L'\0'); | |
218 | BOOST_CHECK_EQUAL(boost::lexical_cast<int>(&buffer4[0]), 1); | |
219 | #endif | |
220 | } | |
221 | ||
222 | void test_conversion_to_double() | |
223 | { | |
224 | BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<double>('1'), (std::numeric_limits<double>::epsilon())); | |
225 | BOOST_CHECK_THROW(lexical_cast<double>('A'), bad_lexical_cast); | |
226 | BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<double>(1), (std::numeric_limits<double>::epsilon())); | |
227 | BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast<double>(1.23), (std::numeric_limits<double>::epsilon())); | |
228 | BOOST_CHECK_CLOSE_FRACTION(1.234567890, lexical_cast<double>(1.234567890), std::numeric_limits<double>::epsilon()); | |
229 | BOOST_CHECK_CLOSE_FRACTION(1.234567890, lexical_cast<double>("1.234567890"), std::numeric_limits<double>::epsilon()); | |
230 | BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<double>(true), (std::numeric_limits<double>::epsilon())); | |
231 | BOOST_CHECK_CLOSE_FRACTION(0.0, lexical_cast<double>(false), (std::numeric_limits<double>::epsilon())); | |
232 | BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast<double>("1.23"), (std::numeric_limits<double>::epsilon())); | |
233 | BOOST_CHECK_THROW(lexical_cast<double>(""), bad_lexical_cast); | |
234 | BOOST_CHECK_THROW(lexical_cast<double>("Test"), bad_lexical_cast); | |
235 | BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast<double>(std::string("1.23")), (std::numeric_limits<double>::epsilon())); | |
236 | BOOST_CHECK_THROW( | |
237 | lexical_cast<double>(std::string("")), bad_lexical_cast); | |
238 | BOOST_CHECK_THROW( | |
239 | lexical_cast<double>(std::string("Test")), bad_lexical_cast); | |
240 | } | |
241 | ||
242 | void test_conversion_to_bool() | |
243 | { | |
244 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>('1')); | |
245 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>('0')); | |
246 | BOOST_CHECK_THROW(lexical_cast<bool>('A'), bad_lexical_cast); | |
247 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>(1)); | |
248 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>(0)); | |
249 | BOOST_CHECK_THROW(lexical_cast<bool>(123), bad_lexical_cast); | |
250 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>(1.0)); | |
251 | BOOST_CHECK_THROW(lexical_cast<bool>(-123), bad_lexical_cast); | |
252 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>(0.0)); | |
253 | BOOST_CHECK_THROW(lexical_cast<bool>(1234), bad_lexical_cast); | |
254 | #if !defined(_CRAYC) | |
255 | // Looks like a bug in CRAY compiler (throws bad_lexical_cast) | |
256 | // TODO: localize the bug and report it to developers. | |
257 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>(true)); | |
258 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>(false)); | |
259 | #endif | |
260 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>("1")); | |
261 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>("0")); | |
262 | BOOST_CHECK_THROW(lexical_cast<bool>(""), bad_lexical_cast); | |
263 | BOOST_CHECK_THROW(lexical_cast<bool>("Test"), bad_lexical_cast); | |
264 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>("1")); | |
265 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>("0")); | |
266 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>(std::string("1"))); | |
267 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>(std::string("0"))); | |
268 | ||
269 | BOOST_CHECK_THROW(lexical_cast<bool>(1.0001L), bad_lexical_cast); | |
270 | BOOST_CHECK_THROW(lexical_cast<bool>(2), bad_lexical_cast); | |
271 | BOOST_CHECK_THROW(lexical_cast<bool>(2u), bad_lexical_cast); | |
272 | BOOST_CHECK_THROW(lexical_cast<bool>(-1), bad_lexical_cast); | |
273 | BOOST_CHECK_THROW(lexical_cast<bool>(-2), bad_lexical_cast); | |
274 | ||
275 | ||
276 | BOOST_CHECK_THROW( | |
277 | lexical_cast<bool>(std::string("")), bad_lexical_cast); | |
278 | BOOST_CHECK_THROW( | |
279 | lexical_cast<bool>(std::string("Test")), bad_lexical_cast); | |
280 | ||
281 | BOOST_CHECK(lexical_cast<bool>("+1") == true); | |
282 | BOOST_CHECK(lexical_cast<bool>("+0") == false); | |
283 | BOOST_CHECK(lexical_cast<bool>("-0") == false); | |
284 | BOOST_CHECK_THROW(lexical_cast<bool>("--0"), bad_lexical_cast); | |
285 | BOOST_CHECK_THROW(lexical_cast<bool>("-+-0"), bad_lexical_cast); | |
286 | ||
287 | BOOST_CHECK(lexical_cast<bool>("0") == false); | |
288 | BOOST_CHECK(lexical_cast<bool>("1") == true); | |
289 | BOOST_CHECK(lexical_cast<bool>("00") == false); | |
290 | BOOST_CHECK(lexical_cast<bool>("00000000000") == false); | |
291 | BOOST_CHECK(lexical_cast<bool>("000000000001") == true); | |
292 | BOOST_CHECK(lexical_cast<bool>("+00") == false ); | |
293 | BOOST_CHECK(lexical_cast<bool>("-00") == false ); | |
294 | BOOST_CHECK(lexical_cast<bool>("+00000000001") == true ); | |
295 | ||
296 | BOOST_CHECK_THROW(lexical_cast<bool>("020"), bad_lexical_cast); | |
297 | BOOST_CHECK_THROW(lexical_cast<bool>("00200"), bad_lexical_cast); | |
298 | BOOST_CHECK_THROW(lexical_cast<bool>("-00200"), bad_lexical_cast); | |
299 | BOOST_CHECK_THROW(lexical_cast<bool>("+00200"), bad_lexical_cast); | |
300 | BOOST_CHECK_THROW(lexical_cast<bool>("000000000002"), bad_lexical_cast); | |
301 | BOOST_CHECK_THROW(lexical_cast<bool>("-1"), bad_lexical_cast); | |
302 | BOOST_CHECK_THROW(lexical_cast<bool>("-0000000001"), bad_lexical_cast); | |
303 | BOOST_CHECK_THROW(lexical_cast<bool>("00000000011"), bad_lexical_cast); | |
304 | BOOST_CHECK_THROW(lexical_cast<bool>("001001"), bad_lexical_cast); | |
305 | BOOST_CHECK_THROW(lexical_cast<bool>("-00000000010"), bad_lexical_cast); | |
306 | BOOST_CHECK_THROW(lexical_cast<bool>("-000000000100"), bad_lexical_cast); | |
307 | } | |
308 | ||
309 | void test_conversion_to_string() | |
310 | { | |
311 | char buf[] = "hello"; | |
312 | char* str = buf; | |
313 | BOOST_CHECK_EQUAL(str, lexical_cast<std::string>(str)); | |
314 | BOOST_CHECK_EQUAL("A", lexical_cast<std::string>('A')); | |
315 | BOOST_CHECK_EQUAL(" ", lexical_cast<std::string>(' ')); | |
316 | BOOST_CHECK_EQUAL("123", lexical_cast<std::string>(123)); | |
317 | BOOST_CHECK_EQUAL("1.23", lexical_cast<std::string>(1.23)); | |
318 | BOOST_CHECK_EQUAL("1.111111111", lexical_cast<std::string>(1.111111111)); | |
319 | BOOST_CHECK_EQUAL("1", lexical_cast<std::string>(true)); | |
320 | BOOST_CHECK_EQUAL("0", lexical_cast<std::string>(false)); | |
321 | BOOST_CHECK_EQUAL("Test", lexical_cast<std::string>("Test")); | |
322 | BOOST_CHECK_EQUAL(" ", lexical_cast<std::string>(" ")); | |
323 | BOOST_CHECK_EQUAL("", lexical_cast<std::string>("")); | |
324 | BOOST_CHECK_EQUAL("Test", lexical_cast<std::string>(std::string("Test"))); | |
325 | BOOST_CHECK_EQUAL(" ", lexical_cast<std::string>(std::string(" "))); | |
326 | BOOST_CHECK_EQUAL("", lexical_cast<std::string>(std::string(""))); | |
327 | } | |
328 | ||
329 | void test_conversion_from_to_wchar_t_alias() | |
330 | { | |
331 | BOOST_CHECK_EQUAL(123u, lexical_cast<unsigned short>("123")); | |
332 | BOOST_CHECK_EQUAL(123u, lexical_cast<unsigned int>("123")); | |
333 | BOOST_CHECK_EQUAL(123u, lexical_cast<unsigned long>("123")); | |
334 | BOOST_CHECK_EQUAL(std::string("123"), | |
335 | lexical_cast<std::string>(static_cast<unsigned short>(123))); | |
336 | BOOST_CHECK_EQUAL(std::string("123"), lexical_cast<std::string>(123u)); | |
337 | BOOST_CHECK_EQUAL(std::string("123"), lexical_cast<std::string>(123ul)); | |
338 | } | |
339 | ||
340 | void test_conversion_from_wchar_t() | |
341 | { | |
342 | #ifndef BOOST_LCAST_NO_WCHAR_T | |
343 | #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) | |
344 | BOOST_CHECK_EQUAL(1, lexical_cast<int>(L'1')); | |
345 | BOOST_CHECK_THROW(lexical_cast<int>(L'A'), bad_lexical_cast); | |
346 | #endif | |
347 | ||
348 | BOOST_CHECK_EQUAL(123, lexical_cast<int>(L"123")); | |
349 | BOOST_CHECK_THROW(lexical_cast<int>(L""), bad_lexical_cast); | |
350 | BOOST_CHECK_THROW(lexical_cast<int>(L"Test"), bad_lexical_cast); | |
351 | ||
352 | #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) | |
353 | BOOST_CHECK_EQUAL(1.0, lexical_cast<double>(L'1')); | |
354 | BOOST_CHECK_THROW(lexical_cast<double>(L'A'), bad_lexical_cast); | |
355 | #endif | |
356 | ||
357 | BOOST_CHECK_EQUAL(1.23, lexical_cast<double>(L"1.23")); | |
358 | BOOST_CHECK_THROW(lexical_cast<double>(L""), bad_lexical_cast); | |
359 | BOOST_CHECK_THROW(lexical_cast<double>(L"Test"), bad_lexical_cast); | |
360 | ||
361 | #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) | |
362 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>(L'1')); | |
363 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>(L'0')); | |
364 | BOOST_CHECK_THROW(lexical_cast<bool>(L'A'), bad_lexical_cast); | |
365 | #endif | |
366 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>(L"1")); | |
367 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>(L"0")); | |
368 | BOOST_CHECK_THROW(lexical_cast<bool>(L""), bad_lexical_cast); | |
369 | BOOST_CHECK_THROW(lexical_cast<bool>(L"Test"), bad_lexical_cast); | |
370 | #endif | |
371 | } | |
372 | ||
373 | void test_conversion_to_wchar_t() | |
374 | { | |
375 | #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) | |
376 | BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(1)); | |
377 | BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(0)); | |
378 | BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>('1')); | |
379 | BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>('0')); | |
380 | BOOST_CHECK_THROW(lexical_cast<wchar_t>(123), bad_lexical_cast); | |
381 | BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(1.0)); | |
382 | BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(0.0)); | |
383 | BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(true)); | |
384 | BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(false)); | |
385 | BOOST_CHECK_EQUAL(L'A', lexical_cast<wchar_t>(L'A')); | |
386 | BOOST_CHECK_EQUAL(L' ', lexical_cast<wchar_t>(L' ')); | |
387 | BOOST_CHECK_EQUAL(L'A', lexical_cast<wchar_t>(L"A")); | |
388 | BOOST_CHECK_EQUAL(L' ', lexical_cast<wchar_t>(L" ")); | |
389 | BOOST_CHECK_THROW(lexical_cast<wchar_t>(L""), bad_lexical_cast); | |
390 | BOOST_CHECK_THROW(lexical_cast<wchar_t>(L"Test"), bad_lexical_cast); | |
391 | BOOST_CHECK_EQUAL(L'A', lexical_cast<wchar_t>(std::wstring(L"A"))); | |
392 | BOOST_CHECK_EQUAL(L' ', lexical_cast<wchar_t>(std::wstring(L" "))); | |
393 | BOOST_CHECK_THROW( | |
394 | lexical_cast<wchar_t>(std::wstring(L"")), bad_lexical_cast); | |
395 | BOOST_CHECK_THROW( | |
396 | lexical_cast<wchar_t>(std::wstring(L"Test")), bad_lexical_cast); | |
397 | #endif | |
398 | BOOST_CHECK(true); | |
399 | } | |
400 | ||
401 | void test_conversion_from_wstring() | |
402 | { | |
403 | #ifndef BOOST_LCAST_NO_WCHAR_T | |
404 | BOOST_CHECK_EQUAL(123, lexical_cast<int>(std::wstring(L"123"))); | |
405 | BOOST_CHECK_THROW( | |
406 | lexical_cast<int>(std::wstring(L"")), bad_lexical_cast); | |
407 | BOOST_CHECK_THROW( | |
408 | lexical_cast<int>(std::wstring(L"Test")), bad_lexical_cast); | |
409 | ||
410 | BOOST_CHECK_EQUAL(true, lexical_cast<bool>(std::wstring(L"1"))); | |
411 | BOOST_CHECK_EQUAL(false, lexical_cast<bool>(std::wstring(L"0"))); | |
412 | BOOST_CHECK_THROW( | |
413 | lexical_cast<bool>(std::wstring(L"")), bad_lexical_cast); | |
414 | BOOST_CHECK_THROW( | |
415 | lexical_cast<bool>(std::wstring(L"Test")), bad_lexical_cast); | |
416 | #endif | |
417 | BOOST_CHECK(true); | |
418 | } | |
419 | ||
420 | void test_conversion_to_wstring() | |
421 | { | |
422 | #ifndef BOOST_LCAST_NO_WCHAR_T | |
423 | wchar_t buf[] = L"hello"; | |
424 | wchar_t* str = buf; | |
425 | BOOST_CHECK(str == lexical_cast<std::wstring>(str)); | |
426 | BOOST_CHECK(L"123" == lexical_cast<std::wstring>(123)); | |
427 | BOOST_CHECK(L"1.23" == lexical_cast<std::wstring>(1.23)); | |
428 | BOOST_CHECK(L"1" == lexical_cast<std::wstring>(true)); | |
429 | BOOST_CHECK(L"0" == lexical_cast<std::wstring>(false)); | |
430 | #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) | |
431 | BOOST_CHECK(L"A" == lexical_cast<std::wstring>(L'A')); | |
432 | BOOST_CHECK(L" " == lexical_cast<std::wstring>(L' ')); | |
433 | BOOST_CHECK(L"A" == lexical_cast<std::wstring>('A')); | |
434 | #endif | |
435 | BOOST_CHECK(L"Test" == lexical_cast<std::wstring>(L"Test")); | |
436 | BOOST_CHECK(L" " == lexical_cast<std::wstring>(L" ")); | |
437 | BOOST_CHECK(L"" == lexical_cast<std::wstring>(L"")); | |
438 | BOOST_CHECK(L"Test" == lexical_cast<std::wstring>(std::wstring(L"Test"))); | |
439 | BOOST_CHECK(L" " == lexical_cast<std::wstring>(std::wstring(L" "))); | |
440 | BOOST_CHECK(L"" == lexical_cast<std::wstring>(std::wstring(L""))); | |
441 | #endif | |
442 | BOOST_CHECK(true); | |
443 | } | |
444 | ||
445 | void test_bad_lexical_cast() | |
446 | { | |
447 | try | |
448 | { | |
449 | lexical_cast<int>(std::string("Test")); | |
450 | ||
451 | BOOST_CHECK(false); // Exception expected | |
452 | } | |
453 | catch(const bad_lexical_cast &e) | |
454 | { | |
455 | BOOST_CHECK(e.source_type() == typeid(std::string)); | |
456 | BOOST_CHECK(e.target_type() == typeid(int)); | |
457 | } | |
458 | } | |
459 | ||
460 | void test_no_whitespace_stripping() | |
461 | { | |
462 | BOOST_CHECK_THROW(lexical_cast<int>(" 123"), bad_lexical_cast); | |
463 | BOOST_CHECK_THROW(lexical_cast<int>("123 "), bad_lexical_cast); | |
464 | } | |
465 | ||
466 | void test_volatile_types_conversions() | |
467 | { | |
468 | volatile int i1 = 100000; | |
469 | BOOST_CHECK_EQUAL("100000", boost::lexical_cast<std::string>(i1)); | |
470 | ||
471 | volatile const int i2 = 100000; | |
472 | BOOST_CHECK_EQUAL("100000", boost::lexical_cast<std::string>(i2)); | |
473 | ||
474 | volatile const long int i3 = 1000000; | |
475 | BOOST_CHECK_EQUAL("1000000", boost::lexical_cast<std::string>(i3)); | |
476 | } | |
477 | ||
478 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
479 | void test_traits() | |
480 | { | |
481 | typedef std::basic_string<char, my_traits<char> > my_string; | |
482 | ||
483 | my_string const s("s"); | |
484 | BOOST_CHECK(boost::lexical_cast<char>(s) == s[0]); | |
485 | BOOST_CHECK(boost::lexical_cast<my_string>(s) == s); | |
486 | BOOST_CHECK(boost::lexical_cast<my_string>(-1) == "-1"); | |
487 | } | |
488 | ||
489 | void test_wtraits() | |
490 | { | |
491 | typedef std::basic_string<wchar_t, my_traits<wchar_t> > my_string; | |
492 | ||
493 | my_string const s(L"s"); | |
494 | BOOST_CHECK(boost::lexical_cast<wchar_t>(s) == s[0]); | |
495 | BOOST_CHECK(boost::lexical_cast<my_string>(s) == s); | |
496 | //BOOST_CHECK(boost::lexical_cast<my_string>(-1) == L"-1"); | |
497 | // Commented out because gcc 3.3 doesn't support this: | |
498 | // basic_ostream<wchar_t, my_traits<wchar_t> > o; o << -1; | |
499 | } | |
500 | ||
501 | void test_allocator() | |
502 | { | |
503 | // Following test cause compilation error on MSVC2012: | |
504 | // (Reason: cannot convert from 'std::_Wrap_alloc<_Alloc>' to 'const my_allocator<CharT>') | |
505 | // | |
506 | // MSVC developer is notified about this issue | |
507 | #if !defined(_MSC_VER) || (_MSC_VER < 1700) | |
508 | typedef std::basic_string< char | |
509 | , std::char_traits<char> | |
510 | , my_allocator<char> | |
511 | > my_string; | |
512 | ||
513 | my_string s("s"); | |
514 | BOOST_CHECK(boost::lexical_cast<char>(s) == s[0]); | |
515 | BOOST_CHECK(boost::lexical_cast<std::string>(s) == "s"); | |
516 | BOOST_CHECK(boost::lexical_cast<my_string>(s) == s); | |
517 | BOOST_CHECK(boost::lexical_cast<my_string>(1) == "1"); | |
518 | BOOST_CHECK(boost::lexical_cast<my_string>("s") == s); | |
519 | BOOST_CHECK(boost::lexical_cast<my_string>(std::string("s")) == s); | |
520 | #endif | |
521 | } | |
522 | ||
523 | void test_wallocator() | |
524 | { | |
525 | // Following test cause compilation error on MSVC2012: | |
526 | // (Reason: cannot convert from 'std::_Wrap_alloc<_Alloc>' to 'const my_allocator<CharT>') | |
527 | // | |
528 | // MSVC developer is notified about this issue | |
529 | #if !defined(_MSC_VER) || (_MSC_VER < 1700) | |
530 | typedef std::basic_string< wchar_t | |
531 | , std::char_traits<wchar_t> | |
532 | , my_allocator<wchar_t> | |
533 | > my_string; | |
534 | ||
535 | my_string s(L"s"); | |
536 | BOOST_CHECK(boost::lexical_cast<wchar_t>(s) == s[0]); | |
537 | BOOST_CHECK(boost::lexical_cast<std::wstring>(s) == L"s"); | |
538 | BOOST_CHECK(boost::lexical_cast<my_string>(s) == s); | |
539 | BOOST_CHECK(boost::lexical_cast<my_string>(1) == L"1"); | |
540 | BOOST_CHECK(boost::lexical_cast<my_string>(L"s") == s); | |
541 | BOOST_CHECK(boost::lexical_cast<my_string>(std::wstring(L"s")) == s); | |
542 | #endif | |
543 | } | |
544 | ||
545 | #endif | |
546 | ||
547 | ||
548 | void test_char_types_conversions() | |
549 | { | |
550 | const char c_arr[] = "Test array of chars"; | |
551 | const unsigned char uc_arr[] = "Test array of chars"; | |
552 | const signed char sc_arr[] = "Test array of chars"; | |
553 | ||
554 | BOOST_CHECK(boost::lexical_cast<std::string>(c_arr) == std::string(c_arr)); | |
555 | BOOST_CHECK(boost::lexical_cast<std::string>(uc_arr) == std::string(c_arr)); | |
556 | BOOST_CHECK(boost::lexical_cast<std::string>(sc_arr) == std::string(c_arr)); | |
557 | ||
558 | BOOST_CHECK(boost::lexical_cast<char>(c_arr[0]) == c_arr[0]); | |
559 | BOOST_CHECK(boost::lexical_cast<char>(uc_arr[0]) == c_arr[0]); | |
560 | BOOST_CHECK(boost::lexical_cast<char>(sc_arr[0]) == c_arr[0]); | |
561 | ||
562 | BOOST_CHECK(boost::lexical_cast<unsigned char>(c_arr[0]) == uc_arr[0]); | |
563 | BOOST_CHECK(boost::lexical_cast<unsigned char>(uc_arr[0]) == uc_arr[0]); | |
564 | BOOST_CHECK(boost::lexical_cast<unsigned char>(sc_arr[0]) == uc_arr[0]); | |
565 | ||
566 | BOOST_CHECK(boost::lexical_cast<signed char>(c_arr[0]) == sc_arr[0]); | |
567 | BOOST_CHECK(boost::lexical_cast<signed char>(uc_arr[0]) == sc_arr[0]); | |
568 | BOOST_CHECK(boost::lexical_cast<signed char>(sc_arr[0]) == sc_arr[0]); | |
569 | ||
570 | #ifndef BOOST_LCAST_NO_WCHAR_T | |
571 | const wchar_t wc_arr[]=L"Test array of chars"; | |
572 | ||
573 | BOOST_CHECK(boost::lexical_cast<std::wstring>(wc_arr) == std::wstring(wc_arr)); | |
574 | BOOST_CHECK(boost::lexical_cast<wchar_t>(wc_arr[0]) == wc_arr[0]); | |
575 | ||
576 | #endif | |
577 | } | |
578 | ||
579 | ||
580 | ||
581 | struct foo_operators_test | |
582 | { | |
583 | foo_operators_test() : f(2) {} | |
584 | int f; | |
585 | }; | |
586 | ||
587 | template <typename OStream> | |
588 | OStream& operator<<(OStream& ostr, const foo_operators_test& foo) | |
589 | { | |
590 | ostr << foo.f; | |
591 | return ostr; | |
592 | } | |
593 | ||
594 | template <typename IStream> | |
595 | IStream& operator>>(IStream& istr, foo_operators_test& foo) | |
596 | { | |
597 | istr >> foo.f; | |
598 | return istr; | |
599 | } | |
600 | ||
601 | void operators_overload_test() | |
602 | { | |
603 | foo_operators_test foo; | |
604 | BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(foo), "2"); | |
605 | BOOST_CHECK_EQUAL((boost::lexical_cast<foo_operators_test>("2")).f, 2); | |
606 | ||
607 | // Must compile | |
608 | (void)boost::lexical_cast<foo_operators_test>(foo); | |
609 | } | |
610 | ||
611 | ||
612 | #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) | |
613 | void test_char16_conversions() | |
614 | { | |
615 | BOOST_CHECK(u"100" == lexical_cast<std::u16string>(u"100")); | |
616 | BOOST_CHECK(u"1" == lexical_cast<std::u16string>(u'1')); | |
617 | } | |
618 | #endif | |
619 | ||
620 | #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) | |
621 | void test_char32_conversions() | |
622 | { | |
623 | BOOST_CHECK(U"100" == lexical_cast<std::u32string>(U"100")); | |
624 | BOOST_CHECK(U"1" == lexical_cast<std::u32string>(U'1')); | |
625 | } | |
626 | #endif | |
627 | ||
628 | void test_getting_pointer_to_function() | |
629 | { | |
630 | // Just checking that &lexical_cast<To, From> is not ambiguous | |
631 | typedef char char_arr[4]; | |
632 | typedef int(*f1)(const char_arr&); | |
633 | f1 p1 = &boost::lexical_cast<int, char_arr>; | |
634 | BOOST_CHECK(p1); | |
635 | ||
636 | typedef int(*f2)(const std::string&); | |
637 | f2 p2 = &boost::lexical_cast<int, std::string>; | |
638 | BOOST_CHECK(p2); | |
639 | ||
640 | typedef std::string(*f3)(const int&); | |
641 | f3 p3 = &boost::lexical_cast<std::string, int>; | |
642 | BOOST_CHECK(p3); | |
643 | ||
644 | std::vector<int> values; | |
645 | std::vector<std::string> ret; | |
646 | std::transform(values.begin(), values.end(), ret.begin(), boost::lexical_cast<std::string, int>); | |
647 | } | |
648 | ||
649 |