Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/basic/source/sbx/sbxstr.cxx
Line
Count
Source
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 <config_features.h>
21
22
#include <basic/sbx.hxx>
23
#include "sbxconv.hxx"
24
#include "sbxres.hxx"
25
#include <runtime.hxx>
26
#include <rtl/ustrbuf.hxx>
27
#include <memory>
28
29
// The conversion of an item onto String was handled via the Put-Methods
30
// of the several data types to avoid duplicated code.
31
32
OUString ImpGetString( const SbxValues* p )
33
0
{
34
0
    SbxValues aTmp;
35
0
    OUString aRes;
36
0
    aTmp.eType = SbxSTRING;
37
0
    aTmp.pOUString = &aRes;
38
0
    switch( +p->eType )
39
0
    {
40
0
        case SbxNULL:
41
0
            SbxBase::SetError( ERRCODE_BASIC_CONVERSION );
42
0
            [[fallthrough]];
43
0
        case SbxEMPTY:
44
0
            break;
45
0
        case SbxCHAR:
46
0
            ImpPutChar( &aTmp, p->nChar ); break;
47
0
        case SbxBYTE:
48
0
            ImpPutByte( &aTmp, p->nByte ); break;
49
0
        case SbxINTEGER:
50
0
            ImpPutInteger( &aTmp, p->nInteger ); break;
51
0
        case SbxBOOL:
52
0
            ImpPutBool( &aTmp, p->nUShort ); break;
53
0
        case SbxUSHORT:
54
0
            ImpPutUShort( &aTmp, p->nUShort ); break;
55
0
        case SbxLONG:
56
0
            ImpPutLong( &aTmp, p->nLong ); break;
57
0
        case SbxULONG:
58
0
            ImpPutULong( &aTmp, p->nULong ); break;
59
0
        case SbxSINGLE:
60
0
            ImpPutSingle( &aTmp, p->nSingle ); break;
61
0
        case SbxDOUBLE:
62
0
            ImpPutDouble( &aTmp, p->nDouble ); break;
63
0
        case SbxCURRENCY:
64
0
            ImpPutCurrency( &aTmp, p->nInt64 ); break;
65
0
        case SbxDECIMAL:
66
0
        case SbxBYREF | SbxDECIMAL:
67
0
            ImpPutDecimal( &aTmp, p->pDecimal ); break;
68
0
        case SbxSALINT64:
69
0
            ImpPutInt64( &aTmp, p->nInt64 ); break;
70
0
        case SbxSALUINT64:
71
0
            ImpPutUInt64( &aTmp, p->uInt64 ); break;
72
0
        case SbxBYREF | SbxSTRING:
73
0
        case SbxSTRING:
74
0
        case SbxLPSTR:
75
0
            if ( p->pOUString )
76
0
            {
77
0
                *aTmp.pOUString = *p->pOUString;
78
0
            }
79
0
            break;
80
0
        case SbxOBJECT:
81
0
        {
82
0
            SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj );
83
0
            if( pVal )
84
0
            {
85
0
                aRes = pVal->GetOUString();
86
0
            }
87
0
            else if( p->pObj && p->pObj->IsFixed()
88
0
                    && (p->pObj->GetType() == (SbxARRAY | SbxBYTE )) )
89
0
            {
90
                // convert byte array to string
91
0
                SbxArray* pArr = dynamic_cast<SbxArray*>( p->pObj );
92
0
                if( pArr )
93
0
                {
94
0
                    aRes = ByteArrayToString( pArr );
95
0
                }
96
0
            }
97
0
            else
98
0
            {
99
0
                SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT );
100
0
            }
101
0
            break;
102
0
        }
103
0
        case SbxERROR:
104
            // Here the String "Error n" is generated
105
0
            aRes = GetSbxRes( StringId::ErrorMsg ) + OUString::number(p->nUShort);
106
0
            break;
107
0
        case SbxDATE:
108
0
            ImpPutDate( &aTmp, p->nDouble ); break;
109
110
0
        case SbxBYREF | SbxCHAR:
111
0
            ImpPutChar( &aTmp, *p->pChar ); break;
112
0
        case SbxBYREF | SbxBYTE:
113
0
            ImpPutByte( &aTmp, *p->pByte ); break;
114
0
        case SbxBYREF | SbxINTEGER:
115
0
        case SbxBYREF | SbxBOOL:
116
0
            ImpPutInteger( &aTmp, *p->pInteger ); break;
117
0
        case SbxBYREF | SbxLONG:
118
0
            ImpPutLong( &aTmp, *p->pLong ); break;
119
0
        case SbxBYREF | SbxULONG:
120
0
            ImpPutULong( &aTmp, *p->pULong ); break;
121
0
        case SbxBYREF | SbxERROR:
122
0
        case SbxBYREF | SbxUSHORT:
123
0
            ImpPutUShort( &aTmp, *p->pUShort ); break;
