Coverage Report

Created: 2025-12-07 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/icu4c/source/i18n/number_patternmodifier.h
Line
Count
Source
1
// © 2017 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_PATTERNMODIFIER_H__
8
#define __NUMBER_PATTERNMODIFIER_H__
9
10
#include "standardplural.h"
11
#include "unicode/numberformatter.h"
12
#include "number_patternstring.h"
13
#include "number_types.h"
14
#include "number_modifiers.h"
15
#include "number_utils.h"
16
#include "number_currencysymbols.h"
17
18
U_NAMESPACE_BEGIN
19
20
namespace number::impl {
21
22
// Forward declaration
23
class MutablePatternModifier;
24
25
// Exported as U_I18N_API_CLASS because it is needed for the unit test PatternModifierTest
26
class U_I18N_API_CLASS ImmutablePatternModifier : public MicroPropsGenerator, public UMemory {
27
  public:
28
286
    ~ImmutablePatternModifier() override = default;
29
30
    void processQuantity(DecimalQuantity&, MicroProps& micros, UErrorCode& status) const override;
31
32
    U_I18N_API void applyToMicros(MicroProps& micros,
33
                                  const DecimalQuantity& quantity,
34
                                  UErrorCode& status) const;
35
36
    const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const;
37
38
    // Non-const method:
39
    void addToChain(const MicroPropsGenerator* parent);
40
41
  private:
42
    ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules);
43
44
    const LocalPointer<AdoptingModifierStore> pm;
45
    const PluralRules* rules;
46
    const MicroPropsGenerator* parent;
47
48
    friend class MutablePatternModifier;
49
};
50
51
/**
52
 * This class is a {@link Modifier} that wraps a decimal format pattern. It applies the pattern's affixes in
53
 * {@link Modifier#apply}.
54
 *
55
 * <p>
56
 * In addition to being a Modifier, this class contains the business logic for substituting the correct locale symbols
57
 * into the affixes of the decimal format pattern.
58
 *
59
 * <p>
60
 * In order to use this class, create a new instance and call the following four setters: {@link #setPatternInfo},
61
 * {@link #setPatternAttributes}, {@link #setSymbols}, and {@link #setNumberProperties}. After calling these four
62
 * setters, the instance will be ready for use as a Modifier.
63
 *
64
 * <p>
65
 * This is a MUTABLE, NON-THREAD-SAFE class designed for performance. Do NOT save references to this or attempt to use
66
 * it from multiple threads! Instead, you can obtain a safe, immutable decimal format pattern modifier by calling
67
 * {@link MutablePatternModifier#createImmutable}, in effect treating this instance as a builder for the immutable
68
 * variant.
69
 */
70
class U_I18N_API_CLASS MutablePatternModifier
71
        : public MicroPropsGenerator,
72
          public Modifier,
73
          public SymbolProvider,
74
          public UMemory {
75
  public:
76
77
98.9k
    ~MutablePatternModifier() override = default;
78
79
    /**
80
     * @param isStrong
81
     *            Whether the modifier should be considered strong. For more information, see
82
     *            {@link Modifier#isStrong()}. Most of the time, decimal format pattern modifiers should be considered
83
     *            as non-strong.
84
     */
85
    U_I18N_API explicit MutablePatternModifier(bool isStrong);
86
87
    /**
88
     * Sets a reference to the parsed decimal format pattern, usually obtained from
89
     * {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is
90
     * accepted.
91
     *
92
     * @param field
93
     *            Which field to use for literal characters in the pattern.
94
     */
95
    U_I18N_API void setPatternInfo(const AffixPatternProvider *patternInfo, Field field);
96
97
    /**
98
     * Sets attributes that imply changes to the literal interpretation of the pattern string affixes.
99
     *
100
     * @param signDisplay
101
     *            Whether to force a plus sign on positive numbers.
102
     * @param perMille
103
     *            Whether to substitute the percent sign in the pattern with a permille sign.
104
     * @param approximately
105
     *            Whether to prepend approximately to the sign
106
     */
107
    U_I18N_API void setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille,
108
                                         bool approximately);
109
110
    /**
111
     * Sets locale-specific details that affect the symbols substituted into the pattern string affixes.
112
     *
113
     * @param symbols
114
     *            The desired instance of DecimalFormatSymbols.
115
     * @param currency
116
     *            The currency to be used when substituting currency values into the affixes.
117
     * @param unitWidth
118
     *            The width used to render currencies.
119
     * @param rules
120
     *            Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the
121
     *            convenience method {@link #needsPlurals()}.
122
     * @param status
123
     *            Set if an error occurs while loading currency data.
124
     */
