1// Unit test for boost::lexical_cast.
2//
3// See http://www.boost.org for most recent version, including documentation.
4//
5// Copyright Antony Polukhin, 2011-2024.
6//
7// Distributed under the Boost
8// Software License, Version 1.0. (See accompanying file
9// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
10
11#ifndef BOOST_LEXICAL_CAST_DETAIL_TEST_ON_OLD
12#include <boost/lexical_cast.hpp>
13#else
14// Make sure that tests work the same way on non-optimized version
15#include "lexical_cast_old.hpp"
16#endif
17
18#include <boost/cstdint.hpp>
19#include <boost/core/lightweight_test.hpp>
20#include <boost/type_traits/is_same.hpp>
21#include <boost/type_traits/is_signed.hpp>
22
23#ifndef BOOST_TEST_CLOSE_FRACTION
24// Naiive, but works for most tests in this file
25#define BOOST_TEST_CLOSE_FRACTION(x, y, eps) \
26 BOOST_TEST(x - y + eps <= eps * 2); \
27 BOOST_TEST(y - x + eps <= eps * 2);
28#endif
29
30#if (defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__NetBSD__) \
31 || (defined(__hppa) && !defined(__OpenBSD__)) || (defined(__NO_LONG_DOUBLE_MATH) && (DBL_MANT_DIG != LDBL_MANT_DIG))) \
32 || defined(__MINGW64__)
33# define BOOST_LEXICAL_CAST_NO_LONG_DOUBLE_MATH_FUNCTIONS
34#endif
35
36using namespace boost;
37
38
39// Replace "-,999" with "-999".
40template<class CharT>
41std::basic_string<CharT> to_str_gcc_workaround(std::basic_string<CharT> str)
42{
43 std::locale loc;
44 std::numpunct<CharT> const& np = BOOST_USE_FACET(std::numpunct<CharT>, loc);
45 std::ctype<CharT> const& ct = BOOST_USE_FACET(std::ctype<CharT>, loc);
46
47 if(np.grouping().empty())
48 return str;
49
50 CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() };
51
52 if(str.find(prefix) != 0)
53 return str;
54
55 prefix[1] = CharT();
56 str.replace(0, 2, prefix);
57 return str;
58}
59
60template<class CharT, class T>
61std::basic_string<CharT> to_str(T t)
62{
63 std::basic_ostringstream<CharT> o;
64 o << t;
65 return to_str_gcc_workaround(o.str());
66}
67
68
69template<class T>
70void test_conversion_from_to_float_for_locale()
71{
72 std::locale current_locale;
73 typedef std::numpunct<char> numpunct;
74 numpunct const& np = BOOST_USE_FACET(numpunct, current_locale);
75 if ( !np.grouping().empty() )
76 {
77 BOOST_TEST_THROWS(
78 lexical_cast<T>( std::string("100") + np.thousands_sep() + np.thousands_sep() + "0" )
79 , bad_lexical_cast);
80 BOOST_TEST_THROWS(lexical_cast<T>( std::string("100") + np.thousands_sep() ), bad_lexical_cast);
81 BOOST_TEST_THROWS(lexical_cast<T>( np.thousands_sep() + std::string("100") ), bad_lexical_cast);
82 BOOST_TEST_THROWS(lexical_cast<T>( std::string("1") + np.thousands_sep() + np.decimal_point() + "e10" ), bad_lexical_cast);
83 BOOST_TEST_THROWS(lexical_cast<T>( std::string("1e10") + np.thousands_sep() ), bad_lexical_cast);
84 BOOST_TEST_THROWS(lexical_cast<T>( std::string("1") + np.thousands_sep() + "e10" ), bad_lexical_cast);
85
86 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(100000) ), 100000, (std::numeric_limits<T>::epsilon()) );
87 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(10000000u) ), 10000000u, (std::numeric_limits<T>::epsilon()) );
88 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(100) ), 100, (std::numeric_limits<T>::epsilon()) );
89#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
90 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(100000) ), 100000, (std::numeric_limits<T>::epsilon()) );
91 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(10000000u) ), 10000000u, (std::numeric_limits<T>::epsilon()) );
92 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(100) ), 100, (std::numeric_limits<T>::epsilon()) );
93#endif
94 // Exception must not be thrown, when we are using no separators at all
95 BOOST_TEST_CLOSE_FRACTION( lexical_cast<T>("30000"), static_cast<T>(30000), (std::numeric_limits<T>::epsilon()) );
96 }
97}
98
99
100
101
102/*
103 * Converts char* [and wchar_t*] to float number type and checks, that generated
104 * number does not exceeds allowed epsilon.
105 */
106#ifndef BOOST_LCAST_NO_WCHAR_T
107#define CHECK_CLOSE_ABS_DIFF(VAL,PREFIX) \
108 converted_val = lexical_cast<test_t>(#VAL); \
109 BOOST_TEST_CLOSE_FRACTION( (static_cast<bool>(VAL ## L)? VAL ## L : std::numeric_limits<test_t>::epsilon()), \
110 (converted_val ? converted_val : std::numeric_limits<test_t>::epsilon()), \
111 std::numeric_limits<test_t>::epsilon() \
112 ); \
113 BOOST_TEST_EQ(converted_val, lexical_cast<test_t>(L## #VAL) );
114
115#else
116#define CHECK_CLOSE_ABS_DIFF(VAL,TYPE) \
117 converted_val = lexical_cast<test_t>(#VAL); \
118 BOOST_TEST_CLOSE_FRACTION( (static_cast<bool>(VAL ## L)? VAL ## L : std::numeric_limits<test_t>::epsilon()), \
119 (converted_val ? converted_val : std::numeric_limits<test_t>::epsilon()), \
120 std::numeric_limits<test_t>::epsilon() \
121 );
122#endif
123
124template <class TestType>
125void test_converion_to_float_types()
126{
127 typedef TestType test_t;
128 test_t converted_val;
129
130 BOOST_TEST_CLOSE_FRACTION(1.0, lexical_cast<test_t>('1'), (std::numeric_limits<test_t>::epsilon()));
131 BOOST_TEST_EQ(0.0, lexical_cast<test_t>('0'));
132
133 unsigned char const uc_one = '1';
134 unsigned char const uc_zero ='0';
135 BOOST_TEST_CLOSE_FRACTION(1.0, lexical_cast<test_t>(uc_one), (std::numeric_limits<test_t>::epsilon()));
136 BOOST_TEST_EQ(0.0, lexical_cast<test_t>(uc_zero));
137
138 signed char const sc_one = '1';
139 signed char const sc_zero ='0';
140 BOOST_TEST_CLOSE_FRACTION(1.0, lexical_cast<test_t>(sc_one), (std::numeric_limits<test_t>::epsilon()));
141 BOOST_TEST_EQ(0.0, lexical_cast<test_t>(sc_zero));
142
143 BOOST_TEST_CLOSE_FRACTION(1e34L, lexical_cast<test_t>( "10000000000000000000000000000000000"), (std::numeric_limits<test_t>::epsilon() * 1e34L) );
144
145// VC failes the next test
146// BOOST_TEST_CLOSE_FRACTION(1e-35L, lexical_cast<test_t>("0.00000000000000000000000000000000001"), (std::numeric_limits<test_t>::epsilon()) );
147 BOOST_TEST_CLOSE_FRACTION(
148 0.1111111111111111111111111111111111111111111111111111111111111111111111111L
149 , lexical_cast<test_t>("0.1111111111111111111111111111111111111111111111111111111111111111111111111")
150 , (std::numeric_limits<test_t>::epsilon()) );
151
152 CHECK_CLOSE_ABS_DIFF(1,test_t);
153 BOOST_TEST_EQ(0,lexical_cast<test_t>("0"));
154 CHECK_CLOSE_ABS_DIFF(-1,test_t);
155
156 CHECK_CLOSE_ABS_DIFF(1.0, test_t);
157 CHECK_CLOSE_ABS_DIFF(0.0, test_t);
158 CHECK_CLOSE_ABS_DIFF(-1.0,test_t);
159
160 CHECK_CLOSE_ABS_DIFF(1e1, test_t);
161 CHECK_CLOSE_ABS_DIFF(0e1, test_t);
162 CHECK_CLOSE_ABS_DIFF(-1e1,test_t);
163
164 CHECK_CLOSE_ABS_DIFF(1.0e1, test_t);
165 CHECK_CLOSE_ABS_DIFF(0.0e1, test_t);
166 CHECK_CLOSE_ABS_DIFF(-1.0e1,test_t);
167
168 CHECK_CLOSE_ABS_DIFF(1e-1, test_t);
169 CHECK_CLOSE_ABS_DIFF(0e-1, test_t);
170 CHECK_CLOSE_ABS_DIFF(-1e-1,test_t);
171
172 CHECK_CLOSE_ABS_DIFF(1.0e-1, test_t);
173 CHECK_CLOSE_ABS_DIFF(0.0e-1, test_t);
174 CHECK_CLOSE_ABS_DIFF(-1.0e-1,test_t);
175
176 CHECK_CLOSE_ABS_DIFF(1E1, test_t);
177 CHECK_CLOSE_ABS_DIFF(0E1, test_t);
178 CHECK_CLOSE_ABS_DIFF(-1E1,test_t);
179
180 CHECK_CLOSE_ABS_DIFF(1.0E1, test_t);
181 CHECK_CLOSE_ABS_DIFF(0.0E1, test_t);
182 CHECK_CLOSE_ABS_DIFF(-1.0E1,test_t);
183
184 CHECK_CLOSE_ABS_DIFF(1E-1, test_t);
185 CHECK_CLOSE_ABS_DIFF(0E-1, test_t);
186 CHECK_CLOSE_ABS_DIFF(-1E-1,test_t);
187
188 CHECK_CLOSE_ABS_DIFF(1.0E-1, test_t);
189 CHECK_CLOSE_ABS_DIFF(0.0E-1, test_t);
190 CHECK_CLOSE_ABS_DIFF(-1.0E-1, test_t);
191
192 CHECK_CLOSE_ABS_DIFF(.0E-1, test_t);
193 CHECK_CLOSE_ABS_DIFF(.0E-1, test_t);
194 CHECK_CLOSE_ABS_DIFF(-.0E-1, test_t);
195
196 CHECK_CLOSE_ABS_DIFF(10.0, test_t);
197 CHECK_CLOSE_ABS_DIFF(00.0, test_t);
198 CHECK_CLOSE_ABS_DIFF(-10.0,test_t);
199
200 CHECK_CLOSE_ABS_DIFF(10e1, test_t);
201 CHECK_CLOSE_ABS_DIFF(00e1, test_t);
202 CHECK_CLOSE_ABS_DIFF(-10e1,test_t);
203
204 CHECK_CLOSE_ABS_DIFF(10.0e1, test_t);
205 CHECK_CLOSE_ABS_DIFF(00.0e1, test_t);
206 CHECK_CLOSE_ABS_DIFF(-10.0e1,test_t);
207
208 CHECK_CLOSE_ABS_DIFF(10e-1, test_t);
209 CHECK_CLOSE_ABS_DIFF(00e-1, test_t);
210 CHECK_CLOSE_ABS_DIFF(-10e-1,test_t);
211
212 CHECK_CLOSE_ABS_DIFF(10.0e-1, test_t);
213 CHECK_CLOSE_ABS_DIFF(00.0e-1, test_t);
214 CHECK_CLOSE_ABS_DIFF(-10.0e-1,test_t);
215
216 CHECK_CLOSE_ABS_DIFF(10E1, test_t);
217 CHECK_CLOSE_ABS_DIFF(00E1, test_t);
218 CHECK_CLOSE_ABS_DIFF(-10E1,test_t);
219
220 CHECK_CLOSE_ABS_DIFF(10.0E1, test_t);
221 CHECK_CLOSE_ABS_DIFF(00.0E1, test_t);
222 CHECK_CLOSE_ABS_DIFF(-10.0E1,test_t);
223
224 CHECK_CLOSE_ABS_DIFF(10E-1, test_t);
225 CHECK_CLOSE_ABS_DIFF(00E-1, test_t);
226 CHECK_CLOSE_ABS_DIFF(-10E-1,test_t);
227
228 CHECK_CLOSE_ABS_DIFF(10.0E-1, test_t);
229 CHECK_CLOSE_ABS_DIFF(00.0E-1, test_t);
230 CHECK_CLOSE_ABS_DIFF(-10.0E-1, test_t);
231
232 CHECK_CLOSE_ABS_DIFF(-10101.0E-011, test_t);
233 CHECK_CLOSE_ABS_DIFF(-10101093, test_t);
234 CHECK_CLOSE_ABS_DIFF(10101093, test_t);
235
236 CHECK_CLOSE_ABS_DIFF(-.34, test_t);
237 CHECK_CLOSE_ABS_DIFF(.34, test_t);
238 CHECK_CLOSE_ABS_DIFF(.34e10, test_t);
239
240 BOOST_TEST_THROWS(lexical_cast<test_t>("-1.e"), bad_lexical_cast);
241 BOOST_TEST_THROWS(lexical_cast<test_t>("-1.E"), bad_lexical_cast);
242 BOOST_TEST_THROWS(lexical_cast<test_t>("1.e"), bad_lexical_cast);
243 BOOST_TEST_THROWS(lexical_cast<test_t>("1.E"), bad_lexical_cast);
244
245 BOOST_TEST_THROWS(lexical_cast<test_t>("1.0e"), bad_lexical_cast);
246 BOOST_TEST_THROWS(lexical_cast<test_t>("1.0E"), bad_lexical_cast);
247 BOOST_TEST_THROWS(lexical_cast<test_t>("10E"), bad_lexical_cast);
248 BOOST_TEST_THROWS(lexical_cast<test_t>("10e"), bad_lexical_cast);
249 BOOST_TEST_THROWS(lexical_cast<test_t>("1.0e-"), bad_lexical_cast);
250 BOOST_TEST_THROWS(lexical_cast<test_t>("1.0E-"), bad_lexical_cast);
251 BOOST_TEST_THROWS(lexical_cast<test_t>("10E-"), bad_lexical_cast);
252 BOOST_TEST_THROWS(lexical_cast<test_t>("10e-"), bad_lexical_cast);
253 BOOST_TEST_THROWS(lexical_cast<test_t>("e1"), bad_lexical_cast);
254 BOOST_TEST_THROWS(lexical_cast<test_t>("e-1"), bad_lexical_cast);
255 BOOST_TEST_THROWS(lexical_cast<test_t>("e-"), bad_lexical_cast);
256 BOOST_TEST_THROWS(lexical_cast<test_t>(".e"), bad_lexical_cast);
257 BOOST_TEST_THROWS(lexical_cast<test_t>(".11111111111111111111111111111111111111111111111111111111111111111111ee"), bad_lexical_cast);
258 BOOST_TEST_THROWS(lexical_cast<test_t>(".11111111111111111111111111111111111111111111111111111111111111111111e-"), bad_lexical_cast);
259 BOOST_TEST_THROWS(lexical_cast<test_t>("."), bad_lexical_cast);
260
261 BOOST_TEST_THROWS(lexical_cast<test_t>("-B"), bad_lexical_cast);
262
263 // Following two tests are not valid for C++11 compilers
264 //BOOST_TEST_THROWS(lexical_cast<test_t>("0xB"), bad_lexical_cast);
265 //BOOST_TEST_THROWS(lexical_cast<test_t>("0x0"), bad_lexical_cast);
266
267 BOOST_TEST_THROWS(lexical_cast<test_t>("--1.0"), bad_lexical_cast);
268 BOOST_TEST_THROWS(lexical_cast<test_t>("1.0e--1"), bad_lexical_cast);
269 BOOST_TEST_THROWS(lexical_cast<test_t>("1.0.0"), bad_lexical_cast);
270 BOOST_TEST_THROWS(lexical_cast<test_t>("1e1e1"), bad_lexical_cast);
271 BOOST_TEST_THROWS(lexical_cast<test_t>("1.0e-1e-1"), bad_lexical_cast);
272 BOOST_TEST_THROWS(lexical_cast<test_t>(" 1.0"), bad_lexical_cast);
273 BOOST_TEST_THROWS(lexical_cast<test_t>("1.0 "), bad_lexical_cast);
274 BOOST_TEST_THROWS(lexical_cast<test_t>(""), bad_lexical_cast);
275 BOOST_TEST_THROWS(lexical_cast<test_t>("-"), bad_lexical_cast);
276 BOOST_TEST_THROWS(lexical_cast<test_t>('\0'), bad_lexical_cast);
277 BOOST_TEST_THROWS(lexical_cast<test_t>('-'), bad_lexical_cast);
278 BOOST_TEST_THROWS(lexical_cast<test_t>('.'), bad_lexical_cast);
279}
280
281template <class T>
282void test_float_typess_for_overflows()
283{
284 typedef T test_t;
285 test_t minvalue = (std::numeric_limits<test_t>::min)();
286 std::string s_min_value = lexical_cast<std::string>(minvalue);
287 BOOST_TEST_CLOSE_FRACTION(minvalue, lexical_cast<test_t>(minvalue), (std::numeric_limits<test_t>::epsilon()));
288 BOOST_TEST_CLOSE_FRACTION(minvalue, lexical_cast<test_t>(s_min_value), (std::numeric_limits<test_t>::epsilon() * 2));
289
290 test_t maxvalue = (std::numeric_limits<test_t>::max)();
291 std::string s_max_value = lexical_cast<std::string>(maxvalue);
292 BOOST_TEST_CLOSE_FRACTION(maxvalue, lexical_cast<test_t>(maxvalue), (std::numeric_limits<test_t>::epsilon()));
293 BOOST_TEST_CLOSE_FRACTION(maxvalue, lexical_cast<test_t>(s_max_value), (std::numeric_limits<test_t>::epsilon()));
294
295#ifndef _LIBCPP_VERSION
296 // libc++ had a bug in implementation of stream conversions for values that must be represented as infinity.
297 // http://llvm.org/bugs/show_bug.cgi?id=15723#c4
298 BOOST_TEST_THROWS(lexical_cast<test_t>(s_max_value+"1"), bad_lexical_cast);
299 BOOST_TEST_THROWS(lexical_cast<test_t>(s_max_value+"9"), bad_lexical_cast);
300
301 // VC9 can fail the following tests on floats and doubles when using stingstream...
302 BOOST_TEST_THROWS(lexical_cast<test_t>("1"+s_max_value), bad_lexical_cast);
303 BOOST_TEST_THROWS(lexical_cast<test_t>("9"+s_max_value), bad_lexical_cast);
304#endif
305
306 if ( is_same<test_t,float>::value )
307 {
308 BOOST_TEST_THROWS(lexical_cast<test_t>( (std::numeric_limits<double>::max)() ), bad_lexical_cast);
309 BOOST_TEST(
310 (std::numeric_limits<double>::min)() - std::numeric_limits<test_t>::epsilon()
311 <= lexical_cast<test_t>( (std::numeric_limits<double>::min)() )
312 && lexical_cast<test_t>( (std::numeric_limits<double>::min)() )
313 <= (std::numeric_limits<double>::min)() + std::numeric_limits<test_t>::epsilon()
314 );
315
316 BOOST_TEST(
317 (std::numeric_limits<double>::min)() / 2 - std::numeric_limits<test_t>::epsilon()
318 <= lexical_cast<test_t>( (std::numeric_limits<double>::min)() / 2 )
319 && lexical_cast<test_t>( (std::numeric_limits<double>::min)() / 2 )
320 <= (std::numeric_limits<double>::min)() / 2 + std::numeric_limits<test_t>::epsilon()
321 );
322 }
323
324 if ( sizeof(test_t) < sizeof(long double) )
325 {
326 BOOST_TEST_THROWS(lexical_cast<test_t>( (std::numeric_limits<long double>::max)() ), bad_lexical_cast);
327 BOOST_TEST(
328 (std::numeric_limits<long double>::min)() - std::numeric_limits<test_t>::epsilon()
329 <= lexical_cast<test_t>( (std::numeric_limits<long double>::min)() )
330 && lexical_cast<test_t>( (std::numeric_limits<long double>::min)() )
331 <= (std::numeric_limits<long double>::min)() + std::numeric_limits<test_t>::epsilon()
332 );
333
334 BOOST_TEST(
335 (std::numeric_limits<long double>::min)() / 2 - std::numeric_limits<test_t>::epsilon()
336 <= lexical_cast<test_t>( (std::numeric_limits<long double>::min)() / 2 )
337 && lexical_cast<test_t>( (std::numeric_limits<long double>::min)() / 2 )
338 <= (std::numeric_limits<long double>::min)() / 2 + std::numeric_limits<test_t>::epsilon()
339 );
340 }
341}
342
343#undef CHECK_CLOSE_ABS_DIFF
344
345// Epsilon is multiplied by 2 because of two lexical conversions
346#define TEST_TO_FROM_CAST_AROUND_TYPED(VAL,STRING_TYPE) \
347 test_value = VAL + std::numeric_limits<test_t>::epsilon() * i ; \
348 converted_val = lexical_cast<test_t>( lexical_cast<STRING_TYPE>(test_value) ); \
349 BOOST_TEST_CLOSE_FRACTION( \
350 test_value, \
351 converted_val, \
352 std::numeric_limits<test_t>::epsilon() * 2 \
353 );
354
355/*
356 * For interval [ from_mult*epsilon+VAL, to_mult*epsilon+VAL ], converts float type
357 * numbers to string[wstring] and then back to float type, then compares initial
358 * values and generated.
359 * Step is epsilon
360 */
361#ifndef BOOST_LCAST_NO_WCHAR_T
362# define TEST_TO_FROM_CAST_AROUND(VAL) \
363 for(i=from_mult; i<=to_mult; ++i) { \
364 TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::string) \
365 TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::wstring) \
366 }
367#else
368# define TEST_TO_FROM_CAST_AROUND(VAL) \
369 for(i=from_mult; i<=to_mult; ++i) { \
370 TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::string) \
371 }
372#endif
373
374template <class TestType>
375void test_converion_from_to_float_types()
376{
377 typedef TestType test_t;
378 test_t test_value;
379 test_t converted_val;
380
381 int i;
382 int from_mult = -50;
383 int to_mult = 50;
384
385 TEST_TO_FROM_CAST_AROUND( 0.0 );
386
387 long double val1;
388 for(val1 = 1.0e-10L; val1 < 1e11; val1*=10 )
389 TEST_TO_FROM_CAST_AROUND( val1 );
390
391 long double val2;
392 for(val2 = -1.0e-10L; val2 > -1e11; val2*=10 )
393 TEST_TO_FROM_CAST_AROUND( val2 );
394
395 from_mult = -100;
396 to_mult = 0;
397 TEST_TO_FROM_CAST_AROUND( (std::numeric_limits<test_t>::max)() );
398
399 from_mult = 0;
400 to_mult = 100;
401 TEST_TO_FROM_CAST_AROUND( (std::numeric_limits<test_t>::min)() );
402}
403
404#undef TEST_TO_FROM_CAST_AROUND
405#undef TEST_TO_FROM_CAST_AROUND_TYPED
406
407
408template<class T, class CharT>
409void test_conversion_from_float_to_char(CharT zero)
410{
411 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(0)) == zero + 0);
412 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(1)) == zero + 1);
413 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(2)) == zero + 2);
414 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(3)) == zero + 3);
415 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(4)) == zero + 4);
416 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(5)) == zero + 5);
417 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(6)) == zero + 6);
418 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(7)) == zero + 7);
419 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(8)) == zero + 8);
420 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(9)) == zero + 9);
421
422 BOOST_TEST_THROWS(lexical_cast<CharT>(static_cast<T>(10)), bad_lexical_cast);
423
424 T t = (std::numeric_limits<T>::max)();
425 BOOST_TEST_THROWS(lexical_cast<CharT>(t), bad_lexical_cast);
426}
427
428template<class T, class CharT>
429void test_conversion_from_char_to_float(CharT zero)
430{
431 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 0)), static_cast<T>(0), (std::numeric_limits<T>::epsilon()) );
432 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 1)), static_cast<T>(1), (std::numeric_limits<T>::epsilon()) );
433 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 2)), static_cast<T>(2), (std::numeric_limits<T>::epsilon()) );
434 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 3)), static_cast<T>(3), (std::numeric_limits<T>::epsilon()) );
435 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 4)), static_cast<T>(4), (std::numeric_limits<T>::epsilon()) );
436 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 5)), static_cast<T>(5), (std::numeric_limits<T>::epsilon()) );
437 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 6)), static_cast<T>(6), (std::numeric_limits<T>::epsilon()) );
438 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 7)), static_cast<T>(7), (std::numeric_limits<T>::epsilon()) );
439 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 8)), static_cast<T>(8), (std::numeric_limits<T>::epsilon()) );
440 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 9)), static_cast<T>(9), (std::numeric_limits<T>::epsilon()) );
441
442 BOOST_TEST_THROWS(lexical_cast<T>( static_cast<CharT>(zero + 10)), bad_lexical_cast);
443 BOOST_TEST_THROWS(lexical_cast<T>( static_cast<CharT>(zero - 1)), bad_lexical_cast);
444}
445
446struct restore_oldloc
447{
448 std::locale oldloc;
449 ~restore_oldloc() { std::locale::global(loc: oldloc); }
450};
451
452template<class T>
453void test_conversion_from_to_float()
454{ char const zero = '0';
455 signed char const szero = '0';
456 unsigned char const uzero = '0';
457 test_conversion_from_float_to_char<T>(zero);
458 test_conversion_from_char_to_float<T>(zero);
459 test_conversion_from_float_to_char<T>(szero);
460 test_conversion_from_char_to_float<T>(szero);
461 test_conversion_from_float_to_char<T>(uzero);
462 test_conversion_from_char_to_float<T>(uzero);
463 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
464 wchar_t const wzero = L'0';
465 test_conversion_from_float_to_char<T>(wzero);
466 test_conversion_from_char_to_float<T>(wzero);
467 #endif
468
469 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>("+1"), 1, std::numeric_limits<T>::epsilon());
470 BOOST_TEST_CLOSE_FRACTION(lexical_cast<T>("+9"), 9, std::numeric_limits<T>::epsilon());
471
472 BOOST_TEST_THROWS(lexical_cast<T>("++1"), bad_lexical_cast);
473 BOOST_TEST_THROWS(lexical_cast<T>("-+9"), bad_lexical_cast);
474 BOOST_TEST_THROWS(lexical_cast<T>("--1"), bad_lexical_cast);
475 BOOST_TEST_THROWS(lexical_cast<T>("+-9"), bad_lexical_cast);
476
477 test_converion_to_float_types<T>();
478 test_float_typess_for_overflows<T>();
479 test_converion_from_to_float_types<T>();
480
481
482 typedef std::numpunct<char> numpunct;
483
484 restore_oldloc guard;
485 std::locale const& oldloc = guard.oldloc;
486
487 std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping();
488 std::string grouping2(grouping1);
489
490 test_conversion_from_to_float_for_locale<T>();
491
492 try
493 {
494 std::locale newloc("");
495 std::locale::global(loc: newloc);
496
497 grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping();
498 }
499 catch(std::exception const& ex)
500 {
501 std::string msg("Failed to set system locale: ");
502 msg += ex.what();
503 std::cerr << msg;
504 }
505
506 if(grouping1 != grouping2)
507 test_conversion_from_to_float_for_locale<T>();
508
509 if(grouping1.empty() && grouping2.empty())
510 std::cerr << "Formatting with thousands_sep has not been tested";
511}
512
513
514
515void test_conversion_from_to_float()
516{
517 test_conversion_from_to_float<float>();
518}
519void test_conversion_from_to_double()
520{
521 test_conversion_from_to_float<double>();
522}
523void test_conversion_from_to_long_double()
524{
525// We do not run tests on compilers and Standard Libraries with poor support of long double
526#if !defined(BOOST_LEXICAL_CAST_NO_LONG_DOUBLE_MATH_FUNCTIONS)
527 test_conversion_from_to_float<long double>();
528#endif
529 BOOST_TEST(true);
530}
531
532template <class Integral, class Float>
533void test_conversion_integral_float()
534{
535 BOOST_TEST_CLOSE_FRACTION(lexical_cast<Float>(static_cast<Float>(1)), static_cast<Float>(1), std::numeric_limits<Float>::epsilon());
536 BOOST_TEST_CLOSE_FRACTION(lexical_cast<Float>(static_cast<Float>(1.1234)), static_cast<Float>(1.1234), std::numeric_limits<Float>::epsilon());
537 BOOST_TEST_CLOSE_FRACTION(lexical_cast<Float>(static_cast<Float>(-1.1234)), static_cast<Float>(-1.1234), std::numeric_limits<Float>::epsilon());
538
539 BOOST_TEST_CLOSE_FRACTION(lexical_cast<Float>(static_cast<Integral>(0)), static_cast<Float>(0), std::numeric_limits<Float>::epsilon());
540 BOOST_TEST_CLOSE_FRACTION(lexical_cast<Float>(static_cast<Integral>(1)), static_cast<Float>(1), std::numeric_limits<Float>::epsilon());
541
542#ifndef __CYGWIN__
543 BOOST_TEST_CLOSE_FRACTION(lexical_cast<Float>((std::numeric_limits<Integral>::max)()), static_cast<Float>((std::numeric_limits<Integral>::max)()), std::numeric_limits<Float>::epsilon());
544 BOOST_TEST_CLOSE_FRACTION(lexical_cast<Float>((std::numeric_limits<Integral>::min)()), static_cast<Float>((std::numeric_limits<Integral>::min)()), std::numeric_limits<Float>::epsilon());
545#endif
546
547 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(0.0)), 0);
548 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(1.0)), 1);
549 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(8.0)), 8);
550 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(16.0)), 16);
551
552 if (boost::is_signed<Integral>::value) {
553 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(-1.0)), -1);
554 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(-8.0)), -8);
555 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(-16.0)), -16);
556 } else {
557 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(-1.0)), (std::numeric_limits<Integral>::max)());
558 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(-8.0)), (std::numeric_limits<Integral>::max)() - 7);
559 BOOST_TEST_EQ(lexical_cast<Integral>(static_cast<Float>(-16.0)), (std::numeric_limits<Integral>::max)() - 15);
560 }
561
562 BOOST_TEST_THROWS(lexical_cast<Integral>(static_cast<Float>(0.5)), bad_lexical_cast);
563 BOOST_TEST_THROWS(lexical_cast<Integral>(static_cast<Float>(-0.5)), bad_lexical_cast);
564 BOOST_TEST_THROWS(lexical_cast<Integral>(static_cast<Float>(1.5)), bad_lexical_cast);
565 BOOST_TEST_THROWS(lexical_cast<Integral>(static_cast<Float>(-1.5)), bad_lexical_cast);
566
567 BOOST_TEST_THROWS(lexical_cast<Integral>((std::numeric_limits<Float>::min)()), bad_lexical_cast);
568 BOOST_TEST_THROWS(lexical_cast<Integral>((std::numeric_limits<Float>::max)()), bad_lexical_cast);
569 BOOST_TEST_THROWS(lexical_cast<Integral>((std::numeric_limits<Float>::epsilon)()), bad_lexical_cast);
570 BOOST_TEST_THROWS(lexical_cast<Integral>((std::numeric_limits<Float>::lowest)()), bad_lexical_cast);
571}
572
573
574int main()
575{
576 test_conversion_from_to_float();
577 test_conversion_from_to_double();
578 test_conversion_from_to_long_double();
579
580 test_conversion_integral_float<int, float>();
581 test_conversion_integral_float<int, double>();
582 test_conversion_integral_float<unsigned short, float>();
583 test_conversion_integral_float<unsigned short, double>();
584 test_conversion_integral_float<short, float>();
585 test_conversion_integral_float<short, double>();
586 test_conversion_integral_float<long int, float>();
587 test_conversion_integral_float<long int, double>();
588 test_conversion_integral_float<long long, float>();
589 test_conversion_integral_float<long long, double>();
590 test_conversion_integral_float<unsigned long long, float>();
591 test_conversion_integral_float<unsigned long long, double>();
592
593 return boost::report_errors();
594}
595

source code of boost/libs/lexical_cast/test/float_types_test.cpp