lcast_put_unsigned in lexical_cast.hpp header is refactored, duplicate code removed (refs #9046)

[SVN r85499]
This commit is contained in:
Antony Polukhin
2013-08-28 12:55:09 +00:00
parent a2299ec1f9
commit 297b115e6c

View File

@@ -635,7 +635,7 @@ namespace boost {
{ {
template<class T> template<class T>
inline inline
BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value) BOOST_NOEXCEPT BOOST_DEDUCED_TYPENAME boost::make_unsigned<T>::type lcast_to_unsigned(const T value) BOOST_NOEXCEPT
{ {
typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned<T>::type result_type; typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned<T>::type result_type;
return static_cast<result_type>( return static_cast<result_type>(
@@ -646,81 +646,89 @@ namespace boost {
namespace detail // lcast_put_unsigned namespace detail // lcast_put_unsigned
{ {
template<class Traits, class T, class CharT> template <class Traits, class T, class CharT>
CharT* lcast_put_unsigned(const T n_param, CharT* finish) class lcast_put_unsigned {
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
#endif
typedef BOOST_DEDUCED_TYPENAME Traits::int_type int_type; typedef BOOST_DEDUCED_TYPENAME Traits::int_type int_type;
CharT const czero = lcast_char_constants<CharT>::zero;
int_type const zero = Traits::to_int_type(czero);
BOOST_DEDUCED_TYPENAME boost::mpl::if_c< BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
(sizeof(int_type) > sizeof(T)) (sizeof(int_type) > sizeof(T))
, int_type , int_type
, T , T
>::type n = n_param; >::type m_value;
CharT* m_finish;
CharT const m_czero;
int_type const m_zero;
public:
lcast_put_unsigned(const T n_param, CharT* finish) BOOST_NOEXCEPT
: m_value(n_param), m_finish(finish)
, m_czero(lcast_char_constants<CharT>::zero), m_zero(Traits::to_int_type(m_czero))
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
#endif
}
CharT* convert() {
#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
std::locale loc; std::locale loc;
if (loc != std::locale::classic()) { if (loc == std::locale::classic()) {
return main_convert_loop();
}
typedef std::numpunct<CharT> numpunct; typedef std::numpunct<CharT> numpunct;
numpunct const& np = BOOST_USE_FACET(numpunct, loc); numpunct const& np = BOOST_USE_FACET(numpunct, loc);
std::string const grouping = np.grouping(); std::string const grouping = np.grouping();
std::string::size_type const grouping_size = grouping.size(); std::string::size_type const grouping_size = grouping.size();
if ( grouping_size && grouping[0] > 0 ) if (!grouping_size || grouping[0] <= 0) {
{ return main_convert_loop();
}
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
// Check that ulimited group is unreachable: // Check that ulimited group is unreachable:
BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX); BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
#endif #endif
CharT thousands_sep = np.thousands_sep(); CharT const thousands_sep = np.thousands_sep();
std::string::size_type group = 0; // current group number std::string::size_type group = 0; // current group number
char last_grp_size = grouping[0]; char last_grp_size = grouping[0];
char left = last_grp_size; char left = last_grp_size;
do do {
{ if (left == 0) {
if(left == 0) ++group;
{ if (group < grouping_size) {
++group; char const grp_size = grouping[group];
if(group < grouping_size) last_grp_size = (grp_size <= 0 ? static_cast<char>(CHAR_MAX) : grp_size);
{
char const grp_size = grouping[group];
last_grp_size = grp_size <= 0 ? static_cast<char>(CHAR_MAX) : grp_size;
}
left = last_grp_size;
--finish;
Traits::assign(*finish, thousands_sep);
} }
--left; left = last_grp_size;
--m_finish;
Traits::assign(*m_finish, thousands_sep);
}
--finish; --left;
int_type const digit = static_cast<int_type>(n % 10U); } while (main_convert_itaration());
Traits::assign(*finish, Traits::to_char_type(zero + digit));
n /= 10; return m_finish;
} while(n); #else
return finish; return main_convert_loop();
}
}
#endif #endif
{
do
{
--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; private:
} inline bool main_convert_itaration() BOOST_NOEXCEPT {
--m_finish;
int_type const digit = static_cast<int_type>(m_value % 10U);
Traits::assign(*m_finish, Traits::to_char_type(m_zero + digit));
m_value /= 10;
return !!m_value; // supressing warnings
}
inline CharT* main_convert_loop() BOOST_NOEXCEPT {
while (main_convert_itaration());
return m_finish;
}
};
} }
namespace detail // lcast_ret_unsigned namespace detail // lcast_ret_unsigned
@@ -1504,11 +1512,16 @@ namespace boost {
} }
template <class T> template <class T>
inline bool shl_signed(T n) inline bool shl_unsigned(const T n) {
{ start = lcast_put_unsigned<Traits, T, CharT>(n, finish).convert();
start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish); return true;
if(n < 0) }
{
template <class T>
inline bool shl_signed(const T n) {
typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned<T>::type utype;
start = lcast_put_unsigned<Traits, utype, CharT>(lcast_to_unsigned(n), finish).convert();
if (n < 0) {
--start; --start;
CharT const minus = lcast_char_constants<CharT>::minus; CharT const minus = lcast_char_constants<CharT>::minus;
Traits::assign(*start, minus); Traits::assign(*start, minus);
@@ -1697,20 +1710,20 @@ namespace boost {
bool operator<<(short n) { return shl_signed(n); } bool operator<<(short n) { return shl_signed(n); }
bool operator<<(int n) { return shl_signed(n); } bool operator<<(int n) { return shl_signed(n); }
bool operator<<(long n) { return shl_signed(n); } bool operator<<(long n) { return shl_signed(n); }
bool operator<<(unsigned short n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } bool operator<<(unsigned short n) { return shl_unsigned(n); }
bool operator<<(unsigned int n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } bool operator<<(unsigned int n) { return shl_unsigned(n); }
bool operator<<(unsigned long n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } bool operator<<(unsigned long n) { return shl_unsigned(n); }
#if defined(BOOST_HAS_LONG_LONG) #if defined(BOOST_HAS_LONG_LONG)
bool operator<<(boost::ulong_long_type n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } bool operator<<(boost::ulong_long_type n) { return shl_unsigned(n); }
bool operator<<(boost::long_long_type n) { return shl_signed(n); } bool operator<<(boost::long_long_type n) { return shl_signed(n); }
#elif defined(BOOST_HAS_MS_INT64) #elif defined(BOOST_HAS_MS_INT64)
bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } bool operator<<(unsigned __int64 n) { return shl_unsigned(n); }
bool operator<<( __int64 n) { return shl_signed(n); } bool operator<<( __int64 n) { return shl_signed(n); }
#endif #endif
#ifdef BOOST_HAS_INT128 #ifdef BOOST_HAS_INT128
bool operator<<(const boost::uint128_type& n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } bool operator<<(const boost::uint128_type& n) { return shl_unsigned(n); }
bool operator<<(const boost::int128_type& n) { return shl_signed(n); } bool operator<<(const boost::int128_type& n) { return shl_signed(n); }
#endif #endif