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