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