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
30U_NAMESPACE_BEGIN
31
32class NFSubstitution : public UObject {
33    int32_t pos;
34    const NFRuleSet* ruleSet;
35    DecimalFormat* numberFormat;
36
37protected:
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     */
47    const NFRuleSet* getRuleSet() const { return ruleSet; }
48
49    /**
50     * get the NumberFormat of this object.
51     * @return the numberformat of this object.
52     */
53    const DecimalFormat* getNumberFormat() const { return numberFormat; }
54
55public:
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
130protected:
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
153public:
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     */
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
244private:
245    NFSubstitution(const NFSubstitution &other); // forbid copying of this class
246    NFSubstitution &operator=(const NFSubstitution &other); // forbid copying of this class
247
248public:
249    static UClassID getStaticClassID(void);
250    virtual UClassID getDynamicClassID(void) const;
251};
252
253U_NAMESPACE_END
254
255/* U_HAVE_RBNF */
256#endif
257
258// NFSUBS_H
259#endif
260