| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_ | 5 #ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_ |
| 6 #define BASE_NUMERICS_SAFE_CONVERSIONS_H_ | 6 #define BASE_NUMERICS_SAFE_CONVERSIONS_H_ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| 11 #include <type_traits> | 11 #include <type_traits> |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/numerics/safe_conversions_impl.h" | 14 #include "base/numerics/safe_conversions_impl.h" |
| 15 | 15 |
| 16 namespace base { | 16 namespace base { |
| 17 | 17 |
| 18 // Convenience function that returns true if the supplied value is in range | 18 // Convenience function that returns true if the supplied value is in range |
| 19 // for the destination type. | 19 // for the destination type. |
| 20 template <typename Dst, typename Src> | 20 template <typename Dst, typename Src> |
| 21 inline constexpr bool IsValueInRangeForNumericType(Src value) { | 21 constexpr bool IsValueInRangeForNumericType(Src value) { |
| 22 return internal::DstRangeRelationToSrcRange<Dst>(value) == | 22 return internal::DstRangeRelationToSrcRange<Dst>(value) == |
| 23 internal::RANGE_VALID; | 23 internal::RANGE_VALID; |
| 24 } | 24 } |
| 25 | 25 |
| 26 // Convenience function for determining if a numeric value is negative without | 26 // Convenience function for determining if a numeric value is negative without |
| 27 // throwing compiler warnings on: unsigned(value) < 0. | 27 // throwing compiler warnings on: unsigned(value) < 0. |
| 28 template <typename T> | 28 template <typename T> |
| 29 constexpr typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type | 29 constexpr typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type |
| 30 IsValueNegative(T value) { | 30 IsValueNegative(T value) { |
| 31 static_assert(std::numeric_limits<T>::is_specialized, | 31 static_assert(std::numeric_limits<T>::is_specialized, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 template <typename T> | 64 template <typename T> |
| 65 static constexpr T HandleNaN() { | 65 static constexpr T HandleNaN() { |
| 66 return T(); | 66 return T(); |
| 67 } | 67 } |
| 68 }; | 68 }; |
| 69 | 69 |
| 70 namespace internal { | 70 namespace internal { |
| 71 // This wrapper is used for C++11 constexpr support by avoiding the declaration | 71 // This wrapper is used for C++11 constexpr support by avoiding the declaration |
| 72 // of local variables in the saturated_cast template function. | 72 // of local variables in the saturated_cast template function. |
| 73 template <typename Dst, class NaNHandler, typename Src> | 73 template <typename Dst, class NaNHandler, typename Src> |
| 74 inline constexpr Dst saturated_cast_impl(const Src value, | 74 constexpr Dst saturated_cast_impl(const Src value, |
| 75 const RangeConstraint constraint) { | 75 const RangeConstraint constraint) { |
| 76 return constraint == RANGE_VALID | 76 return constraint == RANGE_VALID |
| 77 ? static_cast<Dst>(value) | 77 ? static_cast<Dst>(value) |
| 78 : (constraint == RANGE_UNDERFLOW | 78 : (constraint == RANGE_UNDERFLOW |
| 79 ? std::numeric_limits<Dst>::min() | 79 ? std::numeric_limits<Dst>::min() |
| 80 : (constraint == RANGE_OVERFLOW | 80 : (constraint == RANGE_OVERFLOW |
| 81 ? std::numeric_limits<Dst>::max() | 81 ? std::numeric_limits<Dst>::max() |
| 82 : (constraint == RANGE_INVALID | 82 : (constraint == RANGE_INVALID |
| 83 ? NaNHandler::template HandleNaN<Dst>() | 83 ? NaNHandler::template HandleNaN<Dst>() |
| 84 : (NOTREACHED(), static_cast<Dst>(value))))); | 84 : (NOTREACHED(), static_cast<Dst>(value))))); |
| 85 } | 85 } |
| 86 } // namespace internal | 86 } // namespace internal |
| 87 | 87 |
| 88 // saturated_cast<> is analogous to static_cast<> for numeric types, except | 88 // saturated_cast<> is analogous to static_cast<> for numeric types, except |
| 89 // that the specified numeric conversion will saturate rather than overflow or | 89 // that the specified numeric conversion will saturate rather than overflow or |
| 90 // underflow. NaN assignment to an integral will defer the behavior to a | 90 // underflow. NaN assignment to an integral will defer the behavior to a |
| 91 // specified class. By default, it will return 0. | 91 // specified class. By default, it will return 0. |
| 92 template <typename Dst, | 92 template <typename Dst, |
| 93 class NaNHandler = SaturatedCastNaNBehaviorReturnZero, | 93 class NaNHandler = SaturatedCastNaNBehaviorReturnZero, |
| 94 typename Src> | 94 typename Src> |
| 95 inline constexpr Dst saturated_cast(Src value) { | 95 constexpr Dst saturated_cast(Src value) { |
| 96 return std::numeric_limits<Dst>::is_iec559 | 96 return std::numeric_limits<Dst>::is_iec559 |
| 97 ? static_cast<Dst>(value) // Floating point optimization. | 97 ? static_cast<Dst>(value) // Floating point optimization. |
| 98 : internal::saturated_cast_impl<Dst, NaNHandler>( | 98 : internal::saturated_cast_impl<Dst, NaNHandler>( |
| 99 value, internal::DstRangeRelationToSrcRange<Dst>(value)); | 99 value, internal::DstRangeRelationToSrcRange<Dst>(value)); |
| 100 } | 100 } |
| 101 | 101 |
| 102 // strict_cast<> is analogous to static_cast<> for numeric types, except that | 102 // strict_cast<> is analogous to static_cast<> for numeric types, except that |
| 103 // it will cause a compile failure if the destination type is not large enough | 103 // it will cause a compile failure if the destination type is not large enough |
| 104 // to contain any value in the source type. It performs no runtime checking. | 104 // to contain any value in the source type. It performs no runtime checking. |
| 105 template <typename Dst, typename Src> | 105 template <typename Dst, typename Src> |
| 106 inline constexpr Dst strict_cast(Src value) { | 106 constexpr Dst strict_cast(Src value) { |
| 107 static_assert(std::numeric_limits<Src>::is_specialized, | 107 static_assert(std::numeric_limits<Src>::is_specialized, |
| 108 "Argument must be numeric."); | 108 "Argument must be numeric."); |
| 109 static_assert(std::numeric_limits<Dst>::is_specialized, | 109 static_assert(std::numeric_limits<Dst>::is_specialized, |
| 110 "Result must be numeric."); | 110 "Result must be numeric."); |
| 111 static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value == | 111 static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value == |
| 112 internal::NUMERIC_RANGE_CONTAINED), | 112 internal::NUMERIC_RANGE_CONTAINED), |
| 113 "The numeric conversion is out of range for this type. You " | 113 "The numeric conversion is out of range for this type. You " |
| 114 "should probably use one of the following conversion " | 114 "should probably use one of the following conversion " |
| 115 "mechanisms on the value you want to pass:\n" | 115 "mechanisms on the value you want to pass:\n" |
| 116 "- base::checked_cast\n" | 116 "- base::checked_cast\n" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 private: | 157 private: |
| 158 const T value_; | 158 const T value_; |
| 159 }; | 159 }; |
| 160 | 160 |
| 161 // Explicitly make a shorter size_t typedef for convenience. | 161 // Explicitly make a shorter size_t typedef for convenience. |
| 162 typedef StrictNumeric<size_t> SizeT; | 162 typedef StrictNumeric<size_t> SizeT; |
| 163 | 163 |
| 164 } // namespace base | 164 } // namespace base |
| 165 | 165 |
| 166 #endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_ | 166 #endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_ |
| OLD | NEW |