X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/374ca955a76ecab1204ca8bfa63ff9238d998416..729e4ab9bc6618bc3d8a898e575df7f4019e29ca:/icuSources/i18n/nfsubs.cpp diff --git a/icuSources/i18n/nfsubs.cpp b/icuSources/i18n/nfsubs.cpp index 25461981..0ac7ec97 100644 --- a/icuSources/i18n/nfsubs.cpp +++ b/icuSources/i18n/nfsubs.cpp @@ -1,6 +1,6 @@ /* ****************************************************************************** -* Copyright (C) 1997-2004, International Business Machines +* Copyright (C) 1997-2010, International Business Machines * Corporation and others. All Rights Reserved. ****************************************************************************** * file name: nfsubs.cpp @@ -13,11 +13,12 @@ * 10/11/2001 Doug Ported from ICU4J */ +#include +#include // for 'typeid' to work + #include "nfsubs.h" #include "digitlst.h" -#include - #if U_HAVE_RBNF static const UChar gLessThan = 0x003c; @@ -41,6 +42,288 @@ static const UChar gGreaterGreaterThan[] = 0x3E, 0x3E, 0 }; /* ">>" */ +U_NAMESPACE_BEGIN + +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 /*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; +}; + +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 { + 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; +}; + +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 /*oldUpperBound*/) const { return divisor; } + + virtual UBool isModulusSubstitution() const { return TRUE; } + + virtual UChar tokenChar() const { return (UChar)0x003e; } // '>' + +public: + static UClassID getStaticClassID(void); + 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 /*oldUpperBound*/) const { return DBL_MAX; } + virtual UChar tokenChar() const { return (UChar)0x003c; } // '<' + +public: + static UClassID getStaticClassID(void); + 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 /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) 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; +}; + +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 /*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; +}; + +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 /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) 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 /*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; +}; + +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& /*result*/) const {} + virtual void doSubstitution(double /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) const {} + virtual void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) const {} + virtual int64_t transformNumber(int64_t /*number*/) const { return 0; } + virtual double transformNumber(double /*number*/) const { return 0; } + virtual UBool doParse(const UnicodeString& /*text*/, + ParsePosition& /*parsePosition*/, + double baseValue, + double /*upperBound*/, + UBool /*lenientParse*/, + Formattable& result) const + { result.setDouble(baseValue); return TRUE; } + virtual double composeRuleValue(double /*newRuleValue*/, double /*oldRuleValue*/) const { return 0.0; } // never called + virtual double calcUpperBound(double /*oldUpperBound*/) const { return 0; } // never called + virtual UBool isNullSubstitution() const { return TRUE; } + virtual UChar tokenChar() const { return (UChar)0x0020; } // ' ' never called + +public: + static UClassID getStaticClassID(void); + virtual UClassID getDynamicClassID(void) const; +}; + NFSubstitution* NFSubstitution::makeSubstitution(int32_t pos, const NFRule* rule, @@ -230,25 +513,20 @@ NFSubstitution::setDivisor(int32_t /*radix*/, int32_t /*exponent*/, UErrorCode& // boilerplate //----------------------------------------------------------------------- -const char NFSubstitution::fgClassID = 0; - -UClassID -NFSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} +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 - */ +/** + * 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 getDynamicClassID() == rhs.getDynamicClassID() + return typeid(*this) == typeid(rhs) && pos == rhs.pos && (ruleSet == NULL) == (rhs.ruleSet == NULL) // && ruleSet == rhs.ruleSet causes circularity, other checks to make instead? @@ -257,12 +535,12 @@ NFSubstitution::operator==(const NFSubstitution& rhs) const : (*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. - */ +/** + * 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 { @@ -276,7 +554,7 @@ NFSubstitution::toString(UnicodeString& text) const UnicodeString temp; if (ruleSet != NULL) { ruleSet->getName(temp); - } else { + } else if (numberFormat != NULL) { numberFormat->toPattern(temp); } text.append(temp); @@ -305,7 +583,7 @@ NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int3 // 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); - } else { + } 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 @@ -336,10 +614,12 @@ NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32 // perform a transformation on the number being formatted that // is dependent on the type of substitution this is double numberToFormat = transformNumber(number); + DigitList digits; + digits.set(numberToFormat); // 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) { + if (numberToFormat == uprv_floor(numberToFormat) && ruleSet != NULL && (!digits.isInfinite())) { ruleSet->format(util64_fromDouble(numberToFormat), toInsertInto, _pos + this->pos); // if the result isn't an integer, then call either our rule set's @@ -348,7 +628,7 @@ NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32 } else { if (ruleSet != NULL) { ruleSet->format(numberToFormat, toInsertInto, _pos + this->pos); - } else { + } else if (numberFormat != NULL) { UnicodeString temp; numberFormat->format(numberToFormat, temp); toInsertInto.insert(_pos + this->pos, temp); @@ -431,7 +711,7 @@ NFSubstitution::doParse(const UnicodeString& text, } // ...or use our DecimalFormat to parse the text - } else { + } else if (numberFormat != NULL) { numberFormat->parse(text, result, parsePosition); } @@ -491,6 +771,22 @@ NFSubstitution::isModulusSubstitution() const { return FALSE; } + /** + * @return true if this is a decimal format-only substitution + */ +UBool +NFSubstitution::isDecimalFormatSubstitutionOnly() const { + return (ruleSet == NULL && getNumberFormat() != NULL); +} + + /** + * @return true if this substitution uses another ruleSet + */ +UBool +NFSubstitution::isRuleSetSubstitutionOnly() const { + return (getNumberFormat() == NULL && ruleSet != NULL); +} + //=================================================================== // SameValueSubstitution //=================================================================== @@ -512,24 +808,13 @@ SameValueSubstitution::SameValueSubstitution(int32_t _pos, } } -const char SameValueSubstitution::fgClassID = 0; - -UClassID -SameValueSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} - +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SameValueSubstitution) //=================================================================== // MultiplierSubstitution //=================================================================== -const char MultiplierSubstitution::fgClassID = 0; - -UClassID -MultiplierSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MultiplierSubstitution) UBool MultiplierSubstitution::operator==(const NFSubstitution& rhs) const { @@ -578,12 +863,7 @@ ModulusSubstitution::ModulusSubstitution(int32_t _pos, } } -const char ModulusSubstitution::fgClassID = 0; - -UClassID -ModulusSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ModulusSubstitution) UBool ModulusSubstitution::operator==(const NFSubstitution& rhs) const { @@ -681,7 +961,8 @@ ModulusSubstitution::doParse(const UnicodeString& text, ruleToUse->doParse(text, parsePosition, FALSE, upperBound, result); if (parsePosition.getIndex() != 0) { - double tempResult = result.getDouble(); + UErrorCode status = U_ZERO_ERROR; + double tempResult = result.getDouble(status); tempResult = composeRuleValue(tempResult, baseValue); result.setDouble(tempResult); } @@ -695,12 +976,7 @@ ModulusSubstitution::doParse(const UnicodeString& text, // IntegralPartSubstitution //=================================================================== -const char IntegralPartSubstitution::fgClassID = 0; - -UClassID -IntegralPartSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IntegralPartSubstitution) //=================================================================== @@ -784,25 +1060,22 @@ FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInser // } DigitList dl; - dl.set(number, 20, TRUE); + dl.set(number); + dl.roundFixedPoint(20); // round to 20 fraction digits. + dl.reduce(); // Removes any trailing zeros. UBool pad = FALSE; - while (dl.fCount > (dl.fDecimalAt <= 0 ? 0 : dl.fDecimalAt)) { + 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; } - getRuleSet()->format((int64_t)(dl.fDigits[--dl.fCount] - '0'), toInsertInto, _pos + getPos()); - } - while (dl.fDecimalAt < 0) { - if (pad && useSpaces) { - toInsertInto.insert(_pos + getPos(), gSpace); - } else { - pad = TRUE; - } - getRuleSet()->format((int64_t)0, toInsertInto, _pos + getPos()); - ++dl.fDecimalAt; + int64_t digit = didx>=0 ? dl.getDigit(didx) - '0' : 0; + getRuleSet()->format(digit, toInsertInto, _pos + getPos()); } if (!pad) { @@ -881,7 +1154,7 @@ FractionalPartSubstitution::doParse(const UnicodeString& text, } if (fmt) { fmt->parse(workText, temp, workPos); - digit = temp.getLong(); + digit = temp.getLong(status); } } @@ -898,8 +1171,8 @@ FractionalPartSubstitution::doParse(const UnicodeString& text, } } delete fmt; - result = dl.fCount == 0 ? 0 : dl.getDouble(); + result = dl.getCount() == 0 ? 0 : dl.getDouble(); result = composeRuleValue(result, baseValue); resVal.setDouble(result); return TRUE; @@ -913,29 +1186,131 @@ FractionalPartSubstitution::operator==(const NFSubstitution& rhs) const ((const FractionalPartSubstitution*)&rhs)->byDigits == byDigits; } -const char FractionalPartSubstitution::fgClassID = 0; - -UClassID -FractionalPartSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(FractionalPartSubstitution) //=================================================================== // AbsoluteValueSubstitution //=================================================================== -const char AbsoluteValueSubstitution::fgClassID = 0; - -UClassID -AbsoluteValueSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AbsoluteValueSubstitution) //=================================================================== // NumeratorSubstitution //=================================================================== +void +NumeratorSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t apos) 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()); + } + 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()); + + // 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()); + } else { + UErrorCode status = U_ZERO_ERROR; + 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 { @@ -943,23 +1318,17 @@ NumeratorSubstitution::operator==(const NFSubstitution& rhs) const denominator == ((const NumeratorSubstitution*)&rhs)->denominator; } -const char NumeratorSubstitution::fgClassID = 0; - -UClassID -NumeratorSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumeratorSubstitution) +const UChar NumeratorSubstitution::LTLT[] = { 0x003c, 0x003c }; + //=================================================================== // NullSubstitution //=================================================================== -const char NullSubstitution::fgClassID = 0; +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NullSubstitution) -UClassID -NullSubstitution::getDynamicClassID() const { - return getStaticClassID(); -} +U_NAMESPACE_END /* U_HAVE_RBNF */ #endif