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