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_MODIFIERS_H__ |
8 | #define __NUMBER_MODIFIERS_H__ |
9 | |
10 | #include <algorithm> |
11 | #include <cstdint> |
12 | #include "unicode/uniset.h" |
13 | #include "unicode/simpleformatter.h" |
14 | #include "standardplural.h" |
15 | #include "formatted_string_builder.h" |
16 | #include "number_types.h" |
17 | |
18 | U_NAMESPACE_BEGIN namespace number { |
19 | namespace impl { |
20 | |
21 | /** |
22 | * The canonical implementation of {@link Modifier}, containing a prefix and suffix string. |
23 | * TODO: This is not currently being used by real code and could be removed. |
24 | */ |
25 | class U_I18N_API ConstantAffixModifier : public Modifier, public UObject { |
26 | public: |
27 | ConstantAffixModifier(const UnicodeString &prefix, const UnicodeString &suffix, Field field, |
28 | bool strong) |
29 | : fPrefix(prefix), fSuffix(suffix), fField(field), fStrong(strong) {} |
30 | |
31 | int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
32 | UErrorCode &status) const U_OVERRIDE; |
33 | |
34 | int32_t getPrefixLength() const U_OVERRIDE; |
35 | |
36 | int32_t getCodePointCount() const U_OVERRIDE; |
37 | |
38 | bool isStrong() const U_OVERRIDE; |
39 | |
40 | bool containsField(UNumberFormatFields field) const U_OVERRIDE; |
41 | |
42 | void getParameters(Parameters& output) const U_OVERRIDE; |
43 | |
44 | bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; |
45 | |
46 | private: |
47 | UnicodeString fPrefix; |
48 | UnicodeString fSuffix; |
49 | Field fField; |
50 | bool fStrong; |
51 | }; |
52 | |
53 | /** |
54 | * The second primary implementation of {@link Modifier}, this one consuming a {@link SimpleFormatter} |
55 | * pattern. |
56 | */ |
57 | class U_I18N_API SimpleModifier : public Modifier, public UMemory { |
58 | public: |
59 | SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong); |
60 | |
61 | SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong, |
62 | const Modifier::Parameters parameters); |
63 | |
64 | // Default constructor for LongNameHandler.h |
65 | SimpleModifier(); |
66 | |
67 | int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
68 | UErrorCode &status) const U_OVERRIDE; |
69 | |
70 | int32_t getPrefixLength() const U_OVERRIDE; |
71 | |
72 | int32_t getCodePointCount() const U_OVERRIDE; |
73 | |
74 | bool isStrong() const U_OVERRIDE; |
75 | |
76 | bool containsField(UNumberFormatFields field) const U_OVERRIDE; |
77 | |
78 | void getParameters(Parameters& output) const U_OVERRIDE; |
79 | |
80 | bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; |
81 | |
82 | /** |
83 | * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because |
84 | * FormattedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it. |
85 | * |
86 | * <p> |
87 | * Formats a value that is already stored inside the StringBuilder <code>result</code> between the indices |
88 | * <code>startIndex</code> and <code>endIndex</code> by inserting characters before the start index and after the |
89 | * end index. |
90 | * |
91 | * <p> |
92 | * This is well-defined only for patterns with exactly one argument. |
93 | * |
94 | * @param result |
95 | * The StringBuilder containing the value argument. |
96 | * @param startIndex |
97 | * The left index of the value within the string builder. |
98 | * @param endIndex |
99 | * The right index of the value within the string builder. |
100 | * @return The number of characters (UTF-16 code points) that were added to the StringBuilder. |
101 | */ |
102 | int32_t |
103 | formatAsPrefixSuffix(FormattedStringBuilder& result, int32_t startIndex, int32_t endIndex, |
104 | UErrorCode& status) const; |
105 | |
106 | /** |
107 | * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code. |
108 | * I put it here so that the SimpleFormatter uses in FormattedStringBuilder are near each other. |
109 | * |
110 | * <p> |
111 | * Applies the compiled two-argument pattern to the FormattedStringBuilder. |
112 | * |
113 | * <p> |
114 | * This method is optimized for the case where the prefix and suffix are often empty, such as |
115 | * in the range pattern like "{0}-{1}". |
116 | */ |
117 | static int32_t |
118 | formatTwoArgPattern(const SimpleFormatter& compiled, FormattedStringBuilder& result, |
119 | int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength, |
120 | Field field, UErrorCode& status); |
121 | |
122 | private: |
123 | UnicodeString fCompiledPattern; |
124 | Field fField; |
125 | bool fStrong = false; |
126 | int32_t fPrefixLength = 0; |
127 | int32_t fSuffixOffset = -1; |
128 | int32_t fSuffixLength = 0; |
129 | Modifier::Parameters fParameters; |
130 | }; |
131 | |
132 | /** |
133 | * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed |
134 | * based on the contents of two {@link FormattedStringBuilder} instances (one for the prefix, one for the suffix). |
135 | */ |
136 | class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { |
137 | public: |
138 | ConstantMultiFieldModifier( |
139 | const FormattedStringBuilder &prefix, |
140 | const FormattedStringBuilder &suffix, |
141 | bool overwrite, |
142 | bool strong, |
143 | const Modifier::Parameters parameters) |
144 | : fPrefix(prefix), |
145 | fSuffix(suffix), |
146 | fOverwrite(overwrite), |
147 | fStrong(strong), |
148 | fParameters(parameters) {} |
149 | |
150 | ConstantMultiFieldModifier( |
151 | const FormattedStringBuilder &prefix, |
152 | const FormattedStringBuilder &suffix, |
153 | bool overwrite, |
154 | bool strong) |
155 | : fPrefix(prefix), |
156 | fSuffix(suffix), |
157 | fOverwrite(overwrite), |
158 | fStrong(strong) {} |
159 | |
160 | int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
161 | UErrorCode &status) const U_OVERRIDE; |
162 | |
163 | int32_t getPrefixLength() const U_OVERRIDE; |
164 | |
165 | int32_t getCodePointCount() const U_OVERRIDE; |
166 | |
167 | bool isStrong() const U_OVERRIDE; |
168 | |
169 | bool containsField(UNumberFormatFields field) const U_OVERRIDE; |
170 | |
171 | void getParameters(Parameters& output) const U_OVERRIDE; |
172 | |
173 | bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; |
174 | |
175 | protected: |
176 | // NOTE: In Java, these are stored as array pointers. In C++, the FormattedStringBuilder is stored by |
177 | // value and is treated internally as immutable. |
178 | FormattedStringBuilder fPrefix; |
179 | FormattedStringBuilder fSuffix; |
180 | bool fOverwrite; |
181 | bool fStrong; |
182 | Modifier::Parameters fParameters; |
183 | }; |
184 | |
185 | /** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */ |
186 | class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModifier { |
187 | public: |
188 | /** Safe code path */ |
189 | CurrencySpacingEnabledModifier( |
190 | const FormattedStringBuilder &prefix, |
191 | const FormattedStringBuilder &suffix, |
192 | bool overwrite, |
193 | bool strong, |
194 | const DecimalFormatSymbols &symbols, |
195 | UErrorCode &status); |
196 | |
197 | int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
198 | UErrorCode &status) const U_OVERRIDE; |
199 | |
200 | /** Unsafe code path */ |
201 | static int32_t |
202 | applyCurrencySpacing(FormattedStringBuilder &output, int32_t prefixStart, int32_t prefixLen, |
203 | int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols, |
204 | UErrorCode &status); |
205 | |
206 | private: |
207 | UnicodeSet fAfterPrefixUnicodeSet; |
208 | UnicodeString fAfterPrefixInsert; |
209 | UnicodeSet fBeforeSuffixUnicodeSet; |
210 | UnicodeString fBeforeSuffixInsert; |
211 | |
212 | enum EAffix { |
213 | PREFIX, SUFFIX |
214 | }; |
215 | |
216 | enum EPosition { |
217 | IN_CURRENCY, IN_NUMBER |
218 | }; |
219 | |
220 | /** Unsafe code path */ |
221 | static int32_t applyCurrencySpacingAffix(FormattedStringBuilder &output, int32_t index, EAffix affix, |
222 | const DecimalFormatSymbols &symbols, UErrorCode &status); |
223 | |
224 | static UnicodeSet |
225 | getUnicodeSet(const DecimalFormatSymbols &symbols, EPosition position, EAffix affix, |
226 | UErrorCode &status); |
227 | |
228 | static UnicodeString |
229 | getInsertString(const DecimalFormatSymbols &symbols, EAffix affix, UErrorCode &status); |
230 | }; |
231 | |
232 | /** A Modifier that does not do anything. */ |
233 | class U_I18N_API EmptyModifier : public Modifier, public UMemory { |
234 | public: |
235 | explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {} |
236 | |
237 | int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
238 | UErrorCode &status) const U_OVERRIDE { |
239 | (void)output; |
240 | (void)leftIndex; |
241 | (void)rightIndex; |
242 | (void)status; |
243 | return 0; |
244 | } |
245 | |
246 | int32_t getPrefixLength() const U_OVERRIDE { |
247 | return 0; |
248 | } |
249 | |
250 | int32_t getCodePointCount() const U_OVERRIDE { |
251 | return 0; |
252 | } |
253 | |
254 | bool isStrong() const U_OVERRIDE { |
255 | return fStrong; |
256 | } |
257 | |
258 | bool containsField(UNumberFormatFields field) const U_OVERRIDE { |
259 | (void)field; |
260 | return false; |
261 | } |
262 | |
263 | void getParameters(Parameters& output) const U_OVERRIDE { |
264 | output.obj = nullptr; |
265 | } |
266 | |
267 | bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE { |
268 | return other.getCodePointCount() == 0; |
269 | } |
270 | |
271 | private: |
272 | bool fStrong; |
273 | }; |
274 | |
275 | /** |
276 | * This implementation of ModifierStore adopts Modifer pointers. |
277 | */ |
278 | class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory { |
279 | public: |
280 | virtual ~AdoptingModifierStore(); |
281 | |
282 | static constexpr StandardPlural::Form DEFAULT_STANDARD_PLURAL = StandardPlural::OTHER; |
283 | |
284 | AdoptingModifierStore() = default; |
285 | |
286 | // No copying! |
287 | AdoptingModifierStore(const AdoptingModifierStore &other) = delete; |
288 | |
289 | /** |
290 | * Sets the Modifier with the specified signum and plural form. |
291 | */ |
292 | void adoptModifier(Signum signum, StandardPlural::Form plural, const Modifier *mod) { |
293 | U_ASSERT(mods[getModIndex(signum, plural)] == nullptr); |
294 | mods[getModIndex(signum, plural)] = mod; |
295 | } |
296 | |
297 | /** |
298 | * Sets the Modifier with the specified signum. |
299 | * The modifier will apply to all plural forms. |
300 | */ |
301 | void adoptModifierWithoutPlural(Signum signum, const Modifier *mod) { |
302 | U_ASSERT(mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] == nullptr); |
303 | mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] = mod; |
304 | } |
305 | |
306 | /** Returns a reference to the modifier; no ownership change. */ |
307 | const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE { |
308 | const Modifier* modifier = mods[getModIndex(signum, plural)]; |
309 | if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) { |
310 | modifier = mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)]; |
311 | } |
312 | return modifier; |
313 | } |
314 | |
315 | /** Returns a reference to the modifier; no ownership change. */ |
316 | const Modifier *getModifierWithoutPlural(Signum signum) const { |
317 | return mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)]; |
318 | } |
319 | |
320 | private: |
321 | // NOTE: mods is zero-initialized (to nullptr) |
322 | const Modifier *mods[3 * StandardPlural::COUNT] = {}; |
323 | |
324 | inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) { |
325 | U_ASSERT(signum >= -1 && signum <= 1); |
326 | U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT); |
327 | return static_cast<int32_t>(plural) * 3 + (signum + 1); |
328 | } |
329 | }; |
330 | |
331 | } // namespace impl |
332 | } // namespace number |
333 | U_NAMESPACE_END |
334 | |
335 | |
336 | #endif //__NUMBER_MODIFIERS_H__ |
337 | |
338 | #endif /* #if !UCONFIG_NO_FORMATTING */ |
339 | |