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>
26 #include <boost/scoped_array.hpp>
28 // Implementation SbxDecimal
29 SbxDecimal::SbxDecimal()
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()
123 HRESULT hResult
= VarDecNeg( &maDec
, &maDec
);
124 bool bRet
= ( hResult
== S_OK
);
128 bool SbxDecimal::isZero()
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( static_cast<ULONG
>(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
)
199 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
202 sal_Unicode cDecimalSep
;
203 sal_Unicode cThousandSep
;
204 ImpGetIntntlSep( cDecimalSep
, cThousandSep
);
208 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
210 int nLen
= pOUString
->getLength();
211 boost::scoped_array
<sal_Unicode
> pBuffer(new sal_Unicode
[nLen
+ 1]);
214 const sal_Unicode
* pSrc
= pOUString
->getStr();
216 for( i
= 0 ; i
< nLen
; ++i
)
217 pBuffer
[i
] = pSrc
[i
];
221 while( (c
= pBuffer
[i
]) != 0 )
223 if( c
== cDecimalSep
)
225 else if( c
== cThousandSep
)
229 hResult
= VarDecFromStr( (OLECHAR
*)pBuffer
.get(), nLANGID
, 0, &maDec
);
233 hResult
= VarDecFromStr( (OLECHAR
*)pOUString
->getStr(), nLANGID
, 0, &maDec
);
235 bRet
= ( hResult
== S_OK
);
240 bool SbxDecimal::getChar( sal_Unicode
& rVal
)
242 bool bRet
= ( VarUI2FromDec( &maDec
, &rVal
) == 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
&r
)
291 bool SbxDecimal::operator += ( const SbxDecimal
&r
)
297 bool SbxDecimal::operator /= ( const SbxDecimal
&r
)
303 bool SbxDecimal::operator *= ( const SbxDecimal
&r
)
309 bool SbxDecimal::neg()
314 bool SbxDecimal::isZero()
319 SbxDecimal::CmpResult
compare( const SbxDecimal
&rLeft
, const SbxDecimal
&rRight
)
323 return (SbxDecimal::CmpResult
)0;
326 void SbxDecimal::setChar( sal_Unicode val
) { (void)val
; }
327 void SbxDecimal::setByte( sal_uInt8 val
) { (void)val
; }
328 void SbxDecimal::setShort( sal_Int16 val
) { (void)val
; }
329 void SbxDecimal::setLong( sal_Int32 val
) { (void)val
; }
330 void SbxDecimal::setUShort( sal_uInt16 val
) { (void)val
; }
331 void SbxDecimal::setULong( sal_uInt32 val
) { (void)val
; }
332 bool SbxDecimal::setSingle( float val
) { (void)val
; return false; }
333 bool SbxDecimal::setDouble( double val
) { (void)val
; return false; }
334 void SbxDecimal::setInt( int val
) { (void)val
; }
335 void SbxDecimal::setUInt( unsigned int val
) { (void)val
; }
336 bool SbxDecimal::setString( OUString
* pOUString
) { (void)pOUString
; return false; }
338 bool SbxDecimal::getChar( sal_Unicode
& rVal
) { (void)rVal
; return false; }
339 bool SbxDecimal::getShort( sal_Int16
& rVal
) { (void)rVal
; return false; }
340 bool SbxDecimal::getLong( sal_Int32
& rVal
) { (void)rVal
; return false; }
341 bool SbxDecimal::getUShort( sal_uInt16
& rVal
) { (void)rVal
; return false; }
342 bool SbxDecimal::getULong( sal_uInt32
& rVal
) { (void)rVal
; return false; }
343 bool SbxDecimal::getSingle( float& rVal
) { (void)rVal
; return false; }
344 bool SbxDecimal::getDouble( double& rVal
) { (void)rVal
; return false; }
348 bool SbxDecimal::getString( OUString
& rString
)
351 static LCID nLANGID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
356 BSTR aBStr
= SysAllocString( sz
);
359 HRESULT hResult
= VarBstrFromDec( &maDec
, nLANGID
, 0, &aBStr
);
360 bRet
= ( hResult
== S_OK
);
364 sal_Unicode cDecimalSep
;
365 sal_Unicode cThousandSep
;
366 ImpGetIntntlSep( cDecimalSep
, cThousandSep
);
368 if( cDecimalSep
!= '.' || cThousandSep
!= ',' )
372 while( (c
= aBStr
[i
]) != 0 )
375 aBStr
[i
] = cDecimalSep
;
377 aBStr
[i
] = cThousandSep
;
381 rString
= reinterpret_cast<const sal_Unicode
*>(aBStr
);
384 SysFreeString( aBStr
);
393 SbxDecimal
* ImpCreateDecimal( SbxValues
* p
)
398 SbxDecimal
*& rpDecimal
= p
->pDecimal
;
399 if( rpDecimal
== NULL
)
401 rpDecimal
= new SbxDecimal();
407 SbxDecimal
* ImpGetDecimal( const SbxValues
* p
)
410 SbxDecimal
* pnDecRes
;
412 SbxDataType eType
= p
->eType
;
413 if( eType
== SbxDECIMAL
&& p
->pDecimal
)
415 pnDecRes
= new SbxDecimal( *p
->pDecimal
);
419 pnDecRes
= new SbxDecimal();
426 SbxBase::SetError( SbxERR_CONVERSION
);
428 pnDecRes
->setShort( 0 ); break;
430 pnDecRes
->setChar( p
->nChar
); break;
432 pnDecRes
->setByte( p
->nByte
); break;
435 pnDecRes
->setInt( p
->nInteger
); break;
438 pnDecRes
->setUShort( p
->nUShort
); break;
440 pnDecRes
->setLong( p
->nLong
); break;
442 pnDecRes
->setULong( p
->nULong
); break;
444 if( !pnDecRes
->setSingle( p
->nSingle
) )
445 SbxBase::SetError( SbxERR_OVERFLOW
);
449 if( !pnDecRes
->setDouble( ImpCurrencyToDouble( p
->nInt64
) ) )
450 SbxBase::SetError( SbxERR_OVERFLOW
);
455 if( !pnDecRes
->setDouble( (double)p
->nInt64
) )
456 SbxBase::SetError( SbxERR_OVERFLOW
);
461 if( !pnDecRes
->setDouble( (double)p
->uInt64
) )
462 SbxBase::SetError( SbxERR_OVERFLOW
);
468 double dVal
= p
->nDouble
;
469 if( !pnDecRes
->setDouble( dVal
) )
470 SbxBase::SetError( SbxERR_OVERFLOW
);
475 case SbxBYREF
| SbxSTRING
:
477 pnDecRes
->setString( p
->pOUString
);
481 SbxValue
* pVal
= PTR_CAST(SbxValue
,p
->pObj
);
483 pnDecRes
->setDecimal( pVal
->GetDecimal() );
486 SbxBase::SetError( SbxERR_NO_OBJECT
);
487 pnDecRes
->setShort( 0 );
492 case SbxBYREF
| SbxCHAR
:
493 pnDecRes
->setChar( *p
->pChar
); break;
494 case SbxBYREF
| SbxBYTE
:
495 pnDecRes
->setByte( *p
->pByte
); break;
496 case SbxBYREF
| SbxINTEGER
:
497 case SbxBYREF
| SbxBOOL
:
498 pnDecRes
->setInt( *p
->pInteger
); break;
499 case SbxBYREF
| SbxLONG
:
500 pnDecRes
->setLong( *p
->pLong
); break;
501 case SbxBYREF
| SbxULONG
:
502 pnDecRes
->setULong( *p
->pULong
); break;
503 case SbxBYREF
| SbxERROR
:
504 case SbxBYREF
| SbxUSHORT
:
505 pnDecRes
->setUShort( *p
->pUShort
); break;
507 // from here on had to be tested
508 case SbxBYREF
| SbxSINGLE
:
509 aTmp
.nSingle
= *p
->pSingle
; goto ref
;
510 case SbxBYREF
| SbxDATE
:
511 case SbxBYREF
| SbxDOUBLE
:
512 aTmp
.nDouble
= *p
->pDouble
; goto ref
;
513 case SbxBYREF
| SbxCURRENCY
:
514 case SbxBYREF
| SbxSALINT64
:
515 aTmp
.nInt64
= *p
->pnInt64
; goto ref
;
516 case SbxBYREF
| SbxSALUINT64
:
517 aTmp
.uInt64
= *p
->puInt64
; goto ref
;
519 aTmp
.eType
= SbxDataType( p
->eType
& 0x0FFF );
520 p
= &aTmp
; goto start
;
523 SbxBase::SetError( SbxERR_CONVERSION
); pnDecRes
->setShort( 0 );
528 void ImpPutDecimal( SbxValues
* p
, SbxDecimal
* pDec
)
537 // here had to be tested
539 aTmp
.pChar
= &p
->nChar
; goto direct
;
541 aTmp
.pByte
= &p
->nByte
; goto direct
;
543 aTmp
.pULong
= &p
->nULong
; goto direct
;
546 aTmp
.pUShort
= &p
->nUShort
; goto direct
;
549 aTmp
.pInteger
= &p
->nInteger
; goto direct
;
551 aTmp
.pLong
= &p
->nLong
; goto direct
;
554 aTmp
.pnInt64
= &p
->nInt64
; goto direct
;
556 aTmp
.puInt64
= &p
->uInt64
; goto direct
;
559 aTmp
.eType
= SbxDataType( p
->eType
| SbxBYREF
);
560 p
= &aTmp
; goto start
;
562 // from here on no longer
564 case SbxBYREF
| SbxDECIMAL
:
566 if( pDec
!= p
->pDecimal
)
568 releaseDecimalPtr( p
->pDecimal
);
578 pDec
->getSingle( f
);
586 pDec
->getDouble( d
);
593 case SbxBYREF
| SbxSTRING
:
595 p
->pOUString
= new OUString
;
596 pDec
->getString( *p
->pOUString
);
600 SbxValue
* pVal
= PTR_CAST(SbxValue
,p
->pObj
);
602 pVal
->PutDecimal( pDec
);
604 SbxBase::SetError( SbxERR_NO_OBJECT
);
608 case SbxBYREF
| SbxCHAR
:
609 if( !pDec
->getChar( *p
->pChar
) )
611 SbxBase::SetError( SbxERR_OVERFLOW
);
615 case SbxBYREF
| SbxBYTE
:
616 if( !pDec
->getChar( *p
->pChar
) )
618 SbxBase::SetError( SbxERR_OVERFLOW
);
622 case SbxBYREF
| SbxINTEGER
:
623 case SbxBYREF
| SbxBOOL
:
624 if( !pDec
->getShort( *p
->pInteger
) )
626 SbxBase::SetError( SbxERR_OVERFLOW
);
630 case SbxBYREF
| SbxERROR
:
631 case SbxBYREF
| SbxUSHORT
:
632 if( !pDec
->getUShort( *p
->pUShort
) )
634 SbxBase::SetError( SbxERR_OVERFLOW
);
638 case SbxBYREF
| SbxLONG
:
639 if( !pDec
->getLong( *p
->pLong
) )
641 SbxBase::SetError( SbxERR_OVERFLOW
);
645 case SbxBYREF
| SbxULONG
:
646 if( !pDec
->getULong( *p
->pULong
) )
648 SbxBase::SetError( SbxERR_OVERFLOW
);
652 case SbxBYREF
| SbxCURRENCY
:
655 if( !pDec
->getDouble( d
) )
656 SbxBase::SetError( SbxERR_OVERFLOW
);
657 *p
->pnInt64
= ImpDoubleToCurrency( d
);
660 case SbxBYREF
| SbxSALINT64
:
663 if( !pDec
->getDouble( d
) )
664 SbxBase::SetError( SbxERR_OVERFLOW
);
666 *p
->pnInt64
= ImpDoubleToSalInt64( d
);
669 case SbxBYREF
| SbxSALUINT64
:
672 if( !pDec
->getDouble( d
) )
673 SbxBase::SetError( SbxERR_OVERFLOW
);
675 *p
->puInt64
= ImpDoubleToSalUInt64( d
);
678 case SbxBYREF
| SbxSINGLE
:
679 if( !pDec
->getSingle( *p
->pSingle
) )
681 SbxBase::SetError( SbxERR_OVERFLOW
);
685 case SbxBYREF
| SbxDATE
:
686 case SbxBYREF
| SbxDOUBLE
:
687 if( !pDec
->getDouble( *p
->pDouble
) )
689 SbxBase::SetError( SbxERR_OVERFLOW
);
694 SbxBase::SetError( SbxERR_CONVERSION
);
698 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */