ICU-13574 Replacing DigitList with DecimalQuantity through most of the code base.

X-SVN-Rev: 41064
This commit is contained in:
Shane Carr 2018-03-03 10:53:01 +00:00
parent 3681a6803b
commit 94427dc200
21 changed files with 614 additions and 705 deletions

View File

@ -9,11 +9,229 @@
// Helpful in toString methods and elsewhere.
#define UNISTR_FROM_STRING_EXPLICIT
#include "unicode/decimfmt.h"
#include "number_decimalquantity.h"
using namespace icu;
using namespace icu::number;
using namespace icu::number::impl;
using ERoundingMode = icu::DecimalFormat::ERoundingMode;
using EPadPosition = icu::DecimalFormat::EPadPosition;
DecimalFormat::DecimalFormat(UErrorCode& status) {}
DecimalFormat::DecimalFormat(const UnicodeString& pattern, UErrorCode& status) {}
DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt,
UErrorCode& status) {}
DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt,
UNumberFormatStyle style, UErrorCode& status) {}
void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {}
DecimalFormat&
DecimalFormat::setAttribute(UNumberFormatAttribute attr, int32_t newvalue, UErrorCode& status) {}
int32_t DecimalFormat::getAttribute(UNumberFormatAttribute attr, UErrorCode& status) const {}
void DecimalFormat::setGroupingUsed(UBool newValue) {}
void DecimalFormat::setParseIntegerOnly(UBool value) {}
void DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) {}
DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt,
UParseError& parseError, UErrorCode& status) {}
DecimalFormat::DecimalFormat(const UnicodeString& pattern, const DecimalFormatSymbols& symbols,
UErrorCode& status) {}
DecimalFormat::DecimalFormat(const DecimalFormat& source) {}
DecimalFormat& DecimalFormat::operator=(const DecimalFormat& rhs) {}
DecimalFormat::~DecimalFormat() = default;
Format* DecimalFormat::clone() const {}
UBool DecimalFormat::operator==(const Format& other) const {}
UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos) const {}
UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos,
UErrorCode& status) const {}
UnicodeString&
DecimalFormat::format(double number, UnicodeString& appendTo, FieldPositionIterator* posIter,
UErrorCode& status) const {}
UnicodeString& DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPosition& pos) const {}
UnicodeString& DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPosition& pos,
UErrorCode& status) const {}
UnicodeString&
DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPositionIterator* posIter,
UErrorCode& status) const {}
UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPosition& pos) const {}
UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPosition& pos,
UErrorCode& status) const {}
UnicodeString&
DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPositionIterator* posIter,
UErrorCode& status) const {}
UnicodeString&
DecimalFormat::format(StringPiece number, UnicodeString& appendTo, FieldPositionIterator* posIter,
UErrorCode& status) const {}
UnicodeString&
DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, FieldPositionIterator* posIter,
UErrorCode& status) const {}
UnicodeString& DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, FieldPosition& pos,
UErrorCode& status) const {}
void
DecimalFormat::parse(const UnicodeString& text, Formattable& result, ParsePosition& parsePosition) const {}
CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text, ParsePosition& pos) const {}
const DecimalFormatSymbols* DecimalFormat::getDecimalFormatSymbols(void) const {}
void DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt) {}
void DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) {}
const CurrencyPluralInfo* DecimalFormat::getCurrencyPluralInfo(void) const {}
void DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) {}
void DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) {}
UnicodeString& DecimalFormat::getPositivePrefix(UnicodeString& result) const {}
void DecimalFormat::setPositivePrefix(const UnicodeString& newValue) {}
UnicodeString& DecimalFormat::getNegativePrefix(UnicodeString& result) const {}
void DecimalFormat::setNegativePrefix(const UnicodeString& newValue) {}
UnicodeString& DecimalFormat::getPositiveSuffix(UnicodeString& result) const {}
void DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) {}
UnicodeString& DecimalFormat::getNegativeSuffix(UnicodeString& result) const {}
void DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) {}
int32_t DecimalFormat::getMultiplier(void) const {}
void DecimalFormat::setMultiplier(int32_t newValue) {}
double DecimalFormat::getRoundingIncrement(void) const {}
void DecimalFormat::setRoundingIncrement(double newValue) {}
ERoundingMode DecimalFormat::getRoundingMode(void) const {}
void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {}
int32_t DecimalFormat::getFormatWidth(void) const {}
void DecimalFormat::setFormatWidth(int32_t width) {}
UnicodeString DecimalFormat::getPadCharacterString() const {}
void DecimalFormat::setPadCharacter(const UnicodeString& padChar) {}
EPadPosition DecimalFormat::getPadPosition(void) const {}
void DecimalFormat::setPadPosition(EPadPosition padPos) {}
UBool DecimalFormat::isScientificNotation(void) const {}
void DecimalFormat::setScientificNotation(UBool useScientific) {}
int8_t DecimalFormat::getMinimumExponentDigits(void) const {}
void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {}
UBool DecimalFormat::isExponentSignAlwaysShown(void) const {}
void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {}
int32_t DecimalFormat::getGroupingSize(void) const {}
void DecimalFormat::setGroupingSize(int32_t newValue) {}
int32_t DecimalFormat::getSecondaryGroupingSize(void) const {}
void DecimalFormat::setSecondaryGroupingSize(int32_t newValue) {}
int32_t DecimalFormat::getMinimumGroupingDigits() const {}
void DecimalFormat::setMinimumGroupingDigits(int32_t newValue) {}
UBool DecimalFormat::isDecimalSeparatorAlwaysShown(void) const {}
void DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) {}
UBool DecimalFormat::isDecimalPatternMatchRequired(void) const {}
void DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) {}
UnicodeString& DecimalFormat::toPattern(UnicodeString& result) const {}
UnicodeString& DecimalFormat::toLocalizedPattern(UnicodeString& result) const {}
void
DecimalFormat::applyPattern(const UnicodeString& pattern, UParseError& parseError, UErrorCode& status) {}
void DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status) {}
void DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UParseError& parseError,
UErrorCode& status) {}
void DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status) {}
void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {}
void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {}
void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {}
void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {}
int32_t DecimalFormat::getMinimumSignificantDigits() const {}
int32_t DecimalFormat::getMaximumSignificantDigits() const {}
void DecimalFormat::setMinimumSignificantDigits(int32_t min) {}
void DecimalFormat::setMaximumSignificantDigits(int32_t max) {}
UBool DecimalFormat::areSignificantDigitsUsed() const {}
void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {}
void DecimalFormat::setCurrency(const char16_t* theCurrency, UErrorCode& ec) {}
void DecimalFormat::setCurrency(const char16_t* theCurrency) {}
void DecimalFormat::setCurrencyUsage(UCurrencyUsage newUsage, UErrorCode* ec) {}
UCurrencyUsage DecimalFormat::getCurrencyUsage() const {}
number::LocalizedNumberFormatter DecimalFormat::toNumberFormatter() const {}
UClassID DecimalFormat::getStaticClassID() {}
UClassID DecimalFormat::getDynamicClassID() const {}
#endif /* #if !UCONFIG_NO_FORMATTING */

View File

