forked from boostorg/conversion
Merge from trunk (now lexical_cast has optimized conversions to and from array<>, fixes #7065)
[SVN r79364]
This commit is contained in:
+193
-38
@@ -69,12 +69,12 @@ namespace boost
|
||||
{
|
||||
// exception used to indicate runtime lexical_cast failure
|
||||
class BOOST_SYMBOL_VISIBLE bad_lexical_cast :
|
||||
// workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
|
||||
#if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
|
||||
public std::exception
|
||||
#else
|
||||
public std::bad_cast
|
||||
#endif
|
||||
// workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
|
||||
#if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
|
||||
public std::exception
|
||||
#else
|
||||
public std::bad_cast
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
|
||||
// under bcc32 5.5.1 bad_cast doesn't derive from exception
|
||||
@@ -134,10 +134,16 @@ namespace boost
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) && !defined(__PGIC__)
|
||||
|
||||
#include <cmath>
|
||||
#include <istream>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
@@ -168,13 +174,13 @@ namespace boost {
|
||||
{
|
||||
typedef CharT type;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct widest_char< not_a_character_type, not_a_character_type >
|
||||
{
|
||||
typedef char type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail // is_char_or_wchar<...> and stream_char<...> templates
|
||||
{
|
||||
@@ -224,42 +230,68 @@ namespace boost {
|
||||
typedef char type;
|
||||
};
|
||||
|
||||
template<typename CharT>
|
||||
template <typename CharT>
|
||||
struct stream_char<CharT*>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
|
||||
};
|
||||
|
||||
template<typename CharT>
|
||||
template <typename CharT>
|
||||
struct stream_char<const CharT*>
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
|
||||
};
|
||||
|
||||
template<typename CharT>
|
||||
template <typename CharT>
|
||||
struct stream_char<iterator_range<CharT*> >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT*>::type type;
|
||||
};
|
||||
|
||||
template<typename CharT>
|
||||
|
||||
template <typename CharT>
|
||||
struct stream_char<iterator_range<const CharT*> >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME stream_char<const CharT*>::type type;
|
||||
};
|
||||
|
||||
template<class CharT, class Traits, class Alloc>
|
||||
template <class CharT, class Traits, class Alloc>
|
||||
struct stream_char< std::basic_string<CharT, Traits, Alloc> >
|
||||
{
|
||||
typedef CharT type;
|
||||
};
|
||||
|
||||
template<class CharT, class Traits, class Alloc>
|
||||
template <class CharT, class Traits, class Alloc>
|
||||
struct stream_char< ::boost::container::basic_string<CharT, Traits, Alloc> >
|
||||
{
|
||||
typedef CharT type;
|
||||
};
|
||||
|
||||
template<typename CharT, std::size_t N>
|
||||
struct stream_char<boost::array<CharT, N> >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
|
||||
};
|
||||
|
||||
template<typename CharT, std::size_t N>
|
||||
struct stream_char<boost::array<const CharT, N> >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
|
||||
template <typename CharT, std::size_t N>
|
||||
struct stream_char<std::array<CharT, N> >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
|
||||
};
|
||||
|
||||
template <typename CharT, std::size_t N>
|
||||
struct stream_char<std::array<const CharT, N> >
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type;
|
||||
};
|
||||
#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
|
||||
|
||||
#if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
template<>
|
||||
struct stream_char<wchar_t>
|
||||
@@ -430,7 +462,7 @@ namespace boost {
|
||||
// -1.23456789e-123456
|
||||
// ^ sign
|
||||
// ^ leading digit
|
||||
// ^ decimal point
|
||||
// ^ decimal point
|
||||
// ^^^^^^^^ lcast_precision<Source>::value
|
||||
// ^ "e"
|
||||
// ^ exponent sign
|
||||
@@ -1259,7 +1291,6 @@ namespace boost {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template <class T>
|
||||
bool shl_char_array(T const* str)
|
||||
{
|
||||
@@ -1268,7 +1299,13 @@ namespace boost {
|
||||
"Use boost::locale instead" );
|
||||
return shl_input_streamable(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool shl_char_array_limited(CharT const* str, std::size_t max_size)
|
||||
{
|
||||
start = const_cast<CharT*>(str);
|
||||
finish = std::find(start, start + max_size, static_cast<CharT>(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InputStreamable>
|
||||
bool shl_input_streamable(InputStreamable& input)
|
||||
@@ -1403,14 +1440,14 @@ namespace boost {
|
||||
{
|
||||
start = rng.begin();
|
||||
finish = rng.end();
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool operator<<(const iterator_range<const CharT*>& rng)
|
||||
{
|
||||
start = const_cast<CharT*>(rng.begin());
|
||||
finish = const_cast<CharT*>(rng.end());
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator<<(const iterator_range<const signed char*>& rng)
|
||||
@@ -1494,8 +1531,58 @@ namespace boost {
|
||||
return shl_real_type(static_cast<double>(val), start, finish);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(boost::array<CharT, N> const& input)
|
||||
{ return shl_char_array_limited(input.begin(), N); }
|
||||
|
||||
template<class InStreamable>
|
||||
template <std::size_t N>
|
||||
bool operator<<(boost::array<unsigned char, N> const& input)
|
||||
{ return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(boost::array<signed char, N> const& input)
|
||||
{ return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(boost::array<const CharT, N> const& input)
|
||||
{ return shl_char_array_limited(input.begin(), N); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(boost::array<const unsigned char, N> const& input)
|
||||
{ return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(boost::array<const signed char, N> const& input)
|
||||
{ return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
|
||||
template <std::size_t N>
|
||||
bool operator<<(std::array<CharT, N> const& input)
|
||||
{ return shl_char_array_limited(input.begin(), N); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(std::array<unsigned char, N> const& input)
|
||||
{ return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(std::array<signed char, N> const& input)
|
||||
{ return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(std::array<const CharT, N> const& input)
|
||||
{ return shl_char_array_limited(input.begin(), N); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(std::array<const unsigned char, N> const& input)
|
||||
{ return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator<<(std::array<const signed char, N> const& input)
|
||||
{ return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
|
||||
#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
|
||||
|
||||
template <class InStreamable>
|
||||
bool operator<<(const InStreamable& input) { return shl_input_streamable(input); }
|
||||
|
||||
/************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/
|
||||
@@ -1674,6 +1761,70 @@ namespace boost {
|
||||
template<class Alloc>
|
||||
bool operator>>(::boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
|
||||
|
||||
|
||||
private:
|
||||
template <std::size_t N, class ArrayT>
|
||||
bool shr_std_array(ArrayT& output, boost::mpl::bool_<true> /*is_T_char_tag*/)
|
||||
{
|
||||
using namespace std;
|
||||
const std::size_t size = finish - start;
|
||||
if (size > N - 1) { // `-1` because we need to store \0 at the end
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(output.begin(), start, size * sizeof(CharT));
|
||||
*(output.begin() + size) = static_cast<CharT>(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <std::size_t N, class ArrayT>
|
||||
bool shr_std_array(ArrayT& output, boost::mpl::bool_<false> /*is_T_char_tag*/)
|
||||
{
|
||||
return shr_using_base_class(output); // Array consist of non character types or unmatching character type
|
||||
}
|
||||
public:
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator>>(boost::array<CharT, N>& output)
|
||||
{
|
||||
typedef boost::mpl::bool_<true> tag_type;
|
||||
return shr_std_array<N>(output, tag_type());
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator>>(boost::array<unsigned char, N>& output)
|
||||
{
|
||||
return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output));
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator>>(boost::array<signed char, N>& output)
|
||||
{
|
||||
return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output));
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
|
||||
template <std::size_t N>
|
||||
bool operator>>(std::array<CharT, N>& output)
|
||||
{
|
||||
typedef boost::mpl::bool_<true> tag_type;
|
||||
return shr_std_array<N>(output, tag_type());
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator>>(std::array<unsigned char, N>& output)
|
||||
{
|
||||
return ((*this) >> reinterpret_cast<std::array<char, N>& >(output));
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
bool operator>>(std::array<signed char, N>& in)
|
||||
{
|
||||
return ((*this) >> reinterpret_cast<std::array<char, N>& >(output));
|
||||
}
|
||||
#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
|
||||
|
||||
|
||||
/*
|
||||
* case "-0" || "0" || "+0" : output = false; return true;
|
||||
* case "1" || "+1": output = true; return true;
|
||||
@@ -1857,11 +2008,11 @@ namespace boost {
|
||||
};
|
||||
|
||||
|
||||
// this metafunction evaluates to true, if we have optimized comnversion
|
||||
// from Float type to Char array.
|
||||
// this metafunction evaluates to true, if we have optimized comnversion
|
||||
// from Float type to Char array.
|
||||
// Must be in sync with lexical_stream_limited_src<Char, ...>::shl_real_type(...)
|
||||
template <typename Float, typename Char>
|
||||
struct is_this_float_conversion_optimized
|
||||
struct is_this_float_conversion_optimized
|
||||
{
|
||||
typedef ::boost::type_traits::ice_and<
|
||||
::boost::is_float<Float>::value,
|
||||
@@ -1937,11 +2088,6 @@ namespace boost {
|
||||
"Your compiler does not have full support for char32_t" );
|
||||
#endif
|
||||
|
||||
typedef detail::lcast_src_length<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();
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::deduce_char_traits<
|
||||
char_type, Target, Source
|
||||
>::type traits;
|
||||
@@ -1959,20 +2105,29 @@ namespace boost {
|
||||
::boost::detail::is_char_or_wchar<src_char_type >::value
|
||||
> is_source_input_optimized_t;
|
||||
|
||||
// Target type must be default constructible
|
||||
Target result;
|
||||
|
||||
// If we have an optimized conversion for
|
||||
// Source, we do not need to construct stringbuf.
|
||||
const bool requires_stringbuf = ::boost::type_traits::ice_or<
|
||||
is_string_widening_required_t::value,
|
||||
::boost::type_traits::ice_not< is_source_input_optimized_t::value >::value
|
||||
>::value;
|
||||
|
||||
typedef detail::lexical_stream_limited_src<char_type, traits, requires_stringbuf > interpreter_type;
|
||||
|
||||
detail::lexical_stream_limited_src<char_type, traits, requires_stringbuf >
|
||||
interpreter(buf, buf + src_len);
|
||||
typedef detail::lcast_src_length<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();
|
||||
|
||||
interpreter_type interpreter(buf, buf + src_len);
|
||||
|
||||
Target result;
|
||||
// Disabling ADL, by directly specifying operators.
|
||||
if(!(interpreter.operator <<(arg) && interpreter.operator >>(result)))
|
||||
BOOST_LCAST_THROW_BAD_CAST(Source, Target);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@@ -2252,10 +2407,10 @@ namespace boost {
|
||||
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 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;
|
||||
|
||||
Reference in New Issue
Block a user