1 /* 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // Borrowed from Chromium's src/base/numerics/safe_conversions.h. 12 13 #ifndef RTC_BASE_NUMERICS_SAFE_CONVERSIONS_H_ 14 #define RTC_BASE_NUMERICS_SAFE_CONVERSIONS_H_ 15 16 #include <limits> 17 18 #include "rtc_base/checks.h" 19 #include "rtc_base/numerics/safe_conversions_impl.h" 20 21 namespace rtc { 22 23 // Convenience function that returns true if the supplied value is in range 24 // for the destination type. 25 template <typename Dst, typename Src> IsValueInRangeForNumericType(Src value)26inline constexpr bool IsValueInRangeForNumericType(Src value) { 27 return internal::RangeCheck<Dst>(value) == internal::TYPE_VALID; 28 } 29 30 // checked_cast<> and dchecked_cast<> are analogous to static_cast<> for 31 // numeric types, except that they [D]CHECK that the specified numeric 32 // conversion will not overflow or underflow. NaN source will always trigger 33 // the [D]CHECK. 34 template <typename Dst, typename Src> checked_cast(Src value)35inline constexpr Dst checked_cast(Src value) { 36 RTC_CHECK(IsValueInRangeForNumericType<Dst>(value)); 37 return static_cast<Dst>(value); 38 } 39 template <typename Dst, typename Src> dchecked_cast(Src value)40inline constexpr Dst dchecked_cast(Src value) { 41 RTC_DCHECK(IsValueInRangeForNumericType<Dst>(value)); 42 return static_cast<Dst>(value); 43 } 44 45 // saturated_cast<> is analogous to static_cast<> for numeric types, except 46 // that the specified numeric conversion will saturate rather than overflow or 47 // underflow. NaN assignment to an integral will trigger a RTC_CHECK condition. 48 template <typename Dst, typename Src> saturated_cast(Src value)49inline constexpr Dst saturated_cast(Src value) { 50 // Optimization for floating point values, which already saturate. 51 if (std::numeric_limits<Dst>::is_iec559) 52 return static_cast<Dst>(value); 53 54 switch (internal::RangeCheck<Dst>(value)) { 55 case internal::TYPE_VALID: 56 return static_cast<Dst>(value); 57 58 case internal::TYPE_UNDERFLOW: 59 return std::numeric_limits<Dst>::min(); 60 61 case internal::TYPE_OVERFLOW: 62 return std::numeric_limits<Dst>::max(); 63 64 // Should fail only on attempting to assign NaN to a saturated integer. 65 case internal::TYPE_INVALID: 66 RTC_CHECK_NOTREACHED(); 67 } 68 69 RTC_CHECK_NOTREACHED(); 70 } 71 72 } // namespace rtc 73 74 #endif // RTC_BASE_NUMERICS_SAFE_CONVERSIONS_H_ 75