/src/mozilla-central/intl/icu/source/i18n/number_modifiers.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_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 "number_stringbuilder.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 | 0 | : fPrefix(prefix), fSuffix(suffix), fField(field), fStrong(strong) {} |
30 | | |
31 | | int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
32 | | UErrorCode &status) const U_OVERRIDE; |
33 | | |
34 | | int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE; |
35 | | |
36 | | int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE; |
37 | | |
38 | | bool isStrong() const U_OVERRIDE; |
39 | | |
40 | | private: |
41 | | UnicodeString fPrefix; |
42 | | UnicodeString fSuffix; |
43 | | Field fField; |
44 | | bool fStrong; |
45 | | }; |
46 | | |
47 | | /** |
48 | | * The second primary implementation of {@link Modifier}, this one consuming a {@link SimpleFormatter} |
49 | | * pattern. |
50 | | */ |
51 | | class U_I18N_API SimpleModifier : public Modifier, public UMemory { |
52 | | public: |
53 | | SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong); |
54 | | |
55 | | // Default constructor for LongNameHandler.h |
56 | | SimpleModifier(); |
57 | | |
58 | | int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
59 | | UErrorCode &status) const U_OVERRIDE; |
60 | | |
61 | | int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE; |
62 | | |
63 | | int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE; |
64 | | |
65 | | bool isStrong() const U_OVERRIDE; |
66 | | |
67 | | /** |
68 | | * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because |
69 | | * DoubleSidedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it. |
70 | | * |
71 | | * <p> |
72 | | * Formats a value that is already stored inside the StringBuilder <code>result</code> between the indices |
73 | | * <code>startIndex</code> and <code>endIndex</code> by inserting characters before the start index and after the |
74 | | * end index. |
75 | | * |
76 | | * <p> |
77 | | * This is well-defined only for patterns with exactly one argument. |
78 | | * |
79 | | * @param result |
80 | | * The StringBuilder containing the value argument. |
81 | | * @param startIndex |
82 | | * The left index of the value within the string builder. |
83 | | * @param endIndex |
84 | | * The right index of the value within the string builder. |
85 | | * @return The number of characters (UTF-16 code points) that were added to the StringBuilder. |
86 | | */ |
87 | | int32_t |
88 | | formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex, Field field, |
89 | | UErrorCode &status) const; |
90 | | |
91 | | private: |
92 | | UnicodeString fCompiledPattern; |
93 | | Field fField; |
94 | | bool fStrong; |
95 | | int32_t fPrefixLength; |
96 | | int32_t fSuffixOffset; |
97 | | int32_t fSuffixLength; |
98 | | }; |
99 | | |
100 | | /** |
101 | | * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed |
102 | | * based on the contents of two {@link NumberStringBuilder} instances (one for the prefix, one for the suffix). |
103 | | */ |
104 | | class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { |
105 | | public: |
106 | | ConstantMultiFieldModifier( |
107 | | const NumberStringBuilder &prefix, |
108 | | const NumberStringBuilder &suffix, |
109 | | bool overwrite, |
110 | | bool strong) |
111 | | : fPrefix(prefix), |
112 | | fSuffix(suffix), |
113 | | fOverwrite(overwrite), |
114 | 0 | fStrong(strong) {} |
115 | | |
116 | | int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
117 | | UErrorCode &status) const U_OVERRIDE; |
118 | | |
119 | | int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE; |
120 | | |
121 | | int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE; |
122 | | |
123 | | bool isStrong() const U_OVERRIDE; |
124 | | |
125 | | protected: |
126 | | // NOTE: In Java, these are stored as array pointers. In C++, the NumberStringBuilder is stored by |
127 | | // value and is treated internally as immutable. |
128 | | NumberStringBuilder fPrefix; |
129 | | NumberStringBuilder fSuffix; |
130 | | bool fOverwrite; |
131 | | bool fStrong; |
132 | | }; |
133 | | |
134 | | /** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */ |
135 | | class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModifier { |
136 | | public: |
137 | | /** Safe code path */ |
138 | | CurrencySpacingEnabledModifier( |
139 | | const NumberStringBuilder &prefix, |
140 | | const NumberStringBuilder &suffix, |
141 | | bool overwrite, |
142 | | bool strong, |
143 | | const DecimalFormatSymbols &symbols, |
144 | | UErrorCode &status); |
145 | | |
146 | | int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
147 | | UErrorCode &status) const U_OVERRIDE; |
148 | | |
149 | | /** Unsafe code path */ |
150 | | static int32_t |
151 | | applyCurrencySpacing(NumberStringBuilder &output, int32_t prefixStart, int32_t prefixLen, |
152 | | int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols, |
153 | | UErrorCode &status); |
154 | | |
155 | | private: |
156 | | UnicodeSet fAfterPrefixUnicodeSet; |
157 | | UnicodeString fAfterPrefixInsert; |
158 | | UnicodeSet fBeforeSuffixUnicodeSet; |
159 | | UnicodeString fBeforeSuffixInsert; |
160 | | |
161 | | enum EAffix { |
162 | | PREFIX, SUFFIX |
163 | | }; |
164 | | |
165 | | enum EPosition { |
166 | | IN_CURRENCY, IN_NUMBER |
167 | | }; |
168 | | |
169 | | /** Unsafe code path */ |
170 | | static int32_t applyCurrencySpacingAffix(NumberStringBuilder &output, int32_t index, EAffix affix, |
171 | | const DecimalFormatSymbols &symbols, UErrorCode &status); |
172 | | |
173 | | static UnicodeSet |
174 | | getUnicodeSet(const DecimalFormatSymbols &symbols, EPosition position, EAffix affix, |
175 | | UErrorCode &status); |
176 | | |
177 | | static UnicodeString |
178 | | getInsertString(const DecimalFormatSymbols &symbols, EAffix affix, UErrorCode &status); |
179 | | }; |
180 | | |
181 | | /** A Modifier that does not do anything. */ |
182 | | class U_I18N_API EmptyModifier : public Modifier, public UMemory { |
183 | | public: |
184 | 0 | explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {} |
185 | | |
186 | | int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, |
187 | 0 | UErrorCode &status) const U_OVERRIDE { |
188 | 0 | (void)output; |
189 | 0 | (void)leftIndex; |
190 | 0 | (void)rightIndex; |
191 | 0 | (void)status; |
192 | 0 | return 0; |
193 | 0 | } |
194 | | |
195 | 0 | int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE { |
196 | 0 | (void)status; |
197 | 0 | return 0; |
198 | 0 | } |
199 | | |
200 | 0 | int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE { |
201 | 0 | (void)status; |
202 | 0 | return 0; |
203 | 0 | } |
204 | | |
205 | 0 | bool isStrong() const U_OVERRIDE { |
206 | 0 | return fStrong; |
207 | 0 | } |
208 | | |
209 | | private: |
210 | | bool fStrong; |
211 | | }; |
212 | | |
213 | | /** |
214 | | * A ParameterizedModifier by itself is NOT a Modifier. Rather, it wraps a data structure containing two or more |
215 | | * Modifiers and returns the modifier appropriate for the current situation. |
216 | | */ |
217 | | class U_I18N_API ParameterizedModifier : public UMemory { |
218 | | public: |
219 | | // NOTE: mods is zero-initialized (to nullptr) |
220 | 0 | ParameterizedModifier() : mods() { |
221 | 0 | } |
222 | | |
223 | | // No copying! |
224 | | ParameterizedModifier(const ParameterizedModifier &other) = delete; |
225 | | |
226 | 0 | ~ParameterizedModifier() { |
227 | 0 | for (const Modifier *mod : mods) { |
228 | 0 | delete mod; |
229 | 0 | } |
230 | 0 | } |
231 | | |
232 | | void adoptPositiveNegativeModifiers( |
233 | 0 | const Modifier *positive, const Modifier *zero, const Modifier *negative) { |
234 | 0 | mods[2] = positive; |
235 | 0 | mods[1] = zero; |
236 | 0 | mods[0] = negative; |
237 | 0 | } |
238 | | |
239 | | /** The modifier is ADOPTED. */ |
240 | 0 | void adoptSignPluralModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) { |
241 | 0 | mods[getModIndex(signum, plural)] = mod; |
242 | 0 | } |
243 | | |
244 | | /** Returns a reference to the modifier; no ownership change. */ |
245 | 0 | const Modifier *getModifier(int8_t signum) const { |
246 | 0 | return mods[signum + 1]; |
247 | 0 | } |
248 | | |
249 | | /** Returns a reference to the modifier; no ownership change. */ |
250 | 0 | const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const { |
251 | 0 | return mods[getModIndex(signum, plural)]; |
252 | 0 | } |
253 | | |
254 | | private: |
255 | | const Modifier *mods[3 * StandardPlural::COUNT]; |
256 | | |
257 | 0 | inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) { |
258 | 0 | return static_cast<int32_t>(plural) * 3 + (signum + 1); |
259 | 0 | } |
260 | | }; |
261 | | |
262 | | } // namespace impl |
263 | | } // namespace number |
264 | | U_NAMESPACE_END |
265 | | |
266 | | |
267 | | #endif //__NUMBER_MODIFIERS_H__ |
268 | | |
269 | | #endif /* #if !UCONFIG_NO_FORMATTING */ |