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 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 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 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 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 372 double ImpINT64ToDouble( const SbxINT64 &r ) 373 { return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; } 374 375 SbxINT64 ImpDoubleToINT64( double d ) 376 { 377 SbxINT64 nRes; 378 nRes.Set( d ); 379 return nRes; 380 } 381 382 double ImpUINT64ToDouble( const SbxUINT64 &r ) 383 { return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; } 384 385 SbxUINT64 ImpDoubleToUINT64( double d ) 386 { 387 SbxUINT64 nRes; 388 nRes.Set( d ); 389 return nRes; 390 } 391 392