Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/i18npool/source/characterclassification/cclass_unicode_parser.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
21
#include <algorithm>
22
23
#include <cclass_unicode.hxx>
24
#include <unicode/uchar.h>
25
#include <rtl/character.hxx>
26
#include <rtl/math.hxx>
27
#include <rtl/ustring.hxx>
28
#include <sal/log.hxx>
29
#include <com/sun/star/i18n/KParseTokens.hpp>
30
#include <com/sun/star/i18n/KParseType.hpp>
31
#include <com/sun/star/i18n/LocaleData2.hpp>
32
#include <com/sun/star/i18n/NativeNumberMode.hpp>
33
#include <com/sun/star/i18n/NativeNumberSupplier.hpp>
34
35
#include <string.h>
36
#include <string_view>
37
38
using namespace ::com::sun::star::uno;
39
using namespace ::com::sun::star::i18n;
40
using namespace ::com::sun::star::lang;
41
42
62.3k
#define TOKEN_DIGIT_FLAGS (ParserFlags::CHAR_VALUE | ParserFlags::VALUE | ParserFlags::VALUE_EXP | ParserFlags::VALUE_EXP_VALUE | ParserFlags::VALUE_DIGIT)
43
44
namespace i18npool {
45
46
// Default identifier/name specification is [A-Za-z_][A-Za-z0-9_]*
47
48
const sal_uInt8 cclass_Unicode::nDefCnt = 128;
49
const ParserFlags cclass_Unicode::pDefaultParserTable[ nDefCnt ] =
50
{
51
// (...) == Calc formula compiler specific, commented out and modified
52
53
    /* \0 */    ParserFlags::EXCLUDED,
54
                ParserFlags::ILLEGAL,
55
                ParserFlags::ILLEGAL,
56
                ParserFlags::ILLEGAL,
57
                ParserFlags::ILLEGAL,
58
                ParserFlags::ILLEGAL,
59
                ParserFlags::ILLEGAL,
60
                ParserFlags::ILLEGAL,
61
                ParserFlags::ILLEGAL,
62
    /*  9 \t */ ParserFlags::CHAR_DONTCARE | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,     // (ParserFlags::ILLEGAL)
63
                ParserFlags::ILLEGAL,
64
    /* 11 \v */ ParserFlags::CHAR_DONTCARE | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,     // (ParserFlags::ILLEGAL)
65
                ParserFlags::ILLEGAL,
66
                ParserFlags::ILLEGAL,
67
                ParserFlags::ILLEGAL,
68
                ParserFlags::ILLEGAL,
69
                ParserFlags::ILLEGAL,
70
                ParserFlags::ILLEGAL,
71
                ParserFlags::ILLEGAL,
72
                ParserFlags::ILLEGAL,
73
                ParserFlags::ILLEGAL,
74
                ParserFlags::ILLEGAL,
75
                ParserFlags::ILLEGAL,
76
                ParserFlags::ILLEGAL,
77
                ParserFlags::ILLEGAL,
78
                ParserFlags::ILLEGAL,
79
                ParserFlags::ILLEGAL,
80
                ParserFlags::ILLEGAL,
81
                ParserFlags::ILLEGAL,
82
                ParserFlags::ILLEGAL,
83
                ParserFlags::ILLEGAL,
84
                ParserFlags::ILLEGAL,
85
    /*  32   */ ParserFlags::CHAR_DONTCARE | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
86
    /*  33 ! */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
87
    /*  34 " */ ParserFlags::CHAR_STRING | ParserFlags::STRING_SEP,
88
    /*  35 # */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::WORD_SEP)
89
    /*  36 $ */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::CHAR_WORD | ParserFlags::WORD)
90
    /*  37 % */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::VALUE)
91
    /*  38 & */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
92
    /*  39 ' */ ParserFlags::NAME_SEP,
93
    /*  40 ( */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
94
    /*  41 ) */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
95
    /*  42 * */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
96
    /*  43 + */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP | ParserFlags::VALUE_EXP | ParserFlags::VALUE_SIGN,
97
    /*  44 , */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::CHAR_VALUE | ParserFlags::VALUE)
98
    /*  45 - */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP | ParserFlags::VALUE_EXP | ParserFlags::VALUE_SIGN,
99
    /*  46 . */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::WORD | ParserFlags::CHAR_VALUE | ParserFlags::VALUE)
100
    /*  47 / */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
101
    //for ( i = 48; i < 58; i++ )
102
    /*  48 0 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
103
    /*  49 1 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
104
    /*  50 2 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
105
    /*  51 3 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
106
    /*  52 4 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
107
    /*  53 5 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
108
    /*  54 6 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
109
    /*  55 7 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
110
    /*  56 8 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
111
    /*  57 9 */ TOKEN_DIGIT_FLAGS | ParserFlags::WORD,
112
    /*  58 : */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::WORD)
113
    /*  59 ; */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
114
    /*  60 < */ ParserFlags::CHAR_BOOL | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
115
    /*  61 = */ ParserFlags::CHAR | ParserFlags::BOOL | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
116
    /*  62 > */ ParserFlags::CHAR_BOOL | ParserFlags::BOOL | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
117
    /*  63 ? */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::CHAR_WORD | ParserFlags::WORD)
118
    /*  64 @ */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
119
    //for ( i = 65; i < 91; i++ )
120
    /*  65 A */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
121
    /*  66 B */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
122
    /*  67 C */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
123
    /*  68 D */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
124
    /*  69 E */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
125
    /*  70 F */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
126
    /*  71 G */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
127
    /*  72 H */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
128
    /*  73 I */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
129
    /*  74 J */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
130
    /*  75 K */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
131
    /*  76 L */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
132
    /*  77 M */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
133
    /*  78 N */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
134
    /*  79 O */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
135
    /*  80 P */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
136
    /*  81 Q */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
137
    /*  82 R */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
138
    /*  83 S */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
139
    /*  84 T */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
140
    /*  85 U */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
141
    /*  86 V */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
142
    /*  87 W */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
143
    /*  88 X */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
144
    /*  89 Y */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
145
    /*  90 Z */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
146
    /*  91 [ */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
147
    /*  92 \ */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
148
    /*  93 ] */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
149
    /*  94 ^ */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,
150
    /*  95 _ */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
151
    /*  96 ` */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
152
    //for ( i = 97; i < 123; i++ )
153
    /*  97 a */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
154
    /*  98 b */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
155
    /*  99 c */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
156
    /* 100 d */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
157
    /* 101 e */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
158
    /* 102 f */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
159
    /* 103 g */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
160
    /* 104 h */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
161
    /* 105 i */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
162
    /* 106 j */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
163
    /* 107 k */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
164
    /* 108 l */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
165
    /* 109 m */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
166
    /* 110 n */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
167
    /* 111 o */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
168
    /* 112 p */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
169
    /* 113 q */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
170
    /* 114 r */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
171
    /* 115 s */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
172
    /* 116 t */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
173
    /* 117 u */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
174
    /* 118 v */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
175
    /* 119 w */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
176
    /* 120 x */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
177
    /* 121 y */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
178
    /* 122 z */ ParserFlags::CHAR_WORD | ParserFlags::WORD,
179
    /* 123 { */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
180
    /* 124 | */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
181
    /* 125 } */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
