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