// Copyright (C) 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
******************************************************************************
*   Copyright (C) 1997-2015, International Business Machines
*   Corporation and others.  All Rights Reserved.
******************************************************************************
*   file name:  nfsubs.cpp
*   encoding:   US-ASCII
*   tab size:   8 (not used)
*   indentation:4
*
* Modification history
* Date        Name      Comments
* 10/11/2001  Doug      Ported from ICU4J
*/

#include <stdio.h>
#include "utypeinfo.h"  // for 'typeid' to work

#include "nfsubs.h"
#include "digitlst.h"

#if U_HAVE_RBNF

static const UChar gLessThan = 0x003c;
static const UChar gEquals = 0x003d;
static const UChar gGreaterThan = 0x003e;
static const UChar gPercent = 0x0025;
static const UChar gPound = 0x0023;
static const UChar gZero = 0x0030;
static const UChar gSpace = 0x0020;

static const UChar gEqualsEquals[] =
{
    0x3D, 0x3D, 0
}; /* "==" */
static const UChar gGreaterGreaterGreaterThan[] =
{
    0x3E, 0x3E, 0x3E, 0
}; /* ">>>" */
static const UChar gGreaterGreaterThan[] =
{
    0x3E, 0x3E, 0
}; /* ">>" */

U_NAMESPACE_BEGIN

class SameValueSubstitution : public NFSubstitution {
public:
    SameValueSubstitution(int32_t pos,
        const NFRuleSet* ruleset,
        const UnicodeString& description,
        UErrorCode& status);
    virtual ~SameValueSubstitution();

    virtual int64_t transformNumber(int64_t number) const { return number; }
    virtual double transformNumber(double number) const { return number; }
    virtual double composeRuleValue(double newRuleValue, double /*oldRuleValue*/) const { return newRuleValue; }
    virtual double calcUpperBound(double oldUpperBound) const { return oldUpperBound; }
    virtual UChar tokenChar() const { return (UChar)0x003d; } // '='

public:
    static UClassID getStaticClassID(void);
    virtual UClassID getDynamicClassID(void) const;
};

SameValueSubstitution::~SameValueSubstitution() {}

class MultiplierSubstitution : public NFSubstitution {
    double divisor;
    int64_t ldivisor;

public:
    MultiplierSubstitution(int32_t _pos,
        double _divisor,
        const NFRuleSet* _ruleSet,
        const UnicodeString& description,
        UErrorCode& status)
        : NFSubstitution(_pos, _ruleSet, description, status), divisor(_divisor)
    {
        ldivisor = util64_fromDouble(divisor);
        if (divisor == 0) {
            status = U_PARSE_ERROR;
        }
    }
    virtual ~MultiplierSubstitution();

    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 {
        if (getRuleSet()) {
            return uprv_floor(number / divisor);
        } else {
            return number/divisor;
        }
    }

    virtual double composeRuleValue(double newRuleValue, double /*oldRuleValue*/) const {
        return newRuleValue * divisor;
    }

    virtual double calcUpperBound(double /*oldUpperBound*/) const { return divisor; }

    virtual UChar tokenChar() const { return (UChar)0x003c; } // '<'

public:
    static UClassID getStaticClassID(void);
    virtual UClassID getDynamicClassID(void) const;
};

MultiplierSubstitution::~MultiplierSubstitution() {}

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 UnicodeString& description,
        UErrorCode& status);
    virtual ~ModulusSubstitution();

    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, int32_t recursionCount, UErrorCode& status) const;
    virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) 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 /*oldUpperBound*/) const { return divisor; }

    virtual UBool isModulusSubstitution() const { return TRUE; }

    virtual UChar tokenChar() const { return (UChar)0x003e; } // '>'

	virtual void toString(UnicodeString& result) const;

public:
    static UClassID getStaticClassID(void);
    virtual UClassID getDynamicClassID(void) const;
};

ModulusSubstitution::~ModulusSubstitution() {}

class IntegralPartSubstitution : public NFSubstitution {
public:
    IntegralPartSubstitution(int32_t _pos,
        const NFRuleSet* _ruleSet,
        const UnicodeString& description,
        UErrorCode& status)
        : NFSubstitution(_pos, _ruleSet, description, status) {}
    virtual ~IntegralPartSubstitution();

    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 /*oldUpperBound*/) const { return DBL_MAX; }
    virtual UChar tokenChar() const { return (UChar)0x003c; } // '<'

public:
    static UClassID getStaticClassID(void);
    virtual UClassID getDynamicClassID(void) const;
};

IntegralPartSubstitution::~IntegralPartSubstitution() {}

class FractionalPartSubstitution : public NFSubstitution {
    UBool byDigits;
    UBool useSpaces;
    enum { kMaxDecimalDigits = 8 };
public:
    FractionalPartSubstitution(int32_t pos,
        const NFRuleSet* ruleSet,
        const UnicodeString& description,
        UErrorCode& status);
    virtual ~FractionalPartSubstitution();

