]>
Commit | Line | Data |
---|---|---|
0f5d89e8 A |
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_TYPES_H__ | |
8 | #define __NUMBER_TYPES_H__ | |
9 | ||
10 | #include <cstdint> | |
11 | #include "unicode/decimfmt.h" | |
12 | #include "unicode/unum.h" | |
13 | #include "unicode/numsys.h" | |
14 | #include "unicode/numberformatter.h" | |
15 | #include "unicode/utf16.h" | |
16 | #include "uassert.h" | |
17 | #include "unicode/platform.h" | |
18 | #include "unicode/uniset.h" | |
3d1f044b | 19 | #include "standardplural.h" |
340931cb | 20 | #include "formatted_string_builder.h" |
0f5d89e8 | 21 | |
340931cb A |
22 | U_NAMESPACE_BEGIN |
23 | namespace number { | |
0f5d89e8 A |
24 | namespace impl { |
25 | ||
340931cb A |
26 | // For convenience and historical reasons, import the Field typedef to the namespace. |
27 | typedef FormattedStringBuilder::Field Field; | |
0f5d89e8 | 28 | |
340931cb | 29 | // Typedef several enums for brevity and for easier comparison to Java. |
0f5d89e8 A |
30 | |
31 | typedef UNumberFormatRoundingMode RoundingMode; | |
32 | ||
33 | typedef UNumberFormatPadPosition PadPosition; | |
34 | ||
35 | typedef UNumberCompactStyle CompactStyle; | |
36 | ||
37 | // ICU4J Equivalent: RoundingUtils.MAX_INT_FRAC_SIG | |
38 | static constexpr int32_t kMaxIntFracSig = 999; | |
39 | ||
40 | // ICU4J Equivalent: RoundingUtils.DEFAULT_ROUNDING_MODE | |
41 | static constexpr RoundingMode kDefaultMode = RoundingMode::UNUM_FOUND_HALFEVEN; | |
42 | ||
43 | // ICU4J Equivalent: Padder.FALLBACK_PADDING_STRING | |
44 | static constexpr char16_t kFallbackPaddingString[] = u" "; | |
45 | ||
46 | // Forward declarations: | |
47 | ||
48 | class Modifier; | |
49 | class MutablePatternModifier; | |
50 | class DecimalQuantity; | |
3d1f044b | 51 | class ModifierStore; |
0f5d89e8 A |
52 | struct MicroProps; |
53 | ||
54 | ||
55 | enum AffixPatternType { | |
56 | // Represents a literal character; the value is stored in the code point field. | |
57 | TYPE_CODEPOINT = 0, | |
58 | ||
59 | // Represents a minus sign symbol '-'. | |
60 | TYPE_MINUS_SIGN = -1, | |
61 | ||
62 | // Represents a plus sign symbol '+'. | |
63 | TYPE_PLUS_SIGN = -2, | |
64 | ||
65 | // Represents a percent sign symbol '%'. | |
66 | TYPE_PERCENT = -3, | |
67 | ||
68 | // Represents a permille sign symbol '‰'. | |
69 | TYPE_PERMILLE = -4, | |
70 | ||
71 | // Represents a single currency symbol '¤'. | |
72 | TYPE_CURRENCY_SINGLE = -5, | |
73 | ||
74 | // Represents a double currency symbol '¤¤'. | |
75 | TYPE_CURRENCY_DOUBLE = -6, | |
76 | ||
77 | // Represents a triple currency symbol '¤¤¤'. | |
78 | TYPE_CURRENCY_TRIPLE = -7, | |
79 | ||
80 | // Represents a quadruple currency symbol '¤¤¤¤'. | |
81 | TYPE_CURRENCY_QUAD = -8, | |
82 | ||
83 | // Represents a quintuple currency symbol '¤¤¤¤¤'. | |
84 | TYPE_CURRENCY_QUINT = -9, | |
85 | ||
86 | // Represents a sequence of six or more currency symbols. | |
87 | TYPE_CURRENCY_OVERFLOW = -15 | |
88 | }; | |
89 | ||
90 | enum CompactType { | |
91 | TYPE_DECIMAL, TYPE_CURRENCY | |
92 | }; | |
93 | ||
340931cb A |
94 | enum Signum { |
95 | SIGNUM_NEG = -1, | |
96 | SIGNUM_ZERO = 0, | |
97 | SIGNUM_POS = 1 | |
98 | }; | |
99 | ||
0f5d89e8 A |
100 | |
101 | class U_I18N_API AffixPatternProvider { | |
102 | public: | |
103 | static const int32_t AFFIX_PLURAL_MASK = 0xff; | |
104 | static const int32_t AFFIX_PREFIX = 0x100; | |
105 | static const int32_t AFFIX_NEGATIVE_SUBPATTERN = 0x200; | |
106 | static const int32_t AFFIX_PADDING = 0x400; | |
107 | ||
108 | // Convenience compound flags | |
109 | static const int32_t AFFIX_POS_PREFIX = AFFIX_PREFIX; | |
110 | static const int32_t AFFIX_POS_SUFFIX = 0; | |
111 | static const int32_t AFFIX_NEG_PREFIX = AFFIX_PREFIX | AFFIX_NEGATIVE_SUBPATTERN; | |
112 | static const int32_t AFFIX_NEG_SUFFIX = AFFIX_NEGATIVE_SUBPATTERN; | |
113 | ||
114 | virtual ~AffixPatternProvider(); | |
115 | ||
116 | virtual char16_t charAt(int flags, int i) const = 0; | |
117 | ||
118 | virtual int length(int flags) const = 0; | |
119 | ||
120 | virtual UnicodeString getString(int flags) const = 0; | |
121 | ||
122 | virtual bool hasCurrencySign() const = 0; | |
123 | ||
124 | virtual bool positiveHasPlusSign() const = 0; | |
125 | ||
126 | virtual bool hasNegativeSubpattern() const = 0; | |
127 | ||
128 | virtual bool negativeHasMinusSign() const = 0; | |
129 | ||
130 | virtual bool containsSymbolType(AffixPatternType, UErrorCode&) const = 0; | |
131 | ||
132 | /** | |
133 | * True if the pattern has a number placeholder like "0" or "#,##0.00"; false if the pattern does not | |
134 | * have one. This is used in cases like compact notation, where the pattern replaces the entire | |
135 | * number instead of rendering the number. | |
136 | */ | |
137 | virtual bool hasBody() const = 0; | |
138 | }; | |
139 | ||
3d1f044b | 140 | |
0f5d89e8 A |
141 | /** |
142 | * A Modifier is an object that can be passed through the formatting pipeline until it is finally applied to the string | |
143 | * builder. A Modifier usually contains a prefix and a suffix that are applied, but it could contain something else, | |
144 | * like a {@link com.ibm.icu.text.SimpleFormatter} pattern. | |
145 | * | |
3d1f044b | 146 | * A Modifier is usually immutable, except in cases such as {@link MutablePatternModifier}, which are mutable for performance |
0f5d89e8 A |
147 | * reasons. |
148 | * | |
149 | * Exported as U_I18N_API because it is a base class for other exported types | |
150 | */ | |
151 | class U_I18N_API Modifier { | |
152 | public: | |
153 | virtual ~Modifier(); | |
154 | ||
155 | /** | |
156 | * Apply this Modifier to the string builder. | |
157 | * | |
158 | * @param output | |
159 | * The string builder to which to apply this modifier. | |
160 | * @param leftIndex | |
161 | * The left index of the string within the builder. Equal to 0 when only one number is being formatted. | |
162 | * @param rightIndex | |
163 | * The right index of the string within the string builder. Equal to length when only one number is being | |
164 | * formatted. | |
165 | * @return The number of characters (UTF-16 code units) that were added to the string builder. | |
166 | */ | |
340931cb | 167 | virtual int32_t apply(FormattedStringBuilder& output, int leftIndex, int rightIndex, |
0f5d89e8 A |
168 | UErrorCode& status) const = 0; |
169 | ||
170 | /** | |
171 | * Gets the length of the prefix. This information can be used in combination with {@link #apply} to extract the | |
172 | * prefix and suffix strings. | |
173 | * | |
174 | * @return The number of characters (UTF-16 code units) in the prefix. | |
175 | */ | |
3d1f044b | 176 | virtual int32_t getPrefixLength() const = 0; |
0f5d89e8 A |
177 | |
178 | /** | |
179 | * Returns the number of code points in the modifier, prefix plus suffix. | |
180 | */ | |
3d1f044b | 181 | virtual int32_t getCodePointCount() const = 0; |
0f5d89e8 A |
182 | |
183 | /** | |
184 | * Whether this modifier is strong. If a modifier is strong, it should always be applied immediately and not allowed | |
185 | * to bubble up. With regard to padding, strong modifiers are considered to be on the inside of the prefix and | |
186 | * suffix. | |
187 | * | |
188 | * @return Whether the modifier is strong. | |
189 | */ | |
190 | virtual bool isStrong() const = 0; | |
3d1f044b A |
191 | |
192 | /** | |
193 | * Whether the modifier contains at least one occurrence of the given field. | |
194 | */ | |
195 | virtual bool containsField(UNumberFormatFields field) const = 0; | |
196 | ||
197 | /** | |
198 | * A fill-in for getParameters(). obj will always be set; if non-null, the other | |
199 | * two fields are also safe to read. | |
200 | */ | |
201 | struct U_I18N_API Parameters { | |
202 | const ModifierStore* obj = nullptr; | |
340931cb | 203 | Signum signum; |
3d1f044b A |
204 | StandardPlural::Form plural; |
205 | ||
206 | Parameters(); | |
340931cb | 207 | Parameters(const ModifierStore* _obj, Signum _signum, StandardPlural::Form _plural); |
3d1f044b A |
208 | }; |
209 | ||
210 | /** | |
211 | * Gets a set of "parameters" for this Modifier. | |
212 | * | |
213 | * TODO: Make this return a `const Parameters*` more like Java? | |
214 | */ | |
215 | virtual void getParameters(Parameters& output) const = 0; | |
216 | ||
217 | /** | |
218 | * Returns whether this Modifier is *semantically equivalent* to the other Modifier; | |
219 | * in many cases, this is the same as equal, but parameters should be ignored. | |
220 | */ | |
221 | virtual bool semanticallyEquivalent(const Modifier& other) const = 0; | |
0f5d89e8 A |
222 | }; |
223 | ||
3d1f044b A |
224 | |
225 | /** | |
226 | * This is *not* a modifier; rather, it is an object that can return modifiers | |
227 | * based on given parameters. | |
228 | * | |
229 | * Exported as U_I18N_API because it is a base class for other exported types. | |
230 | */ | |
231 | class U_I18N_API ModifierStore { | |
232 | public: | |
233 | virtual ~ModifierStore(); | |
234 | ||
235 | /** | |
236 | * Returns a Modifier with the given parameters (best-effort). | |
237 | */ | |
340931cb | 238 | virtual const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const = 0; |
3d1f044b A |
239 | }; |
240 | ||
241 | ||
0f5d89e8 A |
242 | /** |
243 | * This interface is used when all number formatting settings, including the locale, are known, except for the quantity | |
244 | * itself. The {@link #processQuantity} method performs the final step in the number processing pipeline: it uses the | |
245 | * quantity to generate a finalized {@link MicroProps}, which can be used to render the number to output. | |
246 | * | |
247 | * <p> | |
248 | * In other words, this interface is used for the parts of number processing that are <em>quantity-dependent</em>. | |
249 | * | |
250 | * <p> | |
251 | * In order to allow for multiple different objects to all mutate the same MicroProps, a "chain" of MicroPropsGenerators | |
252 | * are linked together, and each one is responsible for manipulating a certain quantity-dependent part of the | |
253 | * MicroProps. At the tail of the linked list is a base instance of {@link MicroProps} with properties that are not | |
254 | * quantity-dependent. Each element in the linked list calls {@link #processQuantity} on its "parent", then does its | |
255 | * work, and then returns the result. | |
256 | * | |
257 | * Exported as U_I18N_API because it is a base class for other exported types | |
258 | * | |
259 | */ | |
260 | class U_I18N_API MicroPropsGenerator { | |
261 | public: | |
262 | virtual ~MicroPropsGenerator(); | |
263 | ||
264 | /** | |
265 | * Considers the given {@link DecimalQuantity}, optionally mutates it, and returns a {@link MicroProps}. | |
266 | * | |
267 | * @param quantity | |
268 | * The quantity for consideration and optional mutation. | |
269 | * @param micros | |
270 | * The MicroProps instance to populate. | |
271 | * @return A MicroProps instance resolved for the quantity. | |
272 | */ | |
273 | virtual void processQuantity(DecimalQuantity& quantity, MicroProps& micros, | |
274 | UErrorCode& status) const = 0; | |
275 | }; | |
276 | ||
277 | /** | |
278 | * An interface used by compact notation and scientific notation to choose a multiplier while rounding. | |
279 | */ | |
280 | class MultiplierProducer { | |
281 | public: | |
282 | virtual ~MultiplierProducer(); | |
283 | ||
284 | /** | |
285 | * Maps a magnitude to a multiplier in powers of ten. For example, in compact notation in English, a magnitude of 5 | |
286 | * (e.g., 100,000) should return a multiplier of -3, since the number is displayed in thousands. | |
287 | * | |
288 | * @param magnitude | |
289 | * The power of ten of the input number. | |
290 | * @return The shift in powers of ten. | |
291 | */ | |
292 | virtual int32_t getMultiplier(int32_t magnitude) const = 0; | |
293 | }; | |
294 | ||
295 | // Exported as U_I18N_API because it is a public member field of exported DecimalFormatProperties | |
296 | template<typename T> | |
297 | class U_I18N_API NullableValue { | |
298 | public: | |
299 | NullableValue() | |
300 | : fNull(true) {} | |
301 | ||
302 | NullableValue(const NullableValue<T>& other) = default; | |
303 | ||
304 | explicit NullableValue(const T& other) { | |
305 | fValue = other; | |
306 | fNull = false; | |
307 | } | |
308 | ||
309 | NullableValue<T>& operator=(const NullableValue<T>& other) { | |
310 | fNull = other.fNull; | |
311 | if (!fNull) { | |
312 | fValue = other.fValue; | |
313 | } | |
314 | return *this; | |
315 | } | |
316 | ||
317 | NullableValue<T>& operator=(const T& other) { | |
318 | fValue = other; | |
319 | fNull = false; | |
320 | return *this; | |
321 | } | |
322 | ||
323 | bool operator==(const NullableValue& other) const { | |
324 | // "fValue == other.fValue" returns UBool, not bool (causes compiler warnings) | |
325 | return fNull ? other.fNull : (other.fNull ? false : static_cast<bool>(fValue == other.fValue)); | |
326 | } | |
327 | ||
328 | void nullify() { | |
329 | // TODO: It might be nice to call the destructor here. | |
330 | fNull = true; | |
331 | } | |
332 | ||
333 | bool isNull() const { | |
334 | return fNull; | |
335 | } | |
336 | ||
337 | T get(UErrorCode& status) const { | |
338 | if (fNull) { | |
339 | status = U_UNDEFINED_VARIABLE; | |
340 | } | |
341 | return fValue; | |
342 | } | |
343 | ||
344 | T getNoError() const { | |
345 | return fValue; | |
346 | } | |
347 | ||
348 | T getOrDefault(T defaultValue) const { | |
349 | return fNull ? defaultValue : fValue; | |
350 | } | |
351 | ||
352 | private: | |
353 | bool fNull; | |
354 | T fValue; | |
355 | }; | |
356 | ||
3d1f044b | 357 | |
0f5d89e8 A |
358 | } // namespace impl |
359 | } // namespace number | |
360 | U_NAMESPACE_END | |
361 | ||
362 | #endif //__NUMBER_TYPES_H__ | |
363 | ||
364 | #endif /* #if !UCONFIG_NO_FORMATTING */ |