]> git.lyx.org Git - lyx.git/blob - boost/boost/lexical_cast.hpp
thinko: if we have requires, do not test package
[lyx.git] / 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                 finish = start + sprintf(out,"%.*g", static_cast<int>(boost::detail::lcast_get_precision<float >()), val );
1290                 return finish > start;
1291             }
1292
1293             template <class T>
1294             bool shl_double(double val,T* out)
1295             {   using namespace std;
1296                 if (put_inf_nan(start,finish,val)) return true;
1297                 finish = start + sprintf(out,"%.*lg", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
1298                 return finish > start;
1299             }
1300 #ifndef __MINGW32__
1301             template <class T>
1302             bool shl_long_double(long double val,T* out)
1303             {   using namespace std;
1304                 if (put_inf_nan(start,finish,val)) return true;
1305                 finish = start + sprintf(out,"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
1306                 return finish > start;
1307             }
1308 #endif
1309
1310 #if (defined _MSC_VER)
1311 # pragma warning( pop )
1312 #endif
1313
1314
1315 #ifndef BOOST_LCAST_NO_WCHAR_T
1316             bool shl_float(float val,wchar_t* out)
1317             {   using namespace std;
1318                 if (put_inf_nan(start,finish,val)) return true;
1319                 finish = start + swprintf(out,
1320 #if !defined(__MINGW32__) && !defined(UNDER_CE)
1321                                           finish-start,
1322 #endif
1323                                           L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<float >()), val );
1324
1325                 return finish > start;
1326             }
1327
1328
1329             bool shl_double(double val,wchar_t* out)
1330             {   using namespace std;
1331                 if (put_inf_nan(start,finish,val)) return true;
1332                 /* __MINGW32__ is defined for both mingw.org and for mingw-w64.
1333                  * For mingw-w64, __MINGW64__ is defined, too, when targetting
1334                  * 64 bits.
1335                  *
1336                  * swprintf realization in MinGW and under WinCE does not conform
1337                  * to the ISO C
1338                  * Standard.
1339                  */
1340                 finish = start + swprintf(out,
1341 #if !defined(__MINGW32__) && !defined(UNDER_CE)
1342                                           finish-start,
1343 #endif
1344                                           L"%.*lg", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
1345                 return finish > start;
1346             }
1347
1348 #ifndef __MINGW32__
1349             bool shl_long_double(long double val,wchar_t* out)
1350             {   using namespace std;
1351                 if (put_inf_nan(start,finish,val)) return true;
1352                 finish = start + swprintf(out,
1353 #if !defined(UNDER_CE)
1354                                           finish-start,
1355 #endif
1356                                           L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
1357                 return finish > start;
1358             }
1359 #endif
1360
1361 #endif
1362
1363 /************************************ OPERATORS << ( ... ) ********************************/
1364         public:
1365             template<class Alloc>
1366             bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
1367             {
1368                 start = const_cast<CharT*>(str.data());
1369                 finish = start + str.length();
1370                 return true;
1371             }
1372
1373 #if !defined(__SUNPRO_CC)
1374             template<class Alloc>
1375             bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str)
1376             {
1377                 start = const_cast<CharT*>(str.data());
1378                 finish = start + str.length();
1379                 return true;
1380             }
1381 #endif // !defined(__SUNPRO_CC)
1382             bool operator<<(bool value)
1383             {
1384                 CharT const czero = lcast_char_constants<CharT>::zero;
1385                 Traits::assign(*start, Traits::to_char_type(czero + value));
1386                 finish = start + 1;
1387                 return true;
1388             }
1389
1390             bool operator<<(char ch)                    { return shl_char(ch); }
1391             bool operator<<(unsigned char ch)           { return ((*this) << static_cast<char>(ch)); }
1392             bool operator<<(signed char ch)             { return ((*this) << static_cast<char>(ch)); }
1393 #if !defined(BOOST_LCAST_NO_WCHAR_T)
1394             bool operator<<(wchar_t const* str)         { return shl_char_array(str); }
1395             bool operator<<(wchar_t * str)              { return shl_char_array(str); }
1396 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
1397             bool operator<<(wchar_t ch)                 { return shl_char(ch); }
1398 #endif
1399 #endif
1400             bool operator<<(unsigned char const* ch)    { return ((*this) << reinterpret_cast<char const*>(ch)); }
1401             bool operator<<(unsigned char * ch)         { return ((*this) << reinterpret_cast<char *>(ch)); }
1402             bool operator<<(signed char const* ch)      { return ((*this) << reinterpret_cast<char const*>(ch)); }
1403             bool operator<<(signed char * ch)           { return ((*this) << reinterpret_cast<char *>(ch)); }
1404             bool operator<<(char const* str)            { return shl_char_array(str); }
1405             bool operator<<(char* str)                  { return shl_char_array(str); }
1406             bool operator<<(short n)                    { return shl_signed(n); }
1407             bool operator<<(int n)                      { return shl_signed(n); }
1408             bool operator<<(long n)                     { return shl_signed(n); }
1409             bool operator<<(unsigned short n)           { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1410             bool operator<<(unsigned int n)             { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1411             bool operator<<(unsigned long n)            { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1412
1413 #if defined(BOOST_HAS_LONG_LONG)
1414             bool operator<<(boost::ulong_long_type n)   { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1415             bool operator<<(boost::long_long_type n)    { return shl_signed(n); }
1416 #elif defined(BOOST_HAS_MS_INT64)
1417             bool operator<<(unsigned __int64 n)         { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1418             bool operator<<(         __int64 n)         { return shl_signed(n); }
1419 #endif
1420             bool operator<<(float val)                  { return shl_float(val,start); }
1421             bool operator<<(double val)                 { return shl_double(val,start); }
1422             bool operator<<(long double val)            {
1423 #ifndef __MINGW32__
1424                 return shl_long_double(val,start);
1425 #else
1426                 return shl_double(val,start);
1427 #endif
1428             }
1429
1430             template<class InStreamable>
1431             bool operator<<(const InStreamable& input)  { return shl_input_streamable(input); }
1432
1433 /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/
1434         private:
1435
1436             template <typename Type>
1437             bool shr_unsigned(Type& output)
1438             {
1439                 if (start == finish) return false;
1440                 CharT const minus = lcast_char_constants<CharT>::minus;
1441                 CharT const plus = lcast_char_constants<CharT>::plus;
1442                 bool has_minus = false;
1443
1444                 /* We won`t use `start' any more, so no need in decrementing it after */
1445                 if ( Traits::eq(minus,*start) )
1446                 {
1447                     ++start;
1448                     has_minus = true;
1449                 } else if ( Traits::eq( plus, *start ) )
1450                 {
1451                     ++start;
1452                 }
1453
1454                 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish);
1455 #if (defined _MSC_VER)
1456 # pragma warning( push )
1457 // C4146: unary minus operator applied to unsigned type, result still unsigned
1458 # pragma warning( disable : 4146 )
1459 #elif defined( __BORLANDC__ )
1460 # pragma option push -w-8041
1461 #endif
1462                 if (has_minus) output = static_cast<Type>(-output);
1463 #if (defined _MSC_VER)
1464 # pragma warning( pop )
1465 #elif defined( __BORLANDC__ )
1466 # pragma option pop
1467 #endif
1468                 return succeed;
1469             }
1470
1471             template <typename Type>
1472             bool shr_signed(Type& output)
1473             {
1474                 if (start == finish) return false;
1475                 CharT const minus = lcast_char_constants<CharT>::minus;
1476                 CharT const plus = lcast_char_constants<CharT>::plus;
1477                 typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
1478                 utype out_tmp =0;
1479                 bool has_minus = false;
1480
1481                 /* We won`t use `start' any more, so no need in decrementing it after */
1482                 if ( Traits::eq(minus,*start) )
1483                 {
1484                     ++start;
1485                     has_minus = true;
1486                 } else if ( Traits::eq(plus, *start) )
1487                 {
1488                     ++start;
1489                 }
1490
1491                 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish);
1492                 if (has_minus) {
1493 #if (defined _MSC_VER)
1494 # pragma warning( push )
1495 // C4146: unary minus operator applied to unsigned type, result still unsigned
1496 # pragma warning( disable : 4146 )
1497 #elif defined( __BORLANDC__ )
1498 # pragma option push -w-8041
1499 #endif
1500                     utype const comp_val = static_cast<utype>(-(std::numeric_limits<Type>::min)());
1501                     succeed = succeed && out_tmp<=comp_val;
1502                     output = -out_tmp;
1503 #if (defined _MSC_VER)
1504 # pragma warning( pop )
1505 #elif defined( __BORLANDC__ )
1506 # pragma option pop
1507 #endif
1508                 } else {
1509                     utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
1510                     succeed = succeed && out_tmp<=comp_val;
1511                     output = out_tmp;
1512                 }
1513                 return succeed;
1514             }
1515
1516             template<typename InputStreamable>
1517             bool shr_using_base_class(InputStreamable& output)
1518             {
1519 #if (defined _MSC_VER)
1520 # pragma warning( push )
1521   // conditional expression is constant
1522 # pragma warning( disable : 4127 )
1523 #endif
1524                 if(is_pointer<InputStreamable>::value)
1525                     return false;
1526
1527                 local_streambuffer_t bb;
1528                 bb.setg(start, start, finish);
1529                 std::basic_istream<CharT> stream(&bb);
1530                 stream.unsetf(std::ios::skipws);
1531                 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
1532 #if (defined _MSC_VER)
1533 # pragma warning( pop )
1534 #endif
1535                 return stream >> output &&
1536                     stream.get() ==
1537 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
1538         // GCC 2.9x lacks std::char_traits<>::eof().
1539         // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
1540         // configurations, which do provide std::char_traits<>::eof().
1541
1542                     EOF;
1543 #else
1544                 Traits::eof();
1545 #endif
1546             }
1547
1548             template<class T>
1549             inline bool shr_xchar(T& output)
1550             {
1551                 BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ),
1552                     "boost::lexical_cast does not support conversions from whar_t to char types."
1553                     "Use boost::locale instead" );
1554                 bool const ok = (finish - start == 1);
1555                 if(ok) {
1556                     CharT out;
1557                     Traits::assign(out, *start);
1558                     output = static_cast<T>(out);
1559                 }
1560                 return ok;
1561             }
1562
1563 /************************************ OPERATORS >> ( ... ) ********************************/
1564             public:
1565             bool operator>>(unsigned short& output)             { return shr_unsigned(output); }
1566             bool operator>>(unsigned int& output)               { return shr_unsigned(output); }
1567             bool operator>>(unsigned long int& output)          { return shr_unsigned(output); }
1568             bool operator>>(short& output)                      { return shr_signed(output); }
1569             bool operator>>(int& output)                        { return shr_signed(output); }
1570             bool operator>>(long int& output)                   { return shr_signed(output); }
1571 #if defined(BOOST_HAS_LONG_LONG)
1572             bool operator>>(boost::ulong_long_type& output)     { return shr_unsigned(output); }
1573             bool operator>>(boost::long_long_type& output)      { return shr_signed(output); }
1574 #elif defined(BOOST_HAS_MS_INT64)
1575             bool operator>>(unsigned __int64& output)           { return shr_unsigned(output); }
1576             bool operator>>(__int64& output)                    { return shr_signed(output); }
1577 #endif
1578             bool operator>>(char& output)                       { return shr_xchar(output); }
1579             bool operator>>(unsigned char& output)              { return shr_xchar(output); }
1580             bool operator>>(signed char& output)                { return shr_xchar(output); }
1581 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1582             bool operator>>(wchar_t& output)                    { return shr_xchar(output); }
1583 #endif
1584 #ifndef BOOST_NO_CHAR16_T
1585             bool operator>>(char16_t& output)                   { return shr_xchar(output); }
1586 #endif
1587 #ifndef BOOST_NO_CHAR32_T
1588             bool operator>>(char32_t& output)                   { return shr_xchar(output); }
1589 #endif
1590 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1591             bool operator>>(std::string& str)                   { str.assign(start, finish); return true; }
1592 #   ifndef BOOST_LCAST_NO_WCHAR_T
1593             bool operator>>(std::wstring& str)                  { str.assign(start, finish); return true; }
1594 #   endif
1595 #else
1596             template<class Alloc>
1597             bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
1598 #if !defined(__SUNPRO_CC)
1599             template<class Alloc>
1600             bool operator>>(::boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
1601 #endif // !defined(__SUNPRO_CC)
1602 #endif
1603             /*
1604              * case "-0" || "0" || "+0" :   output = false; return true;
1605              * case "1" || "+1":            output = true;  return true;
1606              * default:                     return false;
1607              */
1608             bool operator>>(bool& output)
1609             {
1610                 CharT const zero = lcast_char_constants<CharT>::zero;
1611                 CharT const plus = lcast_char_constants<CharT>::plus;
1612                 CharT const minus = lcast_char_constants<CharT>::minus;
1613
1614                 switch(finish-start)
1615                 {
1616                     case 1:
1617                         output = Traits::eq(start[0],  zero+1);
1618                         return output || Traits::eq(start[0], zero );
1619                     case 2:
1620                         if ( Traits::eq( plus, *start) )
1621                         {
1622                             ++start;
1623                             output = Traits::eq(start[0], zero +1);
1624                             return output || Traits::eq(start[0], zero );
1625                         } else
1626                         {
1627                             output = false;
1628                             return Traits::eq( minus, *start)
1629                                 && Traits::eq( zero, start[1]);
1630                         }
1631                     default:
1632                         output = false; // Suppress warning about uninitalized variable
1633                         return false;
1634                 }
1635             }
1636
1637             bool operator>>(float& output) { return lcast_ret_float<Traits>(output,start,finish); }
1638
1639         private:
1640             // Not optimised converter
1641             template <class T>
1642             bool float_types_converter_internal(T& output, int /*tag*/) {
1643                 if (parse_inf_nan(start, finish, output)) return true;
1644                 bool return_value = shr_using_base_class(output);
1645
1646                 /* Some compilers and libraries successfully
1647                  * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
1648                  * We are trying to provide a unified behaviour,
1649                  * so we just forbid such conversions (as some
1650                  * of the most popular compilers/libraries do)
1651                  * */
1652                 CharT const minus = lcast_char_constants<CharT>::minus;
1653                 CharT const plus = lcast_char_constants<CharT>::plus;
1654                 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
1655                 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
1656                 if ( return_value &&
1657                      (
1658                         *(finish-1) == lowercase_e                   // 1.0e
1659                         || *(finish-1) == capital_e                  // 1.0E
1660                         || *(finish-1) == minus                      // 1.0e- or 1.0E-
1661                         || *(finish-1) == plus                       // 1.0e+ or 1.0E+
1662                      )
1663                 ) return false;
1664
1665                 return return_value;
1666             }
1667
1668             // Optimised converter
1669             bool float_types_converter_internal(double& output,char /*tag*/) {
1670                 return lcast_ret_float<Traits>(output,start,finish);
1671             }
1672         public:
1673
1674             bool operator>>(double& output)
1675             {
1676                 /*
1677                  * Some compilers implement long double as double. In that case these types have
1678                  * same size, same precision, same max and min values... And it means,
1679                  * that current implementation of lcast_ret_float cannot be used for type
1680                  * double, because it will give a big precision loss.
1681                  * */
1682                 boost::mpl::if_c<
1683 #if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)
1684                     ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value,
1685 #else
1686                      0
1687 #endif
1688                     int,
1689                     char
1690                 >::type tag = 0;
1691
1692                 return float_types_converter_internal(output, tag);
1693             }
1694
1695             bool operator>>(long double& output)
1696             {
1697                 int tag = 0;
1698                 return float_types_converter_internal(output, tag);
1699             }
1700
1701             // Generic istream-based algorithm.
1702             // lcast_streambuf_for_target<InputStreamable>::value is true.
1703             template<typename InputStreamable>
1704             bool operator>>(InputStreamable& output) { return shr_using_base_class(output); }
1705         };
1706     }
1707
1708 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1709
1710     // call-by-const reference version
1711
1712     namespace detail
1713     {
1714         template<class T>
1715         struct array_to_pointer_decay
1716         {
1717             typedef T type;
1718         };
1719
1720         template<class T, std::size_t N>
1721         struct array_to_pointer_decay<T[N]>
1722         {
1723             typedef const T * type;
1724         };
1725
1726         template<typename T>
1727         struct is_stdstring
1728         {
1729             BOOST_STATIC_CONSTANT(bool, value = false );
1730         };
1731
1732         template<typename CharT, typename Traits, typename Alloc>
1733         struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
1734         {
1735             BOOST_STATIC_CONSTANT(bool, value = true );
1736         };
1737 #if !defined(__SUNPRO_CC)
1738         template<typename CharT, typename Traits, typename Alloc>
1739         struct is_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc> >
1740         {
1741             BOOST_STATIC_CONSTANT(bool, value = true );
1742         };
1743 #endif // !defined(__SUNPRO_CC)
1744         template<typename T>
1745         struct is_char_or_wchar
1746         {
1747         private:
1748 #ifndef BOOST_LCAST_NO_WCHAR_T
1749             typedef wchar_t wchar_t_if_supported;
1750 #else
1751             typedef char wchar_t_if_supported;
1752 #endif
1753
1754 #ifndef BOOST_NO_CHAR16_T
1755             typedef char16_t char16_t_if_supported;
1756 #else
1757             typedef char char16_t_if_supported;
1758 #endif
1759
1760 #ifndef BOOST_NO_CHAR32_T
1761             typedef char32_t char32_t_if_supported;
1762 #else
1763             typedef char char32_t_if_supported;
1764 #endif
1765             public:
1766
1767             BOOST_STATIC_CONSTANT(bool, value =
1768                     (
1769                     ::boost::type_traits::ice_or<
1770                          is_same< T, char >::value,
1771                          is_same< T, wchar_t_if_supported >::value,
1772                          is_same< T, char16_t_if_supported >::value,
1773                          is_same< T, char32_t_if_supported >::value,
1774                          is_same< T, unsigned char >::value,
1775                          is_same< T, signed char >::value
1776                     >::value
1777                     )
1778             );
1779         };
1780
1781         template<typename Target, typename Source>
1782         struct is_arithmetic_and_not_xchars
1783         {
1784             BOOST_STATIC_CONSTANT(bool, value =
1785                (
1786                    ::boost::type_traits::ice_and<
1787                            is_arithmetic<Source>::value,
1788                            is_arithmetic<Target>::value,
1789                            ::boost::type_traits::ice_not<
1790                                 detail::is_char_or_wchar<Target>::value
1791                            >::value,
1792                            ::boost::type_traits::ice_not<
1793                                 detail::is_char_or_wchar<Source>::value
1794                            >::value
1795                    >::value
1796                )
1797             );
1798         };
1799
1800         /*
1801          * is_xchar_to_xchar<Target, Source>::value is true, when
1802          * Target and Souce are the same char types, or when
1803          * Target and Souce are char types of the same size.
1804          */
1805         template<typename Target, typename Source>
1806         struct is_xchar_to_xchar
1807         {
1808             BOOST_STATIC_CONSTANT(bool, value =
1809                 (
1810                     ::boost::type_traits::ice_or<
1811                         ::boost::type_traits::ice_and<
1812                              is_same<Source,Target>::value,
1813                              is_char_or_wchar<Target>::value
1814                         >::value,
1815                         ::boost::type_traits::ice_and<
1816                              ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
1817                              ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
1818                              is_char_or_wchar<Target>::value,
1819                              is_char_or_wchar<Source>::value
1820                         >::value
1821                     >::value
1822                 )
1823             );
1824         };
1825
1826         template<typename Target, typename Source>
1827         struct is_char_array_to_stdstring
1828         {
1829             BOOST_STATIC_CONSTANT(bool, value = false );
1830         };
1831
1832         template<typename CharT, typename Traits, typename Alloc>
1833         struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
1834         {
1835             BOOST_STATIC_CONSTANT(bool, value = true );
1836         };
1837
1838         template<typename CharT, typename Traits, typename Alloc>
1839         struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
1840         {
1841             BOOST_STATIC_CONSTANT(bool, value = true );
1842         };
1843 #if !defined(__SUNPRO_CC)
1844         template<typename CharT, typename Traits, typename Alloc>
1845         struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
1846         {
1847             BOOST_STATIC_CONSTANT(bool, value = true );
1848         };
1849
1850         template<typename CharT, typename Traits, typename Alloc>
1851         struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
1852         {
1853             BOOST_STATIC_CONSTANT(bool, value = true );
1854         };
1855 #endif // !defined(__SUNPRO_CC)
1856
1857 #if (defined _MSC_VER)
1858 # pragma warning( push )
1859 # pragma warning( disable : 4701 ) // possible use of ... before initialization
1860 # pragma warning( disable : 4702 ) // unreachable code
1861 # pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int'
1862 #endif
1863         template<typename Target, typename Source>
1864         struct lexical_cast_do_cast
1865         {
1866             static inline Target lexical_cast_impl(const Source& arg)
1867             {
1868                 typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
1869
1870                 typedef BOOST_DEDUCED_TYPENAME detail::widest_char<
1871                     BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
1872                     , BOOST_DEDUCED_TYPENAME detail::stream_char<src>::type
1873                 >::type char_type;
1874
1875                 typedef detail::lcast_src_length<src> lcast_src_length;
1876                 std::size_t const src_len = lcast_src_length::value;
1877                 char_type buf[src_len + 1];
1878                 lcast_src_length::check_coverage();
1879
1880                 typedef BOOST_DEDUCED_TYPENAME
1881                     deduce_char_traits<char_type,Target,Source>::type traits;
1882
1883                 typedef BOOST_DEDUCED_TYPENAME remove_pointer<src >::type removed_ptr_t;
1884
1885                 // is_char_types_match variable value can be computed via
1886                 // sizeof(char_type) == sizeof(removed_ptr_t). But when
1887                 // removed_ptr_t is an incomplete type or void*, compilers
1888                 // produce warnings or errors.
1889                 const bool is_char_types_match =
1890                 (::boost::type_traits::ice_or<
1891                     ::boost::type_traits::ice_and<
1892                         ::boost::type_traits::ice_eq<sizeof(char_type), sizeof(char) >::value,
1893                         ::boost::type_traits::ice_or<
1894                             ::boost::is_same<char, removed_ptr_t>::value,
1895                             ::boost::is_same<unsigned char, removed_ptr_t>::value,
1896                             ::boost::is_same<signed char, removed_ptr_t>::value
1897                         >::value
1898                     >::value,
1899                     is_same<char_type, removed_ptr_t>::value
1900                 >::value);
1901
1902                 const bool requires_stringbuf =
1903                         !(
1904                              ::boost::type_traits::ice_or<
1905                                  is_stdstring<src >::value,
1906                                  is_arithmetic<src >::value,
1907                                  ::boost::type_traits::ice_and<
1908                                      is_pointer<src >::value,
1909                                      is_char_or_wchar<removed_ptr_t >::value,
1910                                      is_char_types_match
1911                                  >::value
1912                              >::value
1913                         );
1914
1915                 detail::lexical_stream_limited_src<char_type,traits, requires_stringbuf >
1916                         interpreter(buf, buf + src_len);
1917
1918                 Target result;
1919                 // Disabling ADL, by directly specifying operators.
1920                 if(!(interpreter.operator <<(arg) && interpreter.operator >>(result)))
1921                   BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1922                 return result;
1923             }
1924         };
1925 #if (defined _MSC_VER)
1926 # pragma warning( pop )
1927 #endif
1928
1929         template<typename Source>
1930         struct lexical_cast_copy
1931         {
1932             static inline Source lexical_cast_impl(const Source &arg)
1933             {
1934                 return arg;
1935             }
1936         };
1937
1938         class precision_loss_error : public boost::numeric::bad_numeric_cast
1939         {
1940          public:
1941             virtual const char * what() const throw()
1942              {  return "bad numeric conversion: precision loss error"; }
1943         };
1944
1945         template<class S >
1946         struct throw_on_precision_loss
1947         {
1948          typedef boost::numeric::Trunc<S> Rounder;
1949          typedef S source_type ;
1950
1951          typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
1952
1953          static source_type nearbyint ( argument_type s )
1954          {
1955             source_type orig_div_round = s / Rounder::nearbyint(s);
1956
1957             if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits<source_type>::epsilon() )
1958                BOOST_THROW_EXCEPTION( precision_loss_error() );
1959             return s ;
1960          }
1961
1962          typedef typename Rounder::round_style round_style;
1963         } ;
1964
1965         template<typename Target, typename Source>
1966         struct lexical_cast_dynamic_num_not_ignoring_minus
1967         {
1968             static inline Target lexical_cast_impl(const Source &arg)
1969             {
1970                 try{
1971                     typedef boost::numeric::converter<
1972                             Target,
1973                             Source,
1974                             boost::numeric::conversion_traits<Target,Source>,
1975                             boost::numeric::def_overflow_handler,
1976                             throw_on_precision_loss<Source>
1977                     > Converter ;
1978
1979                     return Converter::convert(arg);
1980                 } catch( ::boost::numeric::bad_numeric_cast const& ) {
1981                     BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1982                 }
1983                 BOOST_UNREACHABLE_RETURN(static_cast<Target>(0));
1984             }
1985         };
1986
1987         template<typename Target, typename Source>
1988         struct lexical_cast_dynamic_num_ignoring_minus
1989         {
1990             static inline Target lexical_cast_impl(const Source &arg)
1991             {
1992                 try{
1993                     typedef boost::numeric::converter<
1994                             Target,
1995                             Source,
1996                             boost::numeric::conversion_traits<Target,Source>,
1997                             boost::numeric::def_overflow_handler,
1998                             throw_on_precision_loss<Source>
1999                     > Converter ;
2000
2001                     bool has_minus = ( arg < 0);
2002                     if ( has_minus ) {
2003                         return static_cast<Target>(-Converter::convert(-arg));
2004                     } else {
2005                         return Converter::convert(arg);
2006                     }
2007                 } catch( ::boost::numeric::bad_numeric_cast const& ) {
2008                     BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2009                 }
2010                 BOOST_UNREACHABLE_RETURN(static_cast<Target>(0));
2011             }
2012         };
2013
2014         /*
2015          * lexical_cast_dynamic_num follows the rules:
2016          * 1) If Source can be converted to Target without precision loss and
2017          * without overflows, then assign Source to Target and return
2018          *
2019          * 2) If Source is less than 0 and Target is an unsigned integer,
2020          * then negate Source, check the requirements of rule 1) and if
2021          * successful, assign static_casted Source to Target and return
2022          *
2023          * 3) Otherwise throw a bad_lexical_cast exception
2024          *
2025          *
2026          * Rule 2) required because boost::lexical_cast has the behavior of
2027          * stringstream, which uses the rules of scanf for conversions. And
2028          * in the C99 standard for unsigned input value minus sign is
2029          * optional, so if a negative number is read, no errors will arise
2030          * and the result will be the two's complement.
2031          */
2032         template<typename Target, typename Source>
2033         struct lexical_cast_dynamic_num
2034         {
2035             static inline Target lexical_cast_impl(const Source &arg)
2036             {
2037                 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2038                     ::boost::type_traits::ice_and<
2039                         ::boost::type_traits::ice_or<
2040                             ::boost::is_signed<Source>::value,
2041                             ::boost::is_float<Source>::value
2042                         >::value,
2043                         ::boost::type_traits::ice_not<
2044                             is_same<Source, bool>::value
2045                         >::value,
2046                         ::boost::type_traits::ice_not<
2047                             is_same<Target, bool>::value
2048                         >::value,
2049                         ::boost::is_unsigned<Target>::value
2050                     >::value,
2051                     lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
2052                     lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
2053                 >::type caster_type;
2054
2055                 return caster_type::lexical_cast_impl(arg);
2056             }
2057         };
2058     }
2059
2060     template<typename Target, typename Source>
2061     inline Target lexical_cast(const Source &arg)
2062     {
2063         typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
2064
2065         typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or<
2066                 detail::is_xchar_to_xchar<Target, src>::value,
2067                 detail::is_char_array_to_stdstring<Target,src>::value,
2068                 ::boost::type_traits::ice_and<
2069                      is_same<Target, src>::value,
2070                      detail::is_stdstring<Target>::value
2071                 >::value
2072         > do_copy_type;
2073
2074         typedef BOOST_DEDUCED_TYPENAME
2075                 detail::is_arithmetic_and_not_xchars<Target, src> do_copy_with_dynamic_check_type;
2076
2077         typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2078             do_copy_type::value,
2079             detail::lexical_cast_copy<src>,
2080             BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2081                  do_copy_with_dynamic_check_type::value,
2082                  detail::lexical_cast_dynamic_num<Target, src>,
2083                  detail::lexical_cast_do_cast<Target, src>
2084             >::type
2085         >::type caster_type;
2086
2087         return caster_type::lexical_cast_impl(arg);
2088     }
2089
2090     #else
2091
2092     namespace detail // stream wrapper for handling lexical conversions
2093     {
2094         template<typename Target, typename Source, typename Traits>
2095         class lexical_stream
2096         {
2097         private:
2098             typedef typename widest_char<
2099                 typename stream_char<Target>::type,
2100                 typename stream_char<Source>::type>::type char_type;
2101
2102             typedef Traits traits_type;
2103
2104         public:
2105             lexical_stream(char_type* = 0, char_type* = 0)
2106             {
2107                 stream.unsetf(std::ios::skipws);
2108                 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
2109             }
2110             ~lexical_stream()
2111             {
2112                 #if defined(BOOST_NO_STRINGSTREAM)
2113                 stream.freeze(false);
2114                 #endif
2115             }
2116             bool operator<<(const Source &input)
2117             {
2118                 return !(stream << input).fail();
2119             }
2120             template<typename InputStreamable>
2121             bool operator>>(InputStreamable &output)
2122             {
2123                 return !is_pointer<InputStreamable>::value &&
2124                        stream >> output &&
2125                        stream.get() ==
2126 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
2127 // GCC 2.9x lacks std::char_traits<>::eof().
2128 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
2129 // configurations, which do provide std::char_traits<>::eof().
2130
2131                            EOF;
2132 #else
2133                            traits_type::eof();
2134 #endif
2135             }
2136
2137             bool operator>>(std::string &output)
2138             {
2139                 #if defined(BOOST_NO_STRINGSTREAM)
2140                 stream << '\0';
2141                 #endif
2142                 stream.str().swap(output);
2143                 return true;
2144             }
2145             #ifndef BOOST_LCAST_NO_WCHAR_T
2146             bool operator>>(std::wstring &output)
2147             {
2148                 stream.str().swap(output);
2149                 return true;
2150             }
2151             #endif
2152
2153         private:
2154             #if defined(BOOST_NO_STRINGSTREAM)
2155             std::strstream stream;
2156             #elif defined(BOOST_NO_STD_LOCALE)
2157             std::stringstream stream;
2158             #else
2159             std::basic_stringstream<char_type,traits_type> stream;
2160             #endif
2161         };
2162     }
2163
2164     // call-by-value fallback version (deprecated)
2165
2166     template<typename Target, typename Source>
2167     Target lexical_cast(Source arg)
2168     {
2169         typedef typename detail::widest_char< 
2170             BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type 
2171           , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type 
2172         >::type char_type; 
2173
2174         typedef std::char_traits<char_type> traits;
2175         detail::lexical_stream<Target, Source, traits> interpreter;
2176         Target result;
2177
2178         if(!(interpreter << arg && interpreter >> result))
2179           BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2180         return result;
2181     }
2182
2183     #endif
2184 }
2185
2186 // Copyright Kevlin Henney, 2000-2005.
2187 // Copyright Alexander Nasonov, 2006-2010.
2188 // Copyright Antony Polukhin, 2011-2012.
2189 //
2190 // Distributed under the Boost Software License, Version 1.0. (See
2191 // accompanying file LICENSE_1_0.txt or copy at
2192 // http://www.boost.org/LICENSE_1_0.txt)
2193
2194 #undef BOOST_LCAST_NO_WCHAR_T
2195 #endif