Branch data Line data Source code
# 1 : : // Copyright (c) 2021 The Bitcoin Core developers # 2 : : // Distributed under the MIT software license, see the accompanying # 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. # 4 : : # 5 : : #ifndef BITCOIN_UTIL_OVERFLOW_H # 6 : : #define BITCOIN_UTIL_OVERFLOW_H # 7 : : # 8 : : #include <limits> # 9 : : #include <optional> # 10 : : #include <type_traits> # 11 : : # 12 : : template <class T> # 13 : : [[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept # 14 : 11464923 : { # 15 : 11464923 : static_assert(std::is_integral<T>::value, "Integral required."); # 16 : 11464923 : if constexpr (std::numeric_limits<T>::is_signed) { # 17 [ + + ][ + + ]: 3489 : return (i > 0 && j > std::numeric_limits<T>::max() - i) || # [ + + ][ - + ] # 18 [ + + ][ - + ]: 3489 : (i < 0 && j < std::numeric_limits<T>::min() - i); # [ + + ][ # # ] # 19 : 3489 : } # 20 : 0 : return std::numeric_limits<T>::max() - i < j; # 21 : 11464923 : } # 22 : : # 23 : : template <class T> # 24 : : [[nodiscard]] std::optional<T> CheckedAdd(const T i, const T j) noexcept # 25 : 11464941 : { # 26 [ - + ][ + + ]: 11464941 : if (AdditionOverflow(i, j)) { # [ + + ][ - + ] # 27 : 12 : return std::nullopt; # 28 : 12 : } # 29 : 11464929 : return i + j; # 30 : 11464941 : } # 31 : : # 32 : : template <class T> # 33 : : [[nodiscard]] T SaturatingAdd(const T i, const T j) noexcept # 34 : 36 : { # 35 : 36 : if constexpr (std::numeric_limits<T>::is_signed) { # 36 [ + + ][ + + ]: 24 : if (i > 0 && j > std::numeric_limits<T>::max() - i) { # 37 : 4 : return std::numeric_limits<T>::max(); # 38 : 4 : } # 39 [ + + ][ + + ]: 20 : if (i < 0 && j < std::numeric_limits<T>::min() - i) { # 40 : 4 : return std::numeric_limits<T>::min(); # 41 : 4 : } # 42 : 20 : } else { # 43 [ + + ]: 12 : if (std::numeric_limits<T>::max() - i < j) { # 44 : 4 : return std::numeric_limits<T>::max(); # 45 : 4 : } # 46 : 12 : } # 47 : 24 : return i + j; # 48 : 36 : } # 49 : : # 50 : : #endif // BITCOIN_UTIL_OVERFLOW_H