number_patternmodifier.h (9513B)
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_PATTERNMODIFIER_H__ 8 #define __NUMBER_PATTERNMODIFIER_H__ 9 10 #include "standardplural.h" 11 #include "unicode/numberformatter.h" 12 #include "number_patternstring.h" 13 #include "number_types.h" 14 #include "number_modifiers.h" 15 #include "number_utils.h" 16 #include "number_currencysymbols.h" 17 18 U_NAMESPACE_BEGIN 19 20 namespace number::impl { 21 22 // Forward declaration 23 class MutablePatternModifier; 24 25 // Exported as U_I18N_API_CLASS because it is needed for the unit test PatternModifierTest 26 class U_I18N_API_CLASS ImmutablePatternModifier : public MicroPropsGenerator, public UMemory { 27 public: 28 ~ImmutablePatternModifier() override = default; 29 30 void processQuantity(DecimalQuantity&, MicroProps& micros, UErrorCode& status) const override; 31 32 U_I18N_API void applyToMicros(MicroProps& micros, 33 const DecimalQuantity& quantity, 34 UErrorCode& status) const; 35 36 const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const; 37 38 // Non-const method: 39 void addToChain(const MicroPropsGenerator* parent); 40 41 private: 42 ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules); 43 44 const LocalPointer<AdoptingModifierStore> pm; 45 const PluralRules* rules; 46 const MicroPropsGenerator* parent; 47 48 friend class MutablePatternModifier; 49 }; 50 51 /** 52 * This class is a {@link Modifier} that wraps a decimal format pattern. It applies the pattern's affixes in 53 * {@link Modifier#apply}. 54 * 55 * <p> 56 * In addition to being a Modifier, this class contains the business logic for substituting the correct locale symbols 57 * into the affixes of the decimal format pattern. 58 * 59 * <p> 60 * In order to use this class, create a new instance and call the following four setters: {@link #setPatternInfo}, 61 * {@link #setPatternAttributes}, {@link #setSymbols}, and {@link #setNumberProperties}. After calling these four 62 * setters, the instance will be ready for use as a Modifier. 63 * 64 * <p> 65 * This is a MUTABLE, NON-THREAD-SAFE class designed for performance. Do NOT save references to this or attempt to use 66 * it from multiple threads! Instead, you can obtain a safe, immutable decimal format pattern modifier by calling 67 * {@link MutablePatternModifier#createImmutable}, in effect treating this instance as a builder for the immutable 68 * variant. 69 */ 70 class U_I18N_API_CLASS MutablePatternModifier 71 : public MicroPropsGenerator, 72 public Modifier, 73 public SymbolProvider, 74 public UMemory { 75 public: 76 77 ~MutablePatternModifier() override = default; 78 79 /** 80 * @param isStrong 81 * Whether the modifier should be considered strong. For more information, see 82 * {@link Modifier#isStrong()}. Most of the time, decimal format pattern modifiers should be considered 83 * as non-strong. 84 */ 85 U_I18N_API explicit MutablePatternModifier(bool isStrong); 86 87 /** 88 * Sets a reference to the parsed decimal format pattern, usually obtained from 89 * {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is 90 * accepted. 91 * 92 * @param field 93 * Which field to use for literal characters in the pattern. 94 */ 95 U_I18N_API void setPatternInfo(const AffixPatternProvider *patternInfo, Field field); 96 97 /** 98 * Sets attributes that imply changes to the literal interpretation of the pattern string affixes. 99 * 100 * @param signDisplay 101 * Whether to force a plus sign on positive numbers. 102 * @param perMille 103 * Whether to substitute the percent sign in the pattern with a permille sign. 104 * @param approximately 105 * Whether to prepend approximately to the sign 106 */ 107 U_I18N_API void setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille, 108 bool approximately); 109 110 /** 111 * Sets locale-specific details that affect the symbols substituted into the pattern string affixes. 112 * 113 * @param symbols 114 * The desired instance of DecimalFormatSymbols. 115 * @param currency 116 * The currency to be used when substituting currency values into the affixes. 117 * @param unitWidth 118 * The width used to render currencies. 119 * @param rules 120 * Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the 121 * convenience method {@link #needsPlurals()}. 122 * @param status 123 * Set if an error occurs while loading currency data. 124 */ 125 U_I18N_API void setSymbols(const DecimalFormatSymbols* symbols, const CurrencyUnit& currency, 126 UNumberUnitWidth unitWidth, const PluralRules* rules, UErrorCode& status); 127 128 /** 129 * Sets attributes of the current number being processed. 130 * 131 * @param signum 132 * -1 if negative; +1 if positive; or 0 if zero. 133 * @param plural 134 * The plural form of the number, required only if the pattern contains the triple 135 * currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}). 136 */ 137 U_I18N_API void setNumberProperties(Signum signum, StandardPlural::Form plural); 138 139 /** 140 * Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize. 141 * This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤"). 142 */ 143 bool needsPlurals() const; 144 145 /** Creates a quantity-dependent Modifier for the specified plural form. */ 146 U_I18N_API AdoptingSignumModifierStore createImmutableForPlural(StandardPlural::Form plural, 147 UErrorCode& status); 148 149 /** 150 * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable 151 * and can be saved for future use. The number properties in the current instance are mutated; all other properties 152 * are left untouched. 153 * 154 * <p> 155 * The resulting modifier cannot be used in a QuantityChain. 156 * 157 * <p> 158 * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP. 159 * 160 * @return An immutable that supports both positive and negative numbers. 161 */ 162 U_I18N_API ImmutablePatternModifier *createImmutable(UErrorCode &status); 163 164 U_I18N_API MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent); 165 166 U_I18N_API void processQuantity(DecimalQuantity &, MicroProps µs, 167 UErrorCode &status) const override; 168 169 U_I18N_API int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, 170 UErrorCode &status) const override; 171 172 int32_t getPrefixLength() const override; 173 174 int32_t getCodePointCount() const override; 175 176 bool isStrong() const override; 177 178 bool containsField(Field field) const override; 179 180 void getParameters(Parameters& output) const override; 181 182 bool strictEquals(const Modifier& other) const override; 183 184 /** 185 * Returns the string that substitutes a given symbol type in a pattern. 186 */ 187 UnicodeString getSymbol(AffixPatternType type) const override; 188 189 /** 190 * Returns the currency symbol for the unit width specified in setSymbols() 191 */ 192 UnicodeString getCurrencySymbolForUnitWidth(UErrorCode& status) const; 193 194 UnicodeString toUnicodeString() const; 195 196 private: 197 // Modifier details (initialized in constructor) 198 const bool fStrong; 199 200 // Pattern details (initialized in setPatternInfo and setPatternAttributes) 201 const AffixPatternProvider *fPatternInfo; 202 Field fField; 203 UNumberSignDisplay fSignDisplay; 204 bool fPerMilleReplacesPercent; 205 bool fApproximately; 206 207 // Symbol details (initialized in setSymbols) 208 const DecimalFormatSymbols *fSymbols; 209 UNumberUnitWidth fUnitWidth; 210 CurrencySymbols fCurrencySymbols; 211 const PluralRules *fRules; 212 213 // Number details (initialized in setNumberProperties) 214 Signum fSignum; 215 StandardPlural::Form fPlural; 216 217 // QuantityChain details (initialized in addToChain) 218 const MicroPropsGenerator *fParent; 219 220 // Transient fields for rendering 221 UnicodeString currentAffix; 222 223 /** 224 * Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency spacing support 225 * if required. 226 * 227 * <p> 228 * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP. 229 * 230 * @param a 231 * A working FormattedStringBuilder object; passed from the outside to prevent the need to create many new 232 * instances if this method is called in a loop. 233 * @param b 234 * Another working FormattedStringBuilder object. 235 * @return The constant modifier object. 236 */ 237 ConstantMultiFieldModifier *createConstantModifier(UErrorCode &status); 238 239 int32_t insertPrefix(FormattedStringBuilder &sb, int position, UErrorCode &status); 240 241 int32_t insertSuffix(FormattedStringBuilder &sb, int position, UErrorCode &status); 242 243 void prepareAffix(bool isPrefix); 244 }; 245 246 } // namespace number::impl 247 248 U_NAMESPACE_END 249 250 #endif //__NUMBER_PATTERNMODIFIER_H__ 251 252 #endif /* #if !UCONFIG_NO_FORMATTING */