summaryrefslogtreecommitdiff
path: root/include/o3tl
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2021-08-23 16:28:10 +0200
committerMike Kaganski <mike.kaganski@collabora.com>2021-08-24 10:37:21 +0200
commitae04cfdbad1f4c09b06cd2cee9d89e9909181acc (patch)
tree1dec02c9c1258ddeb7f21a103483fec70d47e008 /include/o3tl
parentd21a9968728295736e63bfc53eb83ee162dafae7 (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.hxx20
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)
{