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