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