Coverage Report

Created: 2026-08-14 10:22

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
55.2k
#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.34M
{
326
2.34M
    if ( !pStr )
327
0
        return nullptr;
328
2.34M
    sal_Unicode cs[2];
329
2.34M
    auto const n = rtl::splitSurrogates(c, cs);
330
6.97M
    while ( *pStr )
331
4.68M
    {
332
4.68M
        if ( *pStr == cs[0] && (n == 1 || pStr[1] == cs[1]) )
333
48.1k
            return pStr;
334
4.63M
        pStr++;
335
4.63M
    }
336
2.29M
    return nullptr;
337
2.34M
}
338
339
340
sal_Int32 cclass_Unicode::getParseTokensType(sal_uInt32 const c, bool const isFirst)
341
42.0M
{
342
42.0M
    if ( c < nDefCnt )
343
40.6M
        return pParseTokensType[ sal_uInt8(c) ];
344
1.44M
    else
345
1.44M
    {
346
347
        //! all KParseTokens::UNI_... must be matched
348
1.44M
        switch (u_charType(c))
349
1.44M
        {
350
207k
            case U_UPPERCASE_LETTER :
351
207k
                return KParseTokens::UNI_UPALPHA;
352
540k
            case U_LOWERCASE_LETTER :
353
540k
                return KParseTokens::UNI_LOALPHA;
354
123
            case U_TITLECASE_LETTER :
355
123
                return KParseTokens::UNI_TITLE_ALPHA;
356
13.1k
            case U_MODIFIER_LETTER :
357
13.1k
                return KParseTokens::UNI_MODIFIER_LETTER;
358
164k
            case U_OTHER_LETTER :
359
                // Non_Spacing_Mark could not be as leading character
360
164k
                if (isFirst) break;
361
140k
                [[fallthrough]]; // treat it as Other_Letter.
362
268k
            case U_NON_SPACING_MARK :
363
268k
                return KParseTokens::UNI_OTHER_LETTER;
364
5.47k
            case U_DECIMAL_DIGIT_NUMBER :
365
5.47k
                return KParseTokens::UNI_DIGIT;
366
3.14k
            case U_LETTER_NUMBER :
367
3.14k
                return KParseTokens::UNI_LETTER_NUMBER;
368
43.1k
            case U_OTHER_NUMBER :
369
43.1k
                return KParseTokens::UNI_OTHER_NUMBER;
370
1.44M
        }
371
372
365k
        return KParseTokens::UNI_OTHER;
373
1.44M
    }
374
42.0M
}
375
376
void cclass_Unicode::setupInternational( const Locale& rLocale )
377
26.2k
{
378
26.2k
    bool bChanged = (aParserLocale.Language != rLocale.Language
379
25.8k
        || aParserLocale.Country != rLocale.Country
380
25.8k
        || aParserLocale.Variant != rLocale.Variant);
381
26.2k
    if ( bChanged )
382
431
    {
383
431
        aParserLocale.Language = rLocale.Language;
384
431
        aParserLocale.Country = rLocale.Country;
385
431
        aParserLocale.Variant = rLocale.Variant;
386
431
    }
387
26.2k
    if ( !mxLocaleData.is() )
388
431
    {
389
431
        mxLocaleData.set( LocaleData2::create(m_xContext) );
390
431
    }
391
26.2k
}
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
4.36M
{
398
4.36M
    bool bIntlEqual = (rLocale.Language == aParserLocale.Language &&
399
4.36M
        rLocale.Country == aParserLocale.Country &&
400
4.36M
        rLocale.Variant == aParserLocale.Variant);
401
4.36M
    if ( !pTable || !bIntlEqual ||
402
4.36M
            startCharTokenType != nStartTypes ||
403
4.34M
            contCharTokenType != nContTypes ||
404
4.34M
            userDefinedCharactersStart != aStartChars ||
405
4.34M
            userDefinedCharactersCont != aContChars )
406
26.2k
        initParserTable( rLocale, startCharTokenType, userDefinedCharactersStart,
407
26.2k
            contCharTokenType, userDefinedCharactersCont );
408
4.36M
}
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
26.2k
{
415
    // (Re)Init
416
26.2k
    setupInternational( rLocale );
417
    // Memory of pTable is reused.
418
26.2k
    if ( !pTable )
419
431
        pTable.reset(new ParserFlags[nDefCnt]);
420
26.2k
    std::copy_n( pDefaultParserTable, nDefCnt, pTable.get() );
421
    // Start and cont tables only need reallocation if different length.
422
26.2k
    if ( pStart && userDefinedCharactersStart.getLength() != aStartChars.getLength() )
423
7.05k
    {
424
7.05k
        pStart.reset();
425
7.05k
    }
426
26.2k
    if ( pCont && userDefinedCharactersCont.getLength() != aContChars.getLength() )
427
7.05k
    {
428
7.05k
        pCont.reset();
429
7.05k
    }
430
26.2k
    nStartTypes = startCharTokenType;
431
26.2k
    nContTypes = contCharTokenType;
432
26.2k
    aStartChars = userDefinedCharactersStart;
433
26.2k
    aContChars = userDefinedCharactersCont;
434
435
    // specials
436
26.2k
    if( mxLocaleData.is() )
437
26.2k
    {
438
26.2k
        LocaleDataItem2 aItem =
439
26.2k
            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
26.2k
        cGroupSep = aItem.thousandSeparator[0];
443
26.2k
        cDecimalSep = aItem.decimalSeparator[0];
444
26.2k
        cDecimalSepAlt = aItem.decimalSeparatorAlternative.toChar();
445
26.2k
    }
446
447
26.2k
    SAL_WARN_IF((nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER)
448
26.2k
             && (nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3),
449
26.2k
        "i18npool", "only one GROUP_SEPARATOR_IN_NUMBER* should be used");
450
26.2k
    if (nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER
451
26.2k
        || nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3)
452
415
    {
453
415
        if ( cGroupSep < nDefCnt )
454
415
            pTable[cGroupSep] |= ParserFlags::VALUE;
455
415
    }
456
25.8k
    else
457
25.8k
    {
458
25.8k
        cGroupSep = 0;
459
25.8k
    }
460
26.2k
    if ( cDecimalSep < nDefCnt )
461
26.2k
        pTable[cDecimalSep] |= ParserFlags::CHAR_VALUE | ParserFlags::VALUE;
462
26.2k
    if ( cDecimalSepAlt && cDecimalSepAlt < nDefCnt )
463
0
        pTable[cDecimalSepAlt] |= ParserFlags::CHAR_VALUE | ParserFlags::VALUE;
464
465
    // Modify characters according to KParseTokens definitions.
466
26.2k
    {
467
26.2k
        using namespace KParseTokens;
468
26.2k
        sal_uInt8 i;
469
470
26.2k
        if ( !(nStartTypes & ASC_UPALPHA) )
471
2.53k
            for ( i = 65; i < 91; i++ )
472
2.44k
                pTable[i] &= ~ParserFlags::CHAR_WORD;  // not allowed as start character
473
26.2k
        if ( !(nContTypes & ASC_UPALPHA) )
474
2.53k
            for ( i = 65; i < 91; i++ )
475
2.44k
                pTable[i] &= ~ParserFlags::WORD;       // not allowed as cont character
476
477
26.2k
        if ( !(nStartTypes & ASC_LOALPHA) )
478
103k
            for ( i = 97; i < 123; i++ )
479
99.6k
                pTable[i] &= ~ParserFlags::CHAR_WORD;  // not allowed as start character
480
26.2k
        if ( !(nContTypes & ASC_LOALPHA) )
481
103k
            for ( i = 97; i < 123; i++ )
482
99.6k
                pTable[i] &= ~ParserFlags::WORD;       // not allowed as cont character
483
484
26.2k
        if ( nStartTypes & ASC_DIGIT )
485
82.3k
            for ( i = 48; i < 58; i++ )
486
74.8k
                pTable[i] |= ParserFlags::CHAR_WORD;   // allowed as start character
487
26.2k
        if ( !(nContTypes & ASC_DIGIT) )
488
105k
            for ( i = 48; i < 58; i++ )
489
96.1k
                pTable[i] &= ~ParserFlags::WORD;       // not allowed as cont character
490
491
26.2k
        if ( !(nStartTypes & ASC_UNDERSCORE) )
492
19.3k
            pTable[95] &= ~ParserFlags::CHAR_WORD;     // not allowed as start character
493
26.2k
        if ( !(nContTypes & ASC_UNDERSCORE) )
494
19.3k
            pTable[95] &= ~ParserFlags::WORD;          // not allowed as cont character
495
496
26.2k
        if ( nStartTypes & ASC_DOLLAR )
497
3.33k
            pTable[36] |= ParserFlags::CHAR_WORD;      // allowed as start character
498
26.2k
        if ( nContTypes & ASC_DOLLAR )
499
3.33k
            pTable[36] |= ParserFlags::WORD;           // allowed as cont character
500
501
26.2k
        if ( nStartTypes & ASC_DOT )
502
94
            pTable[46] |= ParserFlags::CHAR_WORD;      // allowed as start character
503
26.2k
        if ( nContTypes & ASC_DOT )
504
9.61k
            pTable[46] |= ParserFlags::WORD;           // allowed as cont character
505
506
26.2k
        if ( nStartTypes & ASC_COLON )
507
0
            pTable[58] |= ParserFlags::CHAR_WORD;      // allowed as start character
508
26.2k
        if ( nContTypes & ASC_COLON )
509
0
            pTable[58] |= ParserFlags::WORD;           // allowed as cont character
510
511
26.2k
        if ( nStartTypes & ASC_CONTROL )
512
0
            for ( i = 1; i < 32; i++ )
513
0
                pTable[i] |= ParserFlags::CHAR_WORD;   // allowed as start character
514
26.2k
        if ( nContTypes & ASC_CONTROL )
515
0
            for ( i = 1; i < 32; i++ )
516
0
                pTable[i] |= ParserFlags::WORD;        // allowed as cont character
517
518
26.2k
        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
26.2k
        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
26.2k
    }
526
527
    // Merge in (positively override with) user defined characters.
528
    // StartChars
529
26.2k
    sal_Int32 nLen = aStartChars.getLength();
530
26.2k
    if ( nLen )
531
7.06k
    {
532
7.06k
        if ( !pStart )
533
7.06k
            pStart.reset(new ParserFlags[ nLen ]);
534
7.06k
        const sal_Unicode* p = aStartChars.getStr();
535
17.5k
        for ( sal_Int32 j=0; j<nLen; j++, p++ )
536
10.4k
        {
537
10.4k
            pStart[j] = ParserFlags::CHAR_WORD;
538
10.4k
            if ( *p < nDefCnt )
539
10.4k
                pTable[*p] |= ParserFlags::CHAR_WORD;
540
10.4k
        }
541
7.06k
    }
542
    // ContChars
543
26.2k
    nLen = aContChars.getLength();
544
26.2k
    if ( nLen )
545
7.06k
    {
546
7.06k
        if ( !pCont )
547
7.06k
            pCont.reset(new ParserFlags[ nLen ]);
548
7.06k
        const sal_Unicode* p = aContChars.getStr();
549
21.2k
        for ( sal_Int32 j=0; j<nLen; j++ )
550
14.1k
        {
551
14.1k
            pCont[j] = ParserFlags::WORD;
552
14.1k
            if ( *p < nDefCnt )
553
14.1k
                pTable[*p] |= ParserFlags::WORD;
554
14.1k
        }
555
7.06k
    }
556
26.2k
}
557
558
559
void cclass_Unicode::destroyParserTable()
560
624k
{
561
624k
    pCont.reset();
562
624k
    pStart.reset();
563
624k
    pTable.reset();
564
624k
}
565
566
567
ParserFlags cclass_Unicode::getFlags(sal_uInt32 const c, const cclass_Unicode::ScanState eState)
568
42.2M
{
569
42.2M
    ParserFlags nMask;
570
42.2M
    if ( c < nDefCnt )
571
40.7M
        nMask = pTable[ sal_uInt8(c) ];
572
1.45M
    else
573
1.45M
        nMask = getFlagsExtended(c, eState);
574
42.2M
    switch ( eState )
575
42.2M
    {
576
4.44M
        case ssGetChar :
577
4.48M
        case ssRewindFromValue :
578
4.48M
        case ssIgnoreLeadingInRewind :
579
4.56M
        case ssGetWordFirstChar :
580
4.56M
            if ( !(nMask & ParserFlags::CHAR_WORD) )
581
2.78M
            {
582
2.78M
                nMask |= getStartCharsFlags( c );
583
2.78M
                if ( nMask & ParserFlags::CHAR_WORD )
584
0
                    nMask &= ~ParserFlags::EXCLUDED;
585
2.78M
            }
586
4.56M
        break;
587
8.77M
        case ssGetValue :
588
32.0M
        case ssGetWord :
589
32.0M
            if ( !(nMask & ParserFlags::WORD) )
590
4.49M
            {
591
4.49M
                nMask |= getContCharsFlags( c );
592
4.49M
                if ( nMask & ParserFlags::WORD )
593
48.1k
                    nMask &= ~ParserFlags::EXCLUDED;
594
4.49M
            }
595
32.0M
        break;
596
5.56M
        default:
597
5.56M
            ;   // other cases aren't needed, no compiler warning
598
42.2M
    }
599
42.2M
    return nMask;
600
42.2M
}
601
602
603
ParserFlags cclass_Unicode::getFlagsExtended(sal_uInt32 const c, const cclass_Unicode::ScanState eState) const
604
1.45M
{
605
1.45M
    if ( c == cGroupSep )
606
0
        return ParserFlags::VALUE;
607
1.45M
    else if ( c == cDecimalSep )
608
0
        return ParserFlags::CHAR_VALUE | ParserFlags::VALUE;
609
1.45M
    else if ( cDecimalSepAlt && c == cDecimalSepAlt )
610
0
        return ParserFlags::CHAR_VALUE | ParserFlags::VALUE;
611
1.45M
    bool bStart = (eState == ssGetChar || eState == ssGetWordFirstChar ||
612
1.18M
            eState == ssRewindFromValue || eState == ssIgnoreLeadingInRewind);
613
1.45M
    sal_Int32 nTypes = (bStart ? nStartTypes : nContTypes);
614
615
    //! all KParseTokens::UNI_... must be matched
616
1.45M
    switch (u_charType(c))
617
1.45M
    {
618
210k
        case U_UPPERCASE_LETTER :
619
210k
            return (nTypes & KParseTokens::UNI_UPALPHA) ?
620
210k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
621
210k
                ParserFlags::ILLEGAL;
622
542k
        case U_LOWERCASE_LETTER :
623
542k
            return (nTypes & KParseTokens::UNI_LOALPHA) ?
624
540k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
625
542k
                ParserFlags::ILLEGAL;
626
123
        case U_TITLECASE_LETTER :
627
123
            return (nTypes & KParseTokens::UNI_TITLE_ALPHA) ?
628
123
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
629
123
                ParserFlags::ILLEGAL;
630
13.1k
        case U_MODIFIER_LETTER :
631
13.1k
            return (nTypes & KParseTokens::UNI_MODIFIER_LETTER) ?
632
13.0k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
633
13.1k
                ParserFlags::ILLEGAL;
634
127k
        case U_NON_SPACING_MARK :
635
131k
        case U_COMBINING_SPACING_MARK :
636
            // Non_Spacing_Mark can't be a leading character,
637
            // nor can a spacing combining mark.
638
131k
            if (bStart)
639
41.7k
                return ParserFlags::ILLEGAL;
640
89.3k
            [[fallthrough]]; // treat it as Other_Letter.
641
253k
        case U_OTHER_LETTER :
642
253k
            return (nTypes & KParseTokens::UNI_OTHER_LETTER) ?
643
245k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
644
253k
                ParserFlags::ILLEGAL;
645
5.47k
        case U_DECIMAL_DIGIT_NUMBER :
646
5.47k
            return ((nTypes & KParseTokens::UNI_DIGIT) ?
647
2.23k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
648
5.47k
                ParserFlags::ILLEGAL) | TOKEN_DIGIT_FLAGS;
649
3.14k
        case U_LETTER_NUMBER :
650
3.14k
            return ((nTypes & KParseTokens::UNI_LETTER_NUMBER) ?
651
634
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
652
3.14k
                ParserFlags::ILLEGAL) | TOKEN_DIGIT_FLAGS;
653
46.6k
        case U_OTHER_NUMBER :
654
46.6k
            return ((nTypes & KParseTokens::UNI_OTHER_NUMBER) ?
655
46.0k
                (bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD) :
656
46.6k
                ParserFlags::ILLEGAL) | TOKEN_DIGIT_FLAGS;
657
33.3k
        case U_SPACE_SEPARATOR :
658
33.3k
            return ((nTypes & KParseTokens::IGNORE_LEADING_WS) ?
659
33.3k
                ParserFlags::CHAR_DONTCARE : (bStart ? ParserFlags::CHAR_WORD : (ParserFlags::CHAR_DONTCARE | ParserFlags::WORD_SEP | ParserFlags::VALUE_SEP) ));
660
52.4k
        case U_OTHER_PUNCTUATION:
661
            // fdo#61754 Let's see (if we not at the start) if this is midletter
662
            // punctuation and allow it in a word if it is similarly 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
52.4k
            if (bStart || (U_WB_MIDLETTER != u_getIntPropertyValue(c, UCHAR_WORD_BREAK)
668
36.6k
                        && c != 0x30FB && c != 0xFF65))
669
47.1k
                return ParserFlags::ILLEGAL;
670
5.35k
            else
671
5.35k
            {
672
                //allowing it to continue the word
673
5.35k
                return (nTypes & KParseTokens::UNI_OTHER_LETTER) ?
674
5.35k
                    ParserFlags::WORD : ParserFlags::ILLEGAL;
675
5.35k
            }
676
0
            break;
677
1.53k
        case U_START_PUNCTUATION:
678
            // left angle, double angle and corner brackets
679
1.53k
            if (c != 0x3008 && c != 0x300a && c != 0x300c && c != 0x300e)
680
933
                return ParserFlags::ILLEGAL;
681
602
            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
682
4.32k
        case U_END_PUNCTUATION:
683
            // right angle, double angle and corner brackets
684
4.32k
            if (c != 0x3009 && c != 0x300b && c != 0x300d && c != 0x300f)
685
2.57k
                return ParserFlags::ILLEGAL;
686
1.74k
            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
687
4.69k
        case U_INITIAL_PUNCTUATION:
688
            // left single / double quotation marks
689
4.69k
            if (c != 0x2018 && c != 0x201c)
690
3.80k
                return ParserFlags::ILLEGAL;
691
892
            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
692
4.24k
        case U_FINAL_PUNCTUATION:
693
            // right single / double quotation marks
694
4.24k
            if (c != 0x2019 && c != 0x201d)
695
1.88k
                return ParserFlags::ILLEGAL;
696
2.35k
            return bStart ? ParserFlags::CHAR_WORD : ParserFlags::WORD;
697
1.45M
    }
698
699
238k
    return ParserFlags::ILLEGAL;
700
1.45M
}
701
702
703
ParserFlags cclass_Unicode::getStartCharsFlags( sal_uInt32 c )
704
2.78M
{
705
2.78M
    if ( pStart )
706
721k
    {
707
721k
        const sal_Unicode* pStr = aStartChars.getStr();
708
721k
        const sal_Unicode* p = StrChr( pStr, c );
709
721k
        if ( p )
710
0
            return pStart[ p - pStr ];
711
721k
    }
712
2.78M
    return ParserFlags::ILLEGAL;
713
2.78M
}
714
715
716
ParserFlags cclass_Unicode::getContCharsFlags( sal_Unicode c )
717
4.49M
{
718
4.49M
    if ( pCont )
719
1.61M
    {
720
1.61M
        const sal_Unicode* pStr = aContChars.getStr();
721
1.61M
        const sal_Unicode* p = StrChr( pStr, c );
722
1.61M
        if ( p )
723
48.1k
            return pCont[ p - pStr ];
724
1.61M
    }
725
4.44M
    return ParserFlags::ILLEGAL;
726
4.49M
}
727
728
729
void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32 nPos, sal_Int32 nTokenType )
730
4.36M
{
731
4.36M
    assert(r.LeadingWhiteSpace == 0);
732
4.36M
    ScanState eState = ssGetChar;
733
734
    //! All the variables below (plus ParseResult) have to be reset on ssRewindFromValue!
735
4.36M
    OUStringBuffer aSymbol;
736
4.36M
    bool isFirst(true);
737
4.36M
    sal_Int32 index(nPos); // index of next code point after current
738
4.36M
    sal_Int32 postSymbolIndex(index); // index of code point following last quote
739
4.36M
    sal_uInt32 current((index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0);
740
4.36M
    sal_uInt32 cLast = 0;
741
4.36M
    sal_Int32 nCodePoints(0);
742
4.36M
    int nDecSeps = 0;
743
4.36M
    bool bQuote = false;
744
4.36M
    bool bMightBeWord = true;
745
4.36M
    bool bMightBeWordLast = true;
746
4.36M
    bool bDecSepAltUsed = false;
747
    //! All the variables above (plus ParseResult) have to be reset on ssRewindFromValue!
748
4.36M
    sal_Int32 nextCharIndex(nPos); // == index of nextChar
749
750
46.4M
    while ((current != 0) && (eState != ssStop))
751
42.0M
    {
752
42.0M
        ++nCodePoints;
753
42.0M
        ParserFlags nMask = getFlags(current, eState);
754
42.0M
        if ( nMask & ParserFlags::EXCLUDED )
755
0
            eState = ssBounce;
756
42.0M
        if ( bMightBeWord )
757
25.4M
        {   // only relevant for ssGetValue fall back
758
25.4M
            if ( eState == ssGetChar || eState == ssRewindFromValue ||
759
20.9M
                    eState == ssIgnoreLeadingInRewind )
760
4.48M
                bMightBeWord = bool(nMask & ParserFlags::CHAR_WORD);
761
20.9M
            else
762
20.9M
                bMightBeWord = bool(nMask & ParserFlags::WORD);
763
25.4M
        }
764
42.0M
        sal_Int32 nParseTokensType = getParseTokensType(current, isFirst);
765
42.0M
        isFirst = false;
766
42.0M
        sal_Int32 const nextIndex(nextCharIndex); // == index of char following current
767
42.0M
        nextCharIndex = index; // == index of nextChar
768
42.0M
        sal_uInt32 nextChar((index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0);
769
42.0M
        switch (eState)
770
42.0M
        {
771
4.44M
            case ssGetChar :
772
4.48M
            case ssRewindFromValue :
773
4.48M
            case ssIgnoreLeadingInRewind :
774
4.48M
            {
775
4.48M
                if ( (nMask & ParserFlags::CHAR_VALUE) && eState != ssRewindFromValue
776
1.07M
                        && eState != ssIgnoreLeadingInRewind )
777
1.07M
                {   //! must be first, may fall back to ssGetWord via bMightBeWord
778
1.07M
                    eState = ssGetValue;
779
1.07M
                    if ( nMask & ParserFlags::VALUE_DIGIT )
780
878k
                    {
781
878k
                        if (128 <= current)
782
7.29k
                            r.TokenType = KParseType::UNI_NUMBER;
783
871k
                        else
784
871k
                            r.TokenType = KParseType::ASC_NUMBER;
785
878k
                    }
786
191k
                    else if (current == cDecimalSep || (bDecSepAltUsed = (cDecimalSepAlt && current == cDecimalSepAlt)))
787
191k
                    {
788
191k
                        if (nextChar)
789
186k
                            ++nDecSeps;
790
4.58k
                        else
791
4.58k
                            eState = ssRewindFromValue;
792
                            // retry for ONE_SINGLE_CHAR or others
793
191k
                    }
794
1.07M
                }
795
3.41M
                else if ( nMask & ParserFlags::CHAR_WORD )
796
859k
                {
797
859k
                    eState = ssGetWord;
798
859k
                    r.TokenType = KParseType::IDENTNAME;
799
859k
                }
800
2.55M
                else if ( nMask & ParserFlags::NAME_SEP )
801
112k
                {
802
112k
                    eState = ssGetWordFirstChar;
803
112k
                    bQuote = true;
804
112k
                    postSymbolIndex = nextCharIndex;
805
112k
                    nParseTokensType = 0;   // will be taken of first real character
806
112k
                    r.TokenType = KParseType::SINGLE_QUOTE_NAME;
807
112k
                }
808
2.44M
                else if ( nMask & ParserFlags::CHAR_STRING )
809
125k
                {
810
125k
                    eState = ssGetString;
811
125k
                    postSymbolIndex = nextCharIndex;
812
125k
                    nParseTokensType = 0;   // will be taken of first real character
813
125k
                    r.TokenType = KParseType::DOUBLE_QUOTE_STRING;
814
125k
                }
815
2.31M
                else if ( nMask & ParserFlags::CHAR_DONTCARE )
816
75.7k
                {
817
75.7k
                    if ( nStartTypes & KParseTokens::IGNORE_LEADING_WS )
818
73.5k
                    {
819
73.5k
                        if (eState == ssRewindFromValue)
820
0
                            eState = ssIgnoreLeadingInRewind;
821
73.5k
                        r.LeadingWhiteSpace = nextCharIndex - nPos;
822
73.5k
                        nCodePoints--; // exclude leading whitespace
823
73.5k
                        postSymbolIndex = nextCharIndex;
824
73.5k
                        nParseTokensType = 0;   // wait until real character
825
73.5k
                        bMightBeWord = true;
826
73.5k
                    }
827
2.23k
                    else
828
2.23k
                        eState = ssBounce;
829
75.7k
                }
830
2.24M
                else if ( nMask & ParserFlags::CHAR_BOOL )
831
389k
                {
832
389k
                    eState = ssGetBool;
833
389k
                    r.TokenType = KParseType::BOOLEAN;
834
389k
                }
835
1.85M
                else if ( nMask & ParserFlags::CHAR )
836
1.24M
                {   //! must be last
837
1.24M
                    eState = ssStop;
838
1.24M
                    r.TokenType = KParseType::ONE_SINGLE_CHAR;
839
1.24M
                }
840
611k
                else
841
611k
                    eState = ssBounce;      // not known
842
4.48M
            }
843
4.48M
            break;
844
8.63M
            case ssGetValue :
845
8.63M
            {
846
8.63M
                if ( nMask & ParserFlags::VALUE_DIGIT )
847
7.41M
                {
848
7.41M
                    if (128 <= current)
849
14.0k
                        r.TokenType = KParseType::UNI_NUMBER;
850
7.40M
                    else if ( r.TokenType != KParseType::UNI_NUMBER )
851
7.38M
                        r.TokenType = KParseType::ASC_NUMBER;
852
7.41M
                }
853
8.63M
                if ( nMask & ParserFlags::VALUE )
854
7.60M
                {
855
7.60M
                    if (current == cGroupSep)
856
11.3k
                    {
857
                        // depending or requested nContTypes, accept only if
858
                        // it is followed by 3 digits
859
11.3k
                        sal_Int32 tempIndex(index);
860
11.3k
                        sal_uInt32 const nextChar2((tempIndex < rText.getLength()) ? rText.iterateCodePoints(&tempIndex) : 0);
861
11.3k
                        sal_uInt32 const nextChar3((tempIndex < rText.getLength()) ? rText.iterateCodePoints(&tempIndex) : 0);
862
11.3k
                        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
11.3k
                        else if ((nContTypes & KParseTokens::GROUP_SEPARATOR_IN_NUMBER_3) == 0
870
11.3k
                            && getFlags(nextChar, eState) & ParserFlags::VALUE_DIGIT)
871
8.58k
                        {
872
8.58k
                            nParseTokensType |= KParseTokens::GROUP_SEPARATOR_IN_NUMBER;
873
8.58k
                        }
874
2.80k
                        else
875
2.80k
                        {
876
                            // Trailing group separator character is not a
877
                            // group separator.
878
2.80k
                            eState = ssStopBack;
879
2.80k
                        }
880
11.3k
                    }
881
7.59M
                    else if ((current == cDecimalSep ||
882
7.41M
                                (bDecSepAltUsed = (cDecimalSepAlt && current == cDecimalSepAlt))) &&
883
179k
                            ++nDecSeps > 1)
884
75.4k
                    {
885
75.4k
                        if (nCodePoints == 2)
886
38.9k
                            eState = ssRewindFromValue;
887
                            // consecutive separators
888
36.5k
                        else
889
36.5k
                            eState = ssStopBack;
890
75.4k
                    }
891
                    // else keep it going
892
7.60M
                }
893
1.02M
                else if (current == 'E' || current == 'e')
894
90.6k
                {
895
90.6k
                    ParserFlags nNext = getFlags(nextChar, eState);
896
90.6k
                    if ( nNext & ParserFlags::VALUE_EXP )
897
60.9k
                        ;   // keep it going
898
29.7k
                    else if (bMightBeWord && ((nNext & ParserFlags::WORD) || !nextChar))
899
17.6k
                    {   // might be a numerical name (1.2efg)
900
17.6k
                        eState = ssGetWord;
901
17.6k
                        r.TokenType = KParseType::IDENTNAME;
902
17.6k
                    }
903
12.1k
                    else
904
12.1k
                        eState = ssStopBack;
905
90.6k
                }
906
932k
                else if ( nMask & ParserFlags::VALUE_SIGN )
907
58.9k
                {
908
58.9k
                    if ( (cLast == 'E') || (cLast == 'e') )
909
37.8k
                    {
910
37.8k
                        ParserFlags nNext = getFlags(nextChar, eState);
911
37.8k
                        if ( nNext & ParserFlags::VALUE_EXP_VALUE )
912
34.9k
                            ;   // keep it going
913
2.83k
                        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
2.83k
                        else
919
2.83k
                            eState = ssStopBack;
920
37.8k
                    }
921
21.1k
                    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
21.1k
                    else
927
21.1k
                        eState = ssStopBack;
928
58.9k
                }
929
873k
                else if ( bMightBeWord && (nMask & ParserFlags::WORD) )
930
300k
                {   // might be a numerical name (1995.A1)
931
300k
                    eState = ssGetWord;
932
300k
                    r.TokenType = KParseType::IDENTNAME;
933
300k
                }
934
573k
                else
935
573k
                    eState = ssStopBack;
936
8.63M
            }
937
8.63M
            break;
938
83.0k
            case ssGetWordFirstChar :
939
83.0k
                eState = ssGetWord;
940
83.0k
                [[fallthrough]];
941
23.3M
            case ssGetWord :
942
23.3M
            {
943
23.3M
                if ( nMask & ParserFlags::WORD )
944
19.5M
                    ;   // keep it going
945
3.85M
                else if ( nMask & ParserFlags::NAME_SEP )
946
170k
                {
947
170k
                    if ( bQuote )
948
40.1k
                    {
949
40.1k
                        if ( cLast == '\\' )
950
834
                        {   // escaped
951
834
                            aSymbol.append(
952
834
                                OUString::Concat(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 2))
953
834
                                + OUString(&current, 1));
954
834
                        }
955
39.3k
                        else
956
39.3k
                        {
957
39.3k
                            eState = ssStop;
958
39.3k
                            aSymbol.append(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 1));
959
39.3k
                        }
960
40.1k
                        postSymbolIndex = nextCharIndex;
961
40.1k
                    }
962
130k
                    else
963
130k
                        eState = ssStopBack;
964
170k
                }
965
3.68M
                else if ( bQuote )
966
2.80M
                    ;   // keep it going
967
880k
                else
968
880k
                    eState = ssStopBack;
969
23.3M
            }
970
23.3M
            break;
971
5.36M
            case ssGetString :
972
5.36M
            {
973
5.36M
                if ( nMask & ParserFlags::STRING_SEP )
974
70.1k
                {
975
70.1k
                    if ( cLast == '\\' )
976
2.21k
                    {   // escaped
977
2.21k
                        aSymbol.append(
978
2.21k
                            rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 2)
979
2.21k
                            + OUString(&current, 1));
980
2.21k
                    }
981
67.8k
                    else if (current == nextChar &&
982
5.92k
                            !(nContTypes & KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING) )
983
5.01k
                    {   // "" => literal " escaped
984
5.01k
                        aSymbol.append(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex));
985
5.01k
                        nextCharIndex = index;
986
5.01k
                        if (index < rText.getLength()) { ++nCodePoints; }
987
5.01k
                        nextChar = (index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0;
988
5.01k
                    }
989
62.8k
                    else
990
62.8k
                    {
991
62.8k
                        eState = ssStop;
992
62.8k
                        aSymbol.append(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 1));
993
62.8k
                    }
994
70.1k
                    postSymbolIndex = nextCharIndex;
995
70.1k
                }
996
5.36M
            }
997
5.36M
            break;
998
197k
            case ssGetBool :
999
197k
            {
1000
197k
                if ( nMask & ParserFlags::BOOL )
1001
43.2k
                    eState = ssStop;    // maximum 2: <, >, <>, <=, >=
1002
153k
                else
1003
153k
                    eState = ssStopBack;
1004
197k
            }
1005
197k
            break;
1006
0
            case ssStopBack :
1007
0
            case ssBounce :
1008
0
            case ssStop :
1009
0
                ;   // nothing, no compiler warning
1010
0
            break;
1011
42.0M
        }