    virtual UBool operator==(const NFSubstitution& rhs) const;

    virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const;
    virtual void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/, int32_t /*recursionCount*/, UErrorCode& /*status*/) const {}
    virtual int64_t transformNumber(int64_t /*number*/) 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 /*oldUpperBound*/) const { return 0.0; }
    virtual UChar tokenChar() const { return (UChar)0x003e; } // '>'

public:
    static UClassID getStaticClassID(void);
    virtual UClassID getDynamicClassID(void) const;
};

FractionalPartSubstitution::~FractionalPartSubstitution() {}

class AbsoluteValueSubstitution : public NFSubstitution {
public:
    AbsoluteValueSubstitution(int32_t _pos,
        const NFRuleSet* _ruleSet,
        const UnicodeString& description,
        UErrorCode& status)
        : NFSubstitution(_pos, _ruleSet, description, status) {}
    virtual ~AbsoluteValueSubstitution();

    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 /*oldRuleValue*/) const { return -newRuleValue; }
    virtual double calcUpperBound(double /*oldUpperBound*/) const { return DBL_MAX; }
    virtual UChar tokenChar() const { return (UChar)0x003e; } // '>'

public:
    static UClassID getStaticClassID(void);
    virtual UClassID getDynamicClassID(void) const;
};

AbsoluteValueSubstitution::~AbsoluteValueSubstitution() {}

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,
        NFRuleSet* _ruleSet,
        const UnicodeString& description,
        UErrorCode& status)
        : NFSubstitution(_pos, _ruleSet, fixdesc(description), status), denominator(_denominator) 
    {
        ldenominator = util64_fromDouble(denominator);
        withZeros = description.endsWith(LTLT, 2);
    }
    virtual ~NumeratorSubstitution();

    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 /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/, int32_t /*recursionCount*/, UErrorCode& /*status*/) const {}
    virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const;
    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 /*oldUpperBound*/) const { return denominator; }
    virtual UChar tokenChar() const { return (UChar)0x003c; } // '<'
private:
    static const UChar LTLT[2];

public:
    static UClassID getStaticClassID(void);
    virtual UClassID getDynamicClassID(void) const;
};

NumeratorSubstitution::~NumeratorSubstitution() {}

NFSubstitution*
NFSubstitution::makeSubstitution(int32_t pos,
                                 const NFRule* rule,
                                 const NFRule* predecessor,
                                 const NFRuleSet* ruleSet,
                                 const RuleBasedNumberFormat* formatter,
                                 const UnicodeString& description,
                                 UErrorCode& status)
{
    // if the description is empty, return a NullSubstitution
    if (description.length() == 0) {
        return NULL;
    }

    switch (description.charAt(0)) {
        // if the description begins with '<'...
    case gLessThan:
        // throw an exception if the rule is a negative number
        // rule
        if (rule->getBaseValue() == NFRule::kNegativeNumberRule) {
            // throw new IllegalArgumentException("<< not allowed in negative-number rule");
            status = U_PARSE_ERROR;
            return NULL;
        }

        // if the rule is a fraction rule, return an
        // IntegralPartSubstitution
        else if (rule->getBaseValue() == NFRule::kImproperFractionRule
            || rule->getBaseValue() == NFRule::kProperFractionRule
            || rule->getBaseValue() == NFRule::kMasterRule) {
            return new IntegralPartSubstitution(pos, ruleSet, description, status);
        }

        // if the rule set containing the rule is a fraction
        // rule set, return a NumeratorSubstitution
        else if (ruleSet->isFractionRuleSet()) {
            return new NumeratorSubstitution(pos, (double)rule->getBaseValue(),
                formatter->getDefaultRuleSet(), description, status);
        }

        // otherwise, return a MultiplierSubstitution
        else {
            return new MultiplierSubstitution(pos, rule->getDivisor(), ruleSet,
                description, status);
        }

        // if the description begins with '>'...
    case gGreaterThan:
        // if the rule is a negative-number rule, return
        // an AbsoluteValueSubstitution
        if (rule->getBaseValue() == NFRule::kNegativeNumberRule) {
            return new AbsoluteValueSubstitution(pos, ruleSet, description, status);
        }

        // if the rule is a fraction rule, return a
        // FractionalPartSubstitution
        else if (rule->getBaseValue() == NFRule::kImproperFractionRule
            || rule->getBaseValue() == NFRule::kProperFractionRule
            || rule->getBaseValue() == NFRule::kMasterRule) {
            return new FractionalPartSubstitution(pos, ruleSet, description, status);
        }

        // if the rule set owning the rule is a fraction rule set,
        // throw an exception
        else if (ruleSet->isFractionRuleSet()) {
            // throw new IllegalArgumentException(">> not allowed in fraction rule set");
            status = U_PARSE_ERROR;
            return NULL;
        }

        // otherwise, return a ModulusSubstitution
        else {
            return new ModulusSubstitution(pos, rule->getDivisor(), predecessor,
                ruleSet, description, status);
        }

        // if the description begins with '=', always return a
        // SameValueSubstitution
    case gEquals:
        return new SameValueSubstitution(pos, ruleSet, description, status);

        // and if it's anything else, throw an exception
    default:
        // throw new IllegalArgumentException("Illegal substitution character");
        status = U_PARSE_ERROR;
    }
    return NULL;
}

