#ifndef BOOST_LEXICAL_CAST_INCLUDED #define BOOST_LEXICAL_CAST_INCLUDED // Boost lexical_cast.hpp eader -------------------------------------------// // // See http://www.boost.org/libs/conversion for documentation. // See end of this header for rights and permissions. // // what: lexical_cast custom keyword cast // who: contributed by Kevlin Henney, // enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, // Alexander Nasonov and other Boosters // when: November 2000, March 2003, June 2005, June 2006 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef BOOST_NO_STD_LOCALE #include #endif #ifdef BOOST_NO_STRINGSTREAM #include #else #include #endif #if defined(BOOST_NO_STRINGSTREAM) || \ defined(BOOST_NO_STD_WSTRING) || \ defined(BOOST_NO_STD_LOCALE) #define BOOST_LCAST_NO_WCHAR_T #endif namespace boost { // exception used to indicate runtime lexical_cast failure class bad_lexical_cast : public std::bad_cast #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 ) // under bcc32 5.5.1 bad_cast doesn't derive from exception , public std::exception #endif { public: bad_lexical_cast() : #ifndef BOOST_NO_TYPEID source(&typeid(void)), target(&typeid(void)) #else source(0), target(0) // this breaks getters #endif { } bad_lexical_cast( const std::type_info &source_type_arg, const std::type_info &target_type_arg) : source(&source_type_arg), target(&target_type_arg) { } const std::type_info &source_type() const { return *source; } const std::type_info &target_type() const { return *target; } virtual const char *what() const throw() { return "bad lexical cast: " "source type value could not be interpreted as target"; } virtual ~bad_lexical_cast() throw() { } private: const std::type_info *source; const std::type_info *target; }; namespace detail // selectors for choosing stream character type { template struct stream_char { typedef char type; }; #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct stream_char< std::basic_string > { typedef CharT type; }; #endif #ifndef BOOST_LCAST_NO_WCHAR_T #ifndef BOOST_NO_INTRINSIC_WCHAR_T template<> struct stream_char { typedef wchar_t type; }; #endif template<> struct stream_char { typedef wchar_t type; }; template<> struct stream_char { typedef wchar_t type; }; #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template<> struct stream_char { typedef wchar_t type; }; #endif #endif template struct widest_char { typedef TargetChar type; }; template<> struct widest_char { typedef wchar_t type; }; } namespace detail // deduce_char_traits template { #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct deduce_char_traits { typedef std::char_traits type; }; template struct deduce_char_traits< CharT , std::basic_string , Source > { typedef Traits type; }; template struct deduce_char_traits< CharT , Target , std::basic_string > { typedef Traits type; }; template struct deduce_char_traits< CharT , std::basic_string , std::basic_string > { typedef Traits type; }; #endif } namespace detail // lcast_src_length { // Return max. length of string representation of Source; // 0 if unlimited (with exceptions for some types, see below). // Values with limited string representation are placed to // the buffer locally defined in lexical_cast function. // 1 is returned for few types such as CharT const* or // std::basic_string that already have an internal // buffer ready to be reused by lexical_stream_limited_src. // Each specialization should have a correspondent operator<< // defined in lexical_stream_limited_src. template< class CharT // A result of widest_char transformation. , class Source // Source type of lexical_cast. > struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 0); // To check coverage, build the test with // bjam --v2 profile optimization=off static void check_coverage() {} }; template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; // No specializations for: // lcast_src_length // lcast_src_length // lcast_src_length // lcast_src_length // lcast_src_length // lcast_src_length #ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; #ifndef BOOST_NO_INTRINSIC_WCHAR_T template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; #endif #endif template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; #ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; template<> struct lcast_src_length { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; #endif #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct lcast_src_length< CharT, std::basic_string > { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; #else template<> struct lcast_src_length< char, std::basic_string > { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; #ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_src_length< wchar_t, std::basic_string > { BOOST_STATIC_CONSTANT(std::size_t, value = 1); static void check_coverage() {} }; #endif #endif // Helper for integral types. // Notes on length calculation: // Max length for 32bit int with grouping "\1" and thousands_sep ',': // "-2,1,4,7,4,8,3,6,4,7" // ^ - is_signed // ^ - 1 digit not counted by digits10 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2 // // Constant is_specialized is used instead of constant 1 // to prevent buffer overflow in a rare case when // doesn't add missing specialization for // numeric_limits for some integral type T. // When is_specialized is false, the whole expression is 0. template struct lcast_src_length_integral { #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_CONSTANT(std::size_t, value = std::numeric_limits::is_signed + std::numeric_limits::is_specialized + // == 1 std::numeric_limits::digits10 * 2 ); #else BOOST_STATIC_CONSTANT(std::size_t, value = 156); BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256); #endif }; #define BOOST_LCAST_DEF1(CharT, T) \ template<> struct lcast_src_length \ : lcast_src_length_integral \ { static void check_coverage() {} }; #ifdef BOOST_LCAST_NO_WCHAR_T #define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T) #else #define BOOST_LCAST_DEF(T) \ BOOST_LCAST_DEF1(char, T) \ BOOST_LCAST_DEF1(wchar_t, T) #endif BOOST_LCAST_DEF(short) BOOST_LCAST_DEF(unsigned short) BOOST_LCAST_DEF(int) BOOST_LCAST_DEF(unsigned int) BOOST_LCAST_DEF(long) BOOST_LCAST_DEF(unsigned long) #if defined(BOOST_HAS_LONG_LONG) BOOST_LCAST_DEF(boost::ulong_long_type) BOOST_LCAST_DEF(boost::long_long_type ) #elif defined(BOOST_HAS_MS_INT64) BOOST_LCAST_DEF(unsigned __int64) BOOST_LCAST_DEF( __int64) #endif #undef BOOST_LCAST_DEF #undef BOOST_LCAST_DEF1 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION // Helper for floating point types. // -1.23456789e-123456 // ^ sign // ^ leading digit // ^ decimal point // ^^^^^^^^ lcast_precision::value // ^ "e" // ^ exponent sign // ^^^^^^ exponent (assumed 6 or less digits) // sign + leading digit + decimal point + "e" + exponent sign == 5 template struct lcast_src_length_floating { BOOST_STATIC_ASSERT( std::numeric_limits::max_exponent10 <= 999999L && std::numeric_limits::min_exponent10 >= -999999L ); BOOST_STATIC_CONSTANT(std::size_t, value = 5 + lcast_precision::value + 6 ); }; template<> struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; template<> struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; template<> struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; #ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; template<> struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; template<> struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; #endif // #ifndef BOOST_LCAST_NO_WCHAR_T #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION } namespace detail // '0' and '-' constants { template struct lcast_char_constants; template<> struct lcast_char_constants { BOOST_STATIC_CONSTANT(char, zero = '0'); BOOST_STATIC_CONSTANT(char, minus = '-'); }; #ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_char_constants { BOOST_STATIC_CONSTANT(wchar_t, zero = L'0'); BOOST_STATIC_CONSTANT(wchar_t, minus = L'-'); }; #endif } namespace detail // lexical_streambuf_fake { struct lexical_streambuf_fake { }; } namespace detail // lcast_to_unsigned { #if (defined _MSC_VER) # pragma warning( push ) // C4146: unary minus operator applied to unsigned type, result still unsigned # pragma warning( disable : 4146 ) #elif defined( __BORLANDC__ ) # pragma option push -w-8041 #endif template inline BOOST_DEDUCED_TYPENAME make_unsigned::type lcast_to_unsigned(T value) { typedef BOOST_DEDUCED_TYPENAME make_unsigned::type result_type; result_type uvalue = static_cast(value); return value < 0 ? -uvalue : uvalue; } #if (defined _MSC_VER) # pragma warning( pop ) #elif defined( __BORLANDC__ ) # pragma option pop #endif } namespace detail // lcast_put_unsigned { template CharT* lcast_put_unsigned( T n , CharT* finish #ifndef BOOST_NO_STD_LOCALE // This must be 0 (null pointer) if current global std::locale // is to be used (now the default and previously the only // option). Otherwise a pointer to the std::locale object to be // used during casting. It is better to pass 0 instead of a // pointer to some temporary std::locale() object (the default // constructed std::locale is the current global one) since // global std::locale is used by default and thous no actions // are required in that case while any specific std::locale // requires additional actions. , const std::locale* p_loc #endif // BOOST_NO_STD_LOCALE ) { #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); #endif #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE // TODO: use BOOST_NO_STD_LOCALE fully. #ifndef BOOST_NO_STD_LOCALE // Reference bound to a temporary object extends its lifetime to // match the lifetime of the reference. So this is safe. const std::locale& loc = (p_loc ? *p_loc : std::locale()); #else // BOOST_NO_STD_LOCALE const std::locale loc; #endif // BOOST_NO_STD_LOCALE typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); std::string const& grouping = np.grouping(); std::string::size_type const grouping_size = grouping.size(); CharT thousands_sep = grouping_size ? np.thousands_sep() : 0; std::string::size_type group = 0; // current group number char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0]; // a) Since grouping is const, grouping[grouping.size()] returns 0. // b) It's safe to assume here and below that CHAR_MAX // is equivalent to unlimited grouping: #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif char left = last_grp_size; #endif typedef typename Traits::int_type int_type; CharT const czero = lcast_char_constants::zero; int_type const zero = Traits::to_int_type(czero); do { #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE if(left == 0) { ++group; if(group < grouping_size) { char const grp_size = grouping[group]; last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; } left = last_grp_size; --finish; Traits::assign(*finish, thousands_sep); } --left; #endif --finish; int_type const digit = static_cast(n % 10U); Traits::assign(*finish, Traits::to_char_type(zero + digit)); n /= 10; } while(n); return finish; } } namespace detail // stream wrapper for handling lexical conversions { template class lexical_stream { private: typedef typename widest_char< typename stream_char::type, typename stream_char::type>::type char_type; typedef Traits traits_type; public: lexical_stream( char_type* = 0 , char_type* = 0 #ifndef BOOST_NO_STD_LOCALE // This must be 0 (null pointer) if current global std::locale // is to be used (now the default and previously the only // option). Otherwise a pointer to the std::locale object to be // used during casting. It is better to pass 0 instead of a // pointer to some temporary std::locale() object (the default // constructed std::locale is the current global one) since // global std::locale is used by default and thous no actions // are required in that case while any specific std::locale // requires additional actions. , const std::locale* p_loc = 0 #endif // BOOST_NO_STD_LOCALE ) { #ifndef BOOST_NO_STD_LOCALE if(p_loc) stream.imbue(*p_loc); #endif // BOOST_NO_STD_LOCALE stream.unsetf(std::ios::skipws); lcast_set_precision(stream, (Source*)0, (Target*)0); } ~lexical_stream() { #if defined(BOOST_NO_STRINGSTREAM) stream.freeze(false); #endif } bool operator<<(const Source &input) { return !(stream << input).fail(); } template bool operator>>(InputStreamable &output) { return !is_pointer::value && stream >> output && stream.get() == #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) // GCC 2.9x lacks std::char_traits<>::eof(). // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 // configurations, which do provide std::char_traits<>::eof(). EOF; #else traits_type::eof(); #endif } #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION bool operator>>(std::string &output) { #if defined(BOOST_NO_STRINGSTREAM) stream << '\0'; #endif stream.str().swap(output); return true; } #ifndef BOOST_LCAST_NO_WCHAR_T bool operator>>(std::wstring &output) { stream.str().swap(output); return true; } #endif #else bool operator>>(std::basic_string& output) { stream.str().swap(output); return true; } template bool operator>>(std::basic_string& out) { std::basic_string str(stream.str()); out.assign(str.begin(), str.end()); return true; } #endif private: #if defined(BOOST_NO_STRINGSTREAM) std::strstream stream; #elif defined(BOOST_NO_STD_LOCALE) std::stringstream stream; #else std::basic_stringstream stream; #endif }; } namespace detail // optimized stream wrapper { // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation , class Base // lexical_streambuf_fake or basic_streambuf , class Traits // usually char_traits > class lexical_stream_limited_src : public Base { // A string representation of Source is written to [start, finish). // Currently, it is assumed that [start, finish) is big enough // to hold a string representation of any Source value. CharT* start; CharT* finish; #ifndef BOOST_NO_STD_LOCALE // The std::locale to be used or NULL to use the default current // global std::locale. const std::locale* p_loc; #endif // BOOST_NO_STD_LOCALE private: static void widen_and_assign(char*p, char ch) { Traits::assign(*p, ch); } #ifndef BOOST_LCAST_NO_WCHAR_T static void widen_and_assign(wchar_t* p, char ch) { // TODO: use BOOST_NO_STD_LOCALE fully. #ifndef BOOST_NO_STD_LOCALE // Reference bound to a temporary object extends its lifetime to // match the lifetime of the reference. So this is safe. const std::locale& loc = (p_loc ? *p_loc : std::locale()); #else // BOOST_NO_STD_LOCALE const std::locale loc; #endif // BOOST_NO_STD_LOCALE wchar_t w = BOOST_USE_FACET(std::ctype, loc).widen(ch); Traits::assign(*p, w); } static void widen_and_assign(wchar_t* p, wchar_t ch) { Traits::assign(*p, ch); } static void widen_and_assign(char*, wchar_t ch); // undefined #endif template bool lcast_put(const OutputStreamable& input) { this->setp(start, finish); std::basic_ostream stream(static_cast(this)); #ifndef BOOST_NO_STD_LOCALE if(p_loc) stream.imbue(*p_loc); #endif // BOOST_NO_STD_LOCALE lcast_set_precision(stream, (OutputStreamable*)0); bool const result = !(stream << input).fail(); finish = this->pptr(); return result; } // Undefined: lexical_stream_limited_src(lexical_stream_limited_src const&); void operator=(lexical_stream_limited_src const&); public: lexical_stream_limited_src( CharT* sta , CharT* fin #ifndef BOOST_NO_STD_LOCALE // This must be 0 (null pointer) if current global std::locale // is to be used (now the default and previously the only // option). Otherwise a pointer to the std::locale object to be // used during casting. It is better to pass 0 instead of a // pointer to some temporary std::locale() object (the default // constructed std::locale is the current global one) since // global std::locale is used by default and thous no actions // are required in that case while any specific std::locale // requires additional actions. , const std::locale* p_l #endif // BOOST_NO_STD_LOCALE ) : start(sta) , finish(fin) #ifndef BOOST_NO_STD_LOCALE , p_loc(p_l) #endif // BOOST_NO_STD_LOCALE {} public: // output template bool operator<<(std::basic_string const& str) { start = const_cast(str.data()); finish = start + str.length(); return true; } bool operator<<(bool); bool operator<<(char); #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) bool operator<<(wchar_t); #endif bool operator<<(CharT const*); bool operator<<(short); bool operator<<(int); bool operator<<(long); bool operator<<(unsigned short); bool operator<<(unsigned int); bool operator<<(unsigned long); #if defined(BOOST_HAS_LONG_LONG) bool operator<<(boost::ulong_long_type); bool operator<<(boost::long_long_type ); #elif defined(BOOST_HAS_MS_INT64) bool operator<<(unsigned __int64); bool operator<<( __int64); #endif // These three operators use ostream and streambuf. // lcast_streambuf_for_source::value is true. bool operator<<(float); bool operator<<(double); bool operator<<(long double); public: // input // Generic istream-based algorithm. // lcast_streambuf_for_target::value is true. template bool operator>>(InputStreamable& output) { #if (defined _MSC_VER) # pragma warning( push ) // conditional expression is constant # pragma warning( disable : 4127 ) #endif if(is_pointer::value) return false; this->setg(start, start, finish); std::basic_istream stream(static_cast(this)); #ifndef BOOST_NO_STD_LOCALE if(p_loc) stream.imbue(*p_loc); #endif // BOOST_NO_STD_LOCALE stream.unsetf(std::ios::skipws); lcast_set_precision(stream, (InputStreamable*)0); #if (defined _MSC_VER) # pragma warning( pop ) #endif return stream >> output && stream.get() == #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) // GCC 2.9x lacks std::char_traits<>::eof(). // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 // configurations, which do provide std::char_traits<>::eof(). EOF; #else Traits::eof(); #endif } bool operator>>(CharT&); #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // This #if is in sync with lcast_streambuf_for_target bool operator>>(std::string&); #ifndef BOOST_LCAST_NO_WCHAR_T bool operator>>(std::wstring&); #endif #else template bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } #endif }; template inline bool lexical_stream_limited_src::operator<<( bool value) { typedef typename Traits::int_type int_type; CharT const czero = lcast_char_constants::zero; int_type const zero = Traits::to_int_type(czero); Traits::assign(*start, Traits::to_char_type(zero + value)); finish = start + 1; return true; } template inline bool lexical_stream_limited_src::operator<<( char ch) { widen_and_assign(start, ch); finish = start + 1; return true; } #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) template inline bool lexical_stream_limited_src::operator<<( wchar_t ch) { widen_and_assign(start, ch); finish = start + 1; return true; } #endif template inline bool lexical_stream_limited_src::operator<<( short n) { start = lcast_put_unsigned( lcast_to_unsigned(n) , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); if(n < 0) { --start; CharT const minus = lcast_char_constants::minus; Traits::assign(*start, minus); } return true; } template inline bool lexical_stream_limited_src::operator<<( int n) { start = lcast_put_unsigned( lcast_to_unsigned(n) , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); if(n < 0) { --start; CharT const minus = lcast_char_constants::minus; Traits::assign(*start, minus); } return true; } template inline bool lexical_stream_limited_src::operator<<( long n) { start = lcast_put_unsigned( lcast_to_unsigned(n) , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); if(n < 0) { --start; CharT const minus = lcast_char_constants::minus; Traits::assign(*start, minus); } return true; } #if defined(BOOST_HAS_LONG_LONG) template inline bool lexical_stream_limited_src::operator<<( boost::long_long_type n) { start = lcast_put_unsigned( lcast_to_unsigned(n) , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); if(n < 0) { --start; CharT const minus = lcast_char_constants::minus; Traits::assign(*start, minus); } return true; } #elif defined(BOOST_HAS_MS_INT64) template inline bool lexical_stream_limited_src::operator<<( __int64 n) { start = lcast_put_unsigned( lcast_to_unsigned(n) , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); if(n < 0) { --start; CharT const minus = lcast_char_constants::minus; Traits::assign(*start, minus); } return true; } #endif template inline bool lexical_stream_limited_src::operator<<( unsigned short n) { start = lcast_put_unsigned( n , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); return true; } template inline bool lexical_stream_limited_src::operator<<( unsigned int n) { start = lcast_put_unsigned( n , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); return true; } template inline bool lexical_stream_limited_src::operator<<( unsigned long n) { start = lcast_put_unsigned( n , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); return true; } #if defined(BOOST_HAS_LONG_LONG) template inline bool lexical_stream_limited_src::operator<<( boost::ulong_long_type n) { start = lcast_put_unsigned( n , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); return true; } #elif defined(BOOST_HAS_MS_INT64) template inline bool lexical_stream_limited_src::operator<<( unsigned __int64 n) { start = lcast_put_unsigned( n , finish #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); return true; } #endif template inline bool lexical_stream_limited_src::operator<<( float val) { return this->lcast_put(val); } template inline bool lexical_stream_limited_src::operator<<( double val) { return this->lcast_put(val); } template inline bool lexical_stream_limited_src::operator<<( long double val) { return this->lcast_put(val); } template inline bool lexical_stream_limited_src::operator<<( CharT const* str) { start = const_cast(str); finish = start + Traits::length(str); return true; } template inline bool lexical_stream_limited_src::operator>>( CharT& output) { bool const ok = (finish - start == 1); if(ok) Traits::assign(output, *start); return ok; } #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template inline bool lexical_stream_limited_src::operator>>( std::string& str) { str.assign(start, finish); return true; } #ifndef BOOST_LCAST_NO_WCHAR_T template inline bool lexical_stream_limited_src::operator>>( std::wstring& str) { str.assign(start, finish); return true; } #endif #endif } namespace detail // lcast_streambuf_for_source { // Returns true if optimized stream wrapper needs ostream for writing. template struct lcast_streambuf_for_source { BOOST_STATIC_CONSTANT(bool, value = false); }; template<> struct lcast_streambuf_for_source { BOOST_STATIC_CONSTANT(bool, value = true); }; template<> struct lcast_streambuf_for_source { BOOST_STATIC_CONSTANT(bool, value = true); }; template<> struct lcast_streambuf_for_source { BOOST_STATIC_CONSTANT(bool, value = true); }; } namespace detail // lcast_streambuf_for_target { // Returns true if optimized stream wrapper needs istream for reading. template struct lcast_streambuf_for_target { BOOST_STATIC_CONSTANT(bool, value = true); }; template<> struct lcast_streambuf_for_target { BOOST_STATIC_CONSTANT(bool, value = false); }; #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) template<> struct lcast_streambuf_for_target { BOOST_STATIC_CONSTANT(bool, value = false); }; #endif #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct lcast_streambuf_for_target< std::basic_string > { BOOST_STATIC_CONSTANT(bool, value = false); }; #ifndef BOOST_LCAST_NO_WCHAR_T template struct lcast_streambuf_for_target< std::basic_string > { BOOST_STATIC_CONSTANT(bool, value = false); }; #endif #else template<> struct lcast_streambuf_for_target { BOOST_STATIC_CONSTANT(bool, value = false); }; #ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_streambuf_for_target { BOOST_STATIC_CONSTANT(bool, value = false); }; #endif #endif } #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // call-by-const reference version namespace detail { template struct array_to_pointer_decay { typedef T type; }; template struct array_to_pointer_decay { typedef const T * type; }; template< typename Target , typename Source , bool Unlimited // string representation of Source is unlimited , typename CharT > Target lexical_cast( BOOST_DEDUCED_TYPENAME boost::call_traits::param_type arg , CharT* buf , std::size_t src_len #ifndef BOOST_NO_STD_LOCALE // This must be 0 (null pointer) if current global std::locale // is to be used (now the default and previously the only // option). Otherwise a pointer to the std::locale object to be // used during casting. It is better to pass 0 instead of a // pointer to some temporary std::locale() object (the default // constructed std::locale is the current global one) since // global std::locale is used by default and thous no actions // are required in that case while any specific std::locale // requires additional actions. , const std::locale* p_loc #endif // BOOST_NO_STD_LOCALE ) { typedef BOOST_DEDUCED_TYPENAME deduce_char_traits::type traits; typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< lcast_streambuf_for_target::value || lcast_streambuf_for_source::value , std::basic_streambuf , lexical_streambuf_fake >::type base; BOOST_DEDUCED_TYPENAME boost::mpl::if_c< Unlimited , detail::lexical_stream , detail::lexical_stream_limited_src >::type interpreter( buf , buf + src_len #ifndef BOOST_NO_STD_LOCALE , p_loc #endif // BOOST_NO_STD_LOCALE ); // The original form, reproduced below, is more elegant // but yields a spurious C4701 warning ("possible use of // "result" before initialization") with VC7.1 (/W4). // // Target result; // // if(!(interpreter << arg && interpreter >> result)) // throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); // return result; if(interpreter << arg) { Target result; if (interpreter >> result) return result; } #ifndef BOOST_NO_TYPEID throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); #else throw_exception(bad_lexical_cast()); #endif return Target(); // normally never reached (throw_exception) } } template inline Target lexical_cast(const Source &arg) { typedef typename detail::array_to_pointer_decay::type src; typedef typename detail::widest_char< typename detail::stream_char::type , typename detail::stream_char::type >::type char_type; typedef detail::lcast_src_length lcast_src_length; std::size_t const src_len = lcast_src_length::value; char_type buf[src_len + 1]; lcast_src_length::check_coverage(); return detail::lexical_cast( arg , buf , src_len #ifndef BOOST_NO_STD_LOCALE // NULL pointer means that the default current global std::locale // will be used. , 0 #endif // BOOST_NO_STD_LOCALE ); } template inline Target classic_lexical_cast(const Source &arg) { typedef typename detail::array_to_pointer_decay::type src; typedef typename detail::widest_char< typename detail::stream_char::type , typename detail::stream_char::type >::type char_type; typedef detail::lcast_src_length lcast_src_length; std::size_t const src_len = lcast_src_length::value; char_type buf[src_len + 1]; lcast_src_length::check_coverage(); return detail::lexical_cast( arg , buf , src_len #ifndef BOOST_NO_STD_LOCALE , &std::locale::classic() #endif // BOOST_NO_STD_LOCALE ); } #else // call-by-value fallback version (deprecated) template Target lexical_cast(Source arg) { typedef typename detail::widest_char< BOOST_DEDUCED_TYPENAME detail::stream_char::type , BOOST_DEDUCED_TYPENAME detail::stream_char::type >::type char_type; typedef std::char_traits traits; detail::lexical_stream interpreter; Target result; if(!(interpreter << arg && interpreter >> result)) #ifndef BOOST_NO_TYPEID throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); #else throw_exception(bad_lexical_cast()); #endif return result; } #endif } // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2007. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #undef BOOST_LCAST_NO_WCHAR_T #endif