diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2021-11-24 13:43:05 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2021-12-01 14:03:30 +0100 |
commit | c28a13b9e2bd864e8c574d604bcd6da9e93fb476 (patch) | |
tree | c00f9e065e8f62e755bfbf242ff67eb6ef202165 /basic/source/sbx/sbxconv.hxx | |
parent | 25a368c30acb54e0819d2b2b890a3fd1530d8a76 (diff) |
Unify and simplify floating-point-to-integer conversion
* Round the number once, to avoid doing it three times for a successful conversion.
* Round to nearest before convertsToAtMost/convertsToAtLeast, to handle cases like
Dim n As Integer
n = 32767.4
which should succeed.
* Add overflow checks to Hyper (U/Int64) types.
Change-Id: Ib10837e6df3cc1e3aba7a657e882bd40e344fd3b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126173
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.hxx | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/basic/source/sbx/sbxconv.hxx b/basic/source/sbx/sbxconv.hxx index dede96942297..a3837d9a3dbf 100644 --- a/basic/source/sbx/sbxconv.hxx +++ b/basic/source/sbx/sbxconv.hxx @@ -20,10 +20,45 @@ #pragma once #include "sbxdec.hxx" +#include <basic/sberrors.hxx> #include <basic/sbx.hxx> +#include <basic/sbxcore.hxx> +#include <basic/sbxdef.hxx> + +#include <o3tl/float_int_conversion.hxx> +#include <rtl/math.hxx> +#include <sal/types.h> class SbxArray; +template <typename I> inline I DoubleTo(double f, I min, I max) +{ + f = rtl::math::round(f); + if (!o3tl::convertsToAtMost(f, max)) + { + SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW); + return max; + } + if (!o3tl::convertsToAtLeast(f, min)) + { + SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW); + return min; + } + return f; +} + +inline auto ImpDoubleToChar(double f) { return DoubleTo<sal_Unicode>(f, SbxMINCHAR, SbxMAXCHAR); } +inline auto ImpDoubleToByte(double f) { return DoubleTo<sal_uInt8>(f, 0, SbxMAXBYTE); } +inline auto ImpDoubleToUShort(double f) { return DoubleTo<sal_uInt16>(f, 0, SbxMAXUINT); } +inline auto ImpDoubleToInteger(double f) { return DoubleTo<sal_Int16>(f, SbxMININT, SbxMAXINT); } +inline auto ImpDoubleToULong(double f) { return DoubleTo<sal_uInt32>(f, 0, SbxMAXULNG); } +inline auto ImpDoubleToLong(double f) { return DoubleTo<sal_Int32>(f, SbxMINLNG, SbxMAXLNG); } +inline auto ImpDoubleToSalUInt64(double d) { return DoubleTo<sal_uInt64>(d, 0, SAL_MAX_UINT64); } +inline auto ImpDoubleToSalInt64(double d) +{ + return DoubleTo<sal_Int64>(d, SAL_MIN_INT64, SAL_MAX_INT64); +} + // SBXSCAN.CXX extern void ImpCvtNum( double nNum, short nPrec, OUString& rRes, bool bCoreString=false ); extern ErrCode ImpScan @@ -45,8 +80,6 @@ void ImpPutInt64( SbxValues*, sal_Int64 ); sal_uInt64 ImpGetUInt64( const SbxValues* ); void ImpPutUInt64( SbxValues*, sal_uInt64 ); -sal_Int64 ImpDoubleToSalInt64 ( double d ); -sal_uInt64 ImpDoubleToSalUInt64( double d ); double ImpSalUInt64ToDouble( sal_uInt64 n ); // SBXLNG.CXX |