182
    /* 126 ~ */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP,  // (ParserFlags::ILLEGAL // UNUSED)
183
    /* 127   */ ParserFlags::CHAR | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP   // (ParserFlags::ILLEGAL // UNUSED)
184
};
185
186
187
const sal_Int32 cclass_Unicode::pParseTokensType[ nDefCnt ] =
188
{
189
    /* \0 */    KParseTokens::ASC_OTHER,
190
                KParseTokens::ASC_CONTROL,
191
                KParseTokens::ASC_CONTROL,
192
                KParseTokens::ASC_CONTROL,
193
                KParseTokens::ASC_CONTROL,
194
                KParseTokens::ASC_CONTROL,
195
                KParseTokens::ASC_CONTROL,
196
                KParseTokens::ASC_CONTROL,
197
                KParseTokens::ASC_CONTROL,
198
    /*  9 \t */ KParseTokens::ASC_CONTROL,
199
                KParseTokens::ASC_CONTROL,
200
    /* 11 \v */ KParseTokens::ASC_CONTROL,
201
                KParseTokens::ASC_CONTROL,
202
                KParseTokens::ASC_CONTROL,
203
                KParseTokens::ASC_CONTROL,
204
                KParseTokens::ASC_CONTROL,
205
                KParseTokens::ASC_CONTROL,
206
                KParseTokens::ASC_CONTROL,
207
                KParseTokens::ASC_CONTROL,
208
                KParseTokens::ASC_CONTROL,
209
                KParseTokens::ASC_CONTROL,
210
                KParseTokens::ASC_CONTROL,
211
                KParseTokens::ASC_CONTROL,
212
                KParseTokens::ASC_CONTROL,
213
                KParseTokens::ASC_CONTROL,
214
                KParseTokens::ASC_CONTROL,
215
                KParseTokens::ASC_CONTROL,
216
                KParseTokens::ASC_CONTROL,
217
                KParseTokens::ASC_CONTROL,
218
                KParseTokens::ASC_CONTROL,
219
                KParseTokens::ASC_CONTROL,
220
                KParseTokens::ASC_CONTROL,
221
    /*  32   */ KParseTokens::ASC_OTHER,
222
    /*  33 ! */ KParseTokens::ASC_OTHER,
223
    /*  34 " */ KParseTokens::ASC_OTHER,
224
    /*  35 # */ KParseTokens::ASC_OTHER,
225
    /*  36 $ */ KParseTokens::ASC_DOLLAR,
226
    /*  37 % */ KParseTokens::ASC_OTHER,
227
    /*  38 & */ KParseTokens::ASC_OTHER,
228
    /*  39 ' */ KParseTokens::ASC_OTHER,
229
    /*  40 ( */ KParseTokens::ASC_OTHER,
230
    /*  41 ) */ KParseTokens::ASC_OTHER,
231
    /*  42 * */ KParseTokens::ASC_OTHER,
232
    /*  43 + */ KParseTokens::ASC_OTHER,
233
    /*  44 , */ KParseTokens::ASC_OTHER,
234
    /*  45 - */ KParseTokens::ASC_OTHER,
235
    /*  46 . */ KParseTokens::ASC_DOT,
236
    /*  47 / */ KParseTokens::ASC_OTHER,
237
    //for ( i = 48; i < 58; i++ )
238
    /*  48 0 */ KParseTokens::ASC_DIGIT,
239
    /*  49 1 */ KParseTokens::ASC_DIGIT,
240
    /*  50 2 */ KParseTokens::ASC_DIGIT,
241
    /*  51 3 */ KParseTokens::ASC_DIGIT,
242
    /*  52 4 */ KParseTokens::ASC_DIGIT,
243
    /*  53 5 */ KParseTokens::ASC_DIGIT,
244
    /*  54 6 */ KParseTokens::ASC_DIGIT,
245
    /*  55 7 */ KParseTokens::ASC_DIGIT,
246
    /*  56 8 */ KParseTokens::ASC_DIGIT,
247
    /*  57 9 */ KParseTokens::ASC_DIGIT,
248
    /*  58 : */ KParseTokens::ASC_COLON,
249
    /*  59 ; */ KParseTokens::ASC_OTHER,
250
    /*  60 < */ KParseTokens::ASC_OTHER,
251
    /*  61 = */ KParseTokens::ASC_OTHER,
252
    /*  62 > */ KParseTokens::ASC_OTHER,
253
    /*  63 ? */ KParseTokens::ASC_OTHER,
254
    /*  64 @ */ KParseTokens::ASC_OTHER,
255
    //for ( i = 65; i < 91; i++ )
256
    /*  65 A */ KParseTokens::ASC_UPALPHA,
257
    /*  66 B */ KParseTokens::ASC_UPALPHA,
258
    /*  67 C */ KParseTokens::ASC_UPALPHA,
259
    /*  68 D */ KParseTokens::ASC_UPALPHA,
260
    /*  69 E */ KParseTokens::ASC_UPALPHA,
261
    /*  70 F */ KParseTokens::ASC_UPALPHA,
262
    /*  71 G */ KParseTokens::ASC_UPALPHA,
263
    /*  72 H */ KParseTokens::ASC_UPALPHA,
264
    /*  73 I */ KParseTokens::ASC_UPALPHA,
265
    /*  74 J */ KParseTokens::ASC_UPALPHA,
266
    /*  75 K */ KParseTokens::ASC_UPALPHA,
267
    /*  76 L */ KParseTokens::ASC_UPALPHA,
268
    /*  77 M */ KParseTokens::ASC_UPALPHA,
269
    /*  78 N */ KParseTokens::ASC_UPALPHA,
270
    /*  79 O */ KParseTokens::ASC_UPALPHA,
271
    /*  80 P */ KParseTokens::ASC_UPALPHA,
272
    /*  81 Q */ KParseTokens::ASC_UPALPHA,
273
    /*  82 R */ KParseTokens::ASC_UPALPHA,
274
    /*  83 S */ KParseTokens::ASC_UPALPHA,
275
    /*  84 T */ KParseTokens::ASC_UPALPHA,
276
    /*  85 U */ KParseTokens::ASC_UPALPHA,
277
    /*  86 V */ KParseTokens::ASC_UPALPHA,
278
    /*  87 W */ KParseTokens::ASC_UPALPHA,
279
    /*  88 X */ KParseTokens::ASC_UPALPHA,
280
    /*  89 Y */ KParseTokens::ASC_UPALPHA,
281
    /*  90 Z */ KParseTokens::ASC_UPALPHA,
282
    /*  91 [ */ KParseTokens::ASC_OTHER,
283
    /*  92 \ */ KParseTokens::ASC_OTHER,
284
    /*  93 ] */ KParseTokens::ASC_OTHER,
285
    /*  94 ^ */ KParseTokens::ASC_OTHER,
286
    /*  95 _ */ KParseTokens::ASC_UNDERSCORE,
287
    /*  96 ` */ KParseTokens::ASC_OTHER,
288
    //for ( i = 97; i < 123; i++ )
289
    /*  97 a */ KParseTokens::ASC_LOALPHA,
290
    /*  98 b */ KParseTokens::ASC_LOALPHA,
291
    /*  99 c */ KParseTokens::ASC_LOALPHA,
292
    /* 100 d */ KParseTokens::ASC_LOALPHA,
293
    /* 101 e */ KParseTokens::ASC_LOALPHA,
294
    /* 102 f */ KParseTokens::ASC_LOALPHA,
295
    /* 103 g */ KParseTokens::ASC_LOALPHA,
296
    /* 104 h */ KParseTokens::ASC_LOALPHA,
297
    /* 105 i */ KParseTokens::ASC_LOALPHA,
298
    /* 106 j */ KParseTokens::ASC_LOALPHA,
299
    /* 107 k */ KParseTokens::ASC_LOALPHA,
300
    /* 108 l */ KParseTokens::ASC_LOALPHA,
301
    /* 109 m */ KParseTokens::ASC_LOALPHA,
302
    /* 110 n */ KParseTokens::ASC_LOALPHA,
303
    /* 111 o */ KParseTokens::ASC_LOALPHA,
304
    /* 112 p */ KParseTokens::ASC_LOALPHA,
305
    /* 113 q */ KParseTokens::ASC_LOALPHA,
306
    /* 114 r */ KParseTokens::ASC_LOALPHA,
307
    /* 115 s */ KParseTokens::ASC_LOALPHA,
308
    /* 116 t */ KParseTokens::ASC_LOALPHA,
309
    /* 117 u */ KParseTokens::ASC_LOALPHA,
310
    /* 118 v */ KParseTokens::ASC_LOALPHA,
311
    /* 119 w */ KParseTokens::ASC_LOALPHA,
312
    /* 120 x */ KParseTokens::ASC_LOALPHA,
313
    /* 121 y */ KParseTokens::ASC_LOALPHA,
314
    /* 122 z */ KParseTokens::ASC_LOALPHA,
315
    /* 123 { */ KParseTokens::ASC_OTHER,
316
    /* 124 | */ KParseTokens::ASC_OTHER,
317
    /* 125 } */ KParseTokens::ASC_OTHER,
318
    /* 126 ~ */ KParseTokens::ASC_OTHER,
319
    /* 127   */ KParseTokens::ASC_OTHER
320
};
321
322
323
// static
324
const sal_Unicode* cclass_Unicode::StrChr( const sal_Unicode* pStr, sal_uInt32 c )
325
2.11M
{
326
2.11M
    if ( !pStr )
327
0
        return nullptr;
328
2.11M
    sal_Unicode cs[2];
329
2.11M
    auto const n = rtl::splitSurrogates(c, cs);
330
6.31M
    while ( *pStr )
331
4.23M
    {
332
4.23M
        if ( *pStr == cs[0] && (n == 1 || pStr[1] == cs[1]) )
333
31.7k
            return pStr;
334
4.20M
        pStr++;
335
4.20M
    }
336
2.08M
    return nullptr;
337
2.11M
}
338
339
340
sal_Int32 cclass_Unicode::getParseTokensType(sal_uInt32 const c, bool const isFirst)
341
22.0M
{
342
22.0M
    if ( c < nDefCnt )
343
20.8M
        return pParseTokensType[ sal_uInt8(c) ];
344
1.21M
    else
345
1.21M
    {
346
347
        //! all KParseTokens::UNI_... must be matched
348
1.21M
        switch (u_charType(c))
349
1.21M
        {
350
200k
            case U_UPPERCASE_LETTER :
351
200k
                return KParseTokens::UNI_UPALPHA;
352
599k
            case U_LOWERCASE_LETTER :
353
599k
                return KParseTokens::UNI_LOALPHA;
354
147
            case U_TITLECASE_LETTER :
355
147
                return KParseTokens::UNI_TITLE_ALPHA;
356
11.6k
            case U_MODIFIER_LETTER :
357
11.6k
                return KParseTokens::UNI_MODIFIER_LETTER;
358
116k
            case U_OTHER_LETTER :
359
                // Non_Spacing_Mark could not be as leading character
360
116k
                if (isFirst) break;
361
108k
                [[fallthrough]]; // treat it as Other_Letter.
362
112k
            case U_NON_SPACING_MARK :
363
112k
                return KParseTokens::UNI_OTHER_LETTER;
364
2.58k
            case U_DECIMAL_DIGIT_NUMBER :
365
2.58k
                return KParseTokens::UNI_DIGIT;
366
1.08k
            case U_LETTER_NUMBER :
367
1.08k
                return KParseTokens::UNI_LETTER_NUMBER;
368
52.5k
            case U_OTHER_NUMBER :
369
52.5k
                return KParseTokens::UNI_OTHER_NUMBER;
370
1.21M
        }
371
372
235k
        return KParseTokens::UNI_OTHER;
373
1.21M
    }
374
22.0M
}
375
376
void cclass_Unicode::setupInternational( const Locale& rLocale )
377
3.25k
{
378
3.25k
    bool bChanged = (aParserLocale.Language != rLocale.Language
379
2.91k
        || aParserLocale.Country != rLocale.Country
380
2.91k
        || aParserLocale.Variant != rLocale.Variant);
381
3.25k
    if ( bChanged )
382
338
    {
383
338
        aParserLocale.Language = rLocale.Language;
384
338
        aParserLocale.Country = rLocale.Country;
385
338
        aParserLocale.Variant = rLocale.Variant;
386
338
    }
387
3.25k
    if ( !mxLocaleData.is() )
388
338
    {
389
338
        mxLocaleData.set( LocaleData2::create(m_xContext) );
390
338
    }
391
3.25k
}
392
393
394
void cclass_Unicode::setupParserTable( const Locale& rLocale, sal_Int32 startCharTokenType,
395
            const OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType,
396
            const OUString& userDefinedCharactersCont )
397
1.76M
{
398
1.76M
    bool bIntlEqual = (rLocale.Language == aParserLocale.Language &&
399
1.76M
        rLocale.Country == aParserLocale.Country &&
400
1.76M
        rLocale.Variant == aParserLocale.Variant);
401
1.76M
    if ( !pTable || !bIntlEqual ||
402
1.76M
            startCharTokenType != nStartTypes ||
403
1.76M
            contCharTokenType != nContTypes ||
404
1.76M
            userDefinedCharactersStart != aStartChars ||
405
1.76M
            userDefinedCharactersCont != aContChars )
406
3.25k
        initParserTable( rLocale, startCharTokenType, userDefinedCharactersStart,
407
3.25k
            contCharTokenType, userDefinedCharactersCont );
408
1.76M
}
409
410
411
void cclass_Unicode::initParserTable( const Locale& rLocale, sal_Int32 startCharTokenType,
412
            const OUString& userDefinedCharactersStart, sal_Int32 contCharTokenType,
413
            const OUString& userDefinedCharactersCont )
414
3.25k
{
415
    // (Re)Init
416
3.25k
    setupInternational( rLocale );
417
    // Memory of pTable is reused.
418
3.25k
    if ( !pTable )
419
338
        pTable.reset(new ParserFlags[nDefCnt]);
420
3.25k
    std::copy_n( pDefaultParserTable, nDefCnt, pTable.get() );
421
    // Start and cont tables only need reallocation if different length.
422
3.25k
    if ( pStart && userDefinedCharactersStart.getLength() != aStartChars.getLength() )
423
1.45k
    {
424
1.45k
        pStart.reset();
425
1.45k
    }
426
3.25k
    if ( pCont && userDefinedCharactersCont.getLength() != aContChars.getLength() )
427
1.45k
    {
428
1.45k
        pCont.reset();
429
1.45k
    }
430
3.25k
    nStartTypes = startCharTokenType;
431
3.25k
    nContTypes = contCharTokenType;
432
3.25k
    aStartChars = userDefinedCharactersStart;
433
3.25k
    aContChars = userDefinedCharactersCont;
434
435
    // specials
436
3.25k
    if( mxLocaleData.is() )
437
3.25k
    {
438
3.25k
        LocaleDataItem2 aItem =
439
3.25k
            mxLocaleData->getLocaleItem2( aParserLocale );
440
//!TODO: theoretically separators may be a string, adjustment would have to be
441
//! done here and in parsing and in ::rtl::math::stringToDouble()
442
3.25k
        cGroupSep = aItem.thousandSeparator[0];
443
3.25k
        cDecimalSep = aItem.decimalSeparator[0];
444
3.25k
        cDecimalSepAlt = aItem.decimalSeparatorAlternative.toChar();
445
3.25k
    }
446
447
3.25k
    SAL_WARN_IF((nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER)
448
3.25k
             && (nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3),
449
3.25k
        "i18npool", "only one GROUP_SEPARATOR_IN_NUMBER* should be used");
450
3.25k
    if (nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER
451
3.25k
        || nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3)
452
327
    {
453
327
        if ( cGroupSep < nDefCnt )
454
327
            pTable[cGroupSep] |= ParserFlags::VALUE;
455
327
    }
456
2.92k
    else
457
2.92k
    {
458
2.92k
        cGroupSep = 0;
459
2.92k
    }
460
3.25k
    if ( cDecimalSep < nDefCnt )
461
3.25k
        pTable[cDecimalSep] |= ParserFlags::CHAR_VALUE | ParserFlags::VALUE;
462
3.25k
    if ( cDecimalSepAlt && cDecimalSepAlt < nDefCnt )
463
0
        pTable[cDecimalSepAlt] |= ParserFlags::CHAR_VALUE | ParserFlags::VALUE;
464
465
    // Modify characters according to KParseTokens definitions.
466
3.25k
    {
467
3.25k
        using namespace KParseTokens;
468
3.25k
        sal_uInt8 i;
469
470
3.25k
        if ( !(nStartTypes & ASC_UPALPHA) )
471
0
            for ( i = 65; i < 91; i++ )
472
0
                pTable[i] &= ~ParserFlags::CHAR_WORD;  // not allowed as start character
473
3.25k
        if ( !(nContTypes & ASC_UPALPHA) )
474
0
            for ( i = 65; i < 91; i++ )
475
0
                pTable[i] &= ~ParserFlags::WORD;       // not allowed as cont character
476
477
3.25k
        if ( !(nStartTypes & ASC_LOALPHA) )
478
0
            for ( i = 97; i < 123; i++ )
479
0
                pTable[i] &= ~ParserFlags::CHAR_WORD;  // not allowed as start character
480
3.25k
        if ( !(nContTypes & ASC_LOALPHA) )
481
0
            for ( i = 97; i < 123; i++ )
482
0
                pTable[i] &= ~ParserFlags::WORD;       // not allowed as cont character
483
484
3.25k
        if ( nStartTypes & ASC_DIGIT )
485
19.7k
            for ( i = 48; i < 58; i++ )
486
17.9k
                pTable[i] |= ParserFlags::CHAR_WORD;   // allowed as start character
487
3.25k
        if ( !(nContTypes & ASC_DIGIT) )
488
0
            for ( i = 48; i < 58; i++ )
489
0
                pTable[i] &= ~ParserFlags::WORD;       // not allowed as cont character
490
491
3.25k
        if ( !(nStartTypes & ASC_UNDERSCORE) )
492
0
            pTable[95] &= ~ParserFlags::CHAR_WORD;     // not allowed as start character
493
3.25k
        if ( !(nContTypes & ASC_UNDERSCORE) )
494
0
            pTable[95] &= ~ParserFlags::WORD;          // not allowed as cont character
495
496
3.25k
        if ( nStartTypes & ASC_DOLLAR )
497
1.46k
            pTable[36] |= ParserFlags::CHAR_WORD;      // allowed as start character
498
3.25k
        if ( nContTypes & ASC_DOLLAR )
499
1.46k
            pTable[36] |= ParserFlags::WORD;           // allowed as cont character
500
501
3.25k
        if ( nStartTypes & ASC_DOT )
502
0
            pTable[46] |= ParserFlags::CHAR_WORD;      // allowed as start character
503
3.25k
        if ( nContTypes & ASC_DOT )
504
1.79k
            pTable[46] |= ParserFlags::WORD;           // allowed as cont character
505
506
3.25k
        if ( nStartTypes & ASC_COLON )
507
0
            pTable[58] |= ParserFlags::CHAR_WORD;      // allowed as start character
508
3.25k
        if ( nContTypes & ASC_COLON )
509
0
            pTable[58] |= ParserFlags::WORD;           // allowed as cont character
510
511
3.25k
        if ( nStartTypes & ASC_CONTROL )
512
0
            for ( i = 1; i < 32; i++ )
513
0
                pTable[i] |= ParserFlags::CHAR_WORD;   // allowed as start character
514
3.25k
        if ( nContTypes & ASC_CONTROL )
515
0
            for ( i = 1; i < 32; i++ )
516
0
                pTable[i] |= ParserFlags::WORD;        // allowed as cont character
517
518
3.25k
        if ( nStartTypes & ASC_ANY_BUT_CONTROL )
519
0
            for ( i = 32; i < nDefCnt; i++ )
520
0
                pTable[i] |= ParserFlags::CHAR_WORD;   // allowed as start character
521
3.25k
        if ( nContTypes & ASC_ANY_BUT_CONTROL )
522
0
            for ( i = 32; i < nDefCnt; i++ )
523
0
                pTable[i] |= ParserFlags::WORD;        // allowed as cont character
524
525
3.25k
    }
526
527
    // Merge in (positively override with) user defined characters.
528
    // StartChars
529
3.25k
    sal_Int32 nLen = aStartChars.getLength();
530
3.25k
    if ( nLen )
531
1.46k
    {
532
1.46k
        if ( !pStart )
533
1.46k
            pStart.reset(new ParserFlags[ nLen ]);
534
1.46k
        const sal_Unicode* p = aStartChars.getStr();
535
4.44k
        for ( sal_Int32 j=0; j<nLen; j++, p++ )
536
2.98k
        {
537
2.98k
            pStart[j] = ParserFlags::CHAR_WORD;
538
2.98k
            if ( *p < nDefCnt )
539
2.98k
                pTable[*p] |= ParserFlags::CHAR_WORD;
540
2.98k
        }
541
1.46k
    }
542
    // ContChars
543
3.25k
    nLen = aContChars.getLength();
544
3.25k
    if ( nLen )
545
1.46k
    {
546
1.46k
        if ( !pCont )
547
1.46k
            pCont.reset(new ParserFlags[ nLen ]);
548
1.46k
        const sal_Unicode* p = aContChars.getStr();
549
4.44k
        for ( sal_Int32 j=0; j<nLen; j++ )
550
2.98k
        {
551
2.98k
            pCont[j] = ParserFlags::WORD;
552
2.98k
            if ( *p < nDefCnt )
553
2.98k
                pTable[*p] |= ParserFlags::WORD;
554
2.98k
        }
555
1.46k
    }
556
3.25k
}
557
558
559
void cclass_Unicode::destroyParserTable()
560
650k
{
561
650k
    pCont.reset();
562
650k
    pStart.reset();
563
650k
    pTable.reset();
564
650k
}
565
566
567
ParserFlags cclass_Unicode::getFlags(sal_uInt32 const c, const cclass_Unicode::ScanState eState)
568
22.2M
{
569
22.2M
    ParserFlags nMask;
570
22.2M
    if ( c < nDefCnt )
571
21.0M
        nMask = pTable[ sal_uInt8(c) ];
572
1.23M
    else
573
1.23M
        nMask = getFlagsExtended(c, eState);
574
22.2M
    switch ( eState )
575
22.2M
    {
576
1.76M
        case ssGetChar :
577
1.79M
        case ssRewindFromValue :
578
1.79M
        case ssIgnoreLeadingInRewind :
579
1.85M
        case ssGetWordFirstChar :
580
1.85M
            if ( !(nMask & ParserFlags::CHAR_WORD) )
581
517k
            {
582
517k
                nMask |= getStartCharsFlags( c );
583
517k
                if ( nMask & ParserFlags::CHAR_WORD )
584
0
                    nMask &= ~ParserFlags::EXCLUDED;
585
517k
            }
586
1.85M
        break;
587
4.52M
        case ssGetValue :
588
20.2M
        case ssGetWord :
589
20.2M
            if ( !(nMask & ParserFlags::WORD) )
590
1.60M
            {
591
1.60M
                nMask |= getContCharsFlags( c );
592
1.60M
                if ( nMask & ParserFlags::WORD )
593
31.7k
                    nMask &= ~ParserFlags::EXCLUDED;
594
1.60M
            }
595
20.2M
        break;
596
105k
        default:
597
105k
            ;   // other cases aren't needed, no compiler warning
598
22.2M
    }
599
22.2M
    return nMask;
600
22.2M
}
601
602
603
ParserFlags cclass_Unicode::getFlagsExtended(sal_uInt32 const c, const cclass_Unicode::ScanState eState) const
604
1.23M
{
605
1.23M
    if ( c == cGroupSep )
606
0
        return ParserFlags::VALUE;
607
1.23M
    else if ( c == cDecimalSep )
608
0
        return ParserFlags::CHAR_VALUE | ParserFlags::VALUE;
609
1.23M
    else if ( cDecimalSepAlt && c == cDecimalSepAlt )
610
0
        return ParserFlags::CHAR_VALUE | ParserFlags::VALUE;
611
1.23M
    bool bStart = (eState == ssGetChar || eState == ssGetWordFirstChar ||
612
998k
            eState == ssRewindFromValue || eState == ssIgnoreLeadingInRewind);
613
1.23M
    sal_Int32 nTypes = (bStart ? nStartTypes : nContTypes);
614
615
    //! all KParseTokens::UNI_... must be matched
616
1.23M
    switch (u_charType(c))
617
1.23M
    {
618
205k
        case U_UPPERCASE_LETTER :
619
205k
            return (nTypes & KParseTokens::UNI_UPALPHA) ?
620
205k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
621
205k
                ParserFlags::ILLEGAL;
622
602k
        case U_LOWERCASE_LETTER :
623
602k
            return (nTypes & KParseTokens::UNI_LOALPHA) ?
624
602k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
625
602k
                ParserFlags::ILLEGAL;
626
147
        case U_TITLECASE_LETTER :
627
147
            return (nTypes & KParseTokens::UNI_TITLE_ALPHA) ?
628
147
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
629
147
                ParserFlags::ILLEGAL;
630
11.6k
        case U_MODIFIER_LETTER :
631
11.6k
            return (nTypes & KParseTokens::UNI_MODIFIER_LETTER) ?
632
11.6k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
633
11.6k
                ParserFlags::ILLEGAL;
634
4.21k
        case U_NON_SPACING_MARK :
635
5.39k
        case U_COMBINING_SPACING_MARK :
636
            // Non_Spacing_Mark can't be a leading character,
637
            // nor can a spacing combining mark.
638
5.39k
            if (bStart)
639
876
                return ParserFlags::ILLEGAL;
640
4.51k
            [[fallthrough]]; // treat it as Other_Letter.
641
121k
        case U_OTHER_LETTER :
642
121k
            return (nTypes & KParseTokens::UNI_OTHER_LETTER) ?
643
121k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
644
121k
                ParserFlags::ILLEGAL;
645
2.58k
        case U_DECIMAL_DIGIT_NUMBER :
646
2.58k
            return ((nTypes & KParseTokens::UNI_DIGIT) ?
647
2.58k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
648
2.58k
                ParserFlags::ILLEGAL) | TOKEN_DIGIT_FLAGS;
649
1.08k
        case U_LETTER_NUMBER :
650
1.08k
            return ((nTypes & KParseTokens::UNI_LETTER_NUMBER) ?
651
1.08k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
652
1.08k
                ParserFlags::ILLEGAL) | TOKEN_DIGIT_FLAGS;
653
58.7k
        case U_OTHER_NUMBER :
654
58.7k
            return ((nTypes & KParseTokens::UNI_OTHER_NUMBER) ?
655
58.7k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
656
58.7k
                ParserFlags::ILLEGAL) | TOKEN_DIGIT_FLAGS;
657
41.2k
        case U_SPACE_SEPARATOR :
658
41.2k
            return ((nTypes & KParseTokens::IGNORE_LEADING_WS) ?
659
41.2k
                ParserFlags::CHAR_DONTCARE : (bStart ? ParserFlags::CHAR_WORD : (ParserFlags::CHAR_DONTCARE | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP) ));
660
22.3k
        case U_OTHER_PUNCTUATION:
661
            // fdo#61754 Let's see (if we are not at the start) if this is midletter
662
            // punctuation and allow it in a word if it is similar to
663
            // U_NON_SPACING_MARK, for example U+00B7 MIDDLE DOT.
664
            // tdf#123575 for U+30FB KATAKANA MIDDLE DOT property is not
665
            // U_WB_MIDLETTER but U_WB_KATAKANA instead, explicitly test that
666
            // and U+FF65 HALFWIDTH KATAKANA MIDDLE DOT.
667
22.3k
            if (bStart || (U_WB_MIDLETTER != u_getIntPropertyValue(c, UCHAR_WORD_BREAK)
668
12.9k
                        && c != 0x30FB && c != 0xFF65))
669
16.0k
                return ParserFlags::ILLEGAL;
670
6.30k
            else
671
6.30k
            {
672
                //allowing it to continue the word
673
6.30k
                return (nTypes & KParseTokens::UNI_OTHER_LETTER) ?
674
6.30k
                    ParserFlags::WORD : ParserFlags::ILLEGAL;
675
6.30k
            }
676
0
            break;
677
2.96k
        case U_START_PUNCTUATION:
678
            // left angle, double angle and corner brackets
679
2.96k
            if (c != 0x3008 && c != 0x300a && c != 0x300c && c != 0x300e)
680
1.98k
                return ParserFlags::ILLEGAL;
681
973
            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
682
2.88k
        case U_END_PUNCTUATION:
683
            // right angle, double angle and corner brackets
684
2.88k
            if (c != 0x3009 && c != 0x300b && c != 0x300d && c != 0x300f)
685
1.55k
                return ParserFlags::ILLEGAL;
686
1.32k
            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
687
5.65k
        case U_INITIAL_PUNCTUATION:
688
            // left single / double quotation marks
689
5.65k
            if (c != 0x2018 && c != 0x201c)
690
3.12k
                return ParserFlags::ILLEGAL;
691
2.53k
            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
692
7.87k
        case U_FINAL_PUNCTUATION:
693
            // right single / double quotation marks
694
7.87k
            if (c != 0x2019 && c != 0x201d)
695
5.78k
                return ParserFlags::ILLEGAL;
696
2.09k
            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
697
1.23M
    }
698
699
143k
    return ParserFlags::ILLEGAL;
700
1.23M
}
701
702
703
ParserFlags cclass_Unicode::getStartCharsFlags( sal_uInt32 c )
704
517k
{
705
517k
    if ( pStart )
706
515k
    {
707
515k
        const sal_Unicode* pStr = aStartChars.getStr();
708
515k
        const sal_Unicode* p = StrChr( pStr, c );
709
515k
        if ( p )
710
0
            return pStart[ p - pStr ];
711
515k
    }
712
517k
    return ParserFlags::ILLEGAL;
713
517k
}
714
715
716
ParserFlags cclass_Unicode::getContCharsFlags( sal_Unicode c )
717
1.60M
{
718
1.60M
    if ( pCont )
719
1.59M
    {
720
1.59M
        const sal_Unicode* pStr = aContChars.getStr();
721
1.59M
        const sal_Unicode* p = StrChr( pStr, c );
722
1.59M
        if ( p )
723
31.7k
            return pCont[ p - pStr ];
724
1.59M
    }
725
1.57M
    return ParserFlags::ILLEGAL;
726
1.60M
}
727
728
729
void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32 nPos, sal_Int32 nTokenType )
730
1.76M
{
731
1.76M
    assert(r.LeadingWhiteSpace == 0);
732
1.76M
    ScanState eState = ssGetChar;
733
734
    //! All the variables below (plus ParseResult) have to be reset on ssRewindFromValue!
735
1.76M
    OUStringBuffer aSymbol;
736
1.76M
    bool isFirst(true);
737
1.76M
    sal_Int32 index(nPos); // index of next code point after current
738
1.76M
    sal_Int32 postSymbolIndex(index); // index of code point following last quote
739
1.76M
    sal_uInt32 current((index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0);
740
1.76M
    sal_uInt32 cLast = 0;
741
1.76M
    sal_Int32 nCodePoints(0);
742
1.76M
    int nDecSeps = 0;
743
1.76M
    bool bQuote = false;
744
1.76M
    bool bMightBeWord = true;
745
1.76M
    bool bMightBeWordLast = true;
746
1.76M
    bool bDecSepAltUsed = false;
747
    //! All the variables above (plus ParseResult) have to be reset on ssRewindFromValue!
748
1.76M
    sal_Int32 nextCharIndex(nPos); // == index of nextChar
749
750
23.8M
    while ((current != 0) && (eState != ssStop))
751
22.0M
    {
752
22.0M
        ++nCodePoints;
753
22.0M
        ParserFlags nMask = getFlags(current, eState);
754
22.0M
        if ( nMask & ParserFlags::EXCLUDED )
755
0
            eState = ssBounce;
756
22.0M
        if ( bMightBeWord )
757
16.0M
        {   // only relevant for ssGetValue fall back
758
16.0M
            if ( eState == ssGetChar || eState == ssRewindFromValue ||
759
14.2M
                    eState == ssIgnoreLeadingInRewind )
760
1.79M
                bMightBeWord = bool(nMask & ParserFlags::CHAR_WORD);
761
14.2M
            else
762
14.2M
                bMightBeWord = bool(nMask & ParserFlags::WORD);
763
16.0M
        }
764
22.0M
        sal_Int32 nParseTokensType = getParseTokensType(current, isFirst);
765
22.0M
        isFirst = false;
766
22.0M
        sal_Int32 const nextIndex(nextCharIndex); // == index of char following current
767
22.0M
        nextCharIndex = index; // == index of nextChar
768
22.0M
        sal_uInt32 nextChar((index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0);
769
22.0M
        switch (eState)
770
22.0M
        {
771
1.76M
            case ssGetChar :
772
1.79M
            case ssRewindFromValue :
773
1.79M
            case ssIgnoreLeadingInRewind :
774
1.79M
            {
775
1.79M
                if ( (nMask & ParserFlags::CHAR_VALUE) && eState != ssRewindFromValue
776
909k
                        && eState != ssIgnoreLeadingInRewind )
777
909k
                {   //! must be first, may fall back to ssGetWord via bMightBeWord
778
909k
                    eState = ssGetValue;
779
909k
                    if ( nMask & ParserFlags::VALUE_DIGIT )
780
731k
                    {
781
731k
                        if (128 <= current)
782
11.5k
                            r.TokenType = KParseType::UNI_NUMBER;
783
720k
                        else
784
720k
                            r.TokenType = KParseType::ASC_NUMBER;
785
731k
                    }
786
178k
                    else if (current == cDecimalSep || (bDecSepAltUsed = (cDecimalSepAlt && current == cDecimalSepAlt)))
787
178k
                    {
788
178k
                        if (nextChar)
789
173k
                            ++nDecSeps;
790
4.37k
                        else
791
4.37k
                            eState = ssRewindFromValue;
792
                            // retry for ONE_SINGLE_CHAR or others
793
178k
                    }
794
909k
                }
795
881k
                else if ( nMask & ParserFlags::CHAR_WORD )
796
572k
                {
797
572k
                    eState = ssGetWord;
798
572k
                    r.TokenType = KParseType::IDENTNAME;
799
572k
                }
800
309k
                else if ( nMask & ParserFlags::NAME_SEP )
801
70.6k
                {
802
70.6k
                    eState = ssGetWordFirstChar;
803
70.6k
                    bQuote = true;
804
70.6k
                    postSymbolIndex = nextCharIndex;
805
70.6k
                    nParseTokensType = 0;   // will be taken from first real character
806
70.6k
                    r.TokenType = KParseType::SINGLE_QUOTE_NAME;
807
70.6k
                }
808
238k
                else if ( nMask & ParserFlags::CHAR_STRING )
809
4.39k
                {
810
4.39k
                    eState = ssGetString;
811
4.39k
                    postSymbolIndex = nextCharIndex;
812
4.39k
                    nParseTokensType = 0;   // will be taken from first real character
813
4.39k
                    r.TokenType = KParseType::DOUBLE_QUOTE_STRING;
814
4.39k
                }
815
234k
                else if ( nMask & ParserFlags::CHAR_DONTCARE )
816
2.42k
                {
817
2.42k
                    if ( nStartTypes & KParseTokens::IGNORE_LEADING_WS )
818
1.02k
                    {
819
1.02k
                        if (eState == ssRewindFromValue)
820
0
                            eState = ssIgnoreLeadingInRewind;
821
1.02k
                        r.LeadingWhiteSpace = nextCharIndex - nPos;
822
1.02k
                        nCodePoints--; // exclude leading whitespace
823
1.02k
                        postSymbolIndex = nextCharIndex;
824
1.02k
                        nParseTokensType = 0;   // wait until real character
825
1.02k
                        bMightBeWord = true;
826
1.02k
                    }
827
1.39k
                    else
828
1.39k
                        eState = ssBounce;
829
2.42k
                }
830
232k
                else if ( nMask & ParserFlags::CHAR_BOOL )
831
3.43k
                {
832
3.43k
                    eState = ssGetBool;
833
3.43k
                    r.TokenType = KParseType::BOOLEAN;
834
3.43k
                }
835
228k
                else if ( nMask & ParserFlags::CHAR )
836
168k
                {   //! must be last
837
168k
                    eState = ssStop;
838
168k
                    r.TokenType = KParseType::ONE_SINGLE_CHAR;
839
168k
                }
840
60.2k
                else
841
60.2k
                    eState = ssBounce;      // not known
842
1.79M
            }
843
1.79M
            break;
844
4.38M
            case ssGetValue :
845
4.38M
            {
846
4.38M
                if ( nMask & ParserFlags::VALUE_DIGIT )
847
3.37M
                {
848
3.37M
                    if (128 <= current)
849
18.6k
                        r.TokenType = KParseType::UNI_NUMBER;
850
3.36M
                    else if ( r.TokenType != KParseType::UNI_NUMBER )
851
3.32M
                        r.TokenType = KParseType::ASC_NUMBER;
852
3.37M
                }
853
4.38M
                if ( nMask & ParserFlags::VALUE )
854
3.48M
                {
855
3.48M
                    if (current == cGroupSep)
856
0
                    {
857
                        // depending on requested nContTypes, accept only if
858
                        // it is followed by 3 digits
859
0
                        sal_Int32 tempIndex(index);
860
0
                        sal_uInt32 const nextChar2((tempIndex < rText.getLength()) ? rText.iterateCodePoints(&tempIndex) : 0);
861
0
                        sal_uInt32 const nextChar3((tempIndex < rText.getLength()) ? rText.iterateCodePoints(&tempIndex) : 0);
862
0
                        if ((nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3)
863
0
                            && getFlags(nextChar, eState) & ParserFlags::VALUE_DIGIT
864
0
                            && getFlags(nextChar2, eState) & ParserFlags::VALUE_DIGIT
865
0
                            && getFlags(nextChar3, eState) & ParserFlags::VALUE_DIGIT)
866
0
                        {
867
0
                            nParseTokensType |= KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3;
868
0
                        }
869
0
                        else if ((nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3) == 0
870
0
                            && getFlags(nextChar, eState) & ParserFlags::VALUE_DIGIT)
871
0
                        {
872
0
                            nParseTokensType |= KParseTokens::GROUP_SEPARATOR_IN_NUMBER;
873
0
                        }
874
0
                        else
875
0
                        {
876
                            // Trailing group separator character is not a
877
                            // group separator.
878
0
                            eState = ssStopBack;
879
0
                        }
880
0
                    }
881
3.48M
                    else if ((current == cDecimalSep ||
882
3.37M
                                (bDecSepAltUsed = (cDecimalSepAlt && current == cDecimalSepAlt))) &&
883
107k
                            ++nDecSeps > 1)
884
40.3k
                    {
885
40.3k
                        if (nCodePoints == 2)
886
19.0k
                            eState = ssRewindFromValue;
887
                            // consecutive separators
888
21.2k
                        else
889
21.2k
                            eState = ssStopBack;
890
40.3k
                    }
891
                    // else keep it going
892
3.48M
                }
893
899k
                else if (current == 'E' || current == 'e')
894
94.9k
                {
895
94.9k
                    ParserFlags nNext = getFlags(nextChar, eState);
896
94.9k
                    if ( nNext & ParserFlags::VALUE_EXP )
897
67.2k
                        ;   // keep it going
898
27.6k
                    else if (bMightBeWord && ((nNext & ParserFlags::WORD) || !nextChar))
899
16.4k
                    {   // might be a numerical name (1.2efg)
900
16.4k
                        eState = ssGetWord;
901
16.4k
                        r.TokenType = KParseType::IDENTNAME;
902
16.4k
                    }
903
11.1k
                    else
904
11.1k
                        eState = ssStopBack;
905
94.9k
                }
906
805k
                else if ( nMask & ParserFlags::VALUE_SIGN )
907
60.9k
                {
908
60.9k
                    if ( (cLast == 'E') || (cLast == 'e') )
909
47.0k
                    {
910
47.0k
                        ParserFlags nNext = getFlags(nextChar, eState);
911
47.0k
                        if ( nNext & ParserFlags::VALUE_EXP_VALUE )
912
43.0k
                            ;   // keep it going
913
3.96k
                        else if (bMightBeWord && ((nNext & ParserFlags::WORD) || !nextChar))
914
0
                        {   // might be a numerical name (1.2e+fg)
915
0
                            eState = ssGetWord;
916
0
                            r.TokenType = KParseType::IDENTNAME;
917
0
                        }
918
3.96k
                        else
919
3.96k
                            eState = ssStopBack;
920
47.0k
                    }
921
13.9k
                    else if ( bMightBeWord )
922
0
                    {   // might be a numerical name (1.2+fg)
923
0
                        eState = ssGetWord;
924
0
                        r.TokenType = KParseType::IDENTNAME;
925
0
                    }
926
13.9k
                    else
927
13.9k
                        eState = ssStopBack;
928
60.9k
                }
929
744k
                else if ( bMightBeWord && (nMask & ParserFlags::WORD) )
930
212k
                {   // might be a numerical name (1995.A1)
931
212k
                    eState = ssGetWord;
932
212k
                    r.TokenType = KParseType::IDENTNAME;
933
212k
                }
934
531k
                else
935
531k
                    eState = ssStopBack;
936
4.38M
            }
937
4.38M
            break;
938
60.7k
            case ssGetWordFirstChar :
939
60.7k
                eState = ssGetWord;
940
60.7k
                [[fallthrough]];
941
15.8M
            case ssGetWord :
942
15.8M
            {
943
15.8M
                if ( nMask & ParserFlags::WORD )
944
14.8M
                    ;   // keep it going
945
1.00M
                else if ( nMask & ParserFlags::NAME_SEP )
946
136k
                {
947
136k
                    if ( bQuote )
948
16.6k
                    {
949
16.6k
                        if ( cLast == '\\' )
950
779
                        {   // escaped
951
779
                            aSymbol.append(
952
779
                                OUString::Concat(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 2))
953
779
                                + OUString(&current, 1));
954
779
                        }
955
15.8k
                        else
956
15.8k
                        {
957
15.8k
                            eState = ssStop;
958
15.8k
                            aSymbol.append(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 1));
959
15.8k
                        }
960
16.6k
                        postSymbolIndex = nextCharIndex;
961
16.6k
                    }
962
120k
                    else
963
120k
                        eState = ssStopBack;
964
136k
                }
965
869k
                else if ( bQuote )
966
349k
                    ;   // keep it going
967
519k
                else
968
519k
                    eState = ssStopBack;
969
15.8M
            }
970
15.8M
            break;
971
102k
            case ssGetString :
972
102k
            {
973
102k
                if ( nMask & ParserFlags::STRING_SEP )
974
10.3k
                {
975
10.3k
                    if ( cLast == '\\' )
976
2.23k
                    {   // escaped
977
2.23k
                        aSymbol.append(
978
2.23k
                            rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 2)
979
2.23k
                            + OUString(&current, 1));
980
2.23k
                    }
981
8.15k
                    else if (current == nextChar &&
982
5.74k
                            !(nContTypes & KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING) )
983
5.74k
                    {   // "" => literal " escaped
984
5.74k
                        aSymbol.append(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex));
985
5.74k
                        nextCharIndex = index;
986
5.74k
                        if (index < rText.getLength()) { ++nCodePoints; }
987
5.74k
                        nextChar = (index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0;
988
5.74k
                    }
989
2.40k
                    else
990
2.40k
                    {
991
2.40k
                        eState = ssStop;
992
2.40k
                        aSymbol.append(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 1));
993
2.40k
                    }
994
10.3k
                    postSymbolIndex = nextCharIndex;
995
10.3k
                }
996
102k
            }
997
102k
            break;
998
3.37k
            case ssGetBool :
999
3.37k
            {
1000
3.37k
                if ( nMask & ParserFlags::BOOL )
1001
861
                    eState = ssStop;    // maximum 2: <, >, <>, <=, >=
1002
2.51k
                else
1003
2.51k
                    eState = ssStopBack;
1004
3.37k
            }
1005
3.37k
            break;
1006
0
            case ssStopBack :
1007
0
            case ssBounce :
1008
0
            case ssStop :
1009
0
                ;   // nothing, no compiler warning
1010
0
            break;
1011
22.0M
        }
