1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sbxdec.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
33 #include <tools/errcode.hxx>
35 #include <basic/sbx.hxx>
36 #include "sbxconv.hxx"
38 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
41 // int GnDecCounter = 0;
43 // Implementation SbxDecimal
44 SbxDecimal::SbxDecimal( void )
51 SbxDecimal::SbxDecimal( const SbxDecimal
& rDec
)
62 SbxDecimal::SbxDecimal
63 ( const com::sun::star::bridge::oleautomation::Decimal
& rAutomationDec
)
66 maDec
.scale
= rAutomationDec
.Scale
;
67 maDec
.sign
= rAutomationDec
.Sign
;
68 maDec
.Lo32
= rAutomationDec
.LowValue
;
69 maDec
.Mid32
= rAutomationDec
.MiddleValue
;
70 maDec
.Hi32
= rAutomationDec
.HighValue
;
78 void SbxDecimal::fillAutomationDecimal
79 ( com::sun::star::bridge::oleautomation::Decimal
& rAutomationDec
)
82 rAutomationDec
.Scale
= maDec
.scale
;
83 rAutomationDec
.Sign
= maDec
.sign
;
84 rAutomationDec
.LowValue
= maDec
.Lo32
;
85 rAutomationDec
.MiddleValue
= maDec
.Mid32
;
86 rAutomationDec
.HighValue
= maDec
.Hi32
;
92 SbxDecimal::~SbxDecimal()
97 void releaseDecimalPtr( SbxDecimal
*& rpDecimal
)
101 rpDecimal
->mnRefCount
--;
102 if( rpDecimal
->mnRefCount
== 0 )
112 bool SbxDecimal::operator -= ( const SbxDecimal
&r
)
114 HRESULT hResult
= VarDecSub( &maDec
, (LPDECIMAL
)&r
.maDec
, &maDec
);
115 bool bRet
= ( hResult
== S_OK
);
119 bool SbxDecimal::operator += ( const SbxDecimal
&r
)
121 HRESULT hResult
= VarDecAdd( &maDec
, (LPDECIMAL
)&r
.maDec
, &maDec
);
122 bool bRet
= ( hResult
== S_OK
);
126 bool SbxDecimal::operator /= ( const SbxDecimal
&r
)
128 HRESULT hResult
= VarDecDiv( &maDec
, (LPDECIMAL
)&r
.maDec
, &maDec
);
129 bool bRet
= ( hResult
== S_OK
);
133 bool SbxDecimal::operator *= ( const SbxDecimal
&r
)
135 HRESULT hResult
= VarDecMul( &maDec
, (LPDECIMAL
)&r
.maDec
, &maDec
);
136 bool bRet
= ( hResult
== S_OK
);
140 bool SbxDecimal::neg( void )
142 HRESULT hResult
= VarDecNeg( &maDec
, &maDec
);
143 bool bRet
= ( hResult
== S_OK
);
147 bool SbxDecimal::isZero( void )
150 aZeroDec
.setLong( 0 );
151 bool bZero
= ( EQ
== compare( *this, aZeroDec
) );
155 SbxDecimal::CmpResult
compare( const SbxDecimal
&rLeft
, const SbxDecimal
&rRight
)
157 HRESULT hResult
= VarDecCmp( (LPDECIMAL
)&rLeft
.maDec
, (LPDECIMAL
)&rRight
.maDec
);
158 SbxDecimal::CmpResult eRes
= (SbxDecimal::CmpResult
)hResult
;
162 void SbxDecimal::setChar( sal_Unicode val
)
164 VarDecFromUI2( (USHORT
)val
, &maDec
);
167 void SbxDecimal::setByte( BYTE val
)
169 VarDecFromUI1( (BYTE
)val
, &maDec
);
172 void SbxDecimal::setShort( INT16 val
)
174 VarDecFromI2( (short)val
, &maDec
);
177 void SbxDecimal::setLong( INT32 val
)
179 VarDecFromI4( (long)val
, &maDec
);
182 void SbxDecimal::setUShort( UINT16 val
)
184 VarDecFromUI2( (USHORT
)val
, &maDec
);
187 void SbxDecimal::setULong( UINT32 val
)
189 VarDecFromUI4( (ULONG
)val
, &maDec
);
192 bool SbxDecimal::setSingle( float val
)
194 bool bRet
= ( VarDecFromR4( val
, &maDec
) == S_OK
);
198 bool SbxDecimal::setDouble( double val
)
200 bool bRet
= ( VarDecFromR8( val
, &maDec
) == S_OK
);
204 void SbxDecimal::setInt( int val
)
206 setLong( (INT32
)val
);
209 void SbxDecimal::setUInt( unsigned int val
)
211 setULong( (UINT32
)val
);
215 void ImpGetIntntlSep( sal_Unicode
& rcDecimalSep
, sal_Unicode
& rcThousandSep
);
217 bool SbxDecimal::setString( String
* pString
)
219 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
222 sal_Unicode cDecimalSep
;
223 sal_Unicode cThousandSep
;
224 ImpGetIntntlSep( cDecimalSep
, cThousandSep
);
228 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
230 int nLen
= pString
->Len();
231 sal_Unicode
* pBuffer
= new sal_Unicode
[nLen
+ 1];
234 const sal_Unicode
* pSrc
= pString
->GetBuffer();
236 for( i
= 0 ; i
< nLen
; ++i
)
237 pBuffer
[i
] = pSrc
[i
];
241 while( (c
= pBuffer
[i
]) != 0 )
243 if( c
== cDecimalSep
)
245 else if( c
== cThousandSep
)
249 hResult
= VarDecFromStr( (OLECHAR
*)pBuffer
, nLANGID
, 0, &maDec
);
254 hResult
= VarDecFromStr( (OLECHAR
*)pString
->GetBuffer(), nLANGID
, 0, &maDec
);
256 bRet
= ( hResult
== S_OK
);
261 bool SbxDecimal::getChar( sal_Unicode
& rVal
)
263 bool bRet
= ( VarUI2FromDec( &maDec
, &rVal
) == S_OK
);
267 bool SbxDecimal::getByte( BYTE
& rVal
)
269 bool bRet
= ( VarUI1FromDec( &maDec
, &rVal
) == S_OK
);
273 bool SbxDecimal::getShort( INT16
& rVal
)
275 bool bRet
= ( VarI2FromDec( &maDec
, &rVal
) == S_OK
);
279 bool SbxDecimal::getLong( INT32
& rVal
)
281 bool bRet
= ( VarI4FromDec( &maDec
, &rVal
) == S_OK
);
285 bool SbxDecimal::getUShort( UINT16
& rVal
)
287 bool bRet
= ( VarUI2FromDec( &maDec
, &rVal
) == S_OK
);
291 bool SbxDecimal::getULong( UINT32
& rVal
)
293 bool bRet
= ( VarUI4FromDec( &maDec
, &rVal
) == S_OK
);
297 bool SbxDecimal::getSingle( float& rVal
)
299 bool bRet
= ( VarR4FromDec( &maDec
, &rVal
) == S_OK
);
303 bool SbxDecimal::getDouble( double& rVal
)
305 bool bRet
= ( VarR8FromDec( &maDec
, &rVal
) == S_OK
);
309 bool SbxDecimal::getInt( int& rVal
)
312 bool bRet
= getLong( TmpVal
);
317 bool SbxDecimal::getUInt( unsigned int& rVal
)
320 bool bRet
= getULong( TmpVal
);
328 bool SbxDecimal::operator -= ( const SbxDecimal
&r
)
334 bool SbxDecimal::operator += ( const SbxDecimal
&r
)
340 bool SbxDecimal::operator /= ( const SbxDecimal
&r
)
346 bool SbxDecimal::operator *= ( const SbxDecimal
&r
)
352 bool SbxDecimal::neg( void )
357 bool SbxDecimal::isZero( void )
362 SbxDecimal::CmpResult
compare( const SbxDecimal
&rLeft
, const SbxDecimal
&rRight
)
366 return (SbxDecimal::CmpResult
)0;
369 void SbxDecimal::setChar( sal_Unicode val
) { (void)val
; }
370 void SbxDecimal::setByte( BYTE val
) { (void)val
; }
371 void SbxDecimal::setShort( INT16 val
) { (void)val
; }
372 void SbxDecimal::setLong( INT32 val
) { (void)val
; }
373 void SbxDecimal::setUShort( UINT16 val
) { (void)val
; }
374 void SbxDecimal::setULong( UINT32 val
) { (void)val
; }
375 bool SbxDecimal::setSingle( float val
) { (void)val
; return false; }
376 bool SbxDecimal::setDouble( double val
) { (void)val
; return false; }
377 void SbxDecimal::setInt( int val
) { (void)val
; }
378 void SbxDecimal::setUInt( unsigned int val
) { (void)val
; }
379 bool SbxDecimal::setString( String
* pString
) { (void)pString
; return false; }
381 bool SbxDecimal::getChar( sal_Unicode
& rVal
) { (void)rVal
; return false; }
382 bool SbxDecimal::getByte( BYTE
& rVal
) { (void)rVal
; return false; }
383 bool SbxDecimal::getShort( INT16
& rVal
) { (void)rVal
; return false; }
384 bool SbxDecimal::getLong( INT32
& rVal
) { (void)rVal
; return false; }
385 bool SbxDecimal::getUShort( UINT16
& rVal
) { (void)rVal
; return false; }
386 bool SbxDecimal::getULong( UINT32
& rVal
) { (void)rVal
; return false; }
387 bool SbxDecimal::getSingle( float& rVal
) { (void)rVal
; return false; }
388 bool SbxDecimal::getDouble( double& rVal
) { (void)rVal
; return false; }
389 bool SbxDecimal::getInt( int& rVal
) { (void)rVal
; return false; }
390 bool SbxDecimal::getUInt( unsigned int& rVal
) { (void)rVal
; return false; }
394 bool SbxDecimal::getString( String
& rString
)
397 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
402 BSTR aBStr
= SysAllocString( sz
);
405 HRESULT hResult
= VarBstrFromDec( &maDec
, nLANGID
, 0, &aBStr
);
406 bRet
= ( hResult
== S_OK
);
410 sal_Unicode cDecimalSep
;
411 sal_Unicode cThousandSep
;
412 ImpGetIntntlSep( cDecimalSep
, cThousandSep
);
414 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
418 while( (c
= aBStr
[i
]) != 0 )
421 aBStr
[i
] = cDecimalSep
;
423 aBStr
[i
] = cThousandSep
;
427 rString
= reinterpret_cast<const sal_Unicode
*>(aBStr
);
430 SysFreeString( aBStr
);
439 SbxDecimal
* ImpCreateDecimal( SbxValues
* p
)
445 SbxDecimal
*& rpDecimal
= p
->pDecimal
;
446 if( rpDecimal
== NULL
)
448 rpDecimal
= new SbxDecimal();
458 SbxDecimal
* ImpGetDecimal( const SbxValues
* p
)
462 SbxDecimal
* pnDecRes
;
464 SbxDataType eType
= p
->eType
;
465 if( eType
== SbxDECIMAL
&& p
->pDecimal
)
467 pnDecRes
= new SbxDecimal( *p
->pDecimal
);
471 pnDecRes
= new SbxDecimal();
478 SbxBase::SetError( SbxERR_CONVERSION
);
480 pnDecRes
->setShort( 0 ); break;
482 pnDecRes
->setChar( p
->nChar
); break;
484 pnDecRes
->setByte( p
->nByte
); break;
487 pnDecRes
->setInt( p
->nInteger
); break;
490 pnDecRes
->setUShort( p
->nUShort
); break;
492 pnDecRes
->setLong( p
->nLong
); break;
494 pnDecRes
->setULong( p
->nULong
); break;
496 if( !pnDecRes
->setSingle( p
->nSingle
) )
497 SbxBase::SetError( SbxERR_OVERFLOW
);
501 double d
= (double)p
->nInt64
;
502 pnDecRes
->setDouble( d
);
507 double d
= ImpSalUInt64ToDouble( p
->uInt64
);
508 pnDecRes
->setDouble( d
);
518 if( p
->eType
== SbxCURRENCY
)
519 dVal
= ImpCurrencyToDouble( p
->nLong64
);
520 else if( p
->eType
== SbxLONG64
)
521 dVal
= ImpINT64ToDouble( p
->nLong64
);
522 else if( p
->eType
== SbxULONG64
)
523 dVal
= ImpUINT64ToDouble( p
->nULong64
);
527 if( !pnDecRes
->setDouble( dVal
) )
528 SbxBase::SetError( SbxERR_OVERFLOW
);
533 case SbxBYREF
| SbxSTRING
:
534 pnDecRes
->setString( p
->pString
); break;
537 SbxValue
* pVal
= PTR_CAST(SbxValue
,p
->pObj
);
539 pnDecRes
->setDecimal( pVal
->GetDecimal() );
542 SbxBase::SetError( SbxERR_NO_OBJECT
);
543 pnDecRes
->setShort( 0 );
548 case SbxBYREF
| SbxCHAR
:
549 pnDecRes
->setChar( *p
->pChar
); break;
550 case SbxBYREF
| SbxBYTE
:
551 pnDecRes
->setByte( *p
->pByte
); break;
552 case SbxBYREF
| SbxINTEGER
:
553 case SbxBYREF
| SbxBOOL
:
554 pnDecRes
->setInt( *p
->pInteger
); break;
555 case SbxBYREF
| SbxLONG
:
556 pnDecRes
->setLong( *p
->pLong
); break;
557 case SbxBYREF
| SbxULONG
:
558 pnDecRes
->setULong( *p
->pULong
); break;
559 case SbxBYREF
| SbxERROR
:
560 case SbxBYREF
| SbxUSHORT
:
561 pnDecRes
->setUShort( *p
->pUShort
); break;
563 // ab hier muss getestet werden
564 case SbxBYREF
| SbxSINGLE
:
565 aTmp
.nSingle
= *p
->pSingle
; goto ref
;
566 case SbxBYREF
| SbxDATE
:
567 case SbxBYREF
| SbxDOUBLE
:
568 aTmp
.nDouble
= *p
->pDouble
; goto ref
;
569 case SbxBYREF
| SbxULONG64
:
570 aTmp
.nULong64
= *p
->pULong64
; goto ref
;
571 case SbxBYREF
| SbxLONG64
:
572 case SbxBYREF
| SbxCURRENCY
:
573 aTmp
.nLong64
= *p
->pLong64
; goto ref
;
574 case SbxBYREF
| SbxSALINT64
:
575 aTmp
.nInt64
= *p
->pnInt64
; goto ref
;
576 case SbxBYREF
| SbxSALUINT64
:
577 aTmp
.uInt64
= *p
->puInt64
; goto ref
;
579 aTmp
.eType
= SbxDataType( p
->eType
& 0x0FFF );
580 p
= &aTmp
; goto start
;
583 SbxBase::SetError( SbxERR_CONVERSION
); pnDecRes
->setShort( 0 );
593 void ImpPutDecimal( SbxValues
* p
, SbxDecimal
* pDec
)
603 // hier muss getestet werden
605 aTmp
.pChar
= &p
->nChar
; goto direct
;
607 aTmp
.pByte
= &p
->nByte
; goto direct
;
609 aTmp
.pULong
= &p
->nULong
; goto direct
;
612 aTmp
.pUShort
= &p
->nUShort
; goto direct
;
614 aTmp
.puInt64
= &p
->uInt64
; goto direct
;
617 aTmp
.pInteger
= &p
->nInteger
; goto direct
;
619 aTmp
.pLong
= &p
->nLong
; goto direct
;
621 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
623 aTmp
.pLong64
= &p
->nLong64
; goto direct
;
625 aTmp
.eType
= SbxDataType( p
->eType
| SbxBYREF
);
626 p
= &aTmp
; goto start
;
628 // ab hier nicht mehr
630 case SbxBYREF
| SbxDECIMAL
:
632 if( pDec
!= p
->pDecimal
)
634 releaseDecimalPtr( p
->pDecimal
);
636 // p->pDecimal->ReleaseRef();
646 pDec
->getSingle( f
);
654 pDec
->getDouble( d
);
661 pDec
->getDouble( d
);
662 p
->nULong64
= ImpDoubleToUINT64( d
);
668 pDec
->getDouble( d
);
669 p
->nLong64
= ImpDoubleToINT64( d
);
675 case SbxBYREF
| SbxSTRING
:
677 p
->pString
= new XubString
;
678 // ImpCvtNum( (double) n, 0, *p->pString );
679 pDec
->getString( *p
->pString
);
683 SbxValue
* pVal
= PTR_CAST(SbxValue
,p
->pObj
);
685 pVal
->PutDecimal( pDec
);
687 SbxBase::SetError( SbxERR_NO_OBJECT
);
691 case SbxBYREF
| SbxCHAR
:
692 if( !pDec
->getChar( *p
->pChar
) )
694 SbxBase::SetError( SbxERR_OVERFLOW
);
698 case SbxBYREF
| SbxBYTE
:
699 if( !pDec
->getChar( *p
->pChar
) )
701 SbxBase::SetError( SbxERR_OVERFLOW
);
705 case SbxBYREF
| SbxINTEGER
:
706 case SbxBYREF
| SbxBOOL
:
707 if( !pDec
->getShort( *p
->pInteger
) )
709 SbxBase::SetError( SbxERR_OVERFLOW
);
713 // *p->pInteger = n; break;
714 case SbxBYREF
| SbxERROR
:
715 case SbxBYREF
| SbxUSHORT
:
716 if( !pDec
->getUShort( *p
->pUShort
) )
718 SbxBase::SetError( SbxERR_OVERFLOW
);
722 case SbxBYREF
| SbxLONG
:
723 if( !pDec
->getLong( *p
->pLong
) )
725 SbxBase::SetError( SbxERR_OVERFLOW
);
729 case SbxBYREF
| SbxULONG
:
730 if( !pDec
->getULong( *p
->pULong
) )
732 SbxBase::SetError( SbxERR_OVERFLOW
);
736 case SbxBYREF
| SbxSALINT64
:
739 if( !pDec
->getDouble( d
) )
740 SbxBase::SetError( SbxERR_OVERFLOW
);
742 *p
->pnInt64
= ImpDoubleToSalInt64( d
);
745 case SbxBYREF
| SbxSALUINT64
:
748 if( !pDec
->getDouble( d
) )
749 SbxBase::SetError( SbxERR_OVERFLOW
);
751 *p
->puInt64
= ImpDoubleToSalUInt64( d
);
754 case SbxBYREF
| SbxSINGLE
:
755 if( !pDec
->getSingle( *p
->pSingle
) )
757 SbxBase::SetError( SbxERR_OVERFLOW
);
761 // *p->pSingle = (float) n; break;
762 case SbxBYREF
| SbxDATE
:
763 case SbxBYREF
| SbxDOUBLE
:
764 if( !pDec
->getDouble( *p
->pDouble
) )
766 SbxBase::SetError( SbxERR_OVERFLOW
);
770 case SbxBYREF
| SbxULONG64
:
773 pDec
->getDouble( d
);
774 *p
->pULong64
= ImpDoubleToUINT64( d
);
777 case SbxBYREF
| SbxLONG64
:
780 pDec
->getDouble( d
);
781 *p
->pLong64
= ImpDoubleToINT64( d
);
784 case SbxBYREF
| SbxCURRENCY
:
787 pDec
->getDouble( d
);
788 *p
->pLong64
= ImpDoubleToCurrency( d
);
793 SbxBase::SetError( SbxERR_CONVERSION
);