xref: /trunk/main/basic/source/sbx/sbxcurr.cxx (revision e1f63238)
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