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/char16_t2wchar_t.hxx>
23 #include <systools/win32/oleauto.hxx>
26 #include <basic/sberrors.hxx>
27 #include "sbxconv.hxx"
29 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
31 // Implementation SbxDecimal
32 SbxDecimal::SbxDecimal()
38 SbxDecimal::SbxDecimal( const SbxDecimal
& rDec
)
48 SbxDecimal::SbxDecimal
49 ( const css::bridge::oleautomation::Decimal
& rAutomationDec
)
53 maDec
.scale
= rAutomationDec
.Scale
;
54 maDec
.sign
= rAutomationDec
.Sign
;
55 maDec
.Lo32
= rAutomationDec
.LowValue
;
56 maDec
.Mid32
= rAutomationDec
.MiddleValue
;
57 maDec
.Hi32
= rAutomationDec
.HighValue
;
63 void SbxDecimal::fillAutomationDecimal
64 ( css::bridge::oleautomation::Decimal
& rAutomationDec
)
67 rAutomationDec
.Scale
= maDec
.scale
;
68 rAutomationDec
.Sign
= maDec
.sign
;
69 rAutomationDec
.LowValue
= maDec
.Lo32
;
70 rAutomationDec
.MiddleValue
= maDec
.Mid32
;
71 rAutomationDec
.HighValue
= maDec
.Hi32
;
77 void releaseDecimalPtr( SbxDecimal
*& rpDecimal
)
81 rpDecimal
->mnRefCount
--;
82 if( rpDecimal
->mnRefCount
== 0 )
90 bool SbxDecimal::operator -= ( const SbxDecimal
&r
)
92 HRESULT hResult
= VarDecSub( &maDec
, const_cast<LPDECIMAL
>(&r
.maDec
), &maDec
);
93 bool bRet
= ( hResult
== S_OK
);
97 bool SbxDecimal::operator += ( const SbxDecimal
&r
)
99 HRESULT hResult
= VarDecAdd( &maDec
, const_cast<LPDECIMAL
>(&r
.maDec
), &maDec
);
100 bool bRet
= ( hResult
== S_OK
);
104 bool SbxDecimal::operator /= ( const SbxDecimal
&r
)
106 HRESULT hResult
= VarDecDiv( &maDec
, const_cast<LPDECIMAL
>(&r
.maDec
), &maDec
);
107 bool bRet
= ( hResult
== S_OK
);
111 bool SbxDecimal::operator *= ( const SbxDecimal
&r
)
113 HRESULT hResult
= VarDecMul( &maDec
, const_cast<LPDECIMAL
>(&r
.maDec
), &maDec
);
114 bool bRet
= ( hResult
== S_OK
);
118 bool SbxDecimal::neg()
120 HRESULT hResult
= VarDecNeg( &maDec
, &maDec
);
121 bool bRet
= ( hResult
== S_OK
);
125 bool SbxDecimal::isZero() const
128 aZeroDec
.setLong( 0 );
129 bool bZero
= CmpResult::EQ
== compare( *this, aZeroDec
);
133 SbxDecimal::CmpResult
compare( const SbxDecimal
&rLeft
, const SbxDecimal
&rRight
)
135 HRESULT hResult
= VarDecCmp( const_cast<LPDECIMAL
>(&rLeft
.maDec
), const_cast<LPDECIMAL
>(&rRight
.maDec
) );
136 SbxDecimal::CmpResult eRes
= static_cast<SbxDecimal::CmpResult
>(hResult
);
140 void SbxDecimal::setChar( sal_Unicode val
)
142 VarDecFromUI2( static_cast<sal_uInt16
>(val
), &maDec
);
145 void SbxDecimal::setByte( sal_uInt8 val
)
147 VarDecFromUI1( val
, &maDec
);
150 void SbxDecimal::setShort( sal_Int16 val
)
152 VarDecFromI2( static_cast<short>(val
), &maDec
);
155 void SbxDecimal::setLong( sal_Int32 val
)
157 VarDecFromI4(static_cast<LONG
>(val
), &maDec
);
160 void SbxDecimal::setUShort( sal_uInt16 val
)
162 VarDecFromUI2( val
, &maDec
);
165 void SbxDecimal::setULong( sal_uInt32 val
)
167 VarDecFromUI4( static_cast<ULONG
>(val
), &maDec
);
170 bool SbxDecimal::setSingle( float val
)
172 bool bRet
= ( VarDecFromR4( val
, &maDec
) == S_OK
);
176 bool SbxDecimal::setDouble( double val
)
178 bool bRet
= ( VarDecFromR8( val
, &maDec
) == S_OK
);
182 void SbxDecimal::setInt( int val
)
184 setLong( static_cast<sal_Int32
>(val
) );
187 void SbxDecimal::setUInt( unsigned int val
)
189 setULong( static_cast<sal_uInt32
>(val
) );
192 bool SbxDecimal::setString( OUString
* pOUString
)
196 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
199 sal_Unicode cDecimalSep
;
200 sal_Unicode cThousandSep
;
201 sal_Unicode cDecimalSepAlt
;
202 ImpGetIntntlSep( cDecimalSep
, cThousandSep
, cDecimalSepAlt
);
206 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
208 int nLen
= pOUString
->getLength();
209 std::unique_ptr
<sal_Unicode
[]> pBuffer(new sal_Unicode
[nLen
+ 1]);
212 const sal_Unicode
* pSrc
= pOUString
->getStr();
213 for( int i
= 0 ; i
< nLen
; ++i
)
215 sal_Unicode c
= pSrc
[i
];
216 if (c
== cDecimalSep
)
218 else if (c
== cThousandSep
)
223 hResult
= VarDecFromStr( o3tl::toW(pBuffer
.get()), nLANGID
, 0, &maDec
);
227 hResult
= VarDecFromStr( o3tl::toW(pOUString
->getStr()), nLANGID
, 0, &maDec
);
229 bRet
= ( hResult
== S_OK
);
234 bool SbxDecimal::getChar( sal_Unicode
& rVal
)
237 bool bRet
= ( VarUI2FromDec( &maDec
, &n
) == S_OK
);
244 bool SbxDecimal::getShort( sal_Int16
& rVal
)
246 bool bRet
= ( VarI2FromDec( &maDec
, &rVal
) == S_OK
);
250 bool SbxDecimal::getLong( sal_Int32
& rVal
)
252 bool bRet
= ( VarI4FromDec( &maDec
, &rVal
) == S_OK
);
256 bool SbxDecimal::getUShort( sal_uInt16
& rVal
)
258 bool bRet
= ( VarUI2FromDec( &maDec
, &rVal
) == S_OK
);
262 bool SbxDecimal::getULong( sal_uInt32
& rVal
)
264 bool bRet
= ( VarUI4FromDec( &maDec
, &rVal
) == S_OK
);
268 bool SbxDecimal::getSingle( float& rVal
)
270 bool bRet
= ( VarR4FromDec( &maDec
, &rVal
) == S_OK
);
274 bool SbxDecimal::getDouble( double& rVal
)
276 bool bRet
= ( VarR8FromDec( &maDec
, &rVal
) == S_OK
);
283 bool SbxDecimal::operator -= ( const SbxDecimal
& )
288 bool SbxDecimal::operator += ( const SbxDecimal
& )
293 bool SbxDecimal::operator /= ( const SbxDecimal
& )
298 bool SbxDecimal::operator *= ( const SbxDecimal
& )
303 bool SbxDecimal::neg()
308 bool SbxDecimal::isZero() const
313 SbxDecimal::CmpResult
compare( SAL_UNUSED_PARAMETER
const SbxDecimal
&, SAL_UNUSED_PARAMETER
const SbxDecimal
& )
315 return SbxDecimal::CmpResult::LT
;
318 void SbxDecimal::setChar( SAL_UNUSED_PARAMETER sal_Unicode
) {}
319 void SbxDecimal::setByte( SAL_UNUSED_PARAMETER sal_uInt8
) {}
320 void SbxDecimal::setShort( SAL_UNUSED_PARAMETER sal_Int16
) {}
321 void SbxDecimal::setLong( SAL_UNUSED_PARAMETER sal_Int32
) {}
322 void SbxDecimal::setUShort( SAL_UNUSED_PARAMETER sal_uInt16
) {}
323 void SbxDecimal::setULong( SAL_UNUSED_PARAMETER sal_uInt32
) {}
324 bool SbxDecimal::setSingle( SAL_UNUSED_PARAMETER
float ) { return false; }
325 bool SbxDecimal::setDouble( SAL_UNUSED_PARAMETER
double ) { return false; }
326 void SbxDecimal::setInt( SAL_UNUSED_PARAMETER
int ) {}
327 void SbxDecimal::setUInt( SAL_UNUSED_PARAMETER
unsigned int ) {}
328 bool SbxDecimal::setString( SAL_UNUSED_PARAMETER OUString
* ) { return false; }
330 bool SbxDecimal::getChar( SAL_UNUSED_PARAMETER sal_Unicode
& ) { return false; }
331 bool SbxDecimal::getShort( SAL_UNUSED_PARAMETER sal_Int16
& ) { return false; }
332 bool SbxDecimal::getLong( SAL_UNUSED_PARAMETER sal_Int32
& ) { return false; }
333 bool SbxDecimal::getUShort( SAL_UNUSED_PARAMETER sal_uInt16
& ) { return false; }
334 bool SbxDecimal::getULong( SAL_UNUSED_PARAMETER sal_uInt32
& ) { return false; }
335 bool SbxDecimal::getSingle( SAL_UNUSED_PARAMETER
float& ) { return false; }
336 bool SbxDecimal::getDouble( SAL_UNUSED_PARAMETER
double& ) { return false; }
340 void SbxDecimal::getString( OUString
& rString
)
343 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
345 sal::systools::BStr pBStr
;
346 // VarBstrFromDec allocates new BSTR that needs to be released with SysFreeString
347 HRESULT hResult
= VarBstrFromDec( &maDec
, nLANGID
, 0, &pBStr
);
348 if( hResult
== S_OK
)
351 sal_Unicode cDecimalSep
;
352 sal_Unicode cThousandSep
;
353 sal_Unicode cDecimalSepAlt
;
354 ImpGetIntntlSep( cDecimalSep
, cThousandSep
, cDecimalSepAlt
);
356 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
360 while( (c
= pBStr
[i
]) != 0 )
363 pBStr
[i
] = cDecimalSep
;
365 pBStr
[i
] = cThousandSep
;
376 SbxDecimal
* ImpCreateDecimal( SbxValues
* p
)
381 SbxDecimal
*& rpDecimal
= p
->pDecimal
;
382 if( rpDecimal
== nullptr )
384 rpDecimal
= new SbxDecimal();
390 SbxDecimal
* ImpGetDecimal( const SbxValues
* p
)
393 SbxDecimal
* pnDecRes
;
395 SbxDataType eType
= p
->eType
;
396 if( eType
== SbxDECIMAL
&& p
->pDecimal
)
398 pnDecRes
= new SbxDecimal( *p
->pDecimal
);
402 pnDecRes
= new SbxDecimal();
409 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
412 pnDecRes
->setShort( 0 ); break;
414 pnDecRes
->setChar( p
->nChar
); break;
416 pnDecRes
->setByte( p
->nByte
); break;
419 pnDecRes
->setInt( p
->nInteger
); break;
422 pnDecRes
->setUShort( p
->nUShort
); break;
424 pnDecRes
->setLong( p
->nLong
); break;
426 pnDecRes
->setULong( p
->nULong
); break;
428 if( !pnDecRes
->setSingle( p
->nSingle
) )
429 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
433 if( !pnDecRes
->setDouble( ImpCurrencyToDouble( p
->nInt64
) ) )
434 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
439 if( !pnDecRes
->setDouble( static_cast<double>(p
->nInt64
) ) )
440 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
445 if( !pnDecRes
->setDouble( static_cast<double>(p
->uInt64
) ) )
446 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
452 double dVal
= p
->nDouble
;
453 if( !pnDecRes
->setDouble( dVal
) )
454 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
459 case SbxBYREF
| SbxSTRING
:
461 pnDecRes
->setString( p
->pOUString
);
465 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
467 pnDecRes
->setDecimal( pVal
->GetDecimal() );
470 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
);
471 pnDecRes
->setShort( 0 );
476 case SbxBYREF
| SbxCHAR
:
477 pnDecRes
->setChar( *p
->pChar
); break;
478 case SbxBYREF
| SbxBYTE
:
479 pnDecRes
->setByte( *p
->pByte
); break;
480 case SbxBYREF
| SbxINTEGER
:
481 case SbxBYREF
| SbxBOOL
:
482 pnDecRes
->setInt( *p
->pInteger
); break;
483 case SbxBYREF
| SbxLONG
:
484 pnDecRes
->setLong( *p
->pLong
); break;
485 case SbxBYREF
| SbxULONG
:
486 pnDecRes
->setULong( *p
->pULong
); break;
487 case SbxBYREF
| SbxERROR
:
488 case SbxBYREF
| SbxUSHORT
:
489 pnDecRes
->setUShort( *p
->pUShort
); break;
491 // from here on had to be tested
492 case SbxBYREF
| SbxSINGLE
:
493 aTmp
.nSingle
= *p
->pSingle
; goto ref
;
494 case SbxBYREF
| SbxDATE
:
495 case SbxBYREF
| SbxDOUBLE
:
496 aTmp
.nDouble
= *p
->pDouble
; goto ref
;
497 case SbxBYREF
| SbxCURRENCY
:
498 case SbxBYREF
| SbxSALINT64
:
499 aTmp
.nInt64
= *p
->pnInt64
; goto ref
;
500 case SbxBYREF
| SbxSALUINT64
:
501 aTmp
.uInt64
= *p
->puInt64
; goto ref
;
503 aTmp
.eType
= SbxDataType( p
->eType
& 0x0FFF );
504 p
= &aTmp
; goto start
;
507 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
); pnDecRes
->setShort( 0 );
512 void ImpPutDecimal( SbxValues
* p
, SbxDecimal
* pDec
)
521 // here had to be tested
523 aTmp
.pChar
= &p
->nChar
; goto direct
;
525 aTmp
.pByte
= &p
->nByte
; goto direct
;
527 aTmp
.pULong
= &p
->nULong
; goto direct
;
530 aTmp
.pUShort
= &p
->nUShort
; goto direct
;
533 aTmp
.pInteger
= &p
->nInteger
; goto direct
;
535 aTmp
.pLong
= &p
->nLong
; goto direct
;
538 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
540 aTmp
.puInt64
= &p
->uInt64
; goto direct
;
543 aTmp
.eType
= SbxDataType( p
->eType
| SbxBYREF
);
544 p
= &aTmp
; goto start
;
546 // from here on no longer
548 case SbxBYREF
| SbxDECIMAL
:
550 if( pDec
!= p
->pDecimal
)
552 releaseDecimalPtr( p
->pDecimal
);
562 pDec
->getSingle( f
);
570 pDec
->getDouble( d
);
577 case SbxBYREF
| SbxSTRING
:
579 p
->pOUString
= new OUString
;
580 pDec
->getString( *p
->pOUString
);
584 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
586 pVal
->PutDecimal( pDec
);
588 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
);
592 case SbxBYREF
| SbxCHAR
:
593 if( !pDec
->getChar( *p
->pChar
) )
595 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
599 case SbxBYREF
| SbxBYTE
:
600 if( !pDec
->getChar( *p
->pChar
) )
602 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
606 case SbxBYREF
| SbxINTEGER
:
607 case SbxBYREF
| SbxBOOL
:
608 if( !pDec
->getShort( *p
->pInteger
) )
610 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
614 case SbxBYREF
| SbxERROR
:
615 case SbxBYREF
| SbxUSHORT
:
616 if( !pDec
->getUShort( *p
->pUShort
) )
618 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
622 case SbxBYREF
| SbxLONG
:
623 if( !pDec
->getLong( *p
->pLong
) )
625 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
629 case SbxBYREF
| SbxULONG
:
630 if( !pDec
->getULong( *p
->pULong
) )
632 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
636 case SbxBYREF
| SbxCURRENCY
:
639 if( !pDec
->getDouble( d
) )
640 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
641 *p
->pnInt64
= ImpDoubleToCurrency( d
);
644 case SbxBYREF
| SbxSALINT64
:
647 if( !pDec
->getDouble( d
) )
648 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
650 *p
->pnInt64
= ImpDoubleToSalInt64( d
);
653 case SbxBYREF
| SbxSALUINT64
:
656 if( !pDec
->getDouble( d
) )
657 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
659 *p
->puInt64
= ImpDoubleToSalUInt64( d
);
662 case SbxBYREF
| SbxSINGLE
:
663 if( !pDec
->getSingle( *p
->pSingle
) )
665 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
669 case SbxBYREF
| SbxDATE
:
670 case SbxBYREF
| SbxDOUBLE
:
671 if( !pDec
->getDouble( *p
->pDouble
) )
673 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
678 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */