summaryrefslogtreecommitdiff
path: root/basic/source/sbx/sbxconv.hxx
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2024-09-08 16:52:39 +0500
committerMike Kaganski <mike.kaganski@collabora.com>2024-09-09 17:46:41 +0200
commitb2257d1f78d7d678b87e2c3d590aba47bfec90f0 (patch)
treeaa3daf3bb486620f668cd82af03614cc81a30781 /basic/source/sbx/sbxconv.hxx
parentcaff013bee53216efeb49db4bcda44b55c223b58 (diff)
Improve run-time Currency type support in Basic
Change-Id: I1e04c6022944034a30ef896b8cd24050ebe3bbd5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173042 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'basic/source/sbx/sbxconv.hxx')
-rw-r--r--basic/source/sbx/sbxconv.hxx75
1 files changed, 69 insertions, 6 deletions
diff --git a/basic/source/sbx/sbxconv.hxx b/basic/source/sbx/sbxconv.hxx
index 8f11122bd319..f32e5fc890d7 100644
--- a/basic/source/sbx/sbxconv.hxx
+++ b/basic/source/sbx/sbxconv.hxx
@@ -26,6 +26,7 @@
#include <basic/sbxdef.hxx>
#include <o3tl/float_int_conversion.hxx>
+#include <o3tl/safeint.hxx>
#include <rtl/math.hxx>
#include <sal/types.h>
@@ -107,14 +108,76 @@ void ImpPutCurrency( SbxValues*, const sal_Int64 );
inline sal_Int64 ImpDoubleToCurrency( double d )
{
- if (d > 0)
- return static_cast<sal_Int64>( d * CURRENCY_FACTOR + 0.5);
- else
- return static_cast<sal_Int64>( d * CURRENCY_FACTOR - 0.5);
+ double result = d > 0 ? (d * CURRENCY_FACTOR + 0.5) : (d * CURRENCY_FACTOR - 0.5);
+ if (result >= double(SAL_MAX_INT64)) // double(SAL_MAX_INT64) is greater than SAL_MAX_INT64
+ {
+ SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW);
+ return SAL_MAX_INT64;
+ }
+ if (result < double(SAL_MIN_INT64))
+ {
+ SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW);
+ return SAL_MIN_INT64;
+ }
+ return result;
+}
+
+template <typename I>
+ requires std::is_integral_v<I>
+inline sal_Int64 CurFrom(I n)
+{
+ using ValidRange = o3tl::ValidRange<sal_Int64, SAL_MIN_INT64 / CURRENCY_FACTOR, SAL_MAX_INT64 / CURRENCY_FACTOR>;
+ if (ValidRange::isAbove(n))
+ {
+ SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW);
+ return SAL_MAX_INT64;
+ }
+ if (ValidRange::isBelow(n))
+ {
+ SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW);
+ return SAL_MIN_INT64;
+ }
+ return n * CURRENCY_FACTOR;
}
-inline double ImpCurrencyToDouble( const sal_Int64 r )
- { return static_cast<double>(r) / double(CURRENCY_FACTOR); }
+inline double ImpCurrencyToDouble(sal_Int64 r) { return static_cast<double>(r) / CURRENCY_FACTOR; }
+
+template <typename I>
+ requires std::is_integral_v<I>
+inline I CurTo(sal_Int64 cur_val)
+{
+ sal_Int64 i = CurTo<sal_Int64>(cur_val);
+ if (o3tl::ValidRange<I>::isAbove(i))
+ {
+ SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW);
+ return std::numeric_limits<I>::max();
+ }
+ if (o3tl::ValidRange<I>::isBelow(i))
+ {
+ SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW);
+ return std::numeric_limits<I>::min();
+ }
+ return i;
+}
+
+template <> inline sal_Int64 CurTo<sal_Int64>(sal_Int64 cur_val)
+{
+ sal_Int64 i = cur_val / CURRENCY_FACTOR;
+ // Rounding (half-to-even)
+ int f = cur_val % CURRENCY_FACTOR;
+ if (i % 2 == 1)
+ {
+ if (f < 0)
+ --f;
+ else
+ ++f;
+ }
+ if (f > CURRENCY_FACTOR / 2)
+ ++i;
+ else if (f < -CURRENCY_FACTOR / 2)
+ --i;
+ return i;
+}
// SBXDEC.CXX