NFSubstitution::NFSubstitution(int32_t _pos,
                               const NFRuleSet* _ruleSet,
                               const UnicodeString& description,
                               UErrorCode& status)
                               : pos(_pos), ruleSet(NULL), numberFormat(NULL)
{
    // the description should begin and end with the same character.
    // If it doesn't that's a syntax error.  Otherwise,
    // makeSubstitution() was the only thing that needed to know
    // about these characters, so strip them off
    UnicodeString workingDescription(description);
    if (description.length() >= 2
        && description.charAt(0) == description.charAt(description.length() - 1))
    {
        workingDescription.remove(description.length() - 1, 1);
        workingDescription.remove(0, 1);
    }
    else if (description.length() != 0) {
        // throw new IllegalArgumentException("Illegal substitution syntax");
        status = U_PARSE_ERROR;
        return;
    }

    if (workingDescription.length() == 0) {
        // if the description was just two paired token characters
        // (i.e., "<<" or ">>"), it uses the rule set it belongs to to
        // format its result
        this->ruleSet = _ruleSet;
    }
    else if (workingDescription.charAt(0) == gPercent) {
        // if the description contains a rule set name, that's the rule
        // set we use to format the result: get a reference to the
        // names rule set
        this->ruleSet = _ruleSet->getOwner()->findRuleSet(workingDescription, status);
    }
    else if (workingDescription.charAt(0) == gPound || workingDescription.charAt(0) ==gZero) {
        // if the description begins with 0 or #, treat it as a
        // DecimalFormat pattern, and initialize a DecimalFormat with
        // that pattern (then set it to use the DecimalFormatSymbols
        // belonging to our formatter)
        const DecimalFormatSymbols* sym = _ruleSet->getOwner()->getDecimalFormatSymbols();
        if (!sym) {
            status = U_MISSING_RESOURCE_ERROR;
            return;
        }
        DecimalFormat *tempNumberFormat = new DecimalFormat(workingDescription, *sym, status);
        /* test for NULL */
        if (!tempNumberFormat) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return;
        }
        if (U_FAILURE(status)) {
            delete tempNumberFormat;
            return;
        }
        this->numberFormat = tempNumberFormat;
    }
    else if (workingDescription.charAt(0) == gGreaterThan) {
        // if the description is ">>>", this substitution bypasses the
        // usual rule-search process and always uses the rule that precedes
        // it in its own rule set's rule list (this is used for place-value
        // notations: formats where you want to see a particular part of
        // a number even when it's 0)

        // this causes problems when >>> is used in a frationalPartSubstitution
        // this->ruleSet = NULL;
        this->ruleSet = _ruleSet;
        this->numberFormat = NULL;
    }
    else {
        // and of the description is none of these things, it's a syntax error

        // throw new IllegalArgumentException("Illegal substitution syntax");
        status = U_PARSE_ERROR;
    }
}

NFSubstitution::~NFSubstitution()
{
    delete numberFormat;
    numberFormat = NULL;
}

/**
 * Set's 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
 */
void
NFSubstitution::setDivisor(int32_t /*radix*/, int32_t /*exponent*/, UErrorCode& /*status*/) {
  // a no-op for all substitutions except multiplier and modulus substitutions
}

void
NFSubstitution::setDecimalFormatSymbols(const DecimalFormatSymbols &newSymbols, UErrorCode& /*status*/) {
    if (numberFormat != NULL) {
        numberFormat->setDecimalFormatSymbols(newSymbols);
    }
}

//-----------------------------------------------------------------------
// boilerplate
//-----------------------------------------------------------------------

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NFSubstitution)

/**
 * Compares two substitutions for equality
 * @param The substitution to compare this one to
 * @return true if the two substitutions are functionally equivalent
 */
UBool
NFSubstitution::operator==(const NFSubstitution& rhs) const
{
  // compare class and all of the fields all substitutions have
  // in common
  // this should be called by subclasses before their own equality tests
  return typeid(*this) == typeid(rhs)
  && pos == rhs.pos
  && (ruleSet == NULL) == (rhs.ruleSet == NULL)
  // && ruleSet == rhs.ruleSet causes circularity, other checks to make instead?
  && (numberFormat == NULL
      ? (rhs.numberFormat == NULL)
      : (*numberFormat == *rhs.numberFormat));
}

