// -*- C++ -*- //============================================================================= /** * @file Truncate.h * * $Id$ * * @author Steve Huston * @author Ossama Othman * @author Russell Mora */ //============================================================================= #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" #if defined (__BORLANDC__) && __BORLANDC__ <= 0x590 # include "ace/Basic_Types.h" #endif /* __BORLANDC__ <= 0x590 */ ACE_BEGIN_VERSIONED_NAMESPACE_DECL namespace ACE_Utils { #if !defined (__BORLANDC__) || __BORLANDC__ > 0x590 template struct Sign_Check; // Specialize the unsigned signed cases. template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 0); }; template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 0); }; template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 0); }; template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 0); }; #ifndef ACE_LACKS_LONGLONG_T # ifdef __GNUC__ // Silence g++ "-pedantic" warnings regarding use of "long long" // type. __extension__ # endif /* __GNUC__ */ template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 0); }; #endif /* !ACE_LACKS_LONGLONG_T */ // Specialize the signed cases. template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 1); }; template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 1); }; template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 1); }; template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 1); }; #ifndef ACE_LACKS_LONGLONG_T # ifdef __GNUC__ // Silence g++ "-pedantic" warnings regarding use of "long long" // type. __extension__ # endif /* __GNUC__ */ template<> struct Sign_Check { ACE_STATIC_CONSTANT (bool, is_signed = 1); }; #endif /* !ACE_LACKS_LONGLONG_T */ // ----------------------------------------------------- /** * @struct To_Unsigned * * @brief Retrieve unsigned counterpart to given type or value. * * Retrieve unsigned counterpart to given type or value. */ template struct To_Unsigned; template<> struct To_Unsigned { typedef unsigned char unsigned_type; unsigned_type operator() (unsigned_type x) { return x; } }; template<> struct To_Unsigned { typedef unsigned short unsigned_type; unsigned_type operator() (unsigned_type x) { return x; } }; template<> struct To_Unsigned { typedef unsigned int unsigned_type; unsigned_type operator() (unsigned_type x) { return x; } }; template<> struct To_Unsigned { typedef unsigned long unsigned_type; unsigned_type operator() (unsigned_type x) { return x; } }; #ifndef ACE_LACKS_LONGLONG_T # ifdef __GNUC__ // Silence g++ "-pedantic" warnings regarding use of "long long" // type. __extension__ # endif /* __GNUC__ */ template<> struct To_Unsigned { typedef unsigned long long unsigned_type; unsigned_type operator() (unsigned_type x) { return x; } }; #endif /* !ACE_LACKS_LONGLONG_T */ // ---------------- template<> struct To_Unsigned { typedef signed char signed_type; typedef unsigned char unsigned_type; unsigned_type operator() (signed_type x) { return static_cast (x); } }; template<> struct To_Unsigned { typedef signed short signed_type; typedef unsigned short unsigned_type; unsigned_type operator() (signed_type x) { return static_cast (x); } }; template<> struct To_Unsigned { typedef signed int signed_type; typedef unsigned int unsigned_type; unsigned_type operator() (signed_type x) { return static_cast (x); } }; template<> struct To_Unsigned { typedef signed long signed_type; typedef unsigned long unsigned_type; unsigned_type operator() (signed_type x) { return static_cast (x); } }; #ifndef ACE_LACKS_LONGLONG_T # ifdef __GNUC__ // Silence g++ "-pedantic" warnings regarding use of "long long" // type. __extension__ # endif /* __GNUC__ */ template<> struct To_Unsigned { typedef signed long long signed_type; typedef unsigned long long unsigned_type; unsigned_type operator() (signed_type x) { return static_cast (x); } }; #endif /* !ACE_LACKS_LONGLONG_T */ // ----------------------------------------------------- /** * @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 struct Safe_Comparator; // LEFT: signed, RIGHT: unsigned template struct Safe_Comparator { 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() (lhs) > rhs; } } }; // LEFT: unsigned, RIGHT: signed template struct Safe_Comparator { 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() (rhs); } } }; // LEFT: unsigned, RIGHT: unsigned template struct Safe_Comparator { 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 struct Safe_Comparator { 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 struct Fast_Comparator { ACE_STATIC_CONSTANT ( bool, USE_LEFT = ((sizeof (LEFT) > sizeof (RIGHT) && (Sign_Check::is_signed == 1 || Sign_Check::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::is_signed == // Sign_Check::is_signed, // i.e. comparison of anonymous enumerations, // without triggering a compiler diagnostic // so expand the comparison. && ((Sign_Check::is_signed == 1 && Sign_Check::is_signed == 1) || (Sign_Check::is_signed == 0 && Sign_Check::is_signed == 0))))); ACE_STATIC_CONSTANT ( bool, USE_RIGHT = (sizeof (RIGHT) > sizeof (LEFT) && (Sign_Check::is_signed == 1 || Sign_Check::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 (lhs) > static_cast (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 struct Comparator { typedef typename ACE::If_Then_Else< Fast_Comparator::USABLE, Fast_Comparator, Safe_Comparator::is_signed, Sign_Check::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 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::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, typename Comparator::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::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; // Partial specialization for the case where the types are the same. // No truncation is necessary. template struct Truncator { 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::max() @c < @c numeric_limits::max(). */ template struct Noop_Truncator { TO operator() (FROM val) { return static_cast (val); } }; // ----------------------------------------------------- /** * @class Truncate * * @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 inline TO Truncate (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, Truncator >::result_type truncator; return truncator() (val); } #else // Borland can't handle the template meta-programming above so // provide explicit specializations for a few types. More will be // added if necessary. /** * @deprecated Borland ACE_Utils::Truncator<> specializations should * be removed. */ template struct Truncator; //---------------------------------------------------------- // sizeof(FROM) > sizeof(TO) //---------------------------------------------------------- template<> struct Truncator { ACE_INT8 operator() (ACE_INT32 val) { return (val > ACE_Numeric_Limits::max () ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { ACE_UINT8 operator() (ACE_UINT32 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { ACE_UINT8 operator() (ACE_INT32 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { ACE_INT8 operator() (ACE_UINT32 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; #if defined (ACE_SIZEOF_LONG) && ACE_SIZEOF_LONG < 8 template<> struct Truncator { signed long operator() (ACE_INT64 val) { return (val > ACE_Numeric_Limits::max () ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { unsigned long operator() (ACE_INT64 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { unsigned long operator() (ACE_UINT64 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { signed long operator() (ACE_UINT64 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; #endif /* ACE_SIZEOF_LONG < 8 */ #if defined (ACE_SIZEOF_INT) && ACE_SIZEOF_INT < 8 template<> struct Truncator { ACE_INT32 operator() (ACE_INT64 val) { return (val > ACE_Numeric_Limits::max () ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { ACE_UINT32 operator() (ACE_INT64 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { ACE_UINT32 operator() (ACE_UINT64 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { signed int operator() (ACE_UINT64 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; #endif /* ACE_SIZEOF_INT < 8 */ //---------------------------------------------------------- // sizeof(FROM) == sizeof(TO) //---------------------------------------------------------- template<> struct Truncator { unsigned int operator() (signed int val) { return static_cast (val); } }; template<> struct Truncator { signed int operator() (unsigned int val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { unsigned long operator() (signed long val) { return static_cast (val); } }; template<> struct Truncator { signed long operator() (unsigned long val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; #if defined (ACE_SIZEOF_INT) && defined (ACE_SIZEOF_LONG) \ && ACE_SIZEOF_INT == ACE_SIZEOF_LONG template<> struct Truncator { unsigned long operator() (signed int val) { return static_cast (val); } }; template<> struct Truncator { signed int operator() (unsigned long val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; template<> struct Truncator { unsigned int operator() (signed long val) { return static_cast (val); } }; template<> struct Truncator { signed long operator() (unsigned int val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; #endif /* ACE_SIZEOF_INT == ACE_SIZEOF_LONG */ template<> struct Truncator { ACE_UINT64 operator() (ACE_INT64 val) { return static_cast (val); } }; template<> struct Truncator { ACE_INT64 operator() (ACE_UINT64 val) { return (val > static_cast (ACE_Numeric_Limits::max ()) ? ACE_Numeric_Limits::max () : static_cast (val)); } }; //---------------------------------------------------------- // sizeof(FROM) < sizeof(TO) //---------------------------------------------------------- template<> struct Truncator { ACE_INT32 operator() (ACE_INT8 val) { return static_cast (val); } }; template<> struct Truncator { ACE_UINT32 operator() (ACE_UINT8 val) { return static_cast (val); } }; template<> struct Truncator { ACE_INT32 operator() (ACE_UINT8 val) { return static_cast (val); } }; template<> struct Truncator { ACE_UINT32 operator() (ACE_INT8 val) { return static_cast (val); } }; #if defined (ACE_SIZEOF_LONG) && ACE_SIZEOF_LONG < 8 template<> struct Truncator { ACE_INT64 operator() (signed long val) { return static_cast (val); } }; template<> struct Truncator { ACE_UINT64 operator() (signed long val) { return static_cast (val); } }; template<> struct Truncator { ACE_UINT64 operator() (unsigned long val) { return static_cast (val); } }; template<> struct Truncator { ACE_INT64 operator() (unsigned long val) { return static_cast (val); } }; #endif /* ACE_SIZEOF_LONG < 8 */ #if defined (ACE_SIZEOF_INT) && ACE_SIZEOF_INT < 8 template<> struct Truncator { ACE_INT64 operator() (signed int val) { return static_cast (val); } }; template<> struct Truncator { ACE_UINT64 operator() (signed int val) { return static_cast (val); } }; template<> struct Truncator { ACE_UINT64 operator() (unsigned int val) { return static_cast (val); } }; template<> struct Truncator { ACE_INT64 operator() (unsigned int val) { return static_cast (val); } }; #endif /* ACE_SIZEOF_INT < 8 */ // Partial specialization for the case where the types are the same. // No truncation is necessary. template struct Truncator { T operator() (T val) { return val; } }; // ------------------------------------- template inline TO Truncate (FROM val) { typedef Truncator truncator; return truncator() (val); } #endif /* !__BORLANDC__ || __BORLANDC__ > 0x590 */ } // namespace ACE_Utils ACE_END_VERSIONED_NAMESPACE_DECL #include /**/ "ace/post.h" #endif /* ACE_TRUNCATE_H*/