Coverage Report

Created: 2025-06-24 06:43

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