]> git.lyx.org Git - lyx.git/blob - boost/boost/lexical_cast.hpp
Don't allow newline characters in document settings.
[lyx.git] / boost / boost / lexical_cast.hpp
1 #ifndef BOOST_LEXICAL_CAST_INCLUDED
2 #define BOOST_LEXICAL_CAST_INCLUDED
3
4 // Boost lexical_cast.hpp header  -------------------------------------------//
5 //
6 // See http://www.boost.org/libs/conversion for documentation.
7 // See end of this header for rights and permissions.
8 //
9 // what:  lexical_cast custom keyword cast
10 // who:   contributed by Kevlin Henney,
11 //        enhanced with contributions from Terje Slettebo,
12 //        with additional fixes and suggestions from Gennaro Prota,
13 //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
14 //        Alexander Nasonov, Antony Polukhin and other Boosters
15 // when:  November 2000, March 2003, June 2005, June 2006, March 2011
16
17 #include <climits>
18 #include <cstddef>
19 #include <istream>
20 #include <string>
21 #include <typeinfo>
22 #include <exception>
23 #include <cmath>
24 #include <boost/config.hpp>
25 #include <boost/limits.hpp>
26 #include <boost/mpl/if.hpp>
27 #include <boost/throw_exception.hpp>
28 #include <boost/type_traits/is_pointer.hpp>
29 #include <boost/type_traits/is_integral.hpp>
30 #include <boost/type_traits/is_arithmetic.hpp>
31 #include <boost/numeric/conversion/cast.hpp>
32 #include <boost/type_traits/ice.hpp>
33 #include <boost/type_traits/make_unsigned.hpp>
34 #include <boost/type_traits/is_signed.hpp>
35 #include <boost/call_traits.hpp>
36 #include <boost/static_assert.hpp>
37 #include <boost/detail/lcast_precision.hpp>
38 #include <boost/detail/workaround.hpp>
39
40 #ifndef BOOST_NO_STD_LOCALE
41 #include <locale>
42 #endif
43
44 #ifdef BOOST_NO_STRINGSTREAM
45 #include <strstream>
46 #else
47 #include <sstream>
48 #endif
49
50 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
51 #define BOOST_LCAST_NO_WCHAR_T
52 #endif
53
54 #ifdef BOOST_NO_TYPEID
55 #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast())
56 #else
57 #define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \
58     throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)))
59 #endif
60
61 namespace boost
62 {
63     // exception used to indicate runtime lexical_cast failure
64     class bad_lexical_cast :
65     // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0 
66 #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS 
67         public std::exception 
68 #else 
69         public std::bad_cast 
70 #endif 
71
72 #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
73         // under bcc32 5.5.1 bad_cast doesn't derive from exception
74         , public std::exception
75 #endif
76
77     {
78     public:
79         bad_lexical_cast() :
80 #ifndef BOOST_NO_TYPEID
81           source(&typeid(void)), target(&typeid(void))
82 #else
83           source(0), target(0) // this breaks getters
84 #endif
85         {
86         }
87
88         bad_lexical_cast(
89             const std::type_info &source_type_arg,
90             const std::type_info &target_type_arg) :
91             source(&source_type_arg), target(&target_type_arg)
92         {
93         }
94
95         const std::type_info &source_type() const
96         {
97             return *source;
98         }
99         const std::type_info &target_type() const
100         {
101             return *target;
102         }
103
104         virtual const char *what() const throw()
105         {
106             return "bad lexical cast: "
107                    "source type value could not be interpreted as target";
108         }
109         virtual ~bad_lexical_cast() throw()
110         {
111         }
112     private:
113         const std::type_info *source;
114         const std::type_info *target;
115     };
116
117     namespace detail // selectors for choosing stream character type
118     {
119         template<typename Type>
120         struct stream_char
121         {
122             typedef char type;
123         };
124
125 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
126         template<class CharT, class Traits, class Alloc>
127         struct stream_char< std::basic_string<CharT,Traits,Alloc> >
128         {
129             typedef CharT type;
130         };
131 #endif
132
133 #ifndef BOOST_LCAST_NO_WCHAR_T
134 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
135         template<>
136         struct stream_char<wchar_t>
137         {
138             typedef wchar_t type;
139         };
140 #endif
141
142         template<>
143         struct stream_char<wchar_t *>
144         {
145             typedef wchar_t type;
146         };
147
148         template<>
149         struct stream_char<const wchar_t *>
150         {
151             typedef wchar_t type;
152         };
153
154 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
155         template<>
156         struct stream_char<std::wstring>
157         {
158             typedef wchar_t type;
159         };
160 #endif
161 #endif
162
163         template<typename TargetChar, typename SourceChar>
164         struct widest_char
165         {
166             typedef TargetChar type;
167         };
168
169         template<>
170         struct widest_char<char, wchar_t>
171         {
172             typedef wchar_t type;
173         };
174     }
175
176     namespace detail // deduce_char_traits template
177     {
178 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
179         template<class CharT, class Target, class Source>
180         struct deduce_char_traits
181         {
182             typedef std::char_traits<CharT> type;
183         };
184
185         template<class CharT, class Traits, class Alloc, class Source>
186         struct deduce_char_traits< CharT
187                                  , std::basic_string<CharT,Traits,Alloc>
188                                  , Source
189                                  >
190         {
191             typedef Traits type;
192         };
193
194         template<class CharT, class Target, class Traits, class Alloc>
195         struct deduce_char_traits< CharT
196                                  , Target
197                                  , std::basic_string<CharT,Traits,Alloc>
198                                  >
199         {
200             typedef Traits type;
201         };
202
203         template<class CharT, class Traits, class Alloc1, class Alloc2>
204         struct deduce_char_traits< CharT
205                                  , std::basic_string<CharT,Traits,Alloc1>
206                                  , std::basic_string<CharT,Traits,Alloc2>
207                                  >
208         {
209             typedef Traits type;
210         };
211 #endif
212     }
213
214     namespace detail // lcast_src_length
215     {
216         // Return max. length of string representation of Source;
217         // 0 if unlimited (with exceptions for some types, see below).
218         // Values with limited string representation are placed to
219         // the buffer locally defined in lexical_cast function.
220         // 1 is returned for few types such as CharT const* or
221         // std::basic_string<CharT> that already have an internal
222         // buffer ready to be reused by lexical_stream_limited_src.
223         // Each specialization should have a correspondent operator<<
224         // defined in lexical_stream_limited_src.
225         template< class CharT  // A result of widest_char transformation.
226                 , class Source // Source type of lexical_cast.
227                 >
228         struct lcast_src_length
229         {
230             BOOST_STATIC_CONSTANT(std::size_t, value = 0);
231             // To check coverage, build the test with
232             // bjam --v2 profile optimization=off
233             static void check_coverage() {}
234         };
235
236         template<>
237         struct lcast_src_length<char, bool>
238         {
239             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
240             static void check_coverage() {}
241         };
242
243         template<>
244         struct lcast_src_length<char, char>
245         {
246             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
247             static void check_coverage() {}
248         };
249
250         template<>
251         struct lcast_src_length<char, signed char>
252         {
253             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
254             static void check_coverage() {}
255         };
256         template<>
257         struct lcast_src_length<char, unsigned char>
258         {
259             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
260             static void check_coverage() {}
261         };
262         template<>
263         struct lcast_src_length<char, signed char*>
264         {
265             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
266             static void check_coverage() {}
267         };
268         template<>
269         struct lcast_src_length<char, unsigned char*>
270         {
271             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
272             static void check_coverage() {}
273         };
274         template<>
275         struct lcast_src_length<char, signed char const*>
276         {
277             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
278             static void check_coverage() {}
279         };
280         template<>
281         struct lcast_src_length<char, unsigned char const*>
282         {
283             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
284             static void check_coverage() {}
285         };
286
287 #ifndef BOOST_LCAST_NO_WCHAR_T
288         template<>
289         struct lcast_src_length<wchar_t, bool>
290         {
291             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
292             static void check_coverage() {}
293         };
294
295         template<>
296         struct lcast_src_length<wchar_t, char>
297         {
298             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
299             static void check_coverage() {}
300         };
301
302 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
303         template<>
304         struct lcast_src_length<wchar_t, wchar_t>
305         {
306             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
307             static void check_coverage() {}
308         };
309 #endif
310 #endif
311
312         template<>
313         struct lcast_src_length<char, char const*>
314         {
315             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
316             static void check_coverage() {}
317         };
318
319         template<>
320         struct lcast_src_length<char, char*>
321         {
322             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
323             static void check_coverage() {}
324         };
325
326 #ifndef BOOST_LCAST_NO_WCHAR_T
327         template<>
328         struct lcast_src_length<wchar_t, wchar_t const*>
329         {
330             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
331             static void check_coverage() {}
332         };
333
334         template<>
335         struct lcast_src_length<wchar_t, wchar_t*>
336         {
337             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
338             static void check_coverage() {}
339         };
340 #endif
341
342 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
343         template<class CharT, class Traits, class Alloc>
344         struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
345         {
346             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
347             static void check_coverage() {}
348         };
349 #else
350         template<>
351         struct lcast_src_length< char, std::basic_string<char> >
352         {
353             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
354             static void check_coverage() {}
355         };
356
357 #ifndef BOOST_LCAST_NO_WCHAR_T
358         template<>
359         struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
360         {
361             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
362             static void check_coverage() {}
363         };
364 #endif
365 #endif
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
395 #define BOOST_LCAST_DEF1(CharT, T)               \
396     template<> struct lcast_src_length<CharT, T> \
397         : lcast_src_length_integral<T>           \
398     { static void check_coverage() {} };
399
400 #ifdef BOOST_LCAST_NO_WCHAR_T
401 #define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T)
402 #else
403 #define BOOST_LCAST_DEF(T)          \
404         BOOST_LCAST_DEF1(char, T)   \
405         BOOST_LCAST_DEF1(wchar_t, T)
406 #endif
407
408         BOOST_LCAST_DEF(short)
409         BOOST_LCAST_DEF(unsigned short)
410         BOOST_LCAST_DEF(int)
411         BOOST_LCAST_DEF(unsigned int)
412         BOOST_LCAST_DEF(long)
413         BOOST_LCAST_DEF(unsigned long)
414 #if defined(BOOST_HAS_LONG_LONG)
415         BOOST_LCAST_DEF(boost::ulong_long_type)
416         BOOST_LCAST_DEF(boost::long_long_type )
417 #elif defined(BOOST_HAS_MS_INT64)
418         BOOST_LCAST_DEF(unsigned __int64)
419         BOOST_LCAST_DEF(         __int64)
420 #endif
421
422 #undef BOOST_LCAST_DEF
423 #undef BOOST_LCAST_DEF1
424
425 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
426         // Helper for floating point types.
427         // -1.23456789e-123456
428         // ^                   sign
429         //  ^                  leading digit
430         //   ^                 decimal point 
431         //    ^^^^^^^^         lcast_precision<Source>::value
432         //            ^        "e"
433         //             ^       exponent sign
434         //              ^^^^^^ exponent (assumed 6 or less digits)
435         // sign + leading digit + decimal point + "e" + exponent sign == 5
436         template<class Source>
437         struct lcast_src_length_floating
438         {
439             BOOST_STATIC_ASSERT(
440                     std::numeric_limits<Source>::max_exponent10 <=  999999L &&
441                     std::numeric_limits<Source>::min_exponent10 >= -999999L
442                 );
443             BOOST_STATIC_CONSTANT(std::size_t, value =
444                     5 + lcast_precision<Source>::value + 6
445                 );
446         };
447
448         template<>
449         struct lcast_src_length<char,float>
450           : lcast_src_length_floating<float>
451         {
452             static void check_coverage() {}
453         };
454
455         template<>
456         struct lcast_src_length<char,double>
457           : lcast_src_length_floating<double>
458         {
459             static void check_coverage() {}
460         };
461
462         template<>
463         struct lcast_src_length<char,long double>
464           : lcast_src_length_floating<long double>
465         {
466             static void check_coverage() {}
467         };
468
469 #ifndef BOOST_LCAST_NO_WCHAR_T
470     template<>
471     struct lcast_src_length<wchar_t,float>
472       : lcast_src_length_floating<float>
473     {
474         static void check_coverage() {}
475     };
476
477     template<>
478     struct lcast_src_length<wchar_t,double>
479       : lcast_src_length_floating<double>
480     {
481         static void check_coverage() {}
482     };
483
484     template<>
485     struct lcast_src_length<wchar_t,long double>
486       : lcast_src_length_floating<long double>
487     {
488         static void check_coverage() {}
489     };
490
491 #endif // #ifndef BOOST_LCAST_NO_WCHAR_T
492 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
493     }
494
495     namespace detail // '0', '+' and '-' constants
496     {
497         template<typename CharT> struct lcast_char_constants;
498
499         template<>
500         struct lcast_char_constants<char>
501         {
502             BOOST_STATIC_CONSTANT(char, zero  = '0');
503             BOOST_STATIC_CONSTANT(char, minus = '-');
504             BOOST_STATIC_CONSTANT(char, plus = '+');
505         };
506
507 #ifndef BOOST_LCAST_NO_WCHAR_T
508         template<>
509         struct lcast_char_constants<wchar_t>
510         {
511             BOOST_STATIC_CONSTANT(wchar_t, zero  = L'0');
512             BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
513             BOOST_STATIC_CONSTANT(wchar_t, plus = L'+');
514         };
515 #endif
516     }
517
518     namespace detail // lexical_streambuf_fake
519     {
520         struct lexical_streambuf_fake
521         {
522         };
523     }
524
525     namespace detail // lcast_to_unsigned
526     {
527 #if (defined _MSC_VER)
528 # pragma warning( push )
529 // C4146: unary minus operator applied to unsigned type, result still unsigned
530 # pragma warning( disable : 4146 )
531 #elif defined( __BORLANDC__ )
532 # pragma option push -w-8041
533 #endif
534         template<class T>
535         inline
536         BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
537         {
538             typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
539             result_type uvalue = static_cast<result_type>(value);
540             return value < 0 ? -uvalue : uvalue;
541         }
542 #if (defined _MSC_VER)
543 # pragma warning( pop )
544 #elif defined( __BORLANDC__ )
545 # pragma option pop
546 #endif
547     }
548
549     namespace detail // lcast_put_unsigned
550     {
551         template<class Traits, class T, class CharT>
552         CharT* lcast_put_unsigned(T n, CharT* finish)
553         {
554 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
555             BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
556 #endif
557
558             typedef typename Traits::int_type int_type;
559             CharT const czero = lcast_char_constants<CharT>::zero;
560             int_type const zero = Traits::to_int_type(czero);
561
562 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
563             // TODO: use BOOST_NO_STD_LOCALE
564             std::locale loc;
565             typedef std::numpunct<CharT> numpunct;
566             numpunct const& np = BOOST_USE_FACET(numpunct, loc);
567             std::string const& grouping = np.grouping();
568             std::string::size_type const grouping_size = grouping.size();
569
570             if ( grouping_size && grouping[0] > 0 )
571             {
572
573 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
574             // Check that ulimited group is unreachable:
575             BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
576 #endif
577                 CharT thousands_sep = np.thousands_sep();
578                 std::string::size_type group = 0; // current group number
579                 char last_grp_size = grouping[0];
580                 char left = last_grp_size;
581
582                 do
583                 {
584                     if(left == 0)
585                     {
586                         ++group;
587                         if(group < grouping_size)
588                         {
589                             char const grp_size = grouping[group];
590                             last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
591                         }
592
593                         left = last_grp_size;
594                         --finish;
595                         Traits::assign(*finish, thousands_sep);
596                     }
597
598                     --left;
599
600                     --finish;
601                     int_type const digit = static_cast<int_type>(n % 10U);
602                     Traits::assign(*finish, Traits::to_char_type(zero + digit));
603                     n /= 10;
604                 } while(n);
605
606             } else
607 #endif
608             {
609                 do
610                 {
611                     --finish;
612                     int_type const digit = static_cast<int_type>(n % 10U);
613                     Traits::assign(*finish, Traits::to_char_type(zero + digit));
614                     n /= 10;
615                 } while(n);
616             }
617
618             return finish;
619         }
620     }
621
622     namespace detail // lcast_ret_unsigned
623     {
624         template<class Traits, class T, class CharT>
625         inline bool lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end)
626         {
627 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
628             BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
629 #endif
630             typedef typename Traits::int_type int_type;
631             CharT const czero = lcast_char_constants<CharT>::zero;
632             --end;
633             value = 0;
634
635             if ( *end < czero || *end >= czero + 10 || begin > end)
636                 return false;
637             value = *end - czero;
638             --end;
639             T multiplier = 1;
640
641 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
642             // TODO: use BOOST_NO_STD_LOCALE
643             std::locale loc;
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 [22.2.2.1.2] of 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 new_sub_value = multiplier * 10 * (*end - czero);
663
664                         if (*end < czero || *end >= czero + 10
665                                 /* detecting overflow */
666                                 || new_sub_value/10 != multiplier * (*end - czero)
667                                 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
668                                 )
669                             return false;
670
671                         value += new_sub_value;
672                         multiplier *= 10;
673                         --remained;
674                     } else {
675                         if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false;
676                         {
677                             /*
678                              * According to Programming languages - C++
679                              * Digit grouping is checked. That is, the positions of discarded
680                              * separators is examined for consistency with
681                              * use_facet<numpunct<charT> >(loc ).grouping()
682                              *
683                              * BUT what if there is no separators at all and grouping()
684                              * is not empty? Well, we have no extraced separators, so we
685                              * won`t check them for consistency. This will allow us to
686                              * work with "C" locale from other locales
687                              */
688                             shall_we_return = false;
689                             break;
690                         } else {
691                             if ( begin == end ) return false;
692                             if (current_grouping < grouping_size-1 ) ++current_grouping;
693                             remained = grouping[current_grouping];
694                         }
695                     }
696                 }
697
698                 if (shall_we_return) return true;
699             }
700 #endif
701             {
702                 while ( begin <= end )
703                 {
704                     T const new_sub_value = multiplier * 10 * (*end - czero);
705
706                     if (*end < czero || *end >= czero + 10
707                             /* detecting overflow */
708                             || new_sub_value/10 != multiplier * (*end - czero)
709                             || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
710                             )
711                         return false;
712
713                     value += new_sub_value;
714                     multiplier *= 10;
715                     --end;
716                 }
717             }
718             return true;
719         }
720     }
721
722     namespace detail // stream wrapper for handling lexical conversions
723     {
724         template<typename Target, typename Source, typename Traits>
725         class lexical_stream
726         {
727         private:
728             typedef typename widest_char<
729                 typename stream_char<Target>::type,
730                 typename stream_char<Source>::type>::type char_type;
731
732             typedef Traits traits_type;
733
734         public:
735             lexical_stream(char_type* = 0, char_type* = 0)
736             {
737                 stream.unsetf(std::ios::skipws);
738                 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
739             }
740             ~lexical_stream()
741             {
742                 #if defined(BOOST_NO_STRINGSTREAM)
743                 stream.freeze(false);
744                 #endif
745             }
746             bool operator<<(const Source &input)
747             {
748                 return !(stream << input).fail();
749             }
750             template<typename InputStreamable>
751             bool operator>>(InputStreamable &output)
752             {
753                 return !is_pointer<InputStreamable>::value &&
754                        stream >> output &&
755                        stream.get() ==
756 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
757 // GCC 2.9x lacks std::char_traits<>::eof().
758 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
759 // configurations, which do provide std::char_traits<>::eof().
760     
761                            EOF;
762 #else
763                            traits_type::eof();
764 #endif
765             }
766
767 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
768
769             bool operator>>(std::string &output)
770             {
771                 #if defined(BOOST_NO_STRINGSTREAM)
772                 stream << '\0';
773                 #endif
774                 stream.str().swap(output);
775                 return true;
776             }
777             #ifndef BOOST_LCAST_NO_WCHAR_T
778             bool operator>>(std::wstring &output)
779             {
780                 stream.str().swap(output);
781                 return true;
782             }
783             #endif
784
785 #else
786             bool operator>>(std::basic_string<char_type,traits_type>& output)
787             {
788                 stream.str().swap(output);
789                 return true;
790             }
791
792             template<class Alloc>
793             bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out)
794             {
795                 std::basic_string<char_type,traits_type> str(stream.str());
796                 out.assign(str.begin(), str.end());
797                 return true;
798             }
799 #endif
800         private:
801             #if defined(BOOST_NO_STRINGSTREAM)
802             std::strstream stream;
803             #elif defined(BOOST_NO_STD_LOCALE)
804             std::stringstream stream;
805             #else
806             std::basic_stringstream<char_type,traits_type> stream;
807             #endif
808         };
809     }
810
811     namespace detail // optimized stream wrapper
812     {
813         // String representation of Source has an upper limit.
814         template< class CharT // a result of widest_char transformation
815                 , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
816                 , class Traits // usually char_traits<CharT>
817                 >
818         class lexical_stream_limited_src : public Base
819         {
820             // A string representation of Source is written to [start, finish).
821             // Currently, it is assumed that [start, finish) is big enough
822             // to hold a string representation of any Source value.
823             CharT* start;
824             CharT* finish;
825
826         private:
827
828             static void widen_and_assign(char*p, char ch)
829             {
830                 Traits::assign(*p, ch);
831             }
832
833 #ifndef BOOST_LCAST_NO_WCHAR_T
834             static void widen_and_assign(wchar_t* p, char ch)
835             {
836                 // TODO: use BOOST_NO_STD_LOCALE
837                 std::locale loc;
838                 wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
839                 Traits::assign(*p, w);
840             }
841
842             static void widen_and_assign(wchar_t* p, wchar_t ch)
843             {
844                 Traits::assign(*p, ch);
845             }
846
847             static void widen_and_assign(char*, wchar_t ch); // undefined
848 #endif
849
850             template<class OutputStreamable>
851             bool lcast_put(const OutputStreamable& input)
852             {
853                 this->setp(start, finish);
854                 std::basic_ostream<CharT> stream(static_cast<Base*>(this));
855                 lcast_set_precision(stream, static_cast<OutputStreamable*>(0));
856                 bool const result = !(stream << input).fail();
857                 finish = this->pptr();
858                 return result;
859             }
860
861             // Undefined:
862             lexical_stream_limited_src(lexical_stream_limited_src const&);
863             void operator=(lexical_stream_limited_src const&);
864
865         public:
866
867             lexical_stream_limited_src(CharT* sta, CharT* fin)
868               : start(sta)
869               , finish(fin)
870             {}
871
872         public: // output
873
874             template<class Alloc>
875             bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
876             {
877                 start = const_cast<CharT*>(str.data());
878                 finish = start + str.length();
879                 return true;
880             }
881
882             bool operator<<(bool);
883             bool operator<<(char);
884             bool operator<<(unsigned char);
885             bool operator<<(signed char);
886 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
887             bool operator<<(wchar_t);
888 #endif
889             bool operator<<(unsigned char const*);
890             bool operator<<(signed char const*);
891             bool operator<<(CharT const*);
892             bool operator<<(short);
893             bool operator<<(int);
894             bool operator<<(long);
895             bool operator<<(unsigned short);
896             bool operator<<(unsigned int);
897             bool operator<<(unsigned long);
898 #if defined(BOOST_HAS_LONG_LONG)
899             bool operator<<(boost::ulong_long_type);
900             bool operator<<(boost::long_long_type );
901 #elif defined(BOOST_HAS_MS_INT64)
902             bool operator<<(unsigned __int64);
903             bool operator<<(         __int64);
904 #endif
905             // These three operators use ostream and streambuf.
906             // lcast_streambuf_for_source<T>::value is true.
907             bool operator<<(float);
908             bool operator<<(double);
909             bool operator<<(long double);
910
911         private:
912
913             template <typename Type>
914             bool input_operator_helper_unsigned(Type& output)
915             {
916                 CharT const minus = lcast_char_constants<CharT>::minus;
917                 CharT const plus = lcast_char_constants<CharT>::plus;
918                 bool has_minus = false;
919
920                 /* We won`t use `start' any more, so no need in decrementing it after */
921                 if ( Traits::eq(minus,*start) )
922                 {
923                     ++start;
924                     has_minus = true;
925                 } else if ( Traits::eq( plus, *start ) )
926                 {
927                     ++start;
928                 }
929
930                 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish);
931 #if (defined _MSC_VER)
932 # pragma warning( push )
933 // C4146: unary minus operator applied to unsigned type, result still unsigned
934 # pragma warning( disable : 4146 )
935 #elif defined( __BORLANDC__ )
936 # pragma option push -w-8041
937 #endif
938                 if (has_minus) output = static_cast<Type>(-output);
939 #if (defined _MSC_VER)
940 # pragma warning( pop )
941 #elif defined( __BORLANDC__ )
942 # pragma option pop
943 #endif
944                 return succeed;
945             }
946
947             template <typename Type>
948             bool input_operator_helper_signed(Type& output)
949             {
950                 CharT const minus = lcast_char_constants<CharT>::minus;
951                 CharT const plus = lcast_char_constants<CharT>::plus;
952                 typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
953                 utype out_tmp =0;
954                 bool has_minus = false;
955
956                 /* We won`t use `start' any more, so no need in decrementing it after */
957                 if ( Traits::eq(minus,*start) )
958                 {
959                     ++start;
960                     has_minus = true;
961                 } else if ( Traits::eq(plus, *start) )
962                 {
963                     ++start;
964                 }
965
966                 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish);
967                 if (has_minus) {
968 #if (defined _MSC_VER)
969 # pragma warning( push )
970 // C4146: unary minus operator applied to unsigned type, result still unsigned
971 # pragma warning( disable : 4146 )
972 #elif defined( __BORLANDC__ )
973 # pragma option push -w-8041
974 #endif
975                     utype const comp_val = static_cast<utype>(-(std::numeric_limits<Type>::min)());
976                     succeed = succeed && out_tmp<=comp_val;
977                     output = -out_tmp;
978 #if (defined _MSC_VER)
979 # pragma warning( pop )
980 #elif defined( __BORLANDC__ )
981 # pragma option pop
982 #endif
983                 } else {
984                     utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
985                     succeed = succeed && out_tmp<=comp_val;
986                     output = out_tmp;
987                 }
988                 return succeed;
989             }
990
991         public: // input
992
993             bool operator>>(unsigned short& output)
994             {
995                 return input_operator_helper_unsigned(output);
996             }
997
998             bool operator>>(unsigned int& output)
999             {
1000                 return input_operator_helper_unsigned(output);
1001             }
1002
1003             bool operator>>(unsigned long int& output)
1004             {
1005                 return input_operator_helper_unsigned(output);
1006             }
1007
1008             bool operator>>(short& output)
1009             {
1010                 return input_operator_helper_signed(output);
1011             }
1012
1013             bool operator>>(int& output)
1014             {
1015                 return input_operator_helper_signed(output);
1016             }
1017
1018             bool operator>>(long int& output)
1019             {
1020                 return input_operator_helper_signed(output);
1021             }
1022
1023
1024 #if defined(BOOST_HAS_LONG_LONG)
1025             bool operator>>( boost::ulong_long_type& output)
1026             {
1027                 return input_operator_helper_unsigned(output);
1028             }
1029
1030             bool operator>>(boost::long_long_type& output)
1031             {
1032                 return input_operator_helper_signed(output);
1033             }
1034
1035 #elif defined(BOOST_HAS_MS_INT64)
1036             bool operator>>(unsigned __int64& output)
1037             {
1038                 return input_operator_helper_unsigned(output);
1039             }
1040
1041             bool operator>>(__int64& output)
1042             {
1043                 return input_operator_helper_signed(output);
1044             }
1045
1046 #endif
1047
1048             /*
1049              * case "-0" || "0" || "+0" :   output = false; return true;
1050              * case "1" || "+1":            output = true;  return true;
1051              * default:                     return false;
1052              */
1053             bool operator>>(bool& output)
1054             {
1055                 CharT const zero = lcast_char_constants<CharT>::zero;
1056                 CharT const plus = lcast_char_constants<CharT>::plus;
1057                 CharT const minus = lcast_char_constants<CharT>::minus;
1058
1059                 switch(finish-start)
1060                 {
1061                     case 1:
1062                         output = Traits::eq(start[0],  zero+1);
1063                         return output || Traits::eq(start[0], zero );
1064                     case 2:
1065                         if ( Traits::eq( plus, *start) )
1066                         {
1067                             ++start;
1068                             output = Traits::eq(start[0], zero +1);
1069                             return output || Traits::eq(start[0], zero );
1070                         } else
1071                         {
1072                             output = false;
1073                             return Traits::eq( minus, *start)
1074                                 && Traits::eq( zero, start[1]);
1075                         }
1076                     default:
1077                         output = false; // Suppress warning about uninitalized variable
1078                         return false;
1079                 }
1080             }
1081
1082
1083             // Generic istream-based algorithm.
1084             // lcast_streambuf_for_target<InputStreamable>::value is true.
1085             template<typename InputStreamable>
1086             bool operator>>(InputStreamable& output)
1087             {
1088 #if (defined _MSC_VER)
1089 # pragma warning( push )
1090   // conditional expression is constant
1091 # pragma warning( disable : 4127 )
1092 #endif
1093                 if(is_pointer<InputStreamable>::value)
1094                     return false;
1095
1096                 this->setg(start, start, finish);
1097                 std::basic_istream<CharT> stream(static_cast<Base*>(this));
1098                 stream.unsetf(std::ios::skipws);
1099                 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
1100 #if (defined _MSC_VER)
1101 # pragma warning( pop )
1102 #endif
1103                 return stream >> output &&
1104                     stream.get() ==
1105 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
1106         // GCC 2.9x lacks std::char_traits<>::eof().
1107         // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
1108         // configurations, which do provide std::char_traits<>::eof().
1109
1110                     EOF;
1111 #else
1112                 Traits::eof();
1113 #endif
1114             }
1115
1116             bool operator>>(CharT&);
1117             bool operator>>(unsigned char&);
1118             bool operator>>(signed char&);
1119
1120 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1121 // This #if is in sync with lcast_streambuf_for_target
1122
1123             bool operator>>(std::string&);
1124
1125 #ifndef BOOST_LCAST_NO_WCHAR_T
1126             bool operator>>(std::wstring&);
1127 #endif
1128
1129 #else
1130             template<class Alloc>
1131             bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
1132             {
1133                 str.assign(start, finish);
1134                 return true;
1135             }
1136 #endif
1137         };
1138
1139         template<typename CharT, class Base, class Traits>
1140         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1141                 bool value)
1142         {
1143             typedef typename Traits::int_type int_type;
1144             CharT const czero = lcast_char_constants<CharT>::zero;
1145             int_type const zero = Traits::to_int_type(czero);
1146             Traits::assign(*start, Traits::to_char_type(zero + value));
1147             finish = start + 1;
1148             return true;
1149         }
1150
1151         template<typename CharT, class Base, class Traits>
1152         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1153                 char ch)
1154         {
1155             widen_and_assign(start, ch);
1156             finish = start + 1;
1157             return true;
1158         }
1159
1160         template<typename CharT, class Base, class Traits>
1161         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1162                unsigned char ch)
1163         {
1164             return ((*this) << static_cast<char>(ch));
1165         }
1166
1167         template<typename CharT, class Base, class Traits>
1168         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1169                signed char ch)
1170         {
1171             return ((*this) << static_cast<char>(ch));
1172         }
1173
1174         template<typename CharT, class Base, class Traits>
1175         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1176                unsigned char const* ch)
1177         {
1178             return ((*this) << reinterpret_cast<char const*>(ch));
1179         }
1180
1181         template<typename CharT, class Base, class Traits>
1182         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1183                signed char const* ch)
1184         {
1185             return ((*this) << reinterpret_cast<char const*>(ch));
1186         }
1187
1188 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1189         template<typename CharT, class Base, class Traits>
1190         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1191                 wchar_t ch)
1192         {
1193             widen_and_assign(start, ch);
1194             finish = start + 1;
1195             return true;
1196         }
1197 #endif
1198
1199         template<typename CharT, class Base, class Traits>
1200         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1201                 short n)
1202         {
1203             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1204             if(n < 0)
1205             {
1206                 --start;
1207                 CharT const minus = lcast_char_constants<CharT>::minus;
1208                 Traits::assign(*start, minus);
1209             }
1210             return true;
1211         }
1212
1213         template<typename CharT, class Base, class Traits>
1214         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1215                 int n)
1216         {
1217             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1218             if(n < 0)
1219             {
1220                 --start;
1221                 CharT const minus = lcast_char_constants<CharT>::minus;
1222                 Traits::assign(*start, minus);
1223             }
1224             return true;
1225         }
1226
1227         template<typename CharT, class Base, class Traits>
1228         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1229                 long n)
1230         {
1231             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1232             if(n < 0)
1233             {
1234                 --start;
1235                 CharT const minus = lcast_char_constants<CharT>::minus;
1236                 Traits::assign(*start, minus);
1237             }
1238             return true;
1239         }
1240
1241 #if defined(BOOST_HAS_LONG_LONG)
1242         template<typename CharT, class Base, class Traits>
1243         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1244                 boost::long_long_type n)
1245         {
1246             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1247             if(n < 0)
1248             {
1249                 --start;
1250                 CharT const minus = lcast_char_constants<CharT>::minus;
1251                 Traits::assign(*start, minus);
1252             }
1253             return true;
1254         }
1255 #elif defined(BOOST_HAS_MS_INT64)
1256         template<typename CharT, class Base, class Traits>
1257         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1258                 __int64 n)
1259         {
1260             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1261             if(n < 0)
1262             {
1263                 --start;
1264                 CharT const minus = lcast_char_constants<CharT>::minus;
1265                 Traits::assign(*start, minus);
1266             }
1267             return true;
1268         }
1269 #endif
1270
1271         template<typename CharT, class Base, class Traits>
1272         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1273                 unsigned short n)
1274         {
1275             start = lcast_put_unsigned<Traits>(n, finish);
1276             return true;
1277         }
1278
1279         template<typename CharT, class Base, class Traits>
1280         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1281                 unsigned int n)
1282         {
1283             start = lcast_put_unsigned<Traits>(n, finish);
1284             return true;
1285         }
1286
1287         template<typename CharT, class Base, class Traits>
1288         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1289                 unsigned long n)
1290         {
1291             start = lcast_put_unsigned<Traits>(n, finish);
1292             return true;
1293         }
1294
1295 #if defined(BOOST_HAS_LONG_LONG)
1296         template<typename CharT, class Base, class Traits>
1297         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1298                 boost::ulong_long_type n)
1299         {
1300             start = lcast_put_unsigned<Traits>(n, finish);
1301             return true;
1302         }
1303 #elif defined(BOOST_HAS_MS_INT64)
1304         template<typename CharT, class Base, class Traits>
1305         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1306                 unsigned __int64 n)
1307         {
1308             start = lcast_put_unsigned<Traits>(n, finish);
1309             return true;
1310         }
1311 #endif
1312
1313         template<typename CharT, class Base, class Traits>
1314         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1315                 float val)
1316         {
1317             return this->lcast_put(val);
1318         }
1319
1320         template<typename CharT, class Base, class Traits>
1321         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1322                 double val)
1323         {
1324             return this->lcast_put(val);
1325         }
1326
1327         template<typename CharT, class Base, class Traits>
1328         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1329                 long double val)
1330         {
1331             return this->lcast_put(val);
1332         }
1333
1334         template<typename CharT, class Base, class Traits>
1335         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
1336                 CharT const* str)
1337         {
1338             start = const_cast<CharT*>(str);
1339             finish = start + Traits::length(str);
1340             return true;
1341         }
1342
1343         template<typename CharT, class Base, class Traits>
1344         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1345                 CharT& output)
1346         {
1347             bool const ok = (finish - start == 1);
1348             if(ok)
1349                 Traits::assign(output, *start);
1350             return ok;
1351         }
1352
1353         template<typename CharT, class Base, class Traits>
1354         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1355                 unsigned char& output)
1356         {
1357             BOOST_STATIC_ASSERT( sizeof(CharT) == sizeof(unsigned char) );
1358             bool const ok = (finish - start == 1);
1359             if(ok) {
1360                 CharT out;
1361                 Traits::assign(out, *start);
1362                 output = static_cast<signed char>(out);
1363             }
1364             return ok;
1365         }
1366
1367         template<typename CharT, class Base, class Traits>
1368         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1369                 signed char& output)
1370         {
1371             BOOST_STATIC_ASSERT( sizeof(CharT) == sizeof(signed char) );
1372             bool const ok = (finish - start == 1);
1373             if(ok) {
1374                 CharT out;
1375                 Traits::assign(out, *start);
1376                 output = static_cast<signed char>(out);
1377             }
1378             return ok;
1379         }
1380
1381 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1382         template<typename CharT, class Base, class Traits>
1383         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1384                 std::string& str)
1385         {
1386             str.assign(start, finish);
1387             return true;
1388         }
1389
1390 #ifndef BOOST_LCAST_NO_WCHAR_T
1391         template<typename CharT, class Base, class Traits>
1392         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1393                 std::wstring& str)
1394         {
1395             str.assign(start, finish);
1396             return true;
1397         }
1398 #endif
1399 #endif
1400     }
1401
1402     namespace detail // lcast_streambuf_for_source
1403     {
1404         // Returns true if optimized stream wrapper needs ostream for writing.
1405         template<class Source>
1406         struct lcast_streambuf_for_source
1407         {
1408             BOOST_STATIC_CONSTANT(bool, value = false);
1409         };
1410
1411         template<>
1412         struct lcast_streambuf_for_source<float>
1413         {
1414             BOOST_STATIC_CONSTANT(bool, value = true);
1415         };
1416  
1417         template<>
1418         struct lcast_streambuf_for_source<double>
1419         {
1420             BOOST_STATIC_CONSTANT(bool, value = true);
1421         };
1422   
1423         template<>
1424         struct lcast_streambuf_for_source<long double>
1425         {
1426             BOOST_STATIC_CONSTANT(bool, value = true);
1427         };
1428     }
1429
1430     namespace detail // lcast_streambuf_for_target
1431     {
1432         // Returns true if optimized stream wrapper needs istream for reading.
1433         template<class Target>
1434         struct lcast_streambuf_for_target
1435         {
1436             BOOST_STATIC_CONSTANT(bool, value =
1437                 (
1438                  ::boost::type_traits::ice_not< is_integral<Target>::value >::value
1439                 )
1440             );
1441         };
1442
1443 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1444         template<class Traits, class Alloc>
1445         struct lcast_streambuf_for_target<
1446                     std::basic_string<char,Traits,Alloc> >
1447         {
1448             BOOST_STATIC_CONSTANT(bool, value = false);
1449         };
1450
1451 #ifndef BOOST_LCAST_NO_WCHAR_T
1452         template<class Traits, class Alloc>
1453         struct lcast_streambuf_for_target<
1454                     std::basic_string<wchar_t,Traits,Alloc> >
1455         {
1456             BOOST_STATIC_CONSTANT(bool, value = false);
1457         };
1458 #endif
1459 #else
1460         template<>
1461         struct lcast_streambuf_for_target<std::string>
1462         {
1463             BOOST_STATIC_CONSTANT(bool, value = false);
1464         };
1465
1466 #ifndef BOOST_LCAST_NO_WCHAR_T
1467         template<>
1468         struct lcast_streambuf_for_target<std::wstring>
1469         {
1470             BOOST_STATIC_CONSTANT(bool, value = false);
1471         };
1472 #endif
1473 #endif
1474     }
1475
1476     #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1477
1478     // call-by-const reference version
1479
1480     namespace detail
1481     {
1482         template<class T>
1483         struct array_to_pointer_decay
1484         {
1485             typedef T type;
1486         };
1487
1488         template<class T, std::size_t N>
1489         struct array_to_pointer_decay<T[N]>
1490         {
1491             typedef const T * type;
1492         };
1493
1494 #if (defined _MSC_VER)
1495 # pragma warning( push )
1496 # pragma warning( disable : 4701 ) // possible use of ... before initialization
1497 # pragma warning( disable : 4702 ) // unreachable code
1498 # pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int'
1499 #endif
1500
1501         template< typename Target
1502                 , typename Source
1503                 , bool Unlimited // string representation of Source is unlimited
1504                 , typename CharT
1505                 >
1506         Target lexical_cast(
1507             BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
1508             CharT* buf, std::size_t src_len)
1509         {
1510             typedef BOOST_DEDUCED_TYPENAME
1511                 deduce_char_traits<CharT,Target,Source>::type traits;
1512
1513             typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1514                 lcast_streambuf_for_target<Target>::value ||
1515                 lcast_streambuf_for_source<Source>::value
1516               , std::basic_streambuf<CharT>
1517               , lexical_streambuf_fake
1518               >::type base;
1519
1520             BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1521                 Unlimited
1522               , detail::lexical_stream<Target,Source,traits>
1523               , detail::lexical_stream_limited_src<CharT,base,traits>
1524               >::type interpreter(buf, buf + src_len);
1525
1526             Target result;
1527             if(!(interpreter << arg && interpreter >> result))
1528               BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1529             return result;
1530         }
1531 #if (defined _MSC_VER)
1532 # pragma warning( pop )
1533 #endif
1534
1535         template<typename T>
1536         struct is_stdstring
1537         {
1538             BOOST_STATIC_CONSTANT(bool, value = false );
1539         };
1540
1541         template<typename CharT, typename Traits, typename Alloc>
1542         struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
1543         {
1544             BOOST_STATIC_CONSTANT(bool, value = true );
1545         };
1546
1547         template<typename T>
1548         struct is_char_or_wchar
1549         {
1550 #ifndef BOOST_LCAST_NO_WCHAR_T
1551             BOOST_STATIC_CONSTANT(bool, value =
1552                     (
1553                     ::boost::type_traits::ice_or<
1554                          is_same< T, char >::value,
1555                          is_same< T, wchar_t >::value,
1556                          is_same< T, unsigned char >::value,
1557                          is_same< T, signed char >::value
1558                     >::value
1559                     )
1560             );
1561 #else
1562             BOOST_STATIC_CONSTANT(bool, value =
1563                     (
1564                     ::boost::type_traits::ice_or<
1565                          is_same< T, char >::value,
1566                          is_same< T, unsigned char >::value,
1567                          is_same< T, signed char >::value
1568                     >::value
1569                     )
1570             );
1571 #endif
1572         };
1573
1574         template<typename Target, typename Source>
1575         struct is_arithmetic_and_not_xchars
1576         {
1577             BOOST_STATIC_CONSTANT(bool, value =
1578                (
1579                    ::boost::type_traits::ice_and<
1580                            is_arithmetic<Source>::value,
1581                            is_arithmetic<Target>::value,
1582                            ::boost::type_traits::ice_not<
1583                                 detail::is_char_or_wchar<Target>::value
1584                            >::value,
1585                            ::boost::type_traits::ice_not<
1586                                 detail::is_char_or_wchar<Source>::value
1587                            >::value
1588                    >::value
1589                )
1590             );
1591         };
1592
1593         /*
1594          * is_xchar_to_xchar<Target, Source>::value is true, when
1595          * Target and Souce are the same char types, or when
1596          * Target and Souce are char types of the same size.
1597          */
1598         template<typename Target, typename Source>
1599         struct is_xchar_to_xchar
1600         {
1601             BOOST_STATIC_CONSTANT(bool, value =
1602                 (
1603                     ::boost::type_traits::ice_or<
1604                         ::boost::type_traits::ice_and<
1605                              is_same<Source,Target>::value,
1606                              is_char_or_wchar<Target>::value
1607                         >::value,
1608                         ::boost::type_traits::ice_and<
1609                              ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
1610                              ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
1611                              is_char_or_wchar<Target>::value,
1612                              is_char_or_wchar<Source>::value
1613                         >::value
1614                     >::value
1615                 )
1616             );
1617         };
1618
1619         template<typename Target, typename Source>
1620         struct is_char_array_to_stdstring
1621         {
1622             BOOST_STATIC_CONSTANT(bool, value = false );
1623         };
1624
1625         template<typename CharT, typename Traits, typename Alloc>
1626         struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
1627         {
1628             BOOST_STATIC_CONSTANT(bool, value = true );
1629         };
1630
1631         template<typename CharT, typename Traits, typename Alloc>
1632         struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
1633         {
1634             BOOST_STATIC_CONSTANT(bool, value = true );
1635         };
1636
1637         template<typename Target, typename Source>
1638         struct lexical_cast_do_cast
1639         {
1640             static inline Target lexical_cast_impl(const Source &arg)
1641             {
1642                 typedef typename detail::array_to_pointer_decay<Source>::type src;
1643
1644                 typedef typename detail::widest_char<
1645                 typename detail::stream_char<Target>::type
1646                 , typename detail::stream_char<src>::type
1647                 >::type char_type;
1648
1649                 typedef detail::lcast_src_length<char_type, src> lcast_src_length;
1650                 std::size_t const src_len = lcast_src_length::value;
1651                 char_type buf[src_len + 1];
1652                 lcast_src_length::check_coverage();
1653                 return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
1654             }
1655         };
1656
1657         template<typename Source>
1658         struct lexical_cast_copy
1659         {
1660             static inline Source lexical_cast_impl(const Source &arg)
1661             {
1662                 return arg;
1663             }
1664         };
1665
1666         class precision_loss_error : public boost::numeric::bad_numeric_cast
1667         {
1668          public:
1669             virtual const char * what() const throw()
1670              {  return "bad numeric conversion: precision loss error"; }
1671         };
1672
1673         template<class S >
1674         struct throw_on_precision_loss
1675         {
1676          typedef boost::numeric::Trunc<S> Rounder;
1677          typedef S source_type ;
1678
1679          typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
1680
1681          static source_type nearbyint ( argument_type s )
1682          {
1683             source_type orig_div_round = s / Rounder::nearbyint(s);
1684
1685             if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits<source_type>::epsilon() )
1686                BOOST_THROW_EXCEPTION( precision_loss_error() );
1687             return s ;
1688          }
1689
1690          typedef typename Rounder::round_style round_style;
1691         } ;
1692
1693         template<typename Target, typename Source>
1694         struct lexical_cast_dynamic_num_not_ignoring_minus
1695         {
1696             static inline Target lexical_cast_impl(const Source &arg)
1697             {
1698                 try{
1699                     typedef boost::numeric::converter<
1700                             Target,
1701                             Source,
1702                             boost::numeric::conversion_traits<Target,Source>,
1703                             boost::numeric::def_overflow_handler,
1704                             throw_on_precision_loss<Source>
1705                     > Converter ;
1706
1707                     return Converter::convert(arg);
1708                 } catch( ::boost::numeric::bad_numeric_cast const& ) {
1709                     BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1710                 }
1711             }
1712         };
1713
1714         template<typename Target, typename Source>
1715         struct lexical_cast_dynamic_num_ignoring_minus
1716         {
1717             static inline Target lexical_cast_impl(const Source &arg)
1718             {
1719                 try{
1720                     typedef boost::numeric::converter<
1721                             Target,
1722                             Source,
1723                             boost::numeric::conversion_traits<Target,Source>,
1724                             boost::numeric::def_overflow_handler,
1725                             throw_on_precision_loss<Source>
1726                     > Converter ;
1727
1728                     bool has_minus = ( arg < 0);
1729                     if ( has_minus ) {
1730                         return static_cast<Target>(-Converter::convert(-arg));
1731                     } else {
1732                         return Converter::convert(arg);
1733                     }
1734                 } catch( ::boost::numeric::bad_numeric_cast const& ) {
1735                     BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1736                 }
1737             }
1738         };
1739
1740         /*
1741          * lexical_cast_dynamic_num follows the rules:
1742          * 1) If Source can be converted to Target without precision loss and
1743          * without overflows, then assign Source to Target and return
1744          *
1745          * 2) If Source is less than 0 and Target is an unsigned integer,
1746          * then negate Source, check the requirements of rule 1) and if
1747          * successful, assign static_casted Source to Target and return
1748          *
1749          * 3) Otherwise throw a bad_lexical_cast exception
1750          *
1751          *
1752          * Rule 2) required because boost::lexical_cast has the behavior of
1753          * stringstream, which uses the rules of scanf for conversions. And
1754          * in the C99 standard for unsigned input value minus sign is
1755          * optional, so if a negative number is read, no errors will arise
1756          * and the result will be the two's complement.
1757          */
1758         template<typename Target, typename Source>
1759         struct lexical_cast_dynamic_num
1760         {
1761             static inline Target lexical_cast_impl(const Source &arg)
1762             {
1763                 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
1764                     ::boost::type_traits::ice_and<
1765                         ::boost::type_traits::ice_or<
1766                             ::boost::is_signed<Source>::value,
1767                             ::boost::is_float<Source>::value
1768                         >::value,
1769                         ::boost::type_traits::ice_not<
1770                             is_same<Source, bool>::value
1771                         >::value,
1772                         ::boost::type_traits::ice_not<
1773                             is_same<Target, bool>::value
1774                         >::value,
1775                         ::boost::is_unsigned<Target>::value
1776                     >::value,
1777                     lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
1778                     lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
1779                 >::type caster_type;
1780
1781                 return caster_type::lexical_cast_impl(arg);
1782             }
1783         };
1784     }
1785
1786     template<typename Target, typename Source>
1787     inline Target lexical_cast(const Source &arg)
1788     {
1789         typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
1790
1791         typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or<
1792                 detail::is_xchar_to_xchar<Target, src>::value,
1793                 detail::is_char_array_to_stdstring<Target,src>::value,
1794                 ::boost::type_traits::ice_and<
1795                      is_same<Target, src>::value,
1796                      detail::is_stdstring<Target>::value
1797                 >::value
1798         > do_copy_type;
1799
1800         typedef BOOST_DEDUCED_TYPENAME
1801                 detail::is_arithmetic_and_not_xchars<Target, src> do_copy_with_dynamic_check_type;
1802
1803         typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
1804             do_copy_type::value,
1805             detail::lexical_cast_copy<src>,
1806             BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
1807                  do_copy_with_dynamic_check_type::value,
1808                  detail::lexical_cast_dynamic_num<Target, src>,
1809                  detail::lexical_cast_do_cast<Target, src>
1810             >::type
1811         >::type caster_type;
1812
1813         return caster_type::lexical_cast_impl(arg);
1814     }
1815
1816     #else
1817
1818     // call-by-value fallback version (deprecated)
1819
1820     template<typename Target, typename Source>
1821     Target lexical_cast(Source arg)
1822     {
1823         typedef typename detail::widest_char< 
1824             BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type 
1825           , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type 
1826         >::type char_type; 
1827
1828         typedef std::char_traits<char_type> traits;
1829         detail::lexical_stream<Target, Source, traits> interpreter;
1830         Target result;
1831
1832         if(!(interpreter << arg && interpreter >> result))
1833           BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1834         return result;
1835     }
1836
1837     #endif
1838 }
1839
1840 // Copyright Kevlin Henney, 2000-2005.
1841 // Copyright Alexander Nasonov, 2006-2010.
1842 // Copyright Antony Polukhin, 2011.
1843 //
1844 // Distributed under the Boost Software License, Version 1.0. (See
1845 // accompanying file LICENSE_1_0.txt or copy at
1846 // http://www.boost.org/LICENSE_1_0.txt)
1847
1848 #undef BOOST_LCAST_NO_WCHAR_T
1849 #endif