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 <tools/errcode.hxx>
22 #include <basic/sbx.hxx>
23 #include "sbxconv.hxx"
25 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
28 // Implementation SbxDecimal
29 SbxDecimal::SbxDecimal( void )
35 SbxDecimal::SbxDecimal( const SbxDecimal
& rDec
)
45 SbxDecimal::SbxDecimal
46 ( const com::sun::star::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
;
60 void SbxDecimal::fillAutomationDecimal
61 ( com::sun::star::bridge::oleautomation::Decimal
& rAutomationDec
)
64 rAutomationDec
.Scale
= maDec
.scale
;
65 rAutomationDec
.Sign
= maDec
.sign
;
66 rAutomationDec
.LowValue
= maDec
.Lo32
;
67 rAutomationDec
.MiddleValue
= maDec
.Mid32
;
68 rAutomationDec
.HighValue
= maDec
.Hi32
;
74 SbxDecimal::~SbxDecimal()
78 void releaseDecimalPtr( SbxDecimal
*& rpDecimal
)
82 rpDecimal
->mnRefCount
--;
83 if( rpDecimal
->mnRefCount
== 0 )
93 bool SbxDecimal::operator -= ( const SbxDecimal
&r
)
95 HRESULT hResult
= VarDecSub( &maDec
, (LPDECIMAL
)&r
.maDec
, &maDec
);
96 bool bRet
= ( hResult
== S_OK
);
100 bool SbxDecimal::operator += ( const SbxDecimal
&r
)
102 HRESULT hResult
= VarDecAdd( &maDec
, (LPDECIMAL
)&r
.maDec
, &maDec
);
103 bool bRet
= ( hResult
== S_OK
);
107 bool SbxDecimal::operator /= ( const SbxDecimal
&r
)
109 HRESULT hResult
= VarDecDiv( &maDec
, (LPDECIMAL
)&r
.maDec
, &maDec
);
110 bool bRet
= ( hResult
== S_OK
);
114 bool SbxDecimal::operator *= ( const SbxDecimal
&r
)
116 HRESULT hResult
= VarDecMul( &maDec
, (LPDECIMAL
)&r
.maDec
, &maDec
);
117 bool bRet
= ( hResult
== S_OK
);
121 bool SbxDecimal::neg( void )
123 HRESULT hResult
= VarDecNeg( &maDec
, &maDec
);
124 bool bRet
= ( hResult
== S_OK
);
128 bool SbxDecimal::isZero( void )
131 aZeroDec
.setLong( 0 );
132 bool bZero
= ( EQ
== compare( *this, aZeroDec
) );
136 SbxDecimal::CmpResult
compare( const SbxDecimal
&rLeft
, const SbxDecimal
&rRight
)
138 HRESULT hResult
= VarDecCmp( (LPDECIMAL
)&rLeft
.maDec
, (LPDECIMAL
)&rRight
.maDec
);
139 SbxDecimal::CmpResult eRes
= (SbxDecimal::CmpResult
)hResult
;
143 void SbxDecimal::setChar( sal_Unicode val
)
145 VarDecFromUI2( (sal_uInt16
)val
, &maDec
);
148 void SbxDecimal::setByte( sal_uInt8 val
)
150 VarDecFromUI1( (sal_uInt8
)val
, &maDec
);
153 void SbxDecimal::setShort( sal_Int16 val
)
155 VarDecFromI2( (short)val
, &maDec
);
158 void SbxDecimal::setLong( sal_Int32 val
)
160 VarDecFromI4( (long)val
, &maDec
);
163 void SbxDecimal::setUShort( sal_uInt16 val
)
165 VarDecFromUI2( (sal_uInt16
)val
, &maDec
);
168 void SbxDecimal::setULong( sal_uInt32 val
)
170 VarDecFromUI4( (sal_uIntPtr
)val
, &maDec
);
173 bool SbxDecimal::setSingle( float val
)
175 bool bRet
= ( VarDecFromR4( val
, &maDec
) == S_OK
);
179 bool SbxDecimal::setDouble( double val
)
181 bool bRet
= ( VarDecFromR8( val
, &maDec
) == S_OK
);
185 void SbxDecimal::setInt( int val
)
187 setLong( (sal_Int32
)val
);
190 void SbxDecimal::setUInt( unsigned int val
)
192 setULong( (sal_uInt32
)val
);
195 bool SbxDecimal::setString( OUString
* pOUString
)
197 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
200 sal_Unicode cDecimalSep
;
201 sal_Unicode cThousandSep
;
202 ImpGetIntntlSep( cDecimalSep
, cThousandSep
);
206 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
208 int nLen
= pOUString
->getLength();
209 sal_Unicode
* pBuffer
= new sal_Unicode
[nLen
+ 1];
212 const sal_Unicode
* pSrc
= pOUString
->getStr();
214 for( i
= 0 ; i
< nLen
; ++i
)
215 pBuffer
[i
] = pSrc
[i
];
219 while( (c
= pBuffer
[i
]) != 0 )
221 if( c
== cDecimalSep
)
223 else if( c
== cThousandSep
)
227 hResult
= VarDecFromStr( (OLECHAR
*)pBuffer
, nLANGID
, 0, &maDec
);
232 hResult
= VarDecFromStr( (OLECHAR
*)pOUString
->getStr(), nLANGID
, 0, &maDec
);
234 bRet
= ( hResult
== S_OK
);
239 bool SbxDecimal::getChar( sal_Unicode
& rVal
)
241 bool bRet
= ( VarUI2FromDec( &maDec
, &rVal
) == S_OK
);
245 bool SbxDecimal::getShort( sal_Int16
& rVal
)
247 bool bRet
= ( VarI2FromDec( &maDec
, &rVal
) == S_OK
);
251 bool SbxDecimal::getLong( sal_Int32
& rVal
)
253 bool bRet
= ( VarI4FromDec( &maDec
, &rVal
) == S_OK
);
257 bool SbxDecimal::getUShort( sal_uInt16
& rVal
)
259 bool bRet
= ( VarUI2FromDec( &maDec
, &rVal
) == S_OK
);
263 bool SbxDecimal::getULong( sal_uInt32
& rVal
)
265 bool bRet
= ( VarUI4FromDec( &maDec
, &rVal
) == S_OK
);
269 bool SbxDecimal::getSingle( float& rVal
)
271 bool bRet
= ( VarR4FromDec( &maDec
, &rVal
) == S_OK
);
275 bool SbxDecimal::getDouble( double& rVal
)
277 bool bRet
= ( VarR8FromDec( &maDec
, &rVal
) == S_OK
);
284 bool SbxDecimal::operator -= ( const SbxDecimal
&r
)
290 bool SbxDecimal::operator += ( const SbxDecimal
&r
)
296 bool SbxDecimal::operator /= ( const SbxDecimal
&r
)
302 bool SbxDecimal::operator *= ( const SbxDecimal
&r
)
308 bool SbxDecimal::neg( void )
313 bool SbxDecimal::isZero( void )
318 SbxDecimal::CmpResult
compare( const SbxDecimal
&rLeft
, const SbxDecimal
&rRight
)
322 return (SbxDecimal::CmpResult
)0;
325 void SbxDecimal::setChar( sal_Unicode val
) { (void)val
; }
326 void SbxDecimal::setByte( sal_uInt8 val
) { (void)val
; }
327 void SbxDecimal::setShort( sal_Int16 val
) { (void)val
; }
328 void SbxDecimal::setLong( sal_Int32 val
) { (void)val
; }
329 void SbxDecimal::setUShort( sal_uInt16 val
) { (void)val
; }
330 void SbxDecimal::setULong( sal_uInt32 val
) { (void)val
; }
331 bool SbxDecimal::setSingle( float val
) { (void)val
; return false; }
332 bool SbxDecimal::setDouble( double val
) { (void)val
; return false; }
333 void SbxDecimal::setInt( int val
) { (void)val
; }
334 void SbxDecimal::setUInt( unsigned int val
) { (void)val
; }
335 bool SbxDecimal::setString( OUString
* pOUString
) { (void)pOUString
; return false; }
337 bool SbxDecimal::getChar( sal_Unicode
& rVal
) { (void)rVal
; return false; }
338 bool SbxDecimal::getShort( sal_Int16
& rVal
) { (void)rVal
; return false; }
339 bool SbxDecimal::getLong( sal_Int32
& rVal
) { (void)rVal
; return false; }
340 bool SbxDecimal::getUShort( sal_uInt16
& rVal
) { (void)rVal
; return false; }
341 bool SbxDecimal::getULong( sal_uInt32
& rVal
) { (void)rVal
; return false; }
342 bool SbxDecimal::getSingle( float& rVal
) { (void)rVal
; return false; }
343 bool SbxDecimal::getDouble( double& rVal
) { (void)rVal
; return false; }
347 bool SbxDecimal::getString( OUString
& rString
)
350 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
355 BSTR aBStr
= SysAllocString( sz
);
358 HRESULT hResult
= VarBstrFromDec( &maDec
, nLANGID
, 0, &aBStr
);
359 bRet
= ( hResult
== S_OK
);
363 sal_Unicode cDecimalSep
;
364 sal_Unicode cThousandSep
;
365 ImpGetIntntlSep( cDecimalSep
, cThousandSep
);
367 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
371 while( (c
= aBStr
[i
]) != 0 )
374 aBStr
[i
] = cDecimalSep
;
376 aBStr
[i
] = cThousandSep
;
380 rString
= reinterpret_cast<const sal_Unicode
*>(aBStr
);
383 SysFreeString( aBStr
);
392 SbxDecimal
* ImpCreateDecimal( SbxValues
* p
)
397 SbxDecimal
*& rpDecimal
= p
->pDecimal
;
398 if( rpDecimal
== NULL
)
400 rpDecimal
= new SbxDecimal();
406 SbxDecimal
* ImpGetDecimal( const SbxValues
* p
)
409 SbxDecimal
* pnDecRes
;
411 SbxDataType eType
= p
->eType
;
412 if( eType
== SbxDECIMAL
&& p
->pDecimal
)
414 pnDecRes
= new SbxDecimal( *p
->pDecimal
);
418 pnDecRes
= new SbxDecimal();
425 SbxBase::SetError( SbxERR_CONVERSION
);
427 pnDecRes
->setShort( 0 ); break;
429 pnDecRes
->setChar( p
->nChar
); break;
431 pnDecRes
->setByte( p
->nByte
); break;
434 pnDecRes
->setInt( p
->nInteger
); break;
437 pnDecRes
->setUShort( p
->nUShort
); break;
439 pnDecRes
->setLong( p
->nLong
); break;
441 pnDecRes
->setULong( p
->nULong
); break;
443 if( !pnDecRes
->setSingle( p
->nSingle
) )
444 SbxBase::SetError( SbxERR_OVERFLOW
);
448 if( !pnDecRes
->setDouble( ImpCurrencyToDouble( p
->nInt64
) ) )
449 SbxBase::SetError( SbxERR_OVERFLOW
);
454 if( !pnDecRes
->setDouble( (double)p
->nInt64
) )
455 SbxBase::SetError( SbxERR_OVERFLOW
);
460 if( !pnDecRes
->setDouble( (double)p
->uInt64
) )
461 SbxBase::SetError( SbxERR_OVERFLOW
);
467 double dVal
= p
->nDouble
;
468 if( !pnDecRes
->setDouble( dVal
) )
469 SbxBase::SetError( SbxERR_OVERFLOW
);
474 case SbxBYREF
| SbxSTRING
:
475 pnDecRes
->setString( p
->pOUString
); break;
478 SbxValue
* pVal
= PTR_CAST(SbxValue
,p
->pObj
);
480 pnDecRes
->setDecimal( pVal
->GetDecimal() );
483 SbxBase::SetError( SbxERR_NO_OBJECT
);
484 pnDecRes
->setShort( 0 );
489 case SbxBYREF
| SbxCHAR
:
490 pnDecRes
->setChar( *p
->pChar
); break;
491 case SbxBYREF
| SbxBYTE
:
492 pnDecRes
->setByte( *p
->pByte
); break;
493 case SbxBYREF
| SbxINTEGER
:
494 case SbxBYREF
| SbxBOOL
:
495 pnDecRes
->setInt( *p
->pInteger
); break;
496 case SbxBYREF
| SbxLONG
:
497 pnDecRes
->setLong( *p
->pLong
); break;
498 case SbxBYREF
| SbxULONG
:
499 pnDecRes
->setULong( *p
->pULong
); break;
500 case SbxBYREF
| SbxERROR
:
501 case SbxBYREF
| SbxUSHORT
:
502 pnDecRes
->setUShort( *p
->pUShort
); break;
504 // from here on had to be tested
505 case SbxBYREF
| SbxSINGLE
:
506 aTmp
.nSingle
= *p
->pSingle
; goto ref
;
507 case SbxBYREF
| SbxDATE
:
508 case SbxBYREF
| SbxDOUBLE
:
509 aTmp
.nDouble
= *p
->pDouble
; goto ref
;
510 case SbxBYREF
| SbxCURRENCY
:
511 case SbxBYREF
| SbxSALINT64
:
512 aTmp
.nInt64
= *p
->pnInt64
; goto ref
;
513 case SbxBYREF
| SbxSALUINT64
:
514 aTmp
.uInt64
= *p
->puInt64
; goto ref
;
516 aTmp
.eType
= SbxDataType( p
->eType
& 0x0FFF );
517 p
= &aTmp
; goto start
;
520 SbxBase::SetError( SbxERR_CONVERSION
); pnDecRes
->setShort( 0 );
525 void ImpPutDecimal( SbxValues
* p
, SbxDecimal
* pDec
)
534 // here had to be tested
536 aTmp
.pChar
= &p
->nChar
; goto direct
;
538 aTmp
.pByte
= &p
->nByte
; goto direct
;
540 aTmp
.pULong
= &p
->nULong
; goto direct
;
543 aTmp
.pUShort
= &p
->nUShort
; goto direct
;
546 aTmp
.pInteger
= &p
->nInteger
; goto direct
;
548 aTmp
.pLong
= &p
->nLong
; goto direct
;
551 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
553 aTmp
.puInt64
= &p
->uInt64
; goto direct
;
556 aTmp
.eType
= SbxDataType( p
->eType
| SbxBYREF
);
557 p
= &aTmp
; goto start
;
559 // from here on no longer
561 case SbxBYREF
| SbxDECIMAL
:
563 if( pDec
!= p
->pDecimal
)
565 releaseDecimalPtr( p
->pDecimal
);
575 pDec
->getSingle( f
);
583 pDec
->getDouble( d
);
590 case SbxBYREF
| SbxSTRING
:
592 p
->pOUString
= new OUString
;
593 pDec
->getString( *p
->pOUString
);
597 SbxValue
* pVal
= PTR_CAST(SbxValue
,p
->pObj
);
599 pVal
->PutDecimal( pDec
);
601 SbxBase::SetError( SbxERR_NO_OBJECT
);
605 case SbxBYREF
| SbxCHAR
:
606 if( !pDec
->getChar( *p
->pChar
) )
608 SbxBase::SetError( SbxERR_OVERFLOW
);
612 case SbxBYREF
| SbxBYTE
:
613 if( !pDec
->getChar( *p
->pChar
) )
615 SbxBase::SetError( SbxERR_OVERFLOW
);
619 case SbxBYREF
| SbxINTEGER
:
620 case SbxBYREF
| SbxBOOL
:
621 if( !pDec
->getShort( *p
->pInteger
) )
623 SbxBase::SetError( SbxERR_OVERFLOW
);
627 case SbxBYREF
| SbxERROR
:
628 case SbxBYREF
| SbxUSHORT
:
629 if( !pDec
->getUShort( *p
->pUShort
) )
631 SbxBase::SetError( SbxERR_OVERFLOW
);
635 case SbxBYREF
| SbxLONG
:
636 if( !pDec
->getLong( *p
->pLong
) )
638 SbxBase::SetError( SbxERR_OVERFLOW
);
642 case SbxBYREF
| SbxULONG
:
643 if( !pDec
->getULong( *p
->pULong
) )
645 SbxBase::SetError( SbxERR_OVERFLOW
);
649 case SbxBYREF
| SbxCURRENCY
:
652 if( !pDec
->getDouble( d
) )
653 SbxBase::SetError( SbxERR_OVERFLOW
);
654 *p
->pnInt64
= ImpDoubleToCurrency( d
);
657 case SbxBYREF
| SbxSALINT64
:
660 if( !pDec
->getDouble( d
) )
661 SbxBase::SetError( SbxERR_OVERFLOW
);
663 *p
->pnInt64
= ImpDoubleToSalInt64( d
);
666 case SbxBYREF
| SbxSALUINT64
:
669 if( !pDec
->getDouble( d
) )
670 SbxBase::SetError( SbxERR_OVERFLOW
);
672 *p
->puInt64
= ImpDoubleToSalUInt64( d
);
675 case SbxBYREF
| SbxSINGLE
:
676 if( !pDec
->getSingle( *p
->pSingle
) )
678 SbxBase::SetError( SbxERR_OVERFLOW
);
682 case SbxBYREF
| SbxDATE
:
683 case SbxBYREF
| SbxDOUBLE
:
684 if( !pDec
->getDouble( *p
->pDouble
) )
686 SbxBase::SetError( SbxERR_OVERFLOW
);
691 SbxBase::SetError( SbxERR_CONVERSION
);
695 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */