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