Coverage Report

Created: 2025-06-24 06:54

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