| 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> | 
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 103                ? std::numeric_limits<T>::infinity() * -1 | 103                ? std::numeric_limits<T>::infinity() * -1 | 
| 104                : std::numeric_limits<T>::lowest(); | 104                : std::numeric_limits<T>::lowest(); | 
| 105   } | 105   } | 
| 106 }; | 106 }; | 
| 107 | 107 | 
| 108 namespace internal { | 108 namespace internal { | 
| 109 // saturated_cast<> is analogous to static_cast<> for numeric types, except | 109 // saturated_cast<> is analogous to static_cast<> for numeric types, except | 
| 110 // that the specified numeric conversion will saturate by default rather than | 110 // that the specified numeric conversion will saturate by default rather than | 
| 111 // overflow or underflow, and NaN assignment to an integral will return 0. | 111 // overflow or underflow, and NaN assignment to an integral will return 0. | 
| 112 // All boundary condition behaviors can be overriden with a custom handler. | 112 // All boundary condition behaviors can be overriden with a custom handler. | 
|  | 113 template <template <typename> | 
|  | 114           class SaturationHandler = SaturatedCastDefaultHandler, | 
|  | 115           typename Dst, | 
|  | 116           typename Src> | 
|  | 117 constexpr Dst saturated_cast_impl(const Src value, | 
|  | 118                                   const RangeConstraint constraint) { | 
|  | 119   return constraint.IsValid() | 
|  | 120              ? static_cast<Dst>(value) | 
|  | 121              : (constraint.IsOverflow() | 
|  | 122                     ? SaturationHandler<Dst>::HandleOverflow() | 
|  | 123                     // Skip this check for integral Src, which cannot be NaN. | 
|  | 124                     : (std::is_integral<Src>::value || constraint.IsUnderflow() | 
|  | 125                            ? SaturationHandler<Dst>::HandleUnderflow() | 
|  | 126                            : SaturationHandler<Dst>::HandleNaN())); | 
|  | 127 } | 
|  | 128 | 
|  | 129 // saturated_cast<> is analogous to static_cast<> for numeric types, except | 
|  | 130 // that the specified numeric conversion will saturate by default rather than | 
|  | 131 // overflow or underflow, and NaN assignment to an integral will return 0. | 
|  | 132 // All boundary condition behaviors can be overriden with a custom handler. | 
| 113 template <typename Dst, | 133 template <typename Dst, | 
| 114           template <typename> | 134           template <typename> | 
| 115           class SaturationHandler = SaturatedCastDefaultHandler, | 135           class SaturationHandler = SaturatedCastDefaultHandler, | 
| 116           typename Src> | 136           typename Src> | 
| 117 constexpr Dst saturated_cast(Src value) { | 137 constexpr Dst saturated_cast(Src value) { | 
| 118   static_assert( |  | 
| 119       SaturationHandler<Dst>::lowest() < SaturationHandler<Dst>::max(), ""); |  | 
| 120   // While this looks like a lot of code, it's all constexpr and all but |  | 
| 121   // one variable are compile-time constants (enforced by a static_assert). |  | 
| 122   // So, it should evaluate to the minimum number of comparisons required |  | 
| 123   // for the range check, which is 0-3, depending on the exact source and |  | 
| 124   // destination types, and whatever custom range is specified. |  | 
| 125   using SrcType = typename UnderlyingType<Src>::type; | 138   using SrcType = typename UnderlyingType<Src>::type; | 
| 126   return IsGreaterOrEqual<SrcType, Dst>::Test( | 139   return saturated_cast_impl<SaturationHandler, Dst>( | 
| 127              value, NarrowingRange<Dst, SrcType, SaturationHandler>::lowest()) | 140       static_cast<SrcType>(value), | 
| 128              ? (IsLessOrEqual<SrcType, Dst>::Test( | 141       DstRangeRelationToSrcRange<Dst, SaturationHandler, SrcType>(value)); | 
| 129                     value, |  | 
| 130                     NarrowingRange<Dst, SrcType, SaturationHandler>::max()) |  | 
| 131                     ? static_cast<Dst>(value) |  | 
| 132                     : SaturationHandler<Dst>::HandleOverflow()) |  | 
| 133              // This last branch is a little confusing. It's specifically to |  | 
| 134              // catch NaN when converting from float to integral. |  | 
| 135              : (std::is_integral<SrcType>::value || |  | 
| 136                         std::is_floating_point<Dst>::value || |  | 
| 137                         IsLessOrEqual<SrcType, Dst>::Test( |  | 
| 138                             value, NarrowingRange<Dst, SrcType, |  | 
| 139                                                   SaturationHandler>::max()) |  | 
| 140                     ? SaturationHandler<Dst>::HandleUnderflow() |  | 
| 141                     : SaturationHandler<Dst>::HandleNaN()); |  | 
| 142 } | 142 } | 
| 143 | 143 | 
| 144 // strict_cast<> is analogous to static_cast<> for numeric types, except that | 144 // strict_cast<> is analogous to static_cast<> for numeric types, except that | 
| 145 // it will cause a compile failure if the destination type is not large enough | 145 // it will cause a compile failure if the destination type is not large enough | 
| 146 // to contain any value in the source type. It performs no runtime checking. | 146 // to contain any value in the source type. It performs no runtime checking. | 
| 147 template <typename Dst, typename Src> | 147 template <typename Dst, typename Src> | 
| 148 constexpr Dst strict_cast(Src value) { | 148 constexpr Dst strict_cast(Src value) { | 
| 149   using SrcType = typename UnderlyingType<Src>::type; | 149   using SrcType = typename UnderlyingType<Src>::type; | 
| 150   static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric."); | 150   static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric."); | 
| 151   static_assert(std::is_arithmetic<Dst>::value, "Result must be numeric."); | 151   static_assert(std::is_arithmetic<Dst>::value, "Result must be numeric."); | 
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 270 using internal::StrictNumeric; | 270 using internal::StrictNumeric; | 
| 271 using internal::MakeStrictNum; | 271 using internal::MakeStrictNum; | 
| 272 using internal::IsValueNegative; | 272 using internal::IsValueNegative; | 
| 273 | 273 | 
| 274 // Explicitly make a shorter size_t alias for convenience. | 274 // Explicitly make a shorter size_t alias for convenience. | 
| 275 using SizeT = StrictNumeric<size_t>; | 275 using SizeT = StrictNumeric<size_t>; | 
| 276 | 276 | 
| 277 }  // namespace base | 277 }  // namespace base | 
| 278 | 278 | 
| 279 #endif  // BASE_NUMERICS_SAFE_CONVERSIONS_H_ | 279 #endif  // BASE_NUMERICS_SAFE_CONVERSIONS_H_ | 
| OLD | NEW | 
|---|