From d44a6fcf8bace4216b57ddf61951952a44268c3f Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:07:19 +0000 Subject: [PATCH] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41369] --- include/boost/implicit_cast.hpp | 2 +- include/boost/lexical_cast.hpp | 902 +++++++++++++++++++++++++++++++- 2 files changed, 876 insertions(+), 28 deletions(-) diff --git a/include/boost/implicit_cast.hpp b/include/boost/implicit_cast.hpp index 7043085..5b1cd92 100755 --- a/include/boost/implicit_cast.hpp +++ b/include/boost/implicit_cast.hpp @@ -23,7 +23,7 @@ inline T implicit_cast (typename mpl::identity::type x) { //template //void implicit_cast (...); - } // namespace boost + #endif // IMPLICIT_CAST_DWA200356_HPP diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 926b95e..754aecf 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -3,24 +3,31 @@ // Boost lexical_cast.hpp header -------------------------------------------// // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/libs/converston 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 Slettebų, +// enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// and other Boosters -// when: November 2000, March 2003, June 2005 +// 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 #ifdef BOOST_NO_STRINGSTREAM #include @@ -45,9 +52,9 @@ namespace boost { } bad_lexical_cast( - const std::type_info &source_type, - const std::type_info &target_type) : - source(&source_type), target(&target_type) + 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 @@ -79,8 +86,8 @@ namespace boost typedef char type; }; - #ifndef DISABLE_WIDE_CHAR_SUPPORT -#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_NO_INTRINSIC_WCHAR_T template<> struct stream_char { @@ -105,7 +112,7 @@ namespace boost { typedef wchar_t type; }; - #endif +#endif template struct widest_char @@ -119,7 +126,393 @@ namespace boost typedef wchar_t type; }; } - + + 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 DISABLE_WIDE_CHAR_SUPPORT + 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 DISABLE_WIDE_CHAR_SUPPORT + 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 DISABLE_WIDE_CHAR_SUPPORT + 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_AUX_LEXICAL_CAST_DEF1(CharT, T) template<> \ + struct lcast_src_length : lcast_src_length_integral \ + { static void check_coverage() {} }; + +#ifdef DISABLE_WIDE_CHAR_SUPPORT +#define BOOST_AUX_LEXICAL_CAST_DEF(T) BOOST_AUX_LEXICAL_CAST_DEF1(char, T) +#else +#define BOOST_AUX_LEXICAL_CAST_DEF(T) \ + BOOST_AUX_LEXICAL_CAST_DEF1(char, T) \ + BOOST_AUX_LEXICAL_CAST_DEF1(wchar_t, T) +#endif + + BOOST_AUX_LEXICAL_CAST_DEF(short) + BOOST_AUX_LEXICAL_CAST_DEF(unsigned short) + BOOST_AUX_LEXICAL_CAST_DEF(int) + BOOST_AUX_LEXICAL_CAST_DEF(unsigned int) + BOOST_AUX_LEXICAL_CAST_DEF(long) + BOOST_AUX_LEXICAL_CAST_DEF(unsigned long) +#if defined(BOOST_HAS_LONG_LONG) + BOOST_AUX_LEXICAL_CAST_DEF(boost::ulong_long_type) + BOOST_AUX_LEXICAL_CAST_DEF(boost::long_long_type ) +#elif defined(BOOST_HAS_MS_INT64) + BOOST_AUX_LEXICAL_CAST_DEF(unsigned __int64) + BOOST_AUX_LEXICAL_CAST_DEF( __int64) +#endif + +#undef BOOST_AUX_LEXICAL_CAST_DEF +#undef BOOST_AUX_LEXICAL_CAST_DEF1 + +#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION +// This #if is in sync with lcast_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 DISABLE_WIDE_CHAR_SUPPORT + 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 DISABLE_WIDE_CHAR_SUPPORT +#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 DISABLE_WIDE_CHAR_SUPPORT + 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 ) +#endif + + inline unsigned int lcast_to_unsigned(int value) + { + unsigned int uval = value; + return value < 0 ? -uval : uval; + } + + inline unsigned long lcast_to_unsigned(long value) + { + unsigned long uval = value; + return value < 0 ? -uval : uval; + } + +#if defined(BOOST_HAS_LONG_LONG) + inline boost::ulong_long_type lcast_to_unsigned(boost::long_long_type v) + { + boost::ulong_long_type uval = v; + return v < 0 ? -uval : uval; + } +#elif defined(BOOST_HAS_MS_INT64) + inline unsigned __int64 lcast_to_unsigned(__int64 value) + { + unsigned __int64 uval = value; + return value < 0 ? -uval : uval; + } +#endif + +#if (defined _MSC_VER) +# pragma warning( pop ) // C4146: unary minus operator applied to unsigned type, + // result still unsigned +#endif + } + + namespace detail // lcast_put_unsigned + { + // I'd personally put lcast_put_unsigned in .cpp file if not + // boost practice for header-only libraries (Alexander Nasonov). + template + CharT* lcast_put_unsigned(T n, CharT* finish) + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); +#endif + CharT thousands_sep = 0; + +#ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + char const* grouping = ""; + std::size_t const grouping_size = 0; +#else + std::locale loc; + 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(); + + if(grouping_size) + thousands_sep = np.thousands_sep(); +#endif + + 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; + + do + { + 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; + *finish = thousands_sep; + } + + --left; + --finish; + int const digit = static_cast(n % 10); + int const cdigit = digit + lcast_char_constants::zero; + *finish = static_cast(cdigit); + n /= 10; + } while(n); + + return finish; + } + } + namespace detail // stream wrapper for handling lexical conversions { template @@ -131,14 +524,10 @@ namespace boost typename stream_char::type>::type char_type; public: - lexical_stream() + lexical_stream(char_type* = 0, char_type* = 0) { stream.unsetf(std::ios::skipws); - - if(std::numeric_limits::is_specialized) - stream.precision(std::numeric_limits::digits10 + 1); - else if(std::numeric_limits::is_specialized) - stream.precision(std::numeric_limits::digits10 + 1); + lcast_set_precision(stream, (Source*)0, (Target*)0); } ~lexical_stream() { @@ -171,13 +560,13 @@ namespace boost #if defined(BOOST_NO_STRINGSTREAM) stream << '\0'; #endif - output = stream.str(); + stream.str().swap(output); return true; } #ifndef DISABLE_WIDE_CHAR_SUPPORT bool operator>>(std::wstring &output) { - output = stream.str(); + stream.str().swap(output); return true; } #endif @@ -192,6 +581,419 @@ namespace boost }; } + 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 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) + { + *p = ch; + } + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + static void widen_and_assign(wchar_t* p, char ch) + { + std::locale loc; + *p = BOOST_USE_FACET(std::ctype, loc).widen(ch); + } + + static void widen_and_assign(wchar_t* p, wchar_t ch) + { + *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)); + 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* start, CharT* finish) + : start(start) + , finish(finish) + {} + + 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(DISABLE_WIDE_CHAR_SUPPORT) && !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)); + 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 + std::char_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 DISABLE_WIDE_CHAR_SUPPORT + 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) + { + *start = value + lcast_char_constants::zero; + 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(DISABLE_WIDE_CHAR_SUPPORT) && !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); + if(n < 0) + *--start = lcast_char_constants::minus; + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<(int n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + *--start = lcast_char_constants::minus; + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<(long n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + *--start = lcast_char_constants::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); + if(n < 0) + *--start = lcast_char_constants::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); + if(n < 0) + *--start = lcast_char_constants::minus; + return true; + } +#endif + + template + inline bool lexical_stream_limited_src::operator<<( + unsigned short n) + { + start = lcast_put_unsigned(+n, finish); + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<( + unsigned int n) + { + start = lcast_put_unsigned(n, finish); + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<( + unsigned long n) + { + start = lcast_put_unsigned(n, finish); + 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); + 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); + 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 + std::char_traits::length(str); + return true; + } + + template + inline bool lexical_stream_limited_src::operator>>( + CharT& output) + { + bool const ok = (finish - start == 1); + if(ok) + 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 DISABLE_WIDE_CHAR_SUPPORT + 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(DISABLE_WIDE_CHAR_SUPPORT) && !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 DISABLE_WIDE_CHAR_SUPPORT + 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 DISABLE_WIDE_CHAR_SUPPORT + 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 @@ -209,19 +1011,64 @@ namespace boost { 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) + { + 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); + + // 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; + } + throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); + return Target(); // normally never reached (throw_exception) + } } template - Target lexical_cast(const Source &arg) + inline Target lexical_cast(const Source &arg) { - typedef typename detail::array_to_pointer_decay::type NewSource; + typedef typename detail::array_to_pointer_decay::type src; - detail::lexical_stream interpreter; - Target result; + typedef typename detail::widest_char< + typename detail::stream_char::type + , typename detail::stream_char::type + >::type char_type; - if(!(interpreter << arg && interpreter >> result)) - throw_exception(bad_lexical_cast(typeid(NewSource), typeid(Target))); - return result; + 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); } #else @@ -242,7 +1089,8 @@ namespace boost #endif } -// Copyright Kevlin Henney, 2000-2005. All rights reserved. +// 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