diff --git a/NOTICE.md b/NOTICE.md index 120eb7683..0f50008fb 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -77,3 +77,39 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` + +## chromium/base/numerics + +**Source**: + +### License + +``` +Copyright 2015 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` \ No newline at end of file diff --git a/dep/chromium/LICENSE b/dep/chromium/LICENSE new file mode 100644 index 000000000..ec74230a8 --- /dev/null +++ b/dep/chromium/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/dep/chromium/MAINTAINER_README.md b/dep/chromium/MAINTAINER_README.md new file mode 100644 index 000000000..0168187b6 --- /dev/null +++ b/dep/chromium/MAINTAINER_README.md @@ -0,0 +1,17 @@ +### Notes for Future Maintainers + +This was originally imported by @miniksa in January 2020. + +The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme. +Please update the provenance information in that file when ingesting an updated version of the dependent library. +That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards. + +## What should be done to update this in the future? + +1. Go to chromium/chromium repository on GitHub. +2. Take the entire contents of the base/numerics directory wholesale and drop it in the base/numerics directory here. +3. Don't change anything about it. +4. Validate that the license in the root of the repository didn't change and update it if so. It is sitting in the same directory as this readme. + If it changed dramatically, ensure that it is still compatible with our license scheme. Also update the NOTICE file in the root of our repository to declare the third-party usage. +5. Submit the pull. + diff --git a/dep/chromium/base/numerics/BUILD.gn b/dep/chromium/base/numerics/BUILD.gn new file mode 100644 index 000000000..0bb8dd103 --- /dev/null +++ b/dep/chromium/base/numerics/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This is a dependency-free, header-only, library, and it needs to stay that +# way to facilitate pulling it into various third-party projects. So, this +# file is here to protect against accidentally introducing external +# dependencies or depending on internal implementation details. +source_set("base_numerics") { + visibility = [ "//base/*" ] + sources = [ + "checked_math_impl.h", + "clamped_math_impl.h", + "safe_conversions_arm_impl.h", + "safe_conversions_impl.h", + "safe_math_arm_impl.h", + "safe_math_clang_gcc_impl.h", + "safe_math_shared_impl.h", + ] + public = [ + "checked_math.h", + "clamped_math.h", + "math_constants.h", + "ranges.h", + "safe_conversions.h", + "safe_math.h", + ] +} diff --git a/dep/chromium/base/numerics/DEPS b/dep/chromium/base/numerics/DEPS new file mode 100644 index 000000000..d95bf133f --- /dev/null +++ b/dep/chromium/base/numerics/DEPS @@ -0,0 +1,7 @@ +# This is a dependency-free, header-only, library, and it needs to stay that +# way to facilitate pulling it into various third-party projects. So, this +# file is here to protect against accidentally introducing dependencies. +include_rules = [ + "-base", + "+base/numerics", +] diff --git a/dep/chromium/base/numerics/OWNERS b/dep/chromium/base/numerics/OWNERS new file mode 100644 index 000000000..5493fba47 --- /dev/null +++ b/dep/chromium/base/numerics/OWNERS @@ -0,0 +1,5 @@ +jschuh@chromium.org +tsepez@chromium.org + + +# COMPONENT: Internals diff --git a/dep/chromium/base/numerics/README.md b/dep/chromium/base/numerics/README.md new file mode 100644 index 000000000..9d00d77ac --- /dev/null +++ b/dep/chromium/base/numerics/README.md @@ -0,0 +1,409 @@ +# `base/numerics` + +This directory contains a dependency-free, header-only library of templates +providing well-defined semantics for safely and performantly handling a variety +of numeric operations, including most common arithmetic operations and +conversions. + +The public API is broken out into the following header files: + +* `checked_math.h` contains the `CheckedNumeric` template class and helper + functions for performing arithmetic and conversion operations that detect + errors and boundary conditions (e.g. overflow, truncation, etc.). +* `clamped_math.h` contains the `ClampedNumeric` template class and + helper functions for performing fast, clamped (i.e. [non-sticky](#notsticky) + saturating) arithmetic operations and conversions. +* `safe_conversions.h` contains the `StrictNumeric` template class and + a collection of custom casting templates and helper functions for safely + converting between a range of numeric types. +* `safe_math.h` includes all of the previously mentioned headers. + +*** aside +**Note:** The `Numeric` template types implicitly convert from C numeric types +and `Numeric` templates that are convertable to an underlying C numeric type. +The conversion priority for `Numeric` type coercions is: + +* `StrictNumeric` coerces to `ClampedNumeric` and `CheckedNumeric` +* `ClampedNumeric` coerces to `CheckedNumeric` +*** + +[TOC] + +## Common patterns and use-cases + +The following covers the preferred style for the most common uses of this +library. Please don't cargo-cult from anywhere else. 😉 + +### Performing checked arithmetic type conversions + +The `checked_cast` template converts between arbitrary arithmetic types, and is +used for cases where a conversion failure should result in program termination: + +```cpp +// Crash if signed_value is out of range for buff_size. +size_t buff_size = checked_cast(signed_value); +``` + +### Performing saturated (clamped) arithmetic type conversions + +The `saturated_cast` template converts between arbitrary arithmetic types, and +is used in cases where an out-of-bounds source value should be saturated to the +corresponding maximum or minimum of the destination type: + +```cpp +// Convert from float with saturation to INT_MAX, INT_MIN, or 0 for NaN. +int int_value = saturated_cast(floating_point_value); +``` + +### Enforcing arithmetic type conversions at compile-time + +The `strict_cast` emits code that is identical to `static_cast`. However, +provides static checks that will cause a compilation failure if the +destination type cannot represent the full range of the source type: + +```cpp +// Throw a compiler error if byte_value is changed to an out-of-range-type. +int int_value = strict_cast(byte_value); +``` + +You can also enforce these compile-time restrictions on function parameters by +using the `StrictNumeric` template: + +```cpp +// Throw a compiler error if the size argument cannot be represented by a +// size_t (e.g. passing an int will fail to compile). +bool AllocateBuffer(void** buffer, StrictCast size); +``` + +### Comparing values between arbitrary arithmetic types + +Both the `StrictNumeric` and `ClampedNumeric` types provide well defined +comparisons between arbitrary arithmetic types. This allows you to perform +comparisons that are not legal or would trigger compiler warnings or errors +under the normal arithmetic promotion rules: + +```cpp +bool foo(unsigned value, int upper_bound) { + // Converting to StrictNumeric allows this comparison to work correctly. + if (MakeStrictNum(value) >= upper_bound) + return false; +``` + +*** note +**Warning:** Do not perform manual conversions using the comparison operators. +Instead, use the cast templates described in the previous sections, or the +constexpr template functions `IsValueInRangeForNumericType` and +`IsTypeInRangeForNumericType`, as these templates properly handle the full range +of corner cases and employ various optimizations. +*** + +### Calculating a buffer size (checked arithmetic) + +When making exact calculations—such as for buffer lengths—it's often necessary +to know when those calculations trigger an overflow, undefined behavior, or +other boundary conditions. The `CheckedNumeric` template does this by storing +a bit determining whether or not some arithmetic operation has occured that +would put the variable in an "invalid" state. Attempting to extract the value +from a variable in an invalid state will trigger a check/trap condition, that +by default will result in process termination. + +Here's an example of a buffer calculation using a `CheckedNumeric` type (note: +the AssignIfValid method will trigger a compile error if the result is ignored). + +```cpp +// Calculate the buffer size and detect if an overflow occurs. +size_t size; +if (!CheckAdd(kHeaderSize, CheckMul(count, kItemSize)).AssignIfValid(&size)) { + // Handle an overflow error... +} +``` + +### Calculating clamped coordinates (non-sticky saturating arithmetic) + +Certain classes of calculations—such as coordinate calculations—require +well-defined semantics that always produce a valid result on boundary +conditions. The `ClampedNumeric` template addresses this by providing +performant, non-sticky saturating arithmetic operations. + +Here's an example of using a `ClampedNumeric` to calculate an operation +insetting a rectangle. + +```cpp +// Use clamped arithmetic since inset calculations might overflow. +void Rect::Inset(int left, int top, int right, int bottom) { + origin_ += Vector2d(left, top); + set_width(ClampSub(width(), ClampAdd(left, right))); + set_height(ClampSub(height(), ClampAdd(top, bottom))); +} +``` + +*** note + +The `ClampedNumeric` type is not "sticky", which means the saturation is not +retained across individual operations. As such, one arithmetic operation may +result in a saturated value, while the next operation may then "desaturate" +the value. Here's an example: + +```cpp +ClampedNumeric value = INT_MAX; +++value; // value is still INT_MAX, due to saturation. +--value; // value is now (INT_MAX - 1), because saturation is not sticky. +``` + +*** + +## Conversion functions and StrictNumeric<> in safe_conversions.h + +This header includes a collection of helper `constexpr` templates for safely +performing a range of conversions, assignments, and tests. + +### Safe casting templates + +* `as_signed()` - Returns the supplied integral value as a signed type of + the same width. +* `as_unsigned()` - Returns the supplied integral value as an unsigned type + of the same width. +* `checked_cast<>()` - Analogous to `static_cast<>` for numeric types, except + that by default it will trigger a crash on an out-of-bounds conversion (e.g. + overflow, underflow, NaN to integral) or a compile error if the conversion + error can be detected at compile time. The crash handler can be overridden + to perform a behavior other than crashing. +* `saturated_cast<>()` - Analogous to `static_cast` for numeric types, except + that it returns a saturated result when the specified numeric conversion + would otherwise overflow or underflow. An NaN source returns 0 by + default, but can be overridden to return a different result. +* `strict_cast<>()` - Analogous to `static_cast` for numeric types, except + this causes a compile failure if the destination type is not large + enough to contain any value in the source type. It performs no runtime + checking and thus introduces no runtime overhead. + +### Other helper and conversion functions + +* `IsValueInRangeForNumericType<>()` - A convenience function that returns + true if the type supplied as the template parameter can represent the value + passed as an argument to the function. +* `IsTypeInRangeForNumericType<>()` - A convenience function that evaluates + entirely at compile-time and returns true if the destination type (first + template parameter) can represent the full range of the source type + (second template parameter). +* `IsValueNegative()` - A convenience function that will accept any + arithmetic type as an argument and will return whether the value is less + than zero. Unsigned types always return false. +* `SafeUnsignedAbs()` - Returns the absolute value of the supplied integer + parameter as an unsigned result (thus avoiding an overflow if the value + is the signed, two's complement minimum). + +### StrictNumeric<> + +`StrictNumeric<>` is a wrapper type that performs assignments and copies via +the `strict_cast` template, and can perform valid arithmetic comparisons +across any range of arithmetic types. `StrictNumeric` is the return type for +values extracted from a `CheckedNumeric` class instance. The raw numeric value +is extracted via `static_cast` to the underlying type or any type with +sufficient range to represent the underlying type. + +* `MakeStrictNum()` - Creates a new `StrictNumeric` from the underlying type + of the supplied arithmetic or StrictNumeric type. +* `SizeT` - Alias for `StrictNumeric`. + +## CheckedNumeric<> in checked_math.h + +`CheckedNumeric<>` implements all the logic and operators for detecting integer +boundary conditions such as overflow, underflow, and invalid conversions. +The `CheckedNumeric` type implicitly converts from floating point and integer +data types, and contains overloads for basic arithmetic operations (i.e.: `+`, +`-`, `*`, `/` for all types and `%`, `<<`, `>>`, `&`, `|`, `^` for integers). +However, *the [variadic template functions +](#CheckedNumeric_in-checked_math_h-Non_member-helper-functions) +are the prefered API,* as they remove type ambiguities and help prevent a number +of common errors. The variadic functions can also be more performant, as they +eliminate redundant expressions that are unavoidable with the with the operator +overloads. (Ideally the compiler should optimize those away, but better to avoid +them in the first place.) + +Type promotions are a slightly modified version of the [standard C/C++ numeric +promotions +](http://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotions) +with the two differences being that *there is no default promotion to int* +and *bitwise logical operations always return an unsigned of the wider type.* + +### Members + +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 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 are for converting `CheckedNumeric` instances: + +* `type` - The underlying numeric type. +* `AssignIfValid()` - Assigns the underlying value to the supplied + destination pointer if the value is currently valid and within the + range supported by the destination type. Returns true on success. +* `Cast<>()` - Instance method returning a `CheckedNumeric` derived from + casting the current instance to a `CheckedNumeric` of the supplied + destination type. + +*** aside +The following member functions return a `StrictNumeric`, which is valid for +comparison and assignment operations, but will trigger a compile failure on +attempts to assign to a type of insufficient range. The underlying value can +be extracted by an explicit `static_cast` to the underlying type or any type +with sufficient range to represent the underlying type. +*** + +* `IsValid()` - Returns true if the underlying numeric value is valid (i.e. + has not wrapped or saturated and is not the result of an invalid + conversion). +* `ValueOrDie()` - Returns the underlying value. If the state is not valid + this call will trigger a crash by default (but may be overridden by + supplying an alternate handler to the template). +* `ValueOrDefault()` - Returns the current value, or the supplied default if + the state is not valid (but will not crash). + +**Comparison operators are explicitly not provided** for `CheckedNumeric` +types because they could result in a crash if the type is not in a valid state. +Patterns like the following should be used instead: + +```cpp +// Either input or padding (or both) may be arbitrary sizes. +size_t buff_size; +if (!CheckAdd(input, padding, kHeaderLength).AssignIfValid(&buff_size) || + buff_size >= kMaxBuffer) { + // Handle an error... +} else { + // Do stuff on success... +} +``` + +### Non-member helper functions + +The following variadic convenience functions, which accept standard arithmetic +or `CheckedNumeric` types, perform arithmetic operations, and return a +`CheckedNumeric` result. The supported functions are: + +* `CheckAdd()` - Addition. +* `CheckSub()` - Subtraction. +* `CheckMul()` - Multiplication. +* `CheckDiv()` - Division. +* `CheckMod()` - Modulus (integer only). +* `CheckLsh()` - Left integer shift (integer only). +* `CheckRsh()` - Right integer shift (integer only). +* `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 following wrapper functions can be used to avoid the template +disambiguator syntax when converting a destination type. + +* `IsValidForType<>()` in place of: `a.template IsValid<>()` +* `ValueOrDieForType<>()` in place of: `a.template ValueOrDie<>()` +* `ValueOrDefaultForType<>()` in place of: `a.template ValueOrDefault<>()` + +The following general utility methods is are useful for converting from +arithmetic types to `CheckedNumeric` types: + +* `MakeCheckedNum()` - Creates a new `CheckedNumeric` from the underlying type + of the supplied arithmetic or directly convertible type. + +## ClampedNumeric<> in clamped_math.h + +`ClampedNumeric<>` implements all the logic and operators for clamped +(non-sticky saturating) arithmetic operations and conversions. The +`ClampedNumeric` type implicitly converts back and forth between floating point +and integer data types, saturating on assignment as appropriate. It contains +overloads for basic arithmetic operations (i.e.: `+`, `-`, `*`, `/` for +all types and `%`, `<<`, `>>`, `&`, `|`, `^` for integers) along with comparison +operators for arithmetic types of any size. However, *the [variadic template +functions +](#ClampedNumeric_in-clamped_math_h-Non_member-helper-functions) +are the prefered API,* as they remove type ambiguities and help prevent +a number of common errors. The variadic functions can also be more performant, +as they eliminate redundant expressions that are unavoidable with the operator +overloads. (Ideally the compiler should optimize those away, but better to avoid +them in the first place.) + +Type promotions are a slightly modified version of the [standard C/C++ numeric +promotions +](http://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_promotions) +with the two differences being that *there is no default promotion to int* +and *bitwise logical operations always return an unsigned of the wider type.* + +*** aside +Most arithmetic operations saturate normally, to the numeric limit in the +direction of the sign. The potentially unusual cases are: + +* **Division:** Division by zero returns the saturated limit in the direction + of sign of the dividend (first argument). The one exception is 0/0, which + returns zero (although logically is NaN). +* **Modulus:** Division by zero returns the dividend (first argument). +* **Left shift:** Non-zero values saturate in the direction of the signed + limit (max/min), even for shifts larger than the bit width. 0 shifted any + amount results in 0. +* **Right shift:** Negative values saturate to -1. Positive or 0 saturates + to 0. (Effectively just an unbounded arithmetic-right-shift.) +* **Bitwise operations:** No saturation; bit pattern is identical to + non-saturated bitwise operations. +*** + +### Members + +The unary negation, increment, and decrement operators are supported, along +with the following unary arithmetic methods, which return a new +`ClampedNumeric` as a result of the operation: + +* `Abs()` - Absolute value. +* `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 are for converting `ClampedNumeric` instances: + +* `type` - The underlying numeric type. +* `RawValue()` - Returns the raw value as the underlying arithmetic type. This + is useful when e.g. assigning to an auto type or passing as a deduced + template parameter. +* `Cast<>()` - Instance method returning a `ClampedNumeric` derived from + casting the current instance to a `ClampedNumeric` of the supplied + destination type. + +### Non-member helper functions + +The following variadic convenience functions, which accept standard arithmetic +or `ClampedNumeric` types, perform arithmetic operations, and return a +`ClampedNumeric` result. The supported functions are: + +* `ClampAdd()` - Addition. +* `ClampSub()` - Subtraction. +* `ClampMul()` - Multiplication. +* `ClampDiv()` - Division. +* `ClampMod()` - Modulus (integer only). +* `ClampLsh()` - Left integer shift (integer only). +* `ClampRsh()` - Right integer shift (integer only). +* `ClampAnd()` - Bitwise AND (integer only with unsigned result). +* `ClampOr()` - Bitwise OR (integer only with unsigned result). +* `ClampXor()` - Bitwise XOR (integer only with unsigned result). +* `ClampMax()` - Maximum of supplied arguments. +* `ClampMin()` - Minimum of supplied arguments. + +The following is a general utility method that is useful for converting +to a `ClampedNumeric` type: + +* `MakeClampedNum()` - Creates a new `ClampedNumeric` from the underlying type + of the supplied arithmetic or directly convertible type. diff --git a/dep/chromium/base/numerics/checked_math.h b/dep/chromium/base/numerics/checked_math.h new file mode 100644 index 000000000..ede3344f8 --- /dev/null +++ b/dep/chromium/base/numerics/checked_math.h @@ -0,0 +1,393 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_NUMERICS_CHECKED_MATH_H_ +#define BASE_NUMERICS_CHECKED_MATH_H_ + +#include + +#include +#include + +#include "base/numerics/checked_math_impl.h" + +namespace base { +namespace internal { + +template +class CheckedNumeric { + static_assert(std::is_arithmetic::value, + "CheckedNumeric: T must be a numeric type."); + + public: + using type = T; + + constexpr CheckedNumeric() = default; + + // Copy constructor. + template + constexpr CheckedNumeric(const CheckedNumeric& rhs) + : state_(rhs.state_.value(), rhs.IsValid()) {} + + template + friend class CheckedNumeric; + + // This is not an explicit constructor because we implicitly upgrade regular + // numerics to CheckedNumerics to make them easier to use. + template + constexpr CheckedNumeric(Src value) // NOLINT(runtime/explicit) + : state_(value) { + static_assert(std::is_arithmetic::value, "Argument must be numeric."); + } + + // This is not an explicit constructor because we want a seamless conversion + // from StrictNumeric types. + template + constexpr CheckedNumeric( + StrictNumeric value) // NOLINT(runtime/explicit) + : state_(static_cast(value)) {} + + // IsValid() - The public API to test if a CheckedNumeric is currently valid. + // A range checked destination type can be supplied using the Dst template + // parameter. + template + constexpr bool IsValid() const { + return state_.is_valid() && + IsValueInRangeForNumericType(state_.value()); + } + + // AssignIfValid(Dst) - Assigns the underlying value if it is currently valid + // and is within the range supported by the destination type. Returns true if + // successful and false otherwise. + template +#if defined(__clang__) || defined(__GNUC__) + __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) + _Check_return_ +#endif + constexpr bool + AssignIfValid(Dst* result) const { + return BASE_NUMERICS_LIKELY(IsValid()) + ? ((*result = static_cast(state_.value())), true) + : false; + } + + // ValueOrDie() - The primary accessor for the underlying value. If the + // current state is not valid it will CHECK and crash. + // A range checked destination type can be supplied using the Dst template + // parameter, which will trigger a CHECK if the value is not in bounds for + // the destination. + // The CHECK behavior can be overridden by supplying a handler as a + // template parameter, for test code, etc. However, the handler cannot access + // the underlying value, and it is not available through other means. + template + constexpr StrictNumeric ValueOrDie() const { + return BASE_NUMERICS_LIKELY(IsValid()) + ? static_cast(state_.value()) + : CheckHandler::template HandleFailure(); + } + + // ValueOrDefault(T default_value) - A convenience method that returns the + // current value if the state is valid, and the supplied default_value for + // any other state. + // A range checked destination type can be supplied using the Dst template + // parameter. WARNING: This function may fail to compile or CHECK at runtime + // if the supplied default_value is not within range of the destination type. + template + constexpr StrictNumeric ValueOrDefault(const Src default_value) const { + return BASE_NUMERICS_LIKELY(IsValid()) + ? static_cast(state_.value()) + : checked_cast(default_value); + } + + // Returns a checked numeric of the specified type, cast from the current + // CheckedNumeric. If the current state is invalid or the destination cannot + // represent the result then the returned CheckedNumeric will be invalid. + template + constexpr CheckedNumeric::type> Cast() const { + return *this; + } + + // This friend method is available solely for providing more detailed logging + // in the the tests. Do not implement it in production code, because the + // underlying values may change at any time. + template + friend U GetNumericValueForTest(const CheckedNumeric& src); + + // Prototypes for the supported arithmetic operator overloads. + template + constexpr CheckedNumeric& operator+=(const Src rhs); + template + constexpr CheckedNumeric& operator-=(const Src rhs); + template + constexpr CheckedNumeric& operator*=(const Src rhs); + template + constexpr CheckedNumeric& operator/=(const Src rhs); + template + constexpr CheckedNumeric& operator%=(const Src rhs); + template + constexpr CheckedNumeric& operator<<=(const Src rhs); + template + constexpr CheckedNumeric& operator>>=(const Src rhs); + template + constexpr CheckedNumeric& operator&=(const Src rhs); + template + constexpr CheckedNumeric& operator|=(const Src rhs); + template + constexpr CheckedNumeric& operator^=(const Src rhs); + + constexpr CheckedNumeric operator-() const { + // The negation of two's complement int min is int min, so we simply + // check for that in the constexpr case. + // We use an optimized code path for a known run-time variable. + return MustTreatAsConstexpr(state_.value()) || !std::is_signed::value || + std::is_floating_point::value + ? CheckedNumeric( + NegateWrapper(state_.value()), + IsValid() && (!std::is_signed::value || + std::is_floating_point::value || + NegateWrapper(state_.value()) != + std::numeric_limits::lowest())) + : FastRuntimeNegate(); + } + + constexpr CheckedNumeric operator~() const { + return CheckedNumeric( + InvertWrapper(state_.value()), IsValid()); + } + + constexpr CheckedNumeric Abs() const { + return !IsValueNegative(state_.value()) ? *this : -*this; + } + + template + constexpr CheckedNumeric::type> Max( + const U rhs) const { + using R = typename UnderlyingType::type; + using result_type = typename MathWrapper::type; + // TODO(jschuh): This can be converted to the MathOp version and remain + // constexpr once we have C++14 support. + return CheckedNumeric( + static_cast( + IsGreater::Test(state_.value(), Wrapper::value(rhs)) + ? state_.value() + : Wrapper::value(rhs)), + state_.is_valid() && Wrapper::is_valid(rhs)); + } + + template + constexpr CheckedNumeric::type> Min( + const U rhs) const { + using R = typename UnderlyingType::type; + using result_type = typename MathWrapper::type; + // TODO(jschuh): This can be converted to the MathOp version and remain + // constexpr once we have C++14 support. + return CheckedNumeric( + static_cast( + IsLess::Test(state_.value(), Wrapper::value(rhs)) + ? state_.value() + : Wrapper::value(rhs)), + state_.is_valid() && Wrapper::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. + constexpr CheckedNumeric::type> + UnsignedAbs() const { + return CheckedNumeric::type>( + SafeUnsignedAbs(state_.value()), state_.is_valid()); + } + + constexpr CheckedNumeric& operator++() { + *this += 1; + return *this; + } + + constexpr CheckedNumeric operator++(int) { + CheckedNumeric value = *this; + *this += 1; + return value; + } + + constexpr CheckedNumeric& operator--() { + *this -= 1; + return *this; + } + + constexpr CheckedNumeric operator--(int) { + CheckedNumeric value = *this; + *this -= 1; + return value; + } + + // These perform the actual math operations on the CheckedNumerics. + // Binary arithmetic operations. + template