| /* |
| ****************************************************************************** |
| * Copyright (C) 1997-2001, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| ****************************************************************************** |
| * file name: nfsubs.h |
| * encoding: US-ASCII |
| * tab size: 8 (not used) |
| * indentation:4 |
| * |
| * Modification history |
| * Date Name Comments |
| * 10/11/2001 Doug Ported from ICU4J |
| */ |
| |
| #ifndef NFSUBS_H |
| #define NFSUBS_H |
| |
| #include "unicode/utypes.h" |
| #include "unicode/uobject.h" |
| #include "nfrule.h" |
| |
| #if U_HAVE_RBNF |
| |
| #include "unicode/utypes.h" |
| #include "unicode/decimfmt.h" |
| #include "nfrs.h" |
| #include <float.h> |
| |
| U_NAMESPACE_BEGIN |
| |
| class NFSubstitution : public UObject { |
| int32_t pos; |
| const NFRuleSet* ruleSet; |
| const DecimalFormat* numberFormat; |
| |
| protected: |
| NFSubstitution(int32_t pos, |
| const NFRuleSet* ruleSet, |
| const RuleBasedNumberFormat* rbnf, |
| const UnicodeString& description, |
| UErrorCode& status); |
| |
| /** |
| * Get the Ruleset of the object. |
| * @return the Ruleset of the object. |
| */ |
| const NFRuleSet* getRuleSet() const { return ruleSet; } |
| |
| /** |
| * get the NumberFormat of this object. |
| * @return the numberformat of this object. |
| */ |
| const DecimalFormat* getNumberFormat() const { return numberFormat; } |
| |
| public: |
| static NFSubstitution* makeSubstitution(int32_t pos, |
| const NFRule* rule, |
| const NFRule* predecessor, |
| const NFRuleSet* ruleSet, |
| const RuleBasedNumberFormat* rbnf, |
| const UnicodeString& description, |
| UErrorCode& status); |
| |
| /** |
| * Destructor. |
| */ |
| virtual ~NFSubstitution(); |
| |
| /** |
| * Return true if the given Format objects are semantically equal. |
| * Objects of different subclasses are considered unequal. |
| * @param rhs the object to be compared with. |
| * @return true if the given Format objects are semantically equal. |
| */ |
| virtual UBool operator==(const NFSubstitution& rhs) const; |
| |
| /** |
| * Return true if the given Format objects are semantically unequal. |
| * Objects of different subclasses are considered unequal. |
| * @param rhs the object to be compared with. |
| * @return true if the given Format objects are semantically unequal. |
| */ |
| UBool operator!=(const NFSubstitution& rhs) const { return !operator==(rhs); } |
| |
| /** |
| * Sets the substitution's divisor. Used by NFRule.setBaseValue(). |
| * A no-op for all substitutions except multiplier and modulus |
| * substitutions. |
| * @param radix The radix of the divisor |
| * @param exponent The exponent of the divisor |
| */ |
| virtual void setDivisor(int32_t radix, int32_t exponent); |
| |
| /** |
| * Replaces result with the string describing the substitution. |
| * @param result Output param which will receive the string. |
| */ |
| virtual void toString(UnicodeString& result) const; |
| |
| //----------------------------------------------------------------------- |
| // formatting |
| //----------------------------------------------------------------------- |
| |
| /** |
| * Performs a mathematical operation on the number, formats it using |
| * either ruleSet or decimalFormat, and inserts the result into |
| * toInsertInto. |
| * @param number The number being formatted. |
| * @param toInsertInto The string we insert the result into |
| * @param pos The position in toInsertInto where the owning rule's |
| * rule text begins (this value is added to this substitution's |
| * position to determine exactly where to insert the new text) |
| */ |
| virtual void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos) const; |
| |
| /** |
| * Performs a mathematical operation on the number, formats it using |
| * either ruleSet or decimalFormat, and inserts the result into |
| * toInsertInto. |
| * @param number The number being formatted. |
| * @param toInsertInto The string we insert the result into |
| * @param pos The position in toInsertInto where the owning rule's |
| * rule text begins (this value is added to this substitution's |
| * position to determine exactly where to insert the new text) |
| */ |
| virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const; |
| |
| protected: |
| /** |
| * Subclasses override this function to perform some kind of |
| * mathematical operation on the number. The result of this operation |
| * is formatted using the rule set or DecimalFormat that this |
| * substitution refers to, and the result is inserted into the result |
| * string. |
| * @param The number being formatted |
| * @return The result of performing the opreration on the number |
| */ |
| virtual int64_t transformNumber(int64_t number) const = 0; |
| |
| /** |
| * Subclasses override this function to perform some kind of |
| * mathematical operation on the number. The result of this operation |
| * is formatted using the rule set or DecimalFormat that this |
| * substitution refers to, and the result is inserted into the result |
| * string. |
| * @param The number being formatted |
| * @return The result of performing the opreration on the number |
| */ |
| virtual double transformNumber(double number) const = 0; |
| |
| public: |
| //----------------------------------------------------------------------- |
| // parsing |
| //----------------------------------------------------------------------- |
| |
| /** |
| * Parses a string using the rule set or DecimalFormat belonging |
| * to this substitution. If there's a match, a mathematical |
| * operation (the inverse of the one used in formatting) is |
| * performed on the result of the parse and the value passed in |
| * and returned as the result. The parse position is updated to |
| * point to the first unmatched character in the string. |
| * @param text The string to parse |
| * @param parsePosition On entry, ignored, but assumed to be 0. |
| * On exit, this is updated to point to the first unmatched |
| * character (or 0 if the substitution didn't match) |
| * @param baseValue A partial parse result that should be |
| * combined with the result of this parse |
| * @param upperBound When searching the rule set for a rule |
| * matching the string passed in, only rules with base values |
| * lower than this are considered |
| * @param lenientParse If true and matching against rules fails, |
| * the substitution will also try matching the text against |
| * numerals using a default-costructed NumberFormat. If false, |
| * no extra work is done. (This value is false whenever the |
| * formatter isn't in lenient-parse mode, but is also false |
| * under some conditions even when the formatter _is_ in |
| * lenient-parse mode.) |
| * @return If there's a match, this is the result of composing |
| * baseValue with whatever was returned from matching the |
| * characters. This will be either a Long or a Double. If there's |
| * no match this is new Long(0) (not null), and parsePosition |
| * is left unchanged. |
| */ |
| virtual UBool doParse(const UnicodeString& text, |
| ParsePosition& parsePosition, |
| double baseValue, |
| double upperBound, |
| UBool lenientParse, |
| Formattable& result) const; |
| |
| /** |
| * Derives a new value from the two values passed in. The two values |
| * are typically either the base values of two rules (the one containing |
| * the substitution and the one matching the substitution) or partial |
| * parse results derived in some other way. The operation is generally |
| * the inverse of the operation performed by transformNumber(). |
| * @param newRuleValue The value produced by matching this substitution |
| * @param oldRuleValue The value that was passed to the substitution |
| * by the rule that owns it |
| * @return A third value derived from the other two, representing a |
| * partial parse result |
| */ |
| virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const = 0; |
| |
| /** |
| * Calculates an upper bound when searching for a rule that matches |
| * this substitution. Rules with base values greater than or equal |
| * to upperBound are not considered. |
| * @param oldUpperBound The current upper-bound setting. The new |
| * upper bound can't be any higher. |
| * @return the upper bound when searching for a rule that matches |
| * this substitution. |
| */ |
| virtual double calcUpperBound(double oldUpperBound) const = 0; |
| |
| //----------------------------------------------------------------------- |
| // simple accessors |
| //----------------------------------------------------------------------- |
| |
| /** |
| * Returns the substitution's position in the rule that owns it. |
| * @return The substitution's position in the rule that owns it. |
| */ |
| int32_t getPos() const { return pos; } |
| |
| /** |
| * Returns the character used in the textual representation of |
| * substitutions of this type. Used by toString(). |
| * @return This substitution's token character. |
| */ |
| virtual UChar tokenChar() const = 0; |
| |
| /** |
| * Returns true if this is a null substitution. (We didn't do this |
| * with instanceof partially because it causes source files to |
| * proliferate and partially because we have to port this to C++.) |
| * @return true if this object is an instance of NullSubstitution |
| */ |
| virtual UBool isNullSubstitution() const; |
| |
| /** |
| * Returns true if this is a modulus substitution. (We didn't do this |
| * with instanceof partially because it causes source files to |
| * proliferate and partially because we have to port this to C++.) |
| * @return true if this object is an instance of ModulusSubstitution |
| */ |
| virtual UBool isModulusSubstitution() const; |
| |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| class SameValueSubstitution : public NFSubstitution { |
| public: |
| SameValueSubstitution(int32_t pos, |
| const NFRuleSet* ruleset, |
| const RuleBasedNumberFormat* formatter, |
| const UnicodeString& description, |
| UErrorCode& status); |
| |
| int64_t transformNumber(int64_t number) const { return number; } |
| double transformNumber(double number) const { return number; } |
| double composeRuleValue(double newRuleValue, double /*oldRuleValue*/) const { return newRuleValue; } |
| double calcUpperBound(double oldUpperBound) const { return oldUpperBound; } |
| UChar tokenChar() const { return (UChar)0x003d; } // '=' |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| class MultiplierSubstitution : public NFSubstitution { |
| double divisor; |
| int64_t ldivisor; |
| |
| public: |
| MultiplierSubstitution(int32_t _pos, |
| double _divisor, |
| const NFRuleSet* _ruleSet, |
| const RuleBasedNumberFormat* formatter, |
| const UnicodeString& description, |
| UErrorCode& status) |
| : NFSubstitution(_pos, _ruleSet, formatter, description, status), divisor(_divisor) |
| { |
| ldivisor = util64_fromDouble(divisor); |
| } |
| |
| void setDivisor(int32_t radix, int32_t exponent) { |
| divisor = uprv_pow(radix, exponent); |
| ldivisor = util64_fromDouble(divisor); |
| } |
| |
| UBool operator==(const NFSubstitution& rhs) const; |
| |
| int64_t transformNumber(int64_t number) const { |
| return number / ldivisor; |
| } |
| |
| double transformNumber(double number) const { |
| return uprv_floor(number / divisor); |
| } |
| |
| double composeRuleValue(double newRuleValue, double /*oldRuleValue*/) const { |
| return newRuleValue * divisor; |
| } |
| |
| double calcUpperBound(double /*oldUpperBound*/) const { return divisor; } |
| |
| UChar tokenChar() const { return (UChar)0x003c; } // '<' |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| class ModulusSubstitution : public NFSubstitution { |
| double divisor; |
| int64_t ldivisor; |
| const NFRule* ruleToUse; |
| public: |
| ModulusSubstitution(int32_t pos, |
| double _divisor, |
| const NFRule* rulePredecessor, |
| const NFRuleSet* ruleSet, |
| const RuleBasedNumberFormat* formatter, |
| const UnicodeString& description, |
| UErrorCode& status); |
| |
| void setDivisor(int32_t radix, int32_t exponent) { |
| divisor = uprv_pow(radix, exponent); |
| ldivisor = util64_fromDouble(divisor); |
| } |
| |
| UBool operator==(const NFSubstitution& rhs) const; |
| |
| void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos) const; |
| void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const; |
| |
| int64_t transformNumber(int64_t number) const { return number % ldivisor; } |
| double transformNumber(double number) const { return uprv_fmod(number, divisor); } |
| |
| UBool doParse(const UnicodeString& text, |
| ParsePosition& parsePosition, |
| double baseValue, |
| double upperBound, |
| UBool lenientParse, |
| Formattable& result) const; |
| |
| double composeRuleValue(double newRuleValue, double oldRuleValue) const { |
| return oldRuleValue - uprv_fmod(oldRuleValue, divisor) + newRuleValue; |
| } |
| |
| double calcUpperBound(double /*oldUpperBound*/) const { return divisor; } |
| |
| UBool isModulusSubstitution() const { return TRUE; } |
| |
| UChar tokenChar() const { return (UChar)0x003e; } // '>' |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| class IntegralPartSubstitution : public NFSubstitution { |
| public: |
| IntegralPartSubstitution(int32_t _pos, |
| const NFRuleSet* _ruleSet, |
| const RuleBasedNumberFormat* formatter, |
| const UnicodeString& description, |
| UErrorCode& status) |
| : NFSubstitution(_pos, _ruleSet, formatter, description, status) {} |
| |
| int64_t transformNumber(int64_t number) const { return number; } |
| double transformNumber(double number) const { return uprv_floor(number); } |
| double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue + oldRuleValue; } |
| double calcUpperBound(double /*oldUpperBound*/) const { return DBL_MAX; } |
| UChar tokenChar() const { return (UChar)0x003c; } // '<' |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| class FractionalPartSubstitution : public NFSubstitution { |
| UBool byDigits; |
| UBool useSpaces; |
| enum { kMaxDecimalDigits = 8 }; |
| public: |
| FractionalPartSubstitution(int32_t pos, |
| const NFRuleSet* ruleSet, |
| const RuleBasedNumberFormat* formatter, |
| const UnicodeString& description, |
| UErrorCode& status); |
| |
| UBool operator==(const NFSubstitution& rhs) const; |
| |
| void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const; |
| void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) const {} |
| int64_t transformNumber(int64_t /*number*/) const { return 0; } |
| double transformNumber(double number) const { return number - uprv_floor(number); } |
| |
| UBool doParse(const UnicodeString& text, |
| ParsePosition& parsePosition, |
| double baseValue, |
| double upperBound, |
| UBool lenientParse, |
| Formattable& result) const; |
| |
| double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue + oldRuleValue; } |
| double calcUpperBound(double /*oldUpperBound*/) const { return 0.0; } |
| UChar tokenChar() const { return (UChar)0x003e; } // '>' |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| class AbsoluteValueSubstitution : public NFSubstitution { |
| public: |
| AbsoluteValueSubstitution(int32_t _pos, |
| const NFRuleSet* _ruleSet, |
| const RuleBasedNumberFormat* formatter, |
| const UnicodeString& description, |
| UErrorCode& status) |
| : NFSubstitution(_pos, _ruleSet, formatter, description, status) {} |
| |
| int64_t transformNumber(int64_t number) const { return number >= 0 ? number : -number; } |
| double transformNumber(double number) const { return uprv_fabs(number); } |
| double composeRuleValue(double newRuleValue, double /*oldRuleValue*/) const { return -newRuleValue; } |
| double calcUpperBound(double /*oldUpperBound*/) const { return DBL_MAX; } |
| UChar tokenChar() const { return (UChar)0x003e; } // '>' |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| class NumeratorSubstitution : public NFSubstitution { |
| double denominator; |
| int64_t ldenominator; |
| public: |
| NumeratorSubstitution(int32_t _pos, |
| double _denominator, |
| const NFRuleSet* _ruleSet, |
| const RuleBasedNumberFormat* formatter, |
| const UnicodeString& description, |
| UErrorCode& status) |
| : NFSubstitution(_pos, _ruleSet, formatter, description, status), denominator(_denominator) |
| { |
| ldenominator = util64_fromDouble(denominator); |
| } |
| |
| UBool operator==(const NFSubstitution& rhs) const; |
| |
| int64_t transformNumber(int64_t number) const { return number * ldenominator; } |
| double transformNumber(double number) const { return uprv_round(number * denominator); } |
| |
| UBool doParse(const UnicodeString& text, |
| ParsePosition& parsePosition, |
| double baseValue, |
| double upperBound, |
| UBool /*lenientParse*/, |
| Formattable& result) const |
| { |
| // we don't have to do anything special to do the parsing here, |
| // but we have to turn lenient parsing off-- if we leave it on, |
| // it SERIOUSLY messes up the algorithm |
| return NFSubstitution::doParse(text, parsePosition, baseValue, upperBound, FALSE, result); |
| } |
| double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue / oldRuleValue; } |
| double calcUpperBound(double /*oldUpperBound*/) const { return denominator; } |
| UChar tokenChar() const { return (UChar)0x003c; } // '<' |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| class NullSubstitution : public NFSubstitution { |
| public: |
| NullSubstitution(int32_t _pos, |
| const NFRuleSet* _ruleSet, |
| const RuleBasedNumberFormat* formatter, |
| const UnicodeString& description, |
| UErrorCode& status) |
| : NFSubstitution(_pos, _ruleSet, formatter, description, status) {} |
| |
| void toString(UnicodeString& /*result*/) const {} |
| void doSubstitution(double /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) const {} |
| void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) const {} |
| int64_t transformNumber(int64_t /*number*/) const { return 0; } |
| double transformNumber(double /*number*/) const { return 0; } |
| UBool doParse(const UnicodeString& /*text*/, |
| ParsePosition& /*parsePosition*/, |
| double baseValue, |
| double /*upperBound*/, |
| UBool /*lenientParse*/, |
| Formattable& result) const |
| { result.setDouble(baseValue); return TRUE; } |
| double composeRuleValue(double /*newRuleValue*/, double /*oldRuleValue*/) const { return 0.0; } // never called |
| double calcUpperBound(double /*oldUpperBound*/) const { return 0; } // never called |
| UBool isNullSubstitution() const { return TRUE; } |
| UChar tokenChar() const { return (UChar)0x0020; } // ' ' never called |
| private: |
| static const char fgClassID; |
| |
| public: |
| static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; } |
| virtual UClassID getDynamicClassID(void) const; |
| }; |
| |
| U_NAMESPACE_END |
| |
| /* U_HAVE_RBNF */ |
| #endif |
| |
| // NFSUBS_H |
| #endif |