Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ace / Truncate.h
blobfd9fed20f1fda03c7bf7983e94418f93acf716e7
1 // -*- C++ -*-
3 //=============================================================================
4 /**
5 * @file Truncate.h
7 * @author Steve Huston <shuston@riverace.com>
8 * @author Ossama Othman <ossama_othman@symantec.com>
9 * @author Russell Mora <russell_mora@symantec.com>
11 //=============================================================================
13 #ifndef ACE_TRUNCATE_H
14 #define ACE_TRUNCATE_H
16 #include /**/ "ace/pre.h"
18 #include "ace/config-all.h"
20 #if !defined (ACE_LACKS_PRAGMA_ONCE)
21 # pragma once
22 #endif /* ACE_LACKS_PRAGMA_ONCE */
24 #include "ace/Global_Macros.h"
25 #include "ace/If_Then_Else.h"
26 #include "ace/Numeric_Limits.h"
28 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
30 namespace ACE_Utils
32 template<typename T> struct Sign_Check;
34 // Specialize the unsigned signed cases.
35 template<> struct Sign_Check<unsigned char> { static bool const is_signed = false; };
36 template<> struct Sign_Check<unsigned short> { static bool const is_signed = false; };
37 template<> struct Sign_Check<unsigned int> { static bool const is_signed = false; };
38 template<> struct Sign_Check<unsigned long> { static bool const is_signed = false; };
39 # ifdef __GNUC__
40 // Silence g++ "-pedantic" warnings regarding use of "long long"
41 // type.
42 __extension__
43 # endif /* __GNUC__ */
44 template<> struct Sign_Check<unsigned long long> { static bool const is_signed = false; };
46 // Specialize the signed cases.
47 template<> struct Sign_Check<signed char> { static bool const is_signed = true; };
48 template<> struct Sign_Check<signed short> { static bool const is_signed = true; };
49 template<> struct Sign_Check<signed int> { static bool const is_signed = true; };
50 template<> struct Sign_Check<signed long> { static bool const is_signed = true; };
51 # ifdef __GNUC__
52 // Silence g++ "-pedantic" warnings regarding use of "long long"
53 // type.
54 __extension__
55 # endif /* __GNUC__ */
56 template<> struct Sign_Check<signed long long> { static bool const is_signed = true; };
58 // -----------------------------------------------------
60 /**
61 * @struct To_Unsigned
63 * @brief Retrieve unsigned counterpart to given type or value.
65 * Retrieve unsigned counterpart to given type or value.
67 template<typename T> struct To_Unsigned;
69 template<>
70 struct To_Unsigned<unsigned char>
72 typedef unsigned char unsigned_type;
74 unsigned_type operator() (unsigned_type x) { return x; }
77 template<>
78 struct To_Unsigned<unsigned short>
80 typedef unsigned short unsigned_type;
82 unsigned_type operator() (unsigned_type x) { return x; }
85 template<>
86 struct To_Unsigned<unsigned int>
88 typedef unsigned int unsigned_type;
90 unsigned_type operator() (unsigned_type x) { return x; }
93 template<>
94 struct To_Unsigned<unsigned long>
96 typedef unsigned long unsigned_type;
98 unsigned_type operator() (unsigned_type x) { return x; }
101 # ifdef __GNUC__
102 // Silence g++ "-pedantic" warnings regarding use of "long long"
103 // type.
104 __extension__
105 # endif /* __GNUC__ */
106 template<>
107 struct To_Unsigned<unsigned long long>
109 typedef unsigned long long unsigned_type;
111 unsigned_type operator() (unsigned_type x) { return x; }
114 // ----------------
116 template<>
117 struct To_Unsigned<signed char>
119 typedef signed char signed_type;
120 typedef unsigned char unsigned_type;
122 unsigned_type operator() (signed_type x)
124 return static_cast<unsigned_type> (x);
128 template<>
129 struct To_Unsigned<signed short>
131 typedef signed short signed_type;
132 typedef unsigned short unsigned_type;
134 unsigned_type operator() (signed_type x)
136 return static_cast<unsigned_type> (x);
140 template<>
141 struct To_Unsigned<signed int>
143 typedef signed int signed_type;
144 typedef unsigned int unsigned_type;
146 unsigned_type operator() (signed_type x)
148 return static_cast<unsigned_type> (x);
152 template<>
153 struct To_Unsigned<signed long>
155 typedef signed long signed_type;
156 typedef unsigned long unsigned_type;
158 unsigned_type operator() (signed_type x)
160 return static_cast<unsigned_type> (x);
164 # ifdef __GNUC__
165 // Silence g++ "-pedantic" warnings regarding use of "long long"
166 // type.
167 __extension__
168 # endif /* __GNUC__ */
169 template<>
170 struct To_Unsigned<signed long long>
172 typedef signed long long signed_type;
173 typedef unsigned long long unsigned_type;
175 unsigned_type operator() (signed_type x)
177 return static_cast<unsigned_type> (x);
181 // -----------------------------------------------------
184 * @struct Safe_Comparator
186 * @brief Conservative comparison of types that may not be safely
187 * promoted and/or converted to each other.
189 * The comparison operations provided by this structure perform
190 * negative value checking when necessary to prevent wrap-around
191 * when explicitly casting to an unsigned type.
193 * @internal This structure is not meant for general use.
195 template<typename LEFT,
196 typename RIGHT,
197 bool IS_LEFT_SIGNED,
198 bool IS_RIGHT_SIGNED> struct Safe_Comparator;
200 // LEFT: signed, RIGHT: unsigned
201 template<typename LEFT, typename RIGHT>
202 struct Safe_Comparator<LEFT, RIGHT, true, false>
204 static bool greater_than (LEFT lhs, RIGHT rhs)
206 // Prevent wrap-around when casting to unsigned.
207 if (lhs < 0)
208 return false; // since rhs is always positive
209 else
211 // Implicit promotion of unsigned LEFT and RIGHT types here.
212 return To_Unsigned<LEFT>() (lhs) > rhs;
217 // LEFT: unsigned, RIGHT: signed
218 template<typename LEFT, typename RIGHT>
219 struct Safe_Comparator<LEFT, RIGHT, false, true>
221 static bool greater_than (LEFT lhs, RIGHT rhs)
223 // Prevent wrap-around when casting to unsigned.
224 if (rhs < 0)
225 return true; // since lhs is always positive
226 else
228 // Implicit promotion of unsigned LEFT and RIGHT types here.
229 return lhs > To_Unsigned<RIGHT>() (rhs);
234 // LEFT: unsigned, RIGHT: unsigned
235 template<typename LEFT, typename RIGHT>
236 struct Safe_Comparator<LEFT, RIGHT, false, false>
238 static bool greater_than (LEFT lhs, RIGHT rhs)
240 // Implicit promotion of unsigned LEFT and RIGHT types here.
241 return lhs > rhs;
245 // LEFT: signed, RIGHT: signed
246 template<typename LEFT, typename RIGHT>
247 struct Safe_Comparator<LEFT, RIGHT, true, true>
249 static bool greater_than (LEFT lhs, RIGHT rhs)
251 // Implicit promotion of signed LEFT and RIGHT types here.
252 return lhs > rhs;
256 // -----------------------------------------------------
259 * @struct Fast_Comparator
261 * @brief Quick comparison of types that can be safely promoted
262 * and/or converted to each other.
264 * The comparison operations provided by this structure perform no
265 * negative value checking, meaning it is not applicable to all
266 * types. Check the value of the @c USABLE enumerator to determine
267 * if it applies to the types in question.
269 * @internal This structure is not meant for general use.
271 template<typename LEFT, typename RIGHT>
272 struct Fast_Comparator
274 static bool const USE_LEFT =
275 ((sizeof (LEFT) > sizeof (RIGHT)
276 && (Sign_Check<LEFT>::is_signed == 1
277 || Sign_Check<RIGHT>::is_signed == 0))
279 // The following is basically the case where LEFT
280 // and RIGHT are the same integral type.
281 || (sizeof (LEFT) == sizeof (RIGHT)
282 // Can't portably do
283 // Sign_Check<LEFT>::is_signed ==
284 // Sign_Check<RIGHT>::is_signed,
285 // i.e. comparison of anonymous enumerations,
286 // without triggering a compiler diagnostic
287 // so expand the comparison.
288 && ((Sign_Check<LEFT>::is_signed == 1
289 && Sign_Check<RIGHT>::is_signed == 1)
290 || (Sign_Check<LEFT>::is_signed == 0
291 && Sign_Check<RIGHT>::is_signed == 0))));
293 static bool const USE_RIGHT =
294 (sizeof (RIGHT) > sizeof (LEFT)
295 && (Sign_Check<RIGHT>::is_signed == 1
296 || Sign_Check<LEFT>::is_signed == 0));
298 static bool const USABLE = (USE_LEFT || USE_RIGHT);
300 typedef typename ACE::If_Then_Else<
301 USE_LEFT,
302 LEFT,
303 typename ACE::If_Then_Else<
304 USE_RIGHT,
305 RIGHT,
306 void>::result_type>::result_type promote_type;
308 static bool greater_than (LEFT lhs, RIGHT rhs)
310 // The explicit cast is assumed to change the type of rhs without
311 // changing its value.
312 return
313 (static_cast<promote_type> (lhs) > static_cast<promote_type> (rhs));
318 // -----------------------------------------------------
321 * @struct Comparator
323 * @brief Structure that provides optimal comparison operation for
324 * given types.
326 * The comparison operations provided by this structure are chosen
327 * at compile time based on the signs and sizes of types being
328 * compared.
329 * @par
330 * Comparisons of values with the same sign or those with types that
331 * can be promoted safely are done quickly, without any range
332 * checking.
333 * @par
334 * Comparisons of values of different types that cannot be safely
335 * promoted incur an additional check for a negative value to allow
336 * the compiler to perform the appropriate implicit unsigned type
337 * promotion.
339 * @note In general, the operations found in this structure should
340 * not be used to work around compiler diagnostics regarding
341 * comparison of signed and unsigned types. Verify that your
342 * types are correct before relying on those operations.
344 * @internal This structure is not meant for general use.
346 template<typename LEFT, typename RIGHT>
347 struct Comparator
349 typedef typename ACE::If_Then_Else<
350 Fast_Comparator<LEFT, RIGHT>::USABLE,
351 Fast_Comparator<LEFT, RIGHT>,
352 Safe_Comparator<LEFT,
353 RIGHT,
354 Sign_Check<LEFT>::is_signed,
355 Sign_Check<RIGHT>::is_signed> >::result_type comp_type;
358 // -----------------------------------------------------
361 * @struct Truncator
363 * @brief Truncate value of type @c FROM to value of type @c TO.
365 * Truncate a value of type @c FROM to value of type @c TO, if the
366 * value is larger than the maximum of value of type @c TO.
368 template<typename FROM, typename TO>
369 struct Truncator
371 static bool const
372 // max FROM always greater than max TO
373 MAX_FROM_GT_MAX_TO = (sizeof(FROM) > sizeof (TO)
374 || (sizeof(FROM) == sizeof (TO)
375 && Sign_Check<FROM>::is_signed == 0));
377 typedef typename ACE::If_Then_Else<
378 MAX_FROM_GT_MAX_TO,
379 FROM,
380 TO>::result_type comp_to_type;
382 // Take advantage of knowledge that we're casting a positive value
383 // to a type large enough to hold it so that we can bypass
384 // negative value checks at compile-time. Otherwise fallback on
385 // the safer comparison.
386 typedef typename ACE::If_Then_Else<
387 MAX_FROM_GT_MAX_TO,
388 Fast_Comparator<FROM, comp_to_type>,
389 typename Comparator<FROM, comp_to_type>::comp_type>::result_type comparator;
391 /// Truncate a value of type @c FROM to value of type @c TO, if
392 /// the value is larger than the maximum of value of type @c TO.
393 TO operator() (FROM val)
395 return
396 (comparator::greater_than (val, ACE_Numeric_Limits<TO>::max ())
397 ? ACE_Numeric_Limits<TO>::max ()
398 : static_cast<TO> (val));
403 // Partial specialization for the case where the types are the same.
404 // No truncation is necessary.
405 template<typename T>
406 struct Truncator<T, T>
408 T operator() (T val)
410 return val;
415 // -----------------------------------------------------
417 * @struct Noop_Truncator
419 * @brief No-op truncation.
421 * This structure/functor performs no truncation since it assumes
422 * that @c sizeof(FROM) @c < @c sizeof(TO), meaning that
423 * @c numeric_limits<FROM>::max() @c < @c numeric_limits<TO>::max().
425 template<typename FROM, typename TO>
426 struct Noop_Truncator
428 TO operator() (FROM val)
430 return static_cast<TO> (val);
433 // -----------------------------------------------------
436 * @class truncate_cast
438 * @brief Helper function to truncate an integral value to the
439 * maximum value of the given type.
441 * Very useful since ACE methods return @c int very often and
442 * the value's source is often a different-size integral
443 * type, such as @c size_t. This function hides the
444 * truncation logic and resolves compiler diagnostics.
446 * @internal Internal use only.
448 template<typename TO, typename FROM>
449 inline TO truncate_cast (FROM val)
451 // If the size of FROM is less than the size of TO, "val" will
452 // never be greater than the maximum "TO" value, so there is no
453 // need to attempt to truncate.
454 typedef typename ACE::If_Then_Else<
455 (sizeof (FROM) < sizeof (TO)),
456 Noop_Truncator<FROM, TO>,
457 Truncator<FROM, TO> >::result_type truncator;
459 return truncator() (val);
462 } // namespace ACE_Utils
464 ACE_END_VERSIONED_NAMESPACE_DECL
466 #include /**/ "ace/post.h"
468 #endif /* ACE_TRUNCATE_H*/