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 <o3tl/char16_t2wchar_t.hxx>
22 #include <basic/sberrors.hxx>
23 #include "sbxconv.hxx"
25 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
27 // Implementation SbxDecimal
28 SbxDecimal::SbxDecimal()
34 SbxDecimal::SbxDecimal( const SbxDecimal
& rDec
)
44 SbxDecimal::SbxDecimal
45 ( const css::bridge::oleautomation::Decimal
& rAutomationDec
)
49 maDec
.scale
= rAutomationDec
.Scale
;
50 maDec
.sign
= rAutomationDec
.Sign
;
51 maDec
.Lo32
= rAutomationDec
.LowValue
;
52 maDec
.Mid32
= rAutomationDec
.MiddleValue
;
53 maDec
.Hi32
= rAutomationDec
.HighValue
;
59 void SbxDecimal::fillAutomationDecimal
60 ( css::bridge::oleautomation::Decimal
& rAutomationDec
)
63 rAutomationDec
.Scale
= maDec
.scale
;
64 rAutomationDec
.Sign
= maDec
.sign
;
65 rAutomationDec
.LowValue
= maDec
.Lo32
;
66 rAutomationDec
.MiddleValue
= maDec
.Mid32
;
67 rAutomationDec
.HighValue
= maDec
.Hi32
;
73 SbxDecimal::~SbxDecimal()
77 void releaseDecimalPtr( SbxDecimal
*& rpDecimal
)
81 rpDecimal
->mnRefCount
--;
82 if( rpDecimal
->mnRefCount
== 0 )
92 bool SbxDecimal::operator -= ( const SbxDecimal
&r
)
94 HRESULT hResult
= VarDecSub( &maDec
, const_cast<LPDECIMAL
>(&r
.maDec
), &maDec
);
95 bool bRet
= ( hResult
== S_OK
);
99 bool SbxDecimal::operator += ( const SbxDecimal
&r
)
101 HRESULT hResult
= VarDecAdd( &maDec
, const_cast<LPDECIMAL
>(&r
.maDec
), &maDec
);
102 bool bRet
= ( hResult
== S_OK
);
106 bool SbxDecimal::operator /= ( const SbxDecimal
&r
)
108 HRESULT hResult
= VarDecDiv( &maDec
, const_cast<LPDECIMAL
>(&r
.maDec
), &maDec
);
109 bool bRet
= ( hResult
== S_OK
);
113 bool SbxDecimal::operator *= ( const SbxDecimal
&r
)
115 HRESULT hResult
= VarDecMul( &maDec
, const_cast<LPDECIMAL
>(&r
.maDec
), &maDec
);
116 bool bRet
= ( hResult
== S_OK
);
120 bool SbxDecimal::neg()
122 HRESULT hResult
= VarDecNeg( &maDec
, &maDec
);
123 bool bRet
= ( hResult
== S_OK
);
127 bool SbxDecimal::isZero() const
130 aZeroDec
.setLong( 0 );
131 bool bZero
= CmpResult::EQ
== compare( *this, aZeroDec
);
135 SbxDecimal::CmpResult
compare( const SbxDecimal
&rLeft
, const SbxDecimal
&rRight
)
137 HRESULT hResult
= VarDecCmp( const_cast<LPDECIMAL
>(&rLeft
.maDec
), const_cast<LPDECIMAL
>(&rRight
.maDec
) );
138 SbxDecimal::CmpResult eRes
= static_cast<SbxDecimal::CmpResult
>(hResult
);
142 void SbxDecimal::setChar( sal_Unicode val
)
144 VarDecFromUI2( static_cast<sal_uInt16
>(val
), &maDec
);
147 void SbxDecimal::setByte( sal_uInt8 val
)
149 VarDecFromUI1( val
, &maDec
);
152 void SbxDecimal::setShort( sal_Int16 val
)
154 VarDecFromI2( static_cast<short>(val
), &maDec
);
157 void SbxDecimal::setLong( sal_Int32 val
)
159 VarDecFromI4( static_cast<long>(val
), &maDec
);
162 void SbxDecimal::setUShort( sal_uInt16 val
)
164 VarDecFromUI2( val
, &maDec
);
167 void SbxDecimal::setULong( sal_uInt32 val
)
169 VarDecFromUI4( static_cast<ULONG
>(val
), &maDec
);
172 bool SbxDecimal::setSingle( float val
)
174 bool bRet
= ( VarDecFromR4( val
, &maDec
) == S_OK
);
178 bool SbxDecimal::setDouble( double val
)
180 bool bRet
= ( VarDecFromR8( val
, &maDec
) == S_OK
);
184 void SbxDecimal::setInt( int val
)
186 setLong( static_cast<sal_Int32
>(val
) );
189 void SbxDecimal::setUInt( unsigned int val
)
191 setULong( static_cast<sal_uInt32
>(val
) );
194 bool SbxDecimal::setString( OUString
* pOUString
)
198 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
201 sal_Unicode cDecimalSep
;
202 sal_Unicode cThousandSep
;
203 sal_Unicode cDecimalSepAlt
;
204 ImpGetIntntlSep( cDecimalSep
, cThousandSep
, cDecimalSepAlt
);
208 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
210 int nLen
= pOUString
->getLength();
211 std::unique_ptr
<sal_Unicode
[]> pBuffer(new sal_Unicode
[nLen
+ 1]);
214 const sal_Unicode
* pSrc
= pOUString
->getStr();
215 for( int i
= 0 ; i
< nLen
; ++i
)
217 sal_Unicode c
= pSrc
[i
];
218 if (c
== cDecimalSep
)
220 else if (c
== cThousandSep
)
225 hResult
= VarDecFromStr( o3tl::toW(pBuffer
.get()), nLANGID
, 0, &maDec
);
229 hResult
= VarDecFromStr( o3tl::toW(pOUString
->getStr()), nLANGID
, 0, &maDec
);
231 bRet
= ( hResult
== S_OK
);
236 bool SbxDecimal::getChar( sal_Unicode
& rVal
)
239 bool bRet
= ( VarUI2FromDec( &maDec
, &n
) == S_OK
);
246 bool SbxDecimal::getShort( sal_Int16
& rVal
)
248 bool bRet
= ( VarI2FromDec( &maDec
, &rVal
) == S_OK
);
252 bool SbxDecimal::getLong( sal_Int32
& rVal
)
254 bool bRet
= ( VarI4FromDec( &maDec
, &rVal
) == S_OK
);
258 bool SbxDecimal::getUShort( sal_uInt16
& rVal
)
260 bool bRet
= ( VarUI2FromDec( &maDec
, &rVal
) == S_OK
);
264 bool SbxDecimal::getULong( sal_uInt32
& rVal
)
266 bool bRet
= ( VarUI4FromDec( &maDec
, &rVal
) == S_OK
);
270 bool SbxDecimal::getSingle( float& rVal
)
272 bool bRet
= ( VarR4FromDec( &maDec
, &rVal
) == S_OK
);
276 bool SbxDecimal::getDouble( double& rVal
)
278 bool bRet
= ( VarR8FromDec( &maDec
, &rVal
) == S_OK
);
285 bool SbxDecimal::operator -= ( const SbxDecimal
& )
290 bool SbxDecimal::operator += ( const SbxDecimal
& )
295 bool SbxDecimal::operator /= ( const SbxDecimal
& )
300 bool SbxDecimal::operator *= ( const SbxDecimal
& )
305 bool SbxDecimal::neg()
310 bool SbxDecimal::isZero() const
315 SbxDecimal::CmpResult
compare( SAL_UNUSED_PARAMETER
const SbxDecimal
&, SAL_UNUSED_PARAMETER
const SbxDecimal
& )
317 return SbxDecimal::CmpResult::LT
;
320 void SbxDecimal::setChar( SAL_UNUSED_PARAMETER sal_Unicode
) {}
321 void SbxDecimal::setByte( SAL_UNUSED_PARAMETER sal_uInt8
) {}
322 void SbxDecimal::setShort( SAL_UNUSED_PARAMETER sal_Int16
) {}
323 void SbxDecimal::setLong( SAL_UNUSED_PARAMETER sal_Int32
) {}
324 void SbxDecimal::setUShort( SAL_UNUSED_PARAMETER sal_uInt16
) {}
325 void SbxDecimal::setULong( SAL_UNUSED_PARAMETER sal_uInt32
) {}
326 bool SbxDecimal::setSingle( SAL_UNUSED_PARAMETER
float ) { return false; }
327 bool SbxDecimal::setDouble( SAL_UNUSED_PARAMETER
double ) { return false; }
328 void SbxDecimal::setInt( SAL_UNUSED_PARAMETER
int ) {}
329 void SbxDecimal::setUInt( SAL_UNUSED_PARAMETER
unsigned int ) {}
330 bool SbxDecimal::setString( SAL_UNUSED_PARAMETER OUString
* ) { return false; }
332 bool SbxDecimal::getChar( SAL_UNUSED_PARAMETER sal_Unicode
& ) { return false; }
333 bool SbxDecimal::getShort( SAL_UNUSED_PARAMETER sal_Int16
& ) { return false; }
334 bool SbxDecimal::getLong( SAL_UNUSED_PARAMETER sal_Int32
& ) { return false; }
335 bool SbxDecimal::getUShort( SAL_UNUSED_PARAMETER sal_uInt16
& ) { return false; }
336 bool SbxDecimal::getULong( SAL_UNUSED_PARAMETER sal_uInt32
& ) { return false; }
337 bool SbxDecimal::getSingle( SAL_UNUSED_PARAMETER
float& ) { return false; }
338 bool SbxDecimal::getDouble( SAL_UNUSED_PARAMETER
double& ) { return false; }
342 void SbxDecimal::getString( OUString
& rString
)
345 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
347 BSTR pBStr
= nullptr;
348 // VarBstrFromDec allocates new BSTR that needs to be released with SysFreeString
349 HRESULT hResult
= VarBstrFromDec( &maDec
, nLANGID
, 0, &pBStr
);
350 if( hResult
== S_OK
)
353 sal_Unicode cDecimalSep
;
354 sal_Unicode cThousandSep
;
355 sal_Unicode cDecimalSepAlt
;
356 ImpGetIntntlSep( cDecimalSep
, cThousandSep
, cDecimalSepAlt
);
358 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
362 while( (c
= pBStr
[i
]) != 0 )
365 pBStr
[i
] = cDecimalSep
;
367 pBStr
[i
] = cThousandSep
;
371 rString
= o3tl::toU( pBStr
);
372 SysFreeString( pBStr
);
379 SbxDecimal
* ImpCreateDecimal( SbxValues
* p
)
384 SbxDecimal
*& rpDecimal
= p
->pDecimal
;
385 if( rpDecimal
== nullptr )
387 rpDecimal
= new SbxDecimal();
393 SbxDecimal
* ImpGetDecimal( const SbxValues
* p
)
396 SbxDecimal
* pnDecRes
;
398 SbxDataType eType
= p
->eType
;
399 if( eType
== SbxDECIMAL
&& p
->pDecimal
)
401 pnDecRes
= new SbxDecimal( *p
->pDecimal
);
405 pnDecRes
= new SbxDecimal();
412 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
415 pnDecRes
->setShort( 0 ); break;
417 pnDecRes
->setChar( p
->nChar
); break;
419 pnDecRes
->setByte( p
->nByte
); break;
422 pnDecRes
->setInt( p
->nInteger
); break;
425 pnDecRes
->setUShort( p
->nUShort
); break;
427 pnDecRes
->setLong( p
->nLong
); break;
429 pnDecRes
->setULong( p
->nULong
); break;
431 if( !pnDecRes
->setSingle( p
->nSingle
) )
432 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
436 if( !pnDecRes
->setDouble( ImpCurrencyToDouble( p
->nInt64
) ) )
437 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
442 if( !pnDecRes
->setDouble( static_cast<double>(p
->nInt64
) ) )
443 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
448 if( !pnDecRes
->setDouble( static_cast<double>(p
->uInt64
) ) )
449 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
455 double dVal
= p
->nDouble
;
456 if( !pnDecRes
->setDouble( dVal
) )
457 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
462 case SbxBYREF
| SbxSTRING
:
464 pnDecRes
->setString( p
->pOUString
);
468 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
470 pnDecRes
->setDecimal( pVal
->GetDecimal() );
473 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
);
474 pnDecRes
->setShort( 0 );
479 case SbxBYREF
| SbxCHAR
:
480 pnDecRes
->setChar( *p
->pChar
); break;
481 case SbxBYREF
| SbxBYTE
:
482 pnDecRes
->setByte( *p
->pByte
); break;
483 case SbxBYREF
| SbxINTEGER
:
484 case SbxBYREF
| SbxBOOL
:
485 pnDecRes
->setInt( *p
->pInteger
); break;
486 case SbxBYREF
| SbxLONG
:
487 pnDecRes
->setLong( *p
->pLong
); break;
488 case SbxBYREF
| SbxULONG
:
489 pnDecRes
->setULong( *p
->pULong
); break;
490 case SbxBYREF
| SbxERROR
:
491 case SbxBYREF
| SbxUSHORT
:
492 pnDecRes
->setUShort( *p
->pUShort
); break;
494 // from here on had to be tested
495 case SbxBYREF
| SbxSINGLE
:
496 aTmp
.nSingle
= *p
->pSingle
; goto ref
;
497 case SbxBYREF
| SbxDATE
:
498 case SbxBYREF
| SbxDOUBLE
:
499 aTmp
.nDouble
= *p
->pDouble
; goto ref
;
500 case SbxBYREF
| SbxCURRENCY
:
501 case SbxBYREF
| SbxSALINT64
:
502 aTmp
.nInt64
= *p
->pnInt64
; goto ref
;
503 case SbxBYREF
| SbxSALUINT64
:
504 aTmp
.uInt64
= *p
->puInt64
; goto ref
;
506 aTmp
.eType
= SbxDataType( p
->eType
& 0x0FFF );
507 p
= &aTmp
; goto start
;
510 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
); pnDecRes
->setShort( 0 );
515 void ImpPutDecimal( SbxValues
* p
, SbxDecimal
* pDec
)
524 // here had to be tested
526 aTmp
.pChar
= &p
->nChar
; goto direct
;
528 aTmp
.pByte
= &p
->nByte
; goto direct
;
530 aTmp
.pULong
= &p
->nULong
; goto direct
;
533 aTmp
.pUShort
= &p
->nUShort
; goto direct
;
536 aTmp
.pInteger
= &p
->nInteger
; goto direct
;
538 aTmp
.pLong
= &p
->nLong
; goto direct
;
541 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
543 aTmp
.puInt64
= &p
->uInt64
; goto direct
;
546 aTmp
.eType
= SbxDataType( p
->eType
| SbxBYREF
);
547 p
= &aTmp
; goto start
;
549 // from here on no longer
551 case SbxBYREF
| SbxDECIMAL
:
553 if( pDec
!= p
->pDecimal
)
555 releaseDecimalPtr( p
->pDecimal
);
565 pDec
->getSingle( f
);
573 pDec
->getDouble( d
);
580 case SbxBYREF
| SbxSTRING
:
582 p
->pOUString
= new OUString
;
583 pDec
->getString( *p
->pOUString
);
587 SbxValue
* pVal
= dynamic_cast<SbxValue
*>( p
->pObj
);
589 pVal
->PutDecimal( pDec
);
591 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT
);
595 case SbxBYREF
| SbxCHAR
:
596 if( !pDec
->getChar( *p
->pChar
) )
598 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
602 case SbxBYREF
| SbxBYTE
:
603 if( !pDec
->getChar( *p
->pChar
) )
605 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
609 case SbxBYREF
| SbxINTEGER
:
610 case SbxBYREF
| SbxBOOL
:
611 if( !pDec
->getShort( *p
->pInteger
) )
613 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
617 case SbxBYREF
| SbxERROR
:
618 case SbxBYREF
| SbxUSHORT
:
619 if( !pDec
->getUShort( *p
->pUShort
) )
621 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
625 case SbxBYREF
| SbxLONG
:
626 if( !pDec
->getLong( *p
->pLong
) )
628 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
632 case SbxBYREF
| SbxULONG
:
633 if( !pDec
->getULong( *p
->pULong
) )
635 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
639 case SbxBYREF
| SbxCURRENCY
:
642 if( !pDec
->getDouble( d
) )
643 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
644 *p
->pnInt64
= ImpDoubleToCurrency( d
);
647 case SbxBYREF
| SbxSALINT64
:
650 if( !pDec
->getDouble( d
) )
651 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
653 *p
->pnInt64
= ImpDoubleToSalInt64( d
);
656 case SbxBYREF
| SbxSALUINT64
:
659 if( !pDec
->getDouble( d
) )
660 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
662 *p
->puInt64
= ImpDoubleToSalUInt64( d
);
665 case SbxBYREF
| SbxSINGLE
:
666 if( !pDec
->getSingle( *p
->pSingle
) )
668 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
672 case SbxBYREF
| SbxDATE
:
673 case SbxBYREF
| SbxDOUBLE
:
674 if( !pDec
->getDouble( *p
->pDouble
) )
676 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW
);
681 SbxBase::SetError( ERRCODE_BASIC_CONVERSION
);
685 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */