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 = 0, 96 SIGNUM_NEG_ZERO = 1, 97 SIGNUM_POS_ZERO = 2, 98 SIGNUM_POS = 3, 99 SIGNUM_COUNT = 4, 100 }; 101 102 103 class U_I18N_API AffixPatternProvider { 104 public: 105 static const int32_t AFFIX_PLURAL_MASK = 0xff; 106 static const int32_t AFFIX_PREFIX = 0x100; 107 static const int32_t AFFIX_NEGATIVE_SUBPATTERN = 0x200; 108 static const int32_t AFFIX_PADDING = 0x400; 109 110 // Convenience compound flags 111 static const int32_t AFFIX_POS_PREFIX = AFFIX_PREFIX; 112 static const int32_t AFFIX_POS_SUFFIX = 0; 113 static const int32_t AFFIX_NEG_PREFIX = AFFIX_PREFIX | AFFIX_NEGATIVE_SUBPATTERN; 114 static const int32_t AFFIX_NEG_SUFFIX = AFFIX_NEGATIVE_SUBPATTERN; 115 116 virtual ~AffixPatternProvider(); 117 118 virtual char16_t charAt(int flags, int i) const = 0; 119 120 virtual int length(int flags) const = 0; 121 122 virtual UnicodeString getString(int flags) const = 0; 123 124 virtual bool hasCurrencySign() const = 0; 125 126 virtual bool positiveHasPlusSign() const = 0; 127 128 virtual bool hasNegativeSubpattern() const = 0; 129 130 virtual bool negativeHasMinusSign() const = 0; 131 132 virtual bool containsSymbolType(AffixPatternType, UErrorCode&) const = 0; 133 134 /** 135 * True if the pattern has a number placeholder like "0" or "#,##0.00"; false if the pattern does not 136 * have one. This is used in cases like compact notation, where the pattern replaces the entire 137 * number instead of rendering the number. 138 */ 139 virtual bool hasBody() const = 0; 140 }; 141 142 143 /** 144 * A Modifier is an object that can be passed through the formatting pipeline until it is finally applied to the string 145 * builder. A Modifier usually contains a prefix and a suffix that are applied, but it could contain something else, 146 * like a {@link com.ibm.icu.text.SimpleFormatter} pattern. 147 * 148 * A Modifier is usually immutable, except in cases such as {@link MutablePatternModifier}, which are mutable for performance 149 * reasons. 150 * 151 * Exported as U_I18N_API because it is a base class for other exported types 152 */ 153 class U_I18N_API Modifier { 154 public: 155 virtual ~Modifier(); 156 157 /** 158 * Apply this Modifier to the string builder. 159 * 160 * @param output 161 * The string builder to which to apply this modifier. 162 * @param leftIndex 163 * The left index of the string within the builder. Equal to 0 when only one number is being formatted. 164 * @param rightIndex 165 * The right index of the string within the string builder. Equal to length when only one number is being 166 * formatted. 167 * @return The number of characters (UTF-16 code units) that were added to the string builder. 168 */ 169 virtual int32_t apply(FormattedStringBuilder& output, int leftIndex, int rightIndex, 170 UErrorCode& status) const = 0; 171 172 /** 173 * Gets the length of the prefix. This information can be used in combination with {@link #apply} to extract the 174 * prefix and suffix strings. 175 * 176 * @return The number of characters (UTF-16 code units) in the prefix. 177 */ 178 virtual int32_t getPrefixLength() const = 0; 179 180 /** 181 * Returns the number of code points in the modifier, prefix plus suffix. 182 */ 183 virtual int32_t getCodePointCount() const = 0; 184 185 /** 186 * Whether this modifier is strong. If a modifier is strong, it should always be applied immediately and not allowed 187 * to bubble up. With regard to padding, strong modifiers are considered to be on the inside of the prefix and 188 * suffix. 189 * 190 * @return Whether the modifier is strong. 191 */ 192 virtual bool isStrong() const = 0; 193 194 /** 195 * Whether the modifier contains at least one occurrence of the given field. 196 */ 197 virtual bool containsField(Field field) const = 0; 198 199 /** 200 * A fill-in for getParameters(). obj will always be set; if non-null, the other 201 * two fields are also safe to read. 202 */ 203 struct U_I18N_API Parameters { 204 const ModifierStore* obj = nullptr; 205 Signum signum; 206 StandardPlural::Form plural; 207 208 Parameters(); 209 Parameters(const ModifierStore* _obj, Signum _signum, StandardPlural::Form _plural); 210 }; 211 212 /** 213 * Gets a set of "parameters" for this Modifier. 214 * 215 * TODO: Make this return a `const Parameters*` more like Java? 216 */ 217 virtual void getParameters(Parameters& output) const = 0; 218 219 /** 220 * Returns whether this Modifier is *semantically equivalent* to the other Modifier; 221 * in many cases, this is the same as equal, but parameters should be ignored. 222 */ 223 virtual bool semanticallyEquivalent(const Modifier& other) const = 0; 224 }; 225 226 227 /** 228 * This is *not* a modifier; rather, it is an object that can return modifiers 229 * based on given parameters. 230 * 231 * Exported as U_I18N_API because it is a base class for other exported types. 232 */ 233 class U_I18N_API ModifierStore { 234 public: 235 virtual ~ModifierStore(); 236 237 /** 238 * Returns a Modifier with the given parameters (best-effort). 239 */ 240 virtual const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const = 0; 241 }; 242 243 244 /** 245 * This interface is used when all number formatting settings, including the locale, are known, except for the quantity 246 * itself. The {@link #processQuantity} method performs the final step in the number processing pipeline: it uses the 247 * quantity to generate a finalized {@link MicroProps}, which can be used to render the number to output. 248 * 249 * In other words, this interface is used for the parts of number processing that are <em>quantity-dependent</em>. 250 * 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 * This chain of MicroPropsGenerators is typically constructed by NumberFormatterImpl::macrosToMicroGenerator() when 258 * constructing a NumberFormatter. 259 * 260 * Exported as U_I18N_API because it is a base class for other exported types 261 * 262 */ 263 class U_I18N_API MicroPropsGenerator { 264 public: 265 virtual ~MicroPropsGenerator() = default; 266 267 /** 268 * Considers the given {@link DecimalQuantity}, optionally mutates it, and 269 * populates a {@link MicroProps} instance. 270 * 271 * @param quantity The quantity for consideration and optional mutation. 272 * @param micros The MicroProps instance to populate. It will be modified as 273 * needed for the given quantity. 274 */ 275 virtual void processQuantity(DecimalQuantity& quantity, MicroProps& micros, 276 UErrorCode& status) const = 0; 277 }; 278 279 /** 280 * An interface used by compact notation and scientific notation to choose a multiplier while rounding. 281 */ 282 class MultiplierProducer { 283 public: 284 virtual ~MultiplierProducer(); 285 286 /** 287 * Maps a magnitude to a multiplier in powers of ten. For example, in compact notation in English, a magnitude of 5 288 * (e.g., 100,000) should return a multiplier of -3, since the number is displayed in thousands. 289 * 290 * @param magnitude 291 * The power of ten of the input number. 292 * @return The shift in powers of ten. 293 */ 294 virtual int32_t getMultiplier(int32_t magnitude) const = 0; 295 }; 296 297 // Exported as U_I18N_API because it is a public member field of exported DecimalFormatProperties 298 template<typename T> 299 class U_I18N_API NullableValue { 300 public: NullableValue()301 NullableValue() 302 : fNull(true) {} 303 304 NullableValue(const NullableValue<T>& other) = default; 305 NullableValue(const T & other)306 explicit NullableValue(const T& other) { 307 fValue = other; 308 fNull = false; 309 } 310 311 NullableValue<T>& operator=(const NullableValue<T>& other) { 312 fNull = other.fNull; 313 if (!fNull) { 314 fValue = other.fValue; 315 } 316 return *this; 317 } 318 319 NullableValue<T>& operator=(const T& other) { 320 fValue = other; 321 fNull = false; 322 return *this; 323 } 324 325 bool operator==(const NullableValue& other) const { 326 // "fValue == other.fValue" returns UBool, not bool (causes compiler warnings) 327 return fNull ? other.fNull : (other.fNull ? false : static_cast<bool>(fValue == other.fValue)); 328 } 329 nullify()330 void nullify() { 331 // TODO: It might be nice to call the destructor here. 332 fNull = true; 333 } 334 isNull()335 bool isNull() const { 336 return fNull; 337 } 338 get(UErrorCode & status)339 T get(UErrorCode& status) const { 340 if (fNull) { 341 status = U_UNDEFINED_VARIABLE; 342 } 343 return fValue; 344 } 345 getNoError()346 T getNoError() const { 347 return fValue; 348 } 349 getOrDefault(T defaultValue)350 T getOrDefault(T defaultValue) const { 351 return fNull ? defaultValue : fValue; 352 } 353 354 private: 355 bool fNull; 356 T fValue; 357 }; 358 359 360 } // namespace impl 361 } // namespace number 362 U_NAMESPACE_END 363 364 #endif //__NUMBER_TYPES_H__ 365 366 #endif /* #if !UCONFIG_NO_FORMATTING */ 367