/**
 * Returns a textual description of the substitution
 * @return A textual description of the substitution.  This might
 * not be identical to the description it was created from, but
 * it'll produce the same result.
 */
void
NFSubstitution::toString(UnicodeString& text) const
{
  // use tokenChar() to get the character at the beginning and
  // end of the substitutin token.  In between them will go
  // either the name of the rule set it uses, or the pattern of
  // the DecimalFormat it uses
  text.remove();
  text.append(tokenChar());

  UnicodeString temp;
  if (ruleSet != NULL) {
    ruleSet->getName(temp);
  } else if (numberFormat != NULL) {
    numberFormat->toPattern(temp);
  }
  text.append(temp);
  text.append(tokenChar());
}

//-----------------------------------------------------------------------
// 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)
 */
void
NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const
{
    if (ruleSet != NULL) {
        // perform a transformation on the number that is dependent
        // on the type of substitution this is, then just call its
        // rule set's format() method to format the result
        ruleSet->format(transformNumber(number), toInsertInto, _pos + this->pos, recursionCount, status);
    } else if (numberFormat != NULL) {
        // or perform the transformation on the number (preserving
        // the result's fractional part if the formatter it set
        // to show it), then use that formatter's format() method
        // to format the result
        double numberToFormat = transformNumber((double)number);
        if (numberFormat->getMaximumFractionDigits() == 0) {
            numberToFormat = uprv_floor(numberToFormat);
        }

        UnicodeString temp;
        numberFormat->format(numberToFormat, temp, status);
        toInsertInto.insert(_pos + this->pos, temp);
    }
}

/**
 * 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)
 */
void
NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const {
    // perform a transformation on the number being formatted that
    // is dependent on the type of substitution this is
    double numberToFormat = transformNumber(number);

    if (uprv_isInfinite(numberToFormat)) {
        // This is probably a minus rule. Combine it with an infinite rule.
        const NFRule *infiniteRule = ruleSet->findDoubleRule(uprv_getInfinity());
        infiniteRule->doFormat(numberToFormat, toInsertInto, _pos + this->pos, recursionCount, status);
        return;
    }

    // if the result is an integer, from here on out we work in integer
    // space (saving time and memory and preserving accuracy)
    if (numberToFormat == uprv_floor(numberToFormat) && ruleSet != NULL) {
        ruleSet->format(util64_fromDouble(numberToFormat), toInsertInto, _pos + this->pos, recursionCount, status);

        // if the result isn't an integer, then call either our rule set's
        // format() method or our DecimalFormat's format() method to
        // format the result
    } else {
        if (ruleSet != NULL) {
            ruleSet->format(numberToFormat, toInsertInto, _pos + this->pos, recursionCount, status);
        } else if (numberFormat != NULL) {
            UnicodeString temp;
            numberFormat->format(numberToFormat, temp);
            toInsertInto.insert(_pos + this->pos, temp);
        }
    }
}


    //-----------------------------------------------------------------------
    // parsing
    //-----------------------------------------------------------------------

#ifdef RBNF_DEBUG
#include <stdio.h>
#endif

/**
 * 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.
 */
UBool
NFSubstitution::doParse(const UnicodeString& text,
                        ParsePosition& parsePosition,
                        double baseValue,
                        double upperBound,
                        UBool lenientParse,
                        Formattable& result) const
{
#ifdef RBNF_DEBUG
    fprintf(stderr, "<nfsubs> %x bv: %g ub: %g\n", this, baseValue, upperBound);
#endif
    // figure out the highest base value a rule can have and match
    // the text being parsed (this varies according to the type of
    // substitutions: multiplier, modulus, and numerator substitutions
    // restrict the search to rules with base values lower than their
    // own; same-value substitutions leave the upper bound wherever
    // it was, and the others allow any rule to match
    upperBound = calcUpperBound(upperBound);

    // use our rule set to parse the text.  If that fails and
    // lenient parsing is enabled (this is always false if the
    // formatter's lenient-parsing mode is off, but it may also
    // be false even when the formatter's lenient-parse mode is
    // on), then also try parsing the text using a default-
    // constructed NumberFormat
    if (ruleSet != NULL) {
        ruleSet->parse(text, parsePosition, upperBound, result);
        if (lenientParse && !ruleSet->isFractionRuleSet() && parsePosition.getIndex() == 0) {
            UErrorCode status = U_ZERO_ERROR;
            NumberFormat* fmt = NumberFormat::createInstance(status);
            if (U_SUCCESS(status)) {
                fmt->parse(text, result, parsePosition);
            }
            delete fmt;
        }

        // ...or use our DecimalFormat to parse the text
    } else if (numberFormat != NULL) {
        numberFormat->parse(text, result, parsePosition);
    }

    // if the parse was successful, we've already advanced the caller's
    // parse position (this is the one function that doesn't have one
    // of its own).  Derive a parse result and return it as a Long,
    // if possible, or a Double
    if (parsePosition.getIndex() != 0) {
        UErrorCode status = U_ZERO_ERROR;
        double tempResult = result.getDouble(status);

        // composeRuleValue() produces a full parse result from
        // the partial parse result passed to this function from
        // the caller (this is either the owning rule's base value
        // or the partial result obtained from composing the
        // owning rule's base value with its other substitution's
        // parse result) and the partial parse result obtained by
        // matching the substitution (which will be the same value
        // the caller would get by parsing just this part of the
        // text with RuleBasedNumberFormat.parse() ).  How the two
        // values are used to derive the full parse result depends
        // on the types of substitutions: For a regular rule, the
        // ultimate result is its multiplier substitution's result
        // times the rule's divisor (or the rule's base value) plus
        // the modulus substitution's result (which will actually
        // supersede part of the rule's base value).  For a negative-
        // number rule, the result is the negative of its substitution's
        // result.  For a fraction rule, it's the sum of its two
        // substitution results.  For a rule in a fraction rule set,
        // it's the numerator substitution's result divided by
        // the rule's base value.  Results from same-value substitutions
        // propagate back upard, and null substitutions don't affect
        // the result.
        tempResult = composeRuleValue(tempResult, baseValue);
        result.setDouble(tempResult);
        return TRUE;
        // if the parse was UNsuccessful, return 0
    } else {
        result.setLong(0);
        return FALSE;
    }
}

    /**
     * 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
     */
UBool
NFSubstitution::isModulusSubstitution() const {
    return FALSE;
}

//===================================================================
// SameValueSubstitution
//===================================================================

/**
 * A substitution that passes the value passed to it through unchanged.
 * Represented by == in rule descriptions.
 */
SameValueSubstitution::SameValueSubstitution(int32_t _pos,
                        const NFRuleSet* _ruleSet,
                        const UnicodeString& description,
                        UErrorCode& status)
: NFSubstitution(_pos, _ruleSet, description, status)
{
    if (0 == description.compare(gEqualsEquals, 2)) {
        // throw new IllegalArgumentException("== is not a legal token");
        status = U_PARSE_ERROR;
    }
}

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SameValueSubstitution)

//===================================================================
// MultiplierSubstitution
//===================================================================

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MultiplierSubstitution)

UBool MultiplierSubstitution::operator==(const NFSubstitution& rhs) const
{
    return NFSubstitution::operator==(rhs) &&
        divisor == ((const MultiplierSubstitution*)&rhs)->divisor;
}


//===================================================================
// ModulusSubstitution
//===================================================================

/**
 * A substitution that divides the number being formatted by the its rule's
 * divisor and formats the remainder.  Represented by "&gt;&gt;" in a
 * regular rule.
 */
ModulusSubstitution::ModulusSubstitution(int32_t _pos,
                                         double _divisor,
                                         const NFRule* predecessor,
                                         const NFRuleSet* _ruleSet,
                                         const UnicodeString& description,
                                         UErrorCode& status)
 : NFSubstitution(_pos, _ruleSet, description, status)
 , divisor(_divisor)
 , ruleToUse(NULL)
{
  ldivisor = util64_fromDouble(_divisor);

  // the owning rule's divisor controls the behavior of this
  // substitution: rather than keeping a backpointer to the rule,
  // we keep a copy of the divisor

  if (ldivisor == 0) {
      status = U_PARSE_ERROR;
  }

  if (0 == description.compare(gGreaterGreaterGreaterThan, 3)) {
    // the >>> token doesn't alter how this substituion calculates the
    // values it uses for formatting and parsing, but it changes
    // what's done with that value after it's obtained: >>> short-
    // circuits the rule-search process and goes straight to the
    // specified rule to format the substitution value
    ruleToUse = predecessor;
  }
}

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ModulusSubstitution)

UBool ModulusSubstitution::operator==(const NFSubstitution& rhs) const
{
  return NFSubstitution::operator==(rhs) &&
  divisor == ((const ModulusSubstitution*)&rhs)->divisor &&
  ruleToUse == ((const ModulusSubstitution*)&rhs)->ruleToUse;
}

//-----------------------------------------------------------------------
// formatting
//-----------------------------------------------------------------------


/**
 * If this is a &gt;&gt;&gt; substitution, use ruleToUse to fill in
 * the substitution.  Otherwise, just use the superclass function.
 * @param number The number being formatted
 * @toInsertInto The string to insert the result of this substitution
 * into
 * @param pos The position of the rule text in toInsertInto
 */
void
ModulusSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const
{
    // if this isn't a >>> substitution, just use the inherited version
    // of this function (which uses either a rule set or a DecimalFormat
    // to format its substitution value)
    if (ruleToUse == NULL) {
        NFSubstitution::doSubstitution(number, toInsertInto, _pos, recursionCount, status);

        // a >>> substitution goes straight to a particular rule to
        // format the substitution value
    } else {
        int64_t numberToFormat = transformNumber(number);
        ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos(), recursionCount, status);
    }
}

