1/*
2******************************************************************************
3*   Copyright (C) 1997-2007, 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
30U_NAMESPACE_BEGIN
31
32class NFSubstitution : public UObject {
33    int32_t pos;
34    const NFRuleSet* ruleSet;
35    const DecimalFormat* numberFormat;
36
37protected:
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     */
48    const NFRuleSet* getRuleSet() const { return ruleSet; }
49
50    /**
51     * get the NumberFormat of this object.
52     * @return the numberformat of this object.
53     */
54    const DecimalFormat* getNumberFormat() const { return numberFormat; }
55
56public:
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) 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) const;
128
129protected:
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
152public:
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     */
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
251private:
252    NFSubstitution(const NFSubstitution &other); // forbid copying of this class
253    NFSubstitution &operator=(const NFSubstitution &other); // forbid copying of this class
254
255public:
256    static UClassID getStaticClassID(void);
257    virtual UClassID getDynamicClassID(void) const;
258};
259
260U_NAMESPACE_END
261
262/* U_HAVE_RBNF */
263#endif
264
265// NFSUBS_H
266#endif
267