xref: /core/basic/source/sbx/sbxuint.cxx (revision 4fdc90c5)
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