/**
* If this is a &gt;&gt;&gt; substitution, use ruleToUse to fill in
* the substitution.  Otherwise, just use the superclass function.
* @param number The number being formatted
* @toInsertInto The string to insert the result of this substitution
* into
* @param pos The position of the rule text in toInsertInto
*/
void
ModulusSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const
{
    // if this isn't a >>> substitution, just use the inherited version
    // of this function (which uses either a rule set or a DecimalFormat
    // to format its substitution value)
    if (ruleToUse == NULL) {
        NFSubstitution::doSubstitution(number, toInsertInto, _pos, recursionCount, status);

        // a >>> substitution goes straight to a particular rule to
        // format the substitution value
    } else {
        double numberToFormat = transformNumber(number);

        ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos(), recursionCount, status);
    }
}

//-----------------------------------------------------------------------
// parsing
//-----------------------------------------------------------------------

/**
 * If this is a &gt;&gt;&gt; substitution, match only against ruleToUse.
 * Otherwise, use the superclass function.
 * @param text The string to parse
 * @param parsePosition Ignored on entry, updated on exit to point to
 * the first unmatched character.
 * @param baseValue The partial parse result prior to calling this
 * routine.
 */
UBool
ModulusSubstitution::doParse(const UnicodeString& text,
                             ParsePosition& parsePosition,
                             double baseValue,
                             double upperBound,
                             UBool lenientParse,
                             Formattable& result) const
{
    // if this isn't a >>> substitution, we can just use the
    // inherited parse() routine to do the parsing
    if (ruleToUse == NULL) {
        return NFSubstitution::doParse(text, parsePosition, baseValue, upperBound, lenientParse, result);

        // but if it IS a >>> substitution, we have to do it here: we
        // use the specific rule's doParse() method, and then we have to
        // do some of the other work of NFRuleSet.parse()
    } else {
        ruleToUse->doParse(text, parsePosition, FALSE, upperBound, result);

        if (parsePosition.getIndex() != 0) {
            UErrorCode status = U_ZERO_ERROR;
            double tempResult = result.getDouble(status);
            tempResult = composeRuleValue(tempResult, baseValue);
            result.setDouble(tempResult);
        }

        return TRUE;
    }
}
/**
 * Returns a textual description of the substitution
 * @return A textual description of the substitution.  This might
 * not be identical to the description it was created from, but
 * it'll produce the same result.
 */
void
ModulusSubstitution::toString(UnicodeString& text) const
{
  // use tokenChar() to get the character at the beginning and
  // end of the substitutin token.  In between them will go
  // either the name of the rule set it uses, or the pattern of
  // the DecimalFormat it uses

  if ( ruleToUse != NULL ) { // Must have been a >>> substitution.
      text.remove();
      text.append(tokenChar());
      text.append(tokenChar());
      text.append(tokenChar());
  } else { // Otherwise just use the super-class function.
	  NFSubstitution::toString(text);
  }
}
//===================================================================
// IntegralPartSubstitution
//===================================================================

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IntegralPartSubstitution)


//===================================================================
// FractionalPartSubstitution
//===================================================================


    /**
     * Constructs a FractionalPartSubstitution.  This object keeps a flag
     * telling whether it should format by digits or not.  In addition,
     * it marks the rule set it calls (if any) as a fraction rule set.
     */
FractionalPartSubstitution::FractionalPartSubstitution(int32_t _pos,
                             const NFRuleSet* _ruleSet,
                             const UnicodeString& description,
                             UErrorCode& status)
 : NFSubstitution(_pos, _ruleSet, description, status)
 , byDigits(FALSE)
 , useSpaces(TRUE)

{
    // akk, ruleSet can change in superclass constructor
    if (0 == description.compare(gGreaterGreaterThan, 2) ||
        0 == description.compare(gGreaterGreaterGreaterThan, 3) ||
        _ruleSet == getRuleSet()) {
        byDigits = TRUE;
        if (0 == description.compare(gGreaterGreaterGreaterThan, 3)) {
            useSpaces = FALSE;
        }
    } else {
        // cast away const
        ((NFRuleSet*)getRuleSet())->makeIntoFractionRuleSet();
    }
}

//-----------------------------------------------------------------------
// formatting
//-----------------------------------------------------------------------

/**
 * If in "by digits" mode, fills in the substitution one decimal digit
 * at a time using the rule set containing this substitution.
 * Otherwise, uses the superclass function.
 * @param number The number being formatted
 * @param toInsertInto The string to insert the result of formatting
 * the substitution into
 * @param pos The position of the owning rule's rule text in
 * toInsertInto
 */
void
FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInsertInto,
                                           int32_t _pos, int32_t recursionCount, UErrorCode& status) const
{
  // if we're not in "byDigits" mode, just use the inherited
  // doSubstitution() routine
  if (!byDigits) {
    NFSubstitution::doSubstitution(number, toInsertInto, _pos, recursionCount, status);

    // if we're in "byDigits" mode, transform the value into an integer
    // by moving the decimal point eight places to the right and
    // pulling digits off the right one at a time, formatting each digit
    // as an integer using this substitution's owning rule set
    // (this is slower, but more accurate, than doing it from the
    // other end)
  } else {
    //          int32_t numberToFormat = (int32_t)uprv_round(transformNumber(number) * uprv_pow(10, kMaxDecimalDigits));
    //          // this flag keeps us from formatting trailing zeros.  It starts
    //          // out false because we're pulling from the right, and switches
    //          // to true the first time we encounter a non-zero digit
    //          UBool doZeros = FALSE;
    //          for (int32_t i = 0; i < kMaxDecimalDigits; i++) {
    //              int64_t digit = numberToFormat % 10;
    //              if (digit != 0 || doZeros) {
    //                  if (doZeros && useSpaces) {
    //                      toInsertInto.insert(_pos + getPos(), gSpace);
    //                  }
    //                  doZeros = TRUE;
    //                  getRuleSet()->format(digit, toInsertInto, _pos + getPos());
    //              }
    //              numberToFormat /= 10;
    //          }

    DigitList dl;
    dl.set(number);
    dl.roundFixedPoint(20);     // round to 20 fraction digits.
    dl.reduce();                // Removes any trailing zeros.
    
    UBool pad = FALSE;
    for (int32_t didx = dl.getCount()-1; didx>=dl.getDecimalAt(); didx--) {
      // Loop iterates over fraction digits, starting with the LSD.
      //   include both real digits from the number, and zeros
      //   to the left of the MSD but to the right of the decimal point.
      if (pad && useSpaces) {
        toInsertInto.insert(_pos + getPos(), gSpace);
      } else {
        pad = TRUE;
      }
      int64_t digit = didx>=0 ? dl.getDigit(didx) - '0' : 0;
      getRuleSet()->format(digit, toInsertInto, _pos + getPos(), recursionCount, status);
    }

    if (!pad) {
      // hack around lack of precision in digitlist. if we would end up with
      // "foo point" make sure we add a " zero" to the end.
      getRuleSet()->format((int64_t)0, toInsertInto, _pos + getPos(), recursionCount, status);
    }
  }
}

//-----------------------------------------------------------------------
// parsing
//-----------------------------------------------------------------------

/**
 * If in "by digits" mode, parses the string as if it were a string
 * of individual digits; otherwise, uses the superclass function.
 * @param text The string to parse
 * @param parsePosition Ignored on entry, but updated on exit to point
 * to the first unmatched character
 * @param baseValue The partial parse result prior to entering this
 * function
 * @param upperBound Only consider rules with base values lower than
 * this when filling in the substitution
 * @param lenientParse If true, try matching the text as numerals if
 * matching as words doesn't work
 * @return If the match was successful, the current partial parse
 * result; otherwise new Long(0).  The result is either a Long or
 * a Double.
 */

UBool
FractionalPartSubstitution::doParse(const UnicodeString& text,
                ParsePosition& parsePosition,
                double baseValue,
                double /*upperBound*/,
                UBool lenientParse,
                Formattable& resVal) const
{
    // if we're not in byDigits mode, we can just use the inherited
    // doParse()
    if (!byDigits) {
        return NFSubstitution::doParse(text, parsePosition, baseValue, 0, lenientParse, resVal);

        // if we ARE in byDigits mode, parse the text one digit at a time
        // using this substitution's owning rule set (we do this by setting
        // upperBound to 10 when calling doParse() ) until we reach
        // nonmatching text
    } else {
        UnicodeString workText(text);
        ParsePosition workPos(1);
        double result = 0;
        int32_t digit;
//          double p10 = 0.1;

        DigitList dl;
        NumberFormat* fmt = NULL;
        while (workText.length() > 0 && workPos.getIndex() != 0) {
            workPos.setIndex(0);
            Formattable temp;
            getRuleSet()->parse(workText, workPos, 10, temp);
            UErrorCode status = U_ZERO_ERROR;
            digit = temp.getLong(status);
//            digit = temp.getType() == Formattable::kLong ?
//               temp.getLong() :
//            (int32_t)temp.getDouble();

            if (lenientParse && workPos.getIndex() == 0) {
                if (!fmt) {
                    status = U_ZERO_ERROR;
                    fmt = NumberFormat::createInstance(status);
                    if (U_FAILURE(status)) {
                        delete fmt;
                        fmt = NULL;
                    }
                }
                if (fmt) {
                    fmt->parse(workText, temp, workPos);
                    digit = temp.getLong(status);
                }
            }

            if (workPos.getIndex() != 0) {
                dl.append((char)('0' + digit));
//                  result += digit * p10;
//                  p10 /= 10;
                parsePosition.setIndex(parsePosition.getIndex() + workPos.getIndex());
                workText.removeBetween(0, workPos.getIndex());
                while (workText.length() > 0 && workText.charAt(0) == gSpace) {
                    workText.removeBetween(0, 1);
                    parsePosition.setIndex(parsePosition.getIndex() + 1);
                }
            }
        }
        delete fmt;

        result = dl.getCount() == 0 ? 0 : dl.getDouble();
        result = composeRuleValue(result, baseValue);
        resVal.setDouble(result);
        return TRUE;
    }
}

UBool
FractionalPartSubstitution::operator==(const NFSubstitution& rhs) const
{
  return NFSubstitution::operator==(rhs) &&
  ((const FractionalPartSubstitution*)&rhs)->byDigits == byDigits;
}

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(FractionalPartSubstitution)


//===================================================================
// AbsoluteValueSubstitution
//===================================================================

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AbsoluteValueSubstitution)

//===================================================================
// NumeratorSubstitution
//===================================================================

void
NumeratorSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t apos, int32_t recursionCount, UErrorCode& status) const {
    // perform a transformation on the number being formatted that
    // is dependent on the type of substitution this is

    double numberToFormat = transformNumber(number);
    int64_t longNF = util64_fromDouble(numberToFormat);

    const NFRuleSet* aruleSet = getRuleSet();
    if (withZeros && aruleSet != NULL) {
        // if there are leading zeros in the decimal expansion then emit them
        int64_t nf =longNF;
        int32_t len = toInsertInto.length();
        while ((nf *= 10) < denominator) {
            toInsertInto.insert(apos + getPos(), gSpace);
            aruleSet->format((int64_t)0, toInsertInto, apos + getPos(), recursionCount, status);
        }
        apos += toInsertInto.length() - len;
    }

    // if the result is an integer, from here on out we work in integer
    // space (saving time and memory and preserving accuracy)
    if (numberToFormat == longNF && aruleSet != NULL) {
        aruleSet->format(longNF, toInsertInto, apos + getPos(), recursionCount, status);

        // if the result isn't an integer, then call either our rule set's
        // format() method or our DecimalFormat's format() method to
        // format the result
    } else {
        if (aruleSet != NULL) {
            aruleSet->format(numberToFormat, toInsertInto, apos + getPos(), recursionCount, status);
        } else {
            UnicodeString temp;
            getNumberFormat()->format(numberToFormat, temp, status);
            toInsertInto.insert(apos + getPos(), temp);
        }
    }
}

UBool 
NumeratorSubstitution::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

    // if withZeros is true, we need to count the zeros
    // and use that to adjust the parse result
    UErrorCode status = U_ZERO_ERROR;
    int32_t zeroCount = 0;
    UnicodeString workText(text);

    if (withZeros) {
        ParsePosition workPos(1);
        Formattable temp;

        while (workText.length() > 0 && workPos.getIndex() != 0) {
            workPos.setIndex(0);
            getRuleSet()->parse(workText, workPos, 1, temp); // parse zero or nothing at all
            if (workPos.getIndex() == 0) {
                // we failed, either there were no more zeros, or the number was formatted with digits
                // either way, we're done
                break;
            }

            ++zeroCount;
            parsePosition.setIndex(parsePosition.getIndex() + workPos.getIndex());
            workText.remove(0, workPos.getIndex());
            while (workText.length() > 0 && workText.charAt(0) == gSpace) {
                workText.remove(0, 1);
                parsePosition.setIndex(parsePosition.getIndex() + 1);
            }
        }

        workText = text;
        workText.remove(0, (int32_t)parsePosition.getIndex());
        parsePosition.setIndex(0);
    }

    // we've parsed off the zeros, now let's parse the rest from our current position
    NFSubstitution::doParse(workText, parsePosition, withZeros ? 1 : baseValue, upperBound, FALSE, result);

    if (withZeros) {
        // any base value will do in this case.  is there a way to
        // force this to not bother trying all the base values?

        // compute the 'effective' base and prescale the value down
        int64_t n = result.getLong(status); // force conversion!
        int64_t d = 1;
        int32_t pow = 0;
        while (d <= n) {
            d *= 10;
            ++pow;
        }
        // now add the zeros
        while (zeroCount > 0) {
            d *= 10;
            --zeroCount;
        }
        // d is now our true denominator
        result.setDouble((double)n/(double)d);
    }

    return TRUE;
}

UBool
NumeratorSubstitution::operator==(const NFSubstitution& rhs) const
{
    return NFSubstitution::operator==(rhs) &&
        denominator == ((const NumeratorSubstitution*)&rhs)->denominator;
}

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumeratorSubstitution)

const UChar NumeratorSubstitution::LTLT[] = { 0x003c, 0x003c };
        
U_NAMESPACE_END

/* U_HAVE_RBNF */
#endif

