| #ifndef BOOST_LEXICAL_CAST_INCLUDED |
| #define BOOST_LEXICAL_CAST_INCLUDED |
| |
| // Boost lexical_cast.hpp header -------------------------------------------// |
| // |
| // 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 <climits> |
| #include <cstddef> |
| #include <istream> |
| #include <string> |
| #include <typeinfo> |
| #include <exception> |
| #include <boost/config.hpp> |
| #include <boost/limits.hpp> |
| #include <boost/mpl/if.hpp> |
| #include <boost/throw_exception.hpp> |
| #include <boost/type_traits/is_pointer.hpp> |
| #include <boost/type_traits/make_unsigned.hpp> |
| #include <boost/call_traits.hpp> |
| #include <boost/static_assert.hpp> |
| #include <boost/detail/lcast_precision.hpp> |
| #include <boost/detail/workaround.hpp> |
| |
| #ifndef BOOST_NO_STD_LOCALE |
| #include <locale> |
| #endif |
| |
| #ifdef BOOST_NO_STRINGSTREAM |
| #include <strstream> |
| #else |
| #include <sstream> |
| #endif |
| |
| #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) |
| #define BOOST_LCAST_NO_WCHAR_T |
| #endif |
| |
| #ifdef BOOST_NO_TYPEID |
| #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast()) |
| #else |
| #define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \ |
| throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))) |
| #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<typename Type> |
| struct stream_char |
| { |
| typedef char type; |
| }; |
| |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template<class CharT, class Traits, class Alloc> |
| struct stream_char< std::basic_string<CharT,Traits,Alloc> > |
| { |
| typedef CharT type; |
| }; |
| #endif |
| |
| #ifndef BOOST_LCAST_NO_WCHAR_T |
| #ifndef BOOST_NO_INTRINSIC_WCHAR_T |
| template<> |
| struct stream_char<wchar_t> |
| { |
| typedef wchar_t type; |
| }; |
| #endif |
| |
| template<> |
| struct stream_char<wchar_t *> |
| { |
| typedef wchar_t type; |
| }; |
| |
| template<> |
| struct stream_char<const wchar_t *> |
| { |
| typedef wchar_t type; |
| }; |
| |
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template<> |
| struct stream_char<std::wstring> |
| { |
| typedef wchar_t type; |
| }; |
| #endif |
| #endif |
| |
| template<typename TargetChar, typename SourceChar> |
| struct widest_char |
| { |
| typedef TargetChar type; |
| }; |
| |
| template<> |
| struct widest_char<char, wchar_t> |
| { |
| typedef wchar_t type; |
| }; |
| } |
| |
| namespace detail // deduce_char_traits template |
| { |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template<class CharT, class Target, class Source> |
| struct deduce_char_traits |
| { |
| typedef std::char_traits<CharT> type; |
| }; |
| |
| template<class CharT, class Traits, class Alloc, class Source> |
| struct deduce_char_traits< CharT |
| , std::basic_string<CharT,Traits,Alloc> |
| , Source |
| > |
| { |
| typedef Traits type; |
| }; |
| |
| template<class CharT, class Target, class Traits, class Alloc> |
| struct deduce_char_traits< CharT |
| , Target |
| , std::basic_string<CharT,Traits,Alloc> |
| > |
| { |
| typedef Traits type; |
| }; |
| |
| template<class CharT, class Traits, class Alloc1, class Alloc2> |
| struct deduce_char_traits< CharT |
| , std::basic_string<CharT,Traits,Alloc1> |
| , std::basic_string<CharT,Traits,Alloc2> |
| > |
| { |
| 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<CharT> 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<char, bool> |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| |
| template<> |
| struct lcast_src_length<char, char> |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| |
| // No specializations for: |
| // lcast_src_length<char, signed char> |
| // lcast_src_length<char, unsigned char> |
| // lcast_src_length<char, signed char*> |
| // lcast_src_length<char, unsigned char*> |
| // lcast_src_length<char, signed char const*> |
| // lcast_src_length<char, unsigned char const*> |
| |
| #ifndef BOOST_LCAST_NO_WCHAR_T |
| template<> |
| struct lcast_src_length<wchar_t, bool> |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| |
| template<> |
| struct lcast_src_length<wchar_t, char> |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| |
| #ifndef BOOST_NO_INTRINSIC_WCHAR_T |
| template<> |
| struct lcast_src_length<wchar_t, wchar_t> |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| #endif |
| #endif |
| |
| template<> |
| struct lcast_src_length<char, char const*> |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| |
| template<> |
| struct lcast_src_length<char, char*> |
| { |
| 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, wchar_t const*> |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| |
| template<> |
| struct lcast_src_length<wchar_t, wchar_t*> |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| #endif |
| |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template<class CharT, class Traits, class Alloc> |
| struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> > |
| { |
| BOOST_STATIC_CONSTANT(std::size_t, value = 1); |
| static void check_coverage() {} |
| }; |
| #else |
| template<> |
| struct lcast_src_length< char, std::basic_string<char> > |
| { |
| 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<wchar_t> > |
| { |
| 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 |
| // <boost/limits.hpp> doesn't add missing specialization for |
| // numeric_limits<T> for some integral type T. |
| // When is_specialized is false, the whole expression is 0. |
| template<class Source> |
| struct lcast_src_length_integral |
| { |
| #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
| BOOST_STATIC_CONSTANT(std::size_t, value = |
| std::numeric_limits<Source>::is_signed + |
| std::numeric_limits<Source>::is_specialized + // == 1 |
| std::numeric_limits<Source>::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<CharT, T> \ |
| : lcast_src_length_integral<T> \ |
| { 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<Source>::value |
| // ^ "e" |
| // ^ exponent sign |
| // ^^^^^^ exponent (assumed 6 or less digits) |
| // sign + leading digit + decimal point + "e" + exponent sign == 5 |
| template<class Source> |
| struct lcast_src_length_floating |
| { |
| BOOST_STATIC_ASSERT( |
| std::numeric_limits<Source>::max_exponent10 <= 999999L && |
| std::numeric_limits<Source>::min_exponent10 >= -999999L |
| ); |
| BOOST_STATIC_CONSTANT(std::size_t, value = |
| 5 + lcast_precision<Source>::value + 6 |
| ); |
| }; |
| |
| template<> |
| struct lcast_src_length<char,float> |
| : lcast_src_length_floating<float> |
| { |
| static void check_coverage() {} |
| }; |
| |
| template<> |
| struct lcast_src_length<char,double> |
| : lcast_src_length_floating<double> |
| { |
| static void check_coverage() {} |
| }; |
| |
| template<> |
| struct lcast_src_length<char,long double> |
| : lcast_src_length_floating<long double> |
| { |
| static void check_coverage() {} |
| }; |
| |
| #ifndef BOOST_LCAST_NO_WCHAR_T |
| template<> |
| struct lcast_src_length<wchar_t,float> |
| : lcast_src_length_floating<float> |
| { |
| static void check_coverage() {} |
| }; |
| |
| template<> |
| struct lcast_src_length<wchar_t,double> |
| : lcast_src_length_floating<double> |
| { |
| static void check_coverage() {} |
| }; |
| |
| template<> |
| struct lcast_src_length<wchar_t,long double> |
| : lcast_src_length_floating<long double> |
| { |
| 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<typename CharT> struct lcast_char_constants; |
| |
| template<> |
| struct lcast_char_constants<char> |
| { |
| BOOST_STATIC_CONSTANT(char, zero = '0'); |
| BOOST_STATIC_CONSTANT(char, minus = '-'); |
| }; |
| |
| #ifndef BOOST_LCAST_NO_WCHAR_T |
| template<> |
| struct lcast_char_constants<wchar_t> |
| { |
| 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<class T> |
| inline |
| BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value) |
| { |
| typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type; |
| result_type uvalue = static_cast<result_type>(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<class Traits, class T, class CharT> |
| CharT* lcast_put_unsigned(T n, CharT* finish) |
| { |
| #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
| BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed); |
| #endif |
| |
| #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE |
| // TODO: use BOOST_NO_STD_LOCALE |
| std::locale loc; |
| typedef std::numpunct<CharT> 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<T>::digits10 < CHAR_MAX); |
| #endif |
| |
| char left = last_grp_size; |
| #endif |
| |
| typedef typename Traits::int_type int_type; |
| CharT const czero = lcast_char_constants<CharT>::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<int_type>(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<typename Target, typename Source, typename Traits> |
| class lexical_stream |
| { |
| private: |
| typedef typename widest_char< |
| typename stream_char<Target>::type, |
| typename stream_char<Source>::type>::type char_type; |
| |
| typedef Traits traits_type; |
| |
| public: |
| lexical_stream(char_type* = 0, char_type* = 0) |
| { |
| stream.unsetf(std::ios::skipws); |
| lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) ); |
| } |
| ~lexical_stream() |
| { |
| #if defined(BOOST_NO_STRINGSTREAM) |
| stream.freeze(false); |
| #endif |
| } |
| bool operator<<(const Source &input) |
| { |
| return !(stream << input).fail(); |
| } |
| template<typename InputStreamable> |
| bool operator>>(InputStreamable &output) |
| { |
| return !is_pointer<InputStreamable>::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<char_type,traits_type>& output) |
| { |
| stream.str().swap(output); |
| return true; |
| } |
| |
| template<class Alloc> |
| bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out) |
| { |
| std::basic_string<char_type,traits_type> 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<char_type,traits_type> 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<CharT> |
| , class Traits // usually char_traits<CharT> |
| > |
| 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; |
| |
| 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 |
| std::locale loc; |
| wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, 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<class OutputStreamable> |
| bool lcast_put(const OutputStreamable& input) |
| { |
| this->setp(start, finish); |
| std::basic_ostream<CharT> stream(static_cast<Base*>(this)); |
| lcast_set_precision(stream, static_cast<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) |
| : start(sta) |
| , finish(fin) |
| {} |
| |
| public: // output |
| |
| template<class Alloc> |
| bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str) |
| { |
| start = const_cast<CharT*>(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<T>::value is true. |
| bool operator<<(float); |
| bool operator<<(double); |
| bool operator<<(long double); |
| |
| public: // input |
| |
| // Generic istream-based algorithm. |
| // lcast_streambuf_for_target<InputStreamable>::value is true. |
| template<typename InputStreamable> |
| bool operator>>(InputStreamable& output) |
| { |
| #if (defined _MSC_VER) |
| # pragma warning( push ) |
| // conditional expression is constant |
| # pragma warning( disable : 4127 ) |
| #endif |
| if(is_pointer<InputStreamable>::value) |
| return false; |
| |
| this->setg(start, start, finish); |
| std::basic_istream<CharT> stream(static_cast<Base*>(this)); |
| stream.unsetf(std::ios::skipws); |
| lcast_set_precision(stream, static_cast<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<class Alloc> |
| bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) |
| { |
| str.assign(start, finish); |
| return true; |
| } |
| #endif |
| }; |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| bool value) |
| { |
| typedef typename Traits::int_type int_type; |
| CharT const czero = lcast_char_constants<CharT>::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<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::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<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| wchar_t ch) |
| { |
| widen_and_assign(start, ch); |
| finish = start + 1; |
| return true; |
| } |
| #endif |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| short n) |
| { |
| start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish); |
| if(n < 0) |
| { |
| --start; |
| CharT const minus = lcast_char_constants<CharT>::minus; |
| Traits::assign(*start, minus); |
| } |
| return true; |
| } |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| int n) |
| { |
| start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish); |
| if(n < 0) |
| { |
| --start; |
| CharT const minus = lcast_char_constants<CharT>::minus; |
| Traits::assign(*start, minus); |
| } |
| return true; |
| } |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| long n) |
| { |
| start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish); |
| if(n < 0) |
| { |
| --start; |
| CharT const minus = lcast_char_constants<CharT>::minus; |
| Traits::assign(*start, minus); |
| } |
| return true; |
| } |
| |
| #if defined(BOOST_HAS_LONG_LONG) |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| boost::long_long_type n) |
| { |
| start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish); |
| if(n < 0) |
| { |
| --start; |
| CharT const minus = lcast_char_constants<CharT>::minus; |
| Traits::assign(*start, minus); |
| } |
| return true; |
| } |
| #elif defined(BOOST_HAS_MS_INT64) |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| __int64 n) |
| { |
| start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish); |
| if(n < 0) |
| { |
| --start; |
| CharT const minus = lcast_char_constants<CharT>::minus; |
| Traits::assign(*start, minus); |
| } |
| return true; |
| } |
| #endif |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| unsigned short n) |
| { |
| start = lcast_put_unsigned<Traits>(n, finish); |
| return true; |
| } |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| unsigned int n) |
| { |
| start = lcast_put_unsigned<Traits>(n, finish); |
| return true; |
| } |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| unsigned long n) |
| { |
| start = lcast_put_unsigned<Traits>(n, finish); |
| return true; |
| } |
| |
| #if defined(BOOST_HAS_LONG_LONG) |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| boost::ulong_long_type n) |
| { |
| start = lcast_put_unsigned<Traits>(n, finish); |
| return true; |
| } |
| #elif defined(BOOST_HAS_MS_INT64) |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| unsigned __int64 n) |
| { |
| start = lcast_put_unsigned<Traits>(n, finish); |
| return true; |
| } |
| #endif |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| float val) |
| { |
| return this->lcast_put(val); |
| } |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| double val) |
| { |
| return this->lcast_put(val); |
| } |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| long double val) |
| { |
| return this->lcast_put(val); |
| } |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<( |
| CharT const* str) |
| { |
| start = const_cast<CharT*>(str); |
| finish = start + Traits::length(str); |
| return true; |
| } |
| |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>( |
| CharT& output) |
| { |
| bool const ok = (finish - start == 1); |
| if(ok) |
| Traits::assign(output, *start); |
| return ok; |
| } |
| |
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>( |
| std::string& str) |
| { |
| str.assign(start, finish); |
| return true; |
| } |
| |
| #ifndef BOOST_LCAST_NO_WCHAR_T |
| template<typename CharT, class Base, class Traits> |
| inline bool lexical_stream_limited_src<CharT,Base,Traits>::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<class Source> |
| struct lcast_streambuf_for_source |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| |
| template<> |
| struct lcast_streambuf_for_source<float> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| |
| template<> |
| struct lcast_streambuf_for_source<double> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| |
| template<> |
| struct lcast_streambuf_for_source<long double> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| } |
| |
| namespace detail // lcast_streambuf_for_target |
| { |
| // Returns true if optimized stream wrapper needs istream for reading. |
| template<class Target> |
| struct lcast_streambuf_for_target |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| |
| template<> |
| struct lcast_streambuf_for_target<char> |
| { |
| 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<wchar_t> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| #endif |
| |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template<class Traits, class Alloc> |
| struct lcast_streambuf_for_target< |
| std::basic_string<char,Traits,Alloc> > |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| |
| #ifndef BOOST_LCAST_NO_WCHAR_T |
| template<class Traits, class Alloc> |
| struct lcast_streambuf_for_target< |
| std::basic_string<wchar_t,Traits,Alloc> > |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| #endif |
| #else |
| template<> |
| struct lcast_streambuf_for_target<std::string> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| |
| #ifndef BOOST_LCAST_NO_WCHAR_T |
| template<> |
| struct lcast_streambuf_for_target<std::wstring> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| #endif |
| #endif |
| } |
| |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| |
| // call-by-const reference version |
| |
| namespace detail |
| { |
| template<class T> |
| struct array_to_pointer_decay |
| { |
| typedef T type; |
| }; |
| |
| template<class T, std::size_t N> |
| struct array_to_pointer_decay<T[N]> |
| { |
| typedef const T * type; |
| }; |
| |
| #if (defined _MSC_VER) |
| # pragma warning( push ) |
| # pragma warning( disable : 4701 ) // possible use of ... before initialization |
| # pragma warning( disable : 4702 ) // unreachable code |
| #endif |
| |
| template< typename Target |
| , typename Source |
| , bool Unlimited // string representation of Source is unlimited |
| , typename CharT |
| > |
| Target lexical_cast( |
| BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg, |
| CharT* buf, std::size_t src_len) |
| { |
| typedef BOOST_DEDUCED_TYPENAME |
| deduce_char_traits<CharT,Target,Source>::type traits; |
| |
| typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< |
| lcast_streambuf_for_target<Target>::value || |
| lcast_streambuf_for_source<Source>::value |
| , std::basic_streambuf<CharT> |
| , lexical_streambuf_fake |
| >::type base; |
| |
| BOOST_DEDUCED_TYPENAME boost::mpl::if_c< |
| Unlimited |
| , detail::lexical_stream<Target,Source,traits> |
| , detail::lexical_stream_limited_src<CharT,base,traits> |
| >::type interpreter(buf, buf + src_len); |
| |
| Target result; |
| if(!(interpreter << arg && interpreter >> result)) |
| BOOST_LCAST_THROW_BAD_CAST(Source, Target); |
| return result; |
| } |
| #if (defined _MSC_VER) |
| # pragma warning( pop ) |
| #endif |
| } |
| |
| template<typename Target, typename Source> |
| inline Target lexical_cast(const Source &arg) |
| { |
| typedef typename detail::array_to_pointer_decay<Source>::type src; |
| |
| typedef typename detail::widest_char< |
| typename detail::stream_char<Target>::type |
| , typename detail::stream_char<src>::type |
| >::type char_type; |
| |
| typedef detail::lcast_src_length<char_type, src> 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<Target, src, !src_len>(arg, buf, src_len); |
| } |
| |
| #else |
| |
| // call-by-value fallback version (deprecated) |
| |
| template<typename Target, typename Source> |
| Target lexical_cast(Source arg) |
| { |
| typedef typename detail::widest_char< |
| BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type |
| , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type |
| >::type char_type; |
| |
| typedef std::char_traits<char_type> traits; |
| detail::lexical_stream<Target, Source, traits> 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 |