• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 && !UPRV_INCOMPLETE_CPP11_SUPPORT
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 
19 U_NAMESPACE_BEGIN
20 namespace number {
21 namespace impl {
22 
23 // Typedef several enums for brevity and for easier comparison to Java.
24 
25 typedef UNumberFormatFields Field;
26 
27 typedef UNumberFormatRoundingMode RoundingMode;
28 
29 typedef UNumberFormatPadPosition PadPosition;
30 
31 typedef UNumberCompactStyle CompactStyle;
32 
33 // ICU4J Equivalent: RoundingUtils.MAX_INT_FRAC_SIG
34 static constexpr int32_t kMaxIntFracSig = 100;
35 
36 // ICU4J Equivalent: RoundingUtils.DEFAULT_ROUNDING_MODE
37 static constexpr RoundingMode kDefaultMode = RoundingMode::UNUM_FOUND_HALFEVEN;
38 
39 // ICU4J Equivalent: Padder.FALLBACK_PADDING_STRING
40 static constexpr char16_t kFallbackPaddingString[] = u" ";
41 
42 // ICU4J Equivalent: NumberFormatterImpl.DEFAULT_CURRENCY
43 static constexpr char16_t kDefaultCurrency[] = u"XXX";
44 
45 // FIXME: New error codes:
46 static constexpr UErrorCode U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR = U_ILLEGAL_ARGUMENT_ERROR;
47 static constexpr UErrorCode U_NUMBER_PADDING_WIDTH_OUTOFBOUNDS_ERROR = U_ILLEGAL_ARGUMENT_ERROR;
48 
49 // Forward declarations:
50 
51 class Modifier;
52 class MutablePatternModifier;
53 class DecimalQuantity;
54 class NumberStringBuilder;
55 struct MicroProps;
56 
57 
58 enum AffixPatternType {
59     // Represents a literal character; the value is stored in the code point field.
60             TYPE_CODEPOINT = 0,
61 
62     // Represents a minus sign symbol '-'.
63             TYPE_MINUS_SIGN = -1,
64 
65     // Represents a plus sign symbol '+'.
66             TYPE_PLUS_SIGN = -2,
67 
68     // Represents a percent sign symbol '%'.
69             TYPE_PERCENT = -3,
70 
71     // Represents a permille sign symbol '‰'.
72             TYPE_PERMILLE = -4,
73 
74     // Represents a single currency symbol '¤'.
75             TYPE_CURRENCY_SINGLE = -5,
76 
77     // Represents a double currency symbol '¤¤'.
78             TYPE_CURRENCY_DOUBLE = -6,
79 
80     // Represents a triple currency symbol '¤¤¤'.
81             TYPE_CURRENCY_TRIPLE = -7,
82 
83     // Represents a quadruple currency symbol '¤¤¤¤'.
84             TYPE_CURRENCY_QUAD = -8,
85 
86     // Represents a quintuple currency symbol '¤¤¤¤¤'.
87             TYPE_CURRENCY_QUINT = -9,
88 
89     // Represents a sequence of six or more currency symbols.
90             TYPE_CURRENCY_OVERFLOW = -15
91 };
92 
93 enum CompactType {
94     TYPE_DECIMAL,
95     TYPE_CURRENCY
96 };
97 
98 
99 // TODO: Should this be moved somewhere else, maybe where other ICU classes can use it?
100 // Exported as U_I18N_API because it is a base class for other exported types
101 class U_I18N_API CharSequence {
102 public:
103     virtual ~CharSequence() = default;
104 
105     virtual int32_t length() const = 0;
106 
107     virtual char16_t charAt(int32_t index) const = 0;
108 
codePointAt(int32_t index)109     virtual UChar32 codePointAt(int32_t index) const {
110         // Default implementation; can be overridden with a more efficient version
111         char16_t leading = charAt(index);
112         if (U16_IS_LEAD(leading) && length() > index + 1) {
113             char16_t trailing = charAt(index + 1);
114             return U16_GET_SUPPLEMENTARY(leading, trailing);
115         } else {
116             return leading;
117         }
118     }
119 
120     virtual UnicodeString toUnicodeString() const = 0;
121 };
122 
123 class U_I18N_API AffixPatternProvider {
124   public:
125     static const int32_t AFFIX_PLURAL_MASK = 0xff;
126     static const int32_t AFFIX_PREFIX = 0x100;
127     static const int32_t AFFIX_NEGATIVE_SUBPATTERN = 0x200;
128     static const int32_t AFFIX_PADDING = 0x400;
129 
130     virtual ~AffixPatternProvider() = default;
131 
132     virtual char16_t charAt(int flags, int i) const = 0;
133 
134     virtual int length(int flags) const = 0;
135 
136     virtual bool hasCurrencySign() const = 0;
137 
138     virtual bool positiveHasPlusSign() const = 0;
139 
140     virtual bool hasNegativeSubpattern() const = 0;
141 
142     virtual bool negativeHasMinusSign() const = 0;
143 
144     virtual bool containsSymbolType(AffixPatternType, UErrorCode &) const = 0;
145 };
146 
147 /**
148  * A Modifier is an object that can be passed through the formatting pipeline until it is finally applied to the string
149  * builder. A Modifier usually contains a prefix and a suffix that are applied, but it could contain something else,
150  * like a {@link com.ibm.icu.text.SimpleFormatter} pattern.
151  *
152  * A Modifier is usually immutable, except in cases such as {@link MurkyModifier}, which are mutable for performance
153  * reasons.
154  *
155  * Exported as U_I18N_API because it is a base class for other exported types
156  */
157 class U_I18N_API Modifier {
158   public:
159     virtual ~Modifier() = default;
160 
161     /**
162      * Apply this Modifier to the string builder.
163      *
164      * @param output
165      *            The string builder to which to apply this modifier.
166      * @param leftIndex
167      *            The left index of the string within the builder. Equal to 0 when only one number is being formatted.
168      * @param rightIndex
169      *            The right index of the string within the string builder. Equal to length when only one number is being
170      *            formatted.
171      * @return The number of characters (UTF-16 code units) that were added to the string builder.
172      */
173     virtual int32_t
174     apply(NumberStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const = 0;
175 
176     /**
177      * Gets the length of the prefix. This information can be used in combination with {@link #apply} to extract the
178      * prefix and suffix strings.
179      *
180      * @return The number of characters (UTF-16 code units) in the prefix.
181      */
182     virtual int32_t getPrefixLength(UErrorCode& status) const = 0;
183 
184     /**
185      * Returns the number of code points in the modifier, prefix plus suffix.
186      */
187     virtual int32_t getCodePointCount(UErrorCode &status) const = 0;
188 
189     /**
190      * Whether this modifier is strong. If a modifier is strong, it should always be applied immediately and not allowed
191      * to bubble up. With regard to padding, strong modifiers are considered to be on the inside of the prefix and
192      * suffix.
193      *
194      * @return Whether the modifier is strong.
195      */
196     virtual bool isStrong() const = 0;
197 };
198 
199 /**
200  * This interface is used when all number formatting settings, including the locale, are known, except for the quantity
201  * itself. The {@link #processQuantity} method performs the final step in the number processing pipeline: it uses the
202  * quantity to generate a finalized {@link MicroProps}, which can be used to render the number to output.
203  *
204  * <p>
205  * In other words, this interface is used for the parts of number processing that are <em>quantity-dependent</em>.
206  *
207  * <p>
208  * In order to allow for multiple different objects to all mutate the same MicroProps, a "chain" of MicroPropsGenerators
209  * are linked together, and each one is responsible for manipulating a certain quantity-dependent part of the
210  * MicroProps. At the tail of the linked list is a base instance of {@link MicroProps} with properties that are not
211  * quantity-dependent. Each element in the linked list calls {@link #processQuantity} on its "parent", then does its
212  * work, and then returns the result.
213  *
214  * Exported as U_I18N_API because it is a base class for other exported types
215  *
216  */
217 class U_I18N_API MicroPropsGenerator {
218   public:
219     virtual ~MicroPropsGenerator() = default;
220 
221     /**
222      * Considers the given {@link DecimalQuantity}, optionally mutates it, and returns a {@link MicroProps}.
223      *
224      * @param quantity
225      *            The quantity for consideration and optional mutation.
226      * @param micros
227      *            The MicroProps instance to populate.
228      * @return A MicroProps instance resolved for the quantity.
229      */
230     virtual void processQuantity(DecimalQuantity& quantity, MicroProps& micros, UErrorCode& status) const = 0;
231 };
232 
233 class MultiplierProducer {
234   public:
235     virtual ~MultiplierProducer() = default;
236 
237     virtual int32_t getMultiplier(int32_t magnitude) const = 0;
238 };
239 
240 // Exported as U_I18N_API because it is a public member field of exported DecimalFormatProperties
241 template<typename T>
242 class U_I18N_API NullableValue {
243   public:
NullableValue()244     NullableValue() : fNull(true) {}
245 
246     NullableValue(const NullableValue<T> &other) = default;
247 
NullableValue(const T & other)248     explicit NullableValue(const T &other) {
249         fValue = other;
250         fNull = false;
251     }
252 
253     NullableValue<T> &operator=(const NullableValue<T> &other) = default;
254 
255     NullableValue<T> &operator=(const T &other) {
256         fValue = other;
257         fNull = false;
258         return *this;
259     }
260 
261     bool operator==(const NullableValue &other) const {
262         // "fValue == other.fValue" returns UBool, not bool (causes compiler warnings)
263         return fNull ? other.fNull : (other.fNull ? false : static_cast<bool>(fValue == other.fValue));
264     }
265 
nullify()266     void nullify() {
267         // TODO: It might be nice to call the destructor here.
268         fNull = true;
269     }
270 
isNull()271     bool isNull() const {
272         return fNull;
273     }
274 
get(UErrorCode & status)275     T get(UErrorCode &status) const {
276         if (fNull) {
277             status = U_UNDEFINED_VARIABLE;
278         }
279         return fValue;
280     }
281 
282   private:
283     bool fNull;
284     T fValue;
285 };
286 
287 } // namespace impl
288 } // namespace number
289 U_NAMESPACE_END
290 
291 #endif //__NUMBER_TYPES_H__
292 
293 #endif /* #if !UCONFIG_NO_FORMATTING */
294