Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/helper/strhelper.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 <strhelper.hxx>
21
22
namespace  {
23
24
bool isSpace( sal_Unicode cChar )
25
17.3k
{
26
17.3k
    return
27
17.3k
        cChar == ' '    || cChar == '\t'    ||
28
15.6k
        cChar == '\r'   || cChar == '\n'    ||
29
15.6k
        cChar == 0x0c   || cChar == 0x0b;
30
17.3k
}
31
32
bool isProtect( sal_Unicode cChar )
33
1
{
34
1
    return cChar == '`' || cChar == '\'' || cChar == '"';
35
1
}
36
37
void CopyUntil( char*& pTo, const char*& pFrom, char cUntil, bool bIncludeUntil = false )
38
0
{
39
0
    do
40
0
    {
41
0
        if( *pFrom == '\\' )
42
0
        {
43
0
            pFrom++;
44
0
            if( *pFrom )
45
0
            {
46
0
                *pTo = *pFrom;
47
0
                pTo++;
48
0
            }
49
0
        }
50
0
        else if( bIncludeUntil || ! isProtect( *pFrom ) )
51
0
        {
52
0
            *pTo = *pFrom;
53
0
            pTo++;
54
0
        }
55
0
        pFrom++;
56
0
    } while( *pFrom && *pFrom != cUntil );
57
    // copy the terminating character unless zero or protector
58
0
    if( ! isProtect( *pFrom ) || bIncludeUntil )
59
0
    {
60
0
        *pTo = *pFrom;
61
0
        if( *pTo )
62
0
            pTo++;
63
0
    }
64
0
    if( *pFrom )
65
0
        pFrom++;
66
0
}
67
68
void CopyUntil( sal_Unicode*& pTo, const sal_Unicode*& pFrom, sal_Unicode cUntil, bool bIncludeUntil = false )
69
1
{
70
1
    do
71
16
    {
72
16
        if( *pFrom == '\\' )
73
0
        {
74
0
            pFrom++;
75
0
            if( *pFrom )
76
0
            {
77
0
                *pTo = *pFrom;
78
0
                pTo++;
79
0
            }
80
0
        }
81
16
        else if( bIncludeUntil || ! isProtect( *pFrom ) )
82
16
        {
83
16
            *pTo = *pFrom;
84
16
            pTo++;
85
16
        }
86
16
        if( *pFrom )
87
16
            pFrom++;
88
16
    } while( *pFrom && *pFrom != cUntil );
89
    // copy the terminating character unless zero or protector
90
1
    if( ! isProtect( *pFrom ) || bIncludeUntil )
91
1
    {
92
1
        *pTo = *pFrom;
93
1
        if( *pTo )
94
1
            pTo++;
95
1
    }
96
1
    if( *pFrom )
97
1
        pFrom++;
98
1
}
99
100
}
101
102
namespace psp {
103
104
OUString GetCommandLineToken( int nToken, const OUString& rLine )
105
0
{
106
0
    sal_Int32 nLen = rLine.getLength();
107
0
    if( ! nLen )
108
0
        return OUString();
109
110
0
    int nActualToken = 0;
111
0
    sal_Unicode* pBuffer = static_cast<sal_Unicode*>(alloca( sizeof(sal_Unicode)*( nLen + 1 ) ));
112
0
    const sal_Unicode* pRun = rLine.getStr();
113
0
    sal_Unicode* pLeap = nullptr;
114
115
0
    while( *pRun && nActualToken <= nToken )
116
0
    {
117
0
        while( *pRun && isSpace( *pRun ) )
118
0
            pRun++;
119
0
        pLeap = pBuffer;
120
0
        while( *pRun && ! isSpace( *pRun ) )
121
0
        {
122
0
            if( *pRun == '\\' )
123
0
            {
124
                // escapement
125
0
                pRun++;
126
0
                *pLeap = *pRun;
127
0
                pLeap++;
128
0
                if( *pRun )
129
0
                    pRun++;
130
0
            }
131
0
            else if( *pRun == '`' )
132
0
                CopyUntil( pLeap, pRun, '`' );
133
0
            else if( *pRun == '\'' )
134
0
                CopyUntil( pLeap, pRun, '\'' );
135
0
            else if( *pRun == '"' )
136
0
                CopyUntil( pLeap, pRun, '"' );
137
0
            else
138
0
            {
139
0
                *pLeap = *pRun;
140
0
                pLeap++;
141
0
                pRun++;
142
0
            }
143
0
        }
144
0
        if( nActualToken != nToken )
145
0
            pBuffer[0] = 0;
146
0
        nActualToken++;
147
0
    }
148
149
0
    assert(pLeap && "otherwise would early return");
150
0
    *pLeap = 0;
151
152
0
    return OUString(pBuffer);
153
0
}
154
155
OString GetCommandLineToken(int nToken, const OString& rLine)
156
0
{
157
0
    sal_Int32 nLen = rLine.getLength();
158
0
    if (!nLen)
159
0
        return rLine;
160
161
0
    int nActualToken = 0;
162
0
    char* pBuffer = static_cast<char*>(alloca( nLen + 1 ));
163
0
    const char* pRun = rLine.getStr();
164
0
    char* pLeap = nullptr;
165
166
0
    while( *pRun && nActualToken <= nToken )
167
0
    {
168
0
        while( *pRun && isSpace( *pRun ) )
169
0
            pRun++;
170
0
        pLeap = pBuffer;
171
0
        while( *pRun && ! isSpace( *pRun ) )
172
0
        {
173
0
            if( *pRun == '\\' )
174
0
            {
175
                // escapement
176
0
                pRun++;
177
0
                *pLeap = *pRun;
178
0
                pLeap++;
179
0
                if( *pRun )
180
0
                    pRun++;
181
0
            }
182
0
            else if( *pRun == '`' )
183
0
                CopyUntil( pLeap, pRun, '`' );
184
0
            else if( *pRun == '\'' )
185
0
                CopyUntil( pLeap, pRun, '\'' );
186
0
            else if( *pRun == '"' )
187
0
                CopyUntil( pLeap, pRun, '"' );
188
0
            else
189
0
            {
190
0
                *pLeap = *pRun;
191
0
                pLeap++;
192
0
                pRun++;
193
0
            }
194
0
        }
195
0
        if( nActualToken != nToken )
196
0
            pBuffer[0] = 0;
197
0
        nActualToken++;
198
0
    }
199
200
0
    assert(pLeap && "otherwise would early return");
201
0
    *pLeap = 0;
202
203
0
    return pBuffer;
204
0
}
205
206
int GetCommandLineTokenCount(const OUString& rLine)
207
0
{
208
0
    if (rLine.isEmpty())
209
0
        return 0;
210
211
0
    int nTokenCount = 0;
212
0
    const sal_Unicode *pRun = rLine.getStr();
213
214
0
    while( *pRun )
215
0
    {
216
0
        while( *pRun && isSpace( *pRun ) )
217
0
            pRun++;
218
0
        if( ! *pRun )
219
0
            break;
220
0
        while( *pRun && ! isSpace( *pRun ) )
221
0
        {
222
0
            if( *pRun == '\\' )
223
0
            {
224
                // escapement
225
0
                pRun++;
226
0
                if( *pRun )
227
0
                    pRun++;
228
0
            }
229
0
            else if( *pRun == '`' )
230
0
            {
231
0
                do pRun++; while( *pRun && *pRun != '`' );
232
0
                if( *pRun )
233
0
                    pRun++;
234
0
            }
235
0
            else if( *pRun == '\'' )
236
0
            {
237
0
                do pRun++; while( *pRun && *pRun != '\'' );
238
0
                if( *pRun )
239
0
                    pRun++;
240
0
            }
241
0
            else if( *pRun == '"' )
242
0
            {
243
0
                do pRun++; while( *pRun && *pRun != '"' );
244
0
                if( *pRun )
245
0
                    pRun++;
246
0
            }
247
0
            else
248
0
                pRun++;
249
0
        }
250
0
        nTokenCount++;
251
0
    }
252
253
0
    return nTokenCount;
254
0
}
255
256
OUString WhitespaceToSpace( std::u16string_view rLine )
257
571
{
258
571
    size_t nLen = rLine.size();
259
571
    if( ! nLen )
260
0
        return OUString();
261
262
571
    sal_Unicode *pBuffer = static_cast<sal_Unicode*>(alloca( sizeof(sal_Unicode)*(nLen + 1) ));
263
571
    const sal_Unicode *pRun = rLine.data();
264
571
    const sal_Unicode * const pEnd = rLine.data() + rLine.size();
265
571
    sal_Unicode *pLeap = pBuffer;
266
267
1.98k
    while( pRun != pEnd )
268
1.41k
    {
269
1.41k
        if( isSpace( *pRun ) )
270
841
        {
271
841
            *pLeap = ' ';
272
841
            pLeap++;
273
841
            pRun++;
274
841
        }
275
1.41k
        while( pRun != pEnd && isSpace( *pRun ) )
276
0
            pRun++;
277
15.0k
        while( pRun != pEnd && ! isSpace( *pRun ) )
278
13.6k
        {
279
13.6k
            if( *pRun == '\\' )
280
0
            {
281
                // escapement
282
0
                pRun++;
283
0
                *pLeap = *pRun;
284
0
                pLeap++;
285
0
                if( pRun != pEnd )
286
0
                    pRun++;
287
0
            }
288
13.6k
            else if( *pRun == '`' )
289
0
                CopyUntil( pLeap, pRun, '`', true );
290
13.6k
            else if( *pRun == '\'' )
291
0
                CopyUntil( pLeap, pRun, '\'', true );
292
13.6k
            else if( *pRun == '"' )
293
1
                CopyUntil( pLeap, pRun, '"', true );
294
13.6k
            else
295
13.6k
            {
296
13.6k
                *pLeap = *pRun;
297
13.6k
                ++pLeap;
298
13.6k
                ++pRun;
299
13.6k
            }
300
13.6k
        }
301
1.41k
    }
302
303
571
    *pLeap = 0;
304
305
    // there might be a space at beginning or end
306
571
    if (pLeap > pBuffer)
307
571
    {
308
571
        pLeap--;
309
571
        if( *pLeap == ' ' )
310
0
            *pLeap = 0;
311
571
    }
312
313
571
    return OUString(*pBuffer == ' ' ? pBuffer+1 : pBuffer);
314
571
}
315
316
OString WhitespaceToSpace(std::string_view rLine)
317
0
{
318
0
    size_t nLen = rLine.size();
319
0
    if (!nLen)
320
0
        return OString();
321
322
0
    char *pBuffer = static_cast<char*>(alloca( nLen + 1 ));
323
0
    const char *pRun = rLine.data();
324
0
    const char * const pEnd = rLine.data() + rLine.size();
325
0
    char *pLeap = pBuffer;
326
327
0
    while( pRun != pEnd )
328
0
    {
329
0
        if( isSpace( *pRun ) )
330
0
        {
331
0
            *pLeap = ' ';
332
0
            pLeap++;
333
0
            pRun++;
334
0
        }
335
0
        while( pRun != pEnd && isSpace( *pRun ) )
336
0
            pRun++;
337
0
        while( pRun != pEnd && ! isSpace( *pRun ) )
338
0
        {
339
0
            if( *pRun == '\\' )
340
0
            {
341
                // escapement
342
0
                pRun++;
343
0
                *pLeap = *pRun;
344
0
                pLeap++;
345
0
                if( pRun != pEnd )
346
0
                    pRun++;
347
0
            }
348
0
            else if( *pRun == '`' )
349
0
                CopyUntil( pLeap, pRun, '`', true );
350
0
            else if( *pRun == '\'' )
351
0
                CopyUntil( pLeap, pRun, '\'', true );
352
0
            else if( *pRun == '"' )
353
0
                CopyUntil( pLeap, pRun, '"', true );
354
0
            else
355
0
            {
356
0
                *pLeap = *pRun;
357
0
                ++pLeap;
358
0
                ++pRun;
359
0
            }
360
0
        }
361
0
    }
362
363
0
    *pLeap = 0;
364
365
    // there might be a space at beginning or end
366
0
    assert(pLeap > pBuffer);
367
0
    pLeap--;
368
#if defined(__GNUC__) && __GNUC__ >= 12 && __GNUC__ <= 15
369
#pragma GCC diagnostic push
370
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
371
#endif
372
0
    if( *pLeap == ' ' )
373
0
        *pLeap = 0;
374
#if defined(__GNUC__) && __GNUC__ >= 12 && __GNUC__ <= 15
375
#pragma GCC diagnostic pop
376
#endif
377
0
    return *pBuffer == ' ' ? pBuffer+1 : pBuffer;
378
0
}
379
380
} // namespace
381
382
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */