Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/svl/source/numbers/zforscan.hxx
Line
Count
Source (jump to first uncovered line)
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
#ifndef INCLUDED_SVL_SOURCE_NUMBERS_ZFORSCAN_HXX
20
#define INCLUDED_SVL_SOURCE_NUMBERS_ZFORSCAN_HXX
21
22
#include <i18nlangtag/lang.h>
23
#include <rtl/ustring.hxx>
24
#include <svl/nfkeytab.hxx>
25
#include <svl/nfsymbol.hxx>
26
#include <svl/numformat.hxx>
27
#include <svl/zforlist.hxx>
28
#include <tools/color.hxx>
29
#include <tools/date.hxx>
30
#include <unotools/localedatawrapper.hxx>
31
32
struct ImpSvNumberformatInfo;
33
34
35
const size_t NF_MAX_DEFAULT_COLORS   = 10;
36
37
// Hack: nThousand==1000 => "Default" occurs in format string
38
const sal_uInt16 FLAG_STANDARD_IN_FORMAT = 1000;
39
40
class ImpSvNumberformatScan
41
{
42
public:
43
44
    /** Specify what keyword localization is allowed when scanning the format code. */
45
    enum class KeywordLocalization
46
    {
47
        LocaleLegacy,   ///< unfortunately localized in few locales, otherwise English
48
        EnglishOnly,    ///< only English, no localized keywords
49
        AllowEnglish    ///< allow English keywords as well as localized keywords
50
    };
51
52
    explicit ImpSvNumberformatScan(SvNFLanguageData& rCurrentLanguageData,
53
                                   const SvNumberFormatter& rColorCallback,
54
                                   const Date& aNullDate = Date(30, 12, 1899));
55
    ~ImpSvNumberformatScan();
56
    void ChangeIntl( KeywordLocalization eKeywordLocalization = KeywordLocalization::AllowEnglish ); // Replaces Keywords
57
58
    void ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear); // Replaces reference date
59
    void ChangeStandardPrec(sal_uInt16 nPrec); // Replaces standard precision
60
61
    sal_Int32 ScanFormat( OUString& rString ); // Call scan analysis
62
63
    void CopyInfo(ImpSvNumberformatInfo* pInfo,
64
                     sal_uInt16 nCnt); // Copies the FormatInfo
65
28.6M
    sal_uInt16 GetResultStringsCnt() const      { return nResultStringsCnt; }
66
67
2.77M
    const CharClass& GetChrCls() const          { return *mrCurrentLanguageData.GetCharClass(); }
68
1.19M
    const LocaleDataWrapper& GetLoc() const     { return *mrCurrentLanguageData.GetLocaleData(); }
69
70
    const NfKeywordTable & GetKeywords() const
71
110M
        {
72
110M
            if ( bKeywordsNeedInit )
73
220k
            {
74
220k
                InitKeywords();
75
220k
            }
76
110M
            return sKeyword;
77
110M
        }
78
79
    static const NfKeywordTable & GetEnglishKeywords()
80
0
        {
81
0
            return sEnglishKeyword;
82
0
        }
83
84
    // Keywords used in output like true and false
85
    const OUString& GetSpecialKeyword( NfKeywordIndex eIdx ) const
86
5.05M
        {
87
5.05M
            if ( sKeyword[eIdx].isEmpty() )
88
64.7k
            {
89
64.7k
                InitSpecialKeyword( eIdx );
90
64.7k
            }
91
5.05M
            return sKeyword[eIdx];
92
5.05M
        }
93
2.53M
    const OUString& GetTrueString() const     { return GetSpecialKeyword( NF_KEY_TRUE ); }
94
2.52M
    const OUString& GetFalseString() const    { return GetSpecialKeyword( NF_KEY_FALSE ); }
95
62.7k
    const OUString& GetRedString() const      { return GetKeywords()[NF_KEY_RED]; }
96
262k
    const OUString& GetBooleanString() const  { return GetKeywords()[NF_KEY_BOOLEAN]; }
97
    static const ::std::vector<Color> & GetStandardColors()
98
0
        {
99
0
            return StandardColor;
100
0
        }
101
    static size_t GetMaxDefaultColors()
102
0
        {
103
0
            return NF_MAX_DEFAULT_COLORS;
104
0
        }
105
106
926k
    const Date& GetNullDate() const           { return maNullDate; }
107
    const OUString& GetStandardName() const
108
6.67k
        {
109
6.67k
            if ( bKeywordsNeedInit )
110
51
            {
111
51
                InitKeywords();
112
51
            }
113
6.67k
            return sNameStandardFormat;
114
6.67k
        }
115
734k
    sal_uInt16 GetStandardPrec() const          { return nStandardPrec; }
116
0
    static const Color& GetRedColor()           { return StandardColor[4]; }
117
    const Color* GetColor(OUString& sStr) const; // Set main colors or defines colors
118
119
    // the compatibility currency symbol for old automatic currency formats
120
    const OUString& GetCurSymbol() const
121
28.5M
        {
122
28.5M
            if ( bCompatCurNeedInit )
123
0
            {
124
0
                InitCompatCur();
125
0
            }
126
28.5M
            return sCurSymbol;
127
28.5M
        }
128
129
    // the compatibility currency abbreviation for CCC format code
130
    const OUString& GetCurAbbrev() const
131
287
        {
132
287
            if ( bCompatCurNeedInit )
133
23
            {
134
23
                InitCompatCur();
135
23
            }
136
287
            return sCurAbbrev;
137
287
        }
138
139
    // the compatibility currency symbol upper case for old automatic currency formats
140
    const OUString& GetCurString() const
141
57.2M
        {
142
57.2M
            if ( bCompatCurNeedInit )
143
0
            {
144
0
                InitCompatCur();
145
0
            }
146
57.2M
            return sCurString;
147
57.2M
        }
148
149
    /// Replace Boolean equivalent format codes with proper Boolean format.
150
    bool ReplaceBooleanEquivalent( OUString& rString );
151
152
    void SetConvertMode(LanguageType eTmpLge, LanguageType eNewLge,
153
            bool bSystemToSystem, bool bConvertDateOrder)
154
838k
    {
155
838k
        bConvertMode = true;
156
838k
        eNewLnge = eNewLge;
157
838k
        eTmpLnge = eTmpLge;
158
838k
        bConvertSystemToSystem = bSystemToSystem;
159
838k
        mbConvertDateOrder = bConvertDateOrder;
160
838k
    }
161
    // Only changes the bool variable, in order to temporarily pause the convert mode
162
896k
    void SetConvertMode(bool bMode) { bConvertMode = bMode; }
163
53.7M
    bool GetConvertMode() const     { return bConvertMode; }
164
838k
    LanguageType GetNewLnge() const { return eNewLnge; } // Read access on ConvertMode and convert country/language
165
1.09M
    LanguageType GetTmpLnge() const { return eTmpLnge; } // Read access on StartCountry/Language
166
73.7k
    void SetNewLnge( LanguageType e ) { eNewLnge = e; }  // Set new convert country/language
167
168
                                                /// get Thai T speciality
169
28.5M
    sal_uInt8 GetNatNumModifier() const      { return nNatNumModifier; }
170
                                                /// set Thai T speciality
171
0
    void SetNatNumModifier( sal_uInt8 n )    { nNatNumModifier = n; }
172
173
27.0M
    SvNFLanguageData& GetCurrentLanguageData() { return mrCurrentLanguageData; } // Access to formatter (for zformat.cxx)
174
175
    /// Get type scanned (so far).
176
3.91M
    SvNumFormatType GetScannedType() const { return eScannedType; }
177
178
72.3k
    const SvNumberFormatter& getColorCallback() const { return mrColorCallback; }
179
180
    static constexpr OUString sErrStr = u"#FMT"_ustr; // String for error output
