• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &micros, 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