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