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