1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include <basic/sberrors.hxx>
24 #include <basic/sbx.hxx>
25 #include <basic/sbxcore.hxx>
26 #include <basic/sbxdef.hxx>
28 #include <o3tl/float_int_conversion.hxx>
29 #include <o3tl/safeint.hxx>
30 #include <rtl/math.hxx>
31 #include <sal/types.h>
35 template <typename I
> inline I
DoubleTo(double f
, I min
, I max
)
37 f
= rtl::math::round(f
);
38 if (!o3tl::convertsToAtMost(f
, max
))
40 SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW
);
43 if (!o3tl::convertsToAtLeast(f
, min
))
45 SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW
);
51 inline auto ImpDoubleToChar(double f
) { return DoubleTo
<sal_Unicode
>(f
, SbxMINCHAR
, SbxMAXCHAR
); }
52 inline auto ImpDoubleToByte(double f
) { return DoubleTo
<sal_uInt8
>(f
, 0, SbxMAXBYTE
); }
53 inline auto ImpDoubleToUShort(double f
) { return DoubleTo
<sal_uInt16
>(f
, 0, SbxMAXUINT
); }
54 inline auto ImpDoubleToInteger(double f
) { return DoubleTo
<sal_Int16
>(f
, SbxMININT
, SbxMAXINT
); }
55 inline auto ImpDoubleToULong(double f
) { return DoubleTo
<sal_uInt32
>(f
, 0, SbxMAXULNG
); }
56 inline auto ImpDoubleToLong(double f
) { return DoubleTo
<sal_Int32
>(f
, SbxMINLNG
, SbxMAXLNG
); }
57 inline auto ImpDoubleToSalUInt64(double d
) { return DoubleTo
<sal_uInt64
>(d
, 0, SAL_MAX_UINT64
); }
58 inline auto ImpDoubleToSalInt64(double d
)
60 return DoubleTo
<sal_Int64
>(d
, SAL_MIN_INT64
, SAL_MAX_INT64
);
64 extern void ImpCvtNum( double nNum
, short nPrec
, OUString
& rRes
, bool bCoreString
=false );
65 extern ErrCode ImpScan
66 ( const OUString
& rSrc
, double& nVal
, SbxDataType
& rType
, sal_uInt16
* pLen
,
68 // A version that uses defaults / compatibility settings for bOnlyIntntl
69 extern ErrCode ImpScan
70 ( const OUString
& rSrc
, double& nVal
, SbxDataType
& rType
, sal_uInt16
* pLen
);
72 // with advanced evaluation (International, "TRUE"/"FALSE")
73 extern bool ImpConvStringExt( OUString
& rSrc
, SbxDataType eTargetType
);
75 void ImpGetIntntlSep( sal_Unicode
& rcDecimalSep
, sal_Unicode
& rcThousandSep
, sal_Unicode
& rcDecimalSepAlt
);
79 sal_Int16
ImpGetInteger( const SbxValues
* );
80 void ImpPutInteger( SbxValues
*, sal_Int16
);
82 sal_Int64
ImpGetInt64( const SbxValues
* );
83 void ImpPutInt64( SbxValues
*, sal_Int64
);
84 sal_uInt64
ImpGetUInt64( const SbxValues
* );
85 void ImpPutUInt64( SbxValues
*, sal_uInt64
);
87 double ImpSalUInt64ToDouble( sal_uInt64 n
);
91 sal_Int32
ImpGetLong( const SbxValues
* );
92 void ImpPutLong( SbxValues
*, sal_Int32
);
96 float ImpGetSingle( const SbxValues
* );
97 void ImpPutSingle( SbxValues
*, float );
101 double ImpGetDouble( const SbxValues
* );
102 void ImpPutDouble( SbxValues
*, double, bool bCoreString
=false );
106 sal_Int64
ImpGetCurrency( const SbxValues
* );
107 void ImpPutCurrency( SbxValues
*, const sal_Int64
);
109 inline sal_Int64
ImpDoubleToCurrency( double d
)
111 double result
= d
> 0 ? (d
* CURRENCY_FACTOR
+ 0.5) : (d
* CURRENCY_FACTOR
- 0.5);
112 if (result
>= double(SAL_MAX_INT64
)) // double(SAL_MAX_INT64) is greater than SAL_MAX_INT64
114 SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW
);
115 return SAL_MAX_INT64
;
117 if (result
< double(SAL_MIN_INT64
))
119 SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW
);
120 return SAL_MIN_INT64
;
125 template <typename I
>
126 requires
std::is_integral_v
<I
>
127 inline sal_Int64
CurFrom(I n
)
129 using ValidRange
= o3tl::ValidRange
<sal_Int64
, SAL_MIN_INT64
/ CURRENCY_FACTOR
, SAL_MAX_INT64
/ CURRENCY_FACTOR
>;
130 if (ValidRange::isAbove(n
))
132 SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW
);
133 return SAL_MAX_INT64
;
135 if (ValidRange::isBelow(n
))
137 SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW
);
138 return SAL_MIN_INT64
;
140 return n
* CURRENCY_FACTOR
;
143 inline double ImpCurrencyToDouble(sal_Int64 r
) { return static_cast<double>(r
) / CURRENCY_FACTOR
; }
145 template <typename I
>
146 requires
std::is_integral_v
<I
>
147 inline I
CurTo(sal_Int64 cur_val
)
149 sal_Int64 i
= CurTo
<sal_Int64
>(cur_val
);
150 if (o3tl::ValidRange
<I
>::isAbove(i
))
152 SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW
);
153 return std::numeric_limits
<I
>::max();
155 if (o3tl::ValidRange
<I
>::isBelow(i
))
157 SbxBase::SetError(ERRCODE_BASIC_MATH_OVERFLOW
);
158 return std::numeric_limits
<I
>::min();
163 template <> inline sal_Int64 CurTo
<sal_Int64
>(sal_Int64 cur_val
)
165 sal_Int64 i
= cur_val
/ CURRENCY_FACTOR
;
166 // Rounding (half-to-even)
167 int f
= cur_val
% CURRENCY_FACTOR
;
175 if (f
> CURRENCY_FACTOR
/ 2)
177 else if (f
< -CURRENCY_FACTOR
/ 2)
185 SbxDecimal
* ImpCreateDecimal( SbxValues
* p
);
186 SbxDecimal
* ImpGetDecimal( const SbxValues
* p
);
187 void ImpPutDecimal( SbxValues
* p
, SbxDecimal
* pDec
);
191 double ImpGetDate( const SbxValues
* );
192 void ImpPutDate( SbxValues
*, double );
196 OUString
ImpGetString( const SbxValues
* );
197 OUString
ImpGetCoreString( const SbxValues
* );
198 void ImpPutString( SbxValues
*, const OUString
* );
202 sal_Unicode
ImpGetChar( const SbxValues
* );
203 void ImpPutChar( SbxValues
*, sal_Unicode
);
206 sal_uInt8
ImpGetByte( const SbxValues
* );
207 void ImpPutByte( SbxValues
*, sal_uInt8
);
211 sal_uInt16
ImpGetUShort( const SbxValues
* );
212 void ImpPutUShort( SbxValues
*, sal_uInt16
);
216 sal_uInt32
ImpGetULong( const SbxValues
* );
217 void ImpPutULong( SbxValues
*, sal_uInt32
);
221 enum SbxBOOL
ImpGetBool( const SbxValues
* );
222 void ImpPutBool( SbxValues
*, sal_Int16
);
224 // ByteArray <--> String
225 SbxArray
* StringToByteArray(const OUString
& rStr
);
226 OUString
ByteArrayToString(SbxArray
* pArr
);
228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */