#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);
const NFRuleSet* getRuleSet() const { return ruleSet; }
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);
virtual ~NFSubstitution();
virtual UBool operator==(const NFSubstitution& rhs) const;
UBool operator!=(const NFSubstitution& rhs) const { return !operator==(rhs); }
virtual void setDivisor(int32_t radix, int32_t exponent, UErrorCode& status);
virtual void toString(UnicodeString& result) const;
virtual void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos) const;
virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const;
protected:
virtual int64_t transformNumber(int64_t number) const = 0;
virtual double transformNumber(double number) const = 0;
public:
virtual UBool doParse(const UnicodeString& text,
ParsePosition& parsePosition,
double baseValue,
double upperBound,
UBool lenientParse,
Formattable& result) const;
virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const = 0;
virtual double calcUpperBound(double oldUpperBound) const = 0;
int32_t getPos() const { return pos; }
virtual UChar tokenChar() const = 0;
virtual UBool isNullSubstitution() const;
virtual UBool isModulusSubstitution() const;
private:
NFSubstitution(const NFSubstitution &other); NFSubstitution &operator=(const NFSubstitution &other);
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);
virtual int64_t transformNumber(int64_t number) const { return number; }
virtual double transformNumber(double number) const { return number; }
virtual double composeRuleValue(double newRuleValue, double ) const { return newRuleValue; }
virtual double calcUpperBound(double oldUpperBound) const { return oldUpperBound; }
virtual 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);
if (divisor == 0) {
status = U_PARSE_ERROR;
}
}
virtual void setDivisor(int32_t radix, int32_t exponent, UErrorCode& status) {
divisor = uprv_pow(radix, exponent);
ldivisor = util64_fromDouble(divisor);
if(divisor == 0) {
status = U_PARSE_ERROR;
}
}
virtual UBool operator==(const NFSubstitution& rhs) const;
virtual int64_t transformNumber(int64_t number) const {
return number / ldivisor;
}
virtual double transformNumber(double number) const {
return uprv_floor(number / divisor);
}
virtual double composeRuleValue(double newRuleValue, double ) const {
return newRuleValue * divisor;
}
virtual double calcUpperBound(double ) const { return divisor; }
virtual 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);
virtual void setDivisor(int32_t radix, int32_t exponent, UErrorCode& status) {
divisor = uprv_pow(radix, exponent);
ldivisor = util64_fromDouble(divisor);
if (divisor == 0) {
status = U_PARSE_ERROR;
}
}
virtual UBool operator==(const NFSubstitution& rhs) const;
virtual void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos) const;
virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const;
virtual int64_t transformNumber(int64_t number) const { return number % ldivisor; }
virtual double transformNumber(double number) const { return uprv_fmod(number, divisor); }
virtual UBool doParse(const UnicodeString& text,
ParsePosition& parsePosition,
double baseValue,
double upperBound,
UBool lenientParse,
Formattable& result) const;
virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const {
return oldRuleValue - uprv_fmod(oldRuleValue, divisor) + newRuleValue;
}
virtual double calcUpperBound(double ) const { return divisor; }
virtual UBool isModulusSubstitution() const { return TRUE; }
virtual 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) {}
virtual int64_t transformNumber(int64_t number) const { return number; }
virtual double transformNumber(double number) const { return uprv_floor(number); }
virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue + oldRuleValue; }
virtual double calcUpperBound(double ) const { return DBL_MAX; }
virtual 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);
virtual UBool operator==(const NFSubstitution& rhs) const;
virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const;
virtual void doSubstitution(int64_t , UnicodeString& , int32_t ) const {}
virtual int64_t transformNumber(int64_t ) const { return 0; }
virtual double transformNumber(double number) const { return number - uprv_floor(number); }
virtual UBool doParse(const UnicodeString& text,
ParsePosition& parsePosition,
double baseValue,
double upperBound,
UBool lenientParse,
Formattable& result) const;
virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue + oldRuleValue; }
virtual double calcUpperBound(double ) const { return 0.0; }
virtual 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) {}
virtual int64_t transformNumber(int64_t number) const { return number >= 0 ? number : -number; }
virtual double transformNumber(double number) const { return uprv_fabs(number); }
virtual double composeRuleValue(double newRuleValue, double ) const { return -newRuleValue; }
virtual double calcUpperBound(double ) const { return DBL_MAX; }
virtual 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;
UBool withZeros;
public:
static inline UnicodeString fixdesc(const UnicodeString& desc) {
if (desc.endsWith(LTLT, 2)) {
UnicodeString result(desc, 0, desc.length()-1);
return result;
}
return desc;
}
NumeratorSubstitution(int32_t _pos,
double _denominator,
const NFRuleSet* _ruleSet,
const RuleBasedNumberFormat* formatter,
const UnicodeString& description,
UErrorCode& status)
: NFSubstitution(_pos, _ruleSet, formatter, fixdesc(description), status), denominator(_denominator)
{
ldenominator = util64_fromDouble(denominator);
withZeros = description.endsWith(LTLT, 2);
}
virtual UBool operator==(const NFSubstitution& rhs) const;
virtual int64_t transformNumber(int64_t number) const { return number * ldenominator; }
virtual double transformNumber(double number) const { return uprv_round(number * denominator); }
virtual void doSubstitution(int64_t , UnicodeString& , int32_t ) const {}
virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const;
virtual UBool doParse(const UnicodeString& text,
ParsePosition& parsePosition,
double baseValue,
double upperBound,
UBool ,
Formattable& result) const;
virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue / oldRuleValue; }
virtual double calcUpperBound(double ) const { return denominator; }
virtual UChar tokenChar() const { return (UChar)0x003c; } private:
static const char fgClassID;
static const UChar LTLT[2];
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) {}
virtual void toString(UnicodeString& ) const {}
virtual void doSubstitution(double , UnicodeString& , int32_t ) const {}
virtual void doSubstitution(int64_t , UnicodeString& , int32_t ) const {}
virtual int64_t transformNumber(int64_t ) const { return 0; }
virtual double transformNumber(double ) const { return 0; }
virtual UBool doParse(const UnicodeString& ,
ParsePosition& ,
double baseValue,
double ,
UBool ,
Formattable& result) const
{ result.setDouble(baseValue); return TRUE; }
virtual double composeRuleValue(double , double ) const { return 0.0; } virtual double calcUpperBound(double ) const { return 0; } virtual UBool isNullSubstitution() const { return TRUE; }
virtual UChar tokenChar() const { return (UChar)0x0020; } private:
static const char fgClassID;
public:
static UClassID getStaticClassID(void) { return (UClassID)&fgClassID; }
virtual UClassID getDynamicClassID(void) const;
};
U_NAMESPACE_END
#endif
#endif