1012
22.0M
        if ( eState == ssRewindFromValue )
1013
23.4k
        {
1014
23.4k
            r = ParseResult();
1015
23.4k
            index = nPos;
1016
23.4k
            postSymbolIndex = nPos;
1017
23.4k
            nextCharIndex = nPos;
1018
23.4k
            aSymbol.setLength(0);
1019
23.4k
            current = (index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0;
1020
23.4k
            nCodePoints = (nPos < rText.getLength()) ? 1 : 0;
1021
23.4k
            isFirst = true;
1022
23.4k
            cLast = 0;
1023
23.4k
            nDecSeps = 0;
1024
23.4k
            bQuote = false;
1025
23.4k
            bMightBeWord = true;
1026
23.4k
            bMightBeWordLast = true;
1027
23.4k
            bDecSepAltUsed = false;
1028
23.4k
        }
1029
22.0M
        else
1030
22.0M
        {
1031
22.0M
            if ( !(r.TokenType & nTokenType) )
1032
271k
            {
1033
271k
                if ( (r.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER))
1034
89
                        && (nTokenType & KParseType::IDENTNAME) && bMightBeWord )
1035
0
                    ;   // keep a number that might be a word
1036
271k
                else if (r.LeadingWhiteSpace == (nextCharIndex - nPos))
1037
1.02k
                    ;   // keep ignored white space
1038
270k
                else if ( !r.TokenType && eState == ssGetValue && (nMask & ParserFlags::VALUE_SEP) )
1039
173k
                    ;   // keep uncertain value
1040
97.1k
                else
1041
97.1k
                    eState = ssBounce;
1042
271k
            }
1043
22.0M
            if ( eState == ssBounce )
1044
97.1k
            {
1045
97.1k
                r.TokenType = 0;
1046
97.1k
                eState = ssStopBack;
1047
97.1k
            }
1048
22.0M
            if ( eState == ssStopBack )
1049
1.28M
            {   // put back
1050
1.28M
                nextChar = rText.iterateCodePoints(&index, -1);
1051
1.28M
                nextCharIndex = nextIndex;
1052
1.28M
                --nCodePoints;
1053
1.28M
                bMightBeWord = bMightBeWordLast;
1054
1.28M
                eState = ssStop;
1055
1.28M
            }
1056
22.0M
            if ( eState != ssStop )
1057
20.5M
            {
1058
20.5M
                if ( !r.StartFlags )
1059
1.61M
                    r.StartFlags |= nParseTokensType;
1060
18.9M
                else
1061
18.9M
                    r.ContFlags |= nParseTokensType;
1062
20.5M
            }
1063
22.0M
            bMightBeWordLast = bMightBeWord;
1064
22.0M
            cLast = current;
1065
22.0M
            current = nextChar;
1066
22.0M
        }