1012
42.0M
        if ( eState == ssRewindFromValue )
1013
43.5k
        {
1014
43.5k
            r = ParseResult();
1015
43.5k
            index = nPos;
1016
43.5k
            postSymbolIndex = nPos;
1017
43.5k
            nextCharIndex = nPos;
1018
43.5k
            aSymbol.setLength(0);
1019
43.5k
            current = (index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0;
1020
43.5k
            nCodePoints = (nPos < rText.getLength()) ? 1 : 0;
1021
43.5k
            isFirst = true;
1022
43.5k
            cLast = 0;
1023
43.5k
            nDecSeps = 0;
1024
43.5k
            bQuote = false;
1025
43.5k
            bMightBeWord = true;
1026
43.5k
            bMightBeWordLast = true;
1027
43.5k
            bDecSepAltUsed = false;
1028
43.5k
        }
1029
42.0M
        else
1030
42.0M
        {
1031
42.0M
            if ( !(r.TokenType & nTokenType) )
1032
1.61M
            {
1033
1.61M
                if ( (r.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER))
1034
828
                        && (nTokenType & KParseType::IDENTNAME) && bMightBeWord )
1035
0
                    ;   // keep a number that might be a word
1036
1.61M
                else if (r.LeadingWhiteSpace == (nextCharIndex - nPos))
1037
73.5k
                    ;   // keep ignored white space
1038
1.54M
                else if ( !r.TokenType && eState == ssGetValue && (nMask & ParserFlags::VALUE_SEP) )
1039
186k
                    ;   // keep uncertain value
1040
1.35M
                else
1041
1.35M
                    eState = ssBounce;
1042
1.61M
            }
1043
42.0M
            if ( eState == ssBounce )
1044
1.35M
            {
1045
1.35M
                r.TokenType = 0;
1046
1.35M
                eState = ssStopBack;
1047
1.35M
            }
1048
42.0M
            if ( eState == ssStopBack )
1049
3.13M
            {   // put back
1050
3.13M
                nextChar = rText.iterateCodePoints(&index, -1);
1051
3.13M
                nextCharIndex = nextIndex;
1052
3.13M
                --nCodePoints;
1053
3.13M
                bMightBeWord = bMightBeWordLast;
1054
3.13M
                eState = ssStop;
1055
3.13M
            }
1056
42.0M
            if ( eState != ssStop )
1057
37.9M
            {
1058
37.9M
                if ( !r.StartFlags )
1059
2.48M
                    r.StartFlags |= nParseTokensType;
1060
35.4M
                else
1061
35.4M
                    r.ContFlags |= nParseTokensType;
1062
37.9M
            }
1063
42.0M
            bMightBeWordLast = bMightBeWord;
1064
42.0M
            cLast = current;
1065
42.0M
            current = nextChar;
1066
42.0M
        }
