| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_NUMERICS_SAFE_MATH_H_ | 5 #ifndef BASE_NUMERICS_SAFE_MATH_H_ |
| 6 #define BASE_NUMERICS_SAFE_MATH_H_ | 6 #define BASE_NUMERICS_SAFE_MATH_H_ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 template <typename T> | 68 template <typename T> |
| 69 class CheckedNumeric { | 69 class CheckedNumeric { |
| 70 static_assert(std::is_arithmetic<T>::value, | 70 static_assert(std::is_arithmetic<T>::value, |
| 71 "CheckedNumeric<T>: T must be a numeric type."); | 71 "CheckedNumeric<T>: T must be a numeric type."); |
| 72 | 72 |
| 73 public: | 73 public: |
| 74 typedef T type; | 74 typedef T type; |
| 75 | 75 |
| 76 CheckedNumeric() {} | 76 constexpr CheckedNumeric() {} |
| 77 | 77 |
| 78 // Copy constructor. | 78 // Copy constructor. |
| 79 template <typename Src> | 79 template <typename Src> |
| 80 CheckedNumeric(const CheckedNumeric<Src>& rhs) | 80 constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs) |
| 81 : state_(rhs.state_.value(), rhs.IsValid()) {} | 81 : state_(rhs.state_.value(), rhs.IsValid()) {} |
| 82 | 82 |
| 83 template <typename Src> | 83 template <typename Src> |
| 84 friend class CheckedNumeric; | 84 friend class CheckedNumeric; |
| 85 | 85 |
| 86 // This is not an explicit constructor because we implicitly upgrade regular | 86 // This is not an explicit constructor because we implicitly upgrade regular |
| 87 // numerics to CheckedNumerics to make them easier to use. | 87 // numerics to CheckedNumerics to make them easier to use. |
| 88 template <typename Src> | 88 template <typename Src> |
| 89 CheckedNumeric(Src value) // NOLINT(runtime/explicit) | 89 constexpr CheckedNumeric(Src value) // NOLINT(runtime/explicit) |
| 90 : state_(value) { | 90 : state_(value) { |
| 91 static_assert(std::numeric_limits<Src>::is_specialized, | 91 static_assert(std::numeric_limits<Src>::is_specialized, |
| 92 "Argument must be numeric."); | 92 "Argument must be numeric."); |
| 93 } | 93 } |
| 94 | 94 |
| 95 // This is not an explicit constructor because we want a seamless conversion | 95 // This is not an explicit constructor because we want a seamless conversion |
| 96 // from StrictNumeric types. | 96 // from StrictNumeric types. |
| 97 template <typename Src> | 97 template <typename Src> |
| 98 CheckedNumeric(StrictNumeric<Src> value) // NOLINT(runtime/explicit) | 98 constexpr CheckedNumeric( |
| 99 : state_(static_cast<Src>(value)) { | 99 StrictNumeric<Src> value) // NOLINT(runtime/explicit) |
| 100 } | 100 : state_(static_cast<Src>(value)) {} |
| 101 | 101 |
| 102 // IsValid() is the public API to test if a CheckedNumeric is currently valid. | 102 // IsValid() is the public API to test if a CheckedNumeric is currently valid. |
| 103 bool IsValid() const { return state_.is_valid(); } | 103 constexpr bool IsValid() const { return state_.is_valid(); } |
| 104 | 104 |
| 105 // ValueOrDie() The primary accessor for the underlying value. If the current | 105 // ValueOrDie() The primary accessor for the underlying value. If the current |
| 106 // state is not valid it will CHECK and crash. | 106 // state is not valid it will CHECK and crash. |
| 107 T ValueOrDie() const { | 107 constexpr T ValueOrDie() const { |
| 108 CHECK(IsValid()); | 108 return IsValid() ? state_.value() : CheckOnFailure::HandleFailure<T>(); |
| 109 return state_.value(); | |
| 110 } | 109 } |
| 111 | 110 |
| 112 // ValueOrDefault(T default_value) A convenience method that returns the | 111 // ValueOrDefault(T default_value) A convenience method that returns the |
| 113 // current value if the state is valid, and the supplied default_value for | 112 // current value if the state is valid, and the supplied default_value for |
| 114 // any other state. | 113 // any other state. |
| 115 T ValueOrDefault(T default_value) const { | 114 constexpr T ValueOrDefault(T default_value) const { |
| 116 return IsValid() ? state_.value() : default_value; | 115 return IsValid() ? state_.value() : default_value; |
| 117 } | 116 } |
| 118 | 117 |
| 119 // ValueFloating() - Since floating point values include their validity state, | 118 // ValueFloating() - Since floating point values include their validity state, |
| 120 // we provide an easy method for extracting them directly, without a risk of | 119 // we provide an easy method for extracting them directly, without a risk of |
| 121 // crashing on a CHECK. | 120 // crashing on a CHECK. |
| 122 T ValueFloating() const { | 121 constexpr T ValueFloating() const { |
| 123 static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float."); | 122 static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float."); |
| 124 return state_.value(); | 123 return state_.value(); |
| 125 } | 124 } |
| 126 | 125 |
| 127 // This friend method is available solely for providing more detailed logging | 126 // This friend method is available solely for providing more detailed logging |
| 128 // in the the tests. Do not implement it in production code, because the | 127 // in the the tests. Do not implement it in production code, because the |
| 129 // underlying values may change at any time. | 128 // underlying values may change at any time. |
| 130 template <typename U> | 129 template <typename U> |
| 131 friend U GetNumericValueForTest(const CheckedNumeric<U>& src); | 130 friend U GetNumericValueForTest(const CheckedNumeric<U>& src); |
| 132 | 131 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 158 // Absolute value is always valid for floating point. | 157 // Absolute value is always valid for floating point. |
| 159 T value = 0; | 158 T value = 0; |
| 160 bool is_valid = (std::numeric_limits<T>::is_iec559 || IsValid()) && | 159 bool is_valid = (std::numeric_limits<T>::is_iec559 || IsValid()) && |
| 161 CheckedAbs(state_.value(), &value); | 160 CheckedAbs(state_.value(), &value); |
| 162 return CheckedNumeric<T>(value, is_valid); | 161 return CheckedNumeric<T>(value, is_valid); |
| 163 } | 162 } |
| 164 | 163 |
| 165 // This function is available only for integral types. It returns an unsigned | 164 // This function is available only for integral types. It returns an unsigned |
| 166 // integer of the same width as the source type, containing the absolute value | 165 // integer of the same width as the source type, containing the absolute value |
| 167 // of the source, and properly handling signed min. | 166 // of the source, and properly handling signed min. |
| 168 CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const { | 167 constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> |
| 168 UnsignedAbs() const { |
| 169 return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( | 169 return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( |
| 170 SafeUnsignedAbs(state_.value()), state_.is_valid()); | 170 SafeUnsignedAbs(state_.value()), state_.is_valid()); |
| 171 } | 171 } |
| 172 | 172 |
| 173 CheckedNumeric& operator++() { | 173 CheckedNumeric& operator++() { |
| 174 *this += 1; | 174 *this += 1; |
| 175 return *this; | 175 return *this; |
| 176 } | 176 } |
| 177 | 177 |
| 178 CheckedNumeric operator++(int) { | 178 CheckedNumeric operator++(int) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 bool is_valid = state_.is_valid() && Wrapper<R>::is_valid(rhs) && | 215 bool is_valid = state_.is_valid() && Wrapper<R>::is_valid(rhs) && |
| 216 Math::Op(state_.value(), Wrapper<R>::value(rhs), &result); | 216 Math::Op(state_.value(), Wrapper<R>::value(rhs), &result); |
| 217 *this = CheckedNumeric<T>(result, is_valid); | 217 *this = CheckedNumeric<T>(result, is_valid); |
| 218 return *this; | 218 return *this; |
| 219 }; | 219 }; |
| 220 | 220 |
| 221 private: | 221 private: |
| 222 CheckedNumericState<T> state_; | 222 CheckedNumericState<T> state_; |
| 223 | 223 |
| 224 template <typename Src> | 224 template <typename Src> |
| 225 CheckedNumeric(Src value, bool is_valid) : state_(value, is_valid) {} | 225 constexpr CheckedNumeric(Src value, bool is_valid) |
| 226 : state_(value, is_valid) {} |
| 226 | 227 |
| 227 // These wrappers allow us to handle state the same way for both | 228 // These wrappers allow us to handle state the same way for both |
| 228 // CheckedNumeric and POD arithmetic types. | 229 // CheckedNumeric and POD arithmetic types. |
| 229 template <typename Src> | 230 template <typename Src> |
| 230 struct Wrapper { | 231 struct Wrapper { |
| 231 static bool is_valid(Src) { return true; } | 232 static constexpr bool is_valid(Src) { return true; } |
| 232 static Src value(Src value) { return value; } | 233 static constexpr Src value(Src value) { return value; } |
| 233 }; | 234 }; |
| 234 | 235 |
| 235 template <typename Src> | 236 template <typename Src> |
| 236 struct Wrapper<CheckedNumeric<Src>> { | 237 struct Wrapper<CheckedNumeric<Src>> { |
| 237 static bool is_valid(const CheckedNumeric<Src>& v) { return v.IsValid(); } | 238 static constexpr bool is_valid(const CheckedNumeric<Src>& v) { |
| 238 static Src value(const CheckedNumeric<Src>& v) { return v.state_.value(); } | 239 return v.IsValid(); |
| 240 } |
| 241 static constexpr Src value(const CheckedNumeric<Src>& v) { |
| 242 return v.state_.value(); |
| 243 } |
| 239 }; | 244 }; |
| 240 }; | 245 }; |
| 241 | 246 |
| 242 // This is just boilerplate for the standard arithmetic operator overloads. | 247 // This is just boilerplate for the standard arithmetic operator overloads. |
| 243 // A macro isn't the nicest solution, but it beats rewriting these repeatedly. | 248 // A macro isn't the nicest solution, but it beats rewriting these repeatedly. |
| 244 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ | 249 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ |
| 245 /* Binary arithmetic operator for all CheckedNumeric operations. */ \ | 250 /* Binary arithmetic operator for all CheckedNumeric operations. */ \ |
| 246 template <typename L, typename R, \ | 251 template <typename L, typename R, \ |
| 247 typename std::enable_if<UnderlyingType<L>::is_numeric && \ | 252 typename std::enable_if<UnderlyingType<L>::is_numeric && \ |
| 248 UnderlyingType<R>::is_numeric && \ | 253 UnderlyingType<R>::is_numeric && \ |
| (...skipping 23 matching lines...) Expand all Loading... |
| 272 | 277 |
| 273 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS | 278 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS |
| 274 | 279 |
| 275 } // namespace internal | 280 } // namespace internal |
| 276 | 281 |
| 277 using internal::CheckedNumeric; | 282 using internal::CheckedNumeric; |
| 278 | 283 |
| 279 } // namespace base | 284 } // namespace base |
| 280 | 285 |
| 281 #endif // BASE_NUMERICS_SAFE_MATH_H_ | 286 #endif // BASE_NUMERICS_SAFE_MATH_H_ |
| OLD | NEW |