1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_NUMERICS_CHECKED_MATH_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_NUMERICS_CHECKED_MATH_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stddef.h> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include <limits> 11*6777b538SAndroid Build Coastguard Worker #include <type_traits> 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Worker #include "base/numerics/checked_math_impl.h" 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Worker namespace base { 16*6777b538SAndroid Build Coastguard Worker namespace internal { 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker template <typename T> 19*6777b538SAndroid Build Coastguard Worker class CheckedNumeric { 20*6777b538SAndroid Build Coastguard Worker static_assert(std::is_arithmetic_v<T>, 21*6777b538SAndroid Build Coastguard Worker "CheckedNumeric<T>: T must be a numeric type."); 22*6777b538SAndroid Build Coastguard Worker 23*6777b538SAndroid Build Coastguard Worker public: 24*6777b538SAndroid Build Coastguard Worker template <typename Src> 25*6777b538SAndroid Build Coastguard Worker friend class CheckedNumeric; 26*6777b538SAndroid Build Coastguard Worker 27*6777b538SAndroid Build Coastguard Worker using type = T; 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric() = default; 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker // Copy constructor. 32*6777b538SAndroid Build Coastguard Worker template <typename Src> CheckedNumeric(const CheckedNumeric<Src> & rhs)33*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs) 34*6777b538SAndroid Build Coastguard Worker : state_(rhs.state_.value(), rhs.IsValid()) {} 35*6777b538SAndroid Build Coastguard Worker 36*6777b538SAndroid Build Coastguard Worker // Strictly speaking, this is not necessary, but declaring this allows class 37*6777b538SAndroid Build Coastguard Worker // template argument deduction to be used so that it is possible to simply 38*6777b538SAndroid Build Coastguard Worker // write `CheckedNumeric(777)` instead of `CheckedNumeric<int>(777)`. 39*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor) CheckedNumeric(T value)40*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric(T value) : state_(value) {} 41*6777b538SAndroid Build Coastguard Worker 42*6777b538SAndroid Build Coastguard Worker // This is not an explicit constructor because we implicitly upgrade regular 43*6777b538SAndroid Build Coastguard Worker // numerics to CheckedNumerics to make them easier to use. 44*6777b538SAndroid Build Coastguard Worker template <typename Src> requires(std::is_arithmetic_v<Src>)45*6777b538SAndroid Build Coastguard Worker requires(std::is_arithmetic_v<Src>) 46*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor) 47*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric(Src value) : state_(value) {} 48*6777b538SAndroid Build Coastguard Worker 49*6777b538SAndroid Build Coastguard Worker // This is not an explicit constructor because we want a seamless conversion 50*6777b538SAndroid Build Coastguard Worker // from StrictNumeric types. 51*6777b538SAndroid Build Coastguard Worker template <typename Src> 52*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor) CheckedNumeric(StrictNumeric<Src> value)53*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric(StrictNumeric<Src> value) 54*6777b538SAndroid Build Coastguard Worker : state_(static_cast<Src>(value)) {} 55*6777b538SAndroid Build Coastguard Worker 56*6777b538SAndroid Build Coastguard Worker // IsValid() - The public API to test if a CheckedNumeric is currently valid. 57*6777b538SAndroid Build Coastguard Worker // A range checked destination type can be supplied using the Dst template 58*6777b538SAndroid Build Coastguard Worker // parameter. 59*6777b538SAndroid Build Coastguard Worker template <typename Dst = T> IsValid()60*6777b538SAndroid Build Coastguard Worker constexpr bool IsValid() const { 61*6777b538SAndroid Build Coastguard Worker return state_.is_valid() && 62*6777b538SAndroid Build Coastguard Worker IsValueInRangeForNumericType<Dst>(state_.value()); 63*6777b538SAndroid Build Coastguard Worker } 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard Worker // AssignIfValid(Dst) - Assigns the underlying value if it is currently valid 66*6777b538SAndroid Build Coastguard Worker // and is within the range supported by the destination type. Returns true if 67*6777b538SAndroid Build Coastguard Worker // successful and false otherwise. 68*6777b538SAndroid Build Coastguard Worker template <typename Dst> 69*6777b538SAndroid Build Coastguard Worker #if defined(__clang__) || defined(__GNUC__) 70*6777b538SAndroid Build Coastguard Worker __attribute__((warn_unused_result)) 71*6777b538SAndroid Build Coastguard Worker #elif defined(_MSC_VER) 72*6777b538SAndroid Build Coastguard Worker _Check_return_ 73*6777b538SAndroid Build Coastguard Worker #endif 74*6777b538SAndroid Build Coastguard Worker constexpr bool AssignIfValid(Dst * result)75*6777b538SAndroid Build Coastguard Worker AssignIfValid(Dst* result) const { 76*6777b538SAndroid Build Coastguard Worker return BASE_NUMERICS_LIKELY(IsValid<Dst>()) 77*6777b538SAndroid Build Coastguard Worker ? ((*result = static_cast<Dst>(state_.value())), true) 78*6777b538SAndroid Build Coastguard Worker : false; 79*6777b538SAndroid Build Coastguard Worker } 80*6777b538SAndroid Build Coastguard Worker 81*6777b538SAndroid Build Coastguard Worker // ValueOrDie() - The primary accessor for the underlying value. If the 82*6777b538SAndroid Build Coastguard Worker // current state is not valid it will CHECK and crash. 83*6777b538SAndroid Build Coastguard Worker // A range checked destination type can be supplied using the Dst template 84*6777b538SAndroid Build Coastguard Worker // parameter, which will trigger a CHECK if the value is not in bounds for 85*6777b538SAndroid Build Coastguard Worker // the destination. 86*6777b538SAndroid Build Coastguard Worker // The CHECK behavior can be overridden by supplying a handler as a 87*6777b538SAndroid Build Coastguard Worker // template parameter, for test code, etc. However, the handler cannot access 88*6777b538SAndroid Build Coastguard Worker // the underlying value, and it is not available through other means. 89*6777b538SAndroid Build Coastguard Worker template <typename Dst = T, class CheckHandler = CheckOnFailure> ValueOrDie()90*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric<Dst> ValueOrDie() const { 91*6777b538SAndroid Build Coastguard Worker return BASE_NUMERICS_LIKELY(IsValid<Dst>()) 92*6777b538SAndroid Build Coastguard Worker ? static_cast<Dst>(state_.value()) 93*6777b538SAndroid Build Coastguard Worker : CheckHandler::template HandleFailure<Dst>(); 94*6777b538SAndroid Build Coastguard Worker } 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker // ValueOrDefault(T default_value) - A convenience method that returns the 97*6777b538SAndroid Build Coastguard Worker // current value if the state is valid, and the supplied default_value for 98*6777b538SAndroid Build Coastguard Worker // any other state. 99*6777b538SAndroid Build Coastguard Worker // A range checked destination type can be supplied using the Dst template 100*6777b538SAndroid Build Coastguard Worker // parameter. WARNING: This function may fail to compile or CHECK at runtime 101*6777b538SAndroid Build Coastguard Worker // if the supplied default_value is not within range of the destination type. 102*6777b538SAndroid Build Coastguard Worker template <typename Dst = T, typename Src> ValueOrDefault(const Src default_value)103*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric<Dst> ValueOrDefault(const Src default_value) const { 104*6777b538SAndroid Build Coastguard Worker return BASE_NUMERICS_LIKELY(IsValid<Dst>()) 105*6777b538SAndroid Build Coastguard Worker ? static_cast<Dst>(state_.value()) 106*6777b538SAndroid Build Coastguard Worker : checked_cast<Dst>(default_value); 107*6777b538SAndroid Build Coastguard Worker } 108*6777b538SAndroid Build Coastguard Worker 109*6777b538SAndroid Build Coastguard Worker // Returns a checked numeric of the specified type, cast from the current 110*6777b538SAndroid Build Coastguard Worker // CheckedNumeric. If the current state is invalid or the destination cannot 111*6777b538SAndroid Build Coastguard Worker // represent the result then the returned CheckedNumeric will be invalid. 112*6777b538SAndroid Build Coastguard Worker template <typename Dst> Cast()113*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const { 114*6777b538SAndroid Build Coastguard Worker return *this; 115*6777b538SAndroid Build Coastguard Worker } 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Worker // This friend method is available solely for providing more detailed logging 118*6777b538SAndroid Build Coastguard Worker // in the tests. Do not implement it in production code, because the 119*6777b538SAndroid Build Coastguard Worker // underlying values may change at any time. 120*6777b538SAndroid Build Coastguard Worker template <typename U> 121*6777b538SAndroid Build Coastguard Worker friend U GetNumericValueForTest(const CheckedNumeric<U>& src); 122*6777b538SAndroid Build Coastguard Worker 123*6777b538SAndroid Build Coastguard Worker // Prototypes for the supported arithmetic operator overloads. 124*6777b538SAndroid Build Coastguard Worker template <typename Src> 125*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator+=(const Src rhs); 126*6777b538SAndroid Build Coastguard Worker template <typename Src> 127*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator-=(const Src rhs); 128*6777b538SAndroid Build Coastguard Worker template <typename Src> 129*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator*=(const Src rhs); 130*6777b538SAndroid Build Coastguard Worker template <typename Src> 131*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator/=(const Src rhs); 132*6777b538SAndroid Build Coastguard Worker template <typename Src> 133*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator%=(const Src rhs); 134*6777b538SAndroid Build Coastguard Worker template <typename Src> 135*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator<<=(const Src rhs); 136*6777b538SAndroid Build Coastguard Worker template <typename Src> 137*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator>>=(const Src rhs); 138*6777b538SAndroid Build Coastguard Worker template <typename Src> 139*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator&=(const Src rhs); 140*6777b538SAndroid Build Coastguard Worker template <typename Src> 141*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator|=(const Src rhs); 142*6777b538SAndroid Build Coastguard Worker template <typename Src> 143*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator^=(const Src rhs); 144*6777b538SAndroid Build Coastguard Worker 145*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric operator-() const { 146*6777b538SAndroid Build Coastguard Worker // Use an optimized code path for a known run-time variable. 147*6777b538SAndroid Build Coastguard Worker if (!IsConstantEvaluated() && std::is_signed_v<T> && 148*6777b538SAndroid Build Coastguard Worker std::is_floating_point_v<T>) { 149*6777b538SAndroid Build Coastguard Worker return FastRuntimeNegate(); 150*6777b538SAndroid Build Coastguard Worker } 151*6777b538SAndroid Build Coastguard Worker // The negation of two's complement int min is int min. 152*6777b538SAndroid Build Coastguard Worker const bool is_valid = 153*6777b538SAndroid Build Coastguard Worker IsValid() && 154*6777b538SAndroid Build Coastguard Worker (!std::is_signed_v<T> || std::is_floating_point_v<T> || 155*6777b538SAndroid Build Coastguard Worker NegateWrapper(state_.value()) != std::numeric_limits<T>::lowest()); 156*6777b538SAndroid Build Coastguard Worker return CheckedNumeric<T>(NegateWrapper(state_.value()), is_valid); 157*6777b538SAndroid Build Coastguard Worker } 158*6777b538SAndroid Build Coastguard Worker 159*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric operator~() const { 160*6777b538SAndroid Build Coastguard Worker return CheckedNumeric<decltype(InvertWrapper(T()))>( 161*6777b538SAndroid Build Coastguard Worker InvertWrapper(state_.value()), IsValid()); 162*6777b538SAndroid Build Coastguard Worker } 163*6777b538SAndroid Build Coastguard Worker Abs()164*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric Abs() const { 165*6777b538SAndroid Build Coastguard Worker return !IsValueNegative(state_.value()) ? *this : -*this; 166*6777b538SAndroid Build Coastguard Worker } 167*6777b538SAndroid Build Coastguard Worker 168*6777b538SAndroid Build Coastguard Worker template <typename U> Max(const U rhs)169*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max( 170*6777b538SAndroid Build Coastguard Worker const U rhs) const { 171*6777b538SAndroid Build Coastguard Worker return CheckMax(*this, rhs); 172*6777b538SAndroid Build Coastguard Worker } 173*6777b538SAndroid Build Coastguard Worker 174*6777b538SAndroid Build Coastguard Worker template <typename U> Min(const U rhs)175*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min( 176*6777b538SAndroid Build Coastguard Worker const U rhs) const { 177*6777b538SAndroid Build Coastguard Worker return CheckMin(*this, rhs); 178*6777b538SAndroid Build Coastguard Worker } 179*6777b538SAndroid Build Coastguard Worker 180*6777b538SAndroid Build Coastguard Worker // This function is available only for integral types. It returns an unsigned 181*6777b538SAndroid Build Coastguard Worker // integer of the same width as the source type, containing the absolute value 182*6777b538SAndroid Build Coastguard Worker // of the source, and properly handling signed min. 183*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs()184*6777b538SAndroid Build Coastguard Worker UnsignedAbs() const { 185*6777b538SAndroid Build Coastguard Worker return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( 186*6777b538SAndroid Build Coastguard Worker SafeUnsignedAbs(state_.value()), state_.is_valid()); 187*6777b538SAndroid Build Coastguard Worker } 188*6777b538SAndroid Build Coastguard Worker 189*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator++() { 190*6777b538SAndroid Build Coastguard Worker *this += 1; 191*6777b538SAndroid Build Coastguard Worker return *this; 192*6777b538SAndroid Build Coastguard Worker } 193*6777b538SAndroid Build Coastguard Worker 194*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric operator++(int) { 195*6777b538SAndroid Build Coastguard Worker CheckedNumeric value = *this; 196*6777b538SAndroid Build Coastguard Worker *this += 1; 197*6777b538SAndroid Build Coastguard Worker return value; 198*6777b538SAndroid Build Coastguard Worker } 199*6777b538SAndroid Build Coastguard Worker 200*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& operator--() { 201*6777b538SAndroid Build Coastguard Worker *this -= 1; 202*6777b538SAndroid Build Coastguard Worker return *this; 203*6777b538SAndroid Build Coastguard Worker } 204*6777b538SAndroid Build Coastguard Worker 205*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric operator--(int) { 206*6777b538SAndroid Build Coastguard Worker // TODO(pkasting): Consider std::exchange() once it's constexpr in C++20. 207*6777b538SAndroid Build Coastguard Worker const CheckedNumeric value = *this; 208*6777b538SAndroid Build Coastguard Worker *this -= 1; 209*6777b538SAndroid Build Coastguard Worker return value; 210*6777b538SAndroid Build Coastguard Worker } 211*6777b538SAndroid Build Coastguard Worker 212*6777b538SAndroid Build Coastguard Worker // These perform the actual math operations on the CheckedNumerics. 213*6777b538SAndroid Build Coastguard Worker // Binary arithmetic operations. 214*6777b538SAndroid Build Coastguard Worker template <template <typename, typename> class M, typename L, typename R> MathOp(const L lhs,const R rhs)215*6777b538SAndroid Build Coastguard Worker static constexpr CheckedNumeric MathOp(const L lhs, const R rhs) { 216*6777b538SAndroid Build Coastguard Worker using Math = typename MathWrapper<M, L, R>::math; 217*6777b538SAndroid Build Coastguard Worker T result = 0; 218*6777b538SAndroid Build Coastguard Worker const bool is_valid = 219*6777b538SAndroid Build Coastguard Worker Wrapper<L>::is_valid(lhs) && Wrapper<R>::is_valid(rhs) && 220*6777b538SAndroid Build Coastguard Worker Math::Do(Wrapper<L>::value(lhs), Wrapper<R>::value(rhs), &result); 221*6777b538SAndroid Build Coastguard Worker return CheckedNumeric<T>(result, is_valid); 222*6777b538SAndroid Build Coastguard Worker } 223*6777b538SAndroid Build Coastguard Worker 224*6777b538SAndroid Build Coastguard Worker // Assignment arithmetic operations. 225*6777b538SAndroid Build Coastguard Worker template <template <typename, typename> class M, typename R> MathOp(const R rhs)226*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric& MathOp(const R rhs) { 227*6777b538SAndroid Build Coastguard Worker using Math = typename MathWrapper<M, T, R>::math; 228*6777b538SAndroid Build Coastguard Worker T result = 0; // Using T as the destination saves a range check. 229*6777b538SAndroid Build Coastguard Worker const bool is_valid = 230*6777b538SAndroid Build Coastguard Worker state_.is_valid() && Wrapper<R>::is_valid(rhs) && 231*6777b538SAndroid Build Coastguard Worker Math::Do(state_.value(), Wrapper<R>::value(rhs), &result); 232*6777b538SAndroid Build Coastguard Worker *this = CheckedNumeric<T>(result, is_valid); 233*6777b538SAndroid Build Coastguard Worker return *this; 234*6777b538SAndroid Build Coastguard Worker } 235*6777b538SAndroid Build Coastguard Worker 236*6777b538SAndroid Build Coastguard Worker private: 237*6777b538SAndroid Build Coastguard Worker CheckedNumericState<T> state_; 238*6777b538SAndroid Build Coastguard Worker FastRuntimeNegate()239*6777b538SAndroid Build Coastguard Worker CheckedNumeric FastRuntimeNegate() const { 240*6777b538SAndroid Build Coastguard Worker T result; 241*6777b538SAndroid Build Coastguard Worker const bool success = CheckedSubOp<T, T>::Do(T(0), state_.value(), &result); 242*6777b538SAndroid Build Coastguard Worker return CheckedNumeric<T>(result, IsValid() && success); 243*6777b538SAndroid Build Coastguard Worker } 244*6777b538SAndroid Build Coastguard Worker 245*6777b538SAndroid Build Coastguard Worker template <typename Src> CheckedNumeric(Src value,bool is_valid)246*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric(Src value, bool is_valid) 247*6777b538SAndroid Build Coastguard Worker : state_(value, is_valid) {} 248*6777b538SAndroid Build Coastguard Worker 249*6777b538SAndroid Build Coastguard Worker // These wrappers allow us to handle state the same way for both 250*6777b538SAndroid Build Coastguard Worker // CheckedNumeric and POD arithmetic types. 251*6777b538SAndroid Build Coastguard Worker template <typename Src> 252*6777b538SAndroid Build Coastguard Worker struct Wrapper { is_validWrapper253*6777b538SAndroid Build Coastguard Worker static constexpr bool is_valid(Src) { return true; } valueWrapper254*6777b538SAndroid Build Coastguard Worker static constexpr Src value(Src value) { return value; } 255*6777b538SAndroid Build Coastguard Worker }; 256*6777b538SAndroid Build Coastguard Worker 257*6777b538SAndroid Build Coastguard Worker template <typename Src> 258*6777b538SAndroid Build Coastguard Worker struct Wrapper<CheckedNumeric<Src>> { 259*6777b538SAndroid Build Coastguard Worker static constexpr bool is_valid(const CheckedNumeric<Src> v) { 260*6777b538SAndroid Build Coastguard Worker return v.IsValid(); 261*6777b538SAndroid Build Coastguard Worker } 262*6777b538SAndroid Build Coastguard Worker static constexpr Src value(const CheckedNumeric<Src> v) { 263*6777b538SAndroid Build Coastguard Worker return v.state_.value(); 264*6777b538SAndroid Build Coastguard Worker } 265*6777b538SAndroid Build Coastguard Worker }; 266*6777b538SAndroid Build Coastguard Worker 267*6777b538SAndroid Build Coastguard Worker template <typename Src> 268*6777b538SAndroid Build Coastguard Worker struct Wrapper<StrictNumeric<Src>> { 269*6777b538SAndroid Build Coastguard Worker static constexpr bool is_valid(const StrictNumeric<Src>) { return true; } 270*6777b538SAndroid Build Coastguard Worker static constexpr Src value(const StrictNumeric<Src> v) { 271*6777b538SAndroid Build Coastguard Worker return static_cast<Src>(v); 272*6777b538SAndroid Build Coastguard Worker } 273*6777b538SAndroid Build Coastguard Worker }; 274*6777b538SAndroid Build Coastguard Worker }; 275*6777b538SAndroid Build Coastguard Worker 276*6777b538SAndroid Build Coastguard Worker // Convenience functions to avoid the ugly template disambiguator syntax. 277*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 278*6777b538SAndroid Build Coastguard Worker constexpr bool IsValidForType(const CheckedNumeric<Src> value) { 279*6777b538SAndroid Build Coastguard Worker return value.template IsValid<Dst>(); 280*6777b538SAndroid Build Coastguard Worker } 281*6777b538SAndroid Build Coastguard Worker 282*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src> 283*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric<Dst> ValueOrDieForType( 284*6777b538SAndroid Build Coastguard Worker const CheckedNumeric<Src> value) { 285*6777b538SAndroid Build Coastguard Worker return value.template ValueOrDie<Dst>(); 286*6777b538SAndroid Build Coastguard Worker } 287*6777b538SAndroid Build Coastguard Worker 288*6777b538SAndroid Build Coastguard Worker template <typename Dst, typename Src, typename Default> 289*6777b538SAndroid Build Coastguard Worker constexpr StrictNumeric<Dst> ValueOrDefaultForType( 290*6777b538SAndroid Build Coastguard Worker const CheckedNumeric<Src> value, 291*6777b538SAndroid Build Coastguard Worker const Default default_value) { 292*6777b538SAndroid Build Coastguard Worker return value.template ValueOrDefault<Dst>(default_value); 293*6777b538SAndroid Build Coastguard Worker } 294*6777b538SAndroid Build Coastguard Worker 295*6777b538SAndroid Build Coastguard Worker // Convenience wrapper to return a new CheckedNumeric from the provided 296*6777b538SAndroid Build Coastguard Worker // arithmetic or CheckedNumericType. 297*6777b538SAndroid Build Coastguard Worker template <typename T> 298*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric<typename UnderlyingType<T>::type> MakeCheckedNum( 299*6777b538SAndroid Build Coastguard Worker const T value) { 300*6777b538SAndroid Build Coastguard Worker return value; 301*6777b538SAndroid Build Coastguard Worker } 302*6777b538SAndroid Build Coastguard Worker 303*6777b538SAndroid Build Coastguard Worker // These implement the variadic wrapper for the math operations. 304*6777b538SAndroid Build Coastguard Worker template <template <typename, typename> class M, typename L, typename R> 305*6777b538SAndroid Build Coastguard Worker constexpr CheckedNumeric<typename MathWrapper<M, L, R>::type> CheckMathOp( 306*6777b538SAndroid Build Coastguard Worker const L lhs, 307*6777b538SAndroid Build Coastguard Worker const R rhs) { 308*6777b538SAndroid Build Coastguard Worker using Math = typename MathWrapper<M, L, R>::math; 309*6777b538SAndroid Build Coastguard Worker return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs, 310*6777b538SAndroid Build Coastguard Worker rhs); 311*6777b538SAndroid Build Coastguard Worker } 312*6777b538SAndroid Build Coastguard Worker 313*6777b538SAndroid Build Coastguard Worker // General purpose wrapper template for arithmetic operations. 314*6777b538SAndroid Build Coastguard Worker template <template <typename, typename> class M, 315*6777b538SAndroid Build Coastguard Worker typename L, 316*6777b538SAndroid Build Coastguard Worker typename R, 317*6777b538SAndroid Build Coastguard Worker typename... Args> 318*6777b538SAndroid Build Coastguard Worker constexpr auto CheckMathOp(const L lhs, const R rhs, const Args... args) { 319*6777b538SAndroid Build Coastguard Worker return CheckMathOp<M>(CheckMathOp<M>(lhs, rhs), args...); 320*6777b538SAndroid Build Coastguard Worker } 321*6777b538SAndroid Build Coastguard Worker 322*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Add, +, +=) 323*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Sub, -, -=) 324*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mul, *, *=) 325*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Div, /, /=) 326*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Mod, %, %=) 327*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Lsh, <<, <<=) 328*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Rsh, >>, >>=) 329*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, And, &, &=) 330*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Or, |, |=) 331*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_OPERATORS(Checked, Check, Xor, ^, ^=) 332*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Max) 333*6777b538SAndroid Build Coastguard Worker BASE_NUMERIC_ARITHMETIC_VARIADIC(Checked, Check, Min) 334*6777b538SAndroid Build Coastguard Worker 335*6777b538SAndroid Build Coastguard Worker // These are some extra StrictNumeric operators to support simple pointer 336*6777b538SAndroid Build Coastguard Worker // arithmetic with our result types. Since wrapping on a pointer is always 337*6777b538SAndroid Build Coastguard Worker // bad, we trigger the CHECK condition here. 338*6777b538SAndroid Build Coastguard Worker template <typename L, typename R> 339*6777b538SAndroid Build Coastguard Worker L* operator+(L* lhs, const StrictNumeric<R> rhs) { 340*6777b538SAndroid Build Coastguard Worker const uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs), 341*6777b538SAndroid Build Coastguard Worker CheckMul(sizeof(L), static_cast<R>(rhs))) 342*6777b538SAndroid Build Coastguard Worker .template ValueOrDie<uintptr_t>(); 343*6777b538SAndroid Build Coastguard Worker return reinterpret_cast<L*>(result); 344*6777b538SAndroid Build Coastguard Worker } 345*6777b538SAndroid Build Coastguard Worker 346*6777b538SAndroid Build Coastguard Worker template <typename L, typename R> 347*6777b538SAndroid Build Coastguard Worker L* operator-(L* lhs, const StrictNumeric<R> rhs) { 348*6777b538SAndroid Build Coastguard Worker const uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs), 349*6777b538SAndroid Build Coastguard Worker CheckMul(sizeof(L), static_cast<R>(rhs))) 350*6777b538SAndroid Build Coastguard Worker .template ValueOrDie<uintptr_t>(); 351*6777b538SAndroid Build Coastguard Worker return reinterpret_cast<L*>(result); 352*6777b538SAndroid Build Coastguard Worker } 353*6777b538SAndroid Build Coastguard Worker 354*6777b538SAndroid Build Coastguard Worker } // namespace internal 355*6777b538SAndroid Build Coastguard Worker 356*6777b538SAndroid Build Coastguard Worker using internal::CheckAdd; 357*6777b538SAndroid Build Coastguard Worker using internal::CheckAnd; 358*6777b538SAndroid Build Coastguard Worker using internal::CheckDiv; 359*6777b538SAndroid Build Coastguard Worker using internal::CheckedNumeric; 360*6777b538SAndroid Build Coastguard Worker using internal::CheckLsh; 361*6777b538SAndroid Build Coastguard Worker using internal::CheckMax; 362*6777b538SAndroid Build Coastguard Worker using internal::CheckMin; 363*6777b538SAndroid Build Coastguard Worker using internal::CheckMod; 364*6777b538SAndroid Build Coastguard Worker using internal::CheckMul; 365*6777b538SAndroid Build Coastguard Worker using internal::CheckOr; 366*6777b538SAndroid Build Coastguard Worker using internal::CheckRsh; 367*6777b538SAndroid Build Coastguard Worker using internal::CheckSub; 368*6777b538SAndroid Build Coastguard Worker using internal::CheckXor; 369*6777b538SAndroid Build Coastguard Worker using internal::IsValidForType; 370*6777b538SAndroid Build Coastguard Worker using internal::MakeCheckedNum; 371*6777b538SAndroid Build Coastguard Worker using internal::ValueOrDefaultForType; 372*6777b538SAndroid Build Coastguard Worker using internal::ValueOrDieForType; 373*6777b538SAndroid Build Coastguard Worker 374*6777b538SAndroid Build Coastguard Worker } // namespace base 375*6777b538SAndroid Build Coastguard Worker 376*6777b538SAndroid Build Coastguard Worker #endif // BASE_NUMERICS_CHECKED_MATH_H_ 377