mirror of
https://github.com/boostorg/conversion.git
synced 2026-08-06 21:44:08 +02:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 063feb705c | |||
| 5b6e39b2b8 | |||
| 04f73e5a89 | |||
| 65328d9716 | |||
| dc151d2b5a | |||
| 23949682c1 | |||
| 5055e842cf | |||
| 9e764f3e49 | |||
| a3e690da32 | |||
| fb681bb0ea | |||
| 98a67d93f3 |
Executable → Regular
@@ -41,12 +41,17 @@
|
||||
#include <sstream>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_STRINGSTREAM) || \
|
||||
defined(BOOST_NO_STD_WSTRING) || \
|
||||
defined(BOOST_NO_STD_LOCALE)
|
||||
#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
|
||||
@@ -60,15 +65,21 @@ namespace boost
|
||||
{
|
||||
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;
|
||||
@@ -77,6 +88,7 @@ namespace boost
|
||||
{
|
||||
return *target;
|
||||
}
|
||||
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
return "bad lexical cast: "
|
||||
@@ -570,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()
|
||||
{
|
||||
@@ -687,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;
|
||||
@@ -757,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
|
||||
@@ -1104,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
|
||||
@@ -1129,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>
|
||||
@@ -1183,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;
|
||||
}
|
||||
|
||||
|
||||
+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