1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 #include "unicode/utypes.h"
6 #if !UCONFIG_NO_FORMATTING
7 #ifndef __NUMBER_TYPES_H__
8 #define __NUMBER_TYPES_H__
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"
17 #include "unicode/platform.h"
18 #include "unicode/uniset.h"
19 #include "standardplural.h"
20 #include "formatted_string_builder.h"
26 // For convenience and historical reasons, import the Field typedef to the namespace.
27 typedef FormattedStringBuilder::Field Field
;
29 // Typedef several enums for brevity and for easier comparison to Java.
31 typedef UNumberFormatRoundingMode RoundingMode
;
33 typedef UNumberFormatPadPosition PadPosition
;
35 typedef UNumberCompactStyle CompactStyle
;
37 // ICU4J Equivalent: RoundingUtils.MAX_INT_FRAC_SIG
38 static constexpr int32_t kMaxIntFracSig
= 999;
40 // ICU4J Equivalent: RoundingUtils.DEFAULT_ROUNDING_MODE
41 static constexpr RoundingMode kDefaultMode
= RoundingMode::UNUM_FOUND_HALFEVEN
;
43 // ICU4J Equivalent: Padder.FALLBACK_PADDING_STRING
44 static constexpr char16_t kFallbackPaddingString
[] = u
" ";
46 // Forward declarations:
49 class MutablePatternModifier
;
50 class DecimalQuantity
;
55 enum AffixPatternType
{
56 // Represents a literal character; the value is stored in the code point field.
59 // Represents a minus sign symbol '-'.
62 // Represents a plus sign symbol '+'.
65 // Represents a percent sign symbol '%'.
68 // Represents a permille sign symbol '‰'.
71 // Represents a single currency symbol '¤'.
72 TYPE_CURRENCY_SINGLE
= -5,
74 // Represents a double currency symbol '¤¤'.
75 TYPE_CURRENCY_DOUBLE
= -6,
77 // Represents a triple currency symbol '¤¤¤'.
78 TYPE_CURRENCY_TRIPLE
= -7,
80 // Represents a quadruple currency symbol '¤¤¤¤'.
81 TYPE_CURRENCY_QUAD
= -8,
83 // Represents a quintuple currency symbol '¤¤¤¤¤'.
84 TYPE_CURRENCY_QUINT
= -9,
86 // Represents a sequence of six or more currency symbols.
87 TYPE_CURRENCY_OVERFLOW
= -15
91 TYPE_DECIMAL
, TYPE_CURRENCY
101 class U_I18N_API AffixPatternProvider
{
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;
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
;
114 virtual ~AffixPatternProvider();
116 virtual char16_t charAt(int flags
, int i
) const = 0;
118 virtual int length(int flags
) const = 0;
120 virtual UnicodeString
getString(int flags
) const = 0;
122 virtual bool hasCurrencySign() const = 0;
124 virtual bool positiveHasPlusSign() const = 0;
126 virtual bool hasNegativeSubpattern() const = 0;
128 virtual bool negativeHasMinusSign() const = 0;
130 virtual bool containsSymbolType(AffixPatternType
, UErrorCode
&) const = 0;
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.
137 virtual bool hasBody() const = 0;
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.
146 * A Modifier is usually immutable, except in cases such as {@link MutablePatternModifier}, which are mutable for performance
149 * Exported as U_I18N_API because it is a base class for other exported types
151 class U_I18N_API Modifier
{
156 * Apply this Modifier to the string builder.
159 * The string builder to which to apply this modifier.
161 * The left index of the string within the builder. Equal to 0 when only one number is being formatted.
163 * The right index of the string within the string builder. Equal to length when only one number is being
165 * @return The number of characters (UTF-16 code units) that were added to the string builder.
167 virtual int32_t apply(FormattedStringBuilder
& output
, int leftIndex
, int rightIndex
,
168 UErrorCode
& status
) const = 0;
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.
174 * @return The number of characters (UTF-16 code units) in the prefix.
176 virtual int32_t getPrefixLength() const = 0;
179 * Returns the number of code points in the modifier, prefix plus suffix.
181 virtual int32_t getCodePointCount() const = 0;
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
188 * @return Whether the modifier is strong.
190 virtual bool isStrong() const = 0;
193 * Whether the modifier contains at least one occurrence of the given field.
195 virtual bool containsField(UNumberFormatFields field
) const = 0;
198 * A fill-in for getParameters(). obj will always be set; if non-null, the other
199 * two fields are also safe to read.
201 struct U_I18N_API Parameters
{
202 const ModifierStore
* obj
= nullptr;
204 StandardPlural::Form plural
;
207 Parameters(const ModifierStore
* _obj
, Signum _signum
, StandardPlural::Form _plural
);
211 * Gets a set of "parameters" for this Modifier.
213 * TODO: Make this return a `const Parameters*` more like Java?
215 virtual void getParameters(Parameters
& output
) const = 0;
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.
221 virtual bool semanticallyEquivalent(const Modifier
& other
) const = 0;
226 * This is *not* a modifier; rather, it is an object that can return modifiers
227 * based on given parameters.
229 * Exported as U_I18N_API because it is a base class for other exported types.
231 class U_I18N_API ModifierStore
{
233 virtual ~ModifierStore();
236 * Returns a Modifier with the given parameters (best-effort).
238 virtual const Modifier
* getModifier(Signum signum
, StandardPlural::Form plural
) const = 0;
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.
248 * In other words, this interface is used for the parts of number processing that are <em>quantity-dependent</em>.
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.
257 * Exported as U_I18N_API because it is a base class for other exported types
260 class U_I18N_API MicroPropsGenerator
{
262 virtual ~MicroPropsGenerator();
265 * Considers the given {@link DecimalQuantity}, optionally mutates it, and returns a {@link MicroProps}.
268 * The quantity for consideration and optional mutation.
270 * The MicroProps instance to populate.
271 * @return A MicroProps instance resolved for the quantity.
273 virtual void processQuantity(DecimalQuantity
& quantity
, MicroProps
& micros
,
274 UErrorCode
& status
) const = 0;
278 * An interface used by compact notation and scientific notation to choose a multiplier while rounding.
280 class MultiplierProducer
{
282 virtual ~MultiplierProducer();
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.
289 * The power of ten of the input number.
290 * @return The shift in powers of ten.
292 virtual int32_t getMultiplier(int32_t magnitude
) const = 0;
295 // Exported as U_I18N_API because it is a public member field of exported DecimalFormatProperties
297 class U_I18N_API NullableValue
{
302 NullableValue(const NullableValue
<T
>& other
) = default;
304 explicit NullableValue(const T
& other
) {
309 NullableValue
<T
>& operator=(const NullableValue
<T
>& other
) {
312 fValue
= other
.fValue
;
317 NullableValue
<T
>& operator=(const T
& other
) {
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
));
329 // TODO: It might be nice to call the destructor here.
333 bool isNull() const {
337 T
get(UErrorCode
& status
) const {
339 status
= U_UNDEFINED_VARIABLE
;
344 T
getNoError() const {
348 T
getOrDefault(T defaultValue
) const {
349 return fNull
? defaultValue
: fValue
;
359 } // namespace number
362 #endif //__NUMBER_TYPES_H__
364 #endif /* #if !UCONFIG_NO_FORMATTING */