1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <sal/config.h> 21 22 #include <o3tl/float_int_conversion.hxx> 23 #include <vcl/errcode.hxx> 24 #include <basic/sberrors.hxx> 25 #include "sbxconv.hxx" 26 27 #include <rtl/math.hxx> 28 29 sal_Int16 ImpGetInteger( const SbxValues* p ) 30 { 31 SbxValues aTmp; 32 sal_Int16 nRes; 33 start: 34 switch( +p->eType ) 35 { 36 case SbxNULL: 37 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 38 [[fallthrough]]; 39 case SbxEMPTY: 40 nRes = 0; break; 41 case SbxCHAR: 42 nRes = p->nChar; break; 43 case SbxBYTE: 44 nRes = p->nByte; break; 45 case SbxINTEGER: 46 case SbxBOOL: 47 nRes = p->nInteger; break; 48 case SbxERROR: 49 case SbxUSHORT: 50 if( p->nUShort > sal_uInt16(SbxMAXINT) ) 51 { 52 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 53 } 54 else 55 nRes = static_cast<sal_Int16>(p->nUShort); 56 break; 57 case SbxLONG: 58 if( p->nLong > SbxMAXINT ) 59 { 60 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 61 } 62 else if( p->nLong < SbxMININT ) 63 { 64 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMININT; 65 } 66 else 67 nRes = static_cast<sal_Int16>(p->nLong); 68 break; 69 case SbxULONG: 70 if( p->nULong > SbxMAXINT ) 71 { 72 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 73 } 74 else 75 nRes = static_cast<sal_Int16>(p->nULong); 76 break; 77 case SbxSINGLE: 78 if( !o3tl::convertsToAtMost(o3tl::roundAway(p->nSingle), SbxMAXINT) ) 79 { 80 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 81 } 82 else if( !o3tl::convertsToAtLeast(o3tl::roundAway(p->nSingle), SbxMININT) ) 83 { 84 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMININT; 85 } 86 else 87 nRes = static_cast<sal_Int16>(rtl::math::round( p->nSingle )); 88 break; 89 case SbxCURRENCY: 90 { 91 sal_Int64 tstVal = p->nInt64 / sal_Int64(CURRENCY_FACTOR); 92 93 if( tstVal > SbxMAXINT ) 94 { 95 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 96 } 97 else if( tstVal < SbxMININT ) 98 { 99 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMININT; 100 } 101 else 102 nRes = static_cast<sal_Int16>(tstVal); 103 break; 104 } 105 case SbxSALINT64: 106 if( p->nInt64 > SbxMAXINT ) 107 { 108 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 109 } 110 else if( p->nInt64 < SbxMININT ) 111 { 112 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMININT; 113 } 114 else 115 nRes = static_cast<sal_Int16>(p->nInt64); 116 break; 117 case SbxSALUINT64: 118 if( p->uInt64 > SbxMAXINT ) 119 { 120 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 121 } 122 else 123 nRes = static_cast<sal_Int16>(p->uInt64); 124 break; 125 case SbxDATE: 126 case SbxDOUBLE: 127 case SbxDECIMAL: 128 case SbxBYREF | SbxDECIMAL: 129 { 130 double dVal = 0.0; 131 if( p->eType == SbxDECIMAL ) 132 { 133 if( p->pDecimal ) 134 p->pDecimal->getDouble( dVal ); 135 } 136 else 137 dVal = p->nDouble; 138 139 if( !o3tl::convertsToAtMost(o3tl::roundAway(dVal), SbxMAXINT) ) 140 { 141 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 142 } 143 else if( !o3tl::convertsToAtLeast(o3tl::roundAway(dVal), SbxMININT) ) 144 { 145 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMININT; 146 } 147 else 148 nRes = static_cast<sal_Int16>(rtl::math::round( dVal )); 149 break; 150 } 151 case SbxLPSTR: 152 case SbxSTRING: 153 case SbxBYREF | SbxSTRING: 154 if( !p->pOUString ) 155 nRes = 0; 156 else 157 { 158 double d; 159 SbxDataType t; 160 if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE ) 161 nRes = 0; 162 else if( !o3tl::convertsToAtMost(o3tl::roundAway(d), SbxMAXINT) ) 163 { 164 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXINT; 165 } 166 else if( !o3tl::convertsToAtLeast(o3tl::roundAway(d), SbxMININT) ) 167 { 168 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMININT; 169 } 170 else 171 nRes = static_cast<sal_Int16>(rtl::math::round( d )); 172 } 173 break; 174 case SbxOBJECT: 175 { 176 SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj ); 177 if( pVal ) 178 nRes = pVal->GetInteger(); 179 else 180 { 181 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); nRes = 0; 182 } 183 break; 184 } 185 186 case SbxBYREF | SbxCHAR: 187 nRes = *p->pChar; break; 188 case SbxBYREF | SbxBYTE: 189 nRes = *p->pByte; break; 190 case SbxBYREF | SbxINTEGER: 191 case SbxBYREF | SbxBOOL: 192 nRes = *p->pInteger; break; 193 194 // from here had to be tested 195 case SbxBYREF | SbxLONG: 196 aTmp.nLong = *p->pLong; goto ref; 197 case SbxBYREF | SbxULONG: 198 aTmp.nULong = *p->pULong; goto ref; 199 case SbxBYREF | SbxERROR: 200 case SbxBYREF | SbxUSHORT: 201 aTmp.nUShort = *p->pUShort; goto ref; 202 case SbxBYREF | SbxSINGLE: 203 aTmp.nSingle = *p->pSingle; goto ref; 204 case SbxBYREF | SbxDATE: 205 case SbxBYREF | SbxDOUBLE: 206 aTmp.nDouble = *p->pDouble; goto ref; 207 case SbxBYREF | SbxCURRENCY: 208 case SbxBYREF | SbxSALINT64: 209 aTmp.nInt64 = *p->pnInt64; goto ref; 210 case SbxBYREF | SbxSALUINT64: 211 aTmp.uInt64 = *p->puInt64; goto ref; 212 ref: 213 aTmp.eType = SbxDataType( p->eType & 0x0FFF ); 214 p = &aTmp; goto start; 215 216 default: 217 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); nRes = 0; 218 } 219 return nRes; 220 } 221 222 void ImpPutInteger( SbxValues* p, sal_Int16 n ) 223 { 224 SbxValues aTmp; 225 start: 226 switch( +p->eType ) 227 { 228 // here had to be tested 229 case SbxCHAR: 230 aTmp.pChar = &p->nChar; goto direct; 231 case SbxBYTE: 232 aTmp.pByte = &p->nByte; goto direct; 233 case SbxULONG: 234 aTmp.pULong = &p->nULong; goto direct; 235 case SbxERROR: 236 case SbxUSHORT: 237 aTmp.pUShort = &p->nUShort; goto direct; 238 case SbxSALUINT64: 239 aTmp.puInt64 = &p->uInt64; goto direct; 240 direct: 241 aTmp.eType = SbxDataType( p->eType | SbxBYREF ); 242 p = &aTmp; goto start; 243 244 // from here no tests needed 245 case SbxINTEGER: 246 case SbxBOOL: 247 p->nInteger = n; break; 248 case SbxLONG: 249 p->nLong = n; break; 250 case SbxSINGLE: 251 p->nSingle = n; break; 252 case SbxDATE: 253 case SbxDOUBLE: 254 p->nDouble = n; break; 255 case SbxCURRENCY: 256 p->nInt64 = n * CURRENCY_FACTOR; break; 257 case SbxSALINT64: 258 p->nInt64 = n; break; 259 case SbxDECIMAL: 260 case SbxBYREF | SbxDECIMAL: 261 ImpCreateDecimal( p )->setInt( n ); 262 break; 263 264 case SbxLPSTR: 265 case SbxSTRING: 266 case SbxBYREF | SbxSTRING: 267 if( !p->pOUString ) 268 p->pOUString = new OUString; 269 ImpCvtNum( static_cast<double>(n), 0, *p->pOUString ); 270 break; 271 case SbxOBJECT: 272 { 273 SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj ); 274 if( pVal ) 275 pVal->PutInteger( n ); 276 else 277 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); 278 break; 279 } 280 case SbxBYREF | SbxCHAR: 281 if( n < SbxMINCHAR ) 282 { 283 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINCHAR; 284 } 285 *p->pChar = static_cast<char>(n); break; 286 case SbxBYREF | SbxBYTE: 287 if( n > SbxMAXBYTE ) 288 { 289 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXBYTE; 290 } 291 else if( n < 0 ) 292 { 293 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0; 294 } 295 *p->pByte = static_cast<sal_uInt8>(n); break; 296 case SbxBYREF | SbxINTEGER: 297 case SbxBYREF | SbxBOOL: 298 *p->pInteger = n; break; 299 case SbxBYREF | SbxERROR: 300 case SbxBYREF | SbxUSHORT: 301 if( n < 0 ) 302 { 303 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0; 304 } 305 *p->pUShort = static_cast<sal_uInt16>(n); break; 306 case SbxBYREF | SbxLONG: 307 *p->pLong = static_cast<sal_Int32>(n); break; 308 case SbxBYREF | SbxULONG: 309 if( n < 0 ) 310 { 311 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0; 312 } 313 *p->pULong = static_cast<sal_uInt32>(n); break; 314 case SbxBYREF | SbxCURRENCY: 315 *p->pnInt64 = n * CURRENCY_FACTOR; break; 316 case SbxBYREF | SbxSALINT64: 317 *p->pnInt64 = n; break; 318 case SbxBYREF | SbxSALUINT64: 319 if( n < 0 ) 320 { 321 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); 322 *p->puInt64 = 0; 323 } 324 else 325 *p->puInt64 = n; 326 break; 327 case SbxBYREF | SbxSINGLE: 328 *p->pSingle = static_cast<float>(n); break; 329 case SbxBYREF | SbxDATE: 330 case SbxBYREF | SbxDOUBLE: 331 *p->pDouble = static_cast<double>(n); break; 332 333 default: 334 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 335 } 336 } 337 338 339 // sal_Int64 / hyper 340 341 sal_Int64 ImpDoubleToSalInt64( double d ) 342 { 343 sal_Int64 nRes; 344 if( !o3tl::convertsToAtMost(o3tl::roundAway(d), SAL_MAX_INT64) ) 345 { 346 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SAL_MAX_INT64; 347 } 348 else if( !o3tl::convertsToAtLeast(o3tl::roundAway(d), SAL_MIN_INT64) ) 349 { 350 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SAL_MIN_INT64; 351 } 352 else 353 nRes = static_cast<sal_Int64>(rtl::math::round( d )); 354 return nRes; 355 } 356 357 sal_uInt64 ImpDoubleToSalUInt64( double d ) 358 { 359 sal_uInt64 nRes; 360 if( !o3tl::convertsToAtMost(o3tl::roundAway(d), SAL_MAX_UINT64) ) 361 { 362 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SAL_MAX_UINT64; 363 } 364 else if( d < 0.0 ) 365 { 366 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 367 } 368 else 369 nRes = static_cast<sal_uInt64>(rtl::math::round( d )); 370 return nRes; 371 } 372 373 374 double ImpSalUInt64ToDouble( sal_uInt64 n ) 375 { 376 double d = 0.0; 377 if( n > SAL_MAX_INT64 ) 378 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 379 else 380 d = static_cast<double>(static_cast<sal_Int64>(n)); 381 return d; 382 } 383 384 385 sal_Int64 ImpGetInt64( const SbxValues* p ) 386 { 387 SbxValues aTmp; 388 sal_Int64 nRes; 389 start: 390 switch( +p->eType ) 391 { 392 case SbxNULL: 393 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 394 [[fallthrough]]; 395 case SbxEMPTY: 396 nRes = 0; break; 397 case SbxCHAR: 398 nRes = p->nChar; break; 399 case SbxBYTE: 400 nRes = p->nByte; break; 401 case SbxINTEGER: 402 case SbxBOOL: 403 nRes = p->nInteger; break; 404 case SbxERROR: 405 case SbxUSHORT: 406 nRes = static_cast<sal_Int64>(p->nUShort); break; 407 case SbxLONG: 408 nRes = static_cast<sal_Int64>(p->nLong); break; 409 case SbxULONG: 410 nRes = static_cast<sal_Int64>(p->nULong); break; 411 case SbxSINGLE: 412 nRes = static_cast<sal_Int64>(p->nSingle); 413 break; 414 case SbxDATE: 415 case SbxDOUBLE: 416 nRes = static_cast<sal_Int64>(p->nDouble); 417 break; 418 case SbxCURRENCY: 419 nRes = p->nInt64 / CURRENCY_FACTOR; break; 420 case SbxSALINT64: 421 nRes = p->nInt64; break; 422 case SbxSALUINT64: 423 if( p->uInt64 > SAL_MAX_INT64 ) 424 { 425 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SAL_MAX_INT64; 426 } 427 else 428 nRes = static_cast<sal_Int64>(p->uInt64); 429 break; 430 431 case SbxBYREF | SbxSTRING: 432 case SbxSTRING: 433 case SbxLPSTR: 434 if( !p->pOUString ) 435 nRes = 0; 436 else 437 { 438 ::OString aOStr = OUStringToOString( *p->pOUString, RTL_TEXTENCODING_ASCII_US ); 439 nRes = aOStr.toInt64(); 440 if( nRes == 0 ) 441 { 442 // Check if really 0 or invalid conversion 443 double d; 444 SbxDataType t; 445 if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE ) 446 nRes = 0; 447 else 448 nRes = static_cast<sal_Int64>(d); 449 } 450 } 451 break; 452 case SbxOBJECT: 453 { 454 SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj ); 455 if( pVal ) 456 nRes = pVal->GetInt64(); 457 else 458 { 459 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); nRes = 0; 460 } 461 break; 462 } 463 464 case SbxBYREF | SbxCHAR: 465 nRes = *p->pChar; break; 466 case SbxBYREF | SbxBYTE: 467 nRes = *p->pByte; break; 468 case SbxBYREF | SbxINTEGER: 469 case SbxBYREF | SbxBOOL: 470 nRes = *p->pInteger; break; 471 case SbxBYREF | SbxLONG: 472 nRes = *p->pLong; break; 473 case SbxBYREF | SbxULONG: 474 nRes = *p->pULong; break; 475 case SbxBYREF | SbxCURRENCY: 476 nRes = p->nInt64 / CURRENCY_FACTOR; break; 477 case SbxBYREF | SbxSALINT64: 478 nRes = *p->pnInt64; break; 479 480 // from here the values has to be checked 481 case SbxBYREF | SbxSALUINT64: 482 aTmp.uInt64 = *p->puInt64; goto ref; 483 484 case SbxBYREF | SbxERROR: 485 case SbxBYREF | SbxUSHORT: 486 aTmp.nUShort = *p->pUShort; goto ref; 487 case SbxBYREF | SbxSINGLE: 488 aTmp.nSingle = *p->pSingle; goto ref; 489 case SbxBYREF | SbxDATE: 490 case SbxBYREF | SbxDOUBLE: 491 aTmp.nDouble = *p->pDouble; goto ref; 492 ref: 493 aTmp.eType = SbxDataType( p->eType & 0x0FFF ); 494 p = &aTmp; goto start; 495 496 default: 497 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); nRes = 0; 498 } 499 return nRes; 500 } 501 502 void ImpPutInt64( SbxValues* p, sal_Int64 n ) 503 { 504 SbxValues aTmp; 505 506 start: 507 switch( +p->eType ) 508 { 509 // Check necessary 510 case SbxCHAR: 511 aTmp.pChar = &p->nChar; goto direct; 512 case SbxBYTE: 513 aTmp.pByte = &p->nByte; goto direct; 514 case SbxINTEGER: 515 case SbxBOOL: 516 aTmp.pInteger = &p->nInteger; goto direct; 517 case SbxULONG: 518 aTmp.pULong = &p->nULong; goto direct; 519 case SbxERROR: 520 case SbxUSHORT: 521 aTmp.pUShort = &p->nUShort; goto direct; 522 case SbxLONG: 523 aTmp.pnInt64 = &p->nInt64; goto direct; 524 case SbxCURRENCY: 525 case SbxSALINT64: 526 aTmp.pnInt64 = &p->nInt64; goto direct; 527 case SbxSALUINT64: 528 aTmp.puInt64 = &p->uInt64; goto direct; 529 530 direct: 531 aTmp.eType = SbxDataType( p->eType | SbxBYREF ); 532 p = &aTmp; goto start; 533 534 case SbxSINGLE: 535 p->nSingle = static_cast<float>(n); break; 536 case SbxDATE: 537 case SbxDOUBLE: 538 p->nDouble = static_cast<double>(n); break; 539 540 case SbxBYREF | SbxSTRING: 541 case SbxSTRING: 542 case SbxLPSTR: 543 { 544 if( !p->pOUString ) 545 p->pOUString = new OUString; 546 547 ::OString aOStr = OString::number( n ); 548 (*p->pOUString) = ::OStringToOUString( aOStr, RTL_TEXTENCODING_ASCII_US ); 549 break; 550 } 551 case SbxOBJECT: 552 { 553 SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj ); 554 if( pVal ) 555 pVal->PutInt64( n ); 556 else 557 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); 558 break; 559 } 560 case SbxBYREF | SbxCHAR: 561 if( n > SbxMAXCHAR ) 562 { 563 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXCHAR; 564 } 565 else if( n < SbxMINCHAR ) 566 { 567 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINCHAR; 568 } 569 *p->pChar = static_cast<sal_Unicode>(n); break; 570 case SbxBYREF | SbxBYTE: 571 if( n > SbxMAXBYTE ) 572 { 573 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXBYTE; 574 } 575 else if( n < 0 ) 576 { 577 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0; 578 } 579 *p->pByte = static_cast<sal_uInt8>(n); break; 580 case SbxBYREF | SbxINTEGER: 581 case SbxBYREF | SbxBOOL: 582 if( n > SbxMAXINT ) 583 { 584 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXINT; 585 } 586 else if( n < SbxMININT ) 587 { 588 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMININT; 589 } 590 *p->pInteger = static_cast<sal_Int16>(n); break; 591 case SbxBYREF | SbxERROR: 592 case SbxBYREF | SbxUSHORT: 593 if( n > SbxMAXUINT ) 594 { 595 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXUINT; 596 } 597 else if( n < 0 ) 598 { 599 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0; 600 } 601 *p->pUShort = static_cast<sal_uInt16>(n); break; 602 case SbxBYREF | SbxLONG: 603 if( n > SbxMAXLNG ) 604 { 605 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXLNG; 606 } 607 else if( n < SbxMINLNG ) 608 { 609 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINLNG; 610 } 611 *p->pLong = static_cast<sal_Int32>(n); break; 612 case SbxBYREF | SbxULONG: 613 if( n > SbxMAXULNG ) 614 { 615 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXULNG; 616 } 617 else if( n < 0 ) 618 { 619 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0; 620 } 621 *p->pULong = static_cast<sal_uInt32>(n); break; 622 case SbxBYREF | SbxSINGLE: 623 *p->pSingle = static_cast<float>(n); break; 624 case SbxBYREF | SbxDATE: 625 case SbxBYREF | SbxDOUBLE: 626 *p->pDouble = static_cast<double>(n); break; 627 case SbxBYREF | SbxCURRENCY: 628 *p->pnInt64 = n * CURRENCY_FACTOR; break; 629 case SbxBYREF | SbxSALINT64: 630 *p->pnInt64 = n; break; 631 case SbxBYREF | SbxSALUINT64: 632 if( n < 0 ) 633 { 634 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0; 635 } 636 *p->puInt64 = n; break; 637 638 default: 639 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 640 } 641 } 642 643 sal_uInt64 ImpGetUInt64( const SbxValues* p ) 644 { 645 SbxValues aTmp; 646 sal_uInt64 nRes; 647 start: 648 switch( +p->eType ) 649 { 650 case SbxNULL: 651 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 652 [[fallthrough]]; 653 case SbxEMPTY: 654 nRes = 0; break; 655 case SbxCHAR: 656 nRes = p->nChar; break; 657 case SbxBYTE: 658 nRes = p->nByte; break; 659 case SbxINTEGER: 660 case SbxBOOL: 661 nRes = p->nInteger; break; 662 case SbxERROR: 663 case SbxUSHORT: 664 nRes = p->nUShort; break; 665 case SbxLONG: 666 nRes = p->nLong; break; 667 case SbxULONG: 668 nRes = static_cast<sal_uInt64>(p->nULong); break; 669 case SbxSINGLE: 670 nRes = static_cast<sal_uInt64>(p->nSingle); break; 671 case SbxDATE: 672 case SbxDOUBLE: 673 { 674 //TODO overflow check 675 nRes = static_cast<sal_uInt64>(p->nDouble); 676 break; 677 } 678 case SbxCURRENCY: 679 nRes = p->nInt64 * CURRENCY_FACTOR; break; 680 case SbxSALINT64: 681 if( p->nInt64 < 0 ) 682 { 683 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 684 } 685 else 686 nRes = static_cast<sal_uInt64>(p->nInt64); 687 break; 688 case SbxSALUINT64: 689 nRes = p->uInt64; break; 690 691 case SbxBYREF | SbxSTRING: 692 case SbxSTRING: 693 case SbxLPSTR: 694 if( !p->pOUString ) 695 nRes = 0; 696 else 697 { 698 ::OString aOStr = OUStringToOString 699 ( *p->pOUString, RTL_TEXTENCODING_ASCII_US ); 700 sal_Int64 n64 = aOStr.toInt64(); 701 if( n64 == 0 ) 702 { 703 // Check if really 0 or invalid conversion 704 double d; 705 SbxDataType t; 706 if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE ) 707 nRes = 0; 708 else if( !o3tl::convertsToAtMost(o3tl::roundAway(d), SAL_MAX_UINT64) ) 709 { 710 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SAL_MAX_UINT64; 711 } 712 else if( d < 0.0 ) 713 { 714 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 715 } 716 else 717 nRes = static_cast<sal_uInt64>(rtl::math::round( d )); 718 } 719 else if( n64 < 0 ) 720 { 721 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 722 } 723 else 724 { 725 nRes = n64; 726 } 727 } 728 break; 729 case SbxOBJECT: 730 { 731 SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj ); 732 if( pVal ) 733 nRes = pVal->GetUInt64(); 734 else 735 { 736 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); nRes = 0; 737 } 738 break; 739 } 740 741 case SbxBYREF | SbxCHAR: 742 nRes = *p->pChar; break; 743 case SbxBYREF | SbxBYTE: 744 nRes = *p->pByte; break; 745 case SbxBYREF | SbxINTEGER: 746 case SbxBYREF | SbxBOOL: 747 nRes = *p->pInteger; break; 748 case SbxBYREF | SbxLONG: 749 nRes = *p->pLong; break; 750 case SbxBYREF | SbxULONG: 751 nRes = *p->pULong; break; 752 case SbxBYREF | SbxSALUINT64: 753 nRes = *p->puInt64; break; 754 755 // from here on the value has to be checked 756 case SbxBYREF | SbxERROR: 757 case SbxBYREF | SbxUSHORT: 758 aTmp.nUShort = *p->pUShort; goto ref; 759 case SbxBYREF | SbxSINGLE: 760 aTmp.nSingle = *p->pSingle; goto ref; 761 case SbxBYREF | SbxDATE: 762 case SbxBYREF | SbxDOUBLE: 763 aTmp.nDouble = *p->pDouble; goto ref; 764 case SbxBYREF | SbxCURRENCY: 765 case SbxBYREF | SbxSALINT64: 766 aTmp.nInt64 = *p->pnInt64; goto ref; 767 ref: 768 aTmp.eType = SbxDataType( p->eType & 0x0FFF ); 769 p = &aTmp; goto start; 770 771 default: 772 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); nRes = 0; 773 } 774 return nRes; 775 } 776 777 void ImpPutUInt64( SbxValues* p, sal_uInt64 n ) 778 { 779 SbxValues aTmp; 780 781 start: 782 switch( +p->eType ) 783 { 784 // Check necessary 785 case SbxCHAR: 786 aTmp.pChar = &p->nChar; goto direct; 787 case SbxBYTE: 788 aTmp.pByte = &p->nByte; goto direct; 789 case SbxINTEGER: 790 case SbxBOOL: 791 aTmp.pInteger = &p->nInteger; goto direct; 792 case SbxULONG: 793 aTmp.pULong = &p->nULong; goto direct; 794 case SbxERROR: 795 case SbxUSHORT: 796 aTmp.pUShort = &p->nUShort; goto direct; 797 case SbxLONG: 798 aTmp.pnInt64 = &p->nInt64; goto direct; 799 case SbxCURRENCY: 800 case SbxSALINT64: 801 aTmp.pnInt64 = &p->nInt64; goto direct; 802 case SbxSINGLE: 803 aTmp.pSingle = &p->nSingle; goto direct; 804 case SbxDATE: 805 case SbxDOUBLE: 806 aTmp.pDouble = &p->nDouble; goto direct; 807 808 direct: 809 aTmp.eType = SbxDataType( p->eType | SbxBYREF ); 810 p = &aTmp; goto start; 811 812 // Check not necessary 813 case SbxSALUINT64: 814 p->uInt64 = n; break; 815 816 case SbxBYREF | SbxSTRING: 817 case SbxSTRING: 818 case SbxLPSTR: 819 if( !p->pOUString ) 820 p->pOUString = new OUString; 821 if( n > SAL_MAX_INT64 ) 822 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 823 else 824 { 825 ::OString aOStr = OString::number( n ); 826 (*p->pOUString) = ::OStringToOUString( aOStr, RTL_TEXTENCODING_ASCII_US ); 827 } 828 break; 829 case SbxOBJECT: 830 { 831 SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj ); 832 if( pVal ) 833 pVal->PutUInt64( n ); 834 else 835 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); 836 break; 837 } 838 case SbxBYREF | SbxCHAR: 839 if( n > SbxMAXCHAR ) 840 { 841 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXCHAR; 842 } 843 *p->pChar = static_cast<sal_Unicode>(n); break; 844 case SbxBYREF | SbxBYTE: 845 if( n > SbxMAXBYTE ) 846 { 847 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXBYTE; 848 } 849 *p->pByte = static_cast<sal_uInt8>(n); break; 850 case SbxBYREF | SbxINTEGER: 851 case SbxBYREF | SbxBOOL: 852 if( n > SbxMAXINT ) 853 { 854 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXINT; 855 } 856 *p->pInteger = static_cast<sal_Int16>(n); break; 857 case SbxBYREF | SbxERROR: 858 case SbxBYREF | SbxUSHORT: 859 if( n > SbxMAXUINT ) 860 { 861 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXUINT; 862 } 863 *p->pUShort = static_cast<sal_uInt16>(n); break; 864 case SbxBYREF | SbxLONG: 865 if( n > SbxMAXLNG ) 866 { 867 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXLNG; 868 } 869 *p->pLong = static_cast<sal_Int32>(n); break; 870 case SbxBYREF | SbxULONG: 871 if( n > SbxMAXULNG ) 872 { 873 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXULNG; 874 } 875 *p->pULong = static_cast<sal_uInt32>(n); break; 876 case SbxBYREF | SbxSINGLE: 877 *p->pDouble = static_cast<float>(ImpSalUInt64ToDouble( n )); break; 878 case SbxBYREF | SbxDATE: 879 case SbxBYREF | SbxDOUBLE: 880 881 *p->pDouble = ImpSalUInt64ToDouble( n ); break; 882 case SbxBYREF | SbxCURRENCY: 883 if ( n > ( SAL_MAX_INT64 / CURRENCY_FACTOR ) ) 884 { 885 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); 886 n = SAL_MAX_INT64; 887 } 888 *p->pnInt64 = static_cast<sal_Int64>( n * CURRENCY_FACTOR ); break; 889 case SbxBYREF | SbxSALUINT64: 890 *p->puInt64 = n; break; 891 case SbxBYREF | SbxSALINT64: 892 if( n > SAL_MAX_INT64 ) 893 { 894 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0; 895 } 896 *p->pnInt64 = static_cast<sal_Int64>(n); break; 897 898 default: 899 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 900 } 901 } 902 903 904 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 905
