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