1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 *   Copyright (C) 1997-2015, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 ******************************************************************************
8 *   file name:  nfsubs.h
9 *   encoding:   UTF-8
10 *   tab size:   8 (not used)
11 *   indentation:4
12 *
13 * Modification history
14 * Date        Name      Comments
15 * 10/11/2001  Doug      Ported from ICU4J
16 */
17 
18 #ifndef NFSUBS_H
19 #define NFSUBS_H
20 
21 #include "unicode/utypes.h"
22 #include "unicode/uobject.h"
23 #include "nfrule.h"
24 
25 #if U_HAVE_RBNF
26 
27 #include "unicode/utypes.h"
28 #include "unicode/decimfmt.h"
29 #include "nfrs.h"
30 #include <float.h>
31 
32 U_NAMESPACE_BEGIN
33 
34 class NFSubstitution : public UObject {
35     int32_t pos;
36     const NFRuleSet* ruleSet;
37     DecimalFormat* numberFormat;
38 
39 protected:
40     NFSubstitution(int32_t pos,
41         const NFRuleSet* ruleSet,
42         const UnicodeString& description,
43         UErrorCode& status);
44 
45     /**
46      * Get the Ruleset of the object.
47      * @return the Ruleset of the object.
48      */
getRuleSet()49     const NFRuleSet* getRuleSet() const { return ruleSet; }
50 
51     /**
52      * get the NumberFormat of this object.
53      * @return the numberformat of this object.
54      */
getNumberFormat()55     const DecimalFormat* getNumberFormat() const { return numberFormat; }
56 
57 public:
58     static NFSubstitution* makeSubstitution(int32_t pos,
59         const NFRule* rule,
60         const NFRule* predecessor,
61         const NFRuleSet* ruleSet,
62         const RuleBasedNumberFormat* rbnf,
63         const UnicodeString& description,
64         UErrorCode& status);
65 
66     /**
67      * Destructor.
68      */
69     virtual ~NFSubstitution();
70 
71     /**
72      * Return true if the given Format objects are semantically equal.
73      * Objects of different subclasses are considered unequal.
74      * @param rhs    the object to be compared with.
75      * @return       true if the given Format objects are semantically equal.
76      */
77     virtual UBool operator==(const NFSubstitution& rhs) const;
78 
79     /**
80      * Return true if the given Format objects are semantically unequal.
81      * Objects of different subclasses are considered unequal.
82      * @param rhs    the object to be compared with.
83      * @return       true if the given Format objects are semantically unequal.
84      */
85     UBool operator!=(const NFSubstitution& rhs) const { return !operator==(rhs); }
86 
87     /**
88      * Sets the substitution's divisor.  Used by NFRule.setBaseValue().
89      * A no-op for all substitutions except multiplier and modulus
90      * substitutions.
91      * @param radix The radix of the divisor
92      * @param exponent The exponent of the divisor
93      */
94     virtual void setDivisor(int32_t radix, int16_t exponent, UErrorCode& status);
95 
96     /**
97      * Replaces result with the string describing the substitution.
98      * @param result    Output param which will receive the string.
99      */
100     virtual void toString(UnicodeString& result) const;
101 
102     void setDecimalFormatSymbols(const DecimalFormatSymbols &newSymbols, UErrorCode& status);
103 
104     //-----------------------------------------------------------------------
105     // formatting
106     //-----------------------------------------------------------------------
107 
108     /**
109      * Performs a mathematical operation on the number, formats it using
110      * either ruleSet or decimalFormat, and inserts the result into
111      * toInsertInto.
112      * @param number The number being formatted.
113      * @param toInsertInto The string we insert the result into
114      * @param pos The position in toInsertInto where the owning rule's
115      * rule text begins (this value is added to this substitution's
116      * position to determine exactly where to insert the new text)
117      */
118     virtual void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const;
119 
120     /**
121      * Performs a mathematical operation on the number, formats it using
122      * either ruleSet or decimalFormat, and inserts the result into
123      * toInsertInto.
124      * @param number The number being formatted.
125      * @param toInsertInto The string we insert the result into
126      * @param pos The position in toInsertInto where the owning rule's
127      * rule text begins (this value is added to this substitution's
128      * position to determine exactly where to insert the new text)
129      */
130     virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const;
131 
132 protected:
133     /**
134      * Subclasses override this function to perform some kind of
135      * mathematical operation on the number.  The result of this operation
136      * is formatted using the rule set or DecimalFormat that this
137      * substitution refers to, and the result is inserted into the result
138      * string.
139      * @param The number being formatted
140      * @return The result of performing the opreration on the number
141      */
142     virtual int64_t transformNumber(int64_t number) const = 0;
143 
144     /**
145      * Subclasses override this function to perform some kind of
146      * mathematical operation on the number.  The result of this operation
147      * is formatted using the rule set or DecimalFormat that this
148      * substitution refers to, and the result is inserted into the result
149      * string.
150      * @param The number being formatted
151      * @return The result of performing the opreration on the number
152      */
153     virtual double transformNumber(double number) const = 0;
154 
155 public:
156     //-----------------------------------------------------------------------
157     // parsing
158     //-----------------------------------------------------------------------
159 
160     /**
161      * Parses a string using the rule set or DecimalFormat belonging
162      * to this substitution.  If there's a match, a mathematical
163      * operation (the inverse of the one used in formatting) is
164      * performed on the result of the parse and the value passed in
165      * and returned as the result.  The parse position is updated to
166      * point to the first unmatched character in the string.
167      * @param text The string to parse
168      * @param parsePosition On entry, ignored, but assumed to be 0.
169      * On exit, this is updated to point to the first unmatched
170      * character (or 0 if the substitution didn't match)
171      * @param baseValue A partial parse result that should be
172      * combined with the result of this parse
173      * @param upperBound When searching the rule set for a rule
174      * matching the string passed in, only rules with base values
175      * lower than this are considered
176      * @param lenientParse If true and matching against rules fails,
177      * the substitution will also try matching the text against
178      * numerals using a default-costructed NumberFormat.  If false,
179      * no extra work is done.  (This value is false whenever the
180      * formatter isn't in lenient-parse mode, but is also false
181      * under some conditions even when the formatter _is_ in
182      * lenient-parse mode.)
183      * @return If there's a match, this is the result of composing
184      * baseValue with whatever was returned from matching the
185      * characters.  This will be either a Long or a Double.  If there's
186      * no match this is new Long(0) (not null), and parsePosition
187      * is left unchanged.
188      */
189     virtual UBool doParse(const UnicodeString& text,
190         ParsePosition& parsePosition,
191         double baseValue,
192         double upperBound,
193         UBool lenientParse,
194         uint32_t nonNumericalExecutedRuleMask,
195         Formattable& result) const;
196 
197     /**
198      * Derives a new value from the two values passed in.  The two values
199      * are typically either the base values of two rules (the one containing
200      * the substitution and the one matching the substitution) or partial
201      * parse results derived in some other way.  The operation is generally
202      * the inverse of the operation performed by transformNumber().
203      * @param newRuleValue The value produced by matching this substitution
204      * @param oldRuleValue The value that was passed to the substitution
205      * by the rule that owns it
206      * @return A third value derived from the other two, representing a
207      * partial parse result
208      */
209     virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const = 0;
210 
211     /**
212      * Calculates an upper bound when searching for a rule that matches
213      * this substitution.  Rules with base values greater than or equal
214      * to upperBound are not considered.
215      * @param oldUpperBound    The current upper-bound setting.  The new
216      *                         upper bound can't be any higher.
217      * @return                 the upper bound when searching for a rule that matches
218      *                         this substitution.
219      */
220     virtual double calcUpperBound(double oldUpperBound) const = 0;
221 
222     //-----------------------------------------------------------------------
223     // simple accessors
224     //-----------------------------------------------------------------------
225 
226     /**
227      * Returns the substitution's position in the rule that owns it.
228      * @return The substitution's position in the rule that owns it.
229      */
getPos()230     int32_t getPos() const { return pos; }
231 
232     /**
233      * Returns the character used in the textual representation of
234      * substitutions of this type.  Used by toString().
235      * @return This substitution's token character.
236      */
237     virtual UChar tokenChar() const = 0;
238 
239     /**
240      * Returns true if this is a modulus substitution.  (We didn't do this
241      * with instanceof partially because it causes source files to
242      * proliferate and partially because we have to port this to C++.)
243      * @return true if this object is an instance of ModulusSubstitution
244      */
245     virtual UBool isModulusSubstitution() const;
246 
247 private:
248     NFSubstitution(const NFSubstitution &other); // forbid copying of this class
249     NFSubstitution &operator=(const NFSubstitution &other); // forbid copying of this class
250 
251 public:
252     static UClassID getStaticClassID(void);
253     virtual UClassID getDynamicClassID(void) const;
254 };
255 
256 U_NAMESPACE_END
257 
258 /* U_HAVE_RBNF */
259 #endif
260 
261 // NFSUBS_H
262 #endif
263