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