1 | // Testing boost::lexical_cast with boost::container::string. |
2 | // |
3 | // See http://www.boost.org for most recent version, including documentation. |
4 | // |
5 | // Copyright Antony Polukhin, 2012-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 | #include <boost/lexical_cast.hpp> |
12 | |
13 | #include <boost/core/lightweight_test.hpp> |
14 | |
15 | #include <boost/array.hpp> |
16 | |
17 | using namespace boost; |
18 | |
19 | #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION) && !defined(BOOST_MSVC) |
20 | #define BOOST_LC_RUNU16 |
21 | #endif |
22 | |
23 | #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION) && !defined(BOOST_MSVC) |
24 | #define BOOST_LC_RUNU32 |
25 | #endif |
26 | |
27 | template <template <class, std::size_t> class ArrayT, class T> |
28 | static void testing_template_array_output_on_spec_value(T val) |
29 | { |
30 | typedef ArrayT<char, 300> arr_type; |
31 | typedef ArrayT<char, 1> short_arr_type; |
32 | typedef ArrayT<unsigned char, 300> uarr_type; |
33 | typedef ArrayT<unsigned char, 1> ushort_arr_type; |
34 | typedef ArrayT<signed char, 4> sarr_type; |
35 | typedef ArrayT<signed char, 3> sshort_arr_type; |
36 | |
37 | std::string ethalon("100" ); |
38 | using namespace std; |
39 | |
40 | { |
41 | arr_type res1 = lexical_cast<arr_type>(val); |
42 | BOOST_TEST_EQ(&res1[0], ethalon); |
43 | const arr_type res2 = lexical_cast<arr_type>(val); |
44 | BOOST_TEST_EQ(&res2[0], ethalon); |
45 | BOOST_TEST_THROWS(lexical_cast<short_arr_type>(val), boost::bad_lexical_cast); |
46 | } |
47 | |
48 | { |
49 | uarr_type res1 = lexical_cast<uarr_type>(val); |
50 | BOOST_TEST_EQ(reinterpret_cast<char*>(&res1[0]), ethalon); |
51 | const uarr_type res2 = lexical_cast<uarr_type>(val); |
52 | BOOST_TEST_EQ(reinterpret_cast<const char*>(&res2[0]), ethalon); |
53 | BOOST_TEST_THROWS(lexical_cast<ushort_arr_type>(val), boost::bad_lexical_cast); |
54 | } |
55 | |
56 | { |
57 | sarr_type res1 = lexical_cast<sarr_type>(val); |
58 | BOOST_TEST_EQ(reinterpret_cast<char*>(&res1[0]), ethalon); |
59 | const sarr_type res2 = lexical_cast<sarr_type>(val); |
60 | BOOST_TEST_EQ(reinterpret_cast<const char*>(&res2[0]), ethalon); |
61 | BOOST_TEST_THROWS(lexical_cast<sshort_arr_type>(val), boost::bad_lexical_cast); |
62 | } |
63 | |
64 | #if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING) |
65 | typedef ArrayT<wchar_t, 300> warr_type; |
66 | typedef ArrayT<wchar_t, 3> wshort_arr_type; |
67 | std::wstring wethalon(L"100" ); |
68 | |
69 | { |
70 | warr_type res = lexical_cast<warr_type>(val); |
71 | BOOST_TEST(&res[0] == wethalon); |
72 | } |
73 | |
74 | { |
75 | const warr_type res = lexical_cast<warr_type>(val); |
76 | BOOST_TEST(&res[0] == wethalon); |
77 | } |
78 | |
79 | BOOST_TEST_THROWS(lexical_cast<wshort_arr_type>(val), boost::bad_lexical_cast); |
80 | |
81 | #endif |
82 | |
83 | #ifdef BOOST_LC_RUNU16 |
84 | typedef ArrayT<char16_t, 300> u16arr_type; |
85 | typedef ArrayT<char16_t, 3> u16short_arr_type; |
86 | std::u16string u16ethalon(u"100" ); |
87 | |
88 | { |
89 | u16arr_type res = lexical_cast<u16arr_type>(val); |
90 | BOOST_TEST(&res[0] == u16ethalon); |
91 | } |
92 | |
93 | { |
94 | const u16arr_type res = lexical_cast<u16arr_type>(val); |
95 | BOOST_TEST(&res[0] == u16ethalon); |
96 | } |
97 | |
98 | BOOST_TEST_THROWS(lexical_cast<u16short_arr_type>(val), boost::bad_lexical_cast); |
99 | #endif |
100 | |
101 | #ifdef BOOST_LC_RUNU32 |
102 | typedef ArrayT<char32_t, 300> u32arr_type; |
103 | typedef ArrayT<char32_t, 3> u32short_arr_type; |
104 | std::u32string u32ethalon(U"100" ); |
105 | |
106 | { |
107 | u32arr_type res = lexical_cast<u32arr_type>(val); |
108 | BOOST_TEST(&res[0] == u32ethalon); |
109 | } |
110 | |
111 | { |
112 | const u32arr_type res = lexical_cast<u32arr_type>(val); |
113 | BOOST_TEST(&res[0] == u32ethalon); |
114 | } |
115 | |
116 | BOOST_TEST_THROWS(lexical_cast<u32short_arr_type>(val), boost::bad_lexical_cast); |
117 | #endif |
118 | } |
119 | |
120 | |
121 | template <template <class, std::size_t> class ArrayT> |
122 | static void testing_template_array_output_on_char_value() |
123 | { |
124 | typedef ArrayT<char, 300> arr_type; |
125 | typedef ArrayT<char, 1> short_arr_type; |
126 | typedef ArrayT<unsigned char, 300> uarr_type; |
127 | typedef ArrayT<unsigned char, 1> ushort_arr_type; |
128 | typedef ArrayT<signed char, 4> sarr_type; |
129 | typedef ArrayT<signed char, 3> sshort_arr_type; |
130 | |
131 | const char val[] = "100" ; |
132 | std::string ethalon("100" ); |
133 | using namespace std; |
134 | |
135 | { |
136 | arr_type res1 = lexical_cast<arr_type>(val); |
137 | BOOST_TEST_EQ(&res1[0], ethalon); |
138 | const arr_type res2 = lexical_cast<arr_type>(val); |
139 | BOOST_TEST_EQ(&res2[0], ethalon); |
140 | BOOST_TEST_THROWS(lexical_cast<short_arr_type>(val), boost::bad_lexical_cast); |
141 | } |
142 | |
143 | { |
144 | uarr_type res1 = lexical_cast<uarr_type>(val); |
145 | BOOST_TEST_EQ(reinterpret_cast<char*>(&res1[0]), ethalon); |
146 | const uarr_type res2 = lexical_cast<uarr_type>(val); |
147 | BOOST_TEST_EQ(reinterpret_cast<const char*>(&res2[0]), ethalon); |
148 | BOOST_TEST_THROWS(lexical_cast<ushort_arr_type>(val), boost::bad_lexical_cast); |
149 | } |
150 | |
151 | { |
152 | sarr_type res1 = lexical_cast<sarr_type>(val); |
153 | BOOST_TEST_EQ(reinterpret_cast<char*>(&res1[0]), ethalon); |
154 | const sarr_type res2 = lexical_cast<sarr_type>(val); |
155 | BOOST_TEST_EQ(reinterpret_cast<const char*>(&res2[0]), ethalon); |
156 | BOOST_TEST_THROWS(lexical_cast<sshort_arr_type>(val), boost::bad_lexical_cast); |
157 | } |
158 | |
159 | #if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING) |
160 | typedef ArrayT<wchar_t, 4> warr_type; |
161 | typedef ArrayT<wchar_t, 3> wshort_arr_type; |
162 | std::wstring wethalon(L"100" ); |
163 | |
164 | { |
165 | warr_type res = lexical_cast<warr_type>(val); |
166 | BOOST_TEST(&res[0] == wethalon); |
167 | warr_type res3 = lexical_cast<warr_type>(wethalon); |
168 | BOOST_TEST(&res3[0] == wethalon); |
169 | } |
170 | |
171 | { |
172 | const warr_type res = lexical_cast<warr_type>(val); |
173 | BOOST_TEST(&res[0] == wethalon); |
174 | const warr_type res3 = lexical_cast<warr_type>(wethalon); |
175 | BOOST_TEST(&res3[0] == wethalon); |
176 | } |
177 | |
178 | BOOST_TEST_THROWS(lexical_cast<wshort_arr_type>(val), boost::bad_lexical_cast); |
179 | |
180 | #endif |
181 | |
182 | #ifdef BOOST_LC_RUNU16 |
183 | typedef ArrayT<char16_t, 300> u16arr_type; |
184 | typedef ArrayT<char16_t, 3> u16short_arr_type; |
185 | std::u16string u16ethalon(u"100" ); |
186 | |
187 | { |
188 | #ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES |
189 | u16arr_type res = lexical_cast<u16arr_type>(val); |
190 | BOOST_TEST(&res[0] == u16ethalon); |
191 | #endif |
192 | |
193 | u16arr_type res3 = lexical_cast<u16arr_type>(u16ethalon); |
194 | BOOST_TEST(&res3[0] == u16ethalon); |
195 | } |
196 | |
197 | { |
198 | #ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES |
199 | const u16arr_type res = lexical_cast<u16arr_type>(val); |
200 | BOOST_TEST(&res[0] == u16ethalon); |
201 | #endif |
202 | const u16arr_type res3 = lexical_cast<u16arr_type>(u16ethalon); |
203 | BOOST_TEST(&res3[0] == u16ethalon); |
204 | } |
205 | |
206 | // Some compillers may throw std::bad_alloc here |
207 | BOOST_TEST_THROWS(lexical_cast<u16short_arr_type>(val), std::exception); |
208 | #endif |
209 | |
210 | #ifdef BOOST_LC_RUNU32 |
211 | typedef ArrayT<char32_t, 300> u32arr_type; |
212 | typedef ArrayT<char32_t, 3> u32short_arr_type; |
213 | std::u32string u32ethalon(U"100" ); |
214 | |
215 | { |
216 | #ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES |
217 | u32arr_type res = lexical_cast<u32arr_type>(val); |
218 | BOOST_TEST(&res[0] == u32ethalon); |
219 | #endif |
220 | u32arr_type res3 = lexical_cast<u32arr_type>(u32ethalon); |
221 | BOOST_TEST(&res3[0] == u32ethalon); |
222 | } |
223 | |
224 | { |
225 | #ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES |
226 | const u32arr_type res = lexical_cast<u32arr_type>(val); |
227 | BOOST_TEST(&res[0] == u32ethalon); |
228 | #endif |
229 | const u32arr_type res3 = lexical_cast<u32arr_type>(u32ethalon); |
230 | BOOST_TEST(&res3[0] == u32ethalon); |
231 | } |
232 | |
233 | // Some compillers may throw std::bad_alloc here |
234 | BOOST_TEST_THROWS(lexical_cast<u32short_arr_type>(val), std::exception); |
235 | #endif |
236 | } |
237 | |
238 | |
239 | void testing_boost_array_output_conversion() |
240 | { |
241 | testing_template_array_output_on_char_value<boost::array>(); |
242 | testing_template_array_output_on_spec_value<boost::array>(val: 100); |
243 | testing_template_array_output_on_spec_value<boost::array>(val: static_cast<short>(100)); |
244 | testing_template_array_output_on_spec_value<boost::array>(val: static_cast<unsigned short>(100)); |
245 | testing_template_array_output_on_spec_value<boost::array>(val: static_cast<unsigned int>(100)); |
246 | } |
247 | |
248 | void testing_std_array_output_conversion() |
249 | { |
250 | #ifndef BOOST_NO_CXX11_HDR_ARRAY |
251 | testing_template_array_output_on_char_value<std::array>(); |
252 | testing_template_array_output_on_spec_value<std::array>(val: 100); |
253 | testing_template_array_output_on_spec_value<std::array>(val: static_cast<short>(100)); |
254 | testing_template_array_output_on_spec_value<std::array>(val: static_cast<unsigned short>(100)); |
255 | testing_template_array_output_on_spec_value<std::array>(val: static_cast<unsigned int>(100)); |
256 | #endif |
257 | |
258 | BOOST_TEST(true); |
259 | } |
260 | |
261 | template <template <class, std::size_t> class ArrayT> |
262 | static void testing_generic_array_input_conversion() |
263 | { |
264 | { |
265 | ArrayT<char, 4> var_zero_terminated = {{ '1', '0', '0', '\0'}}; |
266 | BOOST_TEST_EQ(lexical_cast<std::string>(var_zero_terminated), "100" ); |
267 | BOOST_TEST_EQ(lexical_cast<int>(var_zero_terminated), 100); |
268 | |
269 | ArrayT<char, 3> var_none_terminated = {{ '1', '0', '0'}}; |
270 | BOOST_TEST_EQ(lexical_cast<std::string>(var_none_terminated), "100" ); |
271 | BOOST_TEST_EQ(lexical_cast<short>(var_none_terminated), static_cast<short>(100)); |
272 | |
273 | ArrayT<const char, 4> var_zero_terminated_const_char = {{ '1', '0', '0', '\0'}}; |
274 | BOOST_TEST_EQ(lexical_cast<std::string>(var_zero_terminated_const_char), "100" ); |
275 | |
276 | ArrayT<const char, 3> var_none_terminated_const_char = {{ '1', '0', '0'}}; |
277 | BOOST_TEST_EQ(lexical_cast<std::string>(var_none_terminated_const_char), "100" ); |
278 | |
279 | const ArrayT<char, 4> var_zero_terminated_const_var = {{ '1', '0', '0', '\0'}}; |
280 | BOOST_TEST_EQ(lexical_cast<std::string>(var_zero_terminated_const_var), "100" ); |
281 | |
282 | const ArrayT<char, 3> var_none_terminated_const_var = {{ '1', '0', '0'}}; |
283 | BOOST_TEST_EQ(lexical_cast<std::string>(var_none_terminated_const_var), "100" ); |
284 | |
285 | const ArrayT<const char, 4> var_zero_terminated_const_var_const_char = {{ '1', '0', '0', '\0'}}; |
286 | BOOST_TEST_EQ(lexical_cast<std::string>(var_zero_terminated_const_var_const_char), "100" ); |
287 | |
288 | const ArrayT<const char, 3> var_none_terminated_const_var_const_char = {{ '1', '0', '0'}}; |
289 | BOOST_TEST_EQ(lexical_cast<std::string>(var_none_terminated_const_var_const_char), "100" ); |
290 | BOOST_TEST_EQ(lexical_cast<int>(var_none_terminated_const_var_const_char), 100); |
291 | } |
292 | |
293 | { |
294 | const ArrayT<const unsigned char, 4> var_zero_terminated_const_var_const_char = {{ '1', '0', '0', '\0'}}; |
295 | BOOST_TEST_EQ(lexical_cast<std::string>(var_zero_terminated_const_var_const_char), "100" ); |
296 | |
297 | const ArrayT<const unsigned char, 3> var_none_terminated_const_var_const_char = {{ '1', '0', '0'}}; |
298 | BOOST_TEST_EQ(lexical_cast<std::string>(var_none_terminated_const_var_const_char), "100" ); |
299 | } |
300 | |
301 | { |
302 | const ArrayT<const signed char, 4> var_zero_terminated_const_var_const_char = {{ '1', '0', '0', '\0'}}; |
303 | BOOST_TEST_EQ(lexical_cast<std::string>(var_zero_terminated_const_var_const_char), "100" ); |
304 | |
305 | const ArrayT<const signed char, 3> var_none_terminated_const_var_const_char = {{ '1', '0', '0'}}; |
306 | BOOST_TEST_EQ(lexical_cast<std::string>(var_none_terminated_const_var_const_char), "100" ); |
307 | BOOST_TEST_EQ(lexical_cast<unsigned int>(var_none_terminated_const_var_const_char), 100u); |
308 | } |
309 | |
310 | |
311 | #if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING) |
312 | { |
313 | const ArrayT<const wchar_t, 4> var_zero_terminated_const_var_const_char = {{ L'1', L'0', L'0', L'\0'}}; |
314 | BOOST_TEST(lexical_cast<std::wstring>(var_zero_terminated_const_var_const_char) == L"100" ); |
315 | |
316 | const ArrayT<const wchar_t, 3> var_none_terminated_const_var_const_char = {{ L'1', L'0', L'0'}}; |
317 | BOOST_TEST(lexical_cast<std::wstring>(var_none_terminated_const_var_const_char) == L"100" ); |
318 | BOOST_TEST_EQ(lexical_cast<int>(var_none_terminated_const_var_const_char), 100); |
319 | } |
320 | #endif |
321 | |
322 | #ifdef BOOST_LC_RUNU16 |
323 | { |
324 | const ArrayT<const char16_t, 4> var_zero_terminated_const_var_const_char = {{ u'1', u'0', u'0', u'\0'}}; |
325 | BOOST_TEST(lexical_cast<std::u16string>(var_zero_terminated_const_var_const_char) == u"100" ); |
326 | BOOST_TEST_EQ(lexical_cast<unsigned short>(var_zero_terminated_const_var_const_char), static_cast<unsigned short>(100)); |
327 | |
328 | const ArrayT<const char16_t, 3> var_none_terminated_const_var_const_char = {{ u'1', u'0', u'0'}}; |
329 | BOOST_TEST(lexical_cast<std::u16string>(var_none_terminated_const_var_const_char) == u"100" ); |
330 | } |
331 | #endif |
332 | |
333 | #ifdef BOOST_LC_RUNU32 |
334 | { |
335 | const ArrayT<const char32_t, 4> var_zero_terminated_const_var_const_char = {{ U'1', U'0', U'0', U'\0'}}; |
336 | BOOST_TEST(lexical_cast<std::u32string>(var_zero_terminated_const_var_const_char) == U"100" ); |
337 | |
338 | const ArrayT<const char32_t, 3> var_none_terminated_const_var_const_char = {{ U'1', U'0', U'0'}}; |
339 | BOOST_TEST(lexical_cast<std::u32string>(var_none_terminated_const_var_const_char) == U"100" ); |
340 | BOOST_TEST_EQ(lexical_cast<int>(var_none_terminated_const_var_const_char), 100); |
341 | } |
342 | #endif |
343 | } |
344 | |
345 | void testing_boost_array_input_conversion() |
346 | { |
347 | testing_generic_array_input_conversion<boost::array>(); |
348 | } |
349 | |
350 | void testing_std_array_input_conversion() |
351 | { |
352 | #ifndef BOOST_NO_CXX11_HDR_ARRAY |
353 | testing_generic_array_input_conversion<std::array>(); |
354 | #endif |
355 | |
356 | BOOST_TEST(true); |
357 | } |
358 | |
359 | int main() |
360 | { |
361 | testing_boost_array_output_conversion(); |
362 | testing_std_array_output_conversion(); |
363 | testing_boost_array_input_conversion(); |
364 | testing_std_array_input_conversion(); |
365 | |
366 | return boost::report_errors(); |
367 | } |
368 | |
369 | |