125
    U_I18N_API void setSymbols(const DecimalFormatSymbols* symbols, const CurrencyUnit& currency,
126
                               UNumberUnitWidth unitWidth, const PluralRules* rules, UErrorCode& status);
127
128
    /**
129
     * Sets attributes of the current number being processed.
130
     *
131
     * @param signum
132
     *            -1 if negative; +1 if positive; or 0 if zero.
133
     * @param plural
134
     *            The plural form of the number, required only if the pattern contains the triple
135
     *            currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
136
     */
137
    U_I18N_API void setNumberProperties(Signum signum, StandardPlural::Form plural);
138
139
    /**
140
     * Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize.
141
     * This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤").
142
     */
143
    bool needsPlurals() const;
144
145
    /** Creates a quantity-dependent Modifier for the specified plural form. */
146
    U_I18N_API AdoptingSignumModifierStore createImmutableForPlural(StandardPlural::Form plural,
147
                                                                    UErrorCode& status);
148
149
    /**
150
     * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable
151
     * and can be saved for future use. The number properties in the current instance are mutated; all other properties
152
     * are left untouched.
153
     *
154
     * <p>
155
     * The resulting modifier cannot be used in a QuantityChain.
156
     *
157
     * <p>
158
     * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
159
     *
160
     * @return An immutable that supports both positive and negative numbers.
161
     */
162
    U_I18N_API ImmutablePatternModifier *createImmutable(UErrorCode &status);
163
164
    U_I18N_API MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent);
165
166
    U_I18N_API void processQuantity(DecimalQuantity &, MicroProps &micros,
167
                                    UErrorCode &status) const override;
168
169
    U_I18N_API int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
170
                             UErrorCode &status) const override;
171
172
    int32_t getPrefixLength() const override;
173
174
    int32_t getCodePointCount() const override;
175
176
    bool isStrong() const override;
177
178
    bool containsField(Field field) const override;
179
180
    void getParameters(Parameters& output) const override;
181
182
    bool strictEquals(const Modifier& other) const override;
183
184
    /**
185
     * Returns the string that substitutes a given symbol type in a pattern.
186
     */
187
    UnicodeString getSymbol(AffixPatternType type) const override;
188
189
    /**
190
     * Returns the currency symbol for the unit width specified in setSymbols()
191
     */
192
    UnicodeString getCurrencySymbolForUnitWidth(UErrorCode& status) const;
193
194
    UnicodeString toUnicodeString() const;
195
196
  private:
197
    // Modifier details (initialized in constructor)
198
    const bool fStrong;
199
200
    // Pattern details (initialized in setPatternInfo and setPatternAttributes)
201
    const AffixPatternProvider *fPatternInfo;
202
    Field fField;
203
    UNumberSignDisplay fSignDisplay;
204
    bool fPerMilleReplacesPercent;
205
    bool fApproximately;
206
207
    // Symbol details (initialized in setSymbols)
208
    const DecimalFormatSymbols *fSymbols;
209
    UNumberUnitWidth fUnitWidth;
210
    CurrencySymbols fCurrencySymbols;
211
    const PluralRules *fRules;
212
213
    // Number details (initialized in setNumberProperties)
214
    Signum fSignum;
215
    StandardPlural::Form fPlural;
216
217
    // QuantityChain details (initialized in addToChain)
218
    const MicroPropsGenerator *fParent;
219
220
    // Transient fields for rendering
221
    UnicodeString currentAffix;
222
223
    /**
224
     * Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency spacing support
225
     * if required.
226
     *
227
     * <p>
228
     * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
229
     *
230
     * @param a
231
     *            A working FormattedStringBuilder object; passed from the outside to prevent the need to create many new
232
     *            instances if this method is called in a loop.
233
     * @param b
234
     *            Another working FormattedStringBuilder object.
235
     * @return The constant modifier object.
236
     */
237
    ConstantMultiFieldModifier *createConstantModifier(UErrorCode &status);
238
239
    int32_t insertPrefix(FormattedStringBuilder &sb, int position, UErrorCode &status);
240
241
    int32_t insertSuffix(FormattedStringBuilder &sb, int position, UErrorCode &status);
242
243
    void prepareAffix(bool isPrefix);
244
};
245
246
} // namespace number::impl
247
248
U_NAMESPACE_END
249
250
#endif //__NUMBER_PATTERNMODIFIER_H__
251
252
#endif /* #if !UCONFIG_NO_FORMATTING */