181
182
private: // Private section
183
    NfKeywordTable sKeyword;                    // Syntax keywords
184
    static const NfKeywordTable sEnglishKeyword; // English Syntax keywords
185
    static const ::std::vector<Color> StandardColor;  // Standard color array
186
    Date maNullDate;                            // 30Dec1899
187
    OUString sNameStandardFormat;               // "Standard"
188
    sal_uInt16 nStandardPrec;                   // Default Precision for Standardformat
189
    SvNFLanguageData& mrCurrentLanguageData;    // Reference to the Language Data
190
    const SvNumberFormatter& mrColorCallback;   // Reference to the Color Callback supplier
191
    css::uno::Reference< css::i18n::XNumberFormatCode > xNFC;
192
193
    OUString sStrArray[NF_MAX_FORMAT_SYMBOLS];  // Array of symbols
194
    short nTypeArray[NF_MAX_FORMAT_SYMBOLS];    // Array of infos
195
                                                // External Infos:
196
    sal_uInt16 nResultStringsCnt;               // Result symbol count
197
    SvNumFormatType eScannedType;               // Type according to scan
198
    bool bThousand;                             // With thousands marker
199
    sal_uInt16 nThousand;                       // Counts ... series
200
    sal_uInt16 nCntPre;                         // Counts digits of integral part
201
    sal_uInt16 nCntPost;                        // Counts digits of fractional part
202
    sal_uInt16 nCntExp;                         // Counts exponent digits AM/PM
203
                                                // Internal info:
204
    sal_uInt16 nStringsCnt;                     // Symbol count
205
    sal_uInt16 nExpPos;                         // Internal position of E
206
    sal_uInt16 nBlankPos;                       // Internal position of the Blank
207
    short nDecPos;                              // Internal position of the ,
208
    bool bExp;                                  // Set when reading E
209
    bool bFrac;                                 // Set when reading /
210
    bool bBlank;                                // Set when reading ' ' (Fraction)
211
    bool bDecSep;                               // Set on first ,
212
    mutable bool bKeywordsNeedInit;             // Locale dependent keywords need to be initialized
213
    mutable bool bCompatCurNeedInit;            // Locale dependent compatibility currency need to be initialized
214
    OUString sCurSymbol;                        // Currency symbol for compatibility format codes
215
    OUString sCurString;                        // Currency symbol in upper case
216
    OUString sCurAbbrev;                        // Currency abbreviation
217
    OUString sBooleanEquivalent1;               // "TRUE";"TRUE";"FALSE"
218
    OUString sBooleanEquivalent2;               // [>0]"TRUE";[<0]"TRUE";"FALSE"
219
220
    bool bConvertMode;                          // Set in the convert mode
221
    bool mbConvertDateOrder;                    // Set in the convert mode whether to convert date particles order
222
223
    LanguageType eNewLnge;                      // Language/country which the scanned string is converted to (for Excel filter)
224
    LanguageType eTmpLnge;                      // Language/country which the scanned string is converted from (for Excel filter)
225
226
    bool bConvertSystemToSystem;                // Whether the conversion is from one system locale to another system locale
227
                                                // (in this case the automatic currency symbol is converted too).
228
229
    sal_Int32 nCurrPos;                         // Position of currency symbol
230
231
    sal_uInt8 nNatNumModifier;                  // Thai T speciality
232
233
    KeywordLocalization meKeywordLocalization;  ///< which keywords localization to scan
234
235
    // Copy assignment is forbidden and not implemented.
236
    ImpSvNumberformatScan (const ImpSvNumberformatScan &) = delete;
237
    ImpSvNumberformatScan & operator= (const ImpSvNumberformatScan &) = delete;
238
239
    void InitKeywords() const;
240
    void InitSpecialKeyword( NfKeywordIndex eIdx ) const;
241
    void InitCompatCur() const;
242
243
    void SetDependentKeywords();
