Chris@102
|
1 // Copyright Kevlin Henney, 2000-2005.
|
Chris@102
|
2 // Copyright Alexander Nasonov, 2006-2010.
|
Chris@102
|
3 // Copyright Antony Polukhin, 2011-2014.
|
Chris@102
|
4 //
|
Chris@102
|
5 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@102
|
6 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
8 //
|
Chris@102
|
9 // what: lexical_cast custom keyword cast
|
Chris@102
|
10 // who: contributed by Kevlin Henney,
|
Chris@102
|
11 // enhanced with contributions from Terje Slettebo,
|
Chris@102
|
12 // with additional fixes and suggestions from Gennaro Prota,
|
Chris@102
|
13 // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
|
Chris@102
|
14 // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
|
Chris@102
|
15 // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
|
Chris@102
|
16 // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
|
Chris@102
|
17
|
Chris@102
|
18 #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
|
Chris@102
|
19 #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
|
Chris@102
|
20
|
Chris@102
|
21 #include <boost/config.hpp>
|
Chris@102
|
22 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@102
|
23 # pragma once
|
Chris@102
|
24 #endif
|
Chris@102
|
25
|
Chris@102
|
26 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
|
Chris@102
|
27 #define BOOST_LCAST_NO_WCHAR_T
|
Chris@102
|
28 #endif
|
Chris@102
|
29
|
Chris@102
|
30 #include <cstddef>
|
Chris@102
|
31 #include <string>
|
Chris@102
|
32 #include <boost/limits.hpp>
|
Chris@102
|
33 #include <boost/mpl/if.hpp>
|
Chris@102
|
34 #include <boost/type_traits/ice.hpp>
|
Chris@102
|
35 #include <boost/type_traits/is_integral.hpp>
|
Chris@102
|
36 #include <boost/type_traits/is_float.hpp>
|
Chris@102
|
37 #include <boost/type_traits/has_left_shift.hpp>
|
Chris@102
|
38 #include <boost/type_traits/has_right_shift.hpp>
|
Chris@102
|
39 #include <boost/static_assert.hpp>
|
Chris@102
|
40 #include <boost/detail/lcast_precision.hpp>
|
Chris@102
|
41
|
Chris@102
|
42 #include <boost/lexical_cast/detail/widest_char.hpp>
|
Chris@102
|
43 #include <boost/lexical_cast/detail/is_character.hpp>
|
Chris@102
|
44
|
Chris@102
|
45 #ifndef BOOST_NO_CXX11_HDR_ARRAY
|
Chris@102
|
46 #include <array>
|
Chris@102
|
47 #endif
|
Chris@102
|
48
|
Chris@102
|
49 #include <boost/array.hpp>
|
Chris@102
|
50 #include <boost/range/iterator_range_core.hpp>
|
Chris@102
|
51 #include <boost/container/container_fwd.hpp>
|
Chris@102
|
52
|
Chris@102
|
53 #include <boost/lexical_cast/detail/converter_lexical_streams.hpp>
|
Chris@102
|
54
|
Chris@102
|
55 namespace boost {
|
Chris@102
|
56
|
Chris@102
|
57 namespace detail // normalize_single_byte_char<Char>
|
Chris@102
|
58 {
|
Chris@102
|
59 // Converts signed/unsigned char to char
|
Chris@102
|
60 template < class Char >
|
Chris@102
|
61 struct normalize_single_byte_char
|
Chris@102
|
62 {
|
Chris@102
|
63 typedef Char type;
|
Chris@102
|
64 };
|
Chris@102
|
65
|
Chris@102
|
66 template <>
|
Chris@102
|
67 struct normalize_single_byte_char< signed char >
|
Chris@102
|
68 {
|
Chris@102
|
69 typedef char type;
|
Chris@102
|
70 };
|
Chris@102
|
71
|
Chris@102
|
72 template <>
|
Chris@102
|
73 struct normalize_single_byte_char< unsigned char >
|
Chris@102
|
74 {
|
Chris@102
|
75 typedef char type;
|
Chris@102
|
76 };
|
Chris@102
|
77 }
|
Chris@102
|
78
|
Chris@102
|
79 namespace detail // deduce_character_type_later<T>
|
Chris@102
|
80 {
|
Chris@102
|
81 // Helper type, meaning that stram character for T must be deduced
|
Chris@102
|
82 // at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
|
Chris@102
|
83 template < class T > struct deduce_character_type_later {};
|
Chris@102
|
84 }
|
Chris@102
|
85
|
Chris@102
|
86 namespace detail // stream_char_common<T>
|
Chris@102
|
87 {
|
Chris@102
|
88 // Selectors to choose stream character type (common for Source and Target)
|
Chris@102
|
89 // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later<T> types
|
Chris@102
|
90 // Executed on Stage 1 (See deduce_source_char<T> and deduce_target_char<T>)
|
Chris@102
|
91 template < typename Type >
|
Chris@102
|
92 struct stream_char_common: public boost::mpl::if_c<
|
Chris@102
|
93 boost::detail::is_character< Type >::value,
|
Chris@102
|
94 Type,
|
Chris@102
|
95 boost::detail::deduce_character_type_later< Type >
|
Chris@102
|
96 > {};
|
Chris@102
|
97
|
Chris@102
|
98 template < typename Char >
|
Chris@102
|
99 struct stream_char_common< Char* >: public boost::mpl::if_c<
|
Chris@102
|
100 boost::detail::is_character< Char >::value,
|
Chris@102
|
101 Char,
|
Chris@102
|
102 boost::detail::deduce_character_type_later< Char* >
|
Chris@102
|
103 > {};
|
Chris@102
|
104
|
Chris@102
|
105 template < typename Char >
|
Chris@102
|
106 struct stream_char_common< const Char* >: public boost::mpl::if_c<
|
Chris@102
|
107 boost::detail::is_character< Char >::value,
|
Chris@102
|
108 Char,
|
Chris@102
|
109 boost::detail::deduce_character_type_later< const Char* >
|
Chris@102
|
110 > {};
|
Chris@102
|
111
|
Chris@102
|
112 template < typename Char >
|
Chris@102
|
113 struct stream_char_common< boost::iterator_range< Char* > >: public boost::mpl::if_c<
|
Chris@102
|
114 boost::detail::is_character< Char >::value,
|
Chris@102
|
115 Char,
|
Chris@102
|
116 boost::detail::deduce_character_type_later< boost::iterator_range< Char* > >
|
Chris@102
|
117 > {};
|
Chris@102
|
118
|
Chris@102
|
119 template < typename Char >
|
Chris@102
|
120 struct stream_char_common< boost::iterator_range< const Char* > >: public boost::mpl::if_c<
|
Chris@102
|
121 boost::detail::is_character< Char >::value,
|
Chris@102
|
122 Char,
|
Chris@102
|
123 boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > >
|
Chris@102
|
124 > {};
|
Chris@102
|
125
|
Chris@102
|
126 template < class Char, class Traits, class Alloc >
|
Chris@102
|
127 struct stream_char_common< std::basic_string< Char, Traits, Alloc > >
|
Chris@102
|
128 {
|
Chris@102
|
129 typedef Char type;
|
Chris@102
|
130 };
|
Chris@102
|
131
|
Chris@102
|
132 template < class Char, class Traits, class Alloc >
|
Chris@102
|
133 struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > >
|
Chris@102
|
134 {
|
Chris@102
|
135 typedef Char type;
|
Chris@102
|
136 };
|
Chris@102
|
137
|
Chris@102
|
138 template < typename Char, std::size_t N >
|
Chris@102
|
139 struct stream_char_common< boost::array< Char, N > >: public boost::mpl::if_c<
|
Chris@102
|
140 boost::detail::is_character< Char >::value,
|
Chris@102
|
141 Char,
|
Chris@102
|
142 boost::detail::deduce_character_type_later< boost::array< Char, N > >
|
Chris@102
|
143 > {};
|
Chris@102
|
144
|
Chris@102
|
145 template < typename Char, std::size_t N >
|
Chris@102
|
146 struct stream_char_common< boost::array< const Char, N > >: public boost::mpl::if_c<
|
Chris@102
|
147 boost::detail::is_character< Char >::value,
|
Chris@102
|
148 Char,
|
Chris@102
|
149 boost::detail::deduce_character_type_later< boost::array< const Char, N > >
|
Chris@102
|
150 > {};
|
Chris@102
|
151
|
Chris@102
|
152 #ifndef BOOST_NO_CXX11_HDR_ARRAY
|
Chris@102
|
153 template < typename Char, std::size_t N >
|
Chris@102
|
154 struct stream_char_common< std::array<Char, N > >: public boost::mpl::if_c<
|
Chris@102
|
155 boost::detail::is_character< Char >::value,
|
Chris@102
|
156 Char,
|
Chris@102
|
157 boost::detail::deduce_character_type_later< std::array< Char, N > >
|
Chris@102
|
158 > {};
|
Chris@102
|
159
|
Chris@102
|
160 template < typename Char, std::size_t N >
|
Chris@102
|
161 struct stream_char_common< std::array< const Char, N > >: public boost::mpl::if_c<
|
Chris@102
|
162 boost::detail::is_character< Char >::value,
|
Chris@102
|
163 Char,
|
Chris@102
|
164 boost::detail::deduce_character_type_later< std::array< const Char, N > >
|
Chris@102
|
165 > {};
|
Chris@102
|
166 #endif
|
Chris@102
|
167
|
Chris@102
|
168 #ifdef BOOST_HAS_INT128
|
Chris@102
|
169 template <> struct stream_char_common< boost::int128_type >: public boost::mpl::identity< char > {};
|
Chris@102
|
170 template <> struct stream_char_common< boost::uint128_type >: public boost::mpl::identity< char > {};
|
Chris@102
|
171 #endif
|
Chris@102
|
172
|
Chris@102
|
173 #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
Chris@102
|
174 template <>
|
Chris@102
|
175 struct stream_char_common< wchar_t >
|
Chris@102
|
176 {
|
Chris@102
|
177 typedef char type;
|
Chris@102
|
178 };
|
Chris@102
|
179 #endif
|
Chris@102
|
180 }
|
Chris@102
|
181
|
Chris@102
|
182 namespace detail // deduce_source_char_impl<T>
|
Chris@102
|
183 {
|
Chris@102
|
184 // If type T is `deduce_character_type_later` type, then tries to deduce
|
Chris@102
|
185 // character type using boost::has_left_shift<T> metafunction.
|
Chris@102
|
186 // Otherwise supplied type T is a character type, that must be normalized
|
Chris@102
|
187 // using normalize_single_byte_char<Char>.
|
Chris@102
|
188 // Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
|
Chris@102
|
189 template < class Char >
|
Chris@102
|
190 struct deduce_source_char_impl
|
Chris@102
|
191 {
|
Chris@102
|
192 typedef BOOST_DEDUCED_TYPENAME boost::detail::normalize_single_byte_char< Char >::type type;
|
Chris@102
|
193 };
|
Chris@102
|
194
|
Chris@102
|
195 template < class T >
|
Chris@102
|
196 struct deduce_source_char_impl< deduce_character_type_later< T > >
|
Chris@102
|
197 {
|
Chris@102
|
198 typedef boost::has_left_shift< std::basic_ostream< char >, T > result_t;
|
Chris@102
|
199
|
Chris@102
|
200 #if defined(BOOST_LCAST_NO_WCHAR_T)
|
Chris@102
|
201 BOOST_STATIC_ASSERT_MSG((result_t::value),
|
Chris@102
|
202 "Source type is not std::ostream`able and std::wostream`s are not supported by your STL implementation");
|
Chris@102
|
203 typedef char type;
|
Chris@102
|
204 #else
|
Chris@102
|
205 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
|
Chris@102
|
206 result_t::value, char, wchar_t
|
Chris@102
|
207 >::type type;
|
Chris@102
|
208
|
Chris@102
|
209 BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_left_shift< std::basic_ostream< type >, T >::value),
|
Chris@102
|
210 "Source type is neither std::ostream`able nor std::wostream`able");
|
Chris@102
|
211 #endif
|
Chris@102
|
212 };
|
Chris@102
|
213 }
|
Chris@102
|
214
|
Chris@102
|
215 namespace detail // deduce_target_char_impl<T>
|
Chris@102
|
216 {
|
Chris@102
|
217 // If type T is `deduce_character_type_later` type, then tries to deduce
|
Chris@102
|
218 // character type using boost::has_right_shift<T> metafunction.
|
Chris@102
|
219 // Otherwise supplied type T is a character type, that must be normalized
|
Chris@102
|
220 // using normalize_single_byte_char<Char>.
|
Chris@102
|
221 // Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
|
Chris@102
|
222 template < class Char >
|
Chris@102
|
223 struct deduce_target_char_impl
|
Chris@102
|
224 {
|
Chris@102
|
225 typedef BOOST_DEDUCED_TYPENAME normalize_single_byte_char< Char >::type type;
|
Chris@102
|
226 };
|
Chris@102
|
227
|
Chris@102
|
228 template < class T >
|
Chris@102
|
229 struct deduce_target_char_impl< deduce_character_type_later<T> >
|
Chris@102
|
230 {
|
Chris@102
|
231 typedef boost::has_right_shift<std::basic_istream<char>, T > result_t;
|
Chris@102
|
232
|
Chris@102
|
233 #if defined(BOOST_LCAST_NO_WCHAR_T)
|
Chris@102
|
234 BOOST_STATIC_ASSERT_MSG((result_t::value),
|
Chris@102
|
235 "Target type is not std::istream`able and std::wistream`s are not supported by your STL implementation");
|
Chris@102
|
236 typedef char type;
|
Chris@102
|
237 #else
|
Chris@102
|
238 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
|
Chris@102
|
239 result_t::value, char, wchar_t
|
Chris@102
|
240 >::type type;
|
Chris@102
|
241
|
Chris@102
|
242 BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value),
|
Chris@102
|
243 "Target type is neither std::istream`able nor std::wistream`able");
|
Chris@102
|
244 #endif
|
Chris@102
|
245 };
|
Chris@102
|
246 }
|
Chris@102
|
247
|
Chris@102
|
248 namespace detail // deduce_target_char<T> and deduce_source_char<T>
|
Chris@102
|
249 {
|
Chris@102
|
250 // We deduce stream character types in two stages.
|
Chris@102
|
251 //
|
Chris@102
|
252 // Stage 1 is common for Target and Source. At Stage 1 we get
|
Chris@102
|
253 // non normalized character type (may contain unsigned/signed char)
|
Chris@102
|
254 // or deduce_character_type_later<T> where T is the original type.
|
Chris@102
|
255 // Stage 1 is executed by stream_char_common<T>
|
Chris@102
|
256 //
|
Chris@102
|
257 // At Stage 2 we normalize character types or try to deduce character
|
Chris@102
|
258 // type using metafunctions.
|
Chris@102
|
259 // Stage 2 is executed by deduce_target_char_impl<T> and
|
Chris@102
|
260 // deduce_source_char_impl<T>
|
Chris@102
|
261 //
|
Chris@102
|
262 // deduce_target_char<T> and deduce_source_char<T> functions combine
|
Chris@102
|
263 // both stages
|
Chris@102
|
264
|
Chris@102
|
265 template < class T >
|
Chris@102
|
266 struct deduce_target_char
|
Chris@102
|
267 {
|
Chris@102
|
268 typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type;
|
Chris@102
|
269 typedef BOOST_DEDUCED_TYPENAME deduce_target_char_impl< stage1_type >::type stage2_type;
|
Chris@102
|
270
|
Chris@102
|
271 typedef stage2_type type;
|
Chris@102
|
272 };
|
Chris@102
|
273
|
Chris@102
|
274 template < class T >
|
Chris@102
|
275 struct deduce_source_char
|
Chris@102
|
276 {
|
Chris@102
|
277 typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type;
|
Chris@102
|
278 typedef BOOST_DEDUCED_TYPENAME deduce_source_char_impl< stage1_type >::type stage2_type;
|
Chris@102
|
279
|
Chris@102
|
280 typedef stage2_type type;
|
Chris@102
|
281 };
|
Chris@102
|
282 }
|
Chris@102
|
283
|
Chris@102
|
284 namespace detail // extract_char_traits template
|
Chris@102
|
285 {
|
Chris@102
|
286 // We are attempting to get char_traits<> from T
|
Chris@102
|
287 // template parameter. Otherwise we'll be using std::char_traits<Char>
|
Chris@102
|
288 template < class Char, class T >
|
Chris@102
|
289 struct extract_char_traits
|
Chris@102
|
290 : boost::false_type
|
Chris@102
|
291 {
|
Chris@102
|
292 typedef std::char_traits< Char > trait_t;
|
Chris@102
|
293 };
|
Chris@102
|
294
|
Chris@102
|
295 template < class Char, class Traits, class Alloc >
|
Chris@102
|
296 struct extract_char_traits< Char, std::basic_string< Char, Traits, Alloc > >
|
Chris@102
|
297 : boost::true_type
|
Chris@102
|
298 {
|
Chris@102
|
299 typedef Traits trait_t;
|
Chris@102
|
300 };
|
Chris@102
|
301
|
Chris@102
|
302 template < class Char, class Traits, class Alloc>
|
Chris@102
|
303 struct extract_char_traits< Char, boost::container::basic_string< Char, Traits, Alloc > >
|
Chris@102
|
304 : boost::true_type
|
Chris@102
|
305 {
|
Chris@102
|
306 typedef Traits trait_t;
|
Chris@102
|
307 };
|
Chris@102
|
308 }
|
Chris@102
|
309
|
Chris@102
|
310 namespace detail // array_to_pointer_decay<T>
|
Chris@102
|
311 {
|
Chris@102
|
312 template<class T>
|
Chris@102
|
313 struct array_to_pointer_decay
|
Chris@102
|
314 {
|
Chris@102
|
315 typedef T type;
|
Chris@102
|
316 };
|
Chris@102
|
317
|
Chris@102
|
318 template<class T, std::size_t N>
|
Chris@102
|
319 struct array_to_pointer_decay<T[N]>
|
Chris@102
|
320 {
|
Chris@102
|
321 typedef const T * type;
|
Chris@102
|
322 };
|
Chris@102
|
323 }
|
Chris@102
|
324
|
Chris@102
|
325 namespace detail // lcast_src_length
|
Chris@102
|
326 {
|
Chris@102
|
327 // Return max. length of string representation of Source;
|
Chris@102
|
328 template< class Source, // Source type of lexical_cast.
|
Chris@102
|
329 class Enable = void // helper type
|
Chris@102
|
330 >
|
Chris@102
|
331 struct lcast_src_length
|
Chris@102
|
332 {
|
Chris@102
|
333 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
|
Chris@102
|
334 };
|
Chris@102
|
335
|
Chris@102
|
336 // Helper for integral types.
|
Chris@102
|
337 // Notes on length calculation:
|
Chris@102
|
338 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
|
Chris@102
|
339 // "-2,1,4,7,4,8,3,6,4,7"
|
Chris@102
|
340 // ^ - is_signed
|
Chris@102
|
341 // ^ - 1 digit not counted by digits10
|
Chris@102
|
342 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
|
Chris@102
|
343 //
|
Chris@102
|
344 // Constant is_specialized is used instead of constant 1
|
Chris@102
|
345 // to prevent buffer overflow in a rare case when
|
Chris@102
|
346 // <boost/limits.hpp> doesn't add missing specialization for
|
Chris@102
|
347 // numeric_limits<T> for some integral type T.
|
Chris@102
|
348 // When is_specialized is false, the whole expression is 0.
|
Chris@102
|
349 template <class Source>
|
Chris@102
|
350 struct lcast_src_length<
|
Chris@102
|
351 Source, BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_integral<Source> >::type
|
Chris@102
|
352 >
|
Chris@102
|
353 {
|
Chris@102
|
354 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
Chris@102
|
355 BOOST_STATIC_CONSTANT(std::size_t, value =
|
Chris@102
|
356 std::numeric_limits<Source>::is_signed +
|
Chris@102
|
357 std::numeric_limits<Source>::is_specialized + /* == 1 */
|
Chris@102
|
358 std::numeric_limits<Source>::digits10 * 2
|
Chris@102
|
359 );
|
Chris@102
|
360 #else
|
Chris@102
|
361 BOOST_STATIC_CONSTANT(std::size_t, value = 156);
|
Chris@102
|
362 BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
|
Chris@102
|
363 #endif
|
Chris@102
|
364 };
|
Chris@102
|
365
|
Chris@102
|
366 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
Chris@102
|
367 // Helper for floating point types.
|
Chris@102
|
368 // -1.23456789e-123456
|
Chris@102
|
369 // ^ sign
|
Chris@102
|
370 // ^ leading digit
|
Chris@102
|
371 // ^ decimal point
|
Chris@102
|
372 // ^^^^^^^^ lcast_precision<Source>::value
|
Chris@102
|
373 // ^ "e"
|
Chris@102
|
374 // ^ exponent sign
|
Chris@102
|
375 // ^^^^^^ exponent (assumed 6 or less digits)
|
Chris@102
|
376 // sign + leading digit + decimal point + "e" + exponent sign == 5
|
Chris@102
|
377 template<class Source>
|
Chris@102
|
378 struct lcast_src_length<
|
Chris@102
|
379 Source, BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_float<Source> >::type
|
Chris@102
|
380 >
|
Chris@102
|
381 {
|
Chris@102
|
382 BOOST_STATIC_ASSERT(
|
Chris@102
|
383 std::numeric_limits<Source>::max_exponent10 <= 999999L &&
|
Chris@102
|
384 std::numeric_limits<Source>::min_exponent10 >= -999999L
|
Chris@102
|
385 );
|
Chris@102
|
386
|
Chris@102
|
387 BOOST_STATIC_CONSTANT(std::size_t, value =
|
Chris@102
|
388 5 + lcast_precision<Source>::value + 6
|
Chris@102
|
389 );
|
Chris@102
|
390 };
|
Chris@102
|
391 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
Chris@102
|
392 }
|
Chris@102
|
393
|
Chris@102
|
394 namespace detail // lexical_cast_stream_traits<Source, Target>
|
Chris@102
|
395 {
|
Chris@102
|
396 template <class Source, class Target>
|
Chris@102
|
397 struct lexical_cast_stream_traits {
|
Chris@102
|
398 typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay<Source>::type src;
|
Chris@102
|
399 typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<src>::type no_cv_src;
|
Chris@102
|
400
|
Chris@102
|
401 typedef boost::detail::deduce_source_char<no_cv_src> deduce_src_char_metafunc;
|
Chris@102
|
402 typedef BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::type src_char_t;
|
Chris@102
|
403 typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char<Target>::type target_char_t;
|
Chris@102
|
404
|
Chris@102
|
405 typedef BOOST_DEDUCED_TYPENAME boost::detail::widest_char<
|
Chris@102
|
406 target_char_t, src_char_t
|
Chris@102
|
407 >::type char_type;
|
Chris@102
|
408
|
Chris@102
|
409 #if !defined(BOOST_NO_CXX11_CHAR16_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
|
Chris@102
|
410 BOOST_STATIC_ASSERT_MSG(( !boost::is_same<char16_t, src_char_t>::value
|
Chris@102
|
411 && !boost::is_same<char16_t, target_char_t>::value),
|
Chris@102
|
412 "Your compiler does not have full support for char16_t" );
|
Chris@102
|
413 #endif
|
Chris@102
|
414 #if !defined(BOOST_NO_CXX11_CHAR32_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
|
Chris@102
|
415 BOOST_STATIC_ASSERT_MSG(( !boost::is_same<char32_t, src_char_t>::value
|
Chris@102
|
416 && !boost::is_same<char32_t, target_char_t>::value),
|
Chris@102
|
417 "Your compiler does not have full support for char32_t" );
|
Chris@102
|
418 #endif
|
Chris@102
|
419
|
Chris@102
|
420 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
|
Chris@102
|
421 boost::detail::extract_char_traits<char_type, Target>::value,
|
Chris@102
|
422 BOOST_DEDUCED_TYPENAME boost::detail::extract_char_traits<char_type, Target>,
|
Chris@102
|
423 BOOST_DEDUCED_TYPENAME boost::detail::extract_char_traits<char_type, no_cv_src>
|
Chris@102
|
424 >::type::trait_t traits;
|
Chris@102
|
425
|
Chris@102
|
426 typedef boost::type_traits::ice_and<
|
Chris@102
|
427 boost::is_same<char, src_char_t>::value, // source is not a wide character based type
|
Chris@102
|
428 boost::type_traits::ice_ne<sizeof(char), sizeof(target_char_t) >::value, // target type is based on wide character
|
Chris@102
|
429 boost::type_traits::ice_not<
|
Chris@102
|
430 boost::detail::is_character<no_cv_src>::value // single character widening is optimized
|
Chris@102
|
431 >::value // and does not requires stringbuffer
|
Chris@102
|
432 > is_string_widening_required_t;
|
Chris@102
|
433
|
Chris@102
|
434 typedef boost::type_traits::ice_not< boost::type_traits::ice_or<
|
Chris@102
|
435 boost::is_integral<no_cv_src>::value,
|
Chris@102
|
436 boost::detail::is_character<
|
Chris@102
|
437 BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1
|
Chris@102
|
438 >::value // then we have no optimization for that type
|
Chris@102
|
439 >::value > is_source_input_not_optimized_t;
|
Chris@102
|
440
|
Chris@102
|
441 // If we have an optimized conversion for
|
Chris@102
|
442 // Source, we do not need to construct stringbuf.
|
Chris@102
|
443 BOOST_STATIC_CONSTANT(bool, requires_stringbuf =
|
Chris@102
|
444 (boost::type_traits::ice_or<
|
Chris@102
|
445 is_string_widening_required_t::value, is_source_input_not_optimized_t::value
|
Chris@102
|
446 >::value)
|
Chris@102
|
447 );
|
Chris@102
|
448
|
Chris@102
|
449 typedef boost::detail::lcast_src_length<no_cv_src> len_t;
|
Chris@102
|
450 };
|
Chris@102
|
451 }
|
Chris@102
|
452
|
Chris@102
|
453 namespace detail
|
Chris@102
|
454 {
|
Chris@102
|
455 template<typename Target, typename Source>
|
Chris@102
|
456 struct lexical_converter_impl
|
Chris@102
|
457 {
|
Chris@102
|
458 typedef lexical_cast_stream_traits<Source, Target> stream_trait;
|
Chris@102
|
459
|
Chris@102
|
460 typedef detail::lexical_istream_limited_src<
|
Chris@102
|
461 BOOST_DEDUCED_TYPENAME stream_trait::char_type,
|
Chris@102
|
462 BOOST_DEDUCED_TYPENAME stream_trait::traits,
|
Chris@102
|
463 stream_trait::requires_stringbuf,
|
Chris@102
|
464 stream_trait::len_t::value + 1
|
Chris@102
|
465 > i_interpreter_type;
|
Chris@102
|
466
|
Chris@102
|
467 typedef detail::lexical_ostream_limited_src<
|
Chris@102
|
468 BOOST_DEDUCED_TYPENAME stream_trait::char_type,
|
Chris@102
|
469 BOOST_DEDUCED_TYPENAME stream_trait::traits
|
Chris@102
|
470 > o_interpreter_type;
|
Chris@102
|
471
|
Chris@102
|
472 static inline bool try_convert(const Source& arg, Target& result) {
|
Chris@102
|
473 i_interpreter_type i_interpreter;
|
Chris@102
|
474
|
Chris@102
|
475 // Disabling ADL, by directly specifying operators.
|
Chris@102
|
476 if (!(i_interpreter.operator <<(arg)))
|
Chris@102
|
477 return false;
|
Chris@102
|
478
|
Chris@102
|
479 o_interpreter_type out(i_interpreter.cbegin(), i_interpreter.cend());
|
Chris@102
|
480
|
Chris@102
|
481 // Disabling ADL, by directly specifying operators.
|
Chris@102
|
482 if(!(out.operator >>(result)))
|
Chris@102
|
483 return false;
|
Chris@102
|
484
|
Chris@102
|
485 return true;
|
Chris@102
|
486 }
|
Chris@102
|
487 };
|
Chris@102
|
488 }
|
Chris@102
|
489
|
Chris@102
|
490 } // namespace boost
|
Chris@102
|
491
|
Chris@102
|
492 #undef BOOST_LCAST_NO_WCHAR_T
|
Chris@102
|
493
|
Chris@102
|
494 #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
|
Chris@102
|
495
|