472 lines
14 KiB
C++
472 lines
14 KiB
C++
// -*- C++ -*-
|
|
|
|
//=============================================================================
|
|
/**
|
|
* @file Truncate.h
|
|
*
|
|
* @author Steve Huston <shuston@riverace.com>
|
|
* @author Ossama Othman <ossama_othman@symantec.com>
|
|
* @author Russell Mora <russell_mora@symantec.com>
|
|
*/
|
|
//=============================================================================
|
|
|
|
#ifndef ACE_TRUNCATE_H
|
|
#define ACE_TRUNCATE_H
|
|
|
|
#include /**/ "ace/pre.h"
|
|
|
|
#include "ace/config-all.h"
|
|
|
|
#if !defined (ACE_LACKS_PRAGMA_ONCE)
|
|
# pragma once
|
|
#endif /* ACE_LACKS_PRAGMA_ONCE */
|
|
|
|
#include "ace/Global_Macros.h"
|
|
#include "ace/If_Then_Else.h"
|
|
#include "ace/Numeric_Limits.h"
|
|
|
|
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
|
|
|
namespace ACE_Utils
|
|
{
|
|
template<typename T> struct Sign_Check;
|
|
|
|
// Specialize the unsigned signed cases.
|
|
template<> struct Sign_Check<unsigned char> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
|
|
template<> struct Sign_Check<unsigned short> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
|
|
template<> struct Sign_Check<unsigned int> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
|
|
template<> struct Sign_Check<unsigned long> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
|
|
# ifdef __GNUC__
|
|
// Silence g++ "-pedantic" warnings regarding use of "long long"
|
|
// type.
|
|
__extension__
|
|
# endif /* __GNUC__ */
|
|
template<> struct Sign_Check<unsigned long long> { ACE_STATIC_CONSTANT (bool, is_signed = 0); };
|
|
|
|
// Specialize the signed cases.
|
|
template<> struct Sign_Check<signed char> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
|
|
template<> struct Sign_Check<signed short> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
|
|
template<> struct Sign_Check<signed int> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
|
|
template<> struct Sign_Check<signed long> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
|
|
# ifdef __GNUC__
|
|
// Silence g++ "-pedantic" warnings regarding use of "long long"
|
|
// type.
|
|
__extension__
|
|
# endif /* __GNUC__ */
|
|
template<> struct Sign_Check<signed long long> { ACE_STATIC_CONSTANT (bool, is_signed = 1); };
|
|
|
|
// -----------------------------------------------------
|
|
|
|
/**
|
|
* @struct To_Unsigned
|
|
*
|
|
* @brief Retrieve unsigned counterpart to given type or value.
|
|
*
|
|
* Retrieve unsigned counterpart to given type or value.
|
|
*/
|
|
template<typename T> struct To_Unsigned;
|
|
|
|
template<>
|
|
struct To_Unsigned<unsigned char>
|
|
{
|
|
typedef unsigned char unsigned_type;
|
|
|
|
unsigned_type operator() (unsigned_type x) { return x; }
|
|
};
|
|
|
|
template<>
|
|
struct To_Unsigned<unsigned short>
|
|
{
|
|
typedef unsigned short unsigned_type;
|
|
|
|
unsigned_type operator() (unsigned_type x) { return x; }
|
|
};
|
|
|
|
template<>
|
|
struct To_Unsigned<unsigned int>
|
|
{
|
|
typedef unsigned int unsigned_type;
|
|
|
|
unsigned_type operator() (unsigned_type x) { return x; }
|
|
};
|
|
|
|
template<>
|
|
struct To_Unsigned<unsigned long>
|
|
{
|
|
typedef unsigned long unsigned_type;
|
|
|
|
unsigned_type operator() (unsigned_type x) { return x; }
|
|
};
|
|
|
|
# ifdef __GNUC__
|
|
// Silence g++ "-pedantic" warnings regarding use of "long long"
|
|
// type.
|
|
__extension__
|
|
# endif /* __GNUC__ */
|
|
template<>
|
|
struct To_Unsigned<unsigned long long>
|
|
{
|
|
typedef unsigned long long unsigned_type;
|
|
|
|
unsigned_type operator() (unsigned_type x) { return x; }
|
|
};
|
|
|
|
// ----------------
|
|
|
|
template<>
|
|
struct To_Unsigned<signed char>
|
|
{
|
|
typedef signed char signed_type;
|
|
typedef unsigned char unsigned_type;
|
|
|
|
unsigned_type operator() (signed_type x)
|
|
{
|
|
return static_cast<unsigned_type> (x);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct To_Unsigned<signed short>
|
|
{
|
|
typedef signed short signed_type;
|
|
typedef unsigned short unsigned_type;
|
|
|
|
unsigned_type operator() (signed_type x)
|
|
{
|
|
return static_cast<unsigned_type> (x);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct To_Unsigned<signed int>
|
|
{
|
|
typedef signed int signed_type;
|
|
typedef unsigned int unsigned_type;
|
|
|
|
unsigned_type operator() (signed_type x)
|
|
{
|
|
return static_cast<unsigned_type> (x);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct To_Unsigned<signed long>
|
|
{
|
|
typedef signed long signed_type;
|
|
typedef unsigned long unsigned_type;
|
|
|
|
unsigned_type operator() (signed_type x)
|
|
{
|
|
return static_cast<unsigned_type> (x);
|
|
}
|
|
};
|
|
|
|
# ifdef __GNUC__
|
|
// Silence g++ "-pedantic" warnings regarding use of "long long"
|
|
// type.
|
|
__extension__
|
|
# endif /* __GNUC__ */
|
|
template<>
|
|
struct To_Unsigned<signed long long>
|
|
{
|
|
typedef signed long long signed_type;
|
|
typedef unsigned long long unsigned_type;
|
|
|
|
unsigned_type operator() (signed_type x)
|
|
{
|
|
return static_cast<unsigned_type> (x);
|
|
}
|
|
};
|
|
|
|
// -----------------------------------------------------
|
|
|
|
/**
|
|
* @struct Safe_Comparator
|
|
*
|
|
* @brief Conservative comparison of types that may not be safely
|
|
* promoted and/or converted to each other.
|
|
*
|
|
* The comparison operations provided by this structure perform
|
|
* negative value checking when necessary to prevent wrap-around
|
|
* when explicitly casting to an unsigned type.
|
|
*
|
|
* @internal This structure is not meant for general use.
|
|
*/
|
|
template<typename LEFT,
|
|
typename RIGHT,
|
|
bool IS_LEFT_SIGNED,
|
|
bool IS_RIGHT_SIGNED> struct Safe_Comparator;
|
|
|
|
// LEFT: signed, RIGHT: unsigned
|
|
template<typename LEFT, typename RIGHT>
|
|
struct Safe_Comparator<LEFT, RIGHT, true, false>
|
|
{
|
|
static bool greater_than (LEFT lhs, RIGHT rhs)
|
|
{
|
|
// Prevent wrap-around when casting to unsigned.
|
|
if (lhs < 0)
|
|
return false; // since rhs is always positive
|
|
else
|
|
{
|
|
// Implicit promotion of unsigned LEFT and RIGHT types here.
|
|
return To_Unsigned<LEFT>() (lhs) > rhs;
|
|
}
|
|
}
|
|
};
|
|
|
|
// LEFT: unsigned, RIGHT: signed
|
|
template<typename LEFT, typename RIGHT>
|
|
struct Safe_Comparator<LEFT, RIGHT, false, true>
|
|
{
|
|
static bool greater_than (LEFT lhs, RIGHT rhs)
|
|
{
|
|
// Prevent wrap-around when casting to unsigned.
|
|
if (rhs < 0)
|
|
return true; // since lhs is always positive
|
|
else
|
|
{
|
|
// Implicit promotion of unsigned LEFT and RIGHT types here.
|
|
return lhs > To_Unsigned<RIGHT>() (rhs);
|
|
}
|
|
}
|
|
};
|
|
|
|
// LEFT: unsigned, RIGHT: unsigned
|
|
template<typename LEFT, typename RIGHT>
|
|
struct Safe_Comparator<LEFT, RIGHT, false, false>
|
|
{
|
|
static bool greater_than (LEFT lhs, RIGHT rhs)
|
|
{
|
|
// Implicit promotion of unsigned LEFT and RIGHT types here.
|
|
return lhs > rhs;
|
|
}
|
|
};
|
|
|
|
// LEFT: signed, RIGHT: signed
|
|
template<typename LEFT, typename RIGHT>
|
|
struct Safe_Comparator<LEFT, RIGHT, true, true>
|
|
{
|
|
static bool greater_than (LEFT lhs, RIGHT rhs)
|
|
{
|
|
// Implicit promotion of signed LEFT and RIGHT types here.
|
|
return lhs > rhs;
|
|
}
|
|
};
|
|
|
|
// -----------------------------------------------------
|
|
|
|
/**
|
|
* @struct Fast_Comparator
|
|
*
|
|
* @brief Quick comparison of types that can be safely promoted
|
|
* and/or converted to each other.
|
|
*
|
|
* The comparison operations provided by this structure perform no
|
|
* negative value checking, meaning it is not applicable to all
|
|
* types. Check the value of the @c USABLE enumerator to determine
|
|
* if it applies to the types in question.
|
|
*
|
|
* @internal This structure is not meant for general use.
|
|
*/
|
|
template<typename LEFT, typename RIGHT>
|
|
struct Fast_Comparator
|
|
{
|
|
ACE_STATIC_CONSTANT (
|
|
bool,
|
|
USE_LEFT = ((sizeof (LEFT) > sizeof (RIGHT)
|
|
&& (Sign_Check<LEFT>::is_signed == 1
|
|
|| Sign_Check<RIGHT>::is_signed == 0))
|
|
|
|
// The following is basically the case where LEFT
|
|
// and RIGHT are the same integral type.
|
|
|| (sizeof (LEFT) == sizeof (RIGHT)
|
|
// Can't portably do
|
|
// Sign_Check<LEFT>::is_signed ==
|
|
// Sign_Check<RIGHT>::is_signed,
|
|
// i.e. comparison of anonymous enumerations,
|
|
// without triggering a compiler diagnostic
|
|
// so expand the comparison.
|
|
&& ((Sign_Check<LEFT>::is_signed == 1
|
|
&& Sign_Check<RIGHT>::is_signed == 1)
|
|
|| (Sign_Check<LEFT>::is_signed == 0
|
|
&& Sign_Check<RIGHT>::is_signed == 0)))));
|
|
|
|
ACE_STATIC_CONSTANT (
|
|
bool,
|
|
USE_RIGHT = (sizeof (RIGHT) > sizeof (LEFT)
|
|
&& (Sign_Check<RIGHT>::is_signed == 1
|
|
|| Sign_Check<LEFT>::is_signed == 0)));
|
|
|
|
ACE_STATIC_CONSTANT (bool, USABLE = (USE_LEFT || USE_RIGHT));
|
|
|
|
typedef typename ACE::If_Then_Else<
|
|
USE_LEFT,
|
|
LEFT,
|
|
typename ACE::If_Then_Else<
|
|
USE_RIGHT,
|
|
RIGHT,
|
|
void>::result_type>::result_type promote_type;
|
|
|
|
static bool greater_than (LEFT lhs, RIGHT rhs)
|
|
{
|
|
// The explicit cast is assumed to change the type of rhs without
|
|
// changing its value.
|
|
return
|
|
(static_cast<promote_type> (lhs) > static_cast<promote_type> (rhs));
|
|
}
|
|
|
|
};
|
|
|
|
// -----------------------------------------------------
|
|
|
|
/**
|
|
* @struct Comparator
|
|
*
|
|
* @brief Structure that provides optimal comparison operation for
|
|
* given types.
|
|
*
|
|
* The comparison operations provided by this structure are chosen
|
|
* at compile time based on the signs and sizes of types being
|
|
* compared.
|
|
* @par
|
|
* Comparisons of values with the same sign or those with types that
|
|
* can be promoted safely are done quickly, without any range
|
|
* checking.
|
|
* @par
|
|
* Comparisons of values of different types that cannot be safely
|
|
* promoted incur an additional check for a negative value to allow
|
|
* the compiler to perform the appropriate implicit unsigned type
|
|
* promotion.
|
|
*
|
|
* @note In general, the operations found in this structure should
|
|
* not be used to work around compiler diagnostics regarding
|
|
* comparison of signed and unsigned types. Verify that your
|
|
* types are correct before relying on those operations.
|
|
*
|
|
* @internal This structure is not meant for general use.
|
|
*/
|
|
template<typename LEFT, typename RIGHT>
|
|
struct Comparator
|
|
{
|
|
typedef typename ACE::If_Then_Else<
|
|
Fast_Comparator<LEFT, RIGHT>::USABLE,
|
|
Fast_Comparator<LEFT, RIGHT>,
|
|
Safe_Comparator<LEFT,
|
|
RIGHT,
|
|
Sign_Check<LEFT>::is_signed,
|
|
Sign_Check<RIGHT>::is_signed> >::result_type comp_type;
|
|
};
|
|
|
|
// -----------------------------------------------------
|
|
|
|
/**
|
|
* @struct Truncator
|
|
*
|
|
* @brief Truncate value of type @c FROM to value of type @c TO.
|
|
*
|
|
* Truncate a value of type @c FROM to value of type @c TO, if the
|
|
* value is larger than the maximum of value of type @c TO.
|
|
*/
|
|
template<typename FROM, typename TO>
|
|
struct Truncator
|
|
{
|
|
ACE_STATIC_CONSTANT (
|
|
bool,
|
|
// max FROM always greater than max TO
|
|
MAX_FROM_GT_MAX_TO = (sizeof(FROM) > sizeof (TO)
|
|
|| (sizeof(FROM) == sizeof (TO)
|
|
&& Sign_Check<FROM>::is_signed == 0)));
|
|
|
|
typedef typename ACE::If_Then_Else<
|
|
MAX_FROM_GT_MAX_TO,
|
|
FROM,
|
|
TO>::result_type comp_to_type;
|
|
|
|
// Take advantage of knowledge that we're casting a positive value
|
|
// to a type large enough to hold it so that we can bypass
|
|
// negative value checks at compile-time. Otherwise fallback on
|
|
// the safer comparison.
|
|
typedef typename ACE::If_Then_Else<
|
|
MAX_FROM_GT_MAX_TO,
|
|
Fast_Comparator<FROM, comp_to_type>,
|
|
typename Comparator<FROM, comp_to_type>::comp_type>::result_type comparator;
|
|
|
|
/// Truncate a value of type @c FROM to value of type @c TO, if
|
|
/// the value is larger than the maximum of value of type @c TO.
|
|
TO operator() (FROM val)
|
|
{
|
|
return
|
|
(comparator::greater_than (val, ACE_Numeric_Limits<TO>::max ())
|
|
? ACE_Numeric_Limits<TO>::max ()
|
|
: static_cast<TO> (val));
|
|
}
|
|
|
|
};
|
|
|
|
// Partial specialization for the case where the types are the same.
|
|
// No truncation is necessary.
|
|
template<typename T>
|
|
struct Truncator<T, T>
|
|
{
|
|
T operator() (T val)
|
|
{
|
|
return val;
|
|
}
|
|
};
|
|
|
|
|
|
// -----------------------------------------------------
|
|
/**
|
|
* @struct Noop_Truncator
|
|
*
|
|
* @brief No-op truncation.
|
|
*
|
|
* This structure/functor performs no truncation since it assumes
|
|
* that @c sizeof(FROM) @c < @c sizeof(TO), meaning that
|
|
* @c numeric_limits<FROM>::max() @c < @c numeric_limits<TO>::max().
|
|
*/
|
|
template<typename FROM, typename TO>
|
|
struct Noop_Truncator
|
|
{
|
|
TO operator() (FROM val)
|
|
{
|
|
return static_cast<TO> (val);
|
|
}
|
|
};
|
|
// -----------------------------------------------------
|
|
|
|
/**
|
|
* @class truncate_cast
|
|
*
|
|
* @brief Helper function to truncate an integral value to the
|
|
* maximum value of the given type.
|
|
*
|
|
* Very useful since ACE methods return @c int very often and
|
|
* the value's source is often a different-size integral
|
|
* type, such as @c size_t. This function hides the
|
|
* truncation logic and resolves compiler diagnostics.
|
|
*
|
|
* @internal Internal use only.
|
|
*/
|
|
template<typename TO, typename FROM>
|
|
inline TO truncate_cast (FROM val)
|
|
{
|
|
// If the size of FROM is less than the size of TO, "val" will
|
|
// never be greater than the maximum "TO" value, so there is no
|
|
// need to attempt to truncate.
|
|
typedef typename ACE::If_Then_Else<
|
|
(sizeof (FROM) < sizeof (TO)),
|
|
Noop_Truncator<FROM, TO>,
|
|
Truncator<FROM, TO> >::result_type truncator;
|
|
|
|
return truncator() (val);
|
|
}
|
|
|
|
} // namespace ACE_Utils
|
|
|
|
ACE_END_VERSIONED_NAMESPACE_DECL
|
|
|
|
#include /**/ "ace/post.h"
|
|
|
|
#endif /* ACE_TRUNCATE_H*/
|