1 #ifndef BOOST_LEXICAL_CAST_INCLUDED
2 #define BOOST_LEXICAL_CAST_INCLUDED
3 
4 // MS compatible compilers support #pragma once
5 
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 # pragma once
8 #endif
9 
10 // Boost lexical_cast.hpp header  -------------------------------------------//
11 //
12 // See http://www.boost.org/libs/conversion for documentation.
13 // See end of this header for rights and permissions.
14 //
15 // what:  lexical_cast custom keyword cast
16 // who:   contributed by Kevlin Henney,
17 //        enhanced with contributions from Terje Slettebo,
18 //        with additional fixes and suggestions from Gennaro Prota,
19 //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
20 //        Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
21 //        Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
22 // when:  November 2000, March 2003, June 2005, June 2006, March 2011 - 2012
23 
24 #include <boost/config.hpp>
25 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
26 #define BOOST_LCAST_NO_WCHAR_T
27 #endif
28 
29 #include <climits>
30 #include <cstddef>
31 #include <string>
32 #include <cstring>
33 #include <cstdio>
34 #include <typeinfo>
35 #include <exception>
36 #include <boost/limits.hpp>
37 #include <boost/mpl/if.hpp>
38 #include <boost/throw_exception.hpp>
39 #include <boost/type_traits/ice.hpp>
40 #include <boost/type_traits/is_pointer.hpp>
41 #include <boost/static_assert.hpp>
42 #include <boost/detail/lcast_precision.hpp>
43 #include <boost/detail/workaround.hpp>
44 
45 
46 #ifndef BOOST_NO_STD_LOCALE
47 #   include <locale>
48 #else
49 #   ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
50         // Getting error at this point means, that your STL library is old/lame/misconfigured.
51         // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
52         // but beware: lexical_cast will understand only 'C' locale delimeters and thousands
53         // separators.
54 #       error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
55 #       error "boost::lexical_cast to use only 'C' locale during conversions."
56 #   endif
57 #endif
58 
59 #ifdef BOOST_NO_STRINGSTREAM
60 #include <strstream>
61 #else
62 #include <sstream>
63 #endif
64 
65 #ifdef BOOST_NO_TYPEID
66 #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast())
67 #else
68 #define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \
69     throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)))
70 #endif
71 
72 namespace boost
73 {
74     // exception used to indicate runtime lexical_cast failure
75     class BOOST_SYMBOL_VISIBLE bad_lexical_cast :
76     // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
77 #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
78         public std::exception
79 #else
80         public std::bad_cast
81 #endif
82 
83 #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
84         // under bcc32 5.5.1 bad_cast doesn't derive from exception
85         , public std::exception
86 #endif
87 
88     {
89     public:
bad_lexical_cast()90         bad_lexical_cast() BOOST_NOEXCEPT :
91 #ifndef BOOST_NO_TYPEID
92           source(&typeid(void)), target(&typeid(void))
93 #else
94           source(0), target(0) // this breaks getters
95 #endif
96         {
97         }
98 
bad_lexical_cast(const std::type_info & source_type_arg,const std::type_info & target_type_arg)99         bad_lexical_cast(
100             const std::type_info &source_type_arg,
101             const std::type_info &target_type_arg) BOOST_NOEXCEPT :
102             source(&source_type_arg), target(&target_type_arg)
103         {
104         }
105 
source_type() const106         const std::type_info &source_type() const
107         {
108             return *source;
109         }
target_type() const110         const std::type_info &target_type() const
111         {
112             return *target;
113         }
114 
115 #ifndef BOOST_NO_NOEXCEPT
what() const116         virtual const char *what() const noexcept
117 #else
118         virtual const char *what() const throw()
119 #endif
120         {
121             return "bad lexical cast: "
122                    "source type value could not be interpreted as target";
123         }
124 
125 #ifndef BOOST_NO_NOEXCEPT
~bad_lexical_cast()126         virtual ~bad_lexical_cast() BOOST_NOEXCEPT
127 #else
128         virtual ~bad_lexical_cast() throw()
129 #endif
130         {}
131     private:
132         const std::type_info *source;
133         const std::type_info *target;
134     };
135 
136     namespace detail // widest_char
137     {
138         template <typename TargetChar, typename SourceChar>
139         struct widest_char
140         {
141             typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
142                 (sizeof(TargetChar) > sizeof(SourceChar))
143                 , TargetChar
144                 , SourceChar >::type type;
145         };
146     }
147 } // namespace boost
148 
149 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) && !defined(__PGIC__)
150 
151 #include <cmath>
152 #include <istream>
153 
154 #if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
155 #include <array>
156 #endif
157 
158 #include <boost/array.hpp>
159 #include <boost/numeric/conversion/cast.hpp>
160 #include <boost/type_traits/make_unsigned.hpp>
161 #include <boost/type_traits/is_signed.hpp>
162 #include <boost/type_traits/is_integral.hpp>
163 #include <boost/type_traits/is_arithmetic.hpp>
164 #include <boost/type_traits/remove_pointer.hpp>
165 #include <boost/math/special_functions/sign.hpp>
166 #include <boost/math/special_functions/fpclassify.hpp>
167 #include <boost/range/iterator_range_core.hpp>
168 #include <boost/container/container_fwd.hpp>
169 #ifndef BOOST_NO_CWCHAR
170 #   include <cwchar>
171 #endif
172 
173 namespace boost {
174     namespace detail // widest_char<...> (continuation)
175     {
176         struct not_a_character_type{};
177 
178         template <typename CharT>
179         struct widest_char<not_a_character_type, CharT >
180         {
181             typedef CharT type;
182         };
183 
184         template <typename CharT>
185         struct widest_char< CharT, not_a_character_type >
186         {
187             typedef CharT type;
188         };
189 
190         template <>
191         struct widest_char< not_a_character_type, not_a_character_type >
192         {
193             typedef char type;
194         };
195     }
196 
197     namespace detail // is_char_or_wchar<...> and stream_char<...> templates
198     {
199         // returns true, if T is one of the character types
200         template <typename T>
201         struct is_char_or_wchar
202         {
203             typedef ::boost::type_traits::ice_or<
204                     ::boost::is_same< T, char >::value,
205                     #ifndef BOOST_LCAST_NO_WCHAR_T
206                         ::boost::is_same< T, wchar_t >::value,
207                     #endif
208                     #ifndef BOOST_NO_CHAR16_T
209                         ::boost::is_same< T, char16_t >::value,
210                     #endif
211                     #ifndef BOOST_NO_CHAR32_T
212                         ::boost::is_same< T, char32_t >::value,
213                     #endif
214                     ::boost::is_same< T, unsigned char >::value,
215                     ::boost::is_same< T, signed char >::value
216             > result_type;
217 
218             BOOST_STATIC_CONSTANT(bool, value = (result_type::value) );
219         };
220 
221         // selectors for choosing stream character type
222         // returns one of char, wchar_t, char16_t, char32_t or not_a_character_type types
223         template <typename Type>
224         struct stream_char
225         {
226             typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
227                 is_char_or_wchar<Type >::value,
228                 Type,
229                 boost::detail::not_a_character_type
230             >::type type;
231         };
232 
233         template <>
234         struct stream_char<unsigned char>
235         {
236             typedef char type;
237         };
238 
239         template <>
240         struct stream_char<signed char>
241         {
242             typedef char type;
243         };
244 
245         template <typename CharT>
246         struct stream_char<CharT*>
247         {
248             typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
249         };
250 
251         template <typename CharT>
252         struct stream_char<const CharT*>
253         {
254             typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
255         };
256 
257         template <typename CharT>
258         struct stream_char<iterator_range<CharT*> >
259         {
260             typedef BOOST_DEDUCED_TYPENAME stream_char<CharT*>::type type;
261         };
262 
263         template <typename CharT>
264         struct stream_char<iterator_range<const CharT*> >
265         {
266             typedef BOOST_DEDUCED_TYPENAME stream_char<const CharT*>::type type;
267         };
268 
269         template <class CharT, class Traits, class Alloc>
270         struct stream_char< std::basic_string<CharT, Traits, Alloc> >
271         {
272             typedef CharT type;
273         };
274 
275         template <class CharT, class Traits, class Alloc>
276         struct stream_char< ::boost::container::basic_string<CharT, Traits, Alloc> >
277         {
278             typedef CharT type;
279         };
280 
281         template<typename CharT, std::size_t N>
282         struct stream_char<boost::array<CharT, N> >
283         {
284             typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
285         };
286 
287         template<typename CharT, std::size_t N>
288         struct stream_char<boost::array<const CharT, N> >
289         {
290             typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
291         };
292 
293 #if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
294         template <typename CharT, std::size_t N>
295         struct stream_char<std::array<CharT, N> >
296         {
297             typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
298         };
299 
300         template <typename CharT, std::size_t N>
301         struct stream_char<std::array<const CharT, N> >
302         {
303             typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
304         };
305 #endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
306 
307 #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T)
308         template<>
309         struct stream_char<wchar_t>
310         {
311             typedef boost::detail::not_a_character_type type;
312         };
313 
314         template<>
315         struct stream_char<wchar_t*>
316         {
317             typedef wchar_t type;
318         };
319 
320         template<>
321         struct stream_char<const wchar_t*>
322         {
323             typedef wchar_t type;
324         };
325 #endif
326     }
327 
328     namespace detail // deduce_char_traits template
329     {
330 
331         template<class CharT, class Target, class Source>
332         struct deduce_char_traits
333         {
334             typedef std::char_traits<CharT> type;
335         };
336 
337         template<class CharT, class Traits, class Alloc, class Source>
338         struct deduce_char_traits< CharT
339                                  , std::basic_string<CharT,Traits,Alloc>
340                                  , Source
341                                  >
342         {
343             typedef Traits type;
344         };
345 
346         template<class CharT, class Target, class Traits, class Alloc>
347         struct deduce_char_traits< CharT
348                                  , Target
349                                  , std::basic_string<CharT,Traits,Alloc>
350                                  >
351         {
352             typedef Traits type;
353         };
354 
355         template<class CharT, class Traits, class Alloc, class Source>
356         struct deduce_char_traits< CharT
357                                  , ::boost::container::basic_string<CharT,Traits,Alloc>
358                                  , Source
359                                  >
360         {
361             typedef Traits type;
362         };
363 
364         template<class CharT, class Target, class Traits, class Alloc>
365         struct deduce_char_traits< CharT
366                                  , Target
367                                  , ::boost::container::basic_string<CharT,Traits,Alloc>
368                                  >
369         {
370             typedef Traits type;
371         };
372 
373         template<class CharT, class Traits, class Alloc1, class Alloc2>
374         struct deduce_char_traits< CharT
375                                  , std::basic_string<CharT,Traits,Alloc1>
376                                  , std::basic_string<CharT,Traits,Alloc2>
377                                  >
378         {
379             typedef Traits type;
380         };
381 
382         template<class CharT, class Traits, class Alloc1, class Alloc2>
383         struct deduce_char_traits< CharT
384                                  , ::boost::container::basic_string<CharT,Traits,Alloc1>
385                                  , ::boost::container::basic_string<CharT,Traits,Alloc2>
386                                  >
387         {
388             typedef Traits type;
389         };
390 
391         template<class CharT, class Traits, class Alloc1, class Alloc2>
392         struct deduce_char_traits< CharT
393                                  , ::boost::container::basic_string<CharT,Traits,Alloc1>
394                                  , ::std::basic_string<CharT,Traits,Alloc2>
395                                  >
396         {
397             typedef Traits type;
398         };
399 
400         template<class CharT, class Traits, class Alloc1, class Alloc2>
401         struct deduce_char_traits< CharT
402                                  , ::std::basic_string<CharT,Traits,Alloc1>
403                                  , ::boost::container::basic_string<CharT,Traits,Alloc2>
404                                  >
405         {
406             typedef Traits type;
407         };
408     }
409 
410     namespace detail // lcast_src_length
411     {
412         // Return max. length of string representation of Source;
413         template< class Source // Source type of lexical_cast.
414                 >
415         struct lcast_src_length
416         {
417             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
418             // To check coverage, build the test with
419             // bjam --v2 profile optimization=off
check_coverageboost::detail::lcast_src_length420             static void check_coverage() {}
421         };
422 
423         // Helper for integral types.
424         // Notes on length calculation:
425         // Max length for 32bit int with grouping "\1" and thousands_sep ',':
426         // "-2,1,4,7,4,8,3,6,4,7"
427         //  ^                    - is_signed
428         //   ^                   - 1 digit not counted by digits10
429         //    ^^^^^^^^^^^^^^^^^^ - digits10 * 2
430         //
431         // Constant is_specialized is used instead of constant 1
432         // to prevent buffer overflow in a rare case when
433         // <boost/limits.hpp> doesn't add missing specialization for
434         // numeric_limits<T> for some integral type T.
435         // When is_specialized is false, the whole expression is 0.
436         template<class Source>
437         struct lcast_src_length_integral
438         {
439 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
440             BOOST_STATIC_CONSTANT(std::size_t, value =
441                   std::numeric_limits<Source>::is_signed +
442                   std::numeric_limits<Source>::is_specialized + /* == 1 */
443                   std::numeric_limits<Source>::digits10 * 2
444               );
445 #else
446             BOOST_STATIC_CONSTANT(std::size_t, value = 156);
447             BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
448 #endif
449         };
450 
451 #define BOOST_LCAST_DEF(T)               \
452     template<> struct lcast_src_length<T> \
453         : lcast_src_length_integral<T>           \
454     { static void check_coverage() {} };
455 
456         BOOST_LCAST_DEF(short)
457         BOOST_LCAST_DEF(unsigned short)
458         BOOST_LCAST_DEF(int)
459         BOOST_LCAST_DEF(unsigned int)
460         BOOST_LCAST_DEF(long)
461         BOOST_LCAST_DEF(unsigned long)
462 #if defined(BOOST_HAS_LONG_LONG)
463         BOOST_LCAST_DEF(boost::ulong_long_type)
464         BOOST_LCAST_DEF(boost::long_long_type )
465 #elif defined(BOOST_HAS_MS_INT64)
466         BOOST_LCAST_DEF(unsigned __int64)
467         BOOST_LCAST_DEF(         __int64)
468 #endif
469 
470 #undef BOOST_LCAST_DEF
471 
472 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
473         // Helper for floating point types.
474         // -1.23456789e-123456
475         // ^                   sign
476         //  ^                  leading digit
477         //   ^                 decimal point
478         //    ^^^^^^^^         lcast_precision<Source>::value
479         //            ^        "e"
480         //             ^       exponent sign
481         //              ^^^^^^ exponent (assumed 6 or less digits)
482         // sign + leading digit + decimal point + "e" + exponent sign == 5
483         template<class Source>
484         struct lcast_src_length_floating
485         {
486             BOOST_STATIC_ASSERT(
487                     std::numeric_limits<Source>::max_exponent10 <=  999999L &&
488                     std::numeric_limits<Source>::min_exponent10 >= -999999L
489                 );
490             BOOST_STATIC_CONSTANT(std::size_t, value =
491                     5 + lcast_precision<Source>::value + 6
492                 );
493         };
494 
495         template<>
496         struct lcast_src_length<float>
497           : lcast_src_length_floating<float>
498         {
check_coverageboost::detail::lcast_src_length499             static void check_coverage() {}
500         };
501 
502         template<>
503         struct lcast_src_length<double>
504           : lcast_src_length_floating<double>
505         {
check_coverageboost::detail::lcast_src_length506             static void check_coverage() {}
507         };
508 
509         template<>
510         struct lcast_src_length<long double>
511           : lcast_src_length_floating<long double>
512         {
check_coverageboost::detail::lcast_src_length513             static void check_coverage() {}
514         };
515 
516 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
517     }
518 
519     namespace detail // '0', '+' and '-' constants
520     {
521         template<typename CharT> struct lcast_char_constants;
522 
523         template<>
524         struct lcast_char_constants<char>
525         {
526             BOOST_STATIC_CONSTANT(char, zero  = '0');
527             BOOST_STATIC_CONSTANT(char, minus = '-');
528             BOOST_STATIC_CONSTANT(char, plus = '+');
529             BOOST_STATIC_CONSTANT(char, lowercase_e = 'e');
530             BOOST_STATIC_CONSTANT(char, capital_e = 'E');
531             BOOST_STATIC_CONSTANT(char, c_decimal_separator = '.');
532         };
533 
534 #ifndef BOOST_LCAST_NO_WCHAR_T
535         template<>
536         struct lcast_char_constants<wchar_t>
537         {
538             BOOST_STATIC_CONSTANT(wchar_t, zero  = L'0');
539             BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
540             BOOST_STATIC_CONSTANT(wchar_t, plus = L'+');
541             BOOST_STATIC_CONSTANT(wchar_t, lowercase_e = L'e');
542             BOOST_STATIC_CONSTANT(wchar_t, capital_e = L'E');
543             BOOST_STATIC_CONSTANT(wchar_t, c_decimal_separator = L'.');
544         };
545 #endif
546 
547 #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS)
548         template<>
549         struct lcast_char_constants<char16_t>
550         {
551             BOOST_STATIC_CONSTANT(char16_t, zero  = u'0');
552             BOOST_STATIC_CONSTANT(char16_t, minus = u'-');
553             BOOST_STATIC_CONSTANT(char16_t, plus = u'+');
554             BOOST_STATIC_CONSTANT(char16_t, lowercase_e = u'e');
555             BOOST_STATIC_CONSTANT(char16_t, capital_e = u'E');
556             BOOST_STATIC_CONSTANT(char16_t, c_decimal_separator = u'.');
557         };
558 #endif
559 
560 #if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS)
561         template<>
562         struct lcast_char_constants<char32_t>
563         {
564             BOOST_STATIC_CONSTANT(char32_t, zero  = U'0');
565             BOOST_STATIC_CONSTANT(char32_t, minus = U'-');
566             BOOST_STATIC_CONSTANT(char32_t, plus = U'+');
567             BOOST_STATIC_CONSTANT(char32_t, lowercase_e = U'e');
568             BOOST_STATIC_CONSTANT(char32_t, capital_e = U'E');
569             BOOST_STATIC_CONSTANT(char32_t, c_decimal_separator = U'.');
570         };
571 #endif
572     }
573 
574     namespace detail // lcast_to_unsigned
575     {
576 #if (defined _MSC_VER)
577 # pragma warning( push )
578 // C4146: unary minus operator applied to unsigned type, result still unsigned
579 # pragma warning( disable : 4146 )
580 #elif defined( __BORLANDC__ )
581 # pragma option push -w-8041
582 #endif
583         template<class T>
584         inline
lcast_to_unsigned(T value)585         BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value) BOOST_NOEXCEPT
586         {
587             typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
588             const result_type uvalue = static_cast<result_type>(value);
589             return value < 0 ? -uvalue : uvalue;
590         }
591 #if (defined _MSC_VER)
592 # pragma warning( pop )
593 #elif defined( __BORLANDC__ )
594 # pragma option pop
595 #endif
596     }
597 
598     namespace detail // lcast_put_unsigned
599     {
600         template<class Traits, class T, class CharT>
lcast_put_unsigned(const T n_param,CharT * finish)601         CharT* lcast_put_unsigned(const T n_param, CharT* finish)
602         {
603 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
604             BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
605 #endif
606 
607             typedef typename Traits::int_type int_type;
608             CharT const czero = lcast_char_constants<CharT>::zero;
609             int_type const zero = Traits::to_int_type(czero);
610             BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
611                     (sizeof(int_type) > sizeof(T))
612                     , int_type
613                     , T
614             >::type n = n_param;
615 
616 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
617             std::locale loc;
618             if (loc != std::locale::classic()) {
619                 typedef std::numpunct<CharT> numpunct;
620                 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
621                 std::string const grouping = np.grouping();
622                 std::string::size_type const grouping_size = grouping.size();
623 
624                 if ( grouping_size && grouping[0] > 0 )
625                 {
626 
627 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
628                 // Check that ulimited group is unreachable:
629                 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
630 #endif
631                     CharT thousands_sep = np.thousands_sep();
632                     std::string::size_type group = 0; // current group number
633                     char last_grp_size = grouping[0];
634                     char left = last_grp_size;
635 
636                     do
637                     {
638                         if(left == 0)
639                         {
640                             ++group;
641                             if(group < grouping_size)
642                             {
643                                 char const grp_size = grouping[group];
644                                 last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
645                             }
646 
647                             left = last_grp_size;
648                             --finish;
649                             Traits::assign(*finish, thousands_sep);
650                         }
651 
652                         --left;
653 
654                         --finish;
655                         int_type const digit = static_cast<int_type>(n % 10U);
656                         Traits::assign(*finish, Traits::to_char_type(zero + digit));
657                         n /= 10;
658                     } while(n);
659                     return finish;
660                 }
661             }
662 #endif
663             {
664                 do
665                 {
666                     --finish;
667                     int_type const digit = static_cast<int_type>(n % 10U);
668                     Traits::assign(*finish, Traits::to_char_type(zero + digit));
669                     n /= 10;
670                 } while(n);
671             }
672 
673             return finish;
674         }
675     }
676 
677     namespace detail // lcast_ret_unsigned
678     {
679         template<class Traits, class T, class CharT>
lcast_ret_unsigned(T & value,const CharT * const begin,const CharT * end)680         inline bool lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end)
681         {
682 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
683             BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
684 #endif
685             typedef typename Traits::int_type int_type;
686             CharT const czero = lcast_char_constants<CharT>::zero;
687             --end;
688             value = 0;
689 
690             if (begin > end || *end < czero || *end >= czero + 10)
691                 return false;
692             value = *end - czero;
693             --end;
694             T multiplier = 1;
695             bool multiplier_overflowed = false;
696 
697 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
698             std::locale loc;
699             if (loc != std::locale::classic()) {
700                 typedef std::numpunct<CharT> numpunct;
701                 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
702                 std::string const& grouping = np.grouping();
703                 std::string::size_type const grouping_size = grouping.size();
704 
705                 /* According to Programming languages - C++
706                  * we MUST check for correct grouping
707                  */
708                 if (grouping_size && grouping[0] > 0)
709                 {
710                     unsigned char current_grouping = 0;
711                     CharT const thousands_sep = np.thousands_sep();
712                     char remained = grouping[current_grouping] - 1;
713                     bool shall_we_return = true;
714 
715                     for(;end>=begin; --end)
716                     {
717                         if (remained) {
718                             T const multiplier_10 = multiplier * 10;
719                             if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true;
720 
721                             T const dig_value = *end - czero;
722                             T const new_sub_value = multiplier_10 * dig_value;
723 
724                             if (*end < czero || *end >= czero + 10
725                                     /* detecting overflow */
726                                     || (dig_value && new_sub_value / dig_value != multiplier_10)
727                                     || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
728                                     || (multiplier_overflowed && dig_value)
729                                     )
730                                 return false;
731 
732                             value += new_sub_value;
733                             multiplier *= 10;
734                             --remained;
735                         } else {
736                             if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false;
737                             {
738                                 /*
739                                  * According to Programming languages - C++
740                                  * Digit grouping is checked. That is, the positions of discarded
741                                  * separators is examined for consistency with
742                                  * use_facet<numpunct<charT> >(loc ).grouping()
743                                  *
744                                  * BUT what if there is no separators at all and grouping()
745                                  * is not empty? Well, we have no extraced separators, so we
746                                  * won`t check them for consistency. This will allow us to
747                                  * work with "C" locale from other locales
748                                  */
749                                 shall_we_return = false;
750                                 break;
751                             } else {
752                                 if ( begin == end ) return false;
753                                 if (current_grouping < grouping_size-1 ) ++current_grouping;
754                                 remained = grouping[current_grouping];
755                             }
756                         }
757                     }
758 
759                     if (shall_we_return) return true;
760                 }
761             }
762 #endif
763             {
764                 while ( begin <= end )
765                 {
766                     T const multiplier_10 = multiplier * 10;
767                     if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true;
768 
769                     T const dig_value = *end - czero;
770                     T const new_sub_value = multiplier_10 * dig_value;
771 
772                     if (*end < czero || *end >= czero + 10
773                             /* detecting overflow */
774                             || (dig_value && new_sub_value / dig_value != multiplier_10)
775                             || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
776                             || (multiplier_overflowed && dig_value)
777                             )
778                         return false;
779 
780                     value += new_sub_value;
781                     multiplier *= 10;
782                     --end;
783                 }
784             }
785             return true;
786         }
787     }
788 
789     namespace detail
790     {
791         template <class CharT>
lc_iequal(const CharT * val,const CharT * lcase,const CharT * ucase,unsigned int len)792         bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) BOOST_NOEXCEPT {
793             for( unsigned int i=0; i < len; ++i ) {
794                 if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false;
795             }
796 
797             return true;
798         }
799 
800         /* Returns true and sets the correct value if found NaN or Inf. */
801         template <class CharT, class T>
parse_inf_nan_impl(const CharT * begin,const CharT * end,T & value,const CharT * lc_NAN,const CharT * lc_nan,const CharT * lc_INFINITY,const CharT * lc_infinity,const CharT opening_brace,const CharT closing_brace)802         inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value
803             , const CharT* lc_NAN, const CharT* lc_nan
804             , const CharT* lc_INFINITY, const CharT* lc_infinity
805             , const CharT opening_brace, const CharT closing_brace) BOOST_NOEXCEPT
806         {
807             using namespace std;
808             if (begin == end) return false;
809             const CharT minus = lcast_char_constants<CharT>::minus;
810             const CharT plus = lcast_char_constants<CharT>::plus;
811             const int inifinity_size = 8;
812 
813             bool has_minus = false;
814             /* Parsing +/- */
815             if( *begin == minus)
816             {
817                 ++ begin;
818                 has_minus = true;
819             }
820             else if( *begin == plus ) ++begin;
821 
822             if( end-begin < 3 ) return false;
823             if( lc_iequal(begin, lc_nan, lc_NAN, 3) )
824             {
825                 begin += 3;
826                 if (end != begin) /* It is 'nan(...)' or some bad input*/
827                 {
828                     if(end-begin<2) return false; // bad input
829                     -- end;
830                     if( *begin != opening_brace || *end != closing_brace) return false; // bad input
831                 }
832 
833                 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN();
834                 else value = (boost::math::changesign) (std::numeric_limits<T>::quiet_NaN());
835                 return true;
836             } else
837             if (( /* 'INF' or 'inf' */
838                   end-begin==3
839                   &&
840                   lc_iequal(begin, lc_infinity, lc_INFINITY, 3)
841                 )
842                 ||
843                 ( /* 'INFINITY' or 'infinity' */
844                   end-begin==inifinity_size
845                   &&
846                   lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size)
847                 )
848              )
849             {
850                 if( !has_minus ) value = std::numeric_limits<T>::infinity();
851                 else value = (boost::math::changesign) (std::numeric_limits<T>::infinity());
852                 return true;
853             }
854 
855             return false;
856         }
857 
858         template <class CharT, class T>
put_inf_nan_impl(CharT * begin,CharT * & end,const T & value,const CharT * lc_nan,const CharT * lc_infinity)859         bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value
860                          , const CharT* lc_nan
861                          , const CharT* lc_infinity) BOOST_NOEXCEPT
862         {
863             using namespace std;
864             const CharT minus = lcast_char_constants<CharT>::minus;
865             if ( (boost::math::isnan)(value) )
866             {
867                 if ( (boost::math::signbit)(value) )
868                 {
869                     *begin = minus;
870                     ++ begin;
871                 }
872 
873                 memcpy(begin, lc_nan, 3 * sizeof(CharT));
874                 end = begin + 3;
875                 return true;
876             } else if ( (boost::math::isinf)(value) )
877             {
878                 if ( (boost::math::signbit)(value) )
879                 {
880                     *begin = minus;
881                     ++ begin;
882                 }
883 
884                 memcpy(begin, lc_infinity, 3 * sizeof(CharT));
885                 end = begin + 3;
886                 return true;
887             }
888 
889             return false;
890         }
891 
892 
893 #ifndef BOOST_LCAST_NO_WCHAR_T
894         template <class T>
parse_inf_nan(const wchar_t * begin,const wchar_t * end,T & value)895         bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) BOOST_NOEXCEPT
896         {
897             return parse_inf_nan_impl(begin, end, value
898                                , L"NAN", L"nan"
899                                , L"INFINITY", L"infinity"
900                                , L'(', L')');
901         }
902 
903         template <class T>
put_inf_nan(wchar_t * begin,wchar_t * & end,const T & value)904         bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) BOOST_NOEXCEPT
905         {
906             return put_inf_nan_impl(begin, end, value, L"nan", L"infinity");
907         }
908 
909 #endif
910 #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS)
911         template <class T>
parse_inf_nan(const char16_t * begin,const char16_t * end,T & value)912         bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) BOOST_NOEXCEPT
913         {
914             return parse_inf_nan_impl(begin, end, value
915                                , u"NAN", u"nan"
916                                , u"INFINITY", u"infinity"
917                                , u'(', u')');
918         }
919 
920         template <class T>
put_inf_nan(char16_t * begin,char16_t * & end,const T & value)921         bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) BOOST_NOEXCEPT
922         {
923             return put_inf_nan_impl(begin, end, value, u"nan", u"infinity");
924         }
925 #endif
926 #if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS)
927         template <class T>
parse_inf_nan(const char32_t * begin,const char32_t * end,T & value)928         bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) BOOST_NOEXCEPT
929         {
930             return parse_inf_nan_impl(begin, end, value
931                                , U"NAN", U"nan"
932                                , U"INFINITY", U"infinity"
933                                , U'(', U')');
934         }
935 
936         template <class T>
put_inf_nan(char32_t * begin,char32_t * & end,const T & value)937         bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) BOOST_NOEXCEPT
938         {
939             return put_inf_nan_impl(begin, end, value, U"nan", U"infinity");
940         }
941 #endif
942 
943         template <class CharT, class T>
parse_inf_nan(const CharT * begin,const CharT * end,T & value)944         bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) BOOST_NOEXCEPT
945         {
946             return parse_inf_nan_impl(begin, end, value
947                                , "NAN", "nan"
948                                , "INFINITY", "infinity"
949                                , '(', ')');
950         }
951 
952         template <class CharT, class T>
put_inf_nan(CharT * begin,CharT * & end,const T & value)953         bool put_inf_nan(CharT* begin, CharT*& end, const T& value) BOOST_NOEXCEPT
954         {
955             return put_inf_nan_impl(begin, end, value, "nan", "infinity");
956         }
957     }
958 
959 
960     namespace detail // lcast_ret_float
961     {
962         template <class T>
963         struct mantissa_holder_type
964         {
965             /* Can not be used with this type */
966         };
967 
968         template <>
969         struct mantissa_holder_type<float>
970         {
971             typedef unsigned int type;
972         };
973 
974         template <>
975         struct mantissa_holder_type<double>
976         {
977 #if defined(BOOST_HAS_LONG_LONG)
978             typedef boost::ulong_long_type type;
979 #elif defined(BOOST_HAS_MS_INT64)
980             typedef unsigned __int64 type;
981 #endif
982         };
983 
984         template<class Traits, class T, class CharT>
lcast_ret_float(T & value,const CharT * begin,const CharT * end)985         inline bool lcast_ret_float(T& value, const CharT* begin, const CharT* end)
986         {
987 
988 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
989             std::locale loc;
990             typedef std::numpunct<CharT> numpunct;
991             numpunct const& np = BOOST_USE_FACET(numpunct, loc);
992             std::string const grouping(
993                     (loc == std::locale::classic())
994                     ? std::string()
995                     : np.grouping()
996             );
997             std::string::size_type const grouping_size = grouping.size();
998             CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0;
999             CharT const decimal_point = np.decimal_point();
1000             bool found_grouping = false;
1001             std::string::size_type last_grouping_pos = grouping_size - 1;
1002 #else
1003             CharT const decimal_point = lcast_char_constants<CharT>::c_decimal_separator;
1004 #endif
1005 
1006             CharT const czero = lcast_char_constants<CharT>::zero;
1007             CharT const minus = lcast_char_constants<CharT>::minus;
1008             CharT const plus = lcast_char_constants<CharT>::plus;
1009             CharT const capital_e = lcast_char_constants<CharT>::capital_e;
1010             CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
1011 
1012             value = static_cast<T>(0);
1013 
1014             if (parse_inf_nan(begin, end, value)) return true;
1015 
1016             typedef typename Traits::int_type int_type;
1017             typedef BOOST_DEDUCED_TYPENAME mantissa_holder_type<T>::type mantissa_type;
1018             int_type const zero = Traits::to_int_type(czero);
1019             if (begin == end) return false;
1020 
1021             /* Getting the plus/minus sign */
1022             bool has_minus = false;
1023             if (Traits::eq(*begin, minus) ) {
1024                 ++ begin;
1025                 has_minus = true;
1026                 if (begin == end) return false;
1027             } else if (Traits::eq(*begin, plus) ) {
1028                 ++begin;
1029                 if (begin == end) return false;
1030             }
1031 
1032             bool found_decimal = false;
1033             bool found_number_before_exp = false;
1034             int pow_of_10 = 0;
1035             mantissa_type mantissa=0;
1036             bool is_mantissa_full = false;
1037 
1038             char length_since_last_delim = 0;
1039 
1040             while ( begin != end )
1041             {
1042                 if (found_decimal) {
1043                     /* We allow no thousand_separators after decimal point */
1044 
1045                     mantissa_type tmp_mantissa = mantissa * 10u;
1046                     if (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) break;
1047                     if ( *begin < czero || *begin >= czero + 10 ) return false;
1048                     if (    is_mantissa_full
1049                             || tmp_mantissa / 10u != mantissa
1050                             || (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) < tmp_mantissa
1051                             ) {
1052                         is_mantissa_full = true;
1053                         ++ begin;
1054                         continue;
1055                     }
1056 
1057                     -- pow_of_10;
1058                     mantissa = tmp_mantissa;
1059                     mantissa += *begin - zero;
1060 
1061                     found_number_before_exp = true;
1062                 } else {
1063 
1064                     if (*begin >= czero && *begin < czero + 10) {
1065 
1066                         /* Checking for mantissa overflow. If overflow will
1067                          * occur, them we only increase multiplyer
1068                          */
1069                         mantissa_type tmp_mantissa = mantissa * 10u;
1070                         if(     !is_mantissa_full
1071                                 && tmp_mantissa / 10u == mantissa
1072                                 && (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) >= tmp_mantissa
1073                             )
1074                         {
1075                             mantissa = tmp_mantissa;
1076                             mantissa += *begin - zero;
1077                         } else
1078                         {
1079                             is_mantissa_full = true;
1080                             ++ pow_of_10;
1081                         }
1082 
1083                         found_number_before_exp = true;
1084                         ++ length_since_last_delim;
1085                     } else if (Traits::eq(*begin, decimal_point) || Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) {
1086 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
1087                         /* If ( we need to check grouping
1088                          *      and (   grouping missmatches
1089                          *              or grouping position is incorrect
1090                          *              or we are using the grouping position 0 twice
1091                          *           )
1092                          *    ) then return error
1093                          */
1094                         if( grouping_size && found_grouping
1095                             && (
1096                                    length_since_last_delim != grouping[0]
1097                                    || last_grouping_pos>1
1098                                    || (last_grouping_pos==0 && grouping_size>1)
1099                                 )
1100                            ) return false;
1101 #endif
1102 
1103                         if(Traits::eq(*begin, decimal_point)) {
1104                             ++ begin;
1105                             found_decimal = true;
1106                             if (!found_number_before_exp && begin==end) return false;
1107                             continue;
1108                         }else {
1109                             if (!found_number_before_exp) return false;
1110                             break;
1111                         }
1112                     }
1113 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
1114                     else if (grouping_size && Traits::eq(*begin, thousands_sep)){
1115                         if(found_grouping)
1116                         {
1117                             /* It is not he first time, when we find thousands separator,
1118                              * so we need to chek, is the distance between two groupings
1119                              * equal to grouping[last_grouping_pos] */
1120 
1121                             if (length_since_last_delim != grouping[last_grouping_pos] )
1122                             {
1123                                 if (!last_grouping_pos) return false;
1124                                 else
1125                                 {
1126                                     -- last_grouping_pos;
1127                                     if (length_since_last_delim != grouping[last_grouping_pos]) return false;
1128                                 }
1129                             } else
1130                                 /* We are calling the grouping[0] twice, when grouping size is more than 1 */
1131                                 if (grouping_size>1u && last_grouping_pos+1<grouping_size) return false;
1132 
1133                         } else {
1134                             /* Delimiter at the begining ',000' */
1135                             if (!length_since_last_delim) return false;
1136 
1137                             found_grouping = true;
1138                             if (length_since_last_delim > grouping[last_grouping_pos] ) return false;
1139                         }
1140 
1141                         length_since_last_delim = 0;
1142                         ++ begin;
1143 
1144                         /* Delimiter at the end '100,' */
1145                         if (begin == end) return false;
1146                         continue;
1147                     }
1148 #endif
1149                     else return false;
1150                 }
1151 
1152                 ++begin;
1153             }
1154 
1155             // Exponent found
1156             if ( begin != end && (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) ) {
1157                 ++ begin;
1158                 if ( begin == end ) return false;
1159 
1160                 bool exp_has_minus = false;
1161                 if(Traits::eq(*begin, minus)) {
1162                     exp_has_minus = true;
1163                     ++ begin;
1164                     if ( begin == end ) return false;
1165                 } else if (Traits::eq(*begin, plus)) {
1166                     ++ begin;
1167                     if ( begin == end ) return false;
1168                 }
1169 
1170                 int exp_pow_of_10 = 0;
1171                 while ( begin != end )
1172                 {
1173                     if ( *begin < czero
1174                             || *begin >= czero + 10
1175                             || exp_pow_of_10 * 10 < exp_pow_of_10) /* Overflows are checked lower more precisely*/
1176                         return false;
1177 
1178                     exp_pow_of_10 *= 10;
1179                     exp_pow_of_10 += *begin - zero;
1180                     ++ begin;
1181                 };
1182 
1183                 if ( exp_pow_of_10 ) {
1184                     /* Overflows are checked lower */
1185                     if ( exp_has_minus ) {
1186                         pow_of_10 -= exp_pow_of_10;
1187                     } else {
1188                         pow_of_10 += exp_pow_of_10;
1189                     }
1190                 }
1191             }
1192 
1193             /* We need a more accurate algorithm... We can not use current algorithm
1194              * with long doubles (and with doubles if sizeof(double)==sizeof(long double)).
1195              */
1196             long double result = std::pow(10.0L, pow_of_10) * mantissa;
1197             value = static_cast<T>( has_minus ? (boost::math::changesign)(result) : result);
1198 
1199             if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false;
1200 
1201             return true;
1202         }
1203     }
1204 
1205     namespace detail // stl_buf_unlocker
1206     {
1207         template< class BufferType, class CharT >
1208         class stl_buf_unlocker: public BufferType{
1209         public:
1210             typedef BufferType base_class;
1211 #ifndef BOOST_NO_USING_TEMPLATE
1212             using base_class::pptr;
1213             using base_class::pbase;
1214             using base_class::setg;
1215             using base_class::setp;
1216 #else
pptr() const1217             CharT* pptr() const { return base_class::pptr(); }
pbase() const1218             CharT* pbase() const { return base_class::pbase(); }
setg(CharT * gbeg,CharT * gnext,CharT * gend)1219             void setg(CharT* gbeg, CharT* gnext, CharT* gend){ return base_class::setg(gbeg, gnext, gend); }
setp(CharT * pbeg,CharT * pend)1220             void setp(CharT* pbeg, CharT* pend) { return setp(pbeg, pend); }
1221 #endif
1222         };
1223     }
1224 
1225     namespace detail
1226     {
1227         struct do_not_construct_out_stream_t{};
1228     }
1229 
1230     namespace detail // optimized stream wrapper
1231     {
1232         // String representation of Source has an upper limit.
1233         template< class CharT // a result of widest_char transformation
1234                 , class Traits // usually char_traits<CharT>
1235                 , bool RequiresStringbuffer
1236                 >
1237         class lexical_stream_limited_src
1238         {
1239 
1240 #if defined(BOOST_NO_STRINGSTREAM)
1241             typedef std::ostrstream                         out_stream_t;
1242             typedef stl_buf_unlocker<std::strstreambuf, char>  unlocked_but_t;
1243 #elif defined(BOOST_NO_STD_LOCALE)
1244             typedef std::ostringstream                      out_stream_t;
1245             typedef stl_buf_unlocker<std::stringbuf, char>  unlocked_but_t;
1246 #else
1247             typedef std::basic_ostringstream<CharT, Traits>       out_stream_t;
1248             typedef stl_buf_unlocker<std::basic_stringbuf<CharT, Traits>, CharT> unlocked_but_t;
1249 #endif
1250             typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
1251                 RequiresStringbuffer,
1252                 out_stream_t,
1253                 do_not_construct_out_stream_t
1254             >::type deduced_out_stream_t;
1255 
1256             // A string representation of Source is written to [start, finish).
1257             CharT* start;
1258             CharT* finish;
1259             deduced_out_stream_t out_stream;
1260 
1261         public:
lexical_stream_limited_src(CharT * sta,CharT * fin)1262             lexical_stream_limited_src(CharT* sta, CharT* fin)
1263               : start(sta)
1264               , finish(fin)
1265             {}
1266 
1267         private:
1268             // Undefined:
1269             lexical_stream_limited_src(lexical_stream_limited_src const&);
1270             void operator=(lexical_stream_limited_src const&);
1271 
1272 /************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/
shl_char(CharT ch)1273             bool shl_char(CharT ch) BOOST_NOEXCEPT
1274             {
1275                 Traits::assign(*start, ch);
1276                 finish = start + 1;
1277                 return true;
1278             }
1279 
1280 #ifndef BOOST_LCAST_NO_WCHAR_T
1281             template <class T>
shl_char(T ch)1282             bool shl_char(T ch)
1283             {
1284                 BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) ,
1285                     "boost::lexical_cast does not support narrowing of char types."
1286                     "Use boost::locale instead" );
1287 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
1288                 std::locale loc;
1289                 CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
1290 #else
1291                 CharT const w = ch;
1292 #endif
1293                 Traits::assign(*start, w);
1294                 finish = start + 1;
1295                 return true;
1296             }
1297 #endif
1298 
shl_char_array(CharT const * str)1299             bool shl_char_array(CharT const* str) BOOST_NOEXCEPT
1300             {
1301                 start = const_cast<CharT*>(str);
1302                 finish = start + Traits::length(str);
1303                 return true;
1304             }
1305 
1306             template <class T>
shl_char_array(T const * str)1307             bool shl_char_array(T const* str)
1308             {
1309                 BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)),
1310                     "boost::lexical_cast does not support narrowing of char types."
1311                     "Use boost::locale instead" );
1312                 return shl_input_streamable(str);
1313             }
1314 
shl_char_array_limited(CharT const * str,std::size_t max_size)1315             bool shl_char_array_limited(CharT const* str, std::size_t max_size) BOOST_NOEXCEPT
1316             {
1317                 start = const_cast<CharT*>(str);
1318                 finish = std::find(start, start + max_size, Traits::to_char_type(0));
1319                 return true;
1320             }
1321 
1322             template<typename InputStreamable>
shl_input_streamable(InputStreamable & input)1323             bool shl_input_streamable(InputStreamable& input)
1324             {
1325 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
1326                 // If you have compilation error at this point, than your STL library
1327                 // does not support such conversions. Try updating it.
1328                 BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value));
1329 #endif
1330                 bool const result = !(out_stream << input).fail();
1331                 const unlocked_but_t* const p
1332                         = static_cast<unlocked_but_t*>(out_stream.rdbuf()) ;
1333                 start = p->pbase();
1334                 finish = p->pptr();
1335                 return result;
1336             }
1337 
1338             template <class T>
shl_signed(T n)1339             inline bool shl_signed(T n)
1340             {
1341                 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1342                 if(n < 0)
1343                 {
1344                     --start;
1345                     CharT const minus = lcast_char_constants<CharT>::minus;
1346                     Traits::assign(*start, minus);
1347                 }
1348                 return true;
1349             }
1350 
1351             template <class T, class SomeCharT>
shl_real_type(const T & val,SomeCharT * begin,SomeCharT * & end)1352             bool shl_real_type(const T& val, SomeCharT* begin, SomeCharT*& end)
1353             {
1354                 if (put_inf_nan(begin, end, val)) return true;
1355                 lcast_set_precision(out_stream, &val);
1356                 return shl_input_streamable(val);
1357             }
1358 
shl_real_type(float val,char * begin,char * & end)1359             static bool shl_real_type(float val, char* begin, char*& end)
1360             {   using namespace std;
1361                 if (put_inf_nan(begin, end, val)) return true;
1362                 const double val_as_double = val;
1363                 end = begin +
1364 #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
1365                     sprintf_s(begin, end-begin,
1366 #else
1367                     sprintf(begin,
1368 #endif
1369                     "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double);
1370                 return end > begin;
1371             }
1372 
shl_real_type(double val,char * begin,char * & end)1373             static bool shl_real_type(double val, char* begin, char*& end)
1374             {   using namespace std;
1375                 if (put_inf_nan(begin, end, val)) return true;
1376                 end = begin +
1377 #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
1378                     sprintf_s(begin, end-begin,
1379 #else
1380                     sprintf(begin,
1381 #endif
1382                     "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val);
1383                 return end > begin;
1384             }
1385 
1386 #ifndef __MINGW32__
shl_real_type(long double val,char * begin,char * & end)1387             static bool shl_real_type(long double val, char* begin, char*& end)
1388             {   using namespace std;
1389                 if (put_inf_nan(begin, end, val)) return true;
1390                 end = begin +
1391 #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
1392                     sprintf_s(begin, end-begin,
1393 #else
1394                     sprintf(begin,
1395 #endif
1396                     "%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double>()), val );
1397                 return end > begin;
1398             }
1399 #endif
1400 
1401 
1402 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__)
shl_real_type(float val,wchar_t * begin,wchar_t * & end)1403             static bool shl_real_type(float val, wchar_t* begin, wchar_t*& end)
1404             {   using namespace std;
1405                 if (put_inf_nan(begin, end, val)) return true;
1406                 const double val_as_double = val;
1407                 end = begin + swprintf(begin, end-begin,
1408                                        L"%.*g",
1409                                        static_cast<int>(boost::detail::lcast_get_precision<float >()),
1410                                        val_as_double );
1411                 return end > begin;
1412             }
1413 
shl_real_type(double val,wchar_t * begin,wchar_t * & end)1414             static bool shl_real_type(double val, wchar_t* begin, wchar_t*& end)
1415             {   using namespace std;
1416                 if (put_inf_nan(begin, end, val)) return true;
1417                 end = begin + swprintf(begin, end-begin,
1418                                           L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
1419                 return end > begin;
1420             }
1421 
shl_real_type(long double val,wchar_t * begin,wchar_t * & end)1422             static bool shl_real_type(long double val, wchar_t* begin, wchar_t*& end)
1423             {   using namespace std;
1424                 if (put_inf_nan(begin, end, val)) return true;
1425                 end = begin + swprintf(begin, end-begin,
1426                                           L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
1427                 return end > begin;
1428             }
1429 #endif
1430 
1431 /************************************ OPERATORS << ( ... ) ********************************/
1432         public:
1433             template<class Alloc>
operator <<(std::basic_string<CharT,Traits,Alloc> const & str)1434             bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT
1435             {
1436                 start = const_cast<CharT*>(str.data());
1437                 finish = start + str.length();
1438                 return true;
1439             }
1440 
1441             template<class Alloc>
operator <<(::boost::container::basic_string<CharT,Traits,Alloc> const & str)1442             bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT
1443             {
1444                 start = const_cast<CharT*>(str.data());
1445                 finish = start + str.length();
1446                 return true;
1447             }
1448 
operator <<(bool value)1449             bool operator<<(bool value) BOOST_NOEXCEPT
1450             {
1451                 CharT const czero = lcast_char_constants<CharT>::zero;
1452                 Traits::assign(*start, Traits::to_char_type(czero + value));
1453                 finish = start + 1;
1454                 return true;
1455             }
1456 
operator <<(const iterator_range<CharT * > & rng)1457             bool operator<<(const iterator_range<CharT*>& rng) BOOST_NOEXCEPT
1458             {
1459                 start = rng.begin();
1460                 finish = rng.end();
1461                 return true;
1462             }
1463 
operator <<(const iterator_range<const CharT * > & rng)1464             bool operator<<(const iterator_range<const CharT*>& rng) BOOST_NOEXCEPT
1465             {
1466                 start = const_cast<CharT*>(rng.begin());
1467                 finish = const_cast<CharT*>(rng.end());
1468                 return true;
1469             }
1470 
operator <<(const iterator_range<const signed char * > & rng)1471             bool operator<<(const iterator_range<const signed char*>& rng) BOOST_NOEXCEPT
1472             {
1473                 return (*this) << iterator_range<char*>(
1474                     const_cast<char*>(reinterpret_cast<const char*>(rng.begin())),
1475                     const_cast<char*>(reinterpret_cast<const char*>(rng.end()))
1476                 );
1477             }
1478 
operator <<(const iterator_range<const unsigned char * > & rng)1479             bool operator<<(const iterator_range<const unsigned char*>& rng) BOOST_NOEXCEPT
1480             {
1481                 return (*this) << iterator_range<char*>(
1482                     const_cast<char*>(reinterpret_cast<const char*>(rng.begin())),
1483                     const_cast<char*>(reinterpret_cast<const char*>(rng.end()))
1484                 );
1485             }
1486 
operator <<(const iterator_range<signed char * > & rng)1487             bool operator<<(const iterator_range<signed char*>& rng) BOOST_NOEXCEPT
1488             {
1489                 return (*this) << iterator_range<char*>(
1490                     reinterpret_cast<char*>(rng.begin()),
1491                     reinterpret_cast<char*>(rng.end())
1492                 );
1493             }
1494 
operator <<(const iterator_range<unsigned char * > & rng)1495             bool operator<<(const iterator_range<unsigned char*>& rng) BOOST_NOEXCEPT
1496             {
1497                 return (*this) << iterator_range<char*>(
1498                     reinterpret_cast<char*>(rng.begin()),
1499                     reinterpret_cast<char*>(rng.end())
1500                 );
1501             }
1502 
operator <<(char ch)1503             bool operator<<(char ch)                    { return shl_char(ch); }
operator <<(unsigned char ch)1504             bool operator<<(unsigned char ch)           { return ((*this) << static_cast<char>(ch)); }
operator <<(signed char ch)1505             bool operator<<(signed char ch)             { return ((*this) << static_cast<char>(ch)); }
1506 #if !defined(BOOST_LCAST_NO_WCHAR_T)
operator <<(wchar_t const * str)1507             bool operator<<(wchar_t const* str)         { return shl_char_array(str); }
operator <<(wchar_t * str)1508             bool operator<<(wchar_t * str)              { return shl_char_array(str); }
1509 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
operator <<(wchar_t ch)1510             bool operator<<(wchar_t ch)                 { return shl_char(ch); }
1511 #endif
1512 #endif
1513 #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS)
operator <<(char16_t ch)1514             bool operator<<(char16_t ch)                { return shl_char(ch); }
operator <<(char16_t * str)1515             bool operator<<(char16_t * str)             { return shl_char_array(str); }
operator <<(char16_t const * str)1516             bool operator<<(char16_t const * str)       { return shl_char_array(str); }
1517 #endif
1518 #if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS)
operator <<(char32_t ch)1519             bool operator<<(char32_t ch)                { return shl_char(ch); }
operator <<(char32_t * str)1520             bool operator<<(char32_t * str)             { return shl_char_array(str); }
operator <<(char32_t const * str)1521             bool operator<<(char32_t const * str)       { return shl_char_array(str); }
1522 #endif
operator <<(unsigned char const * ch)1523             bool operator<<(unsigned char const* ch)    { return ((*this) << reinterpret_cast<char const*>(ch)); }
operator <<(unsigned char * ch)1524             bool operator<<(unsigned char * ch)         { return ((*this) << reinterpret_cast<char *>(ch)); }
operator <<(signed char const * ch)1525             bool operator<<(signed char const* ch)      { return ((*this) << reinterpret_cast<char const*>(ch)); }
operator <<(signed char * ch)1526             bool operator<<(signed char * ch)           { return ((*this) << reinterpret_cast<char *>(ch)); }
operator <<(char const * str)1527             bool operator<<(char const* str)            { return shl_char_array(str); }
operator <<(char * str)1528             bool operator<<(char* str)                  { return shl_char_array(str); }
operator <<(short n)1529             bool operator<<(short n)                    { return shl_signed(n); }
operator <<(int n)1530             bool operator<<(int n)                      { return shl_signed(n); }
operator <<(long n)1531             bool operator<<(long n)                     { return shl_signed(n); }
operator <<(unsigned short n)1532             bool operator<<(unsigned short n)           { start = lcast_put_unsigned<Traits>(n, finish); return true; }
operator <<(unsigned int n)1533             bool operator<<(unsigned int n)             { start = lcast_put_unsigned<Traits>(n, finish); return true; }
operator <<(unsigned long n)1534             bool operator<<(unsigned long n)            { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1535 
1536 #if defined(BOOST_HAS_LONG_LONG)
operator <<(boost::ulong_long_type n)1537             bool operator<<(boost::ulong_long_type n)   { start = lcast_put_unsigned<Traits>(n, finish); return true; }
operator <<(boost::long_long_type n)1538             bool operator<<(boost::long_long_type n)    { return shl_signed(n); }
1539 #elif defined(BOOST_HAS_MS_INT64)
operator <<(unsigned __int64 n)1540             bool operator<<(unsigned __int64 n)         { start = lcast_put_unsigned<Traits>(n, finish); return true; }
operator <<(__int64 n)1541             bool operator<<(         __int64 n)         { return shl_signed(n); }
1542 #endif
operator <<(float val)1543             bool operator<<(float val)                  { return shl_real_type(val, start, finish); }
operator <<(double val)1544             bool operator<<(double val)                 { return shl_real_type(val, start, finish); }
operator <<(long double val)1545             bool operator<<(long double val)            {
1546 #ifndef __MINGW32__
1547                 return shl_real_type(val, start, finish);
1548 #else
1549                 return shl_real_type(static_cast<double>(val), start, finish);
1550 #endif
1551             }
1552 
1553             template <std::size_t N>
operator <<(boost::array<CharT,N> const & input)1554             bool operator<<(boost::array<CharT, N> const& input) BOOST_NOEXCEPT
1555             { return shl_char_array_limited(input.begin(), N); }
1556 
1557             template <std::size_t N>
operator <<(boost::array<unsigned char,N> const & input)1558             bool operator<<(boost::array<unsigned char, N> const& input) BOOST_NOEXCEPT
1559             { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
1560 
1561             template <std::size_t N>
operator <<(boost::array<signed char,N> const & input)1562             bool operator<<(boost::array<signed char, N> const& input) BOOST_NOEXCEPT
1563             { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
1564 
1565             template <std::size_t N>
operator <<(boost::array<const CharT,N> const & input)1566             bool operator<<(boost::array<const CharT, N> const& input) BOOST_NOEXCEPT
1567             { return shl_char_array_limited(input.begin(), N); }
1568 
1569             template <std::size_t N>
operator <<(boost::array<const unsigned char,N> const & input)1570             bool operator<<(boost::array<const unsigned char, N> const& input) BOOST_NOEXCEPT
1571             { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
1572 
1573             template <std::size_t N>
operator <<(boost::array<const signed char,N> const & input)1574             bool operator<<(boost::array<const signed char, N> const& input) BOOST_NOEXCEPT
1575             { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
1576 
1577 #if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
1578             template <std::size_t N>
operator <<(std::array<CharT,N> const & input)1579             bool operator<<(std::array<CharT, N> const& input) BOOST_NOEXCEPT
1580             { return shl_char_array_limited(input.begin(), N); }
1581 
1582             template <std::size_t N>
operator <<(std::array<unsigned char,N> const & input)1583             bool operator<<(std::array<unsigned char, N> const& input) BOOST_NOEXCEPT
1584             { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
1585 
1586             template <std::size_t N>
operator <<(std::array<signed char,N> const & input)1587             bool operator<<(std::array<signed char, N> const& input) BOOST_NOEXCEPT
1588             { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
1589 
1590             template <std::size_t N>
operator <<(std::array<const CharT,N> const & input)1591             bool operator<<(std::array<const CharT, N> const& input) BOOST_NOEXCEPT
1592             { return shl_char_array_limited(input.begin(), N); }
1593 
1594             template <std::size_t N>
operator <<(std::array<const unsigned char,N> const & input)1595             bool operator<<(std::array<const unsigned char, N> const& input) BOOST_NOEXCEPT
1596             { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
1597 
1598             template <std::size_t N>
operator <<(std::array<const signed char,N> const & input)1599             bool operator<<(std::array<const signed char, N> const& input) BOOST_NOEXCEPT
1600             { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
1601 #endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
1602 
1603             template <class InStreamable>
operator <<(const InStreamable & input)1604             bool operator<<(const InStreamable& input)  { return shl_input_streamable(input); }
1605 
1606 /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/
1607         private:
1608 
1609             template <typename Type>
shr_unsigned(Type & output)1610             bool shr_unsigned(Type& output)
1611             {
1612                 if (start == finish) return false;
1613                 CharT const minus = lcast_char_constants<CharT>::minus;
1614                 CharT const plus = lcast_char_constants<CharT>::plus;
1615                 bool has_minus = false;
1616 
1617                 /* We won`t use `start' any more, so no need in decrementing it after */
1618                 if ( Traits::eq(minus,*start) )
1619                 {
1620                     ++start;
1621                     has_minus = true;
1622                 } else if ( Traits::eq( plus, *start ) )
1623                 {
1624                     ++start;
1625                 }
1626 
1627                 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish);
1628 #if (defined _MSC_VER)
1629 # pragma warning( push )
1630 // C4146: unary minus operator applied to unsigned type, result still unsigned
1631 # pragma warning( disable : 4146 )
1632 #elif defined( __BORLANDC__ )
1633 # pragma option push -w-8041
1634 #endif
1635                 if (has_minus) output = static_cast<Type>(-output);
1636 #if (defined _MSC_VER)
1637 # pragma warning( pop )
1638 #elif defined( __BORLANDC__ )
1639 # pragma option pop
1640 #endif
1641                 return succeed;
1642             }
1643 
1644             template <typename Type>
shr_signed(Type & output)1645             bool shr_signed(Type& output)
1646             {
1647                 if (start == finish) return false;
1648                 CharT const minus = lcast_char_constants<CharT>::minus;
1649                 CharT const plus = lcast_char_constants<CharT>::plus;
1650                 typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
1651                 utype out_tmp =0;
1652                 bool has_minus = false;
1653 
1654                 /* We won`t use `start' any more, so no need in decrementing it after */
1655                 if ( Traits::eq(minus,*start) )
1656                 {
1657                     ++start;
1658                     has_minus = true;
1659                 } else if ( Traits::eq(plus, *start) )
1660                 {
1661                     ++start;
1662                 }
1663 
1664                 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish);
1665                 if (has_minus) {
1666 #if (defined _MSC_VER)
1667 # pragma warning( push )
1668 // C4146: unary minus operator applied to unsigned type, result still unsigned
1669 # pragma warning( disable : 4146 )
1670 #elif defined( __BORLANDC__ )
1671 # pragma option push -w-8041
1672 #endif
1673                     utype const comp_val = static_cast<utype>(-(std::numeric_limits<Type>::min)());
1674                     succeed = succeed && out_tmp<=comp_val;
1675                     output = -out_tmp;
1676 #if (defined _MSC_VER)
1677 # pragma warning( pop )
1678 #elif defined( __BORLANDC__ )
1679 # pragma option pop
1680 #endif
1681                 } else {
1682                     utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
1683                     succeed = succeed && out_tmp<=comp_val;
1684                     output = out_tmp;
1685                 }
1686                 return succeed;
1687             }
1688 
1689             template<typename InputStreamable>
shr_using_base_class(InputStreamable & output)1690             bool shr_using_base_class(InputStreamable& output)
1691             {
1692 #if (defined _MSC_VER)
1693 # pragma warning( push )
1694   // conditional expression is constant
1695 # pragma warning( disable : 4127 )
1696 #endif
1697                 if(is_pointer<InputStreamable>::value)
1698                     return false;
1699 
1700 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
1701                 // If you have compilation error at this point, than your STL library
1702                 // unsupports such conversions. Try updating it.
1703                 BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value));
1704 #endif
1705 
1706 #if defined(BOOST_NO_STRINGSTREAM)
1707                 std::istrstream stream(start, finish - start);
1708 #elif defined(BOOST_NO_STD_LOCALE)
1709                 std::istringstream stream;
1710 #else
1711                 std::basic_istringstream<CharT, Traits> stream;
1712 #endif
1713                 static_cast<unlocked_but_t*>(stream.rdbuf())
1714                         ->setg(start, start, finish);
1715 
1716                 stream.unsetf(std::ios::skipws);
1717                 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
1718 #if (defined _MSC_VER)
1719 # pragma warning( pop )
1720 #endif
1721                 return stream >> output &&
1722                     stream.get() ==
1723 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
1724         // GCC 2.9x lacks std::char_traits<>::eof().
1725         // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
1726         // configurations, which do provide std::char_traits<>::eof().
1727 
1728                     EOF;
1729 #else
1730                 Traits::eof();
1731 #endif
1732             }
1733 
1734             template<class T>
shr_xchar(T & output)1735             inline bool shr_xchar(T& output)
1736             {
1737                 BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ),
1738                     "boost::lexical_cast does not support narrowing of character types."
1739                     "Use boost::locale instead" );
1740                 bool const ok = (finish - start == 1);
1741                 if (ok) {
1742                     CharT out;
1743                     Traits::assign(out, *start);
1744                     output = static_cast<T>(out);
1745                 }
1746                 return ok;
1747             }
1748 
1749 /************************************ OPERATORS >> ( ... ) ********************************/
1750             public:
operator >>(unsigned short & output)1751             bool operator>>(unsigned short& output)             { return shr_unsigned(output); }
operator >>(unsigned int & output)1752             bool operator>>(unsigned int& output)               { return shr_unsigned(output); }
operator >>(unsigned long int & output)1753             bool operator>>(unsigned long int& output)          { return shr_unsigned(output); }
operator >>(short & output)1754             bool operator>>(short& output)                      { return shr_signed(output); }
operator >>(int & output)1755             bool operator>>(int& output)                        { return shr_signed(output); }
operator >>(long int & output)1756             bool operator>>(long int& output)                   { return shr_signed(output); }
1757 #if defined(BOOST_HAS_LONG_LONG)
operator >>(boost::ulong_long_type & output)1758             bool operator>>(boost::ulong_long_type& output)     { return shr_unsigned(output); }
operator >>(boost::long_long_type & output)1759             bool operator>>(boost::long_long_type& output)      { return shr_signed(output); }
1760 #elif defined(BOOST_HAS_MS_INT64)
operator >>(unsigned __int64 & output)1761             bool operator>>(unsigned __int64& output)           { return shr_unsigned(output); }
operator >>(__int64 & output)1762             bool operator>>(__int64& output)                    { return shr_signed(output); }
1763 #endif
operator >>(char & output)1764             bool operator>>(char& output)                       { return shr_xchar(output); }
operator >>(unsigned char & output)1765             bool operator>>(unsigned char& output)              { return shr_xchar(output); }
operator >>(signed char & output)1766             bool operator>>(signed char& output)                { return shr_xchar(output); }
1767 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
operator >>(wchar_t & output)1768             bool operator>>(wchar_t& output)                    { return shr_xchar(output); }
1769 #endif
1770 #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS)
operator >>(char16_t & output)1771             bool operator>>(char16_t& output)                   { return shr_xchar(output); }
1772 #endif
1773 #if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS)
operator >>(char32_t & output)1774             bool operator>>(char32_t& output)                   { return shr_xchar(output); }
1775 #endif
1776             template<class Alloc>
operator >>(std::basic_string<CharT,Traits,Alloc> & str)1777             bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
1778 
1779             template<class Alloc>
operator >>(::boost::container::basic_string<CharT,Traits,Alloc> & str)1780             bool operator>>(::boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
1781 
1782 
1783     private:
1784             template <std::size_t N, class ArrayT>
shr_std_array(ArrayT & output)1785             bool shr_std_array(ArrayT& output) BOOST_NOEXCEPT
1786             {
1787                 using namespace std;
1788                 const std::size_t size = finish - start;
1789                 if (size > N - 1) { // `-1` because we need to store \0 at the end
1790                     return false;
1791                 }
1792 
1793                 memcpy(output.begin(), start, size * sizeof(CharT));
1794                 *(output.begin() + size) = Traits::to_char_type(0);
1795                 return true;
1796             }
1797 
1798     public:
1799 
1800             template <std::size_t N>
operator >>(boost::array<CharT,N> & output)1801             bool operator>>(boost::array<CharT, N>& output) BOOST_NOEXCEPT
1802             {
1803                 return shr_std_array<N>(output);
1804             }
1805 
1806             template <std::size_t N>
operator >>(boost::array<unsigned char,N> & output)1807             bool operator>>(boost::array<unsigned char, N>& output)
1808             {
1809                 return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output));
1810             }
1811 
1812             template <std::size_t N>
operator >>(boost::array<signed char,N> & output)1813             bool operator>>(boost::array<signed char, N>& output)
1814             {
1815                 return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output));
1816             }
1817 
1818 #if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
1819             template <std::size_t N>
operator >>(std::array<CharT,N> & output)1820             bool operator>>(std::array<CharT, N>& output) BOOST_NOEXCEPT
1821             {
1822                 return shr_std_array<N>(output);
1823             }
1824 
1825             template <std::size_t N>
operator >>(std::array<unsigned char,N> & output)1826             bool operator>>(std::array<unsigned char, N>& output)
1827             {
1828                 return ((*this) >> reinterpret_cast<std::array<char, N>& >(output));
1829             }
1830 
1831             template <std::size_t N>
operator >>(std::array<signed char,N> & in)1832             bool operator>>(std::array<signed char, N>& in)
1833             {
1834                 return ((*this) >> reinterpret_cast<std::array<char, N>& >(output));
1835             }
1836 #endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
1837 
1838 
1839             /*
1840              * case "-0" || "0" || "+0" :   output = false; return true;
1841              * case "1" || "+1":            output = true;  return true;
1842              * default:                     return false;
1843              */
operator >>(bool & output)1844             bool operator>>(bool& output) BOOST_NOEXCEPT
1845             {
1846                 CharT const zero = lcast_char_constants<CharT>::zero;
1847                 CharT const plus = lcast_char_constants<CharT>::plus;
1848                 CharT const minus = lcast_char_constants<CharT>::minus;
1849 
1850                 switch(finish-start)
1851                 {
1852                     case 1:
1853                         output = Traits::eq(start[0],  zero+1);
1854                         return output || Traits::eq(start[0], zero );
1855                     case 2:
1856                         if ( Traits::eq( plus, *start) )
1857                         {
1858                             ++start;
1859                             output = Traits::eq(start[0], zero +1);
1860                             return output || Traits::eq(start[0], zero );
1861                         } else
1862                         {
1863                             output = false;
1864                             return Traits::eq( minus, *start)
1865                                 && Traits::eq( zero, start[1]);
1866                         }
1867                     default:
1868                         output = false; // Suppress warning about uninitalized variable
1869                         return false;
1870                 }
1871             }
1872 
operator >>(float & output)1873             bool operator>>(float& output) { return lcast_ret_float<Traits>(output,start,finish); }
1874 
1875         private:
1876             // Not optimised converter
1877             template <class T>
float_types_converter_internal(T & output,int)1878             bool float_types_converter_internal(T& output, int /*tag*/) {
1879                 if (parse_inf_nan(start, finish, output)) return true;
1880                 bool return_value = shr_using_base_class(output);
1881 
1882                 /* Some compilers and libraries successfully
1883                  * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
1884                  * We are trying to provide a unified behaviour,
1885                  * so we just forbid such conversions (as some
1886                  * of the most popular compilers/libraries do)
1887                  * */
1888                 CharT const minus = lcast_char_constants<CharT>::minus;
1889                 CharT const plus = lcast_char_constants<CharT>::plus;
1890                 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
1891                 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
1892                 if ( return_value &&
1893                      (
1894                         Traits::eq(*(finish-1), lowercase_e)                   // 1.0e
1895                         || Traits::eq(*(finish-1), capital_e)                  // 1.0E
1896                         || Traits::eq(*(finish-1), minus)                      // 1.0e- or 1.0E-
1897                         || Traits::eq(*(finish-1), plus)                       // 1.0e+ or 1.0E+
1898                      )
1899                 ) return false;
1900 
1901                 return return_value;
1902             }
1903 
1904             // Optimised converter
float_types_converter_internal(double & output,char)1905             bool float_types_converter_internal(double& output,char /*tag*/) {
1906                 return lcast_ret_float<Traits>(output,start,finish);
1907             }
1908         public:
1909 
operator >>(double & output)1910             bool operator>>(double& output)
1911             {
1912                 /*
1913                  * Some compilers implement long double as double. In that case these types have
1914                  * same size, same precision, same max and min values... And it means,
1915                  * that current implementation of lcast_ret_float cannot be used for type
1916                  * double, because it will give a big precision loss.
1917                  * */
1918                 boost::mpl::if_c<
1919 #if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)
1920                     ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value,
1921 #else
1922                      0
1923 #endif
1924                     int,
1925                     char
1926                 >::type tag = 0;
1927 
1928                 return float_types_converter_internal(output, tag);
1929             }
1930 
operator >>(long double & output)1931             bool operator>>(long double& output)
1932             {
1933                 int tag = 0;
1934                 return float_types_converter_internal(output, tag);
1935             }
1936 
1937             // Generic istream-based algorithm.
1938             // lcast_streambuf_for_target<InputStreamable>::value is true.
1939             template<typename InputStreamable>
operator >>(InputStreamable & output)1940             bool operator>>(InputStreamable& output) { return shr_using_base_class(output); }
1941         };
1942     }
1943 
1944     namespace detail
1945     {
1946         template<class T>
1947         struct array_to_pointer_decay
1948         {
1949             typedef T type;
1950         };
1951 
1952         template<class T, std::size_t N>
1953         struct array_to_pointer_decay<T[N]>
1954         {
1955             typedef const T * type;
1956         };
1957 
1958         template<typename T>
1959         struct is_stdstring
1960         {
1961             BOOST_STATIC_CONSTANT(bool, value = false );
1962         };
1963 
1964         template<typename CharT, typename Traits, typename Alloc>
1965         struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
1966         {
1967             BOOST_STATIC_CONSTANT(bool, value = true );
1968         };
1969 
1970         template<typename CharT, typename Traits, typename Alloc>
1971         struct is_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc> >
1972         {
1973             BOOST_STATIC_CONSTANT(bool, value = true );
1974         };
1975 
1976         template<typename Target, typename Source>
1977         struct is_arithmetic_and_not_xchars
1978         {
1979             BOOST_STATIC_CONSTANT(bool, value =
1980                (
1981                    ::boost::type_traits::ice_and<
1982                            ::boost::is_arithmetic<Source>::value,
1983                            ::boost::is_arithmetic<Target>::value,
1984                            ::boost::type_traits::ice_not<
1985                                 detail::is_char_or_wchar<Target>::value
1986                            >::value,
1987                            ::boost::type_traits::ice_not<
1988                                 detail::is_char_or_wchar<Source>::value
1989                            >::value
1990                    >::value
1991                )
1992             );
1993         };
1994 
1995         /*
1996          * is_xchar_to_xchar<Target, Source>::value is true, when
1997          * Target and Souce are the same char types, or when
1998          * Target and Souce are char types of the same size.
1999          */
2000         template<typename Target, typename Source>
2001         struct is_xchar_to_xchar
2002         {
2003             BOOST_STATIC_CONSTANT(bool, value =
2004                 (
2005                     ::boost::type_traits::ice_or<
2006                         ::boost::type_traits::ice_and<
2007                              is_same<Source,Target>::value,
2008                              is_char_or_wchar<Target>::value
2009                         >::value,
2010                         ::boost::type_traits::ice_and<
2011                              ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
2012                              ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
2013                              is_char_or_wchar<Target>::value,
2014                              is_char_or_wchar<Source>::value
2015                         >::value
2016                     >::value
2017                 )
2018             );
2019         };
2020 
2021 
2022         // this metafunction evaluates to true, if we have optimized comnversion
2023         // from Float type to Char array.
2024         // Must be in sync with lexical_stream_limited_src<Char, ...>::shl_real_type(...)
2025         template <typename Float, typename Char>
2026         struct is_this_float_conversion_optimized
2027         {
2028             typedef ::boost::type_traits::ice_and<
2029                 ::boost::is_float<Float>::value,
2030 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__)
2031                 ::boost::type_traits::ice_or<
2032                     ::boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value,
2033                     ::boost::is_same<Char, wchar_t>::value
2034                 >::value
2035 #else
2036                 ::boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value
2037 #endif
2038             > result_type;
2039 
2040             BOOST_STATIC_CONSTANT(bool, value = (result_type::value) );
2041         };
2042 
2043         template<typename Target, typename Source>
2044         struct is_char_array_to_stdstring
2045         {
2046             BOOST_STATIC_CONSTANT(bool, value = false );
2047         };
2048 
2049         template<typename CharT, typename Traits, typename Alloc>
2050         struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
2051         {
2052             BOOST_STATIC_CONSTANT(bool, value = true );
2053         };
2054 
2055         template<typename CharT, typename Traits, typename Alloc>
2056         struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
2057         {
2058             BOOST_STATIC_CONSTANT(bool, value = true );
2059         };
2060 
2061         template<typename CharT, typename Traits, typename Alloc>
2062         struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
2063         {
2064             BOOST_STATIC_CONSTANT(bool, value = true );
2065         };
2066 
2067         template<typename CharT, typename Traits, typename Alloc>
2068         struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
2069         {
2070             BOOST_STATIC_CONSTANT(bool, value = true );
2071         };
2072 
2073 #if (defined _MSC_VER)
2074 # pragma warning( push )
2075 # pragma warning( disable : 4701 ) // possible use of ... before initialization
2076 # pragma warning( disable : 4702 ) // unreachable code
2077 # pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int'
2078 #endif
2079         template<typename Target, typename Source>
2080         struct lexical_cast_do_cast
2081         {
lexical_cast_implboost::detail::lexical_cast_do_cast2082             static inline Target lexical_cast_impl(const Source& arg)
2083             {
2084                 typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
2085                 typedef BOOST_DEDUCED_TYPENAME ::boost::remove_cv<src>::type no_cv_src;
2086                 typedef BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type target_char_t;
2087                 typedef BOOST_DEDUCED_TYPENAME detail::stream_char<no_cv_src>::type src_char_type;
2088                 typedef BOOST_DEDUCED_TYPENAME detail::widest_char<
2089                     target_char_t, src_char_type
2090                 >::type char_type;
2091 
2092 #if !defined(BOOST_NO_CHAR16_T) && defined(BOOST_NO_UNICODE_LITERALS)
2093                 BOOST_STATIC_ASSERT_MSG(( !::boost::is_same<char16_t, src_char_type>::value
2094                                           && !::boost::is_same<char16_t, target_char_t>::value),
2095                     "Your compiler does not have full support for char16_t" );
2096 #endif
2097 #if !defined(BOOST_NO_CHAR32_T) && defined(BOOST_NO_UNICODE_LITERALS)
2098                 BOOST_STATIC_ASSERT_MSG(( !::boost::is_same<char32_t, src_char_type>::value
2099                                           && !::boost::is_same<char32_t, target_char_t>::value),
2100                     "Your compiler does not have full support for char32_t" );
2101 #endif
2102 
2103                 typedef BOOST_DEDUCED_TYPENAME ::boost::detail::deduce_char_traits<
2104                     char_type, Target, no_cv_src
2105                 >::type traits;
2106 
2107                 typedef ::boost::type_traits::ice_and<
2108                     ::boost::detail::is_char_or_wchar<src_char_type>::value,                    // source is lexical type
2109                     ::boost::detail::is_char_or_wchar<target_char_t>::value,                    // target is a lexical type
2110                     ::boost::is_same<char, src_char_type>::value,                               // source is not a wide character based type
2111                     ::boost::type_traits::ice_ne<sizeof(char), sizeof(target_char_t) >::value   // target type is based on wide character
2112                 >   is_string_widening_required_t;
2113 
2114                 typedef ::boost::type_traits::ice_or<
2115                     ::boost::is_integral<no_cv_src>::value,
2116                     ::boost::detail::is_this_float_conversion_optimized<no_cv_src, char_type >::value,
2117                     ::boost::detail::is_char_or_wchar<src_char_type >::value
2118                 >   is_source_input_optimized_t;
2119 
2120                 // Target type must be default constructible
2121                 Target result;
2122 
2123                 // If we have an optimized conversion for
2124                 // Source, we do not need to construct stringbuf.
2125                 const bool requires_stringbuf = ::boost::type_traits::ice_or<
2126                         is_string_widening_required_t::value,
2127                         ::boost::type_traits::ice_not< is_source_input_optimized_t::value >::value
2128                 >::value;
2129 
2130                 typedef detail::lexical_stream_limited_src<char_type, traits, requires_stringbuf > interpreter_type;
2131 
2132                 typedef detail::lcast_src_length<no_cv_src> lcast_src_length;
2133                 std::size_t const src_len = lcast_src_length::value;
2134                 char_type buf[src_len + 1];
2135                 lcast_src_length::check_coverage();
2136 
2137                 interpreter_type interpreter(buf, buf + src_len);
2138 
2139                 // Disabling ADL, by directly specifying operators.
2140                 if(!(interpreter.operator <<(arg) && interpreter.operator >>(result)))
2141                   BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2142 
2143                 return result;
2144             }
2145         };
2146 #if (defined _MSC_VER)
2147 # pragma warning( pop )
2148 #endif
2149 
2150         template <typename Source>
2151         struct lexical_cast_copy
2152         {
lexical_cast_implboost::detail::lexical_cast_copy2153             static inline const Source& lexical_cast_impl(const Source &arg) BOOST_NOEXCEPT
2154             {
2155                 return arg;
2156             }
2157         };
2158 
2159         template <class Source, class Target >
2160         struct detect_precision_loss
2161         {
2162          typedef boost::numeric::Trunc<Source> Rounder;
2163          typedef Source source_type ;
2164 
2165          typedef BOOST_DEDUCED_TYPENAME mpl::if_<
2166             ::boost::is_arithmetic<Source>, Source, Source const&
2167           >::type argument_type ;
2168 
nearbyintboost::detail::detect_precision_loss2169          static source_type nearbyint ( argument_type s )
2170          {
2171             const source_type orig_div_round = s / Rounder::nearbyint(s);
2172             const source_type eps = std::numeric_limits<source_type>::epsilon();
2173 
2174             if ((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps)
2175                 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2176 
2177             return s ;
2178          }
2179 
2180          typedef typename Rounder::round_style round_style;
2181         } ;
2182 
2183         template <class Source, class Target >
2184         struct nothrow_overflow_handler
2185         {
operator ()boost::detail::nothrow_overflow_handler2186           void operator() ( boost::numeric::range_check_result r )
2187           {
2188             if (r != boost::numeric::cInRange)
2189                 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2190           }
2191         } ;
2192 
2193         template <typename Target, typename Source>
2194         struct lexical_cast_dynamic_num_not_ignoring_minus
2195         {
lexical_cast_implboost::detail::lexical_cast_dynamic_num_not_ignoring_minus2196             static inline Target lexical_cast_impl(const Source &arg)
2197             {
2198                 return boost::numeric::converter<
2199                         Target,
2200                         Source,
2201                         boost::numeric::conversion_traits<Target,Source>,
2202                         nothrow_overflow_handler<Source, Target>,
2203                         detect_precision_loss<Source, Target>
2204                 >::convert(arg);
2205             }
2206         };
2207 
2208         template <typename Target, typename Source>
2209         struct lexical_cast_dynamic_num_ignoring_minus
2210         {
lexical_cast_implboost::detail::lexical_cast_dynamic_num_ignoring_minus2211             static inline Target lexical_cast_impl(const Source &arg)
2212             {
2213                 typedef boost::numeric::converter<
2214                         Target,
2215                         Source,
2216                         boost::numeric::conversion_traits<Target,Source>,
2217                         nothrow_overflow_handler<Source, Target>,
2218                         detect_precision_loss<Source, Target>
2219                 > converter_t;
2220 
2221                 return (
2222                     arg < 0 ? -converter_t::convert(-arg) : converter_t::convert(arg)
2223                 );
2224             }
2225         };
2226 
2227         /*
2228          * lexical_cast_dynamic_num follows the rules:
2229          * 1) If Source can be converted to Target without precision loss and
2230          * without overflows, then assign Source to Target and return
2231          *
2232          * 2) If Source is less than 0 and Target is an unsigned integer,
2233          * then negate Source, check the requirements of rule 1) and if
2234          * successful, assign static_casted Source to Target and return
2235          *
2236          * 3) Otherwise throw a bad_lexical_cast exception
2237          *
2238          *
2239          * Rule 2) required because boost::lexical_cast has the behavior of
2240          * stringstream, which uses the rules of scanf for conversions. And
2241          * in the C99 standard for unsigned input value minus sign is
2242          * optional, so if a negative number is read, no errors will arise
2243          * and the result will be the two's complement.
2244          */
2245         template <typename Target, typename Source>
2246         struct lexical_cast_dynamic_num
2247         {
lexical_cast_implboost::detail::lexical_cast_dynamic_num2248             static inline Target lexical_cast_impl(const Source &arg)
2249             {
2250                 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2251                     ::boost::type_traits::ice_and<
2252                         ::boost::type_traits::ice_or<
2253                             ::boost::is_signed<Source>::value,
2254                             ::boost::is_float<Source>::value
2255                         >::value,
2256                         ::boost::type_traits::ice_not<
2257                             ::boost::is_same<Source, bool>::value
2258                         >::value,
2259                         ::boost::type_traits::ice_not<
2260                             ::boost::is_same<Target, bool>::value
2261                         >::value,
2262                         ::boost::is_unsigned<Target>::value
2263                     >::value,
2264                     lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
2265                     lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
2266                 >::type caster_type;
2267 
2268                 return caster_type::lexical_cast_impl(arg);
2269             }
2270         };
2271     }
2272 
2273     template <typename Target, typename Source>
lexical_cast(const Source & arg)2274     inline Target lexical_cast(const Source &arg)
2275     {
2276         typedef BOOST_DEDUCED_TYPENAME ::boost::detail::array_to_pointer_decay<Source>::type src;
2277 
2278         typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or<
2279                 ::boost::detail::is_xchar_to_xchar<Target, src >::value,
2280                 ::boost::detail::is_char_array_to_stdstring<Target, src >::value,
2281                 ::boost::type_traits::ice_and<
2282                      ::boost::is_same<Target, src >::value,
2283                      ::boost::detail::is_stdstring<Target >::value
2284                 >::value
2285         > shall_we_copy_t;
2286 
2287         typedef BOOST_DEDUCED_TYPENAME
2288                 ::boost::detail::is_arithmetic_and_not_xchars<Target, src > shall_we_copy_with_dynamic_check_t;
2289 
2290         typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2291             shall_we_copy_t::value,
2292             ::boost::detail::lexical_cast_copy<src >,
2293             BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2294                  shall_we_copy_with_dynamic_check_t::value,
2295                  ::boost::detail::lexical_cast_dynamic_num<Target, src >,
2296                  ::boost::detail::lexical_cast_do_cast<Target, src >
2297             >::type
2298         >::type caster_type;
2299 
2300         return caster_type::lexical_cast_impl(arg);
2301     }
2302 
2303     template <typename Target>
lexical_cast(const char * chars,std::size_t count)2304     inline Target lexical_cast(const char* chars, std::size_t count)
2305     {
2306         return ::boost::lexical_cast<Target>(
2307             ::boost::iterator_range<const char*>(chars, chars + count)
2308         );
2309     }
2310 
2311 
2312     template <typename Target>
lexical_cast(const unsigned char * chars,std::size_t count)2313     inline Target lexical_cast(const unsigned char* chars, std::size_t count)
2314     {
2315         return ::boost::lexical_cast<Target>(
2316             ::boost::iterator_range<const unsigned char*>(chars, chars + count)
2317         );
2318     }
2319 
2320     template <typename Target>
lexical_cast(const signed char * chars,std::size_t count)2321     inline Target lexical_cast(const signed char* chars, std::size_t count)
2322     {
2323         return ::boost::lexical_cast<Target>(
2324             ::boost::iterator_range<const signed char*>(chars, chars + count)
2325         );
2326     }
2327 
2328 #ifndef BOOST_LCAST_NO_WCHAR_T
2329     template <typename Target>
lexical_cast(const wchar_t * chars,std::size_t count)2330     inline Target lexical_cast(const wchar_t* chars, std::size_t count)
2331     {
2332         return ::boost::lexical_cast<Target>(
2333             ::boost::iterator_range<const wchar_t*>(chars, chars + count)
2334         );
2335     }
2336 #endif
2337 #ifndef BOOST_NO_CHAR16_T
2338     template <typename Target>
lexical_cast(const char16_t * chars,std::size_t count)2339     inline Target lexical_cast(const char16_t* chars, std::size_t count)
2340     {
2341         return ::boost::lexical_cast<Target>(
2342             ::boost::iterator_range<const char16_t*>(chars, chars + count)
2343         );
2344     }
2345 #endif
2346 #ifndef BOOST_NO_CHAR32_T
2347     template <typename Target>
lexical_cast(const char32_t * chars,std::size_t count)2348     inline Target lexical_cast(const char32_t* chars, std::size_t count)
2349     {
2350         return ::boost::lexical_cast<Target>(
2351             ::boost::iterator_range<const char32_t*>(chars, chars + count)
2352         );
2353     }
2354 #endif
2355 
2356 } // namespace boost
2357 
2358 #else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
2359 
2360 namespace boost {
2361     namespace detail
2362     {
2363 
2364         // selectors for choosing stream character type
2365         template<typename Type>
2366         struct stream_char
2367         {
2368             typedef char type;
2369         };
2370 
2371 #ifndef BOOST_LCAST_NO_WCHAR_T
2372 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
2373         template<>
2374         struct stream_char<wchar_t>
2375         {
2376             typedef wchar_t type;
2377         };
2378 #endif
2379 
2380         template<>
2381         struct stream_char<wchar_t *>
2382         {
2383             typedef wchar_t type;
2384         };
2385 
2386         template<>
2387         struct stream_char<const wchar_t *>
2388         {
2389             typedef wchar_t type;
2390         };
2391 
2392         template<>
2393         struct stream_char<std::wstring>
2394         {
2395             typedef wchar_t type;
2396         };
2397 #endif
2398 
2399         // stream wrapper for handling lexical conversions
2400         template<typename Target, typename Source, typename Traits>
2401         class lexical_stream
2402         {
2403         private:
2404             typedef typename widest_char<
2405                 typename stream_char<Target>::type,
2406                 typename stream_char<Source>::type>::type char_type;
2407 
2408             typedef Traits traits_type;
2409 
2410         public:
lexical_stream(char_type * =0,char_type * =0)2411             lexical_stream(char_type* = 0, char_type* = 0)
2412             {
2413                 stream.unsetf(std::ios::skipws);
2414                 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
2415             }
~lexical_stream()2416             ~lexical_stream()
2417             {
2418                 #if defined(BOOST_NO_STRINGSTREAM)
2419                 stream.freeze(false);
2420                 #endif
2421             }
operator <<(const Source & input)2422             bool operator<<(const Source &input)
2423             {
2424                 return !(stream << input).fail();
2425             }
2426             template<typename InputStreamable>
operator >>(InputStreamable & output)2427             bool operator>>(InputStreamable &output)
2428             {
2429                 return !is_pointer<InputStreamable>::value &&
2430                        stream >> output &&
2431                        stream.get() ==
2432 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
2433 // GCC 2.9x lacks std::char_traits<>::eof().
2434 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
2435 // configurations, which do provide std::char_traits<>::eof().
2436 
2437                            EOF;
2438 #else
2439                            traits_type::eof();
2440 #endif
2441             }
2442 
operator >>(std::string & output)2443             bool operator>>(std::string &output)
2444             {
2445                 #if defined(BOOST_NO_STRINGSTREAM)
2446                 stream << '\0';
2447                 #endif
2448                 stream.str().swap(output);
2449                 return true;
2450             }
2451             #ifndef BOOST_LCAST_NO_WCHAR_T
operator >>(std::wstring & output)2452             bool operator>>(std::wstring &output)
2453             {
2454                 stream.str().swap(output);
2455                 return true;
2456             }
2457             #endif
2458 
2459         private:
2460             #if defined(BOOST_NO_STRINGSTREAM)
2461             std::strstream stream;
2462             #elif defined(BOOST_NO_STD_LOCALE)
2463             std::stringstream stream;
2464             #else
2465             std::basic_stringstream<char_type,traits_type> stream;
2466             #endif
2467         };
2468     }
2469 
2470     // call-by-value fallback version (deprecated)
2471 
2472     template<typename Target, typename Source>
lexical_cast(Source arg)2473     Target lexical_cast(Source arg)
2474     {
2475         typedef typename detail::widest_char<
2476             BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
2477           , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
2478         >::type char_type;
2479 
2480         typedef std::char_traits<char_type> traits;
2481         detail::lexical_stream<Target, Source, traits> interpreter;
2482         Target result;
2483 
2484         if(!(interpreter << arg && interpreter >> result))
2485           BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2486         return result;
2487     }
2488 
2489 } // namespace boost
2490 
2491 #endif
2492 
2493 // Copyright Kevlin Henney, 2000-2005.
2494 // Copyright Alexander Nasonov, 2006-2010.
2495 // Copyright Antony Polukhin, 2011-2012.
2496 //
2497 // Distributed under the Boost Software License, Version 1.0. (See
2498 // accompanying file LICENSE_1_0.txt or copy at
2499 // http://www.boost.org/LICENSE_1_0.txt)
2500 
2501 #undef BOOST_LCAST_THROW_BAD_CAST
2502 #undef BOOST_LCAST_NO_WCHAR_T
2503 
2504 #endif // BOOST_LEXICAL_CAST_INCLUDED
2505 
2506