diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2021-08-23 16:28:10 +0200 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2021-08-24 10:37:21 +0200 |
commit | ae04cfdbad1f4c09b06cd2cee9d89e9909181acc (patch) | |
tree | 1dec02c9c1258ddeb7f21a103483fec70d47e008 /include/o3tl | |
parent | d21a9968728295736e63bfc53eb83ee162dafae7 (diff) |
Introduce convertNarrowing to return smaller integer types
It will use compile-type constants to clamp input value, instead of
clamping more expensive pre-sanitized output value.
Change-Id: If78f8b1b4c99bd2f16b1d8a71872e89a0dddd8d0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120874
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'include/o3tl')
-rw-r--r-- | include/o3tl/unit_conversion.hxx | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/include/o3tl/unit_conversion.hxx b/include/o3tl/unit_conversion.hxx index cf293662e7b2..7bee0ed397e5 100644 --- a/include/o3tl/unit_conversion.hxx +++ b/include/o3tl/unit_conversion.hxx @@ -221,6 +221,26 @@ template <typename N, typename U> constexpr auto convertSaturate(N n, U from, U return detail::MulDivSaturate(n, detail::md(from, to), detail::md(to, from)); } +// Conversion with saturation (only for integral types), optimized for return types smaller than +// sal_Int64. In this case, it's easier to clamp input values to known bounds, than to do some +// preprocessing to handle too large input values, just to clamp the result anyway. Use it like: +// +// sal_Int32 n = convertNarrowing<sal_Int32, o3tl::Length::mm100, o3tl::Length::emu>(m); +template <typename Out, auto from, auto to, typename N, + std::enable_if_t< + std::is_integral_v<N> && std::is_integral_v<Out> && sizeof(Out) < sizeof(sal_Int64), + int> = 0> +constexpr Out convertNarrowing(N n) +{ + constexpr sal_Int64 nMin = convertSaturate(std::numeric_limits<Out>::min(), to, from); + constexpr sal_Int64 nMax = convertSaturate(std::numeric_limits<Out>::max(), to, from); + if (static_cast<sal_Int64>(n) > nMax) + return std::numeric_limits<Out>::max(); + if (static_cast<sal_Int64>(n) < nMin) + return std::numeric_limits<Out>::min(); + return convert(n, from, to); +} + // Return a pair { multiplier, divisor } for a given conversion template <typename U> constexpr std::pair<sal_Int64, sal_Int64> getConversionMulDiv(U from, U to) { |