@ -29,8 +29,8 @@
#include "cmemory.h"
#include "cstring.h"
#include "decNumber.h"
#include "digitlst.h"
#include "fmtableimp.h"
#include "number_decimalquantity.h"
// *****************************************************************************
// class Formattable
@ -40,6 +40,8 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
using number::impl::DecimalQuantity;
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
@ -103,7 +105,7 @@ void Formattable::init() {
fValue.fInt64 = 0;
fType = kLong;
fDecimalStr = NULL;
fDecimalNum = NULL;
fDecimalQuantity = NULL;
fBogus.setToBogus();
}
@ -257,8 +259,8 @@ Formattable::operator=(const Formattable& source)
}
UErrorCode status = U_ZERO_ERROR;
if (source.fDecimalNum != NULL) {
fDecimalNum = new DigitList(*source.fDecimalNum); // TODO: use internal digit list
if (source.fDecimalQuantity != NULL) {
fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity);
}
if (source.fDecimalStr != NULL) {
fDecimalStr = new CharString(*source.fDecimalStr, status);
@ -356,14 +358,9 @@ void Formattable::dispose()
delete fDecimalStr;
fDecimalStr = NULL;
FmtStackData *stackData = (FmtStackData*)fStackData;
if(fDecimalNum != &(stackData->stackDecimalNum)) {
delete fDecimalNum;
} else {
fDecimalNum->~DigitList(); // destruct, don't deallocate
}
fDecimalNum = NULL;
delete fDecimalQuantity;
fDecimalQuantity = NULL;
}
Formattable *
@ -465,8 +462,8 @@ Formattable::getInt64(UErrorCode& status) const
} else if (fValue.fDouble < (double)U_INT64_MIN) {
status = U_INVALID_FORMAT_ERROR;
return U_INT64_MIN;
} else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) {
int64_t val = fDecimalNum->getInt64();
} else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != NULL) {
int64_t val = fDecimalQuantity->toLong();
if (val != 0) {
return val;
} else {
@ -714,27 +711,27 @@ StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
CharString *Formattable::internalGetCharString(UErrorCode &status) {
if(fDecimalStr == NULL) {
if (fDecimalNum == NULL) {
if (fDecimalQuantity == NULL) {
// No decimal number for the formattable yet. Which means the value was
// set directly by the user as an int, int64 or double. If the value came
// from parsing, or from the user setting a decimal number, fDecimalNum
// would already be set.
//
fDecimalNum = new DigitList; // TODO: use internal digit list
if (fDecimalNum == NULL) {
fDecimalQuantity = new DecimalQuantity(); // TODO: use internal digit list
if (fDecimalQuantity == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
switch (fType) {
case kDouble:
fDecimalNum->set(this->getDouble());
fDecimalQuantity->setToDouble(this->getDouble());
break;
case kLong:
fDecimalNum->set(this->getLong());
fDecimalQuantity->setToInt(this->getLong());
break;
case kInt64:
fDecimalNum->set(this->getInt64());
fDecimalQuantity->setToLong(this->getInt64());
break;
default:
// The formattable's value is not a numeric type.
@ -743,55 +740,48 @@ CharString *Formattable::internalGetCharString(UErrorCode &status) {
}
}
fDecimalStr = new CharString;
fDecimalStr = new CharString();
if (fDecimalStr == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
fDecimalNum->getDecimal(*fDecimalStr, status);
UnicodeString result = fDecimalQuantity->toNumberString();
for (int32_t i=0; i<result.length(); i++) {
fDecimalStr->append(static_cast<char>(result[i]), status);
if (U_FAILURE(status)) {
return NULL;
}
}
}
return fDecimalStr;
}
DigitList *
Formattable::getInternalDigitList() {
FmtStackData *stackData = (FmtStackData*)fStackData;
if(fDecimalNum != &(stackData->stackDecimalNum)) {
delete fDecimalNum;
fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList();
} else {
fDecimalNum->clear();
}
return fDecimalNum;
}
// ---------------------------------------
void
Formattable::adoptDigitList(DigitList *dl) {
if(fDecimalNum==dl) {
fDecimalNum = NULL; // don't delete
}
dispose();
fDecimalNum = dl;
if(dl==NULL) { // allow adoptDigitList(NULL) to clear
return;
}
Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
if (fDecimalQuantity != NULL) {
delete fDecimalQuantity;
}
fDecimalQuantity = dq;
if (dq == NULL) { // allow adoptDigitList(NULL) to clear
return;
}
// Set the value into the Union of simple type values.
// Cannot use the set() functions because they would delete the fDecimalNum value,
if (fDecimalNum->fitsIntoLong(FALSE)) {
// TODO: fDecimalQuantity->fitsInInt() to kLong type.
/*
if (fDecimalQuantity->fitsIntoLong(FALSE)) {
fType = kLong;
fValue.fInt64 = fDecimalNum->getLong();
} else if (fDecimalNum->fitsIntoInt64(FALSE)) {
} else
*/
if (fDecimalQuantity->fitsInLong()) {
fType = kInt64;
fValue.fInt64 = fDecimalNum->getInt64();
fValue.fInt64 = fDecimalQuantity->toLong();
} else {
fType = kDouble;
fValue.fDouble = fDecimalNum->getDouble();
fValue.fDouble = fDecimalQuantity->toDouble();
}
}
@ -804,24 +794,12 @@ Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
}
dispose();
// Copy the input string and nul-terminate it.
// The decNumber library requires nul-terminated input. StringPiece input
// is not guaranteed nul-terminated. Too bad.
// CharString automatically adds the nul.
DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList
if (dnum == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
dnum->set(CharString(numberString, status).toStringPiece(), status);
if (U_FAILURE(status)) {
delete dnum;
return; // String didn't contain a decimal number.
}
adoptDigitList(dnum);
DecimalQuantity* dq = new DecimalQuantity();
dq->setToDecNumber(numberString);
adoptDecimalQuantity(dq);
// Note that we do not hang on to the caller's input string.
// If we are asked for the string, we will regenerate one from fDecimalNum.
// If we are asked for the string, we will regenerate one from fDecimalQuantity.
}
#if 0

View File

@ -10,7 +10,7 @@
#ifndef FMTABLEIMP_H
#define FMTABLEIMP_H
#include "digitlst.h"
#include "number_decimalquantity.h"
#if !UCONFIG_NO_FORMATTING
@ -20,7 +20,7 @@ U_NAMESPACE_BEGIN
* @internal
*/
struct FmtStackData {
DigitList stackDecimalNum; // 128
icu::number::impl::DecimalQuantity stackDecimalNum; // 128
//CharString stackDecimalStr; // 64
// -----
// 192 total

View File

@ -49,6 +49,7 @@
#include "util.h"
#include "uvector.h"
#include "visibledigits.h"
#include "number_decimalquantity.h"
// *****************************************************************************
// class MessageFormat
@ -1961,13 +1962,12 @@ UnicodeString MessageFormat::PluralSelectorProvider::select(void *ctx, double nu
context.formatter->format(context.number, context.numberString, ec);
auto* decFmt = dynamic_cast<const DecimalFormat *>(context.formatter);
if(decFmt != NULL) {
const IFixedDecimal& dec = decFmt->toNumberFormatter()
.formatDouble(context.number.getDouble(ec), ec)
.getFixedDecimal(ec);
number::impl::DecimalQuantity dq;
decFmt->formatToDecimalQuantity(number, dq, ec);
if (U_FAILURE(ec)) {
return UnicodeString(FALSE, OTHER_STRING, 5);
}
return rules->select(dec);
return rules->select(dq);
} else {
return rules->select(number);
}

View File

@ -19,8 +19,8 @@
#include "utypeinfo.h" // for 'typeid' to work
#include "nfsubs.h"
#include "digitlst.h"
#include "fmtableimp.h"
#include "number_decimalquantity.h"
#if U_HAVE_RBNF
@ -47,6 +47,8 @@ static const UChar gGreaterGreaterThan[] =
U_NAMESPACE_BEGIN
using number::impl::DecimalQuantity;
class SameValueSubstitution : public NFSubstitution {
public:
SameValueSubstitution(int32_t pos,
@ -1069,13 +1071,12 @@ FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInser
// numberToFormat /= 10;
// }
DigitList dl;
dl.set(number);
dl.roundFixedPoint(20); // round to 20 fraction digits.
dl.reduce(); // Removes any trailing zeros.
DecimalQuantity dl;
dl.setToDouble(number);
dl.roundToMagnitude(-20, UNUM_ROUND_HALFEVEN, status); // round to 20 fraction digits.
UBool pad = FALSE;
for (int32_t didx = dl.getCount()-1; didx>=dl.getDecimalAt(); didx--) {
for (int32_t didx = dl.getLowerDisplayMagnitude(); didx<0; didx++) {
// Loop iterates over fraction digits, starting with the LSD.
// include both real digits from the number, and zeros
// to the left of the MSD but to the right of the decimal point.
@ -1142,7 +1143,7 @@ FractionalPartSubstitution::doParse(const UnicodeString& text,
int32_t digit;
// double p10 = 0.1;
DigitList dl;
DecimalQuantity dl;
NumberFormat* fmt = NULL;
while (workText.length() > 0 && workPos.getIndex() != 0) {
workPos.setIndex(0);
@ -1170,7 +1171,8 @@ FractionalPartSubstitution::doParse(const UnicodeString& text,
}
if (workPos.getIndex() != 0) {
dl.append((char)('0' + digit));
// TODO(sffc): Make sure this is doing what it is supposed to do.
dl.appendDigit(static_cast<int8_t>(digit), 0, true);
// result += digit * p10;
// p10 /= 10;
parsePosition.setIndex(parsePosition.getIndex() + workPos.getIndex());
@ -1183,7 +1185,7 @@ FractionalPartSubstitution::doParse(const UnicodeString& text,
}
delete fmt;
result = dl.getCount() == 0 ? 0 : dl.getDouble();
result = dl.toDouble();
result = composeRuleValue(result, baseValue);
resVal.setDouble(result);
return TRUE;

View File

@ -241,6 +241,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory {
/** Visible for testing */
inline bool isExplicitExactDouble() { return explicitExactDouble; };
bool operator==(const DecimalQuantity& other) const;
bool operator!=(const DecimalQuantity& other) const;
/**
* Bogus flag for when a DecimalQuantity is stored on the stack.
*/

View File

@ -51,10 +51,10 @@
#include "uassert.h"
#include "umutex.h"
#include "mutex.h"
#include "digitlst.h"
#include <float.h>
#include "sharednumberformat.h"
#include "unifiedcache.h"
#include "number_decimalquantity.h"
//#define FMT_DEBUG
@ -524,7 +524,7 @@ ArgExtractor::ArgExtractor(const NumberFormat& /*nf*/, const Formattable& obj, U
ArgExtractor::~ArgExtractor() {
}
UnicodeString& NumberFormat::format(const DigitList &number,
UnicodeString& NumberFormat::format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const {
@ -534,7 +534,7 @@ UnicodeString& NumberFormat::format(const DigitList &number,
if (U_FAILURE(status)) {
return appendTo;
}
double dnum = number.getDouble();
double dnum = number.toDouble();
format(dnum, appendTo, posIter, status);
return appendTo;
}
@ -542,7 +542,7 @@ UnicodeString& NumberFormat::format(const DigitList &number,
UnicodeString&
NumberFormat::format(const DigitList &number,
NumberFormat::format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode &status) const {
@ -552,7 +552,7 @@ NumberFormat::format(const DigitList &number,
if (U_FAILURE(status)) {
return appendTo;
}
double dnum = number.getDouble();
double dnum = number.toDouble();
format(dnum, appendTo, pos, status);
return appendTo;
}
@ -578,7 +578,7 @@ NumberFormat::format(const Formattable& obj,
return cloneFmt->format(*n, appendTo, pos, status);
}
if (n->isNumeric() && n->getDigitList() != NULL) {
if (n->isNumeric() && n->getDecimalQuantity() != NULL) {
// Decimal Number. We will have a DigitList available if the value was
// set to a decimal number, or if the value originated with a parse.
//
@ -587,7 +587,7 @@ NumberFormat::format(const Formattable& obj,
// know about DigitList to continue to operate as they had.
//
// DecimalFormat overrides the DigitList formatting functions.
format(*n->getDigitList(), appendTo, pos, status);
format(*n->getDecimalQuantity(), appendTo, pos, status);
} else {
switch (n->getType()) {
case Formattable::kDouble:
@ -633,9 +633,9 @@ NumberFormat::format(const Formattable& obj,
return cloneFmt->format(*n, appendTo, posIter, status);
}
if (n->isNumeric() && n->getDigitList() != NULL) {
if (n->isNumeric() && n->getDecimalQuantity() != NULL) {
// Decimal Number
format(*n->getDigitList(), appendTo, posIter, status);
format(*n->getDecimalQuantity(), appendTo, posIter, status);
} else {
switch (n->getType()) {
case Formattable::kDouble:

View File

@ -22,7 +22,6 @@
#include "charstr.h"
#include "cmemory.h"
#include "cstring.h"
#include "digitlst.h"
#include "hash.h"
#include "locutil.h"
#include "mutex.h"
@ -37,12 +36,14 @@
#include "unifiedcache.h"
#include "digitinterval.h"
#include "visibledigits.h"
#include "number_decimalquantity.h"
#if !UCONFIG_NO_FORMATTING
U_NAMESPACE_BEGIN
using namespace icu::pluralimpl;
using icu::number::impl::DecimalQuantity;
static const UChar PLURAL_KEYWORD_OTHER[]={LOW_O,LOW_T,LOW_H,LOW_E,LOW_R,0};
static const UChar PLURAL_DEFAULT_RULE[]={LOW_O,LOW_T,LOW_H,LOW_E,LOW_R,COLON,SPACE,LOW_N,0};
@ -254,11 +255,10 @@ PluralRules::select(const Formattable& obj, const NumberFormat& fmt, UErrorCode&
if (U_SUCCESS(status)) {
const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
if (decFmt != NULL) {
const IFixedDecimal& dec = decFmt->toNumberFormatter()
.formatDouble(obj.getDouble(status), status)
.getFixedDecimal(status);
number::impl::DecimalQuantity dq;
decFmt->formatToDecimalQuantity(obj, dq, status);
if (U_SUCCESS(status)) {
return select(dec);
return select(dq);
}
} else {
double number = obj.getDouble(status);
@ -1477,14 +1477,14 @@ FixedDecimal::FixedDecimal() {
FixedDecimal::FixedDecimal(const UnicodeString &num, UErrorCode &status) {
CharString cs;
cs.appendInvariantChars(num, status);
DigitList dl;
dl.set(cs.toStringPiece(), status);
DecimalQuantity dl;
dl.setToDecNumber(cs.toStringPiece());
if (U_FAILURE(status)) {
init(0, 0, 0);
return;
}
int32_t decimalPoint = num.indexOf(DOT);
double n = dl.getDouble();
double n = dl.toDouble();
if (decimalPoint == -1) {
init(n, 0, 0);
} else {

View File

@ -248,6 +248,10 @@ class U_I18N_API IFixedDecimal {
virtual bool isNaN() const = 0;
virtual bool isInfinite() const = 0;
virtual bool hasIntegerValue() {
return getPluralOperand(PLURAL_OPERAND_N) == getPluralOperand(PLURAL_OPERAND_I);
}
};
/**

View File

@ -25,6 +25,7 @@
#include "standardplural.h"
#include "visibledigits.h"
#include "uassert.h"
#include "number_decimalquantity.h"
U_NAMESPACE_BEGIN
@ -151,13 +152,12 @@ StandardPlural::Form QuantityFormatter::selectPlural(
UnicodeString pluralKeyword;
const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
if (decFmt != NULL) {
const IFixedDecimal& dec = decFmt->toNumberFormatter()
.formatDouble(number.getDouble(status), status)
.getFixedDecimal(status);
number::impl::DecimalQuantity dq;
decFmt->formatToDecimalQuantity(number, dq, status);
if (U_FAILURE(status)) {
return StandardPlural::OTHER;
}
pluralKeyword = rules.select(dec);
pluralKeyword = rules.select(dq);
decFmt->format(number, formattedNumber, pos, status);
} else {
if (number.getType() == Formattable::kDouble) {

View File

@ -34,7 +34,7 @@
#include "patternprops.h"
#include "uresimp.h"
#include "nfrs.h"
#include "digitlst.h"
#include "number_decimalquantity.h"
// debugging
// #define RBNF_DEBUG
@ -68,6 +68,8 @@ static const UChar gSemiPercent[] =
U_NAMESPACE_BEGIN
using number::impl::DecimalQuantity;
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedNumberFormat)
/*
@ -1109,21 +1111,21 @@ RuleBasedNumberFormat::findRuleSet(const UnicodeString& name, UErrorCode& status
}
UnicodeString&
RuleBasedNumberFormat::format(const DigitList &number,
RuleBasedNumberFormat::format(const DecimalQuantity &number,
UnicodeString &appendTo,
FieldPositionIterator *posIter,
UErrorCode &status) const {
if (U_FAILURE(status)) {
return appendTo;
}
DigitList copy(number);
if (copy.fitsIntoInt64(false)) {
format(((DigitList &)number).getInt64(), appendTo, posIter, status);
DecimalQuantity copy(number);
if (copy.fitsInLong()) {
format(((DecimalQuantity &)number).toLong(), appendTo, posIter, status);
}
else {
copy.roundAtExponent(0);
if (copy.fitsIntoInt64(false)) {
format(number.getDouble(), appendTo, posIter, status);
copy.roundToMagnitude(0, number::impl::RoundingMode::UNUM_ROUND_HALFEVEN, status);
if (copy.fitsInLong()) {
format(number.toLong(), appendTo, posIter, status);
}
else {
// We're outside of our normal range that this framework can handle.
@ -1132,7 +1134,7 @@ RuleBasedNumberFormat::format(const DigitList &number,
// TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J.
NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
Formattable f;
f.adoptDigitList(new DigitList(number));
f.adoptDecimalQuantity(new DecimalQuantity(number));
decimalFormat->format(f, appendTo, posIter, status);
delete decimalFormat;
}
@ -1142,21 +1144,21 @@ RuleBasedNumberFormat::format(const DigitList &number,
UnicodeString&
RuleBasedNumberFormat::format(const DigitList &number,
RuleBasedNumberFormat::format(const DecimalQuantity &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode &status) const {
if (U_FAILURE(status)) {
return appendTo;
}
DigitList copy(number);
if (copy.fitsIntoInt64(false)) {
format(((DigitList &)number).getInt64(), appendTo, pos, status);
DecimalQuantity copy(number);
if (copy.fitsInLong()) {
format(((DecimalQuantity &)number).toLong(), appendTo, pos, status);
}
else {
copy.roundAtExponent(0);
if (copy.fitsIntoInt64(false)) {
format(number.getDouble(), appendTo, pos, status);
copy.roundToMagnitude(0, number::impl::RoundingMode::UNUM_ROUND_HALFEVEN, status);
if (copy.fitsInLong()) {
format(number.toLong(), appendTo, pos, status);
}
else {
// We're outside of our normal range that this framework can handle.
@ -1165,7 +1167,7 @@ RuleBasedNumberFormat::format(const DigitList &number,
// TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J.
NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
Formattable f;
f.adoptDigitList(new DigitList(number));
f.adoptDecimalQuantity(new DecimalQuantity(number));
decimalFormat->format(f, appendTo, pos, status);
delete decimalFormat;
}
@ -1270,11 +1272,13 @@ RuleBasedNumberFormat::format(double number,
{
int32_t startPos = toAppendTo.length();
if (getRoundingMode() != DecimalFormat::ERoundingMode::kRoundUnnecessary && !uprv_isNaN(number) && !uprv_isInfinite(number)) {
DigitList digitList;
digitList.set(number);
digitList.setRoundingMode(getRoundingMode());
digitList.roundFixedPoint(getMaximumFractionDigits());
number = digitList.getDouble();
DecimalQuantity digitList;
digitList.setToDouble(number);
digitList.roundToMagnitude(
-getMaximumFractionDigits(),
static_cast<UNumberFormatRoundingMode>(getRoundingMode()),
status);
number = digitList.toDouble();
}
rs.format(number, toAppendTo, toAppendTo.length(), 0, status);
adjustForCapitalizationContext(startPos, toAppendTo, status);
@ -1310,9 +1314,9 @@ RuleBasedNumberFormat::format(int64_t number, NFRuleSet *ruleSet, UnicodeString&
NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
Formattable f;
FieldPosition pos(FieldPosition::DONT_CARE);
DigitList *digitList = new DigitList();
digitList->set(number);
f.adoptDigitList(digitList);
DecimalQuantity *digitList = new DecimalQuantity();
digitList->setToLong(number);
f.adoptDecimalQuantity(digitList);
decimalFormat->format(f, toAppendTo, pos, status);
delete decimalFormat;
}

View File

@ -76,7 +76,7 @@ public:
* Destructor.
* @stable ICU 51
*/
virtual ~CompactDecimalFormat();
~CompactDecimalFormat() U_OVERRIDE;
/**
* Assignment operator.
@ -86,289 +86,8 @@ public:
*/
CompactDecimalFormat& operator=(const CompactDecimalFormat& rhs);
/**
* Clone this Format object polymorphically. The caller owns the
* result and should delete it when done.
*
* @return a polymorphic copy of this CompactDecimalFormat.
* @stable ICU 51
*/
virtual Format* clone() const;
/**
* Return TRUE if the given Format objects are semantically equal.
* Objects of different subclasses are considered unequal.
*
* @param other the object to be compared with.
* @return TRUE if the given Format objects are semantically equal.
* @stable ICU 51
*/
virtual UBool operator==(const Format& other) const;
using DecimalFormat::format;
/**
* Format a double or long number using base-10 representation.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @stable ICU 51
*/
virtual UnicodeString& format(double number,
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Format a double or long number using base-10 representation.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @param status
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(double number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode &status) const;
/**
* Format a double or long number using base-10 representation.
* Currently sets status to U_UNSUPPORTED_ERROR.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param posIter On return, can be used to iterate over positions
* of fields generated by this format call.
* Can be NULL.
* @param status Output param filled with success/failure status.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(double number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const;
/**
* Format a long number using base-10 representation.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @stable ICU 56
*/
virtual UnicodeString& format(int32_t number,
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Format a long number using base-10 representation.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(int32_t number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode &status) const;
/**
* Format a long number using base-10 representation.
* Currently sets status to U_UNSUPPORTED_ERROR
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param posIter On return, can be used to iterate over positions
* of fields generated by this format call.
* Can be NULL.
* @param status Output param filled with success/failure status.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(int32_t number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const;
/**
* Format an int64 number using base-10 representation.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @stable ICU 51
*/
virtual UnicodeString& format(int64_t number,
UnicodeString& appendTo,
FieldPosition& pos) const;
/**
* Format an int64 number using base-10 representation.
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(int64_t number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode &status) const;
/**
* Format an int64 number using base-10 representation.
* Currently sets status to U_UNSUPPORTED_ERROR
*
* @param number The value to be formatted.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param posIter On return, can be used to iterate over positions
* of fields generated by this format call.
* Can be NULL.
* @param status Output param filled with success/failure status.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(int64_t number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const;
/**
* Format a decimal number. Currently sets status to U_UNSUPPORTED_ERROR
* The syntax of the unformatted number is a "numeric string"
* as defined in the Decimal Arithmetic Specification, available at
* http://speleotrove.com/decimal
*
* @param number The unformatted number, as a string.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param posIter On return, can be used to iterate over positions
* of fields generated by this format call.
* Can be NULL.
* @param status Output param filled with success/failure status.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(StringPiece number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const;
/**
* Format a decimal number. Currently sets status to U_UNSUPPORTED_ERROR
* The number is a DigitList wrapper onto a floating point decimal number.
* The default implementation in NumberFormat converts the decimal number
* to a double and formats that.
*
* @param number The number, a DigitList format Decimal Floating Point.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param posIter On return, can be used to iterate over positions
* of fields generated by this format call.
* @param status Output param filled with success/failure status.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(const DigitList &number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const;
/**
* Format a decimal number. Currently sets status to U_UNSUPPORTED_ERROR.
* The number is a DigitList wrapper onto a floating point decimal number.
* The default implementation in NumberFormat converts the decimal number
* to a double and formats that.
*
* @param number The number, a DigitList format Decimal Floating Point.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @param status Output param filled with success/failure status.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(const DigitList &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& status) const;
/**
* CompactDecimalFormat does not support parsing. This implementation
* does nothing.
* @param text Unused.
* @param result Does not change.
* @param parsePosition Does not change.
* @see Formattable
* @stable ICU 51
*/
virtual void parse(const UnicodeString& text,
Formattable& result,
ParsePosition& parsePosition) const;
/**
* CompactDecimalFormat does not support parsing. This implementation
* sets status to U_UNSUPPORTED_ERROR
*
* @param text Unused.
* @param result Does not change.
* @param status Always set to U_UNSUPPORTED_ERROR.
* @stable ICU 51
*/
virtual void parse(const UnicodeString& text,
Formattable& result,
UErrorCode& status) const;
/**
* Parses text from the given string as a currency amount. Unlike
* the parse() method, this method will attempt to parse a generic
* currency name, searching for a match of this object's locale's
* currency display names, or for a 3-letter ISO currency code.
* This method will fail if this format is not a currency format,
* that is, if it does not contain the currency pattern symbol
* (U+00A4) in its prefix or suffix. This implementation always returns
* NULL.
*
* @param text the string to parse
* @param pos input-output position; on input, the position within text
* to match; must have 0 <= pos.getIndex() < text.length();
* on output, the position after the last matched character.
* If the parse fails, the position in unchanged upon output.
* @return if parse succeeds, a pointer to a newly-created CurrencyAmount
* object (owned by the caller) containing information about
* the parsed currency; if parse fails, this is NULL.
* @internal
*/
virtual CurrencyAmount* parseCurrency(const UnicodeString& text,
ParsePosition& pos) const;
/**
* Return the class ID for this class. This is useful only for
* comparing to a return value from getDynamicClassID(). For example:
@ -394,17 +113,6 @@ public:
* @stable ICU 51
*/
virtual UClassID getDynamicClassID() const;
private:
const UHashtable* _unitsByVariant;
const double* _divisors;
PluralRules* _pluralRules;
// Default constructor not implemented.
CompactDecimalFormat(const DecimalFormat &, const UHashtable* unitsByVariant, const double* divisors, PluralRules* pluralRules);
UBool eqHelper(const CompactDecimalFormat& that) const;
};
U_NAMESPACE_END

View File

@ -67,6 +67,12 @@ class DecimalFormatImpl;
class PluralRules;
class VisibleDigitsWithExponent;
namespace number {
namespace impl {
class DecimalQuantity;
}
}
// explicit template instantiation. see digitlst.h
// (When building DLLs for Windows this is required.)
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
@ -1084,11 +1090,11 @@ public:
/**
* Format a decimal number.
* The number is a DigitList wrapper onto a floating point decimal number.
* The number is a DecimalQuantity wrapper onto a floating point decimal number.
* The default implementation in NumberFormat converts the decimal number
* to a double and formats that.
*
* @param number The number, a DigitList format Decimal Floating Point.
* @param number The number, a DecimalQuantity format Decimal Floating Point.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param posIter On return, can be used to iterate over positions
@ -1097,50 +1103,18 @@ public:
* @return Reference to 'appendTo' parameter.
* @internal
*/
UnicodeString& format(const DigitList &number,
UnicodeString& format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const U_OVERRIDE;
/**
* Format a decimal number.
* @param number The number
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @param status Output param filled with success/failure status.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(const VisibleDigitsWithExponent &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& status) const;
/**
* Format a decimal number.
* @param number The number
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param posIter On return, can be used to iterate over positions
* of fields generated by this format call.
* @param status Output param filled with success/failure status.
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(const VisibleDigitsWithExponent &number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const;
/**
* Format a decimal number.
* The number is a DigitList wrapper onto a floating point decimal number.
* The number is a DecimalQuantity wrapper onto a floating point decimal number.
* The default implementation in NumberFormat converts the decimal number
* to a double and formats that.
*
* @param number The number, a DigitList format Decimal Floating Point.
* @param number The number, a DecimalQuantity format Decimal Floating Point.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
@ -1149,7 +1123,7 @@ public:
* @return Reference to 'appendTo' parameter.
* @internal
*/
UnicodeString& format(const DigitList &number,
UnicodeString& format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& status) const U_OVERRIDE;
@ -1967,6 +1941,25 @@ public:
*/
UCurrencyUsage getCurrencyUsage() const;
#ifndef U_HIDE_INTERNAL_API
/**
* Format a number and save it into the given DecimalQuantity.
* Internal, not intended for public use.
* @internal
*/
void formatToDecimalQuantity(double number, number::impl::DecimalQuantity& output,
UErrorCode& status) const;
/**
* Get a DecimalQuantity corresponding to a formattable as it would be
* formatted by this DecimalFormat.
* Internal, not intended for public use.
* @internal
*/
void formatToDecimalQuantity(const Formattable& number, number::impl::DecimalQuantity& output,
UErrorCode& status) const;
#endif
/**
* Converts this DecimalFormat to a NumberFormatter. Starting in ICU 60,
* NumberFormatter is the recommended way to format numbers.

View File

@ -33,7 +33,11 @@
U_NAMESPACE_BEGIN
class CharString;
class DigitList;
namespace number {
namespace impl {
class DecimalQuantity;
}
}
/**
* \def UNUM_INTERNAL_STACKARRAY_SIZE
@ -649,24 +653,19 @@ public:
* Internal function, do not use.
* TODO: figure out how to make this be non-public.
* NumberFormat::format(Formattable, ...
* needs to get at the DigitList, if it exists, for
* needs to get at the DecimalQuantity, if it exists, for
* big decimal formatting.
* @internal
*/
DigitList *getDigitList() const { return fDecimalNum;}
number::impl::DecimalQuantity *getDecimalQuantity() const { return fDecimalQuantity;}
/**
* @internal
*/
DigitList *getInternalDigitList();
/**
* Adopt, and set value from, a DigitList
* Adopt, and set value from, a DecimalQuantity
* Internal Function, do not use.
* @param dl the Digit List to be adopted
* @param dl the DecimalQuantity to be adopted
* @internal
*/
void adoptDigitList(DigitList *dl);
void adoptDecimalQuantity(number::impl::DecimalQuantity *dq);
/**
* Internal function to return the CharString pointer.
@ -706,9 +705,7 @@ private:
CharString *fDecimalStr;
DigitList *fDecimalNum;
char fStackData[UNUM_INTERNAL_STACKARRAY_SIZE]; // must be big enough for DigitList
number::impl::DecimalQuantity *fDecimalQuantity;
Type fType;
UnicodeString fBogus; // Bogus string when it's needed.

View File

@ -558,13 +558,13 @@ public:
public:
/**
* Format a decimal number.
* The number is a DigitList wrapper onto a floating point decimal number.
* The number is a DecimalQuantity wrapper onto a floating point decimal number.
* The default implementation in NumberFormat converts the decimal number
* to a double and formats that. Subclasses of NumberFormat that want
* to specifically handle big decimal numbers must override this method.
* class DecimalFormat does so.
*
* @param number The number, a DigitList format Decimal Floating Point.
* @param number The number, a DecimalQuantity format Decimal Floating Point.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param posIter On return, can be used to iterate over positions
@ -573,20 +573,20 @@ public:
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(const DigitList &number,
virtual UnicodeString& format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const;
/**
* Format a decimal number.
* The number is a DigitList wrapper onto a floating point decimal number.
* The number is a DecimalQuantity wrapper onto a floating point decimal number.
* The default implementation in NumberFormat converts the decimal number
* to a double and formats that. Subclasses of NumberFormat that want
* to specifically handle big decimal numbers must override this method.
* class DecimalFormat does so.
*
* @param number The number, a DigitList format Decimal Floating Point.
* @param number The number, a DecimalQuantity format Decimal Floating Point.
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
* @param pos On input: an alignment field, if desired.
@ -595,7 +595,7 @@ public:
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(const DigitList &number,
virtual UnicodeString& format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& status) const;

View File

@ -884,7 +884,7 @@ protected:
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(const DigitList &number,
virtual UnicodeString& format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const;
@ -906,7 +906,7 @@ protected:
* @return Reference to 'appendTo' parameter.
* @internal
*/
virtual UnicodeString& format(const DigitList &number,
virtual UnicodeString& format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& status) const;

View File

@ -23,6 +23,7 @@
#include "putilimp.h"
#include "plurrule_impl.h"
#include <stdio.h>
#include <number_decimalquantity.h>
// This is an API test, not a unit test. It doesn't test very many cases, and doesn't
// try to test the full functionality. It just calls each function in the class and
@ -613,171 +614,172 @@ void IntlTestDecimalFormatAPI::TestFixedDecimal() {
if (status == U_MISSING_RESOURCE_ERROR) {
return;
}
FixedDecimal fd = df->getFixedDecimal(44, status);
number::impl::DecimalQuantity fd;
df->formatToDecimalQuantity(44, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(44, fd.source);
ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(44, fd.getPluralOperand(PLURAL_OPERAND_N));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(FALSE, fd.isNegative());
fd = df->getFixedDecimal(-44, status);
df->formatToDecimalQuantity(-44, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(44, fd.source);
ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(TRUE, fd.isNegative);
ASSERT_EQUAL(44, fd.getPluralOperand(PLURAL_OPERAND_N));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(TRUE, fd.isNegative());
df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status), status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(123.456, status);
df->formatToDecimalQuantity(123.456, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
ASSERT_EQUAL(456, fd.decimalDigits); // f
ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
ASSERT_EQUAL(123, fd.intValue); // i
ASSERT_EQUAL(123.456, fd.source); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
ASSERT_EQUAL(123.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fd = df->getFixedDecimal(-123.456, status);
df->formatToDecimalQuantity(-123.456, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
ASSERT_EQUAL(456, fd.decimalDigits); // f
ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
ASSERT_EQUAL(123, fd.intValue); // i
ASSERT_EQUAL(123.456, fd.source); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(TRUE, fd.isNegative);
ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
ASSERT_EQUAL(123.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(TRUE, fd.isNegative());
// test max int digits
df->setMaximumIntegerDigits(2);
fd = df->getFixedDecimal(123.456, status);
df->formatToDecimalQuantity(123.456, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
ASSERT_EQUAL(456, fd.decimalDigits); // f
ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
ASSERT_EQUAL(23, fd.intValue); // i
ASSERT_EQUAL(23.456, fd.source); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
ASSERT_EQUAL(23.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fd = df->getFixedDecimal(-123.456, status);
df->formatToDecimalQuantity(-123.456, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
ASSERT_EQUAL(456, fd.decimalDigits); // f
ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
ASSERT_EQUAL(23, fd.intValue); // i
ASSERT_EQUAL(23.456, fd.source); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(TRUE, fd.isNegative);
ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
ASSERT_EQUAL(23.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(TRUE, fd.isNegative());
// test max fraction digits
df->setMaximumIntegerDigits(2000000000);
df->setMaximumFractionDigits(2);
fd = df->getFixedDecimal(123.456, status);
df->formatToDecimalQuantity(123.456, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
ASSERT_EQUAL(46, fd.decimalDigits); // f
ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t
ASSERT_EQUAL(123, fd.intValue); // i
ASSERT_EQUAL(123.46, fd.source); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
ASSERT_EQUAL(123.46, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fd = df->getFixedDecimal(-123.456, status);
df->formatToDecimalQuantity(-123.456, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
ASSERT_EQUAL(46, fd.decimalDigits); // f
ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t
ASSERT_EQUAL(123, fd.intValue); // i
ASSERT_EQUAL(123.46, fd.source); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(TRUE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
ASSERT_EQUAL(123.46, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(TRUE, fd.isNegative());
// test esoteric rounding
df->setMaximumFractionDigits(6);
df->setRoundingIncrement(7.3);
fd = df->getFixedDecimal(30.0, status);
df->formatToDecimalQuantity(30.0, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
ASSERT_EQUAL(20, fd.decimalDigits); // f
ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t
ASSERT_EQUAL(29, fd.intValue); // i
ASSERT_EQUAL(29.2, fd.source); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
ASSERT_EQUAL(20, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
ASSERT_EQUAL(29, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
ASSERT_EQUAL(29.2, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fd = df->getFixedDecimal(-30.0, status);
df->formatToDecimalQuantity(-30.0, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
ASSERT_EQUAL(20, fd.decimalDigits); // f
ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t
ASSERT_EQUAL(29, fd.intValue); // i
ASSERT_EQUAL(29.2, fd.source); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(TRUE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
ASSERT_EQUAL(20, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
ASSERT_EQUAL(29, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
ASSERT_EQUAL(29.2, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(TRUE, fd.isNegative());
df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status), status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(123.456, status);
df->formatToDecimalQuantity(123.456, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(0, fd.decimalDigits);
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(123, fd.intValue);
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(123.01, status);
df->formatToDecimalQuantity(123.01, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(1, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(0, fd.decimalDigits);
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(123, fd.intValue);
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(123.06, status);
df->formatToDecimalQuantity(123.06, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(1, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(1, fd.decimalDigits);
ASSERT_EQUAL(1, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(123, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(123, status);
df->formatToDecimalQuantity(123, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(0, fd.decimalDigits);
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(123, fd.intValue);
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(1.23, status);
df->formatToDecimalQuantity(1.23, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(4, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(2300, fd.decimalDigits);
ASSERT_EQUAL(23, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(1, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(4, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(2300, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fd = df->getFixedDecimal(uprv_getInfinity(), status);
df->formatToDecimalQuantity(uprv_getInfinity(), fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(TRUE, fd.isNanOrInfinity());
fd = df->getFixedDecimal(0.0, status);
ASSERT_EQUAL(FALSE, fd.isNanOrInfinity());
fd = df->getFixedDecimal(uprv_getNaN(), status);
ASSERT_EQUAL(TRUE, fd.isNanOrInfinity());
ASSERT_EQUAL(TRUE, fd.isNaN() || fd.isInfinite());
df->formatToDecimalQuantity(0.0, fd, status);
ASSERT_EQUAL(FALSE, fd.isNaN() || fd.isInfinite());
df->formatToDecimalQuantity(uprv_getNaN(), fd, status);
ASSERT_EQUAL(TRUE, fd.isNaN() || fd.isInfinite());
TEST_ASSERT_STATUS(status);
// Test Big Decimal input.
@ -788,135 +790,141 @@ void IntlTestDecimalFormatAPI::TestFixedDecimal() {
TEST_ASSERT_STATUS(status);
Formattable fable("12.34", status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(34, fd.decimalDigits);
ASSERT_EQUAL(34, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(12, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(34, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(34, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fable.setDecimalNumber("12.345678901234567890123456789", status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(345678901234567890LL, fd.decimalDigits);
ASSERT_EQUAL(34567890123456789LL, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(12, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(345678901234567890LL, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(34567890123456789LL, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
// On field overflow, Integer part is truncated on the left, fraction part on the right.
fable.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(123456789012345678LL, fd.decimalDigits);
ASSERT_EQUAL(123456789012345678LL, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(345678901234567890LL, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(123456789012345678LL, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(123456789012345678LL, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(345678901234567890LL, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
// Digits way to the right of the decimal but within the format's precision aren't truncated
fable.setDecimalNumber("1.0000000000000000000012", status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(12, fd.decimalDigits);
ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(1, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
// Digits beyond the precision of the format are rounded away
fable.setDecimalNumber("1.000000000000000000000012", status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(0, fd.decimalDigits);
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(1, fd.intValue);
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
// Negative numbers come through
fable.setDecimalNumber("-1.0000000000000000000012", status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(12, fd.decimalDigits);
ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(1, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(TRUE, fd.isNegative);
ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(TRUE, fd.isNegative());
// MinFractionDigits from format larger than from number.
fable.setDecimalNumber("1000000000000000000000.3", status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(30, fd.decimalDigits);
ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(100000000000000000LL, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(30, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(100000000000000000LL, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fable.setDecimalNumber("1000000000000000050000.3", status);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(30, fd.decimalDigits);
ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(50000LL, fd.intValue);
ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(30, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(50000LL, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
// Test some int64_t values that are out of the range of a double
fable.setInt64(4503599627370496LL);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(0, fd.decimalDigits);
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(4503599627370496LL, fd.intValue);
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(4503599627370496LL, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fable.setInt64(4503599627370497LL);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(0, fd.decimalDigits);
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(4503599627370497LL, fd.intValue);
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
ASSERT_EQUAL(4503599627370497LL, fd.getPluralOperand(PLURAL_OPERAND_I));
ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
fable.setInt64(9223372036854775807LL);
TEST_ASSERT_STATUS(status);
fd = df->getFixedDecimal(fable, status);
df->formatToDecimalQuantity(fable, fd, status);
TEST_ASSERT_STATUS(status);
ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
ASSERT_EQUAL(0, fd.decimalDigits);
ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
// note: going through DigitList path to FixedDecimal, which is trimming
// int64_t fields to 18 digits. See ticket Ticket #10374
// ASSERT_EQUAL(223372036854775807LL, fd.intValue);
if (!(fd.intValue == 223372036854775807LL || fd.intValue == 9223372036854775807LL)) {
dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__, __LINE__, fd.intValue);
// ASSERT_EQUAL(223372036854775807LL, fd.getPluralOperand(PLURAL_OPERAND_I);
if (!(
fd.getPluralOperand(PLURAL_OPERAND_I) == 223372036854775807LL ||
fd.getPluralOperand(PLURAL_OPERAND_I) == 9223372036854775807LL)) {
dataerrln(
"File %s, Line %d, fd.getPluralOperand(PLURAL_OPERAND_I = %lld",
__FILE__,
__LINE__,
fd.getPluralOperand(PLURAL_OPERAND_I));
}
ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
ASSERT_EQUAL(FALSE, fd.isNegative);
ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
ASSERT_EQUAL(FALSE, fd.isNegative());
}

View File

@ -15,7 +15,6 @@
#include "charstr.h"
#include "cstring.h"
#include "cmemory.h"
#include "digitlst.h"
static NumberFormatTestTuple *gNullPtr = NULL;

View File

@ -23,7 +23,6 @@
#include "unicode/measfmt.h"
#include "unicode/curramt.h"
#include "unicode/strenum.h"
#include "digitlst.h"
#include "textfile.h"
#include "tokiter.h"
#include "charstr.h"
@ -40,6 +39,7 @@
#include "numberformattesttuple.h"
#include "datadrivennumberformattestsuite.h"
#include "unicode/msgfmt.h"
#include "number_decimalquantity.h"
#if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
// These should not be macros. If they are,
@ -62,6 +62,7 @@ namespace std {
#endif
#endif
using icu::number::impl::DecimalQuantity;
class NumberFormatTestDataDriven : public DataDrivenNumberFormatTestSuite {
protected:
@ -83,34 +84,34 @@ UBool isParseCurrencyPass(
UErrorCode &status);
};
static DigitList &strToDigitList(
static DecimalQuantity &strToDigitList(
const UnicodeString &str,
DigitList &digitList,
DecimalQuantity &digitList,
UErrorCode &status) {
if (U_FAILURE(status)) {
return digitList;
}
if (str == "NaN") {
digitList.set(uprv_getNaN());
digitList.setToDouble(uprv_getNaN());
return digitList;
}
if (str == "-Inf") {
digitList.set(-1*uprv_getInfinity());
digitList.setToDouble(-1*uprv_getInfinity());
return digitList;
}
if (str == "Inf") {
digitList.set(uprv_getInfinity());
digitList.setToDouble(uprv_getInfinity());
return digitList;
}
CharString formatValue;
formatValue.appendInvariantChars(str, status);
digitList.set(StringPiece(formatValue.data()), status, 0);
digitList.setToDecNumber(StringPiece(formatValue.data()));
return digitList;
}
static UnicodeString &format(
const DecimalFormat &fmt,
const DigitList &digitList,
const DecimalQuantity &digitList,
UnicodeString &appendTo,
UErrorCode &status) {
if (U_FAILURE(status)) {
@ -315,7 +316,7 @@ UBool NumberFormatTestDataDriven::isFormatPass(
if (appendErrorMessage.length() > 0) {
return FALSE;
}
DigitList digitList;
DecimalQuantity digitList;
strToDigitList(tuple.format, digitList, status);
{
UnicodeString appendTo;
@ -330,7 +331,7 @@ UBool NumberFormatTestDataDriven::isFormatPass(
return FALSE;
}
}
double doubleVal = digitList.getDouble();
double doubleVal = digitList.toDouble();
{
UnicodeString appendTo;
format(*fmtPtr, doubleVal, appendTo, status);
@ -345,7 +346,7 @@ UBool NumberFormatTestDataDriven::isFormatPass(
}
}
if (!uprv_isNaN(doubleVal) && !uprv_isInfinite(doubleVal) && doubleVal == uprv_floor(doubleVal)) {
int64_t intVal = digitList.getInt64();
int64_t intVal = digitList.toLong();
{
UnicodeString appendTo;
format(*fmtPtr, intVal, appendTo, status);
@ -446,13 +447,13 @@ UBool NumberFormatTestDataDriven::isParsePass(
}
return TRUE;
}
DigitList expected;
DecimalQuantity expected;
strToDigitList(tuple.output, expected, status);
if (U_FAILURE(status)) {
appendErrorMessage.append("Error parsing.");
return FALSE;
}
if (expected != *result.getDigitList()) {
if (expected != *result.getDecimalQuantity()) {
appendErrorMessage.append(UnicodeString("Expected: ") + tuple.output + ", but got: " + resultStr + " (" + ppos.getIndex() + ":" + ppos.getErrorIndex() + ")");
return FALSE;
}
@ -490,13 +491,13 @@ UBool NumberFormatTestDataDriven::isParseCurrencyPass(
appendErrorMessage.append(UnicodeString("Parse succeeded: ") + resultStr + ", but was expected to fail.");
return TRUE; // TRUE because failure handling is in the test suite
}
DigitList expected;
DecimalQuantity expected;
strToDigitList(tuple.output, expected, status);
if (U_FAILURE(status)) {
appendErrorMessage.append("Error parsing.");
return FALSE;
}
if (expected != *currAmt->getNumber().getDigitList()) {
if (expected != *currAmt->getNumber().getDecimalQuantity()) {
appendErrorMessage.append(UnicodeString("Expected: ") + tuple.output + ", but got: " + resultStr + " (" + ppos.getIndex() + ":" + ppos.getErrorIndex() + ")");
return FALSE;
}
@ -7024,9 +7025,9 @@ void NumberFormatTest::TestDecimal() {
dataerrln("Unable to create NumberFormat");
} else {
UnicodeString formattedResult;
DigitList dl;
DecimalQuantity dl;
StringPiece num("123.4566666666666666666666666666666666621E+40");
dl.set(num, status);
dl.setToDecNumber(num);
ASSERT_SUCCESS(status);
fmtr->format(dl, formattedResult, NULL, status);
ASSERT_SUCCESS(status);
@ -7034,7 +7035,7 @@ void NumberFormatTest::TestDecimal() {
status = U_ZERO_ERROR;
num.set("666.666");
dl.set(num, status);
dl.setToDecNumber(num);
FieldPosition pos(NumberFormat::FRACTION_FIELD);
ASSERT_SUCCESS(status);
formattedResult.remove();
@ -8671,14 +8672,6 @@ void NumberFormatTest::Test11868() {
}
}
void NumberFormatTest::Test10727_RoundingZero() {
DigitList d;
d.set(-0.0);
assertFalse("", d.isPositive());
d.round(3);
assertFalse("", d.isPositive());
}
void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
{
const UChar USD[] = {0x55, 0x53, 0x44, 0x0};

View File

@ -24,10 +24,12 @@
#include "unicode/stringpiece.h"
#include "cmemory.h"
#include "digitlst.h"
#include "plurrule_impl.h"
#include "plurults.h"
#include "uhash.h"
#include "number_decimalquantity.h"
using icu::number::impl::DecimalQuantity;
void setupResult(const int32_t testSource[], char result[], int32_t* max);
UBool checkEqual(const PluralRules &test, char *result, int32_t max);
@ -633,14 +635,14 @@ void PluralRulesTest::checkSelect(const LocalPointer<PluralRules> &rules, UError
}
// DigitList is a convenient way to parse the decimal number string and get a double.
DigitList dl;
dl.set(StringPiece(num), status);
DecimalQuantity dl;
dl.setToDecNumber(StringPiece(num));
if (U_FAILURE(status)) {
errln("file %s, line %d, ICU error status: %s.", __FILE__, line, u_errorName(status));
status = U_ZERO_ERROR;
continue;
}
double numDbl = dl.getDouble();
double numDbl = dl.toDouble();
const char *decimalPoint = strchr(num, '.');
int fractionDigitCount = decimalPoint == NULL ? 0 : (num + strlen(num) - 1) - decimalPoint;
int fractionDigits = fractionDigitCount == 0 ? 0 : atoi(decimalPoint + 1);

View File

@ -215,7 +215,6 @@ UObject *UObjectTest::testClassNoClassID(UObject *obj, const char *className, co
#include "rbt_data.h"
#include "nultrans.h"
#include "anytrans.h"
#include "digitlst.h"
#include "esctrn.h"
#include "funcrepl.h"
#include "servnotf.h"