mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-13 00:43:32 +00:00
ICU-13177 Adding IFixedDecimal interface to C++.
X-SVN-Rev: 40391
This commit is contained in:
parent
082cbac7fc
commit
1f1a485c3c
5 changed files with 135 additions and 30 deletions
|
@ -521,7 +521,8 @@ static FixedDecimal &initFixedDecimal(
|
|||
const VisibleDigits &digits, FixedDecimal &result) {
|
||||
result.source = 0.0;
|
||||
result.isNegative = digits.isNegative();
|
||||
result.isNanOrInfinity = digits.isNaNOrInfinity();
|
||||
result._isNaN = digits.isNaN();
|
||||
result._isInfinite = digits.isInfinite();
|
||||
digits.getFixedDecimal(
|
||||
result.source, result.intValue, result.decimalDigits,
|
||||
result.decimalDigitsWithoutTrailingZeros,
|
||||
|
|
|
@ -268,7 +268,7 @@ PluralRules::select(const Formattable& obj, const NumberFormat& fmt, UErrorCode&
|
|||
}
|
||||
|
||||
UnicodeString
|
||||
PluralRules::select(const FixedDecimal &number) const {
|
||||
PluralRules::select(const IFixedDecimal &number) const {
|
||||
if (mRules == NULL) {
|
||||
return UnicodeString(TRUE, PLURAL_DEFAULT_RULE, -1);
|
||||
}
|
||||
|
@ -783,15 +783,15 @@ AndConstraint::~AndConstraint() {
|
|||
|
||||
|
||||
UBool
|
||||
AndConstraint::isFulfilled(const FixedDecimal &number) {
|
||||
AndConstraint::isFulfilled(const IFixedDecimal &number) {
|
||||
UBool result = TRUE;
|
||||
if (digitsType == none) {
|
||||
// An empty AndConstraint, created by a rule with a keyword but no following expression.
|
||||
return TRUE;
|
||||
}
|
||||
double n = number.get(digitsType); // pulls n | i | v | f value for the number.
|
||||
// Will always be positive.
|
||||
// May be non-integer (n option only)
|
||||
double n = number.getPluralOperand(digitsType); // pulls n | i | v | f value for the number.
|
||||
// Will always be positive.
|
||||
// May be non-integer (n option only)
|
||||
do {
|
||||
if (integerOnly && n != uprv_floor(n)) {
|
||||
result = FALSE;
|
||||
|
@ -873,7 +873,7 @@ OrConstraint::add()
|
|||
}
|
||||
|
||||
UBool
|
||||
OrConstraint::isFulfilled(const FixedDecimal &number) {
|
||||
OrConstraint::isFulfilled(const IFixedDecimal &number) {
|
||||
OrConstraint* orRule=this;
|
||||
UBool result=FALSE;
|
||||
|
||||
|
@ -914,8 +914,8 @@ RuleChain::~RuleChain() {
|
|||
|
||||
|
||||
UnicodeString
|
||||
RuleChain::select(const FixedDecimal &number) const {
|
||||
if (!number.isNanOrInfinity) {
|
||||
RuleChain::select(const IFixedDecimal &number) const {
|
||||
if (!number.isNaN() && !number.isInfinite()) {
|
||||
for (const RuleChain *rules = this; rules != NULL; rules = rules->fNext) {
|
||||
if (rules->ruleHeader->isFulfilled(number)) {
|
||||
return rules->fKeyword;
|
||||
|
@ -1411,7 +1411,8 @@ FixedDecimal::FixedDecimal(const VisibleDigits &digits) {
|
|||
decimalDigitsWithoutTrailingZeros,
|
||||
visibleDecimalDigitCount, hasIntegerValue);
|
||||
isNegative = digits.isNegative();
|
||||
isNanOrInfinity = digits.isNaNOrInfinity();
|
||||
_isNaN = digits.isNaN();
|
||||
_isInfinite = digits.isInfinite();
|
||||
}
|
||||
|
||||
FixedDecimal::FixedDecimal(double n, int32_t v, int64_t f) {
|
||||
|
@ -1476,7 +1477,8 @@ FixedDecimal::FixedDecimal(const FixedDecimal &other) {
|
|||
intValue = other.intValue;
|
||||
hasIntegerValue = other.hasIntegerValue;
|
||||
isNegative = other.isNegative;
|
||||
isNanOrInfinity = other.isNanOrInfinity;
|
||||
_isNaN = other._isNaN;
|
||||
_isInfinite = other._isInfinite;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1489,8 +1491,9 @@ void FixedDecimal::init(double n) {
|
|||
void FixedDecimal::init(double n, int32_t v, int64_t f) {
|
||||
isNegative = n < 0.0;
|
||||
source = fabs(n);
|
||||
isNanOrInfinity = uprv_isNaN(source) || uprv_isPositiveInfinity(source);
|
||||
if (isNanOrInfinity) {
|
||||
_isNaN = uprv_isNaN(source);
|
||||
_isInfinite = uprv_isInfinite(source);
|
||||
if (_isNaN || _isInfinite) {
|
||||
v = 0;
|
||||
f = 0;
|
||||
intValue = 0;
|
||||
|
@ -1610,19 +1613,31 @@ void FixedDecimal::adjustForMinFractionDigits(int32_t minFractionDigits) {
|
|||
}
|
||||
|
||||
|
||||
double FixedDecimal::get(tokenType operand) const {
|
||||
double FixedDecimal::getPluralOperand(PluralOperand operand) const {
|
||||
switch(operand) {
|
||||
case tVariableN: return source;
|
||||
case tVariableI: return (double)intValue;
|
||||
case tVariableF: return (double)decimalDigits;
|
||||
case tVariableT: return (double)decimalDigitsWithoutTrailingZeros;
|
||||
case tVariableV: return visibleDecimalDigitCount;
|
||||
case PLURAL_OPERAND_N: return source;
|
||||
case PLURAL_OPERAND_I: return intValue;
|
||||
case PLURAL_OPERAND_F: return decimalDigits;
|
||||
case PLURAL_OPERAND_T: return decimalDigitsWithoutTrailingZeros;
|
||||
case PLURAL_OPERAND_V: return visibleDecimalDigitCount;
|
||||
default:
|
||||
U_ASSERT(FALSE); // unexpected.
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
bool FixedDecimal::isNaN() const {
|
||||
return _isNaN;
|
||||
}
|
||||
|
||||
bool FixedDecimal::isInfinite() const {
|
||||
return _isInfinite;
|
||||
}
|
||||
|
||||
bool FixedDecimal::isNanOrInfinity() const {
|
||||
return _isNaN || _isInfinite;
|
||||
}
|
||||
|
||||
int32_t FixedDecimal::getVisibleFractionDigitCount() const {
|
||||
return visibleDecimalDigitCount;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "unicode/ures.h"
|
||||
#include "uvector.h"
|
||||
#include "hash.h"
|
||||
#include "uassert.h"
|
||||
|
||||
class PluralRulesTest;
|
||||
|
||||
|
@ -177,6 +178,87 @@ private:
|
|||
|
||||
};
|
||||
|
||||
enum PluralOperand {
|
||||
/**
|
||||
* The double value of the entire number.
|
||||
*/
|
||||
PLURAL_OPERAND_N,
|
||||
|
||||
/**
|
||||
* The integer value, with the fraction digits truncated off.
|
||||
*/
|
||||
PLURAL_OPERAND_I,
|
||||
|
||||
/**
|
||||
* All visible fraction digits as an integer, including trailing zeros.
|
||||
*/
|
||||
PLURAL_OPERAND_F,
|
||||
|
||||
/**
|
||||
* Visible fraction digits as an integer, not including trailing zeros.
|
||||
*/
|
||||
PLURAL_OPERAND_T,
|
||||
|
||||
/**
|
||||
* Number of visible fraction digits.
|
||||
*/
|
||||
PLURAL_OPERAND_V,
|
||||
|
||||
/**
|
||||
* Number of visible fraction digits, not including trailing zeros.
|
||||
*/
|
||||
PLURAL_OPERAND_W,
|
||||
|
||||
/**
|
||||
* THIS OPERAND IS DEPRECATED AND HAS BEEN REMOVED FROM THE SPEC.
|
||||
*
|
||||
* <p>Returns the integer value, but will fail if the number has fraction digits.
|
||||
* That is, using "j" instead of "i" is like implicitly adding "v is 0".
|
||||
*
|
||||
* <p>For example, "j is 3" is equivalent to "i is 3 and v is 0": it matches
|
||||
* "3" but not "3.1" or "3.0".
|
||||
*/
|
||||
PLURAL_OPERAND_J
|
||||
};
|
||||
|
||||
/**
|
||||
* An interface to FixedDecimal, allowing for other implementations.
|
||||
* @internal
|
||||
*/
|
||||
class IFixedDecimal {
|
||||
public:
|
||||
virtual ~IFixedDecimal() = default;
|
||||
|
||||
/**
|
||||
* Returns the value corresponding to the specified operand (n, i, f, t, v, or w).
|
||||
* If the operand is 'n', returns a double; otherwise, returns an integer.
|
||||
*/
|
||||
virtual double getPluralOperand(PluralOperand operand) const = 0;
|
||||
|
||||
/** Converts from the tokenType enum to PluralOperand. */
|
||||
virtual double getPluralOperand(tokenType tt) const {
|
||||
switch(tt) {
|
||||
case tVariableN:
|
||||
return getPluralOperand(PLURAL_OPERAND_N);
|
||||
case tVariableI:
|
||||
return getPluralOperand(PLURAL_OPERAND_I);
|
||||
case tVariableF:
|
||||
return getPluralOperand(PLURAL_OPERAND_F);
|
||||
case tVariableV:
|
||||
return getPluralOperand(PLURAL_OPERAND_V);
|
||||
case tVariableT:
|
||||
return getPluralOperand(PLURAL_OPERAND_T);
|
||||
default:
|
||||
U_ASSERT(FALSE); // unexpected.
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isNaN() const = 0;
|
||||
|
||||
virtual bool isInfinite() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* class FixedDecimal serves to communicate the properties
|
||||
* of a formatted number from a decimal formatter to PluralRules::select()
|
||||
|
@ -184,7 +266,7 @@ private:
|
|||
* see DecimalFormat::getFixedDecimal()
|
||||
* @internal
|
||||
*/
|
||||
class U_I18N_API FixedDecimal: public UMemory {
|
||||
class U_I18N_API FixedDecimal: public IFixedDecimal, public UObject {
|
||||
public:
|
||||
/**
|
||||
* @param n the number, e.g. 12.345
|
||||
|
@ -196,10 +278,16 @@ class U_I18N_API FixedDecimal: public UMemory {
|
|||
explicit FixedDecimal(double n);
|
||||
explicit FixedDecimal(const VisibleDigits &n);
|
||||
FixedDecimal();
|
||||
~FixedDecimal() override = default;
|
||||
FixedDecimal(const UnicodeString &s, UErrorCode &ec);
|
||||
FixedDecimal(const FixedDecimal &other);
|
||||
|
||||
double get(tokenType operand) const;
|
||||
double getPluralOperand(PluralOperand operand) const override;
|
||||
bool isNaN() const override;
|
||||
bool isInfinite() const override;
|
||||
|
||||
bool isNanOrInfinity() const; // used in decimfmtimpl.cpp
|
||||
|
||||
int32_t getVisibleFractionDigitCount() const;
|
||||
|
||||
void init(double n, int32_t v, int64_t f);
|
||||
|
@ -217,7 +305,8 @@ class U_I18N_API FixedDecimal: public UMemory {
|
|||
int64_t intValue;
|
||||
UBool hasIntegerValue;
|
||||
UBool isNegative;
|
||||
UBool isNanOrInfinity;
|
||||
UBool _isNaN;
|
||||
UBool _isInfinite;
|
||||
};
|
||||
|
||||
class AndConstraint : public UMemory {
|
||||
|
@ -240,7 +329,7 @@ public:
|
|||
virtual ~AndConstraint();
|
||||
AndConstraint* add();
|
||||
// UBool isFulfilled(double number);
|
||||
UBool isFulfilled(const FixedDecimal &number);
|
||||
UBool isFulfilled(const IFixedDecimal &number);
|
||||
};
|
||||
|
||||
class OrConstraint : public UMemory {
|
||||
|
@ -253,7 +342,7 @@ public:
|
|||
virtual ~OrConstraint();
|
||||
AndConstraint* add();
|
||||
// UBool isFulfilled(double number);
|
||||
UBool isFulfilled(const FixedDecimal &number);
|
||||
UBool isFulfilled(const IFixedDecimal &number);
|
||||
};
|
||||
|
||||
class RuleChain : public UMemory {
|
||||
|
@ -271,7 +360,7 @@ public:
|
|||
RuleChain(const RuleChain& other);
|
||||
virtual ~RuleChain();
|
||||
|
||||
UnicodeString select(const FixedDecimal &number) const;
|
||||
UnicodeString select(const IFixedDecimal &number) const;
|
||||
void dumpRules(UnicodeString& result);
|
||||
UErrorCode getKeywords(int32_t maxArraySize, UnicodeString *keywords, int32_t& arraySize) const;
|
||||
UBool isKeyword(const UnicodeString& keyword) const;
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
U_NAMESPACE_BEGIN
|
||||
|
||||
class Hashtable;
|
||||
class FixedDecimal;
|
||||
class IFixedDecimal;
|
||||
class VisibleDigitsWithExponent;
|
||||
class RuleChain;
|
||||
class PluralRuleParser;
|
||||
|
@ -367,7 +367,7 @@ public:
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
UnicodeString select(const FixedDecimal &number) const;
|
||||
UnicodeString select(const IFixedDecimal &number) const;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
|
|
@ -773,11 +773,11 @@ void IntlTestDecimalFormatAPI::TestFixedDecimal() {
|
|||
|
||||
fd = df->getFixedDecimal(uprv_getInfinity(), status);
|
||||
TEST_ASSERT_STATUS(status);
|
||||
ASSERT_EQUAL(TRUE, fd.isNanOrInfinity);
|
||||
ASSERT_EQUAL(TRUE, fd.isNanOrInfinity());
|
||||
fd = df->getFixedDecimal(0.0, status);
|
||||
ASSERT_EQUAL(FALSE, fd.isNanOrInfinity);
|
||||
ASSERT_EQUAL(FALSE, fd.isNanOrInfinity());
|
||||
fd = df->getFixedDecimal(uprv_getNaN(), status);
|
||||
ASSERT_EQUAL(TRUE, fd.isNanOrInfinity);
|
||||
ASSERT_EQUAL(TRUE, fd.isNanOrInfinity());
|
||||
TEST_ASSERT_STATUS(status);
|
||||
|
||||
// Test Big Decimal input.
|
||||
|
|
Loading…
Add table
Reference in a new issue