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 .
20 #include <sal/config.h>
22 #include <o3tl/safeint.hxx>
23 #include <comphelper/errcode.hxx>
24 #include <basic/sberrors.hxx>
25 #include "sbxconv.hxx"
27 #include <rtl/math.hxx>
29 sal_Int16
ImpGetInteger( const SbxValues
* p
)
37 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
42 nRes
= p
->nChar
; break;
44 nRes
= p
->nByte
; break;
47 nRes
= p
->nInteger
; break;
50 if( p
->nUShort
> o3tl::make_unsigned(SbxMAXINT
) )
52 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= SbxMAXINT
;
55 nRes
= static_cast<sal_Int16
>(p
->nUShort
);
58 if( p
->nLong
> SbxMAXINT
)
60 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= SbxMAXINT
;
62 else if( p
->nLong
< SbxMININT
)
64 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= SbxMININT
;
67 nRes
= static_cast<sal_Int16
>(p
->nLong
);
70 if( p
->nULong
> SbxMAXINT
)
72 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= SbxMAXINT
;
75 nRes
= static_cast<sal_Int16
>(p
->nULong
);
78 nRes
= ImpDoubleToInteger(p
->nSingle
);
81 nRes
= CurTo
<sal_Int16
>(p
->nInt64
);
84 if( p
->nInt64
> SbxMAXINT
)
86 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= SbxMAXINT
;
88 else if( p
->nInt64
< SbxMININT
)
90 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= SbxMININT
;
93 nRes
= static_cast<sal_Int16
>(p
->nInt64
);
96 if( p
->uInt64
> SbxMAXINT
)
98 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= SbxMAXINT
;
101 nRes
= static_cast<sal_Int16
>(p
->uInt64
);
106 case SbxBYREF
| SbxDECIMAL
:
109 if( p
->eType
== SbxDECIMAL
)
112 p
->pDecimal
->getDouble( dVal
);
117 nRes
= ImpDoubleToInteger(dVal
);
122 case SbxBYREF
| SbxSTRING
:
129 if( ImpScan( *p
->pOUString
, d
, t
, nullptr ) != ERRCODE_NONE
)
132 nRes
= ImpDoubleToInteger(d
);
137 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
139 nRes
= pVal
->GetInteger();
142 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
); nRes
= 0;
147 case SbxBYREF
| SbxCHAR
:
148 nRes
= *p
->pChar
; break;
149 case SbxBYREF
| SbxBYTE
:
150 nRes
= *p
->pByte
; break;
151 case SbxBYREF
| SbxINTEGER
:
152 case SbxBYREF
| SbxBOOL
:
153 nRes
= *p
->pInteger
; break;
155 // from here had to be tested
156 case SbxBYREF
| SbxLONG
:
157 aTmp
.nLong
= *p
->pLong
; goto ref
;
158 case SbxBYREF
| SbxULONG
:
159 aTmp
.nULong
= *p
->pULong
; goto ref
;
160 case SbxBYREF
| SbxERROR
:
161 case SbxBYREF
| SbxUSHORT
:
162 aTmp
.nUShort
= *p
->pUShort
; goto ref
;
163 case SbxBYREF
| SbxSINGLE
:
164 aTmp
.nSingle
= *p
->pSingle
; goto ref
;
165 case SbxBYREF
| SbxDATE
:
166 case SbxBYREF
| SbxDOUBLE
:
167 aTmp
.nDouble
= *p
->pDouble
; goto ref
;
168 case SbxBYREF
| SbxCURRENCY
:
169 case SbxBYREF
| SbxSALINT64
:
170 aTmp
.nInt64
= *p
->pnInt64
; goto ref
;
171 case SbxBYREF
| SbxSALUINT64
:
172 aTmp
.uInt64
= *p
->puInt64
; goto ref
;
174 aTmp
.eType
= SbxDataType( p
->eType
& 0x0FFF );
175 p
= &aTmp
; goto start
;
178 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
); nRes
= 0;
183 void ImpPutInteger( SbxValues
* p
, sal_Int16 n
)
189 // here had to be tested
191 aTmp
.pChar
= &p
->nChar
; goto direct
;
193 aTmp
.pByte
= &p
->nByte
; goto direct
;
195 aTmp
.pULong
= &p
->nULong
; goto direct
;
198 aTmp
.pUShort
= &p
->nUShort
; goto direct
;
200 aTmp
.puInt64
= &p
->uInt64
; goto direct
;
202 aTmp
.eType
= SbxDataType( p
->eType
| SbxBYREF
);
203 p
= &aTmp
; goto start
;
205 // from here no tests needed
208 p
->nInteger
= n
; break;
212 p
->nSingle
= n
; break;
215 p
->nDouble
= n
; break;
217 p
->nInt64
= CurFrom(n
); break;
219 p
->nInt64
= n
; break;
221 case SbxBYREF
| SbxDECIMAL
:
222 ImpCreateDecimal( p
)->setInt( n
);
227 case SbxBYREF
| SbxSTRING
:
229 p
->pOUString
= new OUString
;
230 ImpCvtNum( static_cast<double>(n
), 0, *p
->pOUString
);
234 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
236 pVal
->PutInteger( n
);
238 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
);
241 case SbxBYREF
| SbxCHAR
:
244 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMINCHAR
;
246 *p
->pChar
= static_cast<char>(n
); break;
247 case SbxBYREF
| SbxBYTE
:
250 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXBYTE
;
254 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= 0;
256 *p
->pByte
= static_cast<sal_uInt8
>(n
); break;
257 case SbxBYREF
| SbxINTEGER
:
258 case SbxBYREF
| SbxBOOL
:
259 *p
->pInteger
= n
; break;
260 case SbxBYREF
| SbxERROR
:
261 case SbxBYREF
| SbxUSHORT
:
264 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= 0;
266 *p
->pUShort
= static_cast<sal_uInt16
>(n
); break;
267 case SbxBYREF
| SbxLONG
:
268 *p
->pLong
= static_cast<sal_Int32
>(n
); break;
269 case SbxBYREF
| SbxULONG
:
272 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= 0;
274 *p
->pULong
= static_cast<sal_uInt32
>(n
); break;
275 case SbxBYREF
| SbxCURRENCY
:
276 *p
->pnInt64
= CurFrom(n
); break;
277 case SbxBYREF
| SbxSALINT64
:
278 *p
->pnInt64
= n
; break;
279 case SbxBYREF
| SbxSALUINT64
:
282 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
288 case SbxBYREF
| SbxSINGLE
:
289 *p
->pSingle
= static_cast<float>(n
); break;
290 case SbxBYREF
| SbxDATE
:
291 case SbxBYREF
| SbxDOUBLE
:
292 *p
->pDouble
= static_cast<double>(n
); break;
295 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
302 double ImpSalUInt64ToDouble( sal_uInt64 n
)
305 if( n
> SAL_MAX_INT64
)
306 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
308 d
= static_cast<double>(static_cast<sal_Int64
>(n
));
313 sal_Int64
ImpGetInt64( const SbxValues
* p
)
321 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
326 nRes
= p
->nChar
; break;
328 nRes
= p
->nByte
; break;
331 nRes
= p
->nInteger
; break;
334 nRes
= static_cast<sal_Int64
>(p
->nUShort
); break;
336 nRes
= static_cast<sal_Int64
>(p
->nLong
); break;
338 nRes
= static_cast<sal_Int64
>(p
->nULong
); break;
340 nRes
= ImpDoubleToSalInt64(p
->nSingle
);
344 nRes
= ImpDoubleToSalInt64(p
->nDouble
);
347 nRes
= CurTo
<sal_Int64
>(p
->nInt64
); break;
349 nRes
= p
->nInt64
; break;
351 if( p
->uInt64
> SAL_MAX_INT64
)
353 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= SAL_MAX_INT64
;
356 nRes
= static_cast<sal_Int64
>(p
->uInt64
);
359 case SbxBYREF
| SbxSTRING
:
366 nRes
= p
->pOUString
->toInt64();
369 // Check if really 0 or invalid conversion
372 if( ImpScan( *p
->pOUString
, d
, t
, nullptr ) != ERRCODE_NONE
)
375 nRes
= ImpDoubleToSalInt64(d
);
381 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
383 nRes
= pVal
->GetInt64();
386 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
); nRes
= 0;
391 case SbxBYREF
| SbxCHAR
:
392 nRes
= *p
->pChar
; break;
393 case SbxBYREF
| SbxBYTE
:
394 nRes
= *p
->pByte
; break;
395 case SbxBYREF
| SbxINTEGER
:
396 case SbxBYREF
| SbxBOOL
:
397 nRes
= *p
->pInteger
; break;
398 case SbxBYREF
| SbxLONG
:
399 nRes
= *p
->pLong
; break;
400 case SbxBYREF
| SbxULONG
:
401 nRes
= *p
->pULong
; break;
402 case SbxBYREF
| SbxCURRENCY
:
403 nRes
= CurTo
<sal_Int64
>(*p
->pnInt64
); break;
404 case SbxBYREF
| SbxSALINT64
:
405 nRes
= *p
->pnInt64
; break;
407 // from here the values has to be checked
408 case SbxBYREF
| SbxSALUINT64
:
409 aTmp
.uInt64
= *p
->puInt64
; goto ref
;
411 case SbxBYREF
| SbxERROR
:
412 case SbxBYREF
| SbxUSHORT
:
413 aTmp
.nUShort
= *p
->pUShort
; goto ref
;
414 case SbxBYREF
| SbxSINGLE
:
415 aTmp
.nSingle
= *p
->pSingle
; goto ref
;
416 case SbxBYREF
| SbxDATE
:
417 case SbxBYREF
| SbxDOUBLE
:
418 aTmp
.nDouble
= *p
->pDouble
; goto ref
;
420 aTmp
.eType
= SbxDataType( p
->eType
& 0x0FFF );
421 p
= &aTmp
; goto start
;
424 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
); nRes
= 0;
429 void ImpPutInt64( SbxValues
* p
, sal_Int64 n
)
438 aTmp
.pChar
= &p
->nChar
; goto direct
;
440 aTmp
.pByte
= &p
->nByte
; goto direct
;
443 aTmp
.pInteger
= &p
->nInteger
; goto direct
;
445 aTmp
.pULong
= &p
->nULong
; goto direct
;
448 aTmp
.pUShort
= &p
->nUShort
; goto direct
;
450 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
453 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
455 aTmp
.puInt64
= &p
->uInt64
; goto direct
;
458 aTmp
.eType
= SbxDataType( p
->eType
| SbxBYREF
);
459 p
= &aTmp
; goto start
;
462 p
->nSingle
= static_cast<float>(n
); break;
465 p
->nDouble
= static_cast<double>(n
); break;
467 case SbxBYREF
| SbxSTRING
:
472 p
->pOUString
= new OUString
;
474 (*p
->pOUString
) = OUString::number(n
);
479 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
483 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
);
486 case SbxBYREF
| SbxCHAR
:
489 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXCHAR
;
491 else if( n
< SbxMINCHAR
)
493 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMINCHAR
;
495 *p
->pChar
= static_cast<sal_Unicode
>(n
); break;
496 case SbxBYREF
| SbxBYTE
:
499 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXBYTE
;
503 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= 0;
505 *p
->pByte
= static_cast<sal_uInt8
>(n
); break;
506 case SbxBYREF
| SbxINTEGER
:
507 case SbxBYREF
| SbxBOOL
:
510 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXINT
;
512 else if( n
< SbxMININT
)
514 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMININT
;
516 *p
->pInteger
= static_cast<sal_Int16
>(n
); break;
517 case SbxBYREF
| SbxERROR
:
518 case SbxBYREF
| SbxUSHORT
:
521 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXUINT
;
525 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= 0;
527 *p
->pUShort
= static_cast<sal_uInt16
>(n
); break;
528 case SbxBYREF
| SbxLONG
:
531 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXLNG
;
533 else if( n
< SbxMINLNG
)
535 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMINLNG
;
537 *p
->pLong
= static_cast<sal_Int32
>(n
); break;
538 case SbxBYREF
| SbxULONG
:
541 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXULNG
;
545 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= 0;
547 *p
->pULong
= static_cast<sal_uInt32
>(n
); break;
548 case SbxBYREF
| SbxSINGLE
:
549 *p
->pSingle
= static_cast<float>(n
); break;
550 case SbxBYREF
| SbxDATE
:
551 case SbxBYREF
| SbxDOUBLE
:
552 *p
->pDouble
= static_cast<double>(n
); break;
553 case SbxBYREF
| SbxCURRENCY
:
554 *p
->pnInt64
= CurFrom(n
); break;
555 case SbxBYREF
| SbxSALINT64
:
556 *p
->pnInt64
= n
; break;
557 case SbxBYREF
| SbxSALUINT64
:
560 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= 0;
562 *p
->puInt64
= n
; break;
565 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
569 sal_uInt64
ImpGetUInt64( const SbxValues
* p
)
577 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
582 nRes
= p
->nChar
; break;
584 nRes
= p
->nByte
; break;
587 nRes
= p
->nInteger
; break;
590 nRes
= p
->nUShort
; break;
592 nRes
= p
->nLong
; break;
594 nRes
= static_cast<sal_uInt64
>(p
->nULong
); break;
596 nRes
= ImpDoubleToSalUInt64(p
->nSingle
); break;
599 nRes
= ImpDoubleToSalUInt64(p
->nDouble
);
602 nRes
= CurFrom(p
->nInt64
); break;
606 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); nRes
= 0;
609 nRes
= static_cast<sal_uInt64
>(p
->nInt64
);
612 nRes
= p
->uInt64
; break;
614 case SbxBYREF
| SbxSTRING
:
621 nRes
= p
->pOUString
->toUInt64();
624 // Check if really 0 or invalid conversion
627 if( ImpScan( *p
->pOUString
, d
, t
, nullptr ) != ERRCODE_NONE
)
630 nRes
= ImpDoubleToSalUInt64(d
);
636 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
638 nRes
= pVal
->GetUInt64();
641 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
); nRes
= 0;
646 case SbxBYREF
| SbxCHAR
:
647 nRes
= *p
->pChar
; break;
648 case SbxBYREF
| SbxBYTE
:
649 nRes
= *p
->pByte
; break;
650 case SbxBYREF
| SbxINTEGER
:
651 case SbxBYREF
| SbxBOOL
:
652 nRes
= *p
->pInteger
; break;
653 case SbxBYREF
| SbxLONG
:
654 nRes
= *p
->pLong
; break;
655 case SbxBYREF
| SbxULONG
:
656 nRes
= *p
->pULong
; break;
657 case SbxBYREF
| SbxSALUINT64
:
658 nRes
= *p
->puInt64
; break;
660 // from here on the value has to be checked
661 case SbxBYREF
| SbxERROR
:
662 case SbxBYREF
| SbxUSHORT
:
663 aTmp
.nUShort
= *p
->pUShort
; goto ref
;
664 case SbxBYREF
| SbxSINGLE
:
665 aTmp
.nSingle
= *p
->pSingle
; goto ref
;
666 case SbxBYREF
| SbxDATE
:
667 case SbxBYREF
| SbxDOUBLE
:
668 aTmp
.nDouble
= *p
->pDouble
; goto ref
;
669 case SbxBYREF
| SbxCURRENCY
:
670 case SbxBYREF
| SbxSALINT64
:
671 aTmp
.nInt64
= *p
->pnInt64
; goto ref
;
673 aTmp
.eType
= SbxDataType( p
->eType
& 0x0FFF );
674 p
= &aTmp
; goto start
;
677 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
); nRes
= 0;
682 void ImpPutUInt64( SbxValues
* p
, sal_uInt64 n
)
691 aTmp
.pChar
= &p
->nChar
; goto direct
;
693 aTmp
.pByte
= &p
->nByte
; goto direct
;
696 aTmp
.pInteger
= &p
->nInteger
; goto direct
;
698 aTmp
.pULong
= &p
->nULong
; goto direct
;
701 aTmp
.pUShort
= &p
->nUShort
; goto direct
;
703 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
706 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
708 aTmp
.pSingle
= &p
->nSingle
; goto direct
;
711 aTmp
.pDouble
= &p
->nDouble
; goto direct
;
714 aTmp
.eType
= SbxDataType( p
->eType
| SbxBYREF
);
715 p
= &aTmp
; goto start
;
717 // Check not necessary
719 p
->uInt64
= n
; break;
721 case SbxBYREF
| SbxSTRING
:
725 p
->pOUString
= new OUString
;
726 if( n
> SAL_MAX_INT64
)
727 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
730 (*p
->pOUString
) = OUString::number(n
);
735 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
737 pVal
->PutUInt64( n
);
739 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
);
742 case SbxBYREF
| SbxCHAR
:
745 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXCHAR
;
747 *p
->pChar
= static_cast<sal_Unicode
>(n
); break;
748 case SbxBYREF
| SbxBYTE
:
751 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXBYTE
;
753 *p
->pByte
= static_cast<sal_uInt8
>(n
); break;
754 case SbxBYREF
| SbxINTEGER
:
755 case SbxBYREF
| SbxBOOL
:
758 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXINT
;
760 *p
->pInteger
= static_cast<sal_Int16
>(n
); break;
761 case SbxBYREF
| SbxERROR
:
762 case SbxBYREF
| SbxUSHORT
:
765 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXUINT
;
767 *p
->pUShort
= static_cast<sal_uInt16
>(n
); break;
768 case SbxBYREF
| SbxLONG
:
771 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXLNG
;
773 *p
->pLong
= static_cast<sal_Int32
>(n
); break;
774 case SbxBYREF
| SbxULONG
:
777 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= SbxMAXULNG
;
779 *p
->pULong
= static_cast<sal_uInt32
>(n
); break;
780 case SbxBYREF
| SbxSINGLE
:
781 *p
->pDouble
= static_cast<float>(ImpSalUInt64ToDouble( n
)); break;
782 case SbxBYREF
| SbxDATE
:
783 case SbxBYREF
| SbxDOUBLE
:
785 *p
->pDouble
= ImpSalUInt64ToDouble( n
); break;
786 case SbxBYREF
| SbxCURRENCY
:
787 *p
->pnInt64
= CurFrom(n
);
789 case SbxBYREF
| SbxSALUINT64
:
790 *p
->puInt64
= n
; break;
791 case SbxBYREF
| SbxSALINT64
:
792 if( n
> SAL_MAX_INT64
)
794 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
); n
= 0;
796 *p
->pnInt64
= static_cast<sal_Int64
>(n
); break;
799 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
804 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */