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