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