Coverage Report

Created: 2025-06-24 06:43

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