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> |
11 #include <type_traits> | 11 #include <type_traits> |
12 | 12 |
13 #include "base/numerics/safe_math_impl.h" | 13 #include "base/numerics/safe_math_impl.h" |
14 | 14 |
15 namespace base { | 15 namespace base { |
16 namespace internal { | 16 namespace internal { |
17 | 17 |
18 // CheckedNumeric implements all the logic and operators for detecting integer | 18 // CheckedNumeric<> implements all the logic and operators for detecting integer |
19 // boundary conditions such as overflow, underflow, and invalid conversions. | 19 // boundary conditions such as overflow, underflow, and invalid conversions. |
20 // The CheckedNumeric type implicitly converts from floating point and integer | 20 // The CheckedNumeric type implicitly converts from floating point and integer |
21 // data types, and contains overloads for basic arithmetic operations (i.e.: +, | 21 // data types, and contains overloads for basic arithmetic operations (i.e.: +, |
22 // -, *, / for all types and %, <<, >>, &, |, ^ for integers; additionally the | 22 // -, *, / for all types and %, <<, >>, &, |, ^ for integers; additionally the |
23 // result of all bitwise logical operations is always promoted to an unsigned | 23 // result of all bitwise logical operations is always promoted to an unsigned |
24 // CheckedNumeric type matching the width of the larger operand). | 24 // CheckedNumeric type matching the width of the larger operand). |
25 // | 25 // |
26 // You may also use one of the variadic convenience functions, which accept | 26 // You may also use one of the variadic convenience functions, which accept |
27 // standard arithmetic or CheckedNumeric types, perform arithmetic operations, | 27 // standard arithmetic or CheckedNumeric types, perform arithmetic operations, |
28 // and return a CheckedNumeric result. The supported functions are: | 28 // and return a CheckedNumeric result. The supported functions are: |
29 // CheckAdd() - Addition. | 29 // CheckAdd() - Addition. |
30 // CheckSub() - Subtraction. | 30 // CheckSub() - Subtraction. |
31 // CheckMul() - Multiplication. | 31 // CheckMul() - Multiplication. |
32 // CheckDiv() - Division. | 32 // CheckDiv() - Division. |
33 // CheckMod() - Modulous (integer only). | 33 // CheckMod() - Modulous (integer only). |
34 // CheckLsh() - Left integer shift (integer only). | 34 // CheckLsh() - Left integer shift (integer only). |
35 // CheckRsh() - Right integer shift (integer only). | 35 // CheckRsh() - Right integer shift (integer only). |
| 36 // CheckAnd() - Bitwise AND (integer only with unsigned result). |
| 37 // CheckOr() - Bitwise OR (integer only with unsigned result). |
| 38 // CheckXor() - Bitwise XOR (integer only with unsigned result). |
36 // | 39 // |
37 // The unary negation, increment, and decrement operators are supported, along | 40 // The unary negation, increment, and decrement operators are supported, along |
38 // with the following unary arithmetic methods, which return a new | 41 // with the following unary arithmetic methods, which return a new |
39 // CheckedNumeric as a result of the operation: | 42 // CheckedNumeric as a result of the operation: |
40 // Abs() - Absolute value. | 43 // Abs() - Absolute value. |
41 // UnsignedAbs() - Absolute value as an equival-width unsigned underlying type | 44 // UnsignedAbs() - Absolute value as an equival-width unsigned underlying type |
42 // (valid for only integral types). | 45 // (valid for only integral types). |
43 // | 46 // |
44 // The following methods convert from CheckedNumeric to standard numeric values: | 47 // The following methods convert from CheckedNumeric to standard numeric values: |
| 48 // AssignIfValid() - Assigns the underlying value to the supplied destination |
| 49 // pointer if the value is currently valid and within the range |
| 50 // supported by the destination type. Returns true on success. |
| 51 // **************************************************************************** |
| 52 // * WARNING: All of the following functions return a StrictNumeric, which * |
| 53 // * is valid for comparison and assignment operations, but will trigger a * |
| 54 // * compile failure on attempts to assign to a type of insufficient range. * |
| 55 // **************************************************************************** |
45 // IsValid() - Returns true if the underlying numeric value is valid (i.e. has | 56 // IsValid() - Returns true if the underlying numeric value is valid (i.e. has |
46 // has not wrapped and is not the result of an invalid conversion). | 57 // has not wrapped and is not the result of an invalid conversion). |
47 // AssignIfValid() - Assigns the underlying value to the supplied destination | |
48 // pointer if the value is currently valid and within the range | |
49 // supported by the destination type. Returns true on success. | |
50 // ValueOrDie() - Returns the underlying value. If the state is not valid this | 58 // ValueOrDie() - Returns the underlying value. If the state is not valid this |
51 // call will crash on a CHECK. | 59 // call will crash on a CHECK. |
52 // ValueOrDefault() - Returns the current value, or the supplied default if the | 60 // ValueOrDefault() - Returns the current value, or the supplied default if the |
53 // state is not valid (will not trigger a CHECK). | 61 // state is not valid (will not trigger a CHECK). |
54 // ValueFloating() - Returns the underlying floating point value (valid only | 62 // |
55 // for floating point CheckedNumeric types; will not cause a CHECK). | 63 // The following wrapper functions can be used to avoid the template |
| 64 // disambiguator syntax when converting a destination type. |
| 65 // IsValidForType<>() in place of: a.template IsValid<Dst>() |
| 66 // ValueOrDieForType<>() in place of: a.template ValueOrDie() |
| 67 // ValueOrDefaultForType<>() in place of: a.template ValueOrDefault(default) |
56 // | 68 // |
57 // The following are general utility methods that are useful for converting | 69 // The following are general utility methods that are useful for converting |
58 // between arithmetic types and CheckedNumeric types: | 70 // between arithmetic types and CheckedNumeric types: |
59 // CheckedNumeric::Cast<Dst>() - Instance method returning a CheckedNumeric | 71 // CheckedNumeric::Cast<Dst>() - Instance method returning a CheckedNumeric |
60 // derived from casting the current instance to a CheckedNumeric of | 72 // derived from casting the current instance to a CheckedNumeric of |
61 // the supplied destination type. | 73 // the supplied destination type. |
62 // CheckNum() - Creates a new CheckedNumeric from the underlying type of the | 74 // CheckNum() - Creates a new CheckedNumeric from the underlying type of the |
63 // supplied arithmetic or CheckedNumeric type. | 75 // supplied arithmetic or CheckedNumeric type. |
64 // | 76 // |
65 // Comparison operations are explicitly not supported because they could result | 77 // Comparison operations are explicitly not supported because they could result |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 | 136 |
125 // ValueOrDie() - The primary accessor for the underlying value. If the | 137 // ValueOrDie() - The primary accessor for the underlying value. If the |
126 // current state is not valid it will CHECK and crash. | 138 // current state is not valid it will CHECK and crash. |
127 // A range checked destination type can be supplied using the Dst template | 139 // A range checked destination type can be supplied using the Dst template |
128 // parameter, which will trigger a CHECK if the value is not in bounds for | 140 // parameter, which will trigger a CHECK if the value is not in bounds for |
129 // the destination. | 141 // the destination. |
130 // The CHECK behavior can be overridden by supplying a handler as a | 142 // The CHECK behavior can be overridden by supplying a handler as a |
131 // template parameter, for test code, etc. However, the handler cannot access | 143 // template parameter, for test code, etc. However, the handler cannot access |
132 // the underlying value, and it is not available through other means. | 144 // the underlying value, and it is not available through other means. |
133 template <typename Dst = T, class CheckHandler = CheckOnFailure> | 145 template <typename Dst = T, class CheckHandler = CheckOnFailure> |
134 constexpr Dst ValueOrDie() const { | 146 constexpr StrictNumeric<Dst> ValueOrDie() const { |
135 return IsValid<Dst>() ? state_.value() | 147 return IsValid<Dst>() ? static_cast<Dst>(state_.value()) |
136 : CheckHandler::template HandleFailure<Dst>(); | 148 : CheckHandler::template HandleFailure<Dst>(); |
137 } | 149 } |
138 | 150 |
139 // ValueOrDefault(T default_value) - A convenience method that returns the | 151 // ValueOrDefault(T default_value) - A convenience method that returns the |
140 // current value if the state is valid, and the supplied default_value for | 152 // current value if the state is valid, and the supplied default_value for |
141 // any other state. | 153 // any other state. |
142 // A range checked destination type can be supplied using the Dst template | 154 // A range checked destination type can be supplied using the Dst template |
143 // parameter. WARNING: This function may fail to compile or CHECK at runtime | 155 // parameter. WARNING: This function may fail to compile or CHECK at runtime |
144 // if the supplied default_value is not within range of the destination type. | 156 // if the supplied default_value is not within range of the destination type. |
145 template <typename Dst = T, typename Src> | 157 template <typename Dst = T, typename Src> |
146 constexpr Dst ValueOrDefault(const Src default_value) const { | 158 constexpr StrictNumeric<Dst> ValueOrDefault(const Src default_value) const { |
147 return IsValid<Dst>() ? state_.value() : checked_cast<Dst>(default_value); | 159 return IsValid<Dst>() ? static_cast<Dst>(state_.value()) |
148 } | 160 : checked_cast<Dst>(default_value); |
149 | |
150 // ValueFloating() - Since floating point values include their validity state, | |
151 // we provide an easy method for extracting them directly, without a risk of | |
152 // crashing on a CHECK. | |
153 // A range checked destination type can be supplied using the Dst template | |
154 // parameter. | |
155 template <typename Dst = T> | |
156 constexpr Dst ValueFloating() const { | |
157 static_assert(std::numeric_limits<T>::is_iec559, | |
158 "Type must be floating point."); | |
159 static_assert(std::numeric_limits<Dst>::is_iec559, | |
160 "Type must be floating point."); | |
161 return static_cast<Dst>(state_.value()); | |
162 } | 161 } |
163 | 162 |
164 // Returns a checked numeric of the specified type, cast from the current | 163 // Returns a checked numeric of the specified type, cast from the current |
165 // CheckedNumeric. If the current state is invalid or the destination cannot | 164 // CheckedNumeric. If the current state is invalid or the destination cannot |
166 // represent the result then the returned CheckedNumeric will be invalid. | 165 // represent the result then the returned CheckedNumeric will be invalid. |
167 template <typename Dst> | 166 template <typename Dst> |
168 constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const { | 167 constexpr CheckedNumeric<typename UnderlyingType<Dst>::type> Cast() const { |
169 return *this; | 168 return *this; |
170 } | 169 } |
171 | 170 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 struct Wrapper<CheckedNumeric<Src>> { | 294 struct Wrapper<CheckedNumeric<Src>> { |
296 static constexpr bool is_valid(const CheckedNumeric<Src>& v) { | 295 static constexpr bool is_valid(const CheckedNumeric<Src>& v) { |
297 return v.IsValid(); | 296 return v.IsValid(); |
298 } | 297 } |
299 static constexpr Src value(const CheckedNumeric<Src>& v) { | 298 static constexpr Src value(const CheckedNumeric<Src>& v) { |
300 return v.state_.value(); | 299 return v.state_.value(); |
301 } | 300 } |
302 }; | 301 }; |
303 }; | 302 }; |
304 | 303 |
| 304 // Convenience functions to avoid the ugly template disambiguator syntax. |
| 305 template <typename Dst, typename Src> |
| 306 constexpr bool IsValidForType(const CheckedNumeric<Src> value) { |
| 307 return value.template IsValid<Dst>(); |
| 308 } |
| 309 |
| 310 template <typename Dst, typename Src> |
| 311 constexpr StrictNumeric<Dst> ValueOrDieForType( |
| 312 const CheckedNumeric<Src> value) { |
| 313 return value.template ValueOrDie<Dst>(); |
| 314 } |
| 315 |
| 316 template <typename Dst, typename Src, typename Default> |
| 317 constexpr StrictNumeric<Dst> ValueOrDefaultForType( |
| 318 const CheckedNumeric<Src> value, |
| 319 const Default default_value) { |
| 320 return value.template ValueOrDefault<Dst>(default_value); |
| 321 } |
| 322 |
305 // These variadic templates work out the return types. | 323 // These variadic templates work out the return types. |
306 // TODO(jschuh): Rip all this out once we have C++14 non-trailing auto support. | 324 // TODO(jschuh): Rip all this out once we have C++14 non-trailing auto support. |
307 template <template <typename, typename, typename> class M, | 325 template <template <typename, typename, typename> class M, |
308 typename L, | 326 typename L, |
309 typename R, | 327 typename R, |
310 typename... Args> | 328 typename... Args> |
311 struct ResultType; | 329 struct ResultType; |
312 | 330 |
313 template <template <typename, typename, typename> class M, | 331 template <template <typename, typename, typename> class M, |
314 typename L, | 332 typename L, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=) | 405 BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=) |
388 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=) | 406 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=) |
389 BASE_NUMERIC_ARITHMETIC_OPERATORS(Lsh, <<, <<=) | 407 BASE_NUMERIC_ARITHMETIC_OPERATORS(Lsh, <<, <<=) |
390 BASE_NUMERIC_ARITHMETIC_OPERATORS(Rsh, >>, >>=) | 408 BASE_NUMERIC_ARITHMETIC_OPERATORS(Rsh, >>, >>=) |
391 BASE_NUMERIC_ARITHMETIC_OPERATORS(And, &, &=) | 409 BASE_NUMERIC_ARITHMETIC_OPERATORS(And, &, &=) |
392 BASE_NUMERIC_ARITHMETIC_OPERATORS(Or, |, |=) | 410 BASE_NUMERIC_ARITHMETIC_OPERATORS(Or, |, |=) |
393 BASE_NUMERIC_ARITHMETIC_OPERATORS(Xor, ^, ^=) | 411 BASE_NUMERIC_ARITHMETIC_OPERATORS(Xor, ^, ^=) |
394 | 412 |
395 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS | 413 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS |
396 | 414 |
| 415 // These are some extra StrictNumeric operators to support simple pointer |
| 416 // arithmetic with our result types. Since wrapping on a pointer is always |
| 417 // bad, we trigger the CHECK condition here. |
| 418 template <typename L, typename R> |
| 419 L* operator+(L* lhs, const StrictNumeric<R> rhs) { |
| 420 uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs), |
| 421 CheckMul(sizeof(L), static_cast<R>(rhs))) |
| 422 .template ValueOrDie<uintptr_t>(); |
| 423 return reinterpret_cast<L*>(result); |
| 424 } |
| 425 |
| 426 template <typename L, typename R> |
| 427 L* operator-(L* lhs, const StrictNumeric<R> rhs) { |
| 428 uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs), |
| 429 CheckMul(sizeof(L), static_cast<R>(rhs))) |
| 430 .template ValueOrDie<uintptr_t>(); |
| 431 return reinterpret_cast<L*>(result); |
| 432 } |
| 433 |
397 } // namespace internal | 434 } // namespace internal |
398 | 435 |
399 using internal::CheckedNumeric; | 436 using internal::CheckedNumeric; |
| 437 using internal::IsValidForType; |
| 438 using internal::ValueOrDieForType; |
| 439 using internal::ValueOrDefaultForType; |
400 using internal::CheckNum; | 440 using internal::CheckNum; |
401 using internal::CheckAdd; | 441 using internal::CheckAdd; |
402 using internal::CheckSub; | 442 using internal::CheckSub; |
403 using internal::CheckMul; | 443 using internal::CheckMul; |
404 using internal::CheckDiv; | 444 using internal::CheckDiv; |
405 using internal::CheckMod; | 445 using internal::CheckMod; |
406 using internal::CheckLsh; | 446 using internal::CheckLsh; |
407 using internal::CheckRsh; | 447 using internal::CheckRsh; |
408 using internal::CheckAnd; | 448 using internal::CheckAnd; |
409 using internal::CheckOr; | 449 using internal::CheckOr; |
410 using internal::CheckXor; | 450 using internal::CheckXor; |
411 | 451 |
412 } // namespace base | 452 } // namespace base |
413 | 453 |
414 #endif // BASE_NUMERICS_SAFE_MATH_H_ | 454 #endif // BASE_NUMERICS_SAFE_MATH_H_ |
OLD | NEW |