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