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 | ~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 | ~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 | */ |
120 | void setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille); |
121 | |
122 | /** |
123 | * Sets locale-specific details that affect the symbols substituted into the pattern string affixes. |
124 | * |
125 | * @param symbols |
126 | * The desired instance of DecimalFormatSymbols. |
127 | * @param currencySymbols |
128 | * The currency symbols to be used when substituting currency values into the affixes. |
129 | * @param unitWidth |
130 | * The width used to render currencies. |
131 | * @param rules |
132 | * Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the |
133 | * convenience method {@link #needsPlurals()}. |
134 | */ |
135 | void setSymbols(const DecimalFormatSymbols* symbols, const CurrencySymbols* currencySymbols, |
136 | UNumberUnitWidth unitWidth, const PluralRules* rules); |
137 | |
138 | /** |
139 | * Sets attributes of the current number being processed. |
140 | * |
141 | * @param signum |
142 | * -1 if negative; +1 if positive; or 0 if zero. |
143 | * @param plural |
144 | * The plural form of the number, required only if the pattern contains the triple |
145 | * currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}). |
146 | */ |
147 | void setNumberProperties(Signum signum, StandardPlural::Form plural); |
148 | |
149 | /** |
150 | * Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize. |
151 | * This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤"). |
152 | */ |
153 | bool needsPlurals() const; |
154 | |
155 | /** |
156 | * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable |
157 | * and can be saved for future use. The number properties in the current instance are mutated; all other properties |
158 | * are left untouched. |
159 | * |
160 | * <p> |
161 | * The resulting modifier cannot be used in a QuantityChain. |
162 | * |
163 | * <p> |
164 | * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP. |
165 | * |
166 | * @return An immutable that supports both positive and negative numbers. |
167 | */ |
168 | ImmutablePatternModifier *createImmutable(UErrorCode &status); |
169 | |
170 | MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent); |
171 | |
172 | void processQuantity(DecimalQuantity &, MicroProps µs, UErrorCode &status) const U_OVERRIDE; |
173 | |
174 | int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
175 | UErrorCode &status) const U_OVERRIDE; |
176 | |
177 | int32_t getPrefixLength() const U_OVERRIDE; |
178 | |
179 | int32_t getCodePointCount() const U_OVERRIDE; |
180 | |
181 | bool isStrong() const U_OVERRIDE; |
182 | |
183 | bool containsField(UNumberFormatFields field) const U_OVERRIDE; |
184 | |
185 | void getParameters(Parameters& output) const U_OVERRIDE; |
186 | |
187 | bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; |
188 | |
189 | /** |
190 | * Returns the string that substitutes a given symbol type in a pattern. |
191 | */ |
192 | UnicodeString getSymbol(AffixPatternType type) const U_OVERRIDE; |
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 | |
206 | // Symbol details (initialized in setSymbols) |
207 | const DecimalFormatSymbols *fSymbols; |
208 | UNumberUnitWidth fUnitWidth; |
209 | const CurrencySymbols *fCurrencySymbols; |
210 | const PluralRules *fRules; |
211 | |
212 | // Number details (initialized in setNumberProperties) |
213 | Signum fSignum; |
214 | StandardPlural::Form fPlural; |
215 | |
216 | // QuantityChain details (initialized in addToChain) |
217 | const MicroPropsGenerator *fParent; |
218 | |
219 | // Transient fields for rendering |
220 | UnicodeString currentAffix; |
221 | |
222 | /** |
223 | * Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency spacing support |
224 | * if required. |
225 | * |
226 | * <p> |
227 | * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP. |
228 | * |
229 | * @param a |
230 | * A working FormattedStringBuilder object; passed from the outside to prevent the need to create many new |
231 | * instances if this method is called in a loop. |
232 | * @param b |
233 | * Another working FormattedStringBuilder object. |
234 | * @return The constant modifier object. |
235 | */ |
236 | ConstantMultiFieldModifier *createConstantModifier(UErrorCode &status); |
237 | |
238 | int32_t insertPrefix(FormattedStringBuilder &sb, int position, UErrorCode &status); |
239 | |
240 | int32_t insertSuffix(FormattedStringBuilder &sb, int position, UErrorCode &status); |
241 | |
242 | void prepareAffix(bool isPrefix); |
243 | }; |
244 | |
245 | |
246 | } // namespace impl |
247 | } // namespace number |
248 | U_NAMESPACE_END |
249 | |
250 | #endif //__NUMBER_PATTERNMODIFIER_H__ |
251 | |
252 | #endif /* #if !UCONFIG_NO_FORMATTING */ |
253 | |