1067
42.0M
    }
1068
    // r.CharLen is the length in characters (not code units) of the parsed
1069
    // token not including any leading white space.
1070
4.36M
    r.CharLen = nCodePoints;
1071
4.36M
    r.EndPos = nextCharIndex;
1072
4.36M
    if ( r.TokenType & KParseType::ASC_NUMBER )
1073
660k
    {
1074
660k
        r.Value = rtl_math_uStringToDouble(rText.getStr() + nPos + r.LeadingWhiteSpace,
1075
660k
            rText.getStr() + r.EndPos, (bDecSepAltUsed ? cDecimalSepAlt : cDecimalSep), cGroupSep, nullptr, nullptr);
1076
660k
        if ( bMightBeWord )
1077
522k
            r.TokenType |= KParseType::IDENTNAME;
1078
660k
    }
1079
3.70M
    else if ( r.TokenType & KParseType::UNI_NUMBER )
1080
9.27k
    {
1081
9.27k
        if ( !xNatNumSup.is() )
1082
12
        {
1083
12
            if ( m_xContext.is() )
1084
12
            {
1085
12
                xNatNumSup = NativeNumberSupplier::create( m_xContext );
1086
12
            }
1087
12
        }
1088
9.27k
        OUString aTmp(rText.getStr() + nPos + r.LeadingWhiteSpace,
1089
9.27k
                r.EndPos - nPos - r.LeadingWhiteSpace);
1090
        // transliterate to ASCII
1091
9.27k
        aTmp = xNatNumSup->getNativeNumberString( aTmp, aParserLocale,
1092
9.27k
                NativeNumberMode::NATNUM0 );
1093
9.27k
        r.Value = ::rtl::math::stringToDouble( aTmp, cDecimalSep, cGroupSep );
1094
9.27k
        if ( bMightBeWord )
1095
6.53k
            r.TokenType |= KParseType::IDENTNAME;
1096
9.27k
    }
1097
3.70M
    else if ( r.TokenType & (KParseType::SINGLE_QUOTE_NAME | KParseType::DOUBLE_QUOTE_STRING) )
1098
157k
    {
1099
157k
        if (postSymbolIndex < nextCharIndex)
1100
44.6k
        {   //! open quote
1101
44.6k
            aSymbol.append(rText.subView(postSymbolIndex, nextCharIndex - postSymbolIndex - 1));
1102
44.6k
            r.TokenType |= KParseType::MISSING_QUOTE;
1103
44.6k
        }
1104
157k
        r.DequotedNameOrString = aSymbol.makeStringAndClear();
1105
157k
    }
1106
4.36M
}
1107
1108
}
1109
1110
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */