fix doc example typo
[boost.git] / boost / lexical_cast.hpp
blob0da0d3ded8e3b7820878565f4607a3e61f05d3fd
1 #ifndef BOOST_LEXICAL_CAST_INCLUDED
2 #define BOOST_LEXICAL_CAST_INCLUDED
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
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>
34 #ifndef BOOST_NO_STD_LOCALE
35 #include <locale>
36 #endif
38 #ifdef BOOST_NO_STRINGSTREAM
39 #include <strstream>
40 #else
41 #include <sstream>
42 #endif
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
50 namespace boost
52 // exception used to indicate runtime lexical_cast failure
53 class bad_lexical_cast : public std::bad_cast
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
61 public:
62 bad_lexical_cast() :
63 #ifndef BOOST_NO_TYPEID
64 source(&typeid(void)), target(&typeid(void))
65 #else
66 source(0), target(0) // this breaks getters
67 #endif
71 bad_lexical_cast(
72 const std::type_info &source_type_arg,
73 const std::type_info &target_type_arg) :
74 source(&source_type_arg), target(&target_type_arg)
78 const std::type_info &source_type() const
80 return *source;
82 const std::type_info &target_type() const
84 return *target;
87 virtual const char *what() const throw()
89 return "bad lexical cast: "
90 "source type value could not be interpreted as target";
92 virtual ~bad_lexical_cast() throw()
95 private:
96 const std::type_info *source;
97 const std::type_info *target;
100 namespace detail // selectors for choosing stream character type
102 template<typename Type>
103 struct stream_char
105 typedef char type;
108 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
109 template<class CharT, class Traits, class Alloc>
110 struct stream_char< std::basic_string<CharT,Traits,Alloc> >
112 typedef CharT type;
114 #endif
116 #ifndef BOOST_LCAST_NO_WCHAR_T
117 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
118 template<>
119 struct stream_char<wchar_t>
121 typedef wchar_t type;
123 #endif
125 template<>
126 struct stream_char<wchar_t *>
128 typedef wchar_t type;
131 template<>
132 struct stream_char<const wchar_t *>
134 typedef wchar_t type;
137 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
138 template<>
139 struct stream_char<std::wstring>
141 typedef wchar_t type;
143 #endif
144 #endif
146 template<typename TargetChar, typename SourceChar>
147 struct widest_char
149 typedef TargetChar type;
152 template<>
153 struct widest_char<char, wchar_t>
155 typedef wchar_t type;
159 namespace detail // deduce_char_traits template
161 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
162 template<class CharT, class Target, class Source>
163 struct deduce_char_traits
165 typedef std::char_traits<CharT> type;
168 template<class CharT, class Traits, class Alloc, class Source>
169 struct deduce_char_traits< CharT
170 , std::basic_string<CharT,Traits,Alloc>
171 , Source
174 typedef Traits type;
177 template<class CharT, class Target, class Traits, class Alloc>
178 struct deduce_char_traits< CharT
179 , Target
180 , std::basic_string<CharT,Traits,Alloc>
183 typedef Traits type;
186 template<class CharT, class Traits, class Alloc1, class Alloc2>
187 struct deduce_char_traits< CharT
188 , std::basic_string<CharT,Traits,Alloc1>
189 , std::basic_string<CharT,Traits,Alloc2>
192 typedef Traits type;
194 #endif
197 namespace detail // lcast_src_length
199 // Return max. length of string representation of Source;
200 // 0 if unlimited (with exceptions for some types, see below).
201 // Values with limited string representation are placed to
202 // the buffer locally defined in lexical_cast function.
203 // 1 is returned for few types such as CharT const* or
204 // std::basic_string<CharT> that already have an internal
205 // buffer ready to be reused by lexical_stream_limited_src.
206 // Each specialization should have a correspondent operator<<
207 // defined in lexical_stream_limited_src.
208 template< class CharT // A result of widest_char transformation.
209 , class Source // Source type of lexical_cast.
211 struct lcast_src_length
213 BOOST_STATIC_CONSTANT(std::size_t, value = 0);
214 // To check coverage, build the test with
215 // bjam --v2 profile optimization=off
216 static void check_coverage() {}
219 template<>
220 struct lcast_src_length<char, bool>
222 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
223 static void check_coverage() {}
226 template<>
227 struct lcast_src_length<char, char>
229 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
230 static void check_coverage() {}
233 // No specializations for:
234 // lcast_src_length<char, signed char>
235 // lcast_src_length<char, unsigned char>
236 // lcast_src_length<char, signed char*>
237 // lcast_src_length<char, unsigned char*>
238 // lcast_src_length<char, signed char const*>
239 // lcast_src_length<char, unsigned char const*>
241 #ifndef BOOST_LCAST_NO_WCHAR_T
242 template<>
243 struct lcast_src_length<wchar_t, bool>
245 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
246 static void check_coverage() {}
249 template<>
250 struct lcast_src_length<wchar_t, char>
252 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
253 static void check_coverage() {}
256 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
257 template<>
258 struct lcast_src_length<wchar_t, wchar_t>
260 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
261 static void check_coverage() {}
263 #endif
264 #endif
266 template<>
267 struct lcast_src_length<char, char const*>
269 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
270 static void check_coverage() {}
273 template<>
274 struct lcast_src_length<char, char*>
276 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
277 static void check_coverage() {}
280 #ifndef BOOST_LCAST_NO_WCHAR_T
281 template<>
282 struct lcast_src_length<wchar_t, wchar_t const*>
284 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
285 static void check_coverage() {}
288 template<>
289 struct lcast_src_length<wchar_t, wchar_t*>
291 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
292 static void check_coverage() {}
294 #endif
296 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
297 template<class CharT, class Traits, class Alloc>
298 struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
300 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
301 static void check_coverage() {}
303 #else
304 template<>
305 struct lcast_src_length< char, std::basic_string<char> >
307 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
308 static void check_coverage() {}
311 #ifndef BOOST_LCAST_NO_WCHAR_T
312 template<>
313 struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
315 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
316 static void check_coverage() {}
318 #endif
319 #endif
321 // Helper for integral types.
322 // Notes on length calculation:
323 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
324 // "-2,1,4,7,4,8,3,6,4,7"
325 // ^ - is_signed
326 // ^ - 1 digit not counted by digits10
327 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
329 // Constant is_specialized is used instead of constant 1
330 // to prevent buffer overflow in a rare case when
331 // <boost/limits.hpp> doesn't add missing specialization for
332 // numeric_limits<T> for some integral type T.
333 // When is_specialized is false, the whole expression is 0.
334 template<class Source>
335 struct lcast_src_length_integral
337 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
338 BOOST_STATIC_CONSTANT(std::size_t, value =
339 std::numeric_limits<Source>::is_signed +
340 std::numeric_limits<Source>::is_specialized + // == 1
341 std::numeric_limits<Source>::digits10 * 2
343 #else
344 BOOST_STATIC_CONSTANT(std::size_t, value = 156);
345 BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
346 #endif
349 #define BOOST_LCAST_DEF1(CharT, T) \
350 template<> struct lcast_src_length<CharT, T> \
351 : lcast_src_length_integral<T> \
352 { static void check_coverage() {} };
354 #ifdef BOOST_LCAST_NO_WCHAR_T
355 #define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T)
356 #else
357 #define BOOST_LCAST_DEF(T) \
358 BOOST_LCAST_DEF1(char, T) \
359 BOOST_LCAST_DEF1(wchar_t, T)
360 #endif
362 BOOST_LCAST_DEF(short)
363 BOOST_LCAST_DEF(unsigned short)
364 BOOST_LCAST_DEF(int)
365 BOOST_LCAST_DEF(unsigned int)
366 BOOST_LCAST_DEF(long)
367 BOOST_LCAST_DEF(unsigned long)
368 #if defined(BOOST_HAS_LONG_LONG)
369 BOOST_LCAST_DEF(boost::ulong_long_type)
370 BOOST_LCAST_DEF(boost::long_long_type )
371 #elif defined(BOOST_HAS_MS_INT64)
372 BOOST_LCAST_DEF(unsigned __int64)
373 BOOST_LCAST_DEF( __int64)
374 #endif
376 #undef BOOST_LCAST_DEF
377 #undef BOOST_LCAST_DEF1
379 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
380 // Helper for floating point types.
381 // -1.23456789e-123456
382 // ^ sign
383 // ^ leading digit
384 // ^ decimal point
385 // ^^^^^^^^ lcast_precision<Source>::value
386 // ^ "e"
387 // ^ exponent sign
388 // ^^^^^^ exponent (assumed 6 or less digits)
389 // sign + leading digit + decimal point + "e" + exponent sign == 5
390 template<class Source>
391 struct lcast_src_length_floating
393 BOOST_STATIC_ASSERT(
394 std::numeric_limits<Source>::max_exponent10 <= 999999L &&
395 std::numeric_limits<Source>::min_exponent10 >= -999999L
397 BOOST_STATIC_CONSTANT(std::size_t, value =
398 5 + lcast_precision<Source>::value + 6
402 template<>
403 struct lcast_src_length<char,float>
404 : lcast_src_length_floating<float>
406 static void check_coverage() {}
409 template<>
410 struct lcast_src_length<char,double>
411 : lcast_src_length_floating<double>
413 static void check_coverage() {}
416 template<>
417 struct lcast_src_length<char,long double>
418 : lcast_src_length_floating<long double>
420 static void check_coverage() {}
423 #ifndef BOOST_LCAST_NO_WCHAR_T
424 template<>
425 struct lcast_src_length<wchar_t,float>
426 : lcast_src_length_floating<float>
428 static void check_coverage() {}
431 template<>
432 struct lcast_src_length<wchar_t,double>
433 : lcast_src_length_floating<double>
435 static void check_coverage() {}
438 template<>
439 struct lcast_src_length<wchar_t,long double>
440 : lcast_src_length_floating<long double>
442 static void check_coverage() {}
445 #endif // #ifndef BOOST_LCAST_NO_WCHAR_T
446 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
449 namespace detail // '0' and '-' constants
451 template<typename CharT> struct lcast_char_constants;
453 template<>
454 struct lcast_char_constants<char>
456 BOOST_STATIC_CONSTANT(char, zero = '0');
457 BOOST_STATIC_CONSTANT(char, minus = '-');
460 #ifndef BOOST_LCAST_NO_WCHAR_T
461 template<>
462 struct lcast_char_constants<wchar_t>
464 BOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
465 BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
467 #endif
470 namespace detail // lexical_streambuf_fake
472 struct lexical_streambuf_fake
477 namespace detail // lcast_to_unsigned
479 #if (defined _MSC_VER)
480 # pragma warning( push )
481 // C4146: unary minus operator applied to unsigned type, result still unsigned
482 # pragma warning( disable : 4146 )
483 #elif defined( __BORLANDC__ )
484 # pragma option push -w-8041
485 #endif
486 template<class T>
487 inline
488 BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
490 typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
491 result_type uvalue = static_cast<result_type>(value);
492 return value < 0 ? -uvalue : uvalue;
494 #if (defined _MSC_VER)
495 # pragma warning( pop )
496 #elif defined( __BORLANDC__ )
497 # pragma option pop
498 #endif
501 namespace detail // lcast_put_unsigned
503 template<class Traits, class T, class CharT>
504 CharT* lcast_put_unsigned(T n, CharT* finish)
506 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
507 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
508 #endif
510 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
511 // TODO: use BOOST_NO_STD_LOCALE
512 std::locale loc;
513 typedef std::numpunct<CharT> numpunct;
514 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
515 std::string const& grouping = np.grouping();
516 std::string::size_type const grouping_size = grouping.size();
517 CharT thousands_sep = grouping_size ? np.thousands_sep() : 0;
518 std::string::size_type group = 0; // current group number
519 char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0];
520 // a) Since grouping is const, grouping[grouping.size()] returns 0.
521 // b) It's safe to assume here and below that CHAR_MAX
522 // is equivalent to unlimited grouping:
523 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
524 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
525 #endif
527 char left = last_grp_size;
528 #endif
530 typedef typename Traits::int_type int_type;
531 CharT const czero = lcast_char_constants<CharT>::zero;
532 int_type const zero = Traits::to_int_type(czero);
536 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
537 if(left == 0)
539 ++group;
540 if(group < grouping_size)
542 char const grp_size = grouping[group];
543 last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
546 left = last_grp_size;
547 --finish;
548 Traits::assign(*finish, thousands_sep);
551 --left;
552 #endif
554 --finish;
555 int_type const digit = static_cast<int_type>(n % 10U);
556 Traits::assign(*finish, Traits::to_char_type(zero + digit));
557 n /= 10;
558 } while(n);
560 return finish;
564 namespace detail // stream wrapper for handling lexical conversions
566 template<typename Target, typename Source, typename Traits>
567 class lexical_stream
569 private:
570 typedef typename widest_char<
571 typename stream_char<Target>::type,
572 typename stream_char<Source>::type>::type char_type;
574 typedef Traits traits_type;
576 public:
577 lexical_stream(char_type* = 0, char_type* = 0)
579 stream.unsetf(std::ios::skipws);
580 lcast_set_precision(stream, (Source*)0, (Target*)0);
582 ~lexical_stream()
584 #if defined(BOOST_NO_STRINGSTREAM)
585 stream.freeze(false);
586 #endif
588 bool operator<<(const Source &input)
590 return !(stream << input).fail();
592 template<typename InputStreamable>
593 bool operator>>(InputStreamable &output)
595 return !is_pointer<InputStreamable>::value &&
596 stream >> output &&
597 stream.get() ==
598 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
599 // GCC 2.9x lacks std::char_traits<>::eof().
600 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
601 // configurations, which do provide std::char_traits<>::eof().
603 EOF;
604 #else
605 traits_type::eof();
606 #endif
609 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
611 bool operator>>(std::string &output)
613 #if defined(BOOST_NO_STRINGSTREAM)
614 stream << '\0';
615 #endif
616 stream.str().swap(output);
617 return true;
619 #ifndef BOOST_LCAST_NO_WCHAR_T
620 bool operator>>(std::wstring &output)
622 stream.str().swap(output);
623 return true;
625 #endif
627 #else
628 bool operator>>(std::basic_string<char_type,traits_type>& output)
630 stream.str().swap(output);
631 return true;
634 template<class Alloc>
635 bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out)
637 std::basic_string<char_type,traits_type> str(stream.str());
638 out.assign(str.begin(), str.end());
639 return true;
641 #endif
642 private:
643 #if defined(BOOST_NO_STRINGSTREAM)
644 std::strstream stream;
645 #elif defined(BOOST_NO_STD_LOCALE)
646 std::stringstream stream;
647 #else
648 std::basic_stringstream<char_type,traits_type> stream;
649 #endif
653 namespace detail // optimized stream wrapper
655 // String representation of Source has an upper limit.
656 template< class CharT // a result of widest_char transformation
657 , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
658 , class Traits // usually char_traits<CharT>
660 class lexical_stream_limited_src : public Base
662 // A string representation of Source is written to [start, finish).
663 // Currently, it is assumed that [start, finish) is big enough
664 // to hold a string representation of any Source value.
665 CharT* start;
666 CharT* finish;
668 private:
670 static void widen_and_assign(char*p, char ch)
672 Traits::assign(*p, ch);
675 #ifndef BOOST_LCAST_NO_WCHAR_T
676 static void widen_and_assign(wchar_t* p, char ch)
678 // TODO: use BOOST_NO_STD_LOCALE
679 std::locale loc;
680 wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
681 Traits::assign(*p, w);
684 static void widen_and_assign(wchar_t* p, wchar_t ch)
686 Traits::assign(*p, ch);
689 static void widen_and_assign(char*, wchar_t ch); // undefined
690 #endif
692 template<class OutputStreamable>
693 bool lcast_put(const OutputStreamable& input)
695 this->setp(start, finish);
696 std::basic_ostream<CharT> stream(static_cast<Base*>(this));
697 lcast_set_precision(stream, (OutputStreamable*)0);
698 bool const result = !(stream << input).fail();
699 finish = this->pptr();
700 return result;
703 // Undefined:
704 lexical_stream_limited_src(lexical_stream_limited_src const&);
705 void operator=(lexical_stream_limited_src const&);
707 public:
709 lexical_stream_limited_src(CharT* sta, CharT* fin)
710 : start(sta)
711 , finish(fin)
714 public: // output
716 template<class Alloc>
717 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
719 start = const_cast<CharT*>(str.data());
720 finish = start + str.length();
721 return true;
724 bool operator<<(bool);
725 bool operator<<(char);
726 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
727 bool operator<<(wchar_t);
728 #endif
729 bool operator<<(CharT const*);
730 bool operator<<(short);
731 bool operator<<(int);
732 bool operator<<(long);
733 bool operator<<(unsigned short);
734 bool operator<<(unsigned int);
735 bool operator<<(unsigned long);
736 #if defined(BOOST_HAS_LONG_LONG)
737 bool operator<<(boost::ulong_long_type);
738 bool operator<<(boost::long_long_type );
739 #elif defined(BOOST_HAS_MS_INT64)
740 bool operator<<(unsigned __int64);
741 bool operator<<( __int64);
742 #endif
743 // These three operators use ostream and streambuf.
744 // lcast_streambuf_for_source<T>::value is true.
745 bool operator<<(float);
746 bool operator<<(double);
747 bool operator<<(long double);
749 public: // input
751 // Generic istream-based algorithm.
752 // lcast_streambuf_for_target<InputStreamable>::value is true.
753 template<typename InputStreamable>
754 bool operator>>(InputStreamable& output)
756 #if (defined _MSC_VER)
757 # pragma warning( push )
758 // conditional expression is constant
759 # pragma warning( disable : 4127 )
760 #endif
761 if(is_pointer<InputStreamable>::value)
762 return false;
764 this->setg(start, start, finish);
765 std::basic_istream<CharT> stream(static_cast<Base*>(this));
766 stream.unsetf(std::ios::skipws);
767 lcast_set_precision(stream, (InputStreamable*)0);
768 #if (defined _MSC_VER)
769 # pragma warning( pop )
770 #endif
771 return stream >> output &&
772 stream.get() ==
773 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
774 // GCC 2.9x lacks std::char_traits<>::eof().
775 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
776 // configurations, which do provide std::char_traits<>::eof().
778 EOF;
779 #else
780 Traits::eof();
781 #endif
784 bool operator>>(CharT&);
786 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
787 // This #if is in sync with lcast_streambuf_for_target
789 bool operator>>(std::string&);
791 #ifndef BOOST_LCAST_NO_WCHAR_T
792 bool operator>>(std::wstring&);
793 #endif
795 #else
796 template<class Alloc>
797 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
799 str.assign(start, finish);
800 return true;
802 #endif
805 template<typename CharT, class Base, class Traits>
806 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
807 bool value)
809 typedef typename Traits::int_type int_type;
810 CharT const czero = lcast_char_constants<CharT>::zero;
811 int_type const zero = Traits::to_int_type(czero);
812 Traits::assign(*start, Traits::to_char_type(zero + value));
813 finish = start + 1;
814 return true;
817 template<typename CharT, class Base, class Traits>
818 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
819 char ch)
821 widen_and_assign(start, ch);
822 finish = start + 1;
823 return true;
826 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
827 template<typename CharT, class Base, class Traits>
828 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
829 wchar_t ch)
831 widen_and_assign(start, ch);
832 finish = start + 1;
833 return true;
835 #endif
837 template<typename CharT, class Base, class Traits>
838 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
839 short n)
841 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
842 if(n < 0)
844 --start;
845 CharT const minus = lcast_char_constants<CharT>::minus;
846 Traits::assign(*start, minus);
848 return true;
851 template<typename CharT, class Base, class Traits>
852 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
853 int n)
855 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
856 if(n < 0)
858 --start;
859 CharT const minus = lcast_char_constants<CharT>::minus;
860 Traits::assign(*start, minus);
862 return true;
865 template<typename CharT, class Base, class Traits>
866 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
867 long n)
869 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
870 if(n < 0)
872 --start;
873 CharT const minus = lcast_char_constants<CharT>::minus;
874 Traits::assign(*start, minus);
876 return true;
879 #if defined(BOOST_HAS_LONG_LONG)
880 template<typename CharT, class Base, class Traits>
881 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
882 boost::long_long_type n)
884 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
885 if(n < 0)
887 --start;
888 CharT const minus = lcast_char_constants<CharT>::minus;
889 Traits::assign(*start, minus);
891 return true;
893 #elif defined(BOOST_HAS_MS_INT64)
894 template<typename CharT, class Base, class Traits>
895 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
896 __int64 n)
898 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
899 if(n < 0)
901 --start;
902 CharT const minus = lcast_char_constants<CharT>::minus;
903 Traits::assign(*start, minus);
905 return true;
907 #endif
909 template<typename CharT, class Base, class Traits>
910 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
911 unsigned short n)
913 start = lcast_put_unsigned<Traits>(n, finish);
914 return true;
917 template<typename CharT, class Base, class Traits>
918 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
919 unsigned int n)
921 start = lcast_put_unsigned<Traits>(n, finish);
922 return true;
925 template<typename CharT, class Base, class Traits>
926 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
927 unsigned long n)
929 start = lcast_put_unsigned<Traits>(n, finish);
930 return true;
933 #if defined(BOOST_HAS_LONG_LONG)
934 template<typename CharT, class Base, class Traits>
935 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
936 boost::ulong_long_type n)
938 start = lcast_put_unsigned<Traits>(n, finish);
939 return true;
941 #elif defined(BOOST_HAS_MS_INT64)
942 template<typename CharT, class Base, class Traits>
943 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
944 unsigned __int64 n)
946 start = lcast_put_unsigned<Traits>(n, finish);
947 return true;
949 #endif
951 template<typename CharT, class Base, class Traits>
952 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
953 float val)
955 return this->lcast_put(val);
958 template<typename CharT, class Base, class Traits>
959 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
960 double val)
962 return this->lcast_put(val);
965 template<typename CharT, class Base, class Traits>
966 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
967 long double val)
969 return this->lcast_put(val);
972 template<typename CharT, class Base, class Traits>
973 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
974 CharT const* str)
976 start = const_cast<CharT*>(str);
977 finish = start + Traits::length(str);
978 return true;
981 template<typename CharT, class Base, class Traits>
982 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
983 CharT& output)
985 bool const ok = (finish - start == 1);
986 if(ok)
987 Traits::assign(output, *start);
988 return ok;
991 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
992 template<typename CharT, class Base, class Traits>
993 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
994 std::string& str)
996 str.assign(start, finish);
997 return true;
1000 #ifndef BOOST_LCAST_NO_WCHAR_T
1001 template<typename CharT, class Base, class Traits>
1002 inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
1003 std::wstring& str)
1005 str.assign(start, finish);
1006 return true;
1008 #endif
1009 #endif
1012 namespace detail // lcast_streambuf_for_source
1014 // Returns true if optimized stream wrapper needs ostream for writing.
1015 template<class Source>
1016 struct lcast_streambuf_for_source
1018 BOOST_STATIC_CONSTANT(bool, value = false);
1021 template<>
1022 struct lcast_streambuf_for_source<float>
1024 BOOST_STATIC_CONSTANT(bool, value = true);
1027 template<>
1028 struct lcast_streambuf_for_source<double>
1030 BOOST_STATIC_CONSTANT(bool, value = true);
1033 template<>
1034 struct lcast_streambuf_for_source<long double>
1036 BOOST_STATIC_CONSTANT(bool, value = true);
1040 namespace detail // lcast_streambuf_for_target
1042 // Returns true if optimized stream wrapper needs istream for reading.
1043 template<class Target>
1044 struct lcast_streambuf_for_target
1046 BOOST_STATIC_CONSTANT(bool, value = true);
1049 template<>
1050 struct lcast_streambuf_for_target<char>
1052 BOOST_STATIC_CONSTANT(bool, value = false);
1055 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1056 template<>
1057 struct lcast_streambuf_for_target<wchar_t>
1059 BOOST_STATIC_CONSTANT(bool, value = false);
1061 #endif
1063 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1064 template<class Traits, class Alloc>
1065 struct lcast_streambuf_for_target<
1066 std::basic_string<char,Traits,Alloc> >
1068 BOOST_STATIC_CONSTANT(bool, value = false);
1071 #ifndef BOOST_LCAST_NO_WCHAR_T
1072 template<class Traits, class Alloc>
1073 struct lcast_streambuf_for_target<
1074 std::basic_string<wchar_t,Traits,Alloc> >
1076 BOOST_STATIC_CONSTANT(bool, value = false);
1078 #endif
1079 #else
1080 template<>
1081 struct lcast_streambuf_for_target<std::string>
1083 BOOST_STATIC_CONSTANT(bool, value = false);
1086 #ifndef BOOST_LCAST_NO_WCHAR_T
1087 template<>
1088 struct lcast_streambuf_for_target<std::wstring>
1090 BOOST_STATIC_CONSTANT(bool, value = false);
1092 #endif
1093 #endif
1096 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1098 // call-by-const reference version
1100 namespace detail
1102 template<class T>
1103 struct array_to_pointer_decay
1105 typedef T type;
1108 template<class T, std::size_t N>
1109 struct array_to_pointer_decay<T[N]>
1111 typedef const T * type;
1114 template< typename Target
1115 , typename Source
1116 , bool Unlimited // string representation of Source is unlimited
1117 , typename CharT
1119 Target lexical_cast(
1120 BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
1121 CharT* buf, std::size_t src_len)
1123 typedef BOOST_DEDUCED_TYPENAME
1124 deduce_char_traits<CharT,Target,Source>::type traits;
1126 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1127 lcast_streambuf_for_target<Target>::value ||
1128 lcast_streambuf_for_source<Source>::value
1129 , std::basic_streambuf<CharT>
1130 , lexical_streambuf_fake
1131 >::type base;
1133 BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
1134 Unlimited
1135 , detail::lexical_stream<Target,Source,traits>
1136 , detail::lexical_stream_limited_src<CharT,base,traits>
1137 >::type interpreter(buf, buf + src_len);
1139 // The original form, reproduced below, is more elegant
1140 // but yields a spurious C4701 warning ("possible use of
1141 // "result" before initialization") with VC7.1 (/W4).
1143 // Target result;
1145 // if(!(interpreter << arg && interpreter >> result))
1146 // throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1147 // return result;
1149 if(interpreter << arg) {
1150 Target result;
1151 if (interpreter >> result)
1152 return result;
1154 #ifndef BOOST_NO_TYPEID
1155 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1156 #else
1157 throw_exception(bad_lexical_cast());
1158 #endif
1159 return Target(); // normally never reached (throw_exception)
1163 template<typename Target, typename Source>
1164 inline Target lexical_cast(const Source &arg)
1166 typedef typename detail::array_to_pointer_decay<Source>::type src;
1168 typedef typename detail::widest_char<
1169 typename detail::stream_char<Target>::type
1170 , typename detail::stream_char<src>::type
1171 >::type char_type;
1173 typedef detail::lcast_src_length<char_type, src> lcast_src_length;
1174 std::size_t const src_len = lcast_src_length::value;
1175 char_type buf[src_len + 1];
1176 lcast_src_length::check_coverage();
1177 return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
1180 #else
1182 // call-by-value fallback version (deprecated)
1184 template<typename Target, typename Source>
1185 Target lexical_cast(Source arg)
1187 typedef typename detail::widest_char<
1188 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
1189 , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
1190 >::type char_type;
1192 typedef std::char_traits<char_type> traits;
1193 detail::lexical_stream<Target, Source, traits> interpreter;
1194 Target result;
1196 if(!(interpreter << arg && interpreter >> result))
1197 #ifndef BOOST_NO_TYPEID
1198 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
1199 #else
1200 throw_exception(bad_lexical_cast());
1201 #endif
1202 return result;
1205 #endif
1208 // Copyright Kevlin Henney, 2000-2005.
1209 // Copyright Alexander Nasonov, 2006-2007.
1211 // Distributed under the Boost Software License, Version 1.0. (See
1212 // accompanying file LICENSE_1_0.txt or copy at
1213 // http://www.boost.org/LICENSE_1_0.txt)
1215 #undef BOOST_LCAST_NO_WCHAR_T
1216 #endif