Coverage Report

Created: 2023-03-04 07:00

/src/icu/icu4c/source/i18n/number_mapper.h
Line
Count
Source (jump to first uncovered line)
1
// © 2018 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
4
#include "unicode/utypes.h"
5
6
#if !UCONFIG_NO_FORMATTING
7
#ifndef __NUMBER_MAPPER_H__
8
#define __NUMBER_MAPPER_H__
9
10
#include <atomic>
11
#include "number_types.h"
12
#include "unicode/currpinf.h"
13
#include "standardplural.h"
14
#include "number_patternstring.h"
15
#include "number_currencysymbols.h"
16
#include "numparse_impl.h"
17
18
U_NAMESPACE_BEGIN
19
namespace number {
20
namespace impl {
21
22
23
class AutoAffixPatternProvider;
24
class CurrencyPluralInfoAffixProvider;
25
26
27
class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemory {
28
  public:
29
0
    bool isBogus() const {
30
0
        return fBogus;
31
0
    }
32
33
0
    void setToBogus() {
34
0
        fBogus = true;
35
0
    }
36
37
    void setTo(const DecimalFormatProperties& properties, UErrorCode& status);
38
39
    // AffixPatternProvider Methods:
40
41
    char16_t charAt(int32_t flags, int32_t i) const override;
42
43
    int32_t length(int32_t flags) const override;
44
45
    UnicodeString getString(int32_t flags) const override;
46
47
    bool hasCurrencySign() const override;
48
49
    bool positiveHasPlusSign() const override;
50
51
    bool hasNegativeSubpattern() const override;
52
53
    bool negativeHasMinusSign() const override;
54
55
    bool containsSymbolType(AffixPatternType, UErrorCode&) const override;
56
57
    bool hasBody() const override;
58
59
    bool currencyAsDecimal() const override;
60
61
  private:
62
    UnicodeString posPrefix;
63
    UnicodeString posSuffix;
64
    UnicodeString negPrefix;
65
    UnicodeString negSuffix;
66
    bool isCurrencyPattern;
67
    bool fCurrencyAsDecimal;
68
69
57.2k
    PropertiesAffixPatternProvider() = default; // puts instance in valid but undefined state
70
71
    const UnicodeString& getStringInternal(int32_t flags) const;
72
73
    bool fBogus{true};
74
75
    friend class AutoAffixPatternProvider;
76
    friend class CurrencyPluralInfoAffixProvider;
77
};
78
79
80
class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMemory {
81
  public:
82
15.4k
    bool isBogus() const {
83
15.4k
        return fBogus;
84
15.4k
    }
85
86
6.36k
    void setToBogus() {
87
6.36k
        fBogus = true;
88
6.36k
    }
89
90
    void setTo(const CurrencyPluralInfo& cpi, const DecimalFormatProperties& properties,
91
               UErrorCode& status);
92
93
    // AffixPatternProvider Methods:
94
95
    char16_t charAt(int32_t flags, int32_t i) const override;
96
97
    int32_t length(int32_t flags) const override;
98
99
    UnicodeString getString(int32_t flags) const override;
100
101
    bool hasCurrencySign() const override;
102
103
    bool positiveHasPlusSign() const override;
104
105
    bool hasNegativeSubpattern() const override;
106
107
    bool negativeHasMinusSign() const override;
108
109
    bool containsSymbolType(AffixPatternType, UErrorCode&) const override;
110
111
    bool hasBody() const override;
112
113
    bool currencyAsDecimal() const override;
114
115
  private:
116
    PropertiesAffixPatternProvider affixesByPlural[StandardPlural::COUNT];
117
118
6.36k
    CurrencyPluralInfoAffixProvider() = default;
119
120
    bool fBogus{true};
121
122
    friend class AutoAffixPatternProvider;
123
};
124
125
126
class AutoAffixPatternProvider {
127
  public:
128
3.60k
    inline AutoAffixPatternProvider() = default;
129
130
2.76k
    inline AutoAffixPatternProvider(const DecimalFormatProperties& properties, UErrorCode& status) {
131
2.76k
        setTo(properties, status);
132
2.76k
    }
133
134
6.36k
    inline void setTo(const DecimalFormatProperties& properties, UErrorCode& status) {
135
6.36k
        if (properties.currencyPluralInfo.fPtr.isNull()) {
136
6.36k
            propertiesAPP.setTo(properties, status);
137
6.36k
            currencyPluralInfoAPP.setToBogus();
138
6.36k
        } else {
139
0
            propertiesAPP.setToBogus();
140
0
            currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr, properties, status);
141
0
        }
142
6.36k
    }
143
144
0
    inline void setTo(const AffixPatternProvider* provider, UErrorCode& status) {
145
0
        if (auto ptr = dynamic_cast<const PropertiesAffixPatternProvider*>(provider)) {
146
0
            propertiesAPP = *ptr;
147
0
        } else if (auto ptr = dynamic_cast<const CurrencyPluralInfoAffixProvider*>(provider)) {
148
0
            currencyPluralInfoAPP = *ptr;
149
0
        } else {
150
0
            status = U_INTERNAL_PROGRAM_ERROR;
151
0
        }
152
0
    }
153
154
15.4k
    inline const AffixPatternProvider& get() const {
155
15.4k
      if (!currencyPluralInfoAPP.isBogus()) {
156
0
        return currencyPluralInfoAPP;
157
15.4k
      } else {
158
15.4k
        return propertiesAPP;
159
15.4k
      }
160
15.4k
    }
161
162
  private:
163
    PropertiesAffixPatternProvider propertiesAPP;
164
    CurrencyPluralInfoAffixProvider currencyPluralInfoAPP;
165
};
166
167
168
/**
169
 * A struct for ownership of a few objects needed for formatting.
170
 */
171
struct DecimalFormatWarehouse : public UMemory {
172
    AutoAffixPatternProvider affixProvider;
173
    LocalPointer<PluralRules> rules;
174
};
175
176
177
/**
178
* Internal fields for DecimalFormat.
179
* TODO: Make some of these fields by value instead of by LocalPointer?
180
*/
181
struct DecimalFormatFields : public UMemory {
182
183
623
    DecimalFormatFields() {}
184
185
    DecimalFormatFields(const DecimalFormatProperties& propsToCopy)
186
2.98k
        : properties(propsToCopy) {}
187
188
    /** The property bag corresponding to user-specified settings and settings from the pattern string. */
189
    DecimalFormatProperties properties;
190
191
    /** The symbols for the current locale. */
192
    LocalPointer<const DecimalFormatSymbols> symbols;
193
194
    /**
195
    * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link
196
    * #format} method uses the formatter directly without needing to synchronize.
197
    */
198
    LocalizedNumberFormatter formatter;
199
200
    /** The lazy-computed parser for .parse() */
201
    std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicParser = {};
202
203
    /** The lazy-computed parser for .parseCurrency() */
204
    std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicCurrencyParser = {};
205
206
    /** Small object ownership warehouse for the formatter and parser */
207
    DecimalFormatWarehouse warehouse;
208
209
    /** The effective properties as exported from the formatter object. Used by some getters. */
210
    DecimalFormatProperties exportedProperties;
211
212
    // Data for fastpath
213
    bool canUseFastFormat = false;
214
    struct FastFormatData {
215
        char16_t cpZero;
216
        char16_t cpGroupingSeparator;
217
        char16_t cpMinusSign;
218
        int8_t minInt;
219
        int8_t maxInt;
220
    } fastData;
221
};
222
223
224
/**
225
 * Utilities for converting between a DecimalFormatProperties and a MacroProps.
226
 */
227
class NumberPropertyMapper {
228
  public:
229
    /** Convenience method to create a NumberFormatter directly from Properties. */
230
    static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
231
                                             const DecimalFormatSymbols& symbols,
232
                                             DecimalFormatWarehouse& warehouse, UErrorCode& status);
233
234
    /** Convenience method to create a NumberFormatter directly from Properties. */
235
    static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
236
                                             const DecimalFormatSymbols& symbols,
237
                                             DecimalFormatWarehouse& warehouse,
238
                                             DecimalFormatProperties& exportedProperties,
239
                                             UErrorCode& status);
240
241
    /**
242
     * Creates a new {@link MacroProps} object based on the content of a {@link DecimalFormatProperties}
243
     * object. In other words, maps Properties to MacroProps. This function is used by the
244
     * JDK-compatibility API to call into the ICU 60 fluent number formatting pipeline.
245
     *
246
     * @param properties
247
     *            The property bag to be mapped.
248
     * @param symbols
249
     *            The symbols associated with the property bag.
250
     * @param exportedProperties
251
     *            A property bag in which to store validated properties. Used by some DecimalFormat
252
     *            getters.
253
     * @return A new MacroProps containing all of the information in the Properties.
254
     */
255
    static MacroProps oldToNew(const DecimalFormatProperties& properties,
256
                               const DecimalFormatSymbols& symbols, DecimalFormatWarehouse& warehouse,
257
                               DecimalFormatProperties* exportedProperties, UErrorCode& status);
258
};
259
260
261
} // namespace impl
262
} // namespace numparse
263
U_NAMESPACE_END
264
265
#endif //__NUMBER_MAPPER_H__
266
#endif /* #if !UCONFIG_NO_FORMATTING */