Merge c:/dyninst/pc_bluegene/dyninst into dyn_pc_integration
[dyninst.git] / external / 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 and other Boosters
15 // when:  November 2000, March 2003, June 2005, June 2006
16
17 #include <climits>
18 #include <cstddef>
19 #include <istream>
20 #include <string>
21 #include <typeinfo>
22 #include <exception>
23 #include <boost/config.hpp>
24 #include <boost/limits.hpp>
25 #include <boost/mpl/if.hpp>
26 #include <boost/throw_exception.hpp>
27 #include <boost/type_traits/is_pointer.hpp>
28 #include <boost/type_traits/make_unsigned.hpp>
29 #include <boost/call_traits.hpp>
30 #include <boost/static_assert.hpp>
31 #include <boost/detail/lcast_precision.hpp>
32 #include <boost/detail/workaround.hpp>
33
34 #ifndef BOOST_NO_STD_LOCALE
35 #include <locale>
36 #endif
37
38 #ifdef BOOST_NO_STRINGSTREAM
39 #include <strstream>
40 #else
41 #include <sstream>
42 #endif
43
44 #if defined(BOOST_NO_STRINGSTREAM) || \
45     defined(BOOST_NO_STD_WSTRING) || \
46     defined(BOOST_NO_STD_LOCALE) 
47 #define BOOST_LCAST_NO_WCHAR_T
48 #endif
49
50 namespace boost
51 {
52     // exception used to indicate runtime lexical_cast failure
53     class bad_lexical_cast : public std::bad_cast
54
55 #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
56         // under bcc32 5.5.1 bad_cast doesn't derive from exception
57         , public std::exception
58 #endif
59
60     {
61     public:
62         bad_lexical_cast() :
63         source(&typeid(void)), target(&typeid(void))
64         {
65         }
66         bad_lexical_cast(
67             const std::type_info &source_type_arg,
68             const std::type_info &target_type_arg) :
69             source(&source_type_arg), target(&target_type_arg)
70         {
71         }
72         const std::type_info &source_type() const
73         {
74             return *source;
75         }
76         const std::type_info &target_type() const
77         {
78             return *target;
79         }
80         virtual const char *what() const throw()
81         {
82             return "bad lexical cast: "
83                    "source type value could not be interpreted as target";
84         }
85         virtual ~bad_lexical_cast() throw()
86         {
87         }
88     private:
89         const std::type_info *source;
90         const std::type_info *target;
91     };
92
93     namespace detail // selectors for choosing stream character type
94     {
95         template<typename Type>
96         struct stream_char
97         {
98             typedef char type;
99         };
100
101 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
102         template<class CharT, class Traits, class Alloc>
103         struct stream_char< std::basic_string<CharT,Traits,Alloc> >
104         {
105             typedef CharT type;
106         };
107 #endif
108
109 #ifndef BOOST_LCAST_NO_WCHAR_T
110 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
111         template<>
112         struct stream_char<wchar_t>
113         {
114             typedef wchar_t type;
115         };
116 #endif
117
118         template<>
119         struct stream_char<wchar_t *>
120         {
121             typedef wchar_t type;
122         };
123
124         template<>
125         struct stream_char<const wchar_t *>
126         {
127             typedef wchar_t type;
128         };
129
130 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
131         template<>
132         struct stream_char<std::wstring>
133         {
134             typedef wchar_t type;
135         };
136 #endif
137 #endif
138
139         template<typename TargetChar, typename SourceChar>
140         struct widest_char
141         {
142             typedef TargetChar type;
143         };
144
145         template<>
146         struct widest_char<char, wchar_t>
147         {
148             typedef wchar_t type;
149         };
150     }
151
152     namespace detail // deduce_char_traits template
153     {
154 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
155         template<class CharT, class Target, class Source>
156         struct deduce_char_traits
157         {
158             typedef std::char_traits<CharT> type;
159         };
160
161         template<class CharT, class Traits, class Alloc, class Source>
162         struct deduce_char_traits< CharT
163                                  , std::basic_string<CharT,Traits,Alloc>
164                                  , Source
165                                  >
166         {
167             typedef Traits type;
168         };
169
170         template<class CharT, class Target, class Traits, class Alloc>
171         struct deduce_char_traits< CharT
172                                  , Target
173                                  , std::basic_string<CharT,Traits,Alloc>
174                                  >
175         {
176             typedef Traits type;
177         };
178
179         template<class CharT, class Traits, class Alloc1, class Alloc2>
180         struct deduce_char_traits< CharT
181                                  , std::basic_string<CharT,Traits,Alloc1>
182                                  , std::basic_string<CharT,Traits,Alloc2>
183                                  >
184         {
185             typedef Traits type;
186         };
187 #endif
188     }
189
190     namespace detail // lcast_src_length
191     {
192         // Return max. length of string representation of Source;
193         // 0 if unlimited (with exceptions for some types, see below).
194         // Values with limited string representation are placed to
195         // the buffer locally defined in lexical_cast function.
196         // 1 is returned for few types such as CharT const* or
197         // std::basic_string<CharT> that already have an internal
198         // buffer ready to be reused by lexical_stream_limited_src.
199         // Each specialization should have a correspondent operator<<
200         // defined in lexical_stream_limited_src.
201         template< class CharT  // A result of widest_char transformation.
202                 , class Source // Source type of lexical_cast.
203                 >
204         struct lcast_src_length
205         {
206             BOOST_STATIC_CONSTANT(std::size_t, value = 0);
207             // To check coverage, build the test with
208             // bjam --v2 profile optimization=off
209             static void check_coverage() {}
210         };
211
212         template<>
213         struct lcast_src_length<char, bool>
214         {
215             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
216             static void check_coverage() {}
217         };
218
219         template<>
220         struct lcast_src_length<char, char>
221         {
222             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
223             static void check_coverage() {}
224         };
225
226         // No specializations for:
227         // lcast_src_length<char, signed char>
228         // lcast_src_length<char, unsigned char>
229         // lcast_src_length<char, signed char*>
230         // lcast_src_length<char, unsigned char*>
231         // lcast_src_length<char, signed char const*>
232         // lcast_src_length<char, unsigned char const*>
233
234 #ifndef BOOST_LCAST_NO_WCHAR_T
235         template<>
236         struct lcast_src_length<wchar_t, bool>
237         {
238             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
239             static void check_coverage() {}
240         };
241
242         template<>
243         struct lcast_src_length<wchar_t, char>
244         {
245             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
246             static void check_coverage() {}
247         };
248
249 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
250         template<>
251         struct lcast_src_length<wchar_t, wchar_t>
252         {
253             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
254             static void check_coverage() {}
255         };
256 #endif
257 #endif
258
259         template<>
260         struct lcast_src_length<char, char const*>
261         {
262             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
263             static void check_coverage() {}
264         };
265
266         template<>
267         struct lcast_src_length<char, char*>
268         {
269             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
270             static void check_coverage() {}
271         };
272
273 #ifndef BOOST_LCAST_NO_WCHAR_T
274         template<>
275         struct lcast_src_length<wchar_t, wchar_t const*>
276         {
277             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
278             static void check_coverage() {}
279         };
280
281         template<>
282         struct lcast_src_length<wchar_t, wchar_t*>
283         {
284             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
285             static void check_coverage() {}
286         };
287 #endif
288
289 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
290         template<class CharT, class Traits, class Alloc>
291         struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
292         {
293             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
294             static void check_coverage() {}
295         };
296 #else
297         template<>
298         struct lcast_src_length< char, std::basic_string<char> >
299         {
300             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
301             static void check_coverage() {}
302         };
303
304 #ifndef BOOST_LCAST_NO_WCHAR_T
305         template<>
306         struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
307         {
308             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
309             static void check_coverage() {}
310         };
311 #endif
312 #endif
313
314         // Helper for integral types.
315         // Notes on length calculation:
316         // Max length for 32bit int with grouping "\1" and thousands_sep ',':
317         // "-2,1,4,7,4,8,3,6,4,7"
318         //  ^                    - is_signed
319         //   ^                   - 1 digit not counted by digits10
320         //    ^^^^^^^^^^^^^^^^^^ - digits10 * 2
321         //
322         // Constant is_specialized is used instead of constant 1
323         // to prevent buffer overflow in a rare case when
324         // <boost/limits.hpp> doesn't add missing specialization for
325         // numeric_limits<T> for some integral type T.
326         // When is_specialized is false, the whole expression is 0.
327         template<class Source>
328         struct lcast_src_length_integral
329         {
330 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
331             BOOST_STATIC_CONSTANT(std::size_t, value =
332                   std::numeric_limits<Source>::is_signed +
333                   std::numeric_limits<Source>::is_specialized + // == 1
334                   std::numeric_limits<Source>::digits10 * 2
335               );
336 #else
337             BOOST_STATIC_CONSTANT(std::size_t, value = 156);
338             BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
339 #endif
340         };
341
342 #define BOOST_LCAST_DEF1(CharT, T)               \
343     template<> struct lcast_src_length<CharT, T> \
344         : lcast_src_length_integral<T>           \
345     { static void check_coverage() {} };
346
347 #ifdef BOOST_LCAST_NO_WCHAR_T
348 #define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T)
349 #else
350 #define BOOST_LCAST_DEF(T)          \
351         BOOST_LCAST_DEF1(char, T)   \
352         BOOST_LCAST_DEF1(wchar_t, T)
353 #endif
354
355         BOOST_LCAST_DEF(short)
356         BOOST_LCAST_DEF(unsigned short)
357         BOOST_LCAST_DEF(int)
358         BOOST_LCAST_DEF(unsigned int)
359         BOOST_LCAST_DEF(long)
360         BOOST_LCAST_DEF(unsigned long)
361 #if defined(BOOST_HAS_LONG_LONG)
362         BOOST_LCAST_DEF(boost::ulong_long_type)
363         BOOST_LCAST_DEF(boost::long_long_type )
364 #elif defined(BOOST_HAS_MS_INT64)
365         BOOST_LCAST_DEF(unsigned __int64)
366         BOOST_LCAST_DEF(         __int64)
367 #endif
368
369 #undef BOOST_LCAST_DEF
370 #undef BOOST_LCAST_DEF1
371
372 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
373         // Helper for floating point types.
374         // -1.23456789e-123456
375         // ^                   sign
376         //  ^                  leading digit
377         //   ^                 decimal point 
378         //    ^^^^^^^^         lcast_precision<Source>::value
379         //            ^        "e"
380         //             ^       exponent sign
381         //              ^^^^^^ exponent (assumed 6 or less digits)
382         // sign + leading digit + decimal point + "e" + exponent sign == 5
383         template<class Source>
384         struct lcast_src_length_floating
385         {
386             BOOST_STATIC_ASSERT(
387                     std::numeric_limits<Source>::max_exponent10 <=  999999L &&
388                     std::numeric_limits<Source>::min_exponent10 >= -999999L
389                 );
390             BOOST_STATIC_CONSTANT(std::size_t, value =
391                     5 + lcast_precision<Source>::value + 6
392                 );
393         };
394
395         template<>
396         struct lcast_src_length<char,float>
397           : lcast_src_length_floating<float>
398         {
399             static void check_coverage() {}
400         };
401
402         template<>
403         struct lcast_src_length<char,double>
404           : lcast_src_length_floating<double>
405         {
406             static void check_coverage() {}
407         };
408
409         template<>
410         struct lcast_src_length<char,long double>
411           : lcast_src_length_floating<long double>
412         {
413             static void check_coverage() {}
414         };
415
416 #ifndef BOOST_LCAST_NO_WCHAR_T
417     template<>
418     struct lcast_src_length<wchar_t,float>
419       : lcast_src_length_floating<float>
420     {
421         static void check_coverage() {}
422     };
423
424     template<>
425     struct lcast_src_length<wchar_t,double>
426       : lcast_src_length_floating<double>
427     {
428         static void check_coverage() {}
429     };
430
431     template<>
432     struct lcast_src_length<wchar_t,long double>
433       : lcast_src_length_floating<long double>
434     {
435         static void check_coverage() {}
436     };
437
438 #endif // #ifndef BOOST_LCAST_NO_WCHAR_T
439 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
440     }
441
442     namespace detail // '0' and '-' constants
443     {
444         template<typename CharT> struct lcast_char_constants;
445
446         template<>
447         struct lcast_char_constants<char>
448         {
449             BOOST_STATIC_CONSTANT(char, zero  = '0');
450             BOOST_STATIC_CONSTANT(char, minus = '-');
451         };
452
453 #ifndef BOOST_LCAST_NO_WCHAR_T
454         template<>
455         struct lcast_char_constants<wchar_t>
456         {
457             BOOST_STATIC_CONSTANT(wchar_t, zero  = L'0');
458             BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
459         };
460 #endif
461     }
462
463     namespace detail // lexical_streambuf_fake
464     {
465         struct lexical_streambuf_fake
466         {
467         };
468     }
469
470     namespace detail // lcast_to_unsigned
471     {
472 #if (defined _MSC_VER)
473 # pragma warning( push )
474 // C4146: unary minus operator applied to unsigned type, result still unsigned
475 # pragma warning( disable : 4146 )
476 #elif defined( __BORLANDC__ )
477 # pragma option push -w-8041
478 #endif
479         template<class T>
480         inline
481         BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
482         {
483             typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
484             result_type uvalue = static_cast<result_type>(value);
485             return value < 0 ? -uvalue : uvalue;
486         }
487 #if (defined _MSC_VER)
488 # pragma warning( pop )
489 #elif defined( __BORLANDC__ )
490 # pragma option pop
491 #endif
492     }
493
494     namespace detail // lcast_put_unsigned
495     {
496         template<class Traits, class T, class CharT>
497         CharT* lcast_put_unsigned(T n, CharT* finish)
498         {
499 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
500             BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
501 #endif
502
503 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
504             // TODO: use BOOST_NO_STD_LOCALE
505             std::locale loc;
506             typedef std::numpunct<CharT> numpunct;
507             numpunct const& np = BOOST_USE_FACET(numpunct, loc);
508             std::string const& grouping = np.grouping();
509             std::string::size_type const grouping_size = grouping.size();
510             CharT thousands_sep = grouping_size ? np.thousands_sep() : 0;
511             std::string::size_type group = 0; // current group number
512             char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0];
513             // a) Since grouping is const, grouping[grouping.size()] returns 0.
514             // b) It's safe to assume here and below that CHAR_MAX
515             //    is equivalent to unlimited grouping:
516 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
517             BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
518 #endif
519
520             char left = last_grp_size;
521 #endif
522
523             typedef typename Traits::int_type int_type;
524             CharT const czero = lcast_char_constants<CharT>::zero;
525             int_type const zero = Traits::to_int_type(czero);
526
527             do
528             {
529 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
530                 if(left == 0)
531                 {
532                     ++group;
533                     if(group < grouping_size)
534                     {
535                         char const grp_size = grouping[group];
536                         last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
537                     }
538
539                     left = last_grp_size;
540                     --finish;
541                     Traits::assign(*finish, thousands_sep);
542                 }
543
544                 --left;
545 #endif
546
547                 --finish;
548                 int_type const digit = static_cast<int_type>(n % 10U);
549                 Traits::assign(*finish, Traits::to_char_type(zero + digit));
550                 n /= 10;
551             } while(n);
552
553             return finish;
554         }
555     }
556
557     namespace detail // stream wrapper for handling lexical conversions
558     {
559         template<typename Target, typename Source, typename Traits>
560         class lexical_stream
561         {
562         private:
563             typedef typename widest_char<
564                 typename stream_char<Target>::type,
565                 typename stream_char<Source>::type>::type char_type;
566
567             typedef Traits traits_type;
568
569         public:
570             lexical_stream(char_type* = 0, char_type* = 0)
571             {
572                 stream.unsetf(std::ios::skipws);
573                 lcast_set_precision(stream, (Source*)0, (Target*)0);
574             }
575             ~lexical_stream()
576             {
577                 #if defined(BOOST_NO_STRINGSTREAM)
578                 stream.freeze(false);
579                 #endif
580             }
581             bool operator<<(const Source &input)
582             {
583                 return !(stream << input).fail();
584             }
585             template<typename InputStreamable>
586             bool operator>>(InputStreamable &output)
587             {
588                 return !is_pointer<InputStreamable>::value &&
589                        stream >> output &&
590                        stream.get() ==
591 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
592 // GCC 2.9x lacks std::char_traits<>::eof().
593 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
594 // configurations, which do provide std::char_traits<>::eof().
595     
596                            EOF;
597 #else
598                            traits_type::eof();
599 #endif
600             }
601
602 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
603
604             bool operator>>(std::string &output)
605             {
606                 #if defined(BOOST_NO_STRINGSTREAM)
607                 stream << '\0';
608                 #endif
609                 stream.str().swap(output);
610                 return true;
611             }
612             #ifndef BOOST_LCAST_NO_WCHAR_T
613             bool operator>>(std::wstring &output)
614             {
615                 stream.str().swap(output);
616                 return true;
617             }
618             #endif
619
620 #else
621             bool operator>>(std::basic_string<char_type,traits_type>& output)
622             {
623                 stream.str().swap(output);
624                 return true;
625             }
626
627             template<class Alloc>
628             bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out)
629             {
630                 std::basic_string<char_type,traits_type> str(stream.str());
631                 out.assign(str.begin(), str.end());
632                 return true;
633             }
634 #endif
635         private:
636             #if defined(BOOST_NO_STRINGSTREAM)
637             std::strstream stream;
638             #elif defined(BOOST_NO_STD_LOCALE)
639             std::stringstream stream;
640             #else
641             std::basic_stringstream<char_type,traits_type> stream;
642             #endif
643         };
644     }
645
646     namespace detail // optimized stream wrapper
647     {
648         // String representation of Source has an upper limit.
649         template< class CharT // a result of widest_char transformation
650                 , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
651                 , class Traits // usually char_traits<CharT>
652                 >
653         class lexical_stream_limited_src : public Base
654         {
655             // A string representation of Source is written to [start, finish).
656             // Currently, it is assumed that [start, finish) is big enough
657             // to hold a string representation of any Source value.
658             CharT* start;
659             CharT* finish;
660
661         private:
662
663             static void widen_and_assign(char*p, char ch)
664             {
665                 Traits::assign(*p, ch);
666             }
667
668 #ifndef BOOST_LCAST_NO_WCHAR_T
669             static void widen_and_assign(wchar_t* p, char ch)
670             {
671                 // TODO: use BOOST_NO_STD_LOCALE
672                 std::locale loc;
673                 wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
674                 Traits::assign(*p, w);
675             }
676
677             static void widen_and_assign(wchar_t* p, wchar_t ch)
678             {
679                 Traits::assign(*p, ch);
680             }
681
682             static void widen_and_assign(char*, wchar_t ch); // undefined
683 #endif
684
685             template<class OutputStreamable>
686             bool lcast_put(const OutputStreamable& input)
687             {
688                 this->setp(start, finish);
689                 std::basic_ostream<CharT> stream(static_cast<Base*>(this));
690                 lcast_set_precision(stream, (OutputStreamable*)0);
691                 bool const result = !(stream << input).fail();
692                 finish = this->pptr();
693                 return result;
694             }
695
696             // Undefined:
697             lexical_stream_limited_src(lexical_stream_limited_src const&);
698             void operator=(lexical_stream_limited_src const&);
699
700         public:
701
702             lexical_stream_limited_src(CharT* sta, CharT* fin)
703               : start(sta)
704               , finish(fin)
705             {}
706
707         public: // output
708
709             template<class Alloc>
710             bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
711             {
712                 start = const_cast<CharT*>(str.data());
713                 finish = start + str.length();
714                 return true;
715             }
716
717             bool operator<<(bool);
718             bool operator<<(char);
719 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
720             bool operator<<(wchar_t);
721 #endif
722             bool operator<<(CharT const*);
723             bool operator<<(short);
724             bool operator<<(int);
725             bool operator<<(long);
726             bool operator<<(unsigned short);
727             bool operator<<(unsigned int);
728             bool operator<<(unsigned long);
729 #if defined(BOOST_HAS_LONG_LONG)
730             bool operator<<(boost::ulong_long_type);
731             bool operator<<(boost::long_long_type );
732 #elif defined(BOOST_HAS_MS_INT64)
733             bool operator<<(unsigned __int64);
734             bool operator<<(         __int64);
735 #endif
736             // These three operators use ostream and streambuf.
737             // lcast_streambuf_for_source<T>::value is true.
738             bool operator<<(float);
739             bool operator<<(double);
740             bool operator<<(long double);
741
742         public: // input
743
744             // Generic istream-based algorithm.
745             // lcast_streambuf_for_target<InputStreamable>::value is true.
746             template<typename InputStreamable>
747             bool operator>>(InputStreamable& output)
748             {
749 #if (defined _MSC_VER)
750 # pragma warning( push )
751   // conditional expression is constant
752 # pragma warning( disable : 4127 )
753 #endif
754                 if(is_pointer<InputStreamable>::value)
755                     return false;
756
757                 this->setg(start, start, finish);
758                 std::basic_istream<CharT> stream(static_cast<Base*>(this));
759                 stream.unsetf(std::ios::skipws);
760                 lcast_set_precision(stream, (InputStreamable*)0);
761 #if (defined _MSC_VER)
762 # pragma warning( pop )
763 #endif
764                 return stream >> output &&
765                     stream.get() ==
766 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
767         // GCC 2.9x lacks std::char_traits<>::eof().
768         // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
769         // configurations, which do provide std::char_traits<>::eof().
770
771                     EOF;
772 #else
773                 Traits::eof();
774 #endif
775             }
776
777             bool operator>>(CharT&);
778
779 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
780 // This #if is in sync with lcast_streambuf_for_target
781
782             bool operator>>(std::string&);
783
784 #ifndef BOOST_LCAST_NO_WCHAR_T
785             bool operator>>(std::wstring&);
786 #endif
787
788 #else
789             template<class Alloc>
790             bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
791             {
792                 str.assign(start, finish);
793                 return true;
794             }
795 #endif
796         };
797
798         template<typename CharT, class Base, class Traits>
799         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
800                 bool value)
801         {
802             typedef typename Traits::int_type int_type;
803             CharT const czero = lcast_char_constants<CharT>::zero;
804             int_type const zero = Traits::to_int_type(czero);
805             Traits::assign(*start, Traits::to_char_type(zero + value));
806             finish = start + 1;
807             return true;
808         }
809
810         template<typename CharT, class Base, class Traits>
811         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
812                 char ch)
813         {
814             widen_and_assign(start, ch);
815             finish = start + 1;
816             return true;
817         }
818
819 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
820         template<typename CharT, class Base, class Traits>
821         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
822                 wchar_t ch)
823         {
824             widen_and_assign(start, ch);
825             finish = start + 1;
826             return true;
827         }
828 #endif
829
830         template<typename CharT, class Base, class Traits>
831         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
832                 short n)
833         {
834             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
835             if(n < 0)
836             {
837                 --start;
838                 CharT const minus = lcast_char_constants<CharT>::minus;
839                 Traits::assign(*start, minus);
840             }
841             return true;
842         }
843
844         template<typename CharT, class Base, class Traits>
845         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
846                 int n)
847         {
848             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
849             if(n < 0)
850             {
851                 --start;
852                 CharT const minus = lcast_char_constants<CharT>::minus;
853                 Traits::assign(*start, minus);
854             }
855             return true;
856         }
857
858         template<typename CharT, class Base, class Traits>
859         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
860                 long n)
861         {
862             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
863             if(n < 0)
864             {
865                 --start;
866                 CharT const minus = lcast_char_constants<CharT>::minus;
867                 Traits::assign(*start, minus);
868             }
869             return true;
870         }
871
872 #if defined(BOOST_HAS_LONG_LONG)
873         template<typename CharT, class Base, class Traits>
874         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
875                 boost::long_long_type n)
876         {
877             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
878             if(n < 0)
879             {
880                 --start;
881                 CharT const minus = lcast_char_constants<CharT>::minus;
882                 Traits::assign(*start, minus);
883             }
884             return true;
885         }
886 #elif defined(BOOST_HAS_MS_INT64)
887         template<typename CharT, class Base, class Traits>
888         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
889                 __int64 n)
890         {
891             start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
892             if(n < 0)
893             {
894                 --start;
895                 CharT const minus = lcast_char_constants<CharT>::minus;
896                 Traits::assign(*start, minus);
897             }
898             return true;
899         }
900 #endif
901
902         template<typename CharT, class Base, class Traits>
903         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
904                 unsigned short n)
905         {
906             start = lcast_put_unsigned<Traits>(n, finish);
907             return true;
908         }
909
910         template<typename CharT, class Base, class Traits>
911         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
912                 unsigned int n)
913         {
914             start = lcast_put_unsigned<Traits>(n, finish);
915             return true;
916         }
917
918         template<typename CharT, class Base, class Traits>
919         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
920                 unsigned long n)
921         {
922             start = lcast_put_unsigned<Traits>(n, finish);
923             return true;
924         }
925
926 #if defined(BOOST_HAS_LONG_LONG)
927         template<typename CharT, class Base, class Traits>
928         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
929                 boost::ulong_long_type n)
930         {
931             start = lcast_put_unsigned<Traits>(n, finish);
932             return true;
933         }
934 #elif defined(BOOST_HAS_MS_INT64)
935         template<typename CharT, class Base, class Traits>
936         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
937                 unsigned __int64 n)
938         {
939             start = lcast_put_unsigned<Traits>(n, finish);
940             return true;
941         }
942 #endif
943
944         template<typename CharT, class Base, class Traits>
945         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
946                 float val)
947         {
948             return this->lcast_put(val);
949         }
950
951         template<typename CharT, class Base, class Traits>
952         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
953                 double val)
954         {
955             return this->lcast_put(val);
956         }
957
958         template<typename CharT, class Base, class Traits>
959         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
960                 long double val)
961         {
962             return this->lcast_put(val);
963         }
964
965         template<typename CharT, class Base, class Traits>
966         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
967                 CharT const* str)
968         {
969             start = const_cast<CharT*>(str);
970             finish = start + Traits::length(str);
971             return true;
972         }
973
974         template<typename CharT, class Base, class Traits>
975         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
976                 CharT& output)
977         {
978             bool const ok = (finish - start == 1);
979             if(ok)
980                 Traits::assign(output, *start);
981             return ok;
982         }
983
984 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
985         template<typename CharT, class Base, class Traits>
986         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
987                 std::string& str)
988         {
989             str.assign(start, finish);
990             return true;
991         }
992
993 #ifndef BOOST_LCAST_NO_WCHAR_T
994         template<typename CharT, class Base, class Traits>
995         inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
996                 std::wstring& str)
997         {
998             str.assign(start, finish);
999             return true;
1000         }
1001 #endif
1002 #endif
1003     }
1004
1005     namespace detail // lcast_streambuf_for_source
1006     {
1007         // Returns true if optimized stream wrapper needs ostream for writing.
1008         template<class Source>
1009         struct lcast_streambuf_for_source
1010         {
1011             BOOST_STATIC_CONSTANT(bool, value = false);
1012         };
1013
1014         template<>
1015         struct lcast_streambuf_for_source<float>
1016         {
1017             BOOST_STATIC_CONSTANT(bool, value = true);
1018         };
1019  
1020         template<>
1021         struct lcast_streambuf_for_source<double>
1022         {
1023             BOOST_STATIC_CONSTANT(bool, value = true);
1024         };
1025   
1026         template<>
1027         struct lcast_streambuf_for_source<long double>
1028         {
1029             BOOST_STATIC_CONSTANT(bool, value = true);
1030         };
1031     }
1032
1033     namespace detail // lcast_streambuf_for_target
1034     {
1035         // Returns true if optimized stream wrapper needs istream for reading.
1036         template<class Target>
1037         struct lcast_streambuf_for_target
1038         {
1039             BOOST_STATIC_CONSTANT(bool, value = true);
1040         };
1041
1042         template<>
1043         struct lcast_streambuf_for_target<char>
1044         {
1045             BOOST_STATIC_CONSTANT(bool, value = false);
1046         };
1047
1048 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1049         template<>
1050         struct lcast_streambuf_for_target<wchar_t>
1051         {
1052             BOOST_STATIC_CONSTANT(bool, value = false);
1053         };
1054 #endif
1055
1056 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1057         template<class Traits, class Alloc>
1058         struct lcast_streambuf_for_target<
1059                     std::basic_string<char,Traits,Alloc> >
1060         {
1061             BOOST_STATIC_CONSTANT(bool, value = false);
1062         };
1063
1064 #ifndef BOOST_LCAST_NO_WCHAR_T
1065         template<class Traits, class Alloc>
1066         struct lcast_streambuf_for_target<
1067                     std::basic_string<wchar_t,Traits,Alloc> >
1068         {
1069             BOOST_STATIC_CONSTANT(bool, value = false);
1070         };
1071 #endif
1072 #else
1073         template<>
1074         struct lcast_streambuf_for_target<std::string>
1075         {
1076             BOOST_STATIC_CONSTANT(bool, value = false);
1077         };
1078
1079 #ifndef BOOST_LCAST_NO_WCHAR_T
1080         template<>
1081         struct lcast_streambuf_for_target<std::wstring>
1082         {
1083             BOOST_STATIC_CONSTANT(bool, value = false);
1084         };
1085 #endif
1086 #endif
1087     }
1088
1089     #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1090
1091     // call-by-const reference version
1092
1093     namespace detail
1094     {
1095         template<class T>
1096         struct array_to_pointer_decay
1097         {
1098             typedef T type;
1099         };
1100
1101         template<class T, std::size_t N>
1102         struct array_to_pointer_decay<T[N]>
1103         {
1104             typedef const T * type;
1105         };
1106
1107         template< typename Target
1108                 , typename Source
1109                 , bool Unlimited // string representation of Source is unlimited
1110                 , typename CharT
1111                 >
1112         Target lexical_cast(
1113             BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
1114             CharT* buf, std::size_t src_len)
1115         {
1116             typedef BOOST_DEDUCED_TYPENAME
1117                 deduce_char_traits<CharT,Target,Source>::type traits;
1118
1119             typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1120                 lcast_streambuf_for_target<Target>::value ||
1121                 lcast_streambuf_for_source<Source>::value
1122               , std::basic_streambuf<CharT>
1123               , lexical_streambuf_fake
1124               >::type base;
1125
1126             BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1127                 Unlimited
1128               , detail::lexical_stream<Target,Source,traits>
1129               , detail::lexical_stream_limited_src<CharT,base,traits>
1130               >::type interpreter(buf, buf + src_len);
1131
1132             // The original form, reproduced below, is more elegant
1133             // but yields a spurious C4701 warning ("possible use of
1134             // "result" before initialization") with VC7.1 (/W4).
1135 //
1136 //            Target result;
1137 //
1138 //            if(!(interpreter << arg && interpreter >> result))
1139 //                throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1140 //            return result;
1141
1142             if(interpreter << arg) {
1143                 Target result;
1144                 if (interpreter >> result)
1145                     return result;
1146             }
1147             throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1148             return Target(); // normally never reached (throw_exception)
1149         }
1150     }
1151
1152     template<typename Target, typename Source>
1153     inline Target lexical_cast(const Source &arg)
1154     {
1155         typedef typename detail::array_to_pointer_decay<Source>::type src;
1156
1157         typedef typename detail::widest_char<
1158             typename detail::stream_char<Target>::type
1159           , typename detail::stream_char<src>::type
1160           >::type char_type;
1161
1162         typedef detail::lcast_src_length<char_type, src> lcast_src_length;
1163         std::size_t const src_len = lcast_src_length::value;
1164         char_type buf[src_len + 1];
1165         lcast_src_length::check_coverage();
1166         return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
1167     }
1168
1169     #else
1170
1171     // call-by-value fallback version (deprecated)
1172
1173     template<typename Target, typename Source>
1174     Target lexical_cast(Source arg)
1175     {
1176         typedef typename detail::widest_char< 
1177             BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type 
1178           , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type 
1179         >::type char_type; 
1180
1181         typedef std::char_traits<char_type> traits;
1182         detail::lexical_stream<Target, Source, traits> interpreter;
1183         Target result;
1184
1185         if(!(interpreter << arg && interpreter >> result))
1186             throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1187         return result;
1188     }
1189
1190     #endif
1191 }
1192
1193 // Copyright Kevlin Henney, 2000-2005.
1194 // Copyright Alexander Nasonov, 2006-2007.
1195 //
1196 // Distributed under the Boost Software License, Version 1.0. (See
1197 // accompanying file LICENSE_1_0.txt or copy at
1198 // http://www.boost.org/LICENSE_1_0.txt)
1199
1200 #undef BOOST_LCAST_NO_WCHAR_T
1201 #endif