]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/number_types.h
ICU-62141.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"
19
20U_NAMESPACE_BEGIN namespace number {
21namespace impl {
22
23// Typedef several enums for brevity and for easier comparison to Java.
24
25typedef UNumberFormatFields Field;
26
27typedef UNumberFormatRoundingMode RoundingMode;
28
29typedef UNumberFormatPadPosition PadPosition;
30
31typedef UNumberCompactStyle CompactStyle;
32
33// ICU4J Equivalent: RoundingUtils.MAX_INT_FRAC_SIG
34static constexpr int32_t kMaxIntFracSig = 999;
35
36// ICU4J Equivalent: RoundingUtils.DEFAULT_ROUNDING_MODE
37static constexpr RoundingMode kDefaultMode = RoundingMode::UNUM_FOUND_HALFEVEN;
38
39// ICU4J Equivalent: Padder.FALLBACK_PADDING_STRING
40static constexpr char16_t kFallbackPaddingString[] = u" ";
41
42// Forward declarations:
43
44class Modifier;
45class MutablePatternModifier;
46class DecimalQuantity;
47class NumberStringBuilder;
48struct MicroProps;
49
50
51enum 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
86enum CompactType {
87 TYPE_DECIMAL, TYPE_CURRENCY
88};
89
90
91class 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 */
140class 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 */
200class 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 */
220class 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
236template<typename T>
237class 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
299U_NAMESPACE_END
300
301#endif //__NUMBER_TYPES_H__
302
303#endif /* #if !UCONFIG_NO_FORMATTING */