strat: revise fs unsupported operation results, add overflow utils

This commit is contained in:
Michael Scire 2022-03-13 01:32:34 -08:00 committed by SciresM
parent ba4e7c5866
commit 11e4bed199
31 changed files with 265 additions and 142 deletions

View file

@ -69,4 +69,91 @@ namespace ams::util {
return ::ams::util::impl::IsIntValueRepresentableImpl<To, From>(v);
}
template<std::integral T>
constexpr ALWAYS_INLINE bool CanAddWithoutOverflow(T x, T y) {
if constexpr (std::unsigned_integral<T>) {
return x <= std::numeric_limits<T>::max() - y;
} else {
if (y >= 0) {
return x <= std::numeric_limits<T>::max() - y;
} else {
return x >= std::numeric_limits<T>::min() - y;
}
}
}
template<std::integral T>
constexpr ALWAYS_INLINE bool CanSubtractWithoutOverflow(T x, T y) {
if constexpr (std::unsigned_integral<T>) {
return x >= std::numeric_limits<T>::min() + y;
} else {
if (y >= 0) {
return x >= std::numeric_limits<T>::min() + y;
} else {
return x <= std::numeric_limits<T>::max() + y;
}
}
}
template<std::integral T>
constexpr ALWAYS_INLINE bool CanMultiplyWithoutOverflow(T x, T y) {
if (x == 0 || y == 0) {
return true;
}
if constexpr (std::unsigned_integral<T>) {
return y <= std::numeric_limits<T>::max() / x;
} else {
if (x > 0) {
if (y > 0) {
return y <= std::numeric_limits<T>::max() / x;
} else /*if (y < 0) */ {
return y >= std::numeric_limits<T>::min() / x;
}
} else /* if (x < 0) */ {
if (y > 0) {
return x >= std::numeric_limits<T>::min() / y;
} else /*if (y < 0) */ {
return y >= std::numeric_limits<T>::max() / x;
}
}
}
}
template<std::integral T>
constexpr inline bool TryAddWithoutOverflow(T *out, T x, T y) {
AMS_ASSERT(out != nullptr);
if (CanAddWithoutOverflow(x, y)) {
*out = x + y;
return true;
} else {
return false;
}
}
template<std::integral T>
constexpr inline bool TrySubtractWithoutOverflow(T *out, T x, T y) {
AMS_ASSERT(out != nullptr);
if (CanSubtractWithoutOverflow(x, y)) {
*out = x - y;
return true;
} else {
return false;
}
}
template<std::integral T>
constexpr inline bool TryMultiplyWithoutOverflow(T *out, T x, T y) {
AMS_ASSERT(out != nullptr);
if (CanMultiplyWithoutOverflow(x, y)) {
*out = x * y;
return true;
} else {
return false;
}
}
}