mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
parent
a667b279d4
commit
6198151510
14 changed files with 323 additions and 22 deletions
|
@ -13,6 +13,7 @@
|
|||
#include "number_utypes.h"
|
||||
#include "numparse_types.h"
|
||||
#include "formattedval_impl.h"
|
||||
#include "number_decnum.h"
|
||||
#include "unicode/numberformatter.h"
|
||||
#include "unicode/unumberformatter.h"
|
||||
|
||||
|
@ -196,6 +197,23 @@ unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPosition
|
|||
result->fData.getAllFieldPositions(fpih, *ec);
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumf_resultToDecimalNumber(
|
||||
const UFormattedNumber* uresult,
|
||||
char* dest,
|
||||
int32_t destCapacity,
|
||||
UErrorCode* ec) {
|
||||
const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
|
||||
if (U_FAILURE(*ec)) {
|
||||
return 0;
|
||||
}
|
||||
DecNum decnum;
|
||||
return result->fData.quantity
|
||||
.toDecNum(decnum, *ec)
|
||||
.toCharString(*ec)
|
||||
.extract(dest, destCapacity, *ec);
|
||||
}
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
unumf_close(UNumberFormatter* f) {
|
||||
UErrorCode localStatus = U_ZERO_ERROR;
|
||||
|
|
|
@ -627,7 +627,7 @@ double DecimalQuantity::toDouble() const {
|
|||
&count);
|
||||
}
|
||||
|
||||
void DecimalQuantity::toDecNum(DecNum& output, UErrorCode& status) const {
|
||||
DecNum& DecimalQuantity::toDecNum(DecNum& output, UErrorCode& status) const {
|
||||
// Special handling for zero
|
||||
if (precision == 0) {
|
||||
output.setTo("0", status);
|
||||
|
@ -637,12 +637,13 @@ void DecimalQuantity::toDecNum(DecNum& output, UErrorCode& status) const {
|
|||
// The decNumber constructor expects most-significant first, but we store least-significant first.
|
||||
MaybeStackArray<uint8_t, 20> ubcd(precision, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
return output;
|
||||
}
|
||||
for (int32_t m = 0; m < precision; m++) {
|
||||
ubcd[precision - m - 1] = static_cast<uint8_t>(getDigitPos(m));
|
||||
}
|
||||
output.setTo(ubcd.getAlias(), precision, scale, isNegative(), status);
|
||||
return output;
|
||||
}
|
||||
|
||||
void DecimalQuantity::truncate() {
|
||||
|
|
|
@ -209,7 +209,7 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory {
|
|||
double toDouble() const;
|
||||
|
||||
/** Computes a DecNum representation of this DecimalQuantity, saving it to the output parameter. */
|
||||
void toDecNum(DecNum& output, UErrorCode& status) const;
|
||||
DecNum& toDecNum(DecNum& output, UErrorCode& status) const;
|
||||
|
||||
DecimalQuantity &setToInt(int32_t n);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "decNumber.h"
|
||||
#include "charstr.h"
|
||||
#include "bytesinkutil.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -57,6 +58,13 @@ class U_I18N_API DecNum : public UMemory {
|
|||
|
||||
void toString(ByteSink& output, UErrorCode& status) const;
|
||||
|
||||
inline CharString toCharString(UErrorCode& status) const {
|
||||
CharString cstr;
|
||||
CharStringByteSink sink(&cstr);
|
||||
toString(sink, status);
|
||||
return cstr;
|
||||
}
|
||||
|
||||
inline const decNumber* getRawDecNumber() const {
|
||||
return fData.getAlias();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "numparse_types.h"
|
||||
#include "formattedval_impl.h"
|
||||
#include "numrange_impl.h"
|
||||
#include "number_decnum.h"
|
||||
#include "unicode/numberrangeformatter.h"
|
||||
#include "unicode/unumberrangeformatter.h"
|
||||
|
||||
|
@ -138,6 +139,39 @@ unumrf_resultGetIdentityResult(
|
|||
return result->fData.identityResult;
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumrf_resultGetFirstDecimalNumber(
|
||||
const UFormattedNumberRange* uresult,
|
||||
char* dest,
|
||||
int32_t destCapacity,
|
||||
UErrorCode* ec) {
|
||||
const auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
|
||||
if (U_FAILURE(*ec)) {
|
||||
return 0;
|
||||
}
|
||||
DecNum decnum;
|
||||
return result->fData.quantity1.toDecNum(decnum, *ec)
|
||||
.toCharString(*ec)
|
||||
.extract(dest, destCapacity, *ec);
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumrf_resultGetSecondDecimalNumber(
|
||||
const UFormattedNumberRange* uresult,
|
||||
char* dest,
|
||||
int32_t destCapacity,
|
||||
UErrorCode* ec) {
|
||||
const auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
|
||||
if (U_FAILURE(*ec)) {
|
||||
return 0;
|
||||
}
|
||||
DecNum decnum;
|
||||
return result->fData.quantity2
|
||||
.toDecNum(decnum, *ec)
|
||||
.toCharString(*ec)
|
||||
.extract(dest, destCapacity, *ec);
|
||||
}
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
unumrf_close(UNumberRangeFormatter* f) {
|
||||
UErrorCode localStatus = U_ZERO_ERROR;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "numrange_impl.h"
|
||||
#include "util.h"
|
||||
#include "number_utypes.h"
|
||||
#include "number_decnum.h"
|
||||
|
||||
using namespace icu;
|
||||
using namespace icu::number;
|
||||
|
@ -389,6 +390,14 @@ UnicodeString FormattedNumberRange::getSecondDecimal(UErrorCode& status) const {
|
|||
return fData->quantity2.toScientificString();
|
||||
}
|
||||
|
||||
void FormattedNumberRange::getDecimalNumbers(ByteSink& sink1, ByteSink& sink2, UErrorCode& status) const {
|
||||
UPRV_FORMATTED_VALUE_METHOD_GUARD(UPRV_NOARG)
|
||||
impl::DecNum decnum1;
|
||||
impl::DecNum decnum2;
|
||||
fData->quantity1.toDecNum(decnum1, status).toString(sink1, status);
|
||||
fData->quantity2.toDecNum(decnum2, status).toString(sink2, status);
|
||||
}
|
||||
|
||||
UNumberRangeIdentityResult FormattedNumberRange::getIdentityResult(UErrorCode& status) const {
|
||||
UPRV_FORMATTED_VALUE_METHOD_GUARD(UNUM_IDENTITY_RESULT_NOT_EQUAL)
|
||||
return fData->identityResult;
|
||||
|
|
|
@ -2679,7 +2679,6 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
|
|||
explicit FormattedNumber(UErrorCode errorCode)
|
||||
: fData(nullptr), fErrorCode(errorCode) {}
|
||||
|
||||
// TODO(ICU-20775): Propose this as API.
|
||||
void toDecimalNumber(ByteSink& sink, UErrorCode& status) const;
|
||||
|
||||
// To give LocalizedNumberFormatter format methods access to this class's constructor:
|
||||
|
|
|
@ -605,18 +605,22 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
|
|||
/** @copydoc FormattedValue::nextPosition() */
|
||||
UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
#ifndef U_HIDE_DEPRECATED_API
|
||||
/**
|
||||
* Export the first formatted number as a decimal number. This endpoint
|
||||
* is useful for obtaining the exact number being printed after scaling
|
||||
* and rounding have been applied by the number range formatting pipeline.
|
||||
*
|
||||
*
|
||||
* The syntax of the unformatted number is a "numeric string"
|
||||
* as defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* TODO(ICU-21275): This function will be removed in ICU 69.
|
||||
* Use getDecimalNumbers() instead.
|
||||
*
|
||||
* @param status Set if an error occurs.
|
||||
* @return A decimal representation of the first formatted number.
|
||||
* @draft ICU 63
|
||||
* @deprecated ICU 68 Use getDecimalNumbers instead.
|
||||
* @see NumberRangeFormatter
|
||||
* @see #getSecondDecimal
|
||||
*/
|
||||
|
@ -626,17 +630,46 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
|
|||
* Export the second formatted number as a decimal number. This endpoint
|
||||
* is useful for obtaining the exact number being printed after scaling
|
||||
* and rounding have been applied by the number range formatting pipeline.
|
||||
*
|
||||
*
|
||||
* The syntax of the unformatted number is a "numeric string"
|
||||
* as defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* TODO(ICU-21275): This function will be removed in ICU 69.
|
||||
* Use getDecimalNumbers() instead.
|
||||
*
|
||||
* @param status Set if an error occurs.
|
||||
* @return A decimal representation of the second formatted number.
|
||||
* @draft ICU 63
|
||||
* @deprecated ICU 68 Use getDecimalNumbers instead.
|
||||
* @see NumberRangeFormatter
|
||||
* @see #getFirstDecimal
|
||||
*/
|
||||
UnicodeString getSecondDecimal(UErrorCode& status) const;
|
||||
#endif // U_HIDE_DEPRECATED_API
|
||||
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Extracts the formatted range as a pair of decimal numbers. This endpoint
|
||||
* is useful for obtaining the exact number being printed after scaling
|
||||
* and rounding have been applied by the number range formatting pipeline.
|
||||
*
|
||||
* The syntax of the unformatted numbers is a "numeric string"
|
||||
* as defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* Example C++17 call site:
|
||||
*
|
||||
* auto [ first, second ] = range.getDecimalNumbers<std::string>(status);
|
||||
*
|
||||
* @tparam StringClass A string class compatible with StringByteSink;
|
||||
* for example, std::string.
|
||||
* @param status Set if an error occurs.
|
||||
* @return A pair of StringClasses containing the numeric strings.
|
||||
* @draft ICU 68
|
||||
*/
|
||||
template<typename StringClass>
|
||||
inline std::pair<StringClass, StringClass> getDecimalNumbers(UErrorCode& status) const;
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
/**
|
||||
|
@ -698,6 +731,8 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
|
|||
|
||||
void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
|
||||
|
||||
void getDecimalNumbers(ByteSink& sink1, ByteSink& sink2, UErrorCode& status) const;
|
||||
|
||||
// To give LocalizedNumberRangeFormatter format methods access to this class's constructor:
|
||||
friend class LocalizedNumberRangeFormatter;
|
||||
|
||||
|
@ -705,6 +740,19 @@ class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
|
|||
friend struct impl::UFormattedNumberRangeImpl;
|
||||
};
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
// Note: This is draft ICU 68
|
||||
template<typename StringClass>
|
||||
std::pair<StringClass, StringClass> FormattedNumberRange::getDecimalNumbers(UErrorCode& status) const {
|
||||
StringClass str1;
|
||||
StringClass str2;
|
||||
StringByteSink<StringClass> sink1(&str1);
|
||||
StringByteSink<StringClass> sink2(&str2);
|
||||
getDecimalNumbers(sink1, sink2, status);
|
||||
return std::make_pair(str1, str2);
|
||||
}
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
/**
|
||||
* See the main description in numberrangeformatter.h for documentation and examples.
|
||||
*
|
||||
|
|
|
@ -659,11 +659,32 @@ unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPosition
|
|||
UErrorCode* ec);
|
||||
|
||||
|
||||
// TODO(ICU-20775): Propose this as API.
|
||||
// NOTE: This is not currently implemented.
|
||||
// U_CAPI int32_t U_EXPORT2
|
||||
// unumf_resultToDecimalNumber(const UFormattedNumber* uresult, char* buffer, int32_t bufferCapacity,
|
||||
// UErrorCode* ec);
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Extracts the formatted number as a "numeric string" conforming to the
|
||||
* syntax defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* This endpoint is useful for obtaining the exact number being printed
|
||||
* after scaling and rounding have been applied by the number formatter.
|
||||
*
|
||||
* @param uresult The input object containing the formatted number.
|
||||
* @param dest the 8-bit char buffer into which the decimal number is placed
|
||||
* @param destCapacity The size, in chars, of the destination buffer. May be zero
|
||||
* for precomputing the required size.
|
||||
* @param ec receives any error status.
|
||||
* If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
|
||||
* preflighting.
|
||||
* @return Number of chars in the data. Does not include a trailing NUL.
|
||||
* @draft ICU 68
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumf_resultToDecimalNumber(
|
||||
const UFormattedNumber* uresult,
|
||||
char* dest,
|
||||
int32_t destCapacity,
|
||||
UErrorCode* ec);
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -354,15 +354,60 @@ unumrf_resultGetIdentityResult(
|
|||
UErrorCode* ec);
|
||||
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Extracts the first formatted number as a decimal number. This endpoint
|
||||
* is useful for obtaining the exact number being printed after scaling
|
||||
* and rounding have been applied by the number range formatting pipeline.
|
||||
*
|
||||
* The syntax of the unformatted number is a "numeric string"
|
||||
* as defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* @param uresult The input object containing the formatted number range.
|
||||
* @param dest the 8-bit char buffer into which the decimal number is placed
|
||||
* @param destCapacity The size, in chars, of the destination buffer. May be zero
|
||||
* for precomputing the required size.
|
||||
* @param ec receives any error status.
|
||||
* If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
|
||||
* preflighting.
|
||||
* @return Number of chars in the data. Does not include a trailing NUL.
|
||||
* @draft ICU 68
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumrf_resultGetFirstDecimalNumber(
|
||||
const UFormattedNumberRange* uresult,
|
||||
char* dest,
|
||||
int32_t destCapacity,
|
||||
UErrorCode* ec);
|
||||
|
||||
// TODO(ICU-20775): Propose these as API.
|
||||
// NOTE: This is not currently implemented.
|
||||
// U_CAPI int32_t U_EXPORT2
|
||||
// unumf_resultGetFirstDecimal(const UFormattedNumberRange* uresult, char* buffer, int32_t bufferCapacity,
|
||||
// UErrorCode* ec);
|
||||
// U_CAPI int32_t U_EXPORT2
|
||||
// unumf_resultGetSecondDecimal(const UFormattedNumberRange* uresult, char* buffer, int32_t bufferCapacity,
|
||||
// UErrorCode* ec);
|
||||
|
||||
/**
|
||||
* Extracts the second formatted number as a decimal number. This endpoint
|
||||
* is useful for obtaining the exact number being printed after scaling
|
||||
* and rounding have been applied by the number range formatting pipeline.
|
||||
*
|
||||
* The syntax of the unformatted number is a "numeric string"
|
||||
* as defined in the Decimal Arithmetic Specification, available at
|
||||
* http://speleotrove.com/decimal
|
||||
*
|
||||
* @param uresult The input object containing the formatted number range.
|
||||
* @param dest the 8-bit char buffer into which the decimal number is placed
|
||||
* @param destCapacity The size, in chars, of the destination buffer. May be zero
|
||||
* for precomputing the required size.
|
||||
* @param ec receives any error status.
|
||||
* If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
|
||||
* preflighting.
|
||||
* @return Number of chars in the data. Does not include a trailing NUL.
|
||||
* @draft ICU 68
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
unumrf_resultGetSecondDecimalNumber(
|
||||
const UFormattedNumberRange* uresult,
|
||||
char* dest,
|
||||
int32_t destCapacity,
|
||||
UErrorCode* ec);
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,8 @@ static void TestFormattedValue(void);
|
|||
|
||||
static void TestSkeletonParseError(void);
|
||||
|
||||
static void TestToDecimalNumber(void);
|
||||
|
||||
static void TestPerUnitInArabic(void);
|
||||
|
||||
void addUNumberFormatterTest(TestNode** root);
|
||||
|
@ -40,6 +42,7 @@ void addUNumberFormatterTest(TestNode** root) {
|
|||
TESTCASE(TestExampleCode);
|
||||
TESTCASE(TestFormattedValue);
|
||||
TESTCASE(TestSkeletonParseError);
|
||||
TESTCASE(TestToDecimalNumber);
|
||||
TESTCASE(TestPerUnitInArabic);
|
||||
}
|
||||
|
||||
|
@ -259,6 +262,35 @@ static void TestSkeletonParseError() {
|
|||
unumf_close(uformatter);
|
||||
}
|
||||
|
||||
|
||||
static void TestToDecimalNumber() {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
UNumberFormatter* uformatter = unumf_openForSkeletonAndLocale(
|
||||
u"currency/USD",
|
||||
-1,
|
||||
"en-US",
|
||||
&ec);
|
||||
assertSuccessCheck("Should create without error", &ec, TRUE);
|
||||
UFormattedNumber* uresult = unumf_openResult(&ec);
|
||||
assertSuccess("Should create result without error", &ec);
|
||||
|
||||
unumf_formatDouble(uformatter, 3.0, uresult, &ec);
|
||||
const UChar* str = ufmtval_getString(unumf_resultAsValue(uresult, &ec), NULL, &ec);
|
||||
assertSuccessCheck("Formatting should succeed", &ec, TRUE);
|
||||
assertUEquals("Should produce expected string result", u"$3.00", str);
|
||||
|
||||
char buffer[CAPACITY];
|
||||
|
||||
int32_t len = unumf_resultToDecimalNumber(uresult, buffer, CAPACITY, &ec);
|
||||
assertIntEquals("Length should be as expected", strlen(buffer), len);
|
||||
assertEquals("Decimal should be as expected", "3", buffer);
|
||||
|
||||
// cleanup:
|
||||
unumf_closeResult(uresult);
|
||||
unumf_close(uformatter);
|
||||
}
|
||||
|
||||
|
||||
static void TestPerUnitInArabic() {
|
||||
const char* simpleMeasureUnits[] = {
|
||||
"area-acre",
|
||||
|
|
|
@ -25,6 +25,8 @@ static void TestFormattedValue(void);
|
|||
|
||||
static void TestSkeletonParseError(void);
|
||||
|
||||
static void TestGetDecimalNumbers(void);
|
||||
|
||||
void addUNumberRangeFormatterTest(TestNode** root);
|
||||
|
||||
#define TESTCASE(x) addTest(root, &x, "tsformat/unumberrangeformatter/" #x)
|
||||
|
@ -33,9 +35,13 @@ void addUNumberRangeFormatterTest(TestNode** root) {
|
|||
TESTCASE(TestExampleCode);
|
||||
TESTCASE(TestFormattedValue);
|
||||
TESTCASE(TestSkeletonParseError);
|
||||
TESTCASE(TestGetDecimalNumbers);
|
||||
}
|
||||
|
||||
|
||||
#define CAPACITY 30
|
||||
|
||||
|
||||
static void TestExampleCode() {
|
||||
// This is the example code given in unumberrangeformatter.h.
|
||||
|
||||
|
@ -61,6 +67,7 @@ static void TestExampleCode() {
|
|||
const UChar* str = ufmtval_getString(unumrf_resultAsValue(uresult, &ec), &len, &ec);
|
||||
assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
|
||||
assertUEquals("Should produce expected string result", u"$3 – $5", str);
|
||||
assertIntEquals("Length should be as expected", u_strlen(str), len);
|
||||
|
||||
// Cleanup:
|
||||
unumrf_close(uformatter);
|
||||
|
@ -149,4 +156,39 @@ static void TestSkeletonParseError() {
|
|||
unumrf_close(uformatter);
|
||||
}
|
||||
|
||||
|
||||
static void TestGetDecimalNumbers() {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
UNumberRangeFormatter* uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
|
||||
u"currency/USD",
|
||||
-1,
|
||||
UNUM_RANGE_COLLAPSE_AUTO,
|
||||
UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
|
||||
"en-US",
|
||||
NULL,
|
||||
&ec);
|
||||
assertSuccessCheck("Should create without error", &ec, TRUE);
|
||||
UFormattedNumberRange* uresult = unumrf_openResult(&ec);
|
||||
assertSuccess("Should create result without error", &ec);
|
||||
|
||||
unumrf_formatDoubleRange(uformatter, 3.0, 5.0, uresult, &ec);
|
||||
const UChar* str = ufmtval_getString(unumrf_resultAsValue(uresult, &ec), NULL, &ec);
|
||||
assertSuccessCheck("Formatting should succeed", &ec, TRUE);
|
||||
assertUEquals("Should produce expected string result", u"$3.00 \u2013 $5.00", str);
|
||||
|
||||
char buffer[CAPACITY];
|
||||
|
||||
int32_t len = unumrf_resultGetFirstDecimalNumber(uresult, buffer, CAPACITY, &ec);
|
||||
assertIntEquals("First len should be as expected", strlen(buffer), len);
|
||||
assertEquals("First decimal should be as expected", "3", buffer);
|
||||
|
||||
len = unumrf_resultGetSecondDecimalNumber(uresult, buffer, CAPACITY, &ec);
|
||||
assertIntEquals("Second len should be as expected", strlen(buffer), len);
|
||||
assertEquals("Second decimal should be as expected", "5", buffer);
|
||||
|
||||
// cleanup:
|
||||
unumrf_closeResult(uresult);
|
||||
unumrf_close(uformatter);
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -286,6 +286,7 @@ class NumberRangeFormatterTest : public IntlTestWithFieldPosition {
|
|||
void testFieldPositions();
|
||||
void testCopyMove();
|
||||
void toObject();
|
||||
void testGetDecimalNumbers();
|
||||
|
||||
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ void NumberRangeFormatterTest::runIndexedTest(int32_t index, UBool exec, const c
|
|||
TESTCASE_AUTO(testFieldPositions);
|
||||
TESTCASE_AUTO(testCopyMove);
|
||||
TESTCASE_AUTO(toObject);
|
||||
TESTCASE_AUTO(testGetDecimalNumbers);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
|
@ -860,6 +861,48 @@ void NumberRangeFormatterTest::toObject() {
|
|||
}
|
||||
}
|
||||
|
||||
void NumberRangeFormatterTest::testGetDecimalNumbers() {
|
||||
IcuTestErrorCode status(*this, "testGetDecimalNumbers");
|
||||
|
||||
LocalizedNumberRangeFormatter lnf = NumberRangeFormatter::withLocale("en")
|
||||
.numberFormatterBoth(NumberFormatter::with().unit(USD));
|
||||
|
||||
// Range of numbers
|
||||
{
|
||||
FormattedNumberRange range = lnf.formatFormattableRange(1, 5, status);
|
||||
assertEquals("Range: Formatted string should be as expected",
|
||||
u"$1.00 \u2013 $5.00",
|
||||
range.toString(status));
|
||||
auto decimalNumbers = range.getDecimalNumbers<std::string>(status);
|
||||
// TODO(ICU-21281): DecNum doesn't retain trailing zeros. Is that a problem?
|
||||
if (logKnownIssue("ICU-21281")) {
|
||||
assertEquals("First decimal number", "1", decimalNumbers.first.c_str());
|
||||
assertEquals("Second decimal number", "5", decimalNumbers.second.c_str());
|
||||
} else {
|
||||
assertEquals("First decimal number", "1.00", decimalNumbers.first.c_str());
|
||||
assertEquals("Second decimal number", "5.00", decimalNumbers.second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Identity fallback
|
||||
{
|
||||
FormattedNumberRange range = lnf.formatFormattableRange(3, 3, status);
|
||||
assertEquals("Identity: Formatted string should be as expected",
|
||||
u"~$3.00",
|
||||
range.toString(status));
|
||||
auto decimalNumbers = range.getDecimalNumbers<std::string>(status);
|
||||
// NOTE: DecNum doesn't retain trailing zeros. Is that a problem?
|
||||
// TODO(ICU-21281): DecNum doesn't retain trailing zeros. Is that a problem?
|
||||
if (logKnownIssue("ICU-21281")) {
|
||||
assertEquals("First decimal number", "3", decimalNumbers.first.c_str());
|
||||
assertEquals("Second decimal number", "3", decimalNumbers.second.c_str());
|
||||
} else {
|
||||
assertEquals("First decimal number", "3.00", decimalNumbers.first.c_str());
|
||||
assertEquals("Second decimal number", "3.00", decimalNumbers.second.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NumberRangeFormatterTest::assertFormatRange(
|
||||
const char16_t* message,
|
||||
const UnlocalizedNumberRangeFormatter& f,
|
||||
|
|
Loading…
Add table
Reference in a new issue