124
0
        case SbxBYREF | SbxSINGLE:
125
0
            ImpPutSingle( &aTmp, *p->pSingle ); break;
126
0
        case SbxBYREF | SbxDATE:
127
0
        case SbxBYREF | SbxDOUBLE:
128
0
            ImpPutDouble( &aTmp, *p->pDouble ); break;
129
0
        case SbxBYREF | SbxCURRENCY:
130
0
            ImpPutCurrency( &aTmp, *p->pnInt64 ); break;
131
0
        case SbxBYREF | SbxSALINT64:
132
0
            ImpPutInt64( &aTmp, *p->pnInt64 ); break;
133
0
        case SbxBYREF | SbxSALUINT64:
134
0
            ImpPutUInt64( &aTmp, *p->puInt64 ); break;
135
0
        default:
136
0
            SbxBase::SetError( ERRCODE_BASIC_CONVERSION );
137
0
    }
138
0
    return aRes;
139
0
}
140
141
// From 1997-04-10, new function for SbxValue::GetCoreString()
142
OUString ImpGetCoreString( const SbxValues* p )
143
0
{
144
    // For now only for double
145
0
    if( ( p->eType & (~SbxBYREF) ) == SbxDOUBLE )
146
0
    {
147
0
        SbxValues aTmp;
148
0
        OUString aRes;
149
0
        aTmp.eType = SbxSTRING;
150
0
        aTmp.pOUString = &aRes;
151
0
        if( p->eType == SbxDOUBLE )
152
0
            ImpPutDouble( &aTmp, p->nDouble, true );    // true = bCoreString
153
0
        else
154
0
            ImpPutDouble( &aTmp, *p->pDouble, true );   // true = bCoreString
155
0
        return aRes;
156
0
    }
157
0
    else
158
0
        return ImpGetString( p );
159
0
}
160
161
void ImpPutString( SbxValues* p, const OUString* n )
162
5.19k
{
163
5.19k
    SbxValues aTmp;
164
5.19k
    aTmp.eType = SbxSTRING;
165
5.19k
    std::unique_ptr<OUString> pTmp;
166
    // as a precaution, if a NULL-Ptr appears
167
5.19k
    if( !n )
168
0
    {
169
0
        pTmp.reset(new OUString);
170
0
        n = pTmp.get();
171
0
    }
172
5.19k
    aTmp.pOUString = const_cast<OUString*>(n);
173
5.19k
    switch( +p->eType )
174
5.19k
    {
175
0
        case SbxCHAR:
176
0
            p->nChar = ImpGetChar( &aTmp ); break;
177
0
        case SbxBYTE:
178
0
            p->nByte = ImpGetByte( &aTmp ); break;
179
0
        case SbxINTEGER:
180
0
        case SbxBOOL:
181
0
            p->nInteger = ImpGetInteger( &aTmp ); break;
182
0
        case SbxLONG:
183
0
            p->nLong = ImpGetLong( &aTmp ); break;
184
0
        case SbxULONG:
185
0
            p->nULong = ImpGetULong( &aTmp ); break;
186
0
        case SbxERROR:
187
0
        case SbxUSHORT:
188
0
            p->nUShort = ImpGetUShort( &aTmp ); break;
189
0
        case SbxSINGLE:
190
0
            p->nSingle = ImpGetSingle( &aTmp ); break;
191
0
        case SbxDATE:
192
0
            p->nDouble = ImpGetDate( &aTmp ); break;
193
0
        case SbxDOUBLE:
194
0
            p->nDouble = ImpGetDouble( &aTmp ); break;
195
0
        case SbxCURRENCY:
196
0
            p->nInt64 = ImpGetCurrency( &aTmp ); break;
197
0
        case SbxDECIMAL:
198
0
        case SbxBYREF | SbxDECIMAL:
199
0
            releaseDecimalPtr( p->pDecimal );
200
0
            p->pDecimal = ImpGetDecimal( &aTmp ); break;
201
0
        case SbxSALINT64:
202
0
            p->nInt64 = ImpGetInt64( &aTmp ); break;
203
0
        case SbxSALUINT64:
204
0
            p->uInt64 = ImpGetUInt64( &aTmp ); break;
205
206
0
        case SbxBYREF | SbxSTRING:
207
5.19k
        case SbxSTRING:
208
5.19k
        case SbxLPSTR:
209
5.19k
            if( !n->isEmpty() )
210
2
            {
211
2
                if( !p->pOUString )
212
2
                    p->pOUString = new OUString( *n );
213
0
                else
214
0
                    *p->pOUString = *n;
215
2
            }
216
5.19k
            else
217
5.19k
            {
218
5.19k
                delete p->pOUString;
219
5.19k
                p->pOUString = nullptr;
220
5.19k
            }
221
5.19k
            break;
222
0
        case SbxOBJECT:
223
0
        {
224
0
            SbxValue* pVal = dynamic_cast<SbxValue*>( p->pObj );
225
0
            if( pVal )
226
0
                pVal->PutString( *n );
227
0
            else
228
0
                SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT );
229
0
            break;
230
5.19k
        }
231
0
        case SbxBYREF | SbxCHAR:
232
0
            *p->pChar = ImpGetChar( p ); break;
233
0
        case SbxBYREF | SbxBYTE:
234
0
            *p->pByte = ImpGetByte( p ); break;
235
0
        case SbxBYREF | SbxINTEGER:
236
0
            *p->pInteger = ImpGetInteger( p ); break;
237
0
        case SbxBYREF | SbxBOOL:
238
0
            *p->pUShort = sal::static_int_cast< sal_uInt16 >( ImpGetBool( p ) );
239
0
            break;
240
0
        case SbxBYREF | SbxERROR:
241
0
        case SbxBYREF | SbxUSHORT:
242
0
            *p->pUShort = ImpGetUShort( p ); break;
243
0
        case SbxBYREF | SbxLONG:
244
0
            *p->pLong = ImpGetLong( p ); break;
245
0
        case SbxBYREF | SbxULONG:
246
0
            *p->pULong = ImpGetULong( p ); break;
247
0
        case SbxBYREF | SbxSINGLE:
248
0
            *p->pSingle = ImpGetSingle( p ); break;
249
0
        case SbxBYREF | SbxDATE:
250
0
            *p->pDouble = ImpGetDate( p ); break;
251
0
        case SbxBYREF | SbxDOUBLE:
252
0
            *p->pDouble = ImpGetDouble( p ); break;
253
0
        case SbxBYREF | SbxCURRENCY:
254
0
            *p->pnInt64 = ImpGetCurrency( p ); break;
255
0
        case SbxBYREF | SbxSALINT64:
256
0
            *p->pnInt64 = ImpGetInt64( p ); break;
257
0
        case SbxBYREF | SbxSALUINT64:
258
0
            *p->puInt64 = ImpGetUInt64( p ); break;
259
0
        default:
260
0
            SbxBase::SetError( ERRCODE_BASIC_CONVERSION );
261
5.19k
    }
