t/casts: simplify trunc_cast, combine size_cast

This commit is contained in:
Danny Robson 2015-02-17 16:20:46 +11:00
parent 7ba92838df
commit c4df8bf905
2 changed files with 40 additions and 69 deletions

View File

@ -225,25 +225,25 @@ SHA1::digest (void) const {
CHECK_EQ (state, FINISHED); CHECK_EQ (state, FINISHED);
return { { return { {
size_cast<uint8_t> ((H[0] >> 24u) & 0xFF), trunc_cast<uint8_t> ((H[0] >> 24u) & 0xFF),
size_cast<uint8_t> ((H[0] >> 16u) & 0xFF), trunc_cast<uint8_t> ((H[0] >> 16u) & 0xFF),
size_cast<uint8_t> ((H[0] >> 8u) & 0xFF), trunc_cast<uint8_t> ((H[0] >> 8u) & 0xFF),
size_cast<uint8_t> ((H[0] ) & 0xFF), trunc_cast<uint8_t> ((H[0] ) & 0xFF),
size_cast<uint8_t> ((H[1] >> 24u) & 0xFF), trunc_cast<uint8_t> ((H[1] >> 24u) & 0xFF),
size_cast<uint8_t> ((H[1] >> 16u) & 0xFF), trunc_cast<uint8_t> ((H[1] >> 16u) & 0xFF),
size_cast<uint8_t> ((H[1] >> 8u) & 0xFF), trunc_cast<uint8_t> ((H[1] >> 8u) & 0xFF),
size_cast<uint8_t> ((H[1] ) & 0xFF), trunc_cast<uint8_t> ((H[1] ) & 0xFF),
size_cast<uint8_t> ((H[2] >> 24u) & 0xFF), trunc_cast<uint8_t> ((H[2] >> 24u) & 0xFF),
size_cast<uint8_t> ((H[2] >> 16u) & 0xFF), trunc_cast<uint8_t> ((H[2] >> 16u) & 0xFF),
size_cast<uint8_t> ((H[2] >> 8u) & 0xFF), trunc_cast<uint8_t> ((H[2] >> 8u) & 0xFF),
size_cast<uint8_t> ((H[2] ) & 0xFF), trunc_cast<uint8_t> ((H[2] ) & 0xFF),
size_cast<uint8_t> ((H[3] >> 24u) & 0xFF), trunc_cast<uint8_t> ((H[3] >> 24u) & 0xFF),
size_cast<uint8_t> ((H[3] >> 16u) & 0xFF), trunc_cast<uint8_t> ((H[3] >> 16u) & 0xFF),
size_cast<uint8_t> ((H[3] >> 8u) & 0xFF), trunc_cast<uint8_t> ((H[3] >> 8u) & 0xFF),
size_cast<uint8_t> ((H[3] ) & 0xFF), trunc_cast<uint8_t> ((H[3] ) & 0xFF),
size_cast<uint8_t> ((H[4] >> 24u) & 0xFF), trunc_cast<uint8_t> ((H[4] >> 24u) & 0xFF),
size_cast<uint8_t> ((H[4] >> 16u) & 0xFF), trunc_cast<uint8_t> ((H[4] >> 16u) & 0xFF),
size_cast<uint8_t> ((H[4] >> 8u) & 0xFF), trunc_cast<uint8_t> ((H[4] >> 8u) & 0xFF),
size_cast<uint8_t> ((H[4] ) & 0xFF) trunc_cast<uint8_t> ((H[4] ) & 0xFF)
} }; } };
} }

View File

@ -56,6 +56,7 @@ namespace detail {
{ return v; } { return v; }
} }
/// Safely cast a numeric type to its (un)signed counterpart, aborting if the /// Safely cast a numeric type to its (un)signed counterpart, aborting if the
/// dynamically checked result is not representable. May be optimised out if /// dynamically checked result is not representable. May be optimised out if
/// NDEBUG is defined. /// NDEBUG is defined.
@ -65,60 +66,29 @@ sign_cast (const V v)
{ return detail::_sign_cast<T,V>(v); } { return detail::_sign_cast<T,V>(v); }
//----------------------------------------------------------------------------- ///----------------------------------------------------------------------------
namespace detail { /// assert if the value cannot be cast loslessly from U to T, else return the
// Same sign, no possibility of truncation with larger target type /// converted value.Note: this is only a debug-time check and is compiled out
template <typename T, typename V> /// in optimised builds.
template <typename T, typename U>
T T
_trunc_cast (const typename std::enable_if<sizeof (T) >= sizeof (V) && trunc_cast (U u)
std::is_signed<T>::value == std::is_signed<V>::value, V>::type v) {
{ return v; } auto t = static_cast<T> (u);
if (u == u)
CHECK_EQ (t, u);
else
CHECK_NEQ (t, t);
return t;
template <typename T, typename V>
T
_trunc_cast (const typename std::enable_if<sizeof (T) < sizeof (V) &&
std::is_signed<T>::value == std::is_signed<V>::value &&
std::is_integral<T>::value, V>::type v) {
CHECK_LE (v, std::numeric_limits<T>::max ());
CHECK_GE (v, std::numeric_limits<T>::lowest ());
return static_cast<T> (v);
} }
template <typename T, typename V> ///----------------------------------------------------------------------------
T /// assert if the value is not a pointer to a subclass of T, else return the
_trunc_cast (const typename std::enable_if<sizeof (T) < sizeof (V) && /// converted value. Note: this is only a debug-time check and is compiled out
std::is_signed<T>::value == std::is_signed<V>::value && /// in optimised builds.
std::is_floating_point<T>::value, V>::type v) {
CHECK_LE (v, std::numeric_limits<T>::max ());
CHECK_GE (v, std::numeric_limits<T>::lowest ());
CHECK_EQ (remainder (v, 1), 0.0);
return static_cast<T> (v);
}
}
template <typename T, typename V>
T
trunc_cast (V v)
{ return detail::_trunc_cast<T, V> (v); }
//-----------------------------------------------------------------------------
template <typename T, typename V>
T
size_cast (const V v) {
CHECK_LE (std::numeric_limits<T>::lowest (), v);
CHECK_GE (std::numeric_limits<T>::max (), v);
return static_cast<T> (v);
}
//-----------------------------------------------------------------------------
template <typename T, typename V> template <typename T, typename V>
T* T*
known_cast (V *v) { known_cast (V *v) {
@ -127,6 +97,7 @@ known_cast (V *v) {
} }
//-----------------------------------------------------------------------------
template <typename T, typename V> template <typename T, typename V>
T& T&
known_cast (V &v) { known_cast (V &v) {