bump product version to 5.0.4.1
[LibreOffice.git] / basic / source / sbx / sbxdec.cxx
blob267bee9a3c0aa651ab0500856fb2cad5f771e105
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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()
31 setInt( 0 );
32 mnRefCount = 0;
35 SbxDecimal::SbxDecimal( const SbxDecimal& rDec )
37 #ifdef WIN32
38 maDec = rDec.maDec;
39 #else
40 (void)rDec;
41 #endif
42 mnRefCount = 0;
45 SbxDecimal::SbxDecimal
46 ( const com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
48 #ifdef WIN32
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;
54 #else
55 (void)rAutomationDec;
56 #endif
57 mnRefCount = 0;
60 void SbxDecimal::fillAutomationDecimal
61 ( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
63 #ifdef WIN32
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;
69 #else
70 (void)rAutomationDec;
71 #endif
74 SbxDecimal::~SbxDecimal()
78 void releaseDecimalPtr( SbxDecimal*& rpDecimal )
80 if( rpDecimal )
82 rpDecimal->mnRefCount--;
83 if( rpDecimal->mnRefCount == 0 )
85 delete rpDecimal;
86 rpDecimal = NULL;
91 #ifdef WIN32
93 bool SbxDecimal::operator -= ( const SbxDecimal &r )
95 HRESULT hResult = VarDecSub( &maDec, (LPDECIMAL)&r.maDec, &maDec );
96 bool bRet = ( hResult == S_OK );
97 return bRet;
100 bool SbxDecimal::operator += ( const SbxDecimal &r )
102 HRESULT hResult = VarDecAdd( &maDec, (LPDECIMAL)&r.maDec, &maDec );
103 bool bRet = ( hResult == S_OK );
104 return bRet;
107 bool SbxDecimal::operator /= ( const SbxDecimal &r )
109 HRESULT hResult = VarDecDiv( &maDec, (LPDECIMAL)&r.maDec, &maDec );
110 bool bRet = ( hResult == S_OK );
111 return bRet;
114 bool SbxDecimal::operator *= ( const SbxDecimal &r )
116 HRESULT hResult = VarDecMul( &maDec, (LPDECIMAL)&r.maDec, &maDec );
117 bool bRet = ( hResult == S_OK );
118 return bRet;
121 bool SbxDecimal::neg()
123 HRESULT hResult = VarDecNeg( &maDec, &maDec );
124 bool bRet = ( hResult == S_OK );
125 return bRet;
128 bool SbxDecimal::isZero()
130 SbxDecimal aZeroDec;
131 aZeroDec.setLong( 0 );
132 bool bZero = ( EQ == compare( *this, aZeroDec ) );
133 return bZero;
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;
140 return eRes;
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 );
176 return bRet;
179 bool SbxDecimal::setDouble( double val )
181 bool bRet = ( VarDecFromR8( val, &maDec ) == S_OK );
182 return bRet;
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 assert(pOUString);
199 static LCID nLANGID = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
201 // Convert delimiter
202 sal_Unicode cDecimalSep;
203 sal_Unicode cThousandSep;
204 ImpGetIntntlSep( cDecimalSep, cThousandSep );
206 bool bRet = false;
207 HRESULT hResult;
208 if( cDecimalSep != '.' || cThousandSep != ',' )
210 int nLen = pOUString->getLength();
211 boost::scoped_array<sal_Unicode> pBuffer(new sal_Unicode[nLen + 1]);
212 pBuffer[nLen] = 0;
214 const sal_Unicode* pSrc = pOUString->getStr();
215 int i;
216 for( i = 0 ; i < nLen ; ++i )
217 pBuffer[i] = pSrc[i];
219 sal_Unicode c;
220 i = 0;
221 while( (c = pBuffer[i]) != 0 )
223 if( c == cDecimalSep )
224 pBuffer[i] = '.';
225 else if( c == cThousandSep )
226 pBuffer[i] = ',';
227 i++;
229 hResult = VarDecFromStr( (OLECHAR*)pBuffer.get(), nLANGID, 0, &maDec );
231 else
233 hResult = VarDecFromStr( (OLECHAR*)pOUString->getStr(), nLANGID, 0, &maDec );
235 bRet = ( hResult == S_OK );
236 return bRet;
240 bool SbxDecimal::getChar( sal_Unicode& rVal )
242 bool bRet = ( VarUI2FromDec( &maDec, &rVal ) == S_OK );
243 return bRet;
246 bool SbxDecimal::getShort( sal_Int16& rVal )
248 bool bRet = ( VarI2FromDec( &maDec, &rVal ) == S_OK );
249 return bRet;
252 bool SbxDecimal::getLong( sal_Int32& rVal )
254 bool bRet = ( VarI4FromDec( &maDec, &rVal ) == S_OK );
255 return bRet;
258 bool SbxDecimal::getUShort( sal_uInt16& rVal )
260 bool bRet = ( VarUI2FromDec( &maDec, &rVal ) == S_OK );
261 return bRet;
264 bool SbxDecimal::getULong( sal_uInt32& rVal )
266 bool bRet = ( VarUI4FromDec( &maDec, &rVal ) == S_OK );
267 return bRet;
270 bool SbxDecimal::getSingle( float& rVal )
272 bool bRet = ( VarR4FromDec( &maDec, &rVal ) == S_OK );
273 return bRet;
276 bool SbxDecimal::getDouble( double& rVal )
278 bool bRet = ( VarR8FromDec( &maDec, &rVal ) == S_OK );
279 return bRet;
282 #else
283 // !WIN32
285 bool SbxDecimal::operator -= ( const SbxDecimal &r )
287 (void)r;
288 return false;
291 bool SbxDecimal::operator += ( const SbxDecimal &r )
293 (void)r;
294 return false;
297 bool SbxDecimal::operator /= ( const SbxDecimal &r )
299 (void)r;
300 return false;
303 bool SbxDecimal::operator *= ( const SbxDecimal &r )
305 (void)r;
306 return false;
309 bool SbxDecimal::neg()
311 return false;
314 bool SbxDecimal::isZero()
316 return false;
319 SbxDecimal::CmpResult compare( const SbxDecimal &rLeft, const SbxDecimal &rRight )
321 (void)rLeft;
322 (void)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; }
346 #endif
348 bool SbxDecimal::getString( OUString& rString )
350 #ifdef WIN32
351 static LCID nLANGID = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
353 bool bRet = false;
355 OLECHAR sz[100];
356 BSTR aBStr = SysAllocString( sz );
357 if( aBStr != NULL )
359 HRESULT hResult = VarBstrFromDec( &maDec, nLANGID, 0, &aBStr );
360 bRet = ( hResult == S_OK );
361 if( bRet )
363 // Convert delimiter
364 sal_Unicode cDecimalSep;
365 sal_Unicode cThousandSep;
366 ImpGetIntntlSep( cDecimalSep, cThousandSep );
368 if( cDecimalSep != '.' || cThousandSep != ',' )
370 sal_Unicode c;
371 int i = 0;
372 while( (c = aBStr[i]) != 0 )
374 if( c == '.' )
375 aBStr[i] = cDecimalSep;
376 else if( c == ',' )
377 aBStr[i] = cThousandSep;
378 i++;
381 rString = reinterpret_cast<const sal_Unicode*>(aBStr);
384 SysFreeString( aBStr );
386 return bRet;
387 #else
388 (void)rString;
389 return false;
390 #endif
393 SbxDecimal* ImpCreateDecimal( SbxValues* p )
395 if( !p )
396 return NULL;
398 SbxDecimal*& rpDecimal = p->pDecimal;
399 if( rpDecimal == NULL )
401 rpDecimal = new SbxDecimal();
402 rpDecimal->addRef();
404 return rpDecimal;
407 SbxDecimal* ImpGetDecimal( const SbxValues* p )
409 SbxValues aTmp;
410 SbxDecimal* pnDecRes;
412 SbxDataType eType = p->eType;
413 if( eType == SbxDECIMAL && p->pDecimal )
415 pnDecRes = new SbxDecimal( *p->pDecimal );
416 pnDecRes->addRef();
417 return pnDecRes;
419 pnDecRes = new SbxDecimal();
420 pnDecRes->addRef();
422 start:
423 switch( +eType )
425 case SbxNULL:
426 SbxBase::SetError( SbxERR_CONVERSION );
427 case SbxEMPTY:
428 pnDecRes->setShort( 0 ); break;
429 case SbxCHAR:
430 pnDecRes->setChar( p->nChar ); break;
431 case SbxBYTE:
432 pnDecRes->setByte( p->nByte ); break;
433 case SbxINTEGER:
434 case SbxBOOL:
435 pnDecRes->setInt( p->nInteger ); break;
436 case SbxERROR:
437 case SbxUSHORT:
438 pnDecRes->setUShort( p->nUShort ); break;
439 case SbxLONG:
440 pnDecRes->setLong( p->nLong ); break;
441 case SbxULONG:
442 pnDecRes->setULong( p->nULong ); break;
443 case SbxSINGLE:
444 if( !pnDecRes->setSingle( p->nSingle ) )
445 SbxBase::SetError( SbxERR_OVERFLOW );
446 break;
447 case SbxCURRENCY:
449 if( !pnDecRes->setDouble( ImpCurrencyToDouble( p->nInt64 ) ) )
450 SbxBase::SetError( SbxERR_OVERFLOW );
451 break;
453 case SbxSALINT64:
455 if( !pnDecRes->setDouble( (double)p->nInt64 ) )
456 SbxBase::SetError( SbxERR_OVERFLOW );
457 break;
459 case SbxSALUINT64:
461 if( !pnDecRes->setDouble( (double)p->uInt64 ) )
462 SbxBase::SetError( SbxERR_OVERFLOW );
463 break;
465 case SbxDATE:
466 case SbxDOUBLE:
468 double dVal = p->nDouble;
469 if( !pnDecRes->setDouble( dVal ) )
470 SbxBase::SetError( SbxERR_OVERFLOW );
471 break;
473 case SbxLPSTR:
474 case SbxSTRING:
475 case SbxBYREF | SbxSTRING:
476 if ( p->pOUString )
477 pnDecRes->setString( p->pOUString );
478 break;
479 case SbxOBJECT:
481 SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
482 if( pVal )
483 pnDecRes->setDecimal( pVal->GetDecimal() );
484 else
486 SbxBase::SetError( SbxERR_NO_OBJECT );
487 pnDecRes->setShort( 0 );
489 break;
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;
518 ref:
519 aTmp.eType = SbxDataType( p->eType & 0x0FFF );
520 p = &aTmp; goto start;
522 default:
523 SbxBase::SetError( SbxERR_CONVERSION ); pnDecRes->setShort( 0 );
525 return pnDecRes;
528 void ImpPutDecimal( SbxValues* p, SbxDecimal* pDec )
530 if( !pDec )
531 return;
533 SbxValues aTmp;
534 start:
535 switch( +p->eType )
537 // here had to be tested
538 case SbxCHAR:
539 aTmp.pChar = &p->nChar; goto direct;
540 case SbxBYTE:
541 aTmp.pByte = &p->nByte; goto direct;
542 case SbxULONG:
543 aTmp.pULong = &p->nULong; goto direct;
544 case SbxERROR:
545 case SbxUSHORT:
546 aTmp.pUShort = &p->nUShort; goto direct;
547 case SbxINTEGER:
548 case SbxBOOL:
549 aTmp.pInteger = &p->nInteger; goto direct;
550 case SbxLONG:
551 aTmp.pLong = &p->nLong; goto direct;
552 case SbxCURRENCY:
553 case SbxSALINT64:
554 aTmp.pnInt64 = &p->nInt64; goto direct;
555 case SbxSALUINT64:
556 aTmp.puInt64 = &p->uInt64; goto direct;
558 direct:
559 aTmp.eType = SbxDataType( p->eType | SbxBYREF );
560 p = &aTmp; goto start;
562 // from here on no longer
563 case SbxDECIMAL:
564 case SbxBYREF | SbxDECIMAL:
566 if( pDec != p->pDecimal )
568 releaseDecimalPtr( p->pDecimal );
569 p->pDecimal = pDec;
570 if( pDec )
571 pDec->addRef();
573 break;
575 case SbxSINGLE:
577 float f(0.0);
578 pDec->getSingle( f );
579 p->nSingle = f;
580 break;
582 case SbxDATE:
583 case SbxDOUBLE:
585 double d(0.0);
586 pDec->getDouble( d );
587 p->nDouble = d;
588 break;
591 case SbxLPSTR:
592 case SbxSTRING:
593 case SbxBYREF | SbxSTRING:
594 if( !p->pOUString )
595 p->pOUString = new OUString;
596 pDec->getString( *p->pOUString );
597 break;
598 case SbxOBJECT:
600 SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
601 if( pVal )
602 pVal->PutDecimal( pDec );
603 else
604 SbxBase::SetError( SbxERR_NO_OBJECT );
605 break;
608 case SbxBYREF | SbxCHAR:
609 if( !pDec->getChar( *p->pChar ) )
611 SbxBase::SetError( SbxERR_OVERFLOW );
612 *p->pChar = 0;
614 break;
615 case SbxBYREF | SbxBYTE:
616 if( !pDec->getChar( *p->pChar ) )
618 SbxBase::SetError( SbxERR_OVERFLOW );
619 *p->pByte = 0;
621 break;
622 case SbxBYREF | SbxINTEGER:
623 case SbxBYREF | SbxBOOL:
624 if( !pDec->getShort( *p->pInteger ) )
626 SbxBase::SetError( SbxERR_OVERFLOW );
627 *p->pInteger = 0;
629 break;
630 case SbxBYREF | SbxERROR:
631 case SbxBYREF | SbxUSHORT:
632 if( !pDec->getUShort( *p->pUShort ) )
634 SbxBase::SetError( SbxERR_OVERFLOW );
635 *p->pUShort = 0;
637 break;
638 case SbxBYREF | SbxLONG:
639 if( !pDec->getLong( *p->pLong ) )
641 SbxBase::SetError( SbxERR_OVERFLOW );
642 *p->pLong = 0;
644 break;
645 case SbxBYREF | SbxULONG:
646 if( !pDec->getULong( *p->pULong ) )
648 SbxBase::SetError( SbxERR_OVERFLOW );
649 *p->pULong = 0;
651 break;
652 case SbxBYREF | SbxCURRENCY:
654 double d(0.0);
655 if( !pDec->getDouble( d ) )
656 SbxBase::SetError( SbxERR_OVERFLOW );
657 *p->pnInt64 = ImpDoubleToCurrency( d );
659 break;
660 case SbxBYREF | SbxSALINT64:
662 double d(0.0);
663 if( !pDec->getDouble( d ) )
664 SbxBase::SetError( SbxERR_OVERFLOW );
665 else
666 *p->pnInt64 = ImpDoubleToSalInt64( d );
668 break;
669 case SbxBYREF | SbxSALUINT64:
671 double d(0.0);
672 if( !pDec->getDouble( d ) )
673 SbxBase::SetError( SbxERR_OVERFLOW );
674 else
675 *p->puInt64 = ImpDoubleToSalUInt64( d );
677 break;
678 case SbxBYREF | SbxSINGLE:
679 if( !pDec->getSingle( *p->pSingle ) )
681 SbxBase::SetError( SbxERR_OVERFLOW );
682 *p->pSingle = 0;
684 break;
685 case SbxBYREF | SbxDATE:
686 case SbxBYREF | SbxDOUBLE:
687 if( !pDec->getDouble( *p->pDouble ) )
689 SbxBase::SetError( SbxERR_OVERFLOW );
690 *p->pDouble = 0;
692 break;
693 default:
694 SbxBase::SetError( SbxERR_CONVERSION );
698 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */