xref: /aosp_15_r20/external/libchrome/base/numerics/checked_math.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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