262
5.19k
}
263
264
265
// Convert string to an array of bytes, preserving unicode (2bytes per character)
266
SbxArray* StringToByteArray(const OUString& rStr)
267
0
{
268
0
    sal_Int32 nArraySize = rStr.getLength() * 2;
269
0
    const sal_Unicode* pSrc = rStr.getStr();
270
0
    SbxDimArray* pArray = new SbxDimArray(SbxBYTE);
271
0
    if( nArraySize )
272
0
    {
273
0
#if !HAVE_FEATURE_SCRIPTING
274
0
        bool bIncIndex = false;
275
#else
276
        bool bIncIndex = IsBaseIndexOne();
277
#endif
278
0
        if( bIncIndex )
279
0
            pArray->AddDim(1, nArraySize);
280
0
        else
281
0
            pArray->AddDim(0, nArraySize - 1);
282
0
    }
283
0
    else
284
0
    {
285
0
        pArray->unoAddDim(0, -1);
286
0
    }
287
288
0
    for( sal_Int32 i=0; i< nArraySize; i++)
289
0
    {
290
0
        SbxVariable* pNew = new SbxVariable( SbxBYTE );
291
0
        sal_uInt8 aByte = static_cast< sal_uInt8 >( (i%2) ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff );
292
0
        pNew->PutByte( aByte );
293
0
        pNew->SetFlag( SbxFlagBits::Write );
294
0
        pArray->Put(pNew, i);
295
0
        if( i%2 )
296
0
            pSrc++;
297
0
    }
298
0
    return pArray;
299
0
}
300
301
// Convert an array of bytes to string (2bytes per character)
302
OUString ByteArrayToString(SbxArray* pArr)
303
0
{
304
0
    sal_uInt32 nCount = pArr->Count();
305
0
    OUStringBuffer aStrBuf((nCount + 1) / 2);
306
0
    sal_Unicode aChar = 0;
307
0
    for( sal_uInt32 i = 0 ; i < nCount ; i++ )
308
0
    {
309
0
        sal_Unicode aTempChar = pArr->Get(i)->GetByte();
310
0
        if( i%2 )
311
0
        {
312
0
            aChar = (aTempChar << 8 ) | aChar;
313
0
            aStrBuf.append(aChar);
314
0
            aChar = 0;
315
0
        }
316
0
        else
317
0
        {
318
0
            aChar = aTempChar;
319
0
        }
320
0
    }
321
322
0
    if( nCount%2 )
323
0
    {
324
0
        aStrBuf.append(aChar);
325
0
    }
326
327
0
    return aStrBuf.makeStringAndClear();
328
0
}
329
330
331
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */