williamr@2: #ifndef BOOST_LEXICAL_CAST_INCLUDED williamr@2: #define BOOST_LEXICAL_CAST_INCLUDED williamr@2: williamr@2: // Boost lexical_cast.hpp header -------------------------------------------// williamr@2: // williamr@2: // See http://www.boost.org for most recent version including documentation. williamr@2: // See end of this header for rights and permissions. williamr@2: // williamr@2: // what: lexical_cast custom keyword cast williamr@2: // who: contributed by Kevlin Henney, williamr@2: // enhanced with contributions from Terje Slettebų, williamr@2: // with additional fixes and suggestions from Gennaro Prota, williamr@2: // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, williamr@2: // and other Boosters williamr@2: // when: November 2000, March 2003, June 2005 williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #ifdef BOOST_NO_STRINGSTREAM williamr@2: #include williamr@2: #else williamr@2: #include williamr@2: #endif williamr@2: williamr@2: #if defined(BOOST_NO_STRINGSTREAM) || \ williamr@2: defined(BOOST_NO_STD_WSTRING) || \ williamr@2: defined(BOOST_NO_STD_LOCALE) williamr@2: #define DISABLE_WIDE_CHAR_SUPPORT williamr@2: #endif williamr@2: williamr@2: namespace boost williamr@2: { williamr@2: // exception used to indicate runtime lexical_cast failure williamr@2: class bad_lexical_cast : public std::bad_cast williamr@2: { williamr@2: public: williamr@2: bad_lexical_cast() : williamr@2: source(&typeid(void)), target(&typeid(void)) williamr@2: { williamr@2: } williamr@2: bad_lexical_cast( williamr@2: const std::type_info &source_type, williamr@2: const std::type_info &target_type) : williamr@2: source(&source_type), target(&target_type) williamr@2: { williamr@2: } williamr@2: const std::type_info &source_type() const williamr@2: { williamr@2: return *source; williamr@2: } williamr@2: const std::type_info &target_type() const williamr@2: { williamr@2: return *target; williamr@2: } williamr@2: virtual const char *what() const throw() williamr@2: { williamr@2: return "bad lexical cast: " williamr@2: "source type value could not be interpreted as target"; williamr@2: } williamr@2: virtual ~bad_lexical_cast() throw() williamr@2: { williamr@2: } williamr@2: private: williamr@2: const std::type_info *source; williamr@2: const std::type_info *target; williamr@2: }; williamr@2: williamr@2: namespace detail // selectors for choosing stream character type williamr@2: { williamr@2: template williamr@2: struct stream_char williamr@2: { williamr@2: typedef char type; williamr@2: }; williamr@2: williamr@2: #ifndef DISABLE_WIDE_CHAR_SUPPORT williamr@2: #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) williamr@2: template<> williamr@2: struct stream_char williamr@2: { williamr@2: typedef wchar_t type; williamr@2: }; williamr@2: #endif williamr@2: williamr@2: template<> williamr@2: struct stream_char williamr@2: { williamr@2: typedef wchar_t type; williamr@2: }; williamr@2: williamr@2: template<> williamr@2: struct stream_char williamr@2: { williamr@2: typedef wchar_t type; williamr@2: }; williamr@2: williamr@2: template<> williamr@2: struct stream_char williamr@2: { williamr@2: typedef wchar_t type; williamr@2: }; williamr@2: #endif williamr@2: williamr@2: template williamr@2: struct widest_char williamr@2: { williamr@2: typedef TargetChar type; williamr@2: }; williamr@2: williamr@2: template<> williamr@2: struct widest_char williamr@2: { williamr@2: typedef wchar_t type; williamr@2: }; williamr@2: } williamr@2: williamr@2: namespace detail // stream wrapper for handling lexical conversions williamr@2: { williamr@2: template williamr@2: class lexical_stream williamr@2: { williamr@2: private: williamr@2: typedef typename widest_char< williamr@2: typename stream_char::type, williamr@2: typename stream_char::type>::type char_type; williamr@2: williamr@2: public: williamr@2: lexical_stream() williamr@2: { williamr@2: stream.unsetf(std::ios::skipws); williamr@2: williamr@2: if(std::numeric_limits::is_specialized) williamr@2: stream.precision(std::numeric_limits::digits10 + 1); williamr@2: else if(std::numeric_limits::is_specialized) williamr@2: stream.precision(std::numeric_limits::digits10 + 1); williamr@2: } williamr@2: ~lexical_stream() williamr@2: { williamr@2: #if defined(BOOST_NO_STRINGSTREAM) williamr@2: stream.freeze(false); williamr@2: #endif williamr@2: } williamr@2: bool operator<<(const Source &input) williamr@2: { williamr@2: return !(stream << input).fail(); williamr@2: } williamr@2: template williamr@2: bool operator>>(InputStreamable &output) williamr@2: { williamr@2: return !is_pointer::value && williamr@2: stream >> output && williamr@2: stream.get() == williamr@2: #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) williamr@2: // GCC 2.9x lacks std::char_traits<>::eof(). williamr@2: // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 williamr@2: // configurations, which do provide std::char_traits<>::eof(). williamr@2: williamr@2: EOF; williamr@2: #else williamr@2: std::char_traits::eof(); williamr@2: #endif williamr@2: } williamr@2: bool operator>>(std::string &output) williamr@2: { williamr@2: #if defined(BOOST_NO_STRINGSTREAM) williamr@2: stream << '\0'; williamr@2: #endif williamr@2: output = stream.str(); williamr@2: return true; williamr@2: } williamr@2: #ifndef DISABLE_WIDE_CHAR_SUPPORT williamr@2: bool operator>>(std::wstring &output) williamr@2: { williamr@2: output = stream.str(); williamr@2: return true; williamr@2: } williamr@2: #endif williamr@2: private: williamr@2: #if defined(BOOST_NO_STRINGSTREAM) williamr@2: std::strstream stream; williamr@2: #elif defined(BOOST_NO_STD_LOCALE) williamr@2: std::stringstream stream; williamr@2: #else williamr@2: std::basic_stringstream stream; williamr@2: #endif williamr@2: }; williamr@2: } williamr@2: williamr@2: #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION williamr@2: williamr@2: // call-by-const reference version williamr@2: williamr@2: namespace detail williamr@2: { williamr@2: template williamr@2: struct array_to_pointer_decay williamr@2: { williamr@2: typedef T type; williamr@2: }; williamr@2: williamr@2: template williamr@2: struct array_to_pointer_decay williamr@2: { williamr@2: typedef const T * type; williamr@2: }; williamr@2: } williamr@2: williamr@2: template williamr@2: Target lexical_cast(const Source &arg) williamr@2: { williamr@2: typedef typename detail::array_to_pointer_decay::type NewSource; williamr@2: williamr@2: detail::lexical_stream interpreter; williamr@2: Target result; williamr@2: williamr@2: if(!(interpreter << arg && interpreter >> result)) williamr@2: throw_exception(bad_lexical_cast(typeid(NewSource), typeid(Target))); williamr@2: return result; williamr@2: } williamr@2: williamr@2: #else williamr@2: williamr@2: // call-by-value fallback version (deprecated) williamr@2: williamr@2: template williamr@2: Target lexical_cast(Source arg) williamr@2: { williamr@2: detail::lexical_stream interpreter; williamr@2: Target result; williamr@2: williamr@2: if(!(interpreter << arg && interpreter >> result)) williamr@2: throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); williamr@2: return result; williamr@2: } williamr@2: williamr@2: #endif williamr@2: } williamr@2: williamr@2: // Copyright Kevlin Henney, 2000-2005. All rights reserved. williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: #undef DISABLE_WIDE_CHAR_SUPPORT williamr@2: #endif