mirror of
https://github.com/boostorg/conversion.git
synced 2026-08-06 13:34:14 +02:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 21ab509eca | |||
| 5b6e39b2b8 | |||
| 04f73e5a89 | |||
| 65328d9716 | |||
| dc151d2b5a | |||
| 23949682c1 | |||
| 5055e842cf | |||
| 9e764f3e49 | |||
| a3e690da32 | |||
| fb681bb0ea | |||
| 98a67d93f3 | |||
| 0c54d6a037 | |||
| 39329bc5b9 | |||
| 2ce20c872e |
@@ -123,7 +123,7 @@ void f( Fruit * fruit ) {
|
||||
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>.<code><br>
|
||||
An old
|
||||
numeric_cast</code> that was contributed by <a href=
|
||||
"http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/index.html">Boost Numeric Conversion Library</a></p>
|
||||
"http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/html/index.html">Boost Numeric Conversion Library</a></p>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
|
||||
Executable → Regular
+113
-105
@@ -17,17 +17,23 @@
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <istream>
|
||||
#include <locale>
|
||||
#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>
|
||||
@@ -35,28 +41,45 @@
|
||||
#include <sstream>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_STRINGSTREAM) || \
|
||||
defined(BOOST_NO_STD_WSTRING) || \
|
||||
defined(BOOST_NO_STD_LOCALE)
|
||||
#define DISABLE_WIDE_CHAR_SUPPORT
|
||||
#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() :
|
||||
source(&typeid(void)), target(&typeid(void))
|
||||
#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;
|
||||
@@ -65,6 +88,7 @@ namespace boost
|
||||
{
|
||||
return *target;
|
||||
}
|
||||
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
return "bad lexical cast: "
|
||||
@@ -94,7 +118,7 @@ namespace boost
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
||||
template<>
|
||||
struct stream_char<wchar_t>
|
||||
@@ -219,7 +243,7 @@ namespace boost
|
||||
// lcast_src_length<char, signed char const*>
|
||||
// lcast_src_length<char, unsigned char const*>
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template<>
|
||||
struct lcast_src_length<wchar_t, bool>
|
||||
{
|
||||
@@ -258,7 +282,7 @@ namespace boost
|
||||
static void check_coverage() {}
|
||||
};
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template<>
|
||||
struct lcast_src_length<wchar_t, wchar_t const*>
|
||||
{
|
||||
@@ -289,7 +313,7 @@ namespace boost
|
||||
static void check_coverage() {}
|
||||
};
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template<>
|
||||
struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
|
||||
{
|
||||
@@ -327,34 +351,35 @@ namespace boost
|
||||
#endif
|
||||
};
|
||||
|
||||
#define BOOST_AUX_LEXICAL_CAST_DEF1(CharT, T) template<> \
|
||||
struct lcast_src_length<CharT, T> : lcast_src_length_integral<T> \
|
||||
#define BOOST_LCAST_DEF1(CharT, T) \
|
||||
template<> struct lcast_src_length<CharT, T> \
|
||||
: lcast_src_length_integral<T> \
|
||||
{ static void check_coverage() {} };
|
||||
|
||||
#ifdef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#define BOOST_AUX_LEXICAL_CAST_DEF(T) BOOST_AUX_LEXICAL_CAST_DEF1(char, T)
|
||||
#ifdef BOOST_LCAST_NO_WCHAR_T
|
||||
#define BOOST_LCAST_DEF(T) BOOST_LCAST_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)
|
||||
#define BOOST_LCAST_DEF(T) \
|
||||
BOOST_LCAST_DEF1(char, T) \
|
||||
BOOST_LCAST_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)
|
||||
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_AUX_LEXICAL_CAST_DEF(boost::ulong_long_type)
|
||||
BOOST_AUX_LEXICAL_CAST_DEF(boost::long_long_type )
|
||||
BOOST_LCAST_DEF(boost::ulong_long_type)
|
||||
BOOST_LCAST_DEF(boost::long_long_type )
|
||||
#elif defined(BOOST_HAS_MS_INT64)
|
||||
BOOST_AUX_LEXICAL_CAST_DEF(unsigned __int64)
|
||||
BOOST_AUX_LEXICAL_CAST_DEF( __int64)
|
||||
BOOST_LCAST_DEF(unsigned __int64)
|
||||
BOOST_LCAST_DEF( __int64)
|
||||
#endif
|
||||
|
||||
#undef BOOST_AUX_LEXICAL_CAST_DEF
|
||||
#undef BOOST_AUX_LEXICAL_CAST_DEF1
|
||||
#undef BOOST_LCAST_DEF
|
||||
#undef BOOST_LCAST_DEF1
|
||||
|
||||
#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
// Helper for floating point types.
|
||||
@@ -400,7 +425,7 @@ namespace boost
|
||||
static void check_coverage() {}
|
||||
};
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template<>
|
||||
struct lcast_src_length<wchar_t,float>
|
||||
: lcast_src_length_floating<float>
|
||||
@@ -422,7 +447,7 @@ namespace boost
|
||||
static void check_coverage() {}
|
||||
};
|
||||
|
||||
#endif // #ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#endif // #ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
#endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
}
|
||||
|
||||
@@ -437,7 +462,7 @@ namespace boost
|
||||
BOOST_STATIC_CONSTANT(char, minus = '-');
|
||||
};
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template<>
|
||||
struct lcast_char_constants<wchar_t>
|
||||
{
|
||||
@@ -460,37 +485,21 @@ namespace boost
|
||||
# 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
|
||||
|
||||
inline unsigned int lcast_to_unsigned(int value)
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
|
||||
{
|
||||
unsigned int uval = value;
|
||||
return value < 0 ? -uval : uval;
|
||||
typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
|
||||
result_type uvalue = static_cast<result_type>(value);
|
||||
return value < 0 ? -uvalue : uvalue;
|
||||
}
|
||||
|
||||
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
|
||||
# pragma warning( pop )
|
||||
#elif defined( __BORLANDC__ )
|
||||
# pragma option pop
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -502,22 +511,15 @@ namespace boost
|
||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||
BOOST_STATIC_ASSERT(!std::numeric_limits<T>::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
|
||||
#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();
|
||||
|
||||
if(grouping_size)
|
||||
thousands_sep = np.thousands_sep();
|
||||
#endif
|
||||
|
||||
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.
|
||||
@@ -526,14 +528,17 @@ namespace boost
|
||||
#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);
|
||||
|
||||
char left = last_grp_size;
|
||||
|
||||
do
|
||||
{
|
||||
#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
|
||||
if(left == 0)
|
||||
{
|
||||
++group;
|
||||
@@ -549,6 +554,8 @@ namespace boost
|
||||
}
|
||||
|
||||
--left;
|
||||
#endif
|
||||
|
||||
--finish;
|
||||
int_type const digit = static_cast<int_type>(n % 10U);
|
||||
Traits::assign(*finish, Traits::to_char_type(zero + digit));
|
||||
@@ -575,7 +582,7 @@ namespace boost
|
||||
lexical_stream(char_type* = 0, char_type* = 0)
|
||||
{
|
||||
stream.unsetf(std::ios::skipws);
|
||||
lcast_set_precision(stream, (Source*)0, (Target*)0);
|
||||
lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
|
||||
}
|
||||
~lexical_stream()
|
||||
{
|
||||
@@ -614,7 +621,7 @@ namespace boost
|
||||
stream.str().swap(output);
|
||||
return true;
|
||||
}
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
bool operator>>(std::wstring &output)
|
||||
{
|
||||
stream.str().swap(output);
|
||||
@@ -670,9 +677,10 @@ namespace boost
|
||||
Traits::assign(*p, ch);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#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);
|
||||
@@ -691,7 +699,7 @@ namespace boost
|
||||
{
|
||||
this->setp(start, finish);
|
||||
std::basic_ostream<CharT> stream(static_cast<Base*>(this));
|
||||
lcast_set_precision(stream, (OutputStreamable*)0);
|
||||
lcast_set_precision(stream, static_cast<OutputStreamable*>(0));
|
||||
bool const result = !(stream << input).fail();
|
||||
finish = this->pptr();
|
||||
return result;
|
||||
@@ -703,9 +711,9 @@ namespace boost
|
||||
|
||||
public:
|
||||
|
||||
lexical_stream_limited_src(CharT* start, CharT* finish)
|
||||
: start(start)
|
||||
, finish(finish)
|
||||
lexical_stream_limited_src(CharT* sta, CharT* fin)
|
||||
: start(sta)
|
||||
, finish(fin)
|
||||
{}
|
||||
|
||||
public: // output
|
||||
@@ -720,7 +728,7 @@ namespace boost
|
||||
|
||||
bool operator<<(bool);
|
||||
bool operator<<(char);
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
bool operator<<(wchar_t);
|
||||
#endif
|
||||
bool operator<<(CharT const*);
|
||||
@@ -761,7 +769,7 @@ namespace boost
|
||||
this->setg(start, start, finish);
|
||||
std::basic_istream<CharT> stream(static_cast<Base*>(this));
|
||||
stream.unsetf(std::ios::skipws);
|
||||
lcast_set_precision(stream, (InputStreamable*)0);
|
||||
lcast_set_precision(stream, static_cast<InputStreamable*>(0));
|
||||
#if (defined _MSC_VER)
|
||||
# pragma warning( pop )
|
||||
#endif
|
||||
@@ -785,7 +793,7 @@ namespace boost
|
||||
|
||||
bool operator>>(std::string&);
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
bool operator>>(std::wstring&);
|
||||
#endif
|
||||
|
||||
@@ -820,7 +828,7 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
#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)
|
||||
@@ -907,7 +915,7 @@ namespace boost
|
||||
inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
|
||||
unsigned short n)
|
||||
{
|
||||
start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
|
||||
start = lcast_put_unsigned<Traits>(n, finish);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -994,7 +1002,7 @@ namespace boost
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#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)
|
||||
@@ -1049,7 +1057,7 @@ namespace boost
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
template<>
|
||||
struct lcast_streambuf_for_target<wchar_t>
|
||||
{
|
||||
@@ -1065,7 +1073,7 @@ namespace boost
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template<class Traits, class Alloc>
|
||||
struct lcast_streambuf_for_target<
|
||||
std::basic_string<wchar_t,Traits,Alloc> >
|
||||
@@ -1080,7 +1088,7 @@ namespace boost
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template<>
|
||||
struct lcast_streambuf_for_target<std::wstring>
|
||||
{
|
||||
@@ -1108,6 +1116,12 @@ namespace boost
|
||||
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
|
||||
@@ -1133,24 +1147,14 @@ namespace boost
|
||||
, detail::lexical_stream_limited_src<CharT,base,traits>
|
||||
>::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)
|
||||
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>
|
||||
@@ -1187,7 +1191,11 @@ namespace boost
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1201,5 +1209,5 @@ namespace boost
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#undef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#undef BOOST_LCAST_NO_WCHAR_T
|
||||
#endif
|
||||
|
||||
+3
-3
@@ -81,7 +81,7 @@
|
||||
conversions, such as where precision or formatting need tighter control than is
|
||||
offered by the default behavior of <code>lexical_cast</code>, the conventional <code>
|
||||
stringstream</code> approach is recommended. Where the conversions are
|
||||
numeric to numeric, <code><a href="../numeric/conversion/doc/numeric_cast.html">numeric_cast</a></code>
|
||||
numeric to numeric, <code><a href="../numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html">numeric_cast</a></code>
|
||||
may offer more reasonable behavior than <code>lexical_cast</code>.
|
||||
<p>
|
||||
For a good discussion of the options and issues involved in string-based
|
||||
@@ -202,9 +202,9 @@ public:
|
||||
Lexical conversion to these types is simply reading a byte from source but since the source has
|
||||
more than one byte, the exception is thrown.
|
||||
<p>Please use other integer types such as <code>int</code> or <code>short int</code>. If bounds checking
|
||||
is important, you can also call <a href="../../libs/numeric/conversion/doc/numeric_cast.html">numeric_cast</a>:
|
||||
is important, you can also call <a href="../../libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html">numeric_cast</a>:
|
||||
|
||||
<pre><a href="../../libs/numeric/conversion/doc/numeric_cast.html">numeric_cast</a><int8_t>(lexical_cast<int>("127"));</pre>
|
||||
<pre><a href="../../libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html">numeric_cast</a><int8_t>(lexical_cast<int>("127"));</pre>
|
||||
|
||||
<p> Q: What does <code>lexical_cast<std::string></code> of an <code>int8_t</code> or <code>uint8_t</code> not do what I expect?
|
||||
<br> A: As above, note that <code>int8_t</code> and <code>uint8_t</code> are actually chars and are formatted as such. To avoid this, cast to an integer type first:
|
||||
|
||||
+66
-34
@@ -21,18 +21,13 @@
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/floating_point_comparison.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#if defined(BOOST_NO_STRINGSTREAM) || \
|
||||
defined(BOOST_NO_STD_WSTRING) || \
|
||||
defined(BOOST_NO_STD_LOCALE)
|
||||
#define DISABLE_WIDE_CHAR_SUPPORT
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \
|
||||
&& !(defined(BOOST_MSVC) && BOOST_MSVC < 1300)
|
||||
#define LCAST_TEST_LONGLONG
|
||||
@@ -76,6 +71,8 @@ void test_conversion_from_to_int();
|
||||
void test_conversion_from_to_uint();
|
||||
void test_conversion_from_to_long();
|
||||
void test_conversion_from_to_ulong();
|
||||
void test_conversion_from_to_intmax_t();
|
||||
void test_conversion_from_to_uintmax_t();
|
||||
#ifdef LCAST_TEST_LONGLONG
|
||||
void test_conversion_from_to_longlong();
|
||||
void test_conversion_from_to_ulonglong();
|
||||
@@ -98,30 +95,32 @@ unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_to_pointer));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_to_string));
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_from_wchar_t));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_to_wchar_t));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_from_wstring));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_to_wstring));
|
||||
#endif
|
||||
#endif
|
||||
suite->add(BOOST_TEST_CASE(test_bad_lexical_cast));
|
||||
suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_short));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ushort));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long));
|
||||
#ifdef LCAST_TEST_LONGLONG
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_intmax_t));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uintmax_t));
|
||||
#ifdef LCAST_TEST_LONGLONG
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong));
|
||||
#endif
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#endif
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
suite->add(BOOST_TEST_CASE(&test_traits));
|
||||
suite->add(BOOST_TEST_CASE(&test_wtraits));
|
||||
suite->add(BOOST_TEST_CASE(&test_allocator));
|
||||
suite->add(BOOST_TEST_CASE(&test_wallocator));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -263,14 +262,14 @@ void test_conversion_from_to_wchar_t_alias()
|
||||
void test_conversion_to_pointer()
|
||||
{
|
||||
BOOST_CHECK_THROW(lexical_cast<char *>("Test"), bad_lexical_cast);
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), bad_lexical_cast);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_conversion_from_wchar_t()
|
||||
{
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_CHECK_EQUAL(1, lexical_cast<int>(L'1'));
|
||||
BOOST_CHECK_THROW(lexical_cast<int>(L'A'), bad_lexical_cast);
|
||||
@@ -303,7 +302,7 @@ void test_conversion_from_wchar_t()
|
||||
|
||||
void test_conversion_to_wchar_t()
|
||||
{
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(1));
|
||||
BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(0));
|
||||
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>('1'));
|
||||
@@ -325,12 +324,12 @@ void test_conversion_to_wchar_t()
|
||||
lexical_cast<wchar_t>(std::wstring(L"")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<wchar_t>(std::wstring(L"Test")), bad_lexical_cast);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_conversion_from_wstring()
|
||||
{
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
BOOST_CHECK_EQUAL(123, lexical_cast<int>(std::wstring(L"123")));
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<int>(std::wstring(L"")), bad_lexical_cast);
|
||||
@@ -343,12 +342,12 @@ void test_conversion_from_wstring()
|
||||
lexical_cast<bool>(std::wstring(L"")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<bool>(std::wstring(L"Test")), bad_lexical_cast);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_conversion_to_wstring()
|
||||
{
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
wchar_t buf[] = L"hello";
|
||||
wchar_t* str = buf;
|
||||
BOOST_CHECK(str == lexical_cast<std::wstring>(str));
|
||||
@@ -368,7 +367,7 @@ void test_conversion_to_wstring()
|
||||
BOOST_CHECK(L"Test" == lexical_cast<std::wstring>(std::wstring(L"Test")));
|
||||
BOOST_CHECK(L" " == lexical_cast<std::wstring>(std::wstring(L" ")));
|
||||
BOOST_CHECK(L"" == lexical_cast<std::wstring>(std::wstring(L"")));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_bad_lexical_cast()
|
||||
@@ -522,27 +521,50 @@ template<class T, class CharT>
|
||||
void test_conversion_from_string_to_integral(CharT)
|
||||
{
|
||||
typedef std::numeric_limits<T> limits;
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
|
||||
T t;
|
||||
string_type s;
|
||||
string_type const zero = to_str<CharT>(0);
|
||||
string_type const nine = to_str<CharT>(9);
|
||||
T const min_val = (limits::min)();
|
||||
T const max_val = (limits::max)();
|
||||
|
||||
t = (limits::min)();
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
s = to_str<CharT>(min_val);
|
||||
BOOST_CHECK_EQUAL(lexical_cast<T>(s), min_val);
|
||||
if(limits::is_signed)
|
||||
{
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC == 1400
|
||||
// VC++ 8.0 bug, see libs/conversion/test/lexical_cast_vc8_bug_test.cpp
|
||||
if(sizeof(T) < sizeof(boost::intmax_t))
|
||||
#endif
|
||||
{
|
||||
BOOST_CHECK_THROW(lexical_cast<T>(s + zero), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<T>(s + nine), bad_lexical_cast);
|
||||
}
|
||||
}
|
||||
|
||||
t = (limits::max)();
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
s = to_str<CharT>(max_val);
|
||||
BOOST_CHECK_EQUAL(lexical_cast<T>(s), max_val);
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC == 1400
|
||||
// VC++ 8.0 bug, see libs/conversion/test/lexical_cast_vc8_bug_test.cpp
|
||||
if(sizeof(T) != sizeof(boost::intmax_t))
|
||||
#endif
|
||||
{
|
||||
BOOST_CHECK_THROW(lexical_cast<T>(s + zero), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<T>(s + nine), bad_lexical_cast);
|
||||
}
|
||||
|
||||
if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
|
||||
// min and max have already been tested.
|
||||
for(t = 1 + (limits::min)(); t != (limits::max)(); ++t)
|
||||
for(T t = 1 + min_val; t != max_val; ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
else
|
||||
{
|
||||
T const min_val = (limits::min)();
|
||||
T const max_val = (limits::max)();
|
||||
T const half_max_val = max_val / 2;
|
||||
T const cnt = lcast_integral_test_counter; // to supress warnings
|
||||
unsigned int const counter = cnt < half_max_val ? cnt : half_max_val;
|
||||
|
||||
T t;
|
||||
unsigned int i;
|
||||
|
||||
// Test values around min:
|
||||
@@ -577,7 +599,7 @@ void test_conversion_from_to_integral_for_locale()
|
||||
test_conversion_from_integral_to_integral<T>();
|
||||
test_conversion_from_integral_to_string<T>('0');
|
||||
test_conversion_from_string_to_integral<T>('0');
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
#if !defined(BOOST_LCAST_NO_WCHAR_T)
|
||||
test_conversion_from_integral_to_string<T>(L'0');
|
||||
test_conversion_from_string_to_integral<T>(L'0');
|
||||
#endif
|
||||
@@ -598,7 +620,7 @@ void test_conversion_from_to_integral()
|
||||
test_conversion_from_integral_to_char<T>(zero);
|
||||
test_conversion_from_integral_to_char<T>(szero);
|
||||
test_conversion_from_integral_to_char<T>(uzero);
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
wchar_t const wzero = L'0';
|
||||
test_conversion_from_integral_to_char<T>(wzero);
|
||||
#endif
|
||||
@@ -656,14 +678,24 @@ void test_conversion_from_to_uint()
|
||||
test_conversion_from_to_integral<unsigned int>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_long()
|
||||
{
|
||||
test_conversion_from_to_integral<long>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ulong()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned long>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_long()
|
||||
void test_conversion_from_to_intmax_t()
|
||||
{
|
||||
test_conversion_from_to_integral<long>();
|
||||
test_conversion_from_to_integral<boost::intmax_t>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_uintmax_t()
|
||||
{
|
||||
test_conversion_from_to_integral<boost::uintmax_t>();
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_LONG_LONG)
|
||||
|
||||
@@ -24,6 +24,7 @@ test-suite conversion
|
||||
[ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_noncopyable_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_vc8_bug_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
// See also test_conversion_from_string_to_integral(CharT)
|
||||
// in libs/conversion/lexical_cast_test.cpp
|
||||
template<class T, class CharT>
|
||||
void test_too_long_number(CharT zero)
|
||||
{
|
||||
typedef std::numeric_limits<T> limits;
|
||||
|
||||
std::basic_string<CharT> s;
|
||||
|
||||
std::basic_ostringstream<CharT> o;
|
||||
o << (limits::max)() << zero;
|
||||
s = o.str();
|
||||
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
|
||||
s[s.size()-1] += 9; // '0' -> '9'
|
||||
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
|
||||
|
||||
if(limits::is_signed)
|
||||
{
|
||||
std::basic_ostringstream<CharT> o;
|
||||
o << (limits::min)() << zero;
|
||||
s = o.str();
|
||||
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
|
||||
s[s.size()-1] += 9; // '0' -> '9'
|
||||
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
|
||||
}
|
||||
}
|
||||
|
||||
void test_vc8_bug()
|
||||
{
|
||||
test_too_long_number<boost::intmax_t>('0');
|
||||
test_too_long_number<boost::uintmax_t>('0');
|
||||
#if !defined(BOOST_LCAST_NO_WCHAR_T)
|
||||
test_too_long_number<boost::intmax_t>(L'0');
|
||||
test_too_long_number<boost::uintmax_t>(L'0');
|
||||
#endif
|
||||
}
|
||||
|
||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
{
|
||||
unit_test_framework::test_suite *suite =
|
||||
BOOST_TEST_SUITE("lexical_cast vc8 bug unit test");
|
||||
suite->add(BOOST_TEST_CASE(test_vc8_bug));
|
||||
return suite;
|
||||
}
|
||||
Reference in New Issue
Block a user