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 sal_uInt16 ImpGetUShort( const SbxValues* p ) 28 { 29 SbxValues aTmp; 30 sal_uInt16 nRes; 31 start: 32 switch( +p->eType ) 33 { 34 case SbxNULL: 35 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 36 [[fallthrough]]; 37 case SbxEMPTY: 38 nRes = 0; break; 39 case SbxCHAR: 40 nRes = p->nChar; 41 break; 42 case SbxBYTE: 43 nRes = p->nByte; break; 44 case SbxINTEGER: 45 case SbxBOOL: 46 if( p->nInteger < 0 ) 47 { 48 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 49 } 50 else 51 nRes = p->nInteger; 52 break; 53 case SbxERROR: 54 case SbxUSHORT: 55 nRes = p->nUShort; 56 break; 57 case SbxLONG: 58 if( p->nLong > SbxMAXUINT ) 59 { 60 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXUINT; 61 } 62 else if( p->nLong < 0 ) 63 { 64 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 65 } 66 else 67 nRes = static_cast<sal_uInt16>(p->nLong); 68 break; 69 case SbxULONG: 70 if( p->nULong > SbxMAXUINT ) 71 { 72 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXUINT; 73 } 74 else 75 nRes = static_cast<sal_uInt16>(p->nULong); 76 break; 77 case SbxCURRENCY: 78 if( p->nInt64 / CURRENCY_FACTOR > SbxMAXUINT ) 79 { 80 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXUINT; 81 } 82 else if( p->nInt64 < 0 ) 83 { 84 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 85 } 86 else 87 nRes = static_cast<sal_uInt16>(p->nInt64 / CURRENCY_FACTOR); 88 break; 89 case SbxSALINT64: 90 if( p->nInt64 > SbxMAXUINT ) 91 { 92 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXUINT; 93 } 94 else if( p->nInt64 < 0 ) 95 { 96 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 97 } 98 else 99 nRes = static_cast<sal_uInt16>(p->nInt64); 100 break; 101 case SbxSALUINT64: 102 if( p->uInt64 > SbxMAXUINT ) 103 { 104 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXUINT; 105 } 106 else 107 nRes = static_cast<sal_uInt16>(p->uInt64); 108 break; 109 case SbxSINGLE: 110 if( !o3tl::convertsToAtMost(o3tl::roundAway(p->nSingle), SbxMAXUINT) ) 111 { 112 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXUINT; 113 } 114 else if( p->nSingle < 0 ) 115 { 116 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 117 } 118 else 119 nRes = static_cast<sal_uInt16>( p->nSingle + 0.5 ); 120 break; 121 case SbxDATE: 122 case SbxDOUBLE: 123 case SbxDECIMAL: 124 case SbxBYREF | SbxDECIMAL: 125 { 126 double dVal; 127 if( p->eType == SbxDECIMAL ) 128 { 129 dVal = 0.0; 130 if( p->pDecimal ) 131 p->pDecimal->getDouble( dVal ); 132 } 133 else 134 dVal = p->nDouble; 135 136 if( !o3tl::convertsToAtMost(o3tl::roundAway(dVal), SbxMAXUINT) ) 137 { 138 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXUINT; 139 } 140 else if( dVal < 0 ) 141 { 142 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 143 } 144 else 145 nRes = static_cast<sal_uInt16>( dVal + 0.5 ); 146 break; 147 } 148 case SbxBYREF | SbxSTRING: 149 case SbxSTRING: 150 case SbxLPSTR: 151 if( !p->pOUString ) 152 nRes = 0; 153 else 154 { 155 double d; 156 SbxDataType t; 157 if( ImpScan( *p->pOUString, d, t, nullptr, true ) != ERRCODE_NONE ) 158 nRes = 0; 159 else if( !o3tl::convertsToAtMost(o3tl::roundAway(d), SbxMAXUINT) ) 160 { 161 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = SbxMAXUINT; 162 } 163 else if( d < 0 ) 164 { 165 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); nRes = 0; 166 } 167 else 168 nRes = static_cast<sal_uInt16>( d + 0.5 ); 169 } 170 break; 171 case SbxOBJECT: 172 { 173 SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj ); 174 if( pVal ) 175 nRes = pVal->GetUShort(); 176 else 177 { 178 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); nRes = 0; 179 } 180 break; 181 } 182 183 case SbxBYREF | SbxBYTE: 184 nRes = *p->pByte; break; 185 case SbxBYREF | SbxERROR: 186 case SbxBYREF | SbxUSHORT: 187 nRes = *p->pUShort; break; 188 189 // from here on will be tested 190 case SbxBYREF | SbxCHAR: 191 aTmp.nChar = *p->pChar; goto ref; 192 case SbxBYREF | SbxINTEGER: 193 case SbxBYREF | SbxBOOL: 194 aTmp.nInteger = *p->pInteger; goto ref; 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 | SbxSINGLE: 200 aTmp.nSingle = *p->pSingle; goto ref; 201 case SbxBYREF | SbxDATE: 202 case SbxBYREF | SbxDOUBLE: 203 aTmp.nDouble = *p->pDouble; goto ref; 204 case SbxBYREF | SbxCURRENCY: 205 case SbxBYREF | SbxSALINT64: 206 aTmp.nInt64 = *p->pnInt64; goto ref; 207 case SbxBYREF | SbxSALUINT64: 208 aTmp.uInt64 = *p->puInt64; goto ref; 209 ref: 210 aTmp.eType = SbxDataType( p->eType & 0x0FFF ); 211 p = &aTmp; goto start; 212 213 default: 214 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); nRes = 0; 215 } 216 return nRes; 217 } 218 219 void ImpPutUShort( SbxValues* p, sal_uInt16 n ) 220 { 221 SbxValues aTmp; 222 223 start: 224 switch( +p->eType ) 225 { 226 case SbxERROR: 227 case SbxUSHORT: 228 p->nUShort = n; break; 229 case SbxLONG: 230 p->nLong = n; break; 231 case SbxULONG: 232 p->nULong = n; break; 233 case SbxSINGLE: 234 p->nSingle = n; break; 235 case SbxDATE: 236 case SbxDOUBLE: 237 p->nDouble = n; break; 238 case SbxCURRENCY: 239 p->nInt64 = n * CURRENCY_FACTOR; break; 240 case SbxSALINT64: 241 p->nInt64 = n; break; 242 case SbxSALUINT64: 243 p->uInt64 = n; break; 244 case SbxDECIMAL: 245 case SbxBYREF | SbxDECIMAL: 246 ImpCreateDecimal( p )->setUInt( n ); 247 break; 248 249 // from here on tests 250 case SbxCHAR: 251 aTmp.pChar = &p->nChar; goto direct; 252 case SbxBYTE: 253 aTmp.pByte = &p->nByte; goto direct; 254 case SbxINTEGER: 255 case SbxBOOL: 256 aTmp.pInteger = &p->nInteger; 257 direct: 258 aTmp.eType = SbxDataType( p->eType | SbxBYREF ); 259 p = &aTmp; goto start; 260 261 case SbxBYREF | SbxSTRING: 262 case SbxSTRING: 263 case SbxLPSTR: 264 if( !p->pOUString ) 265 p->pOUString = new OUString; 266 ImpCvtNum( static_cast<double>(n), 0, *p->pOUString ); 267 break; 268 case SbxOBJECT: 269 { 270 SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj ); 271 if( pVal ) 272 pVal->PutUShort( n ); 273 else 274 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); 275 break; 276 } 277 278 case SbxBYREF | SbxCHAR: 279 *p->pChar = static_cast<sal_Unicode>(n); break; 280 case SbxBYREF | SbxBYTE: 281 if( n > SbxMAXBYTE ) 282 { 283 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXBYTE; 284 } 285 *p->pByte = static_cast<sal_uInt8>(n); break; 286 case SbxBYREF | SbxINTEGER: 287 case SbxBYREF | SbxBOOL: 288 if( n > SbxMAXINT ) 289 { 290 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXINT; 291 } 292 *p->pInteger = static_cast<sal_Int16>(n); break; 293 case SbxBYREF | SbxERROR: 294 case SbxBYREF | SbxUSHORT: 295 *p->pUShort = n; break; 296 case SbxBYREF | SbxLONG: 297 *p->pLong = n; break; 298 case SbxBYREF | SbxULONG: 299 *p->pULong = n; break; 300 case SbxBYREF | SbxSINGLE: 301 *p->pSingle = n; break; 302 case SbxBYREF | SbxDATE: 303 case SbxBYREF | SbxDOUBLE: 304 *p->pDouble = n; break; 305 case SbxBYREF | SbxCURRENCY: 306 *p->pnInt64 = n * CURRENCY_FACTOR; break; 307 case SbxBYREF | SbxSALINT64: 308 *p->pnInt64 = n; break; 309 case SbxBYREF | SbxSALUINT64: 310 *p->puInt64 = n; break; 311 312 default: 313 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); 314 } 315 } 316 317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 318
