xref: /AOO41X/main/basic/source/sbx/sbxcurr.cxx (revision e1f63238eb022c8a12b30d46a012444ff20e0951)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basic.hxx"
26 
27 #include <basic/sbx.hxx>
28 #include <tools/errcode.hxx>
29 
30 #define _TLBIGINT_INT64
31 #include <tools/bigint.hxx>
32 
33 #include <basic/sbxvar.hxx>
34 #include "sbxconv.hxx"
35 
36 static ::rtl::OUString   ImpCurrencyToString( const SbxINT64& );
37 static SbxINT64 ImpStringToCurrency( const ::rtl::OUString& );
38 
ImpGetCurrency(const SbxValues * p)39 SbxINT64 ImpGetCurrency( const SbxValues* p )
40 {
41     SbxValues aTmp;
42     SbxINT64 nRes;
43 start:
44     switch( +p->eType )
45     {
46         case SbxNULL:
47             SbxBase::SetError( SbxERR_CONVERSION );
48         case SbxEMPTY:
49             nRes.SetNull(); break;
50         case SbxCHAR:
51             nRes = ImpDoubleToCurrency( (double)p->nChar ); break;
52         case SbxBYTE:
53             nRes = ImpDoubleToCurrency( (double)p->nByte ); break;
54         case SbxINTEGER:
55         case SbxBOOL:
56             nRes = ImpDoubleToCurrency( (double)p->nInteger ); break;
57         case SbxERROR:
58         case SbxUSHORT:
59             nRes = ImpDoubleToCurrency( (double)p->nUShort ); break;
60         case SbxCURRENCY:
61             nRes = p->nLong64; break;
62         case SbxLONG:
63             nRes = ImpDoubleToCurrency( (double)p->nLong );
64             break;
65         case SbxULONG:
66             nRes = ImpDoubleToCurrency( (double)p->nULong );
67             break;
68         case SbxSALINT64:
69             nRes = ImpDoubleToCurrency( (double)p->nInt64 );
70             break;
71         case SbxSALUINT64:
72             nRes = ImpDoubleToCurrency( ImpSalUInt64ToDouble( p->uInt64 ) );
73             break;
74         case SbxSINGLE:
75             if( p->nSingle > SbxMAXCURR )
76             {
77                 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax();
78             }
79             else if( p->nSingle < SbxMINCURR )
80             {
81                 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin();
82             }
83             else
84                 nRes = ImpDoubleToCurrency( (double)p->nSingle );
85             break;
86         case SbxDATE:
87         case SbxDOUBLE:
88             if( p->nDouble > SbxMAXCURR )
89             {
90                 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax();
91             }
92             else if( p->nDouble < SbxMINCURR )
93             {
94                 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin();
95             }
96             else
97                 nRes = ImpDoubleToCurrency( p->nDouble );
98             break;
99         case SbxDECIMAL:
100         case SbxBYREF | SbxDECIMAL:
101             {
102             double d = 0.0;
103             if( p->pDecimal )
104                 p->pDecimal->getDouble( d );
105             if( d > SbxMAXCURR )
106             {
107                 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax();
108             }
109             else if( d < SbxMINCURR )
110             {
111                 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin();
112             }
113             else
114                 nRes = ImpDoubleToCurrency( d );
115             break;
116             }
117         case SbxBYREF | SbxSTRING:
118         case SbxSTRING:
119         case SbxLPSTR:
120             if( !p->pOUString )
121                 nRes.SetNull();
122             else
123                 nRes = ImpStringToCurrency( *p->pOUString );
124             break;
125         case SbxOBJECT:
126         {
127             SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
128             if( pVal )
129                 nRes = pVal->GetCurrency();
130             else
131             {
132                 SbxBase::SetError( SbxERR_NO_OBJECT ); nRes.SetNull();
133             }
134             break;
135         }
136 
137         case SbxBYREF | SbxCHAR:
138             nRes = ImpDoubleToCurrency( (double)*p->pChar ); break;
139         case SbxBYREF | SbxBYTE:
140             nRes = ImpDoubleToCurrency( (double)*p->pByte ); break;
141         case SbxBYREF | SbxINTEGER:
142         case SbxBYREF | SbxBOOL:
143             nRes = ImpDoubleToCurrency( (double)*p->pInteger ); break;
144         case SbxBYREF | SbxERROR:
145         case SbxBYREF | SbxUSHORT:
146             nRes = ImpDoubleToCurrency( (double)*p->pUShort ); break;
147         case SbxBYREF | SbxCURRENCY:
148             nRes = *p->pLong64; break;
149 
150         // ab hier muss getestet werden
151         case SbxBYREF | SbxLONG:
152             aTmp.nLong = *p->pLong; goto ref;
153         case SbxBYREF | SbxULONG:
154             aTmp.nULong = *p->pULong; goto ref;
155         case SbxBYREF | SbxSINGLE:
156             aTmp.nSingle = *p->pSingle; goto ref;
157         case SbxBYREF | SbxDATE:
158         case SbxBYREF | SbxDOUBLE:
159             aTmp.nDouble = *p->pDouble; goto ref;
160         case SbxBYREF | SbxSALINT64:
161             aTmp.nInt64 = *p->pnInt64; goto ref;
162         case SbxBYREF | SbxSALUINT64:
163             aTmp.uInt64 = *p->puInt64; goto ref;
164         ref:
165             aTmp.eType = SbxDataType( p->eType & 0x0FFF );
166             p = &aTmp; goto start;
167 
168         default:
169             SbxBase::SetError( SbxERR_CONVERSION ); nRes.SetNull();
170     }
171     return nRes;
172 }
173 
ImpPutCurrency(SbxValues * p,const SbxINT64 & r)174 void ImpPutCurrency( SbxValues* p, const SbxINT64 &r )
175 {
176     double dVal = ImpCurrencyToDouble( r );
177     SbxValues aTmp;
178 start:
179     switch( +p->eType )
180     {
181         // Hier sind Tests notwendig
182         case SbxCHAR:
183             aTmp.pChar = &p->nChar; goto direct;
184         case SbxBYTE:
185             aTmp.pByte = &p->nByte; goto direct;
186         case SbxINTEGER:
187         case SbxBOOL:
188             aTmp.pInteger = &p->nInteger; goto direct;
189         case SbxLONG:
190             aTmp.pLong = &p->nLong; goto direct;
191         case SbxULONG:
192             aTmp.pULong = &p->nULong; goto direct;
193         case SbxERROR:
194         case SbxUSHORT:
195             aTmp.pUShort = &p->nUShort; goto direct;
196         direct:
197             aTmp.eType = SbxDataType( p->eType | SbxBYREF );
198             p = &aTmp; goto start;
199 
200         // ab hier nicht mehr
201         case SbxSINGLE:
202             p->nSingle = (float)dVal; break;
203         case SbxDATE:
204         case SbxDOUBLE:
205             p->nDouble = dVal; break;
206         case SbxSALINT64:
207             p->nInt64 = ImpDoubleToSalInt64( dVal ); break;
208         case SbxSALUINT64:
209             p->uInt64 = ImpDoubleToSalUInt64( dVal ); break;
210         case SbxCURRENCY:
211             p->nLong64 = r; break;
212         case SbxDECIMAL:
213         case SbxBYREF | SbxDECIMAL:
214             {
215             SbxDecimal* pDec = ImpCreateDecimal( p );
216             if( !pDec->setDouble( dVal ) )
217                 SbxBase::SetError( SbxERR_OVERFLOW );
218             break;
219             }
220         case SbxBYREF | SbxSTRING:
221         case SbxSTRING:
222         case SbxLPSTR:
223             if( !p->pOUString )
224                 p->pOUString = new ::rtl::OUString;
225 
226             *p->pOUString = ImpCurrencyToString( r );
227             break;
228         case SbxOBJECT:
229         {
230             SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
231             if( pVal )
232                 pVal->PutCurrency( r );
233             else
234                 SbxBase::SetError( SbxERR_NO_OBJECT );
235             break;
236         }
237         case SbxBYREF | SbxCHAR:
238             if( dVal > SbxMAXCHAR )
239             {
240                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXCHAR;
241             }
242             else if( dVal < SbxMINCHAR )
243             {
244                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMINCHAR;
245             }
246             *p->pChar = (xub_Unicode) dVal; break;
247         case SbxBYREF | SbxBYTE:
248             if( dVal > SbxMAXBYTE )
249             {
250                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXBYTE;
251             }
252             else if( dVal < 0 )
253             {
254                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0;
255             }
256             *p->pByte = (sal_uInt8) dVal; break;
257         case SbxBYREF | SbxINTEGER:
258         case SbxBYREF | SbxBOOL:
259             if( dVal > SbxMAXINT )
260             {
261                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXINT;
262             }
263             else if( dVal < SbxMININT )
264             {
265                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMININT;
266             }
267             *p->pInteger = (sal_Int16) dVal; break;
268         case SbxBYREF | SbxERROR:
269         case SbxBYREF | SbxUSHORT:
270             if( dVal > SbxMAXUINT )
271             {
272                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXUINT;
273             }
274             else if( dVal < 0 )
275             {
276                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0;
277             }
278             *p->pUShort = (sal_uInt16) dVal; break;
279         case SbxBYREF | SbxLONG:
280             if( dVal > SbxMAXLNG )
281             {
282                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXLNG;
283             }
284             else if( dVal < SbxMINLNG )
285             {
286                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMINLNG;
287             }
288             *p->pLong = (sal_Int32) dVal; break;
289         case SbxBYREF | SbxULONG:
290             if( dVal > SbxMAXULNG )
291             {
292                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXULNG;
293             }
294             else if( dVal < 0 )
295             {
296                 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0;
297             }
298             *p->pULong = (sal_uInt32) dVal; break;
299         case SbxBYREF | SbxSALINT64:
300             *p->pnInt64 = ImpDoubleToSalInt64( dVal ); break;
301         case SbxBYREF | SbxSALUINT64:
302             *p->puInt64 = ImpDoubleToSalUInt64( dVal ); break;
303         case SbxBYREF | SbxSINGLE:
304             *p->pSingle = (float) dVal; break;
305         case SbxBYREF | SbxDATE:
306         case SbxBYREF | SbxDOUBLE:
307             *p->pDouble = (double) dVal; break;
308         case SbxBYREF | SbxCURRENCY:
309             *p->pLong64 = r; break;
310 
311         default:
312             SbxBase::SetError( SbxERR_CONVERSION );
313     }
314 }
315 
316 // Hilfs-Funktionen zur Wandlung
317 
ImpCurrencyToString(const SbxINT64 & r)318 static ::rtl::OUString ImpCurrencyToString( const SbxINT64 &r )
319 {
320     BigInt a10000 = 10000;
321 
322     //return GetpApp()->GetAppInternational().GetCurr( BigInt( r ), 4 );
323     BigInt aInt( r );
324     aInt.Abs();
325     BigInt aFrac = aInt;
326     aInt  /= a10000;
327     aFrac %= a10000;
328     aFrac += a10000;
329 
330     ::rtl::OUString aString;
331     if( r.nHigh < 0 )
332         aString = ::rtl::OUString( (sal_Unicode)'-' );
333     aString += aInt.GetString();
334     aString += ::rtl::OUString( (sal_Unicode)'.' );
335     aString += aFrac.GetString().GetBuffer()+1;
336     return aString;
337 }
338 
ImpStringToCurrency(const::rtl::OUString & r)339 static SbxINT64 ImpStringToCurrency( const ::rtl::OUString &r )
340 {
341     int nDec = 4;
342     String aStr;
343     const sal_Unicode* p = r.getStr();
344 
345     if( *p == '-' )
346         aStr += *p++;
347 
348     while( *p >= '0' && *p <= '9' ) {
349         aStr += *p++;
350         if( *p == ',' )
351             p++;
352     }
353 
354     if( *p == '.' ) {
355         p++;
356         while( nDec && *p >= '0' && *p <= '9' ) {
357             aStr += *p++;
358             nDec--;
359         }
360     }
361     while( nDec ) {
362         aStr += '0';
363         nDec--;
364     }
365 
366     BigInt aBig( aStr );
367     SbxINT64 nRes;
368     aBig.INT64( &nRes );
369     return nRes;
370 }
371 
ImpINT64ToDouble(const SbxINT64 & r)372 double ImpINT64ToDouble( const SbxINT64 &r )
373 { return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; }
374 
ImpDoubleToINT64(double d)375 SbxINT64 ImpDoubleToINT64( double d )
376 {
377     SbxINT64 nRes;
378     nRes.Set( d );
379     return nRes;
380 }
381 
ImpUINT64ToDouble(const SbxUINT64 & r)382 double ImpUINT64ToDouble( const SbxUINT64 &r )
383 { return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; }
384 
ImpDoubleToUINT64(double d)385 SbxUINT64 ImpDoubleToUINT64( double d )
386 {
387     SbxUINT64 nRes;
388     nRes.Set( d );
389     return nRes;
390 }
391 
392