Index: base/numerics/safe_math.h |
diff --git a/base/numerics/safe_math.h b/base/numerics/safe_math.h |
index 73bed4e0538b519aac245a8cfdf8a6cd24c5a518..3d765c949a8ed1adb5d3d4655f0f08371ecbc7f4 100644 |
--- a/base/numerics/safe_math.h |
+++ b/base/numerics/safe_math.h |
@@ -37,13 +37,21 @@ namespace internal { |
// CheckAnd() - Bitwise AND (integer only with unsigned result). |
// CheckOr() - Bitwise OR (integer only with unsigned result). |
// CheckXor() - Bitwise XOR (integer only with unsigned result). |
+// CheckMax() - Maximum of supplied arguments. |
+// CheckMin() - Minimum of supplied arguments. |
// |
// The unary negation, increment, and decrement operators are supported, along |
// with the following unary arithmetic methods, which return a new |
// CheckedNumeric as a result of the operation: |
// Abs() - Absolute value. |
-// UnsignedAbs() - Absolute value as an equival-width unsigned underlying type |
+// UnsignedAbs() - Absolute value as an equal-width unsigned underlying type |
// (valid for only integral types). |
+// Max() - Returns whichever is greater of the current instance or argument. |
+// The underlying return type is whichever has the greatest magnitude. |
+// Min() - Returns whichever is lowest of the current instance or argument. |
+// The underlying return type is whichever has can represent the lowest |
+// number in the smallest width (e.g. int8_t over unsigned, int over |
+// int8_t, and float over int). |
// |
// The following methods convert from CheckedNumeric to standard numeric values: |
// AssignIfValid() - Assigns the underlying value to the supplied destination |
@@ -73,7 +81,7 @@ namespace internal { |
// derived from casting the current instance to a CheckedNumeric of |
// the supplied destination type. |
// CheckNum() - Creates a new CheckedNumeric from the underlying type of the |
-// supplied arithmetic or CheckedNumeric type. |
+// supplied arithmetic, CheckedNumeric, or StrictNumeric type. |
// |
// Comparison operations are explicitly not supported because they could result |
// in a crash on an unexpected CHECK condition. You should use patterns like the |
@@ -220,6 +228,36 @@ class CheckedNumeric { |
return CheckedNumeric<T>(value, is_valid); |
} |
+ template <typename U> |
+ constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max( |
+ const U rhs) const { |
+ using R = typename UnderlyingType<U>::type; |
+ using result_type = typename MathWrapper<CheckedMaxOp, T, U>::type; |
+ // TODO(jschuh): This can be converted to the MathOp version and remain |
+ // constexpr once we have C++14 support. |
+ return CheckedNumeric<result_type>( |
+ static_cast<result_type>( |
+ IsGreater<T, R>::Test(state_.value(), Wrapper<U>::value(rhs)) |
+ ? state_.value() |
+ : Wrapper<U>::value(rhs)), |
+ state_.is_valid() && Wrapper<U>::is_valid(rhs)); |
+ } |
+ |
+ template <typename U> |
+ constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min( |
+ const U rhs) const { |
+ using R = typename UnderlyingType<U>::type; |
+ using result_type = typename MathWrapper<CheckedMinOp, T, U>::type; |
+ // TODO(jschuh): This can be converted to the MathOp version and remain |
+ // constexpr once we have C++14 support. |
+ return CheckedNumeric<result_type>( |
+ static_cast<result_type>( |
+ IsLess<T, R>::Test(state_.value(), Wrapper<U>::value(rhs)) |
+ ? state_.value() |
+ : Wrapper<U>::value(rhs)), |
+ state_.is_valid() && Wrapper<U>::is_valid(rhs)); |
+ } |
+ |
// This function is available only for integral types. It returns an unsigned |
// integer of the same width as the source type, containing the absolute value |
// of the source, and properly handling signed min. |
@@ -300,6 +338,14 @@ class CheckedNumeric { |
return v.state_.value(); |
} |
}; |
+ |
+ template <typename Src> |
+ struct Wrapper<StrictNumeric<Src>> { |
+ static constexpr bool is_valid(const StrictNumeric<Src>) { return true; } |
+ static constexpr Src value(const StrictNumeric<Src> v) { |
+ return static_cast<Src>(v); |
+ } |
+ }; |
}; |
// Convenience functions to avoid the ugly template disambiguator syntax. |
@@ -350,7 +396,8 @@ struct ResultType { |
// Convience wrapper to return a new CheckedNumeric from the provided arithmetic |
// or CheckedNumericType. |
template <typename T> |
-CheckedNumeric<typename UnderlyingType<T>::type> CheckNum(T value) { |
+constexpr CheckedNumeric<typename UnderlyingType<T>::type> CheckNum( |
+ const T value) { |
return value; |
} |
@@ -363,8 +410,9 @@ CheckedNumeric<typename MathWrapper<M, L, R>::type> ChkMathOp(const L lhs, |
using Math = typename MathWrapper<M, L, R>::math; |
return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs, |
rhs); |
-}; |
+} |
+// General purpose wrapper template for arithmetic operations. |
template <template <typename, typename, typename> class M, |
typename L, |
typename R, |
@@ -376,8 +424,16 @@ ChkMathOp(const L lhs, const R rhs, const Args... args) { |
: decltype(ChkMathOp<M>(tmp, args...))(tmp); |
}; |
-// This is just boilerplate for the standard arithmetic operator overloads. |
-// A macro isn't the nicest solution, but it beats rewriting these repeatedly. |
+// The following macros are just boilerplate for the standard arithmetic |
+// operator overloads and variadic function templates. A macro isn't the nicest |
+// solution, but it beats rewriting these over and over again. |
+#define BASE_NUMERIC_ARITHMETIC_VARIADIC(NAME) \ |
+ template <typename L, typename R, typename... Args> \ |
+ CheckedNumeric<typename ResultType<Checked##NAME##Op, L, R, Args...>::type> \ |
+ Check##NAME(const L lhs, const R rhs, const Args... args) { \ |
+ return ChkMathOp<Checked##NAME##Op, L, R, Args...>(lhs, rhs, args...); \ |
+ } |
+ |
#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ |
/* Binary arithmetic operator for all CheckedNumeric operations. */ \ |
template <typename L, typename R, \ |
@@ -394,11 +450,7 @@ ChkMathOp(const L lhs, const R rhs, const Args... args) { |
return MathOp<Checked##NAME##Op>(rhs); \ |
} \ |
/* Variadic arithmetic functions that return CheckedNumeric. */ \ |
- template <typename L, typename R, typename... Args> \ |
- CheckedNumeric<typename ResultType<Checked##NAME##Op, L, R, Args...>::type> \ |
- Check##NAME(const L lhs, const R rhs, const Args... args) { \ |
- return ChkMathOp<Checked##NAME##Op, L, R, Args...>(lhs, rhs, args...); \ |
- } |
+ BASE_NUMERIC_ARITHMETIC_VARIADIC(NAME) |
BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=) |
BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=) |
@@ -410,7 +462,10 @@ BASE_NUMERIC_ARITHMETIC_OPERATORS(Rsh, >>, >>=) |
BASE_NUMERIC_ARITHMETIC_OPERATORS(And, &, &=) |
BASE_NUMERIC_ARITHMETIC_OPERATORS(Or, |, |=) |
BASE_NUMERIC_ARITHMETIC_OPERATORS(Xor, ^, ^=) |
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Max) |
+BASE_NUMERIC_ARITHMETIC_VARIADIC(Min) |
+#undef BASE_NUMERIC_ARITHMETIC_VARIADIC |
#undef BASE_NUMERIC_ARITHMETIC_OPERATORS |
// These are some extra StrictNumeric operators to support simple pointer |
@@ -439,6 +494,8 @@ using internal::IsValidForType; |
using internal::ValueOrDieForType; |
using internal::ValueOrDefaultForType; |
using internal::CheckNum; |
+using internal::CheckMax; |
+using internal::CheckMin; |
using internal::CheckAdd; |
using internal::CheckSub; |
using internal::CheckMul; |