// from parsing, or from the user setting a decimal number, fDecimalNum
// would already be set.
//
- fDecimalQuantity = new DecimalQuantity(); // TODO: use internal digit list
- if (fDecimalQuantity == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
-
- switch (fType) {
- case kDouble:
- fDecimalQuantity->setToDouble(this->getDouble());
- fDecimalQuantity->roundToInfinity();
- break;
- case kLong:
- fDecimalQuantity->setToInt(this->getLong());
- break;
- case kInt64:
- fDecimalQuantity->setToLong(this->getInt64());
- break;
- default:
- // The formattable's value is not a numeric type.
- status = U_INVALID_STATE_ERROR;
- return NULL;
- }
+ LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status);
+ if (U_FAILURE(status)) { return nullptr; }
+ populateDecimalQuantity(*dq, status);
+ if (U_FAILURE(status)) { return nullptr; }
+ fDecimalQuantity = dq.orphan();
}
fDecimalStr = new CharString();
return fDecimalStr;
}
+void
+Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const {
+ if (fDecimalQuantity != nullptr) {
+ output = *fDecimalQuantity;
+ return;
+ }
+
+ switch (fType) {
+ case kDouble:
+ output.setToDouble(this->getDouble());
+ output.roundToInfinity();
+ break;
+ case kLong:
+ output.setToInt(this->getLong());
+ break;
+ case kInt64:
+ output.setToLong(this->getInt64());
+ break;
+ default:
+ // The formattable's value is not a numeric type.
+ status = U_INVALID_STATE_ERROR;
+ }
+}
+
// ---------------------------------------
void
Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
#include "uassert.h"
#include "uhash.h"
#include "number_decimalquantity.h"
+#include "number_utils.h"
+#include "number_utypes.h"
#if !UCONFIG_NO_FORMATTING
if (msgPattern.countParts() == 0) {
return numberFormat->format(numberObject, appendTo, pos, status);
}
+
// Get the appropriate sub-message.
// Select it based on the formatted number-offset.
double numberMinusOffset = number - offset;
- UnicodeString numberString;
- DecimalQuantity quantity;
- FieldPosition ignorePos;
+ // Call NumberFormatter to get both the DecimalQuantity and the string.
+ // This call site needs to use more internal APIs than the Java equivalent.
+ number::impl::UFormattedNumberData data;
if (offset == 0) {
- DecimalFormat *decFmt = dynamic_cast<DecimalFormat *>(numberFormat);
- if(decFmt != NULL) {
- decFmt->formatToDecimalQuantity(numberObject, quantity, status);
- } else {
- numberFormat->format(
- numberObject, numberString, ignorePos, status); // could be BigDecimal etc.
- quantity.setToDouble(numberMinusOffset);
- quantity.roundToInfinity();
- }
+ // could be BigDecimal etc.
+ numberObject.populateDecimalQuantity(data.quantity, status);
} else {
- DecimalFormat *decFmt = dynamic_cast<DecimalFormat *>(numberFormat);
- if(decFmt != NULL) {
- decFmt->formatToDecimalQuantity(numberMinusOffset, quantity, status);
+ data.quantity.setToDouble(numberMinusOffset);
+ }
+ UnicodeString numberString;
+ auto *decFmt = dynamic_cast<DecimalFormat *>(numberFormat);
+ if(decFmt != nullptr) {
+ decFmt->toNumberFormatter().formatImpl(&data, status); // mutates &data
+ numberString = data.string.toUnicodeString();
+ } else {
+ if (offset == 0) {
+ numberFormat->format(numberObject, numberString, status);
} else {
- numberFormat->format(
- numberMinusOffset, numberString, ignorePos, status);
- quantity.setToDouble(numberMinusOffset);
- quantity.roundToInfinity();
+ numberFormat->format(numberMinusOffset, numberString, status);
}
}
- int32_t partIndex = findSubMessage(msgPattern, 0, pluralRulesWrapper, &quantity, number, status);
+
+ int32_t partIndex = findSubMessage(msgPattern, 0, pluralRulesWrapper, &data.quantity, number, status);
if (U_FAILURE(status)) { return appendTo; }
// Replace syntactic # signs in the top level of this sub-message
// (not in nested arguments) with the formatted number-offset.
*/
number::impl::DecimalQuantity *getDecimalQuantity() const { return fDecimalQuantity;}
+ /**
+ * Export the value of this Formattable to a DecimalQuantity.
+ * @internal
+ */
+ void populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const;
+
/**
* Adopt, and set value from, a DecimalQuantity
* Internal Function, do not use.
PluralFormat* plFmt[8];
Locale locale = Locale::getDefault();
UnicodeString otherPattern = UnicodeString("other{#}");
- UnicodeString message=UnicodeString("ERROR: PluralFormat basic test");
+ UnicodeString message=UnicodeString("PluralFormat basic test");
// ========= Test constructors
logln(" Testing PluralFormat constructors ...");
}
void
-PluralFormatTest::numberFormatTest(PluralFormat* plFmt,
+PluralFormatTest::numberFormatTest(PluralFormat* plFmt,
NumberFormat *numFmt,
int32_t start,
int32_t end,
}
}
}
- if ( (numResult!=plResult) || U_FAILURE(status) ) {
+ if (U_FAILURE(status)) {
+ assertSuccess(*message + " in numberFormatTest", status);
+ }
+ if (numResult!=plResult) {
if ( message == NULL ) {
errln("ERROR: Unexpected plural format - got:"+plResult+ UnicodeString(" expecting:")+numResult);
}
else {
- errln( *message+UnicodeString(" got:")+plResult+UnicodeString(" expecting:")+numResult);
+ assertEquals(*message + " in numberFormatTest", numResult, plResult);
}
}
}
}
public DecimalQuantity_DualStorageBCD(Number number) {
+ // NOTE: Number type expansion happens both here
+ // and in NumberFormat.java
if (number instanceof Long) {
setToLong(number.longValue());
} else if (number instanceof Integer) {
public StringBuffer format(Object number,
StringBuffer toAppendTo,
FieldPosition pos) {
+ // NOTE: Number type expansion happens both here
+ // and in DecimalQuantity_DualStorageBCD.java
if (number instanceof Long) {
return format(((Long)number).longValue(), toAppendTo, pos);
} else if (number instanceof BigInteger) {
import java.util.Map;
import com.ibm.icu.impl.Utility;
+import com.ibm.icu.number.FormattedNumber;
+import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.text.PluralRules.FixedDecimal;
import com.ibm.icu.text.PluralRules.IFixedDecimal;
import com.ibm.icu.text.PluralRules.PluralType;
// Select it based on the formatted number-offset.
double numberMinusOffset = number - offset;
String numberString;
- if (offset == 0) {
- numberString = numberFormat.format(numberObject); // could be BigDecimal etc.
- } else {
- numberString = numberFormat.format(numberMinusOffset);
- }
IFixedDecimal dec;
if(numberFormat instanceof DecimalFormat) {
- dec = ((DecimalFormat) numberFormat).getFixedDecimal(numberMinusOffset);
+ // Call NumberFormatter to get both the DecimalQuantity and the string.
+ LocalizedNumberFormatter f = ((DecimalFormat) numberFormat).toNumberFormatter();
+ FormattedNumber result;
+ if (offset == 0) {
+ // could be BigDecimal etc.
+ result = f.format(numberObject);
+ } else {
+ result = f.format(numberMinusOffset);
+ }
+ numberString = result.toString();
+ dec = result.getFixedDecimal();
} else {
+ if (offset == 0) {
+ numberString = numberFormat.format(numberObject);
+ } else {
+ numberString = numberFormat.format(numberMinusOffset);
+ }
dec = new FixedDecimal(numberMinusOffset);
}
+
int partIndex = findSubMessage(msgPattern, 0, pluralRulesWrapper, dec, number);
// Replace syntactic # signs in the top level of this sub-message
// (not in nested arguments) with the formatted number-offset.