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