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