1067
22.0M
    }
1068
    // r.CharLen is the length in characters (not code units) of the parsed
1069
    // token not including any leading white space.
1070
1.76M
    r.CharLen = nCodePoints;
1071
1.76M
    r.EndPos = nextCharIndex;
1072
1.76M
    if ( r.TokenType & KParseType::ASC_NUMBER )
1073
608k
    {
1074
608k
        r.Value = rtl_math_uStringToDouble(rText.getStr() + nPos + r.LeadingWhiteSpace,
1075
608k
            rText.getStr() + r.EndPos, (bDecSepAltUsed ? cDecimalSepAlt : cDecimalSep), cGroupSep, nullptr, nullptr);
1076
608k
        if ( bMightBeWord )
1077
461k
            r.TokenType |= KParseType::IDENTNAME;
1078
608k
    }
1079
1.15M
    else if ( r.TokenType & KParseType::UNI_NUMBER )
1080
13.2k
    {
1081
13.2k
        if ( !xNatNumSup.is() )
1082
8
        {
1083
8
            if ( m_xContext.is() )
1084
8
            {
1085
8
                xNatNumSup = NativeNumberSupplier::create( m_xContext );
1086
8
            }
1087
8
        }
1088
13.2k
        OUString aTmp(rText.getStr() + nPos + r.LeadingWhiteSpace,
1089
13.2k
                r.EndPos - nPos - r.LeadingWhiteSpace);
1090
        // transliterate to ASCII
1091
13.2k
        aTmp = xNatNumSup->getNativeNumberString( aTmp, aParserLocale,
1092
13.2k
                NativeNumberMode::NATNUM0 );
1093
13.2k
        r.Value = ::rtl::math::stringToDouble( aTmp, cDecimalSep, cGroupSep );
1094
13.2k
        if ( bMightBeWord )
1095
8.98k
            r.TokenType |= KParseType::IDENTNAME;
1096
13.2k
    }
1097
1.14M
    else if ( r.TokenType & (KParseType::SINGLE_QUOTE_NAME | KParseType::DOUBLE_QUOTE_STRING) )
1098
75.0k
    {
1099
75.0k
        if (postSymbolIndex < nextCharIndex)
1100
46.1k
        {   //! open quote
1101
46.1k
            aSymbol.append(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 1));
1102
46.1k
            r.TokenType |= KParseType::MISSING_QUOTE;
1103
46.1k
        }
1104
75.0k
        r.DequotedNameOrString = aSymbol.makeStringAndClear();
1105
75.0k
    }
1106
1.76M
}
1107
1108
}
1109
1110
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */