mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-06 22:15:31 +00:00
ICU-1766 Make RBNF in ICU4C use 64-bit ints
(still need to remove llong.h, llong.cpp and commented-out code) X-SVN-Rev: 8008
This commit is contained in:
parent
66bee38a79
commit
f3acab9495
13 changed files with 848 additions and 505 deletions
|
@ -14,6 +14,9 @@
|
|||
*/
|
||||
|
||||
#include "nfrs.h"
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
#include "nfrule.h"
|
||||
#include "nfrlist.h"
|
||||
#include "unicode/uchar.h"
|
||||
|
@ -30,8 +33,8 @@ U_NAMESPACE_BEGIN
|
|||
// isn't as much range as we get with longs. We probably still
|
||||
// want either 64-bit math, or BigInteger.
|
||||
|
||||
static llong
|
||||
util_lcm(llong x, llong y)
|
||||
static int64_t
|
||||
util_lcm(int64_t x, int64_t y)
|
||||
{
|
||||
x.abs();
|
||||
y.abs();
|
||||
|
@ -41,7 +44,7 @@ util_lcm(llong x, llong y)
|
|||
} else {
|
||||
do {
|
||||
if (x < y) {
|
||||
llong t = x; x = y; y = t;
|
||||
int64_t t = x; x = y; y = t;
|
||||
}
|
||||
x -= y * (x/y);
|
||||
} while (x != 0);
|
||||
|
@ -54,13 +57,13 @@ util_lcm(llong x, llong y)
|
|||
/**
|
||||
* Calculates the least common multiple of x and y.
|
||||
*/
|
||||
static llong
|
||||
util_lcm(llong x, llong y)
|
||||
static int64_t
|
||||
util_lcm(int64_t x, int64_t y)
|
||||
{
|
||||
// binary gcd algorithm from Knuth, "The Art of Computer Programming,"
|
||||
// vol. 2, 1st ed., pp. 298-299
|
||||
llong x1 = x;
|
||||
llong y1 = y;
|
||||
int64_t x1 = x;
|
||||
int64_t y1 = y;
|
||||
|
||||
int p2 = 0;
|
||||
while ((x1 & 1) == 0 && (y1 & 1) == 0) {
|
||||
|
@ -69,7 +72,7 @@ util_lcm(llong x, llong y)
|
|||
y1 >>= 1;
|
||||
}
|
||||
|
||||
llong t;
|
||||
int64_t t;
|
||||
if ((x1 & 1) == 1) {
|
||||
t = -y1;
|
||||
} else {
|
||||
|
@ -88,7 +91,7 @@ util_lcm(llong x, llong y)
|
|||
t = x1 - y1;
|
||||
}
|
||||
|
||||
llong gcd = x1 << p2;
|
||||
int64_t gcd = x1 << p2;
|
||||
|
||||
// x * y == gcd(x, y) * lcm(x, y)
|
||||
return x / gcd * y;
|
||||
|
@ -187,7 +190,7 @@ NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* o
|
|||
// were initialized to 0. Make another pass through the list and
|
||||
// set all those rules' base values. We also remove any special
|
||||
// rules from the list and put them into their own member variables
|
||||
llong defaultBaseValue = (int32_t)0;
|
||||
int64_t defaultBaseValue = 0;
|
||||
|
||||
// (this isn't a for loop because we might be deleting items from
|
||||
// the vector-- we want to make sure we only increment i when
|
||||
|
@ -296,7 +299,7 @@ NFRuleSet::operator==(const NFRuleSet& rhs) const
|
|||
}
|
||||
|
||||
void
|
||||
NFRuleSet::format(llong number, UnicodeString& toAppendTo, int32_t pos) const
|
||||
NFRuleSet::format(int64_t number, UnicodeString& toAppendTo, int32_t pos) const
|
||||
{
|
||||
NFRule *rule = findNormalRule(number);
|
||||
rule->doFormat(number, toAppendTo, pos);
|
||||
|
@ -348,18 +351,18 @@ NFRuleSet::findDoubleRule(double number) const
|
|||
|
||||
// and if we haven't yet returned a rule, use findNormalRule()
|
||||
// to find the applicable rule
|
||||
llong r = number + 0.5;
|
||||
int64_t r = util64_fromDouble(number + 0.5);
|
||||
return findNormalRule(r);
|
||||
}
|
||||
|
||||
NFRule *
|
||||
NFRuleSet::findNormalRule(llong number) const
|
||||
NFRuleSet::findNormalRule(int64_t number) const
|
||||
{
|
||||
// if this is a fraction rule set, use findFractionRuleSetRule()
|
||||
// to find the rule (we should only go into this clause if the
|
||||
// value is 0)
|
||||
if (fIsFractionRuleSet) {
|
||||
return findFractionRuleSetRule(number.asDouble());
|
||||
return findFractionRuleSetRule((double)number);
|
||||
}
|
||||
|
||||
// if the number is negative, return the negative-number rule
|
||||
|
@ -410,7 +413,7 @@ NFRuleSet::findNormalRule(llong number) const
|
|||
// an explanation of the rollback rule). If we do, roll back
|
||||
// one rule and return that one instead of the one we'd normally
|
||||
// return
|
||||
if (result->shouldRollBack(number.asDouble())) {
|
||||
if (result->shouldRollBack((double)number)) {
|
||||
result = rules[hi - 2];
|
||||
}
|
||||
return result;
|
||||
|
@ -446,17 +449,17 @@ NFRuleSet::findFractionRuleSetRule(double number) const
|
|||
// and multiply this by the number being formatted. This is
|
||||
// all the precision we need, and we can do all of the rest
|
||||
// of the math using integer arithmetic
|
||||
llong leastCommonMultiple = rules[0]->getBaseValue();
|
||||
llong numerator;
|
||||
int64_t leastCommonMultiple = rules[0]->getBaseValue();
|
||||
int64_t numerator;
|
||||
{
|
||||
for (uint32_t i = 1; i < rules.size(); ++i) {
|
||||
leastCommonMultiple = util_lcm(leastCommonMultiple, rules[i]->getBaseValue());
|
||||
}
|
||||
numerator = number * leastCommonMultiple.asDouble() + 0.5;
|
||||
numerator = util64_fromDouble(number * (double)leastCommonMultiple + 0.5);
|
||||
}
|
||||
// for each rule, do the following...
|
||||
llong tempDifference;
|
||||
llong difference(uprv_maxMantissa());
|
||||
int64_t tempDifference;
|
||||
int64_t difference = util64_fromDouble(uprv_maxMantissa());
|
||||
int32_t winner = 0;
|
||||
for (uint32_t i = 0; i < rules.size(); ++i) {
|
||||
// "numerator" is the numerator of the fraction if the
|
||||
|
@ -496,7 +499,7 @@ NFRuleSet::findFractionRuleSetRule(double number) const
|
|||
// a whole bunch of extra rule sets)
|
||||
if ((unsigned)(winner + 1) < rules.size() &&
|
||||
rules[winner + 1]->getBaseValue() == rules[winner]->getBaseValue()) {
|
||||
double n = rules[winner]->getBaseValue().asDouble() * number;
|
||||
double n = ((double)rules[winner]->getBaseValue()) * number;
|
||||
if (n < 0.5 || n >= 2) {
|
||||
++winner;
|
||||
}
|
||||
|
@ -617,12 +620,14 @@ NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBoun
|
|||
// limit ambiguity by making sure the rules that match a rule's
|
||||
// are less significant than the rule containing the substitutions)/
|
||||
{
|
||||
llong ub(upperBound);
|
||||
int64_t ub = util64_fromDouble(upperBound);
|
||||
#ifdef RBNF_DEBUG
|
||||
{
|
||||
char ubstr[64];
|
||||
ub.lltoa(ubstr, 64);
|
||||
fprintf(stderr, "ub: %g, ll: %s(%x/%x)\n", upperBound, ubstr, ub.hi, ub.lo);
|
||||
util64_toa(ub, ubstr, 64);
|
||||
char ubstrhex[64];
|
||||
util64_toa(ub, ubstrhex, 64, 16);
|
||||
fprintf(stderr, "ub: %g, i64: %s (%s)\n", upperBound, ubstr, ubstrhex);
|
||||
}
|
||||
#endif
|
||||
for (int32_t i = rules.size(); --i >= 0 && highWaterMark.getIndex() < text.length();) {
|
||||
|
@ -682,4 +687,224 @@ NFRuleSet::appendRules(UnicodeString& result) const
|
|||
}
|
||||
}
|
||||
|
||||
// utility functions
|
||||
|
||||
int64_t util64_fromDouble(double d) {
|
||||
int64_t result = 0;
|
||||
if (!uprv_isNaN(d)) {
|
||||
double mant = uprv_maxMantissa();
|
||||
if (d < -mant) {
|
||||
d = -mant;
|
||||
} else if (d > mant) {
|
||||
d = mant;
|
||||
}
|
||||
UBool neg = d < 0;
|
||||
if (neg) {
|
||||
d = -d;
|
||||
}
|
||||
result = (int64_t)uprv_floor(d);
|
||||
if (neg) {
|
||||
result = -result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t util64_pow(int32_t r, uint32_t e) {
|
||||
if (r == 0) {
|
||||
return 0;
|
||||
} else if (e == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
int64_t n = r;
|
||||
while (--e > 0) {
|
||||
n *= r;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
static const uint8_t asciiDigits[] = {
|
||||
0x30u, 0x31u, 0x32u, 0x33u, 0x34u, 0x35u, 0x36u, 0x37u,
|
||||
0x38u, 0x39u, 0x61u, 0x62u, 0x63u, 0x64u, 0x65u, 0x66u,
|
||||
0x67u, 0x68u, 0x69u, 0x6au, 0x6bu, 0x6cu, 0x6du, 0x6eu,
|
||||
0x6fu, 0x70u, 0x71u, 0x72u, 0x73u, 0x74u, 0x75u, 0x76u,
|
||||
0x77u, 0x78u, 0x79u, 0x7au,
|
||||
};
|
||||
|
||||
static const UChar kUMinus = (UChar)0x002d;
|
||||
|
||||
static const char kMinus = '-';
|
||||
|
||||
static const uint8_t digitInfo[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x80u, 0x81u, 0x82u, 0x83u, 0x84u, 0x85u, 0x86u, 0x87u,
|
||||
0x88u, 0x89u, 0, 0, 0, 0, 0, 0,
|
||||
0, 0x8au, 0x8bu, 0x8cu, 0x8du, 0x8eu, 0x8fu, 0x90u,
|
||||
0x91u, 0x92u, 0x93u, 0x94u, 0x95u, 0x96u, 0x97u, 0x98u,
|
||||
0x99u, 0x9au, 0x9bu, 0x9cu, 0x9du, 0x9eu, 0x9fu, 0xa0u,
|
||||
0xa1u, 0xa2u, 0xa3u, 0, 0, 0, 0, 0,
|
||||
0, 0x8au, 0x8bu, 0x8cu, 0x8du, 0x8eu, 0x8fu, 0x90u,
|
||||
0x91u, 0x92u, 0x93u, 0x94u, 0x95u, 0x96u, 0x97u, 0x98u,
|
||||
0x99u, 0x9au, 0x9bu, 0x9cu, 0x9du, 0x9eu, 0x9fu, 0xa0u,
|
||||
0xa1u, 0xa2u, 0xa3u, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
#ifdef RBNF_DEBUG
|
||||
int64_t util64_atoi(const char* str, uint32_t radix)
|
||||
{
|
||||
if (radix > 36) {
|
||||
radix = 36;
|
||||
} else if (radix < 2) {
|
||||
radix = 2;
|
||||
}
|
||||
int64_t lradix = radix;
|
||||
|
||||
int neg = 0;
|
||||
if (*str == kMinus) {
|
||||
++str;
|
||||
neg = 1;
|
||||
}
|
||||
int64_t result = 0;
|
||||
uint8_t b;
|
||||
while ((b = digitInfo[*str++]) && ((b &= 0x7f) < radix)) {
|
||||
result *= lradix;
|
||||
result += (int32_t)b;
|
||||
}
|
||||
if (neg) {
|
||||
result = -result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
int64_t util64_utoi(const UChar* str, uint32_t radix)
|
||||
{
|
||||
if (radix > 36) {
|
||||
radix = 36;
|
||||
} else if (radix < 2) {
|
||||
radix = 2;
|
||||
}
|
||||
int64_t lradix = radix;
|
||||
|
||||
int neg = 0;
|
||||
if (*str == kUMinus) {
|
||||
++str;
|
||||
neg = 1;
|
||||
}
|
||||
int64_t result = 0;
|
||||
UChar c;
|
||||
uint8_t b;
|
||||
while (((c = *str++) < 0x0080) && (b = digitInfo[c]) && ((b &= 0x7f) < radix)) {
|
||||
result *= lradix;
|
||||
result += (int32_t)b;
|
||||
}
|
||||
if (neg) {
|
||||
result = -result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef RBNF_DEBUG
|
||||
uint32_t util64_toa(int64_t w, char* buf, uint32_t len, uint32_t radix, UBool raw)
|
||||
{
|
||||
if (radix > 36) {
|
||||
radix = 36;
|
||||
} else if (radix < 2) {
|
||||
radix = 2;
|
||||
}
|
||||
int64_t base = radix;
|
||||
|
||||
char* p = buf;
|
||||
if (len && (w < 0) && (radix == 10) && !raw) {
|
||||
w = -w;
|
||||
*p++ = kMinus;
|
||||
--len;
|
||||
} else if (len && (w == 0)) {
|
||||
*p++ = (char)raw ? 0 : asciiDigits[0];
|
||||
--len;
|
||||
}
|
||||
|
||||
while (len && w != 0) {
|
||||
int64_t n = w / base;
|
||||
int64_t m = n * base;
|
||||
int32_t d = (int32_t)(w-m);
|
||||
*p++ = raw ? (char)d : asciiDigits[d];
|
||||
w = n;
|
||||
--len;
|
||||
}
|
||||
if (len) {
|
||||
*p = 0; // null terminate if room for caller convenience
|
||||
}
|
||||
|
||||
len = p - buf;
|
||||
if (*buf == kMinus) {
|
||||
++buf;
|
||||
}
|
||||
while (--p > buf) {
|
||||
char c = *p;
|
||||
*p = *buf;
|
||||
*buf = c;
|
||||
++buf;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t util64_tou(int64_t w, UChar* buf, uint32_t len, uint32_t radix, UBool raw)
|
||||
{
|
||||
if (radix > 36) {
|
||||
radix = 36;
|
||||
} else if (radix < 2) {
|
||||
radix = 2;
|
||||
}
|
||||
int64_t base = radix;
|
||||
|
||||
UChar* p = buf;
|
||||
if (len && (w < 0) && (radix == 10) && !raw) {
|
||||
w = -w;
|
||||
*p++ = kUMinus;
|
||||
--len;
|
||||
} else if (len && (w == 0)) {
|
||||
*p++ = (UChar)raw ? 0 : asciiDigits[0];
|
||||
--len;
|
||||
}
|
||||
|
||||
while (len && (w != 0)) {
|
||||
int64_t n = w / base;
|
||||
int64_t m = n * base;
|
||||
int32_t d = (int32_t)(w-m);
|
||||
*p++ = (UChar)(raw ? d : asciiDigits[d]);
|
||||
w = n;
|
||||
--len;
|
||||
}
|
||||
if (len) {
|
||||
*p = 0; // null terminate if room for caller convenience
|
||||
}
|
||||
|
||||
len = p - buf;
|
||||
if (*buf == kUMinus) {
|
||||
++buf;
|
||||
}
|
||||
while (--p > buf) {
|
||||
UChar c = *p;
|
||||
*p = *buf;
|
||||
*buf = c;
|
||||
++buf;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
#ifndef NFRS_H
|
||||
#define NFRS_H
|
||||
|
||||
#include "unicode/rbnf.h"
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/umisc.h"
|
||||
|
||||
#include "unicode/rbnf.h"
|
||||
#include "nfrlist.h"
|
||||
#include "llong.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -42,7 +44,7 @@ class NFRuleSet {
|
|||
void getName(UnicodeString& result) const { result.setTo(name); }
|
||||
UBool isNamed(const UnicodeString& _name) const { return this->name == _name; }
|
||||
|
||||
void format(llong number, UnicodeString& toAppendTo, int32_t pos) const;
|
||||
void format(int64_t number, UnicodeString& toAppendTo, int32_t pos) const;
|
||||
void format(double number, UnicodeString& toAppendTo, int32_t pos) const;
|
||||
|
||||
UBool parse(const UnicodeString& text, ParsePosition& pos, double upperBound, Formattable& result) const;
|
||||
|
@ -50,7 +52,7 @@ class NFRuleSet {
|
|||
void appendRules(UnicodeString& result) const; // toString
|
||||
|
||||
private:
|
||||
NFRule * findNormalRule(llong number) const;
|
||||
NFRule * findNormalRule(int64_t number) const;
|
||||
NFRule * findDoubleRule(double number) const;
|
||||
NFRule * findFractionRuleSetRule(double number) const;
|
||||
|
||||
|
@ -63,8 +65,28 @@ class NFRuleSet {
|
|||
UBool fIsPublic;
|
||||
};
|
||||
|
||||
// utilities from old llong.h
|
||||
// convert mantissa portion of double to int64
|
||||
int64_t util64_fromDouble(double d);
|
||||
|
||||
// raise radix to the power exponent, only non-negative exponents
|
||||
int64_t util64_pow(int32_t radix, uint32_t exponent);
|
||||
|
||||
// convert n to digit string in buffer, return length of string
|
||||
uint32_t util64_tou(int64_t n, UChar* buffer, uint32_t buflen, uint32_t radix = 10, UBool raw = FALSE);
|
||||
int64_t util64_utoi(const UChar* str, uint32_t radix = 10);
|
||||
|
||||
#ifdef RBNF_DEBUG
|
||||
uint32_t util64_toa(int64_t n, char* buffer, uint32_t buflen, uint32_t radix = 10, UBool raw = FALSE);
|
||||
int64_t util64_atoi(const char* str, uint32_t radix);
|
||||
#endif
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
||||
// NFRS_H
|
||||
#endif
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "nfrule.h"
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
#include "unicode/rbnf.h"
|
||||
#include "unicode/tblcoll.h"
|
||||
#include "unicode/coleitr.h"
|
||||
|
@ -124,7 +126,7 @@ NFRule::makeRules(UnicodeString& description,
|
|||
// base value is an even multiple of its divisor (or it's one
|
||||
// of the special rules)
|
||||
if ((rule1->baseValue > 0
|
||||
&& (rule1->baseValue % ((llong)rule1->radix).pow((int32_t)rule1->exponent)) == 0)
|
||||
&& (rule1->baseValue % util64_pow(rule1->radix, rule1->exponent)) == 0)
|
||||
|| rule1->getType() == kImproperFractionRule
|
||||
|| rule1->getType() == kMasterRule) {
|
||||
|
||||
|
@ -249,7 +251,7 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
|
|||
// since we don't have Long.parseLong, and this isn't much work anyway,
|
||||
// just build up the value as we encounter the digits.
|
||||
else if (descriptor.charAt(0) >= gZero && descriptor.charAt(0) <= gNine) {
|
||||
llong val = (int32_t)0;
|
||||
int64_t val = 0;
|
||||
p = 0;
|
||||
UChar c = gSpace;
|
||||
|
||||
|
@ -257,7 +259,7 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
|
|||
// into "tempValue", skip periods, commas, and spaces,
|
||||
// stop on a slash or > sign (or at the end of the string),
|
||||
// and throw an exception on any other character
|
||||
llong ll_10 = (int32_t)10;
|
||||
int64_t ll_10 = 10;
|
||||
while (p < descriptor.length()) {
|
||||
c = descriptor.charAt(p);
|
||||
if (c >= gZero && c <= gNine) {
|
||||
|
@ -284,9 +286,9 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
|
|||
// in tempValue, skip punctuation, stop on a > mark, and
|
||||
// throw an exception on anything else
|
||||
if (c == gSlash) {
|
||||
val = (int32_t)0;
|
||||
val = 0;
|
||||
++p;
|
||||
llong ll_10 = (int32_t)10;
|
||||
int64_t ll_10 = 10;
|
||||
while (p < descriptor.length()) {
|
||||
c = descriptor.charAt(p);
|
||||
if (c >= gZero && c <= gNine) {
|
||||
|
@ -307,7 +309,7 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
|
|||
|
||||
// tempValue now contain's the rule's radix. Set it
|
||||
// accordingly, and recalculate the rule's exponent
|
||||
radix = (int16_t)val.asInt();
|
||||
radix = (int16_t)val;
|
||||
if (radix == 0) {
|
||||
// throw new IllegalArgumentException("Rule can't have radix of 0");
|
||||
status = U_PARSE_ERROR;
|
||||
|
@ -442,7 +444,7 @@ NFRule::extractSubstitution(const NFRuleSet* ruleSet,
|
|||
* @param The new base value for the rule.
|
||||
*/
|
||||
void
|
||||
NFRule::setBaseValue(llong newBaseValue)
|
||||
NFRule::setBaseValue(int64_t newBaseValue)
|
||||
{
|
||||
// set the base value
|
||||
baseValue = newBaseValue;
|
||||
|
@ -493,8 +495,8 @@ NFRule::expectedExponent() const
|
|||
// we get rounding error in some cases-- for example, log 1000 / log 10
|
||||
// gives us 1.9999999996 instead of 2. The extra logic here is to take
|
||||
// that into account
|
||||
int16_t tempResult = (int16_t)(uprv_log(baseValue.asDouble()) / uprv_log((double)radix));
|
||||
llong temp = ((llong)radix).pow(tempResult + 1);
|
||||
int16_t tempResult = (int16_t)(uprv_log((double)baseValue) / uprv_log((double)radix));
|
||||
int64_t temp = util64_pow(radix, tempResult + 1);
|
||||
if (temp <= baseValue) {
|
||||
tempResult += 1;
|
||||
}
|
||||
|
@ -543,39 +545,16 @@ NFRule::operator==(const NFRule& rhs) const
|
|||
&& *sub2 == *rhs.sub2;
|
||||
}
|
||||
|
||||
/*
|
||||
static void
|
||||
util_append_llong(UnicodeString& result, const llong& value)
|
||||
{
|
||||
llong n(value);
|
||||
|
||||
if (n < 0) {
|
||||
result.append(gMinus);
|
||||
n = -n;
|
||||
}
|
||||
if (n == 0) {
|
||||
result.append(gZero);
|
||||
} else {
|
||||
llong ll_10((int32_t)10);
|
||||
while (n != 0) {
|
||||
llong nn = n / ll_10;
|
||||
result.append((UChar)(gZero + llong_asInt(n - nn * ll_10)));
|
||||
n = nn;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a textual representation of the rule. This won't
|
||||
* necessarily be the same as the description that this rule
|
||||
* was created with, but it will produce the same result.
|
||||
* @return A textual description of the rule
|
||||
*/
|
||||
static void util_append64(UnicodeString& result, const llong& n)
|
||||
static void util_append64(UnicodeString& result, int64_t n)
|
||||
{
|
||||
UChar buffer[256];
|
||||
int32_t len = n.lltou(buffer, sizeof(buffer));
|
||||
int32_t len = util64_tou(n, buffer, sizeof(buffer));
|
||||
UnicodeString temp(buffer, len);
|
||||
result.append(temp);
|
||||
}
|
||||
|
@ -648,7 +627,7 @@ NFRule::appendRuleText(UnicodeString& result) const
|
|||
* should be inserted
|
||||
*/
|
||||
void
|
||||
NFRule::doFormat(const llong &number, UnicodeString& toInsertInto, int32_t pos) const
|
||||
NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos) const
|
||||
{
|
||||
// first, insert the rule's rule text into toInsertInto at the
|
||||
// specified position, then insert the results of the substitutions
|
||||
|
@ -711,8 +690,8 @@ NFRule::shouldRollBack(double number) const
|
|||
// of 100, and the value we're trying to format _is_ an even
|
||||
// multiple of 100. This is called the "rollback rule."
|
||||
if ((sub1->isModulusSubstitution()) || (sub2->isModulusSubstitution())) {
|
||||
llong re = ((llong)radix).pow(exponent);
|
||||
return uprv_fmod(number, re.asDouble()) == 0 && (baseValue % re) != 0;
|
||||
int64_t re = util64_pow(radix, exponent);
|
||||
return uprv_fmod(number, (double)re) == 0 && (baseValue % re) != 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -831,7 +810,7 @@ NFRule::doParse(const UnicodeString& text,
|
|||
int highWaterMark = 0;
|
||||
double result = 0;
|
||||
int start = 0;
|
||||
double tempBaseValue = (baseValue <= 0) ? 0 : baseValue.asDouble();
|
||||
double tempBaseValue = (double)(baseValue <= 0 ? 0 : baseValue);
|
||||
|
||||
UnicodeString temp;
|
||||
do {
|
||||
|
@ -1423,4 +1402,7 @@ NFRule::allIgnorable(const UnicodeString& str) const
|
|||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
#ifndef NFRULE_H
|
||||
#define NFRULE_H
|
||||
|
||||
#include "unicode/rbnf.h"
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/unistr.h"
|
||||
|
||||
#include "llong.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class FieldPosition;
|
||||
|
@ -48,15 +50,15 @@ public:
|
|||
UBool operator==(const NFRule& rhs) const;
|
||||
UBool operator!=(const NFRule& rhs) const { return !operator==(rhs); }
|
||||
|
||||
ERuleType getType() const { return (ERuleType)(baseValue <= 0 ? baseValue.asInt() : kOtherRule); }
|
||||
ERuleType getType() const { return (ERuleType)(baseValue <= 0 ? baseValue : kOtherRule); }
|
||||
void setType(ERuleType ruleType) { baseValue = (int32_t)ruleType; }
|
||||
|
||||
llong getBaseValue() const { return baseValue; }
|
||||
void setBaseValue(llong value);
|
||||
int64_t getBaseValue() const { return baseValue; }
|
||||
void setBaseValue(int64_t value);
|
||||
|
||||
double getDivisor() const { return uprv_pow(radix, exponent); }
|
||||
|
||||
void doFormat(const llong &number, UnicodeString& toAppendTo, int32_t pos) const;
|
||||
void doFormat(int64_t number, UnicodeString& toAppendTo, int32_t pos) const;
|
||||
void doFormat(double number, UnicodeString& toAppendTo, int32_t pos) const;
|
||||
|
||||
UBool doParse(const UnicodeString& text,
|
||||
|
@ -87,7 +89,7 @@ private:
|
|||
int32_t startingAt, int32_t* resultCount) const;
|
||||
|
||||
private:
|
||||
llong baseValue;
|
||||
int64_t baseValue;
|
||||
int16_t radix;
|
||||
int16_t exponent;
|
||||
UnicodeString ruleText;
|
||||
|
@ -98,5 +100,9 @@ private:
|
|||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
||||
// NFRULE_H
|
||||
#endif
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "nfsubs.h"
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
static const UChar gLessThan = 0x003c;
|
||||
static const UChar gEquals = 0x003d;
|
||||
static const UChar gGreaterThan = 0x003e;
|
||||
|
@ -45,84 +47,84 @@ NFSubstitution::makeSubstitution(int32_t pos,
|
|||
const UnicodeString& description,
|
||||
UErrorCode& status)
|
||||
{
|
||||
// if the description is empty, return a NullSubstitution
|
||||
if (description.length() == 0) {
|
||||
return new NullSubstitution(pos, ruleSet, formatter, description, status);
|
||||
// if the description is empty, return a NullSubstitution
|
||||
if (description.length() == 0) {
|
||||
return new NullSubstitution(pos, ruleSet, formatter, description, status);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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, formatter, 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, rule->getBaseValue().asDouble(),
|
||||
formatter->getDefaultRuleSet(), formatter, description, status);
|
||||
}
|
||||
|
||||
// otherwise, return a MultiplierSubstitution
|
||||
else {
|
||||
return new MultiplierSubstitution(pos, rule->getDivisor(), ruleSet,
|
||||
formatter, 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, formatter, 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, formatter, 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, formatter, description, status);
|
||||
}
|
||||
|
||||
// if the description begins with '=', always return a
|
||||
// SameValueSubstitution
|
||||
case gEquals:
|
||||
return new SameValueSubstitution(pos, ruleSet, formatter, description, status);
|
||||
|
||||
// and if it's anything else, throw an exception
|
||||
default:
|
||||
// throw new IllegalArgumentException("Illegal substitution character");
|
||||
status = U_PARSE_ERROR;
|
||||
// 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, formatter, description, status);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
// 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(), formatter, description, status);
|
||||
}
|
||||
|
||||
// otherwise, return a MultiplierSubstitution
|
||||
else {
|
||||
return new MultiplierSubstitution(pos, rule->getDivisor(), ruleSet,
|
||||
formatter, 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, formatter, 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, formatter, 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, formatter, description, status);
|
||||
}
|
||||
|
||||
// if the description begins with '=', always return a
|
||||
// SameValueSubstitution
|
||||
case gEquals:
|
||||
return new SameValueSubstitution(pos, ruleSet, formatter, 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,
|
||||
|
@ -130,66 +132,66 @@ NFSubstitution::NFSubstitution(int32_t _pos,
|
|||
const RuleBasedNumberFormat* formatter,
|
||||
const UnicodeString& description,
|
||||
UErrorCode& status)
|
||||
: pos(_pos), ruleSet(NULL), numberFormat(NULL)
|
||||
: 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;
|
||||
}
|
||||
// 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 the description was just two paired token characters
|
||||
// (i.e., "<<" or ">>"), it uses the rule set it belongs to to
|
||||
// format its result
|
||||
if (workingDescription.length() == 0) {
|
||||
this->ruleSet = _ruleSet;
|
||||
}
|
||||
// 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
|
||||
else if (workingDescription.charAt(0) == gPercent) {
|
||||
this->ruleSet = formatter->findRuleSet(workingDescription, status);
|
||||
}
|
||||
// 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)
|
||||
else if (workingDescription.charAt(0) == gPound || workingDescription.charAt(0) ==gZero) {
|
||||
this->numberFormat = new DecimalFormat(workingDescription, *(formatter->getDecimalFormatSymbols()), status);
|
||||
// this->numberFormat->setDecimalFormatSymbols(formatter->getDecimalFormatSymbols());
|
||||
}
|
||||
// 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)
|
||||
else if (workingDescription.charAt(0) == gGreaterThan) {
|
||||
// this causes problems when >>> is used in a frationalPartSubstitution
|
||||
// this->ruleSet = NULL;
|
||||
this->ruleSet = _ruleSet;
|
||||
this->numberFormat = NULL;
|
||||
}
|
||||
// and of the description is none of these things, it's a syntax error
|
||||
else {
|
||||
// throw new IllegalArgumentException("Illegal substitution syntax");
|
||||
status = U_PARSE_ERROR;
|
||||
}
|
||||
// if the description was just two paired token characters
|
||||
// (i.e., "<<" or ">>"), it uses the rule set it belongs to to
|
||||
// format its result
|
||||
if (workingDescription.length() == 0) {
|
||||
this->ruleSet = _ruleSet;
|
||||
}
|
||||
// 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
|
||||
else if (workingDescription.charAt(0) == gPercent) {
|
||||
this->ruleSet = formatter->findRuleSet(workingDescription, status);
|
||||
}
|
||||
// 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)
|
||||
else if (workingDescription.charAt(0) == gPound || workingDescription.charAt(0) ==gZero) {
|
||||
this->numberFormat = new DecimalFormat(workingDescription, *(formatter->getDecimalFormatSymbols()), status);
|
||||
// this->numberFormat->setDecimalFormatSymbols(formatter->getDecimalFormatSymbols());
|
||||
}
|
||||
// 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)
|
||||
else if (workingDescription.charAt(0) == gGreaterThan) {
|
||||
// this causes problems when >>> is used in a frationalPartSubstitution
|
||||
// this->ruleSet = NULL;
|
||||
this->ruleSet = _ruleSet;
|
||||
this->numberFormat = NULL;
|
||||
}
|
||||
// and of the description is none of these things, it's a syntax error
|
||||
else {
|
||||
// throw new IllegalArgumentException("Illegal substitution syntax");
|
||||
status = U_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
NFSubstitution::~NFSubstitution()
|
||||
{
|
||||
// cast away const
|
||||
delete (NumberFormat*)numberFormat; numberFormat = NULL;
|
||||
// cast away const
|
||||
delete (NumberFormat*)numberFormat; numberFormat = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,7 +203,7 @@ NFSubstitution::~NFSubstitution()
|
|||
*/
|
||||
void
|
||||
NFSubstitution::setDivisor(int32_t /*radix*/, int32_t /*exponent*/) {
|
||||
// a no-op for all substitutions except multiplier and modulus substitutions
|
||||
// a no-op for all substitutions except multiplier and modulus substitutions
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,11 +215,9 @@ const char NFSubstitution::fgClassID = 0;
|
|||
|
||||
UClassID
|
||||
NFSubstitution::getDynamicClassID() const {
|
||||
return getStaticClassID();
|
||||
return getStaticClassID();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compares two substitutions for equality
|
||||
* @param The substitution to compare this one to
|
||||
|
@ -226,16 +226,16 @@ NFSubstitution::getDynamicClassID() const {
|
|||
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()
|
||||
&& 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));
|
||||
// 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()
|
||||
&& 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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,21 +247,21 @@ NFSubstitution::operator==(const NFSubstitution& rhs) const
|
|||
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());
|
||||
// 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 {
|
||||
numberFormat->toPattern(temp);
|
||||
}
|
||||
text.append(temp);
|
||||
text.append(tokenChar());
|
||||
UnicodeString temp;
|
||||
if (ruleSet != NULL) {
|
||||
ruleSet->getName(temp);
|
||||
} else {
|
||||
numberFormat->toPattern(temp);
|
||||
}
|
||||
text.append(temp);
|
||||
text.append(tokenChar());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -279,27 +279,27 @@ NFSubstitution::toString(UnicodeString& text) const
|
|||
* position to determine exactly where to insert the new text)
|
||||
*/
|
||||
void
|
||||
NFSubstitution::doSubstitution(const llong &number, UnicodeString& toInsertInto, int32_t _pos) const
|
||||
NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos) 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);
|
||||
} else {
|
||||
// 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(number.asDouble());
|
||||
if (numberFormat->getMaximumFractionDigits() == 0) {
|
||||
numberToFormat = uprv_floor(numberToFormat);
|
||||
}
|
||||
|
||||
UnicodeString temp;
|
||||
numberFormat->format(numberToFormat, temp);
|
||||
toInsertInto.insert(_pos + this->pos, temp);
|
||||
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);
|
||||
} else {
|
||||
// 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);
|
||||
toInsertInto.insert(_pos + this->pos, temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -314,27 +314,27 @@ NFSubstitution::doSubstitution(const llong &number, UnicodeString& toInsertInto,
|
|||
*/
|
||||
void
|
||||
NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos) const {
|
||||
// perform a transformation on the number being formatted that
|
||||
// is dependent on the type of substitution this is
|
||||
double numberToFormat = transformNumber(number);
|
||||
// perform a transformation on the number being formatted that
|
||||
// is dependent on the type of substitution this is
|
||||
double numberToFormat = transformNumber(number);
|
||||
|
||||
// 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(llong(numberToFormat), toInsertInto, _pos + this->pos);
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
} else {
|
||||
if (ruleSet != NULL) {
|
||||
ruleSet->format(numberToFormat, toInsertInto, _pos + this->pos);
|
||||
} else {
|
||||
UnicodeString temp;
|
||||
numberFormat->format(numberToFormat, temp);
|
||||
toInsertInto.insert(_pos + this->pos, temp);
|
||||
}
|
||||
UnicodeString temp;
|
||||
numberFormat->format(numberToFormat, temp);
|
||||
toInsertInto.insert(_pos + this->pos, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -384,80 +384,79 @@ NFSubstitution::doParse(const UnicodeString& text,
|
|||
Formattable& result) const
|
||||
{
|
||||
#ifdef RBNF_DEBUG
|
||||
fprintf(stderr, "<nfsubs> %x bv: %g ub: %g\n", this, baseValue, upperBound);
|
||||
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);
|
||||
// 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 {
|
||||
numberFormat->parse(text, result, parsePosition);
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
double tempResult = (result.getType() == Formattable::kLong) ?
|
||||
(double)result.getLong() :
|
||||
result.getDouble();
|
||||
// ...or use our DecimalFormat to parse the text
|
||||
} else {
|
||||
numberFormat->parse(text, result, parsePosition);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
// 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) {
|
||||
double tempResult = (result.getType() == Formattable::kLong) ?
|
||||
(double)result.getLong() :
|
||||
result.getDouble();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UBool
|
||||
NFSubstitution::isNullSubstitution() const {
|
||||
return FALSE;
|
||||
|
@ -541,20 +540,20 @@ ModulusSubstitution::ModulusSubstitution(int32_t _pos,
|
|||
, divisor(_divisor)
|
||||
, ruleToUse(NULL)
|
||||
{
|
||||
ldivisor = _divisor;
|
||||
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
|
||||
// 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 (description == gGreaterGreaterGreaterThan) {
|
||||
// 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;
|
||||
}
|
||||
if (description == gGreaterGreaterGreaterThan) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
const char ModulusSubstitution::fgClassID = 0;
|
||||
|
@ -566,15 +565,16 @@ ModulusSubstitution::getDynamicClassID() const {
|
|||
|
||||
UBool ModulusSubstitution::operator==(const NFSubstitution& rhs) const
|
||||
{
|
||||
return NFSubstitution::operator==(rhs) &&
|
||||
divisor == ((const ModulusSubstitution*)&rhs)->divisor &&
|
||||
ruleToUse == ((const ModulusSubstitution*)&rhs)->ruleToUse;
|
||||
return NFSubstitution::operator==(rhs) &&
|
||||
divisor == ((const ModulusSubstitution*)&rhs)->divisor &&
|
||||
ruleToUse == ((const ModulusSubstitution*)&rhs)->ruleToUse;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// formatting
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* If this is a >>> substitution, use ruleToUse to fill in
|
||||
* the substitution. Otherwise, just use the superclass function.
|
||||
|
@ -584,20 +584,20 @@ UBool ModulusSubstitution::operator==(const NFSubstitution& rhs) const
|
|||
* @param pos The position of the rule text in toInsertInto
|
||||
*/
|
||||
void
|
||||
ModulusSubstitution::doSubstitution(const llong & number, UnicodeString& toInsertInto, int32_t _pos) const
|
||||
ModulusSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos) 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);
|
||||
// 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);
|
||||
|
||||
// a >>> substitution goes straight to a particular rule to
|
||||
// format the substitution value
|
||||
} else {
|
||||
llong numberToFormat = transformNumber(number);
|
||||
ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos());
|
||||
}
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -611,22 +611,21 @@ ModulusSubstitution::doSubstitution(const llong & number, UnicodeString& toIns
|
|||
void
|
||||
ModulusSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos) 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);
|
||||
// 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);
|
||||
|
||||
// a >>> substitution goes straight to a particular rule to
|
||||
// format the substitution value
|
||||
} else {
|
||||
double numberToFormat = transformNumber(number);
|
||||
// a >>> substitution goes straight to a particular rule to
|
||||
// format the substitution value
|
||||
} else {
|
||||
double numberToFormat = transformNumber(number);
|
||||
|
||||
ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos());
|
||||
}
|
||||
ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// parsing
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -648,25 +647,25 @@ ModulusSubstitution::doParse(const UnicodeString& text,
|
|||
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);
|
||||
// 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);
|
||||
// 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) {
|
||||
double tempResult = result.getDouble();
|
||||
tempResult = composeRuleValue(tempResult, baseValue);
|
||||
result.setDouble(tempResult);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
if (parsePosition.getIndex() != 0) {
|
||||
double tempResult = result.getDouble();
|
||||
tempResult = composeRuleValue(tempResult, baseValue);
|
||||
result.setDouble(tempResult);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -678,7 +677,7 @@ const char IntegralPartSubstitution::fgClassID = 0;
|
|||
|
||||
UClassID
|
||||
IntegralPartSubstitution::getDynamicClassID() const {
|
||||
return getStaticClassID();
|
||||
return getStaticClassID();
|
||||
}
|
||||
|
||||
|
||||
|
@ -733,35 +732,35 @@ FractionalPartSubstitution::FractionalPartSubstitution(int32_t _pos,
|
|||
void
|
||||
FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos) const
|
||||
{
|
||||
// if we're not in "byDigits" mode, just use the inherited
|
||||
// doSubstitution() routine
|
||||
if (!byDigits) {
|
||||
NFSubstitution::doSubstitution(number, toInsertInto, _pos);
|
||||
// if we're not in "byDigits" mode, just use the inherited
|
||||
// doSubstitution() routine
|
||||
if (!byDigits) {
|
||||
NFSubstitution::doSubstitution(number, toInsertInto, _pos);
|
||||
|
||||
// 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++) {
|
||||
int32_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;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -784,6 +783,7 @@ FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInser
|
|||
* result; otherwise new Long(0). The result is either a Long or
|
||||
* a Double.
|
||||
*/
|
||||
|
||||
UBool
|
||||
FractionalPartSubstitution::doParse(const UnicodeString& text,
|
||||
ParsePosition& parsePosition,
|
||||
|
@ -792,70 +792,70 @@ FractionalPartSubstitution::doParse(const UnicodeString& text,
|
|||
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'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;
|
||||
// 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;
|
||||
|
||||
NumberFormat* fmt = NULL;
|
||||
while (workText.length() > 0 && workPos.getIndex() != 0) {
|
||||
workPos.setIndex(0);
|
||||
Formattable temp;
|
||||
getRuleSet()->parse(workText, workPos, 10, temp);
|
||||
digit = temp.getType() == Formattable::kLong ?
|
||||
temp.getLong() :
|
||||
(int32_t)temp.getDouble();
|
||||
NumberFormat* fmt = NULL;
|
||||
while (workText.length() > 0 && workPos.getIndex() != 0) {
|
||||
workPos.setIndex(0);
|
||||
Formattable temp;
|
||||
getRuleSet()->parse(workText, workPos, 10, temp);
|
||||
digit = temp.getType() == Formattable::kLong ?
|
||||
temp.getLong() :
|
||||
(int32_t)temp.getDouble();
|
||||
|
||||
if (lenientParse && workPos.getIndex() == 0) {
|
||||
if (!fmt) {
|
||||
UErrorCode 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();
|
||||
}
|
||||
}
|
||||
if (lenientParse && workPos.getIndex() == 0) {
|
||||
if (!fmt) {
|
||||
UErrorCode 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();
|
||||
}
|
||||
}
|
||||
|
||||
if (workPos.getIndex() != 0) {
|
||||
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 = composeRuleValue(result, baseValue);
|
||||
resVal.setDouble(result);
|
||||
return TRUE;
|
||||
if (workPos.getIndex() != 0) {
|
||||
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 = composeRuleValue(result, baseValue);
|
||||
resVal.setDouble(result);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
UBool
|
||||
FractionalPartSubstitution::operator==(const NFSubstitution& rhs) const
|
||||
{
|
||||
return NFSubstitution::operator==(rhs) &&
|
||||
((const FractionalPartSubstitution*)&rhs)->byDigits == byDigits;
|
||||
return NFSubstitution::operator==(rhs) &&
|
||||
((const FractionalPartSubstitution*)&rhs)->byDigits == byDigits;
|
||||
}
|
||||
|
||||
const char FractionalPartSubstitution::fgClassID = 0;
|
||||
|
@ -906,3 +906,6 @@ NullSubstitution::getDynamicClassID() const {
|
|||
return getStaticClassID();
|
||||
}
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
#ifndef NFSUBS_H
|
||||
#define NFSUBS_H
|
||||
|
||||
#include "nfrule.h"
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "nfrs.h"
|
||||
#include "nfrule.h"
|
||||
#include "llong.h"
|
||||
#include <float.h>
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
@ -82,7 +83,7 @@ public:
|
|||
* rule text begins (this value is added to this substitution's
|
||||
* position to determine exactly where to insert the new text)
|
||||
*/
|
||||
virtual void doSubstitution(const llong &number, UnicodeString& toInsertInto, int32_t pos) 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:
|
||||
|
@ -95,7 +96,7 @@ protected:
|
|||
* @param The number being formatted
|
||||
* @return The result of performing the opreration on the number
|
||||
*/
|
||||
virtual llong transformNumber(const llong &number) const = 0;
|
||||
virtual int64_t transformNumber(int64_t number) const = 0;
|
||||
virtual double transformNumber(double number) const = 0;
|
||||
|
||||
public:
|
||||
|
@ -211,7 +212,7 @@ public:
|
|||
const UnicodeString& description,
|
||||
UErrorCode& status);
|
||||
|
||||
llong transformNumber(const llong &number) const { return number; }
|
||||
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; }
|
||||
|
@ -226,7 +227,7 @@ public:
|
|||
|
||||
class MultiplierSubstitution : public NFSubstitution {
|
||||
double divisor;
|
||||
llong ldivisor;
|
||||
int64_t ldivisor;
|
||||
|
||||
public:
|
||||
MultiplierSubstitution(int32_t _pos,
|
||||
|
@ -237,17 +238,17 @@ public:
|
|||
UErrorCode& status)
|
||||
: NFSubstitution(_pos, _ruleSet, formatter, description, status), divisor(_divisor)
|
||||
{
|
||||
ldivisor = _divisor;
|
||||
ldivisor = util64_fromDouble(divisor);
|
||||
}
|
||||
|
||||
void setDivisor(int32_t radix, int32_t exponent) {
|
||||
divisor = uprv_pow(radix, exponent);
|
||||
ldivisor = divisor;
|
||||
ldivisor = util64_fromDouble(divisor);
|
||||
}
|
||||
|
||||
UBool operator==(const NFSubstitution& rhs) const;
|
||||
|
||||
llong transformNumber(const llong &number) const {
|
||||
int64_t transformNumber(int64_t number) const {
|
||||
return number / ldivisor;
|
||||
}
|
||||
|
||||
|
@ -272,7 +273,7 @@ public:
|
|||
|
||||
class ModulusSubstitution : public NFSubstitution {
|
||||
double divisor;
|
||||
llong ldivisor;
|
||||
int64_t ldivisor;
|
||||
const NFRule* ruleToUse;
|
||||
public:
|
||||
ModulusSubstitution(int32_t pos,
|
||||
|
@ -285,15 +286,15 @@ public:
|
|||
|
||||
void setDivisor(int32_t radix, int32_t exponent) {
|
||||
divisor = uprv_pow(radix, exponent);
|
||||
ldivisor = divisor;
|
||||
ldivisor = util64_fromDouble(divisor);
|
||||
}
|
||||
|
||||
UBool operator==(const NFSubstitution& rhs) const;
|
||||
|
||||
void doSubstitution(const llong &number, UnicodeString& toInsertInto, int32_t pos) const;
|
||||
void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos) const;
|
||||
void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const;
|
||||
|
||||
llong transformNumber(const llong &number) const { return number % ldivisor; }
|
||||
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,
|
||||
|
@ -329,7 +330,7 @@ public:
|
|||
UErrorCode& status)
|
||||
: NFSubstitution(_pos, _ruleSet, formatter, description, status) {}
|
||||
|
||||
llong transformNumber(const llong &number) const { return number; }
|
||||
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; }
|
||||
|
@ -356,8 +357,8 @@ public:
|
|||
UBool operator==(const NFSubstitution& rhs) const;
|
||||
|
||||
void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos) const;
|
||||
void doSubstitution(const llong &/*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) const {}
|
||||
llong transformNumber(const llong &/*number*/) const { return llong(0,0); }
|
||||
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,
|
||||
|
@ -387,7 +388,7 @@ public:
|
|||
UErrorCode& status)
|
||||
: NFSubstitution(_pos, _ruleSet, formatter, description, status) {}
|
||||
|
||||
llong transformNumber(const llong &number) const { return number.abs(); }
|
||||
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; }
|
||||
|
@ -402,7 +403,7 @@ public:
|
|||
|
||||
class NumeratorSubstitution : public NFSubstitution {
|
||||
double denominator;
|
||||
llong ldenominator;
|
||||
int64_t ldenominator;
|
||||
public:
|
||||
NumeratorSubstitution(int32_t _pos,
|
||||
double _denominator,
|
||||
|
@ -412,12 +413,12 @@ public:
|
|||
UErrorCode& status)
|
||||
: NFSubstitution(_pos, _ruleSet, formatter, description, status), denominator(_denominator)
|
||||
{
|
||||
ldenominator = _denominator;
|
||||
ldenominator = util64_fromDouble(denominator);
|
||||
}
|
||||
|
||||
UBool operator==(const NFSubstitution& rhs) const;
|
||||
|
||||
llong transformNumber(const llong &number) const { return number * ldenominator; }
|
||||
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,
|
||||
|
@ -454,8 +455,8 @@ public:
|
|||
|
||||
void toString(UnicodeString& /*result*/) const {}
|
||||
void doSubstitution(double /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) const {}
|
||||
void doSubstitution(const llong &/*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/) const {}
|
||||
llong transformNumber(const llong &/*number*/) const { return llong(0,0); }
|
||||
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*/,
|
||||
|
@ -478,5 +479,8 @@ public:
|
|||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
||||
// NFSUBS_H
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "unicode/rbnf.h"
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
#include "nfrs.h"
|
||||
|
||||
#include "cmemory.h"
|
||||
|
@ -219,20 +221,20 @@ RuleBasedNumberFormat::format(int32_t number,
|
|||
UnicodeString& toAppendTo,
|
||||
FieldPosition& pos) const
|
||||
{
|
||||
defaultRuleSet->format(llong(number), toAppendTo, toAppendTo.length());
|
||||
defaultRuleSet->format((int64_t)number, toAppendTo, toAppendTo.length());
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(llong number,
|
||||
RuleBasedNumberFormat::format(int64_t number,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& pos) const
|
||||
{
|
||||
defaultRuleSet->format(number, toAppendTo, toAppendTo.length());
|
||||
return toAppendTo;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(double number,
|
||||
|
@ -251,7 +253,7 @@ RuleBasedNumberFormat::format(int32_t number,
|
|||
FieldPosition& pos,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
// return format(llong(number), ruleSetName, toAppendTo, pos, status);
|
||||
// return format((int64_t)number, ruleSetName, toAppendTo, pos, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
if (ruleSetName.indexOf(gPercentPercent) == 0) {
|
||||
// throw new IllegalArgumentException("Can't use internal rule set");
|
||||
|
@ -259,16 +261,16 @@ RuleBasedNumberFormat::format(int32_t number,
|
|||
} else {
|
||||
NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
||||
if (rs) {
|
||||
rs->format(llong(number), toAppendTo, toAppendTo.length());
|
||||
rs->format((int64_t)number, toAppendTo, toAppendTo.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
UnicodeString&
|
||||
RuleBasedNumberFormat::format(llong number,
|
||||
RuleBasedNumberFormat::format(int64_t number,
|
||||
const UnicodeString& ruleSetName,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& pos,
|
||||
|
@ -287,7 +289,7 @@ RuleBasedNumberFormat::format(llong number,
|
|||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// make linker happy
|
||||
UnicodeString&
|
||||
|
@ -630,3 +632,5 @@ RuleBasedNumberFormat::getDecimalFormatSymbols() const
|
|||
return decimalFormatSymbols;
|
||||
}
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
#ifndef RBNF_H
|
||||
#define RBNF_H
|
||||
|
||||
#if 0 //U_INT64_T_UNAVAILABLE -- fix once George defines this
|
||||
#define U_HAVE_RBNF 0
|
||||
#else
|
||||
#define U_HAVE_RBNF 1
|
||||
|
||||
#include "unicode/coll.h"
|
||||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/fmtable.h"
|
||||
|
@ -583,7 +588,7 @@ public:
|
|||
virtual int32_t getNumberOfRuleSetNames() const;
|
||||
|
||||
/**
|
||||
* Formats the specified number using the default ruleset.
|
||||
* Formats the specified 32-bit number using the default ruleset.
|
||||
* @param number The number to format.
|
||||
* @param toAppendTo the string that will hold the (appended) result
|
||||
* @param pos the fieldposition
|
||||
|
@ -593,6 +598,18 @@ public:
|
|||
virtual UnicodeString& format(int32_t number,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& pos) const;
|
||||
|
||||
/**
|
||||
* Formats the specified 64-bit number using the default ruleset.
|
||||
* @param number The number to format.
|
||||
* @param toAppendTo the string that will hold the (appended) result
|
||||
* @param pos the fieldposition
|
||||
* @return A textual representation of the number.
|
||||
* @draft ICU 2.1
|
||||
*/
|
||||
virtual UnicodeString& format(int64_t number,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& pos) const;
|
||||
/**
|
||||
* Formats the specified number using the default ruleset.
|
||||
* @param number The number to format.
|
||||
|
@ -621,6 +638,22 @@ public:
|
|||
UnicodeString& toAppendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode& status) const;
|
||||
/**
|
||||
* Formats the specified 64-bit number using the default ruleset.
|
||||
* @param number The number to format.
|
||||
* @param ruleSetName The name of the rule set to format the number with.
|
||||
* This must be the name of a valid public rule set for this formatter.
|
||||
* @param toAppendTo the string that will hold the (appended) result
|
||||
* @param pos the fieldposition
|
||||
* @param status the status
|
||||
* @return A textual representation of the number.
|
||||
* @draft ICU 2.1
|
||||
*/
|
||||
virtual UnicodeString& format(int64_t number,
|
||||
const UnicodeString& ruleSetName,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode& status) const;
|
||||
/**
|
||||
* Formats the specified number using the default ruleset.
|
||||
* @param number The number to format.
|
||||
|
@ -824,5 +857,8 @@ RuleBasedNumberFormat::getDefaultRuleSet() const {
|
|||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
||||
/* RBNF_H */
|
||||
#endif
|
||||
|
|
|
@ -137,8 +137,11 @@ unum_open( UNumberFormatStyle style,
|
|||
break;
|
||||
|
||||
case UNUM_SPELLOUT:
|
||||
#if U_HAVE_RBNF
|
||||
return (UNumberFormat*)new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
|
||||
|
||||
#else
|
||||
// fall through
|
||||
#endif
|
||||
default:
|
||||
*status = U_UNSUPPORTED_ERROR;
|
||||
return 0;
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
*/
|
||||
#include "itrbnf.h"
|
||||
|
||||
#include "unicode/umachine.h"
|
||||
|
||||
#include "unicode/tblcoll.h"
|
||||
#include "unicode/coleitr.h"
|
||||
#include "unicode/ures.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "llong.h"
|
||||
//#include "llong.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -35,6 +37,7 @@ void IntlTestRBNF::runIndexedTest(int32_t index, UBool exec, const char* &name,
|
|||
{
|
||||
if (exec) logln("TestSuite RuleBasedNumberFormat");
|
||||
switch (index) {
|
||||
#if U_HAVE_RBNF
|
||||
TESTCASE(0, TestEnglishSpellout);
|
||||
TESTCASE(1, TestOrdinalAbbreviations);
|
||||
TESTCASE(2, TestDurations);
|
||||
|
@ -46,13 +49,18 @@ void IntlTestRBNF::runIndexedTest(int32_t index, UBool exec, const char* &name,
|
|||
TESTCASE(8, TestThaiSpellout);
|
||||
TESTCASE(9, TestAPI);
|
||||
TESTCASE(10, TestFractionalRuleSet);
|
||||
TESTCASE(11, TestLLong);
|
||||
// TESTCASE(11, TestLLong);
|
||||
#else
|
||||
TESTCASE(0, TestRBNFDisabled);
|
||||
#endif
|
||||
default:
|
||||
name = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
void
|
||||
IntlTestRBNF::TestAPI() {
|
||||
// This test goes through the APIs that were not tested before.
|
||||
|
@ -265,6 +273,7 @@ void IntlTestRBNF::TestFractionalRuleSet()
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define LLAssert(a) \
|
||||
if (!(a)) errln("FAIL: " #a)
|
||||
|
||||
|
@ -890,6 +899,9 @@ void IntlTestRBNF::TestLLong()
|
|||
}
|
||||
}
|
||||
|
||||
/* if 0 */
|
||||
#endif
|
||||
|
||||
void
|
||||
IntlTestRBNF::TestEnglishSpellout()
|
||||
{
|
||||
|
@ -1389,3 +1401,13 @@ IntlTestRBNF::doLenientParseTest(RuleBasedNumberFormat* formatter, const char* t
|
|||
}
|
||||
}
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#else
|
||||
|
||||
void
|
||||
IntlTestRBNF::TestRBNFDisabled() {
|
||||
logln("*** RBNF currently disabled on this platform ***");
|
||||
}
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@ class IntlTestRBNF : public IntlTest {
|
|||
// IntlTest override
|
||||
virtual void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par);
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
/**
|
||||
* Perform an API test
|
||||
*/
|
||||
|
@ -30,12 +31,14 @@ class IntlTestRBNF : public IntlTest {
|
|||
*/
|
||||
virtual void TestFractionalRuleSet();
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Perform API tests on llong
|
||||
*/
|
||||
virtual void TestLLong();
|
||||
virtual void TestLLongConstructors();
|
||||
virtual void TestLLongSimpleOperators();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Perform a simple spot check on the English spellout rules
|
||||
|
@ -85,6 +88,14 @@ class IntlTestRBNF : public IntlTest {
|
|||
protected:
|
||||
virtual void doTest(RuleBasedNumberFormat* formatter, const char* testData[][2], UBool testParsing);
|
||||
virtual void doLenientParseTest(RuleBasedNumberFormat* formatter, const char* testData[][2]);
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#else
|
||||
|
||||
virtual void TestRBNFDisabled();
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
};
|
||||
|
||||
// endif ITRBNF_H
|
||||
|
|
|
@ -25,6 +25,7 @@ void RbnfRoundTripTest::runIndexedTest(int32_t index, UBool exec, const char* &n
|
|||
{
|
||||
if (exec) logln("TestSuite RuleBasedNumberFormatRT");
|
||||
switch (index) {
|
||||
#if U_HAVE_RBNF
|
||||
TESTCASE(0, TestEnglishSpelloutRT);
|
||||
TESTCASE(1, TestDurationsRT);
|
||||
TESTCASE(2, TestSpanishSpelloutRT);
|
||||
|
@ -37,12 +38,17 @@ void RbnfRoundTripTest::runIndexedTest(int32_t index, UBool exec, const char* &n
|
|||
TESTCASE(9, TestJapaneseSpelloutRT);
|
||||
TESTCASE(10, TestRussianSpelloutRT);
|
||||
TESTCASE(11, TestGreekSpelloutRT);
|
||||
#else
|
||||
TESTCASE(0, TestRBNFDisabled);
|
||||
#endif
|
||||
default:
|
||||
name = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
|
||||
/**
|
||||
* Perform an exhaustive round-trip test on the English spellout rules
|
||||
*/
|
||||
|
@ -339,3 +345,13 @@ RbnfRoundTripTest::doTest(const RuleBasedNumberFormat* formatter,
|
|||
}
|
||||
}
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#else
|
||||
|
||||
void
|
||||
RbnfRoundTripTest::TestRBNFDisabled() {
|
||||
logln("*** RBNF currently disabled on this platform ***");
|
||||
}
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@ class RbnfRoundTripTest : public IntlTest {
|
|||
// IntlTest override
|
||||
virtual void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par);
|
||||
|
||||
#if U_HAVE_RBNF
|
||||
/**
|
||||
* Perform an exhaustive round-trip test on the English spellout rules
|
||||
*/
|
||||
|
@ -80,6 +81,14 @@ class RbnfRoundTripTest : public IntlTest {
|
|||
|
||||
protected:
|
||||
void doTest(const RuleBasedNumberFormat* formatter, double lowLimit, double highLimit);
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#else
|
||||
|
||||
void TestRBNFDisabled();
|
||||
|
||||
/* U_HAVE_RBNF */
|
||||
#endif
|
||||
};
|
||||
|
||||
// endif ITRBNFRT_H
|
||||
|
|
Loading…
Add table
Reference in a new issue