244
                                                // Sets the language dependent keywords
245
    void SkipStrings(sal_uInt16& i, sal_Int32& nPos) const;// Skips StringSymbols
246
    sal_uInt16 PreviousKeyword(sal_uInt16 i) const;  // Returns index of the preceding one
247
                                                // Keyword or 0
248
    sal_uInt16 NextKeyword(sal_uInt16 i) const; // Returns index of the next one
249
                                                // Keyword or 0
250
    sal_Unicode PreviousChar(sal_uInt16 i) const; // Returns last char before index skips EMPTY, STRING, STAR, BLANK
251
    sal_Unicode NextChar(sal_uInt16 i) const;   // Returns first following char
252
    short PreviousType( sal_uInt16 i ) const;   // Returns type before position skips EMPTY
253
    bool IsLastBlankBeforeFrac(sal_uInt16 i) const; // True <=> there won't be a ' ' until the '/'
254
    void Reset();                               // Reset all variables before starting the analysis
255
256
    /** Determine keyword at nPos.
257
        @param  rbFoundEnglish set if English instead of locale's keyword
258
                found, never cleared, thus init with false.
259
        @return 0 if not found, else keyword enumeration.
260
     */
261
    short GetKeyWord( const OUString& sSymbol,
262
                      sal_Int32 nPos,
263
                      bool& rbFoundEnglish ) const;
264
265
    bool IsAmbiguousE( short nKey ) const  // whether nKey is ambiguous E of NF_KEY_E/NF_KEY_EC
266
50.8M
        {
267
50.8M
            return (nKey == NF_KEY_EC || nKey == NF_KEY_E) &&
268
50.8M
                (GetKeywords()[NF_KEY_EC] == GetKeywords()[NF_KEY_E]);
269
50.8M
        }
270
271
    // if 0 at strArray[i] is of S,00 or SS,00 or SS"any"00 in ScanType() or FinalScan()
272
    bool Is100SecZero( sal_uInt16 i, bool bHadDecSep ) const;
273
274
    short Next_Symbol(const OUString& rStr,
275
                      sal_Int32& nPos,
276
                      OUString& sSymbol) const; // Next Symbol
277
    sal_Int32 Symbol_Division(const OUString& rString);// Initial lexical scan
278
    sal_Int32 ScanType(); // Analysis of the Format type
279
    sal_Int32 FinalScan( OUString& rString ); // Final analysis with supplied type
280
281
    // -1:= error, return nPos in FinalScan; 0:= no calendar, 1:= calendar found
282
    int FinalScanGetCalendar( sal_Int32& nPos, sal_uInt16& i, sal_uInt16& nResultStringsCnt );
283
284
    /** Insert symbol into nTypeArray and sStrArray, e.g. grouping separator.
285
        If at nPos-1 a symbol type NF_SYMBOLTYPE_EMPTY is present, that is
286
        reused instead of shifting all one up and nPos is decremented! */
287
    bool InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const OUString& rStr );
288
289
    /** Whether two key symbols are adjacent separated by date separator.
290
        This can only be used at the end of FinalScan() after
291
        NF_SYMBOLTYPE_DATESEP has already been set.
292
     */
293
    bool IsDateFragment( size_t nPos1, size_t nPos2 ) const;
294
295
    /** Swap nTypeArray and sStrArray elements at positions. */
296
    void SwapArrayElements( size_t nPos1, size_t nPos2 );
297
298
    Color* GetUserDefColor(sal_uInt16 nIndex) const;
299
300
    static bool StringEqualsChar( std::u16string_view rStr, sal_Unicode ch )
301
513M
        { return rStr.size() == 1 && rStr[0] == ch; }
302
303
    // remove "..." and \... quotes from rStr, return how many chars removed
304
    static sal_Int32 RemoveQuotes( OUString& rStr );
305
};
306
307
#endif // INCLUDED_SVL_SOURCE_NUMBERS_ZFORSCAN_HXX
308
309
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */