]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/number_types.h
ICU-66108.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"
340931cb 20#include "formatted_string_builder.h"
0f5d89e8 21
340931cb
A
22U_NAMESPACE_BEGIN
23namespace number {
0f5d89e8
A
24namespace impl {
25
340931cb
A
26// For convenience and historical reasons, import the Field typedef to the namespace.
27typedef FormattedStringBuilder::Field Field;
0f5d89e8 28
340931cb 29// Typedef several enums for brevity and for easier comparison to Java.
0f5d89e8
A
30
31typedef UNumberFormatRoundingMode RoundingMode;
32
33typedef UNumberFormatPadPosition PadPosition;
34
35typedef UNumberCompactStyle CompactStyle;
36
37// ICU4J Equivalent: RoundingUtils.MAX_INT_FRAC_SIG
38static constexpr int32_t kMaxIntFracSig = 999;
39
40// ICU4J Equivalent: RoundingUtils.DEFAULT_ROUNDING_MODE
41static constexpr RoundingMode kDefaultMode = RoundingMode::UNUM_FOUND_HALFEVEN;
42
43// ICU4J Equivalent: Padder.FALLBACK_PADDING_STRING
44static constexpr char16_t kFallbackPaddingString[] = u" ";
45
46// Forward declarations:
47
48class Modifier;
49class MutablePatternModifier;
50class DecimalQuantity;
3d1f044b 51class ModifierStore;
0f5d89e8
A
52struct MicroProps;
53
54
55enum 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
90enum CompactType {
91 TYPE_DECIMAL, TYPE_CURRENCY
92};
93
340931cb
A
94enum Signum {
95 SIGNUM_NEG = -1,
96 SIGNUM_ZERO = 0,
97 SIGNUM_POS = 1
98};
99
0f5d89e8
A
100
101class 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 */
151class 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 */
231class 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 */
260class 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 */
280class 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
296template<typename T>
297class 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
360U_NAMESPACE_END
361
362#endif //__NUMBER_TYPES_H__
363
364#endif /* #if !UCONFIG_NO_FORMATTING */