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 #include "standardplural.h"
20 #include "formatted_string_builder.h"
21 
22 U_NAMESPACE_BEGIN
23 namespace number {
24 namespace impl {
25 
26 // For convenience and historical reasons, import the Field typedef to the namespace.
27 typedef FormattedStringBuilder::Field Field;
28 
29 // Typedef several enums for brevity and for easier comparison to Java.
30 
31 typedef UNumberFormatRoundingMode RoundingMode;
32 
33 typedef UNumberFormatPadPosition PadPosition;
34 
35 typedef UNumberCompactStyle CompactStyle;
36 
37 // ICU4J Equivalent: RoundingUtils.MAX_INT_FRAC_SIG
38 static constexpr int32_t kMaxIntFracSig = 999;
39 
40 // ICU4J Equivalent: RoundingUtils.DEFAULT_ROUNDING_MODE
41 static constexpr RoundingMode kDefaultMode = RoundingMode::UNUM_FOUND_HALFEVEN;
42 
43 // ICU4J Equivalent: Padder.FALLBACK_PADDING_STRING
44 static constexpr char16_t kFallbackPaddingString[] = u" ";
45 
46 // Forward declarations:
47 
48 class Modifier;
49 class MutablePatternModifier;
50 class DecimalQuantity;
51 class ModifierStore;
52 struct MicroProps;
53 
54 
55 enum 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 
90 enum CompactType {
91     TYPE_DECIMAL, TYPE_CURRENCY
92 };
93 
94 enum Signum {
95     SIGNUM_NEG = -1,
96     SIGNUM_ZERO = 0,
97     SIGNUM_POS = 1
98 };
99 
100 
101 class 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 
140 
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  *
146  * A Modifier is usually immutable, except in cases such as {@link MutablePatternModifier}, which are mutable for performance
147  * reasons.
148  *
149  * Exported as U_I18N_API because it is a base class for other exported types
150  */
151 class 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      */
167     virtual int32_t apply(FormattedStringBuilder& output, int leftIndex, int rightIndex,
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      */
176     virtual int32_t getPrefixLength() const = 0;
177 
178     /**
179      * Returns the number of code points in the modifier, prefix plus suffix.
180      */
181     virtual int32_t getCodePointCount() const = 0;
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;
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;
203         Signum signum;
204         StandardPlural::Form plural;
205 
206         Parameters();
207         Parameters(const ModifierStore* _obj, Signum _signum, StandardPlural::Form _plural);
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;
222 };
223 
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  */
231 class U_I18N_API ModifierStore {
232   public:
233     virtual ~ModifierStore();
234 
235     /**
236      * Returns a Modifier with the given parameters (best-effort).
237      */
238     virtual const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const = 0;
239 };
240 
241 
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  */
260 class 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  */
280 class 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
296 template<typename T>
297 class U_I18N_API NullableValue {
298   public:
NullableValue()299     NullableValue()
300             : fNull(true) {}
301 
302     NullableValue(const NullableValue<T>& other) = default;
303 
NullableValue(const T & other)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 
nullify()328     void nullify() {
329         // TODO: It might be nice to call the destructor here.
330         fNull = true;
331     }
332 
isNull()333     bool isNull() const {
334         return fNull;
335     }
336 
get(UErrorCode & status)337     T get(UErrorCode& status) const {
338         if (fNull) {
339             status = U_UNDEFINED_VARIABLE;
340         }
341         return fValue;
342     }
343 
getNoError()344     T getNoError() const {
345         return fValue;
346     }
347 
getOrDefault(T defaultValue)348     T getOrDefault(T defaultValue) const {
349         return fNull ? defaultValue : fValue;
350     }
351 
352   private:
353     bool fNull;
354     T fValue;
355 };
356 
357 
358 } // namespace impl
359 } // namespace number
360 U_NAMESPACE_END
361 
362 #endif //__NUMBER_TYPES_H__
363 
364 #endif /* #if !UCONFIG_NO_FORMATTING */
365