1// Copyright 2023 Matt Borland
2// Copyright 2023 Peter Dimov
3// Distributed under the Boost Software License, Version 1.0.
4// https://www.boost.org/LICENSE_1_0.txt
5
6#include <boost/config.hpp>
7
8#ifdef BOOST_HAS_INT128
9
10// We need to define these operator<< overloads before
11// including boost/core/lightweight_test.hpp, or they
12// won't be visible to BOOST_TEST_EQ
13// LCOV_EXCL_START
14
15#include <ostream>
16
17static char* mini_to_chars( char (&buffer)[ 64 ], boost::uint128_type v )
18{
19 char* p = buffer + 64;
20 *--p = '\0';
21
22 do
23 {
24 *--p = "0123456789"[ v % 10 ];
25 v /= 10;
26 }
27 while ( v != 0 );
28
29 return p;
30}
31
32std::ostream& operator<<( std::ostream& os, boost::uint128_type v )
33{
34 char buffer[ 64 ];
35
36 os << mini_to_chars( buffer, v );
37 return os;
38}
39
40std::ostream& operator<<( std::ostream& os, boost::int128_type v )
41{
42 char buffer[ 64 ];
43 char* p;
44
45 if( v >= 0 )
46 {
47 p = mini_to_chars( buffer, v: static_cast<boost::uint128_type>(v) );
48 }
49 else
50 {
51 p = mini_to_chars( buffer, v: -static_cast<boost::uint128_type>(v) );
52 *--p = '-';
53 }
54
55 os << p;
56 return os;
57}
58
59// LCOV_EXCL_STOP
60
61#endif // #ifdef BOOST_HAS_INT128
62
63#include <boost/charconv/limits.hpp>
64#include <boost/charconv/to_chars.hpp>
65#include <boost/charconv/from_chars.hpp>
66#include <boost/core/lightweight_test.hpp>
67#include <system_error>
68#include <limits>
69#include <string>
70
71void test_odr_use( int const* );
72
73template<typename T> void test_integral( T value )
74{
75 // no base
76 {
77 char buffer[ boost::charconv::limits<T>::max_chars10 ];
78 auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value );
79 BOOST_TEST(r.ec == std::errc());
80
81 T v2 = 0;
82 auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2 );
83
84 if( BOOST_TEST( r2.ec == std::errc() ) && BOOST_TEST( v2 == value ) )
85 {
86 }
87 else
88 {
89 std::cerr << "... test failure for value=" << value << "; buffer='" << std::string( buffer, r.ptr ) << "'" << std::endl; // LCOV_EXCL_LINE
90 }
91 }
92
93 // base 10
94 {
95 char buffer[ boost::charconv::limits<T>::max_chars10 ];
96 auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value, 10 );
97 BOOST_TEST(r.ec == std::errc());
98
99 T v2 = 0;
100 auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2, 10 );
101
102 if( BOOST_TEST( r2.ec == std::errc() ) && BOOST_TEST( v2 == value ) )
103 {
104 }
105 else
106 {
107 std::cerr << "... test failure for value=" << value << "; buffer='" << std::string( buffer, r.ptr ) << "'" << std::endl; // LCOV_EXCL_LINE
108 }
109 }
110
111 // any base
112 for( int base = 2; base <= 36; ++base )
113 {
114 char buffer[ boost::charconv::limits<T>::max_chars ];
115 auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value, base );
116 BOOST_TEST(r.ec == std::errc());
117
118 T v2 = 0;
119 auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2, base );
120
121 if( BOOST_TEST( r2.ec == std::errc() ) && BOOST_TEST( v2 == value ) )
122 {
123 }
124 else
125 {
126 std::cerr << "... test failure for value=" << value << "; buffer='" << std::string( buffer, r.ptr ) << "'" << std::endl; // LCOV_EXCL_LINE
127 }
128 }
129}
130
131template<typename T> void test_integral()
132{
133 BOOST_TEST_GE( boost::charconv::limits<T>::max_chars10, std::numeric_limits<T>::digits10 );
134 BOOST_TEST_GE( boost::charconv::limits<T>::max_chars, std::numeric_limits<T>::digits );
135
136 test_odr_use( &boost::charconv::limits<T>::max_chars10 );
137 test_odr_use( &boost::charconv::limits<T>::max_chars );
138
139 test_integral( std::numeric_limits<T>::min() );
140 test_integral( std::numeric_limits<T>::max() );
141}
142
143template<typename T> void test_floating_point( T value )
144{
145 // no base, max_chars10
146 {
147 char buffer[ boost::charconv::limits<T>::max_chars10 ];
148 auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value );
149 if (!BOOST_TEST(r.ec == std::errc()))
150 {
151 // LCOV_EXCL_START
152 std::cerr << " Value: " << value
153 << "\nBuffer: " << std::string(buffer)
154 << "\n Ec: " << static_cast<int>(r.ec) << std::endl;
155 // LCOV_EXCL_STOP
156 }
157
158 T v2 = 0;
159 auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2 );
160
161 if (!BOOST_TEST(r2.ec == std::errc()) && BOOST_TEST_EQ( v2, value ))
162 {
163 // LCOV_EXCL_START
164 std::cerr << " Value: " << value
165 << "\nBuffer: " << std::string(buffer)
166 << "\nRetVal: " << v2
167 << "\n Ec: " << static_cast<int>(r2.ec) << std::endl;
168 // LCOV_EXCL_STOP
169 }
170 }
171
172 // no base, max_chars
173 {
174 char buffer[ boost::charconv::limits<T>::max_chars ];
175 auto r = boost::charconv::to_chars( buffer, buffer + sizeof( buffer ), value );
176 if (!BOOST_TEST(r.ec == std::errc()))
177 {
178 // LCOV_EXCL_START
179 std::cerr << " Value: " << value
180 << "\nBuffer: " << std::string(buffer)
181 << "\n Ec: " << static_cast<int>(r.ec) << std::endl;
182 // LCOV_EXCL_STOP
183 }
184
185 T v2 = 0;
186 auto r2 = boost::charconv::from_chars( buffer, r.ptr, v2 );
187
188 if (!BOOST_TEST(r2.ec == std::errc()) && BOOST_TEST_EQ( v2, value ))
189 {
190 // LCOV_EXCL_START
191 std::cerr << " Value: " << value
192 << "\nBuffer: " << std::string(buffer)
193 << "\nRetVal: " << v2
194 << "\n Ec: " << static_cast<int>(r2.ec) << std::endl;
195 // LCOV_EXCL_STOP
196 }
197 }
198}
199
200template<typename T> void test_floating_point()
201{
202 BOOST_TEST_GE( boost::charconv::limits<T>::max_chars10, std::numeric_limits<T>::max_digits10 );
203 BOOST_TEST_GE( boost::charconv::limits<T>::max_chars, std::numeric_limits<T>::max_digits10 );
204
205 test_odr_use( &boost::charconv::limits<T>::max_chars10 );
206 test_odr_use( &boost::charconv::limits<T>::max_chars );
207
208 test_floating_point( std::numeric_limits<T>::min() );
209 test_floating_point( -std::numeric_limits<T>::min() );
210 test_floating_point( std::numeric_limits<T>::max() );
211 test_floating_point( -std::numeric_limits<T>::max() );
212}
213
214int main()
215{
216 test_integral<char>();
217 test_integral<signed char>();
218 test_integral<unsigned char>();
219 test_integral<short>();
220 test_integral<unsigned short>();
221 test_integral<int>();
222 test_integral<unsigned>();
223 test_integral<long>();
224 test_integral<unsigned long>();
225 test_integral<long long>();
226 test_integral<unsigned long long>();
227
228 test_floating_point<float>();
229 test_floating_point<double>();
230 test_floating_point<long double>();
231
232#ifdef BOOST_CHARCONV_HAS_INT128
233
234 test_integral<boost::int128_type>();
235 test_integral<boost::uint128_type>();
236
237#endif
238
239 return boost::report_errors();
240}
241
242void test_odr_use( int const* )
243{
244}
245

source code of boost/libs/charconv/test/limits.cpp