xref: /core/basic/source/sbx/sbxint.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 #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