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