mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-20844 remove restriction on minInt=minFrac=0, ensure doFastFormatInt32
and NumberFormatterImpl::writeNumber produce at least 1 result digit (#917)
This commit is contained in:
parent
afbd1b91d9
commit
ceb84b5dde
5 changed files with 111 additions and 5 deletions
|
@ -1834,7 +1834,8 @@ void DecimalFormat::doFastFormatInt32(int32_t input, bool isNegative, UnicodeStr
|
|||
char16_t localBuffer[localCapacity];
|
||||
char16_t* ptr = localBuffer + localCapacity;
|
||||
int8_t group = 0;
|
||||
for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < fields->fastData.minInt); i++) {
|
||||
int8_t minInt = (fields->fastData.minInt < 1)? 1: fields->fastData.minInt;
|
||||
for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < minInt); i++) {
|
||||
if (group++ == 3 && fields->fastData.cpGroupingSeparator != 0) {
|
||||
*(--ptr) = fields->fastData.cpGroupingSeparator;
|
||||
group = 1;
|
||||
|
|
|
@ -509,6 +509,12 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti
|
|||
|
||||
// Add the fraction digits
|
||||
length += writeFractionDigits(micros, quantity, string, length + index, status);
|
||||
|
||||
if (length == 0) {
|
||||
// Force output of the digit for value 0
|
||||
length += utils::insertDigitFromSymbols(
|
||||
string, index, 0, *micros.symbols, UNUM_INTEGER_FIELD, status);
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
|
|
|
@ -125,10 +125,8 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert
|
|||
}
|
||||
// Validate min/max int/frac.
|
||||
// For backwards compatibility, minimum overrides maximum if the two conflict.
|
||||
// The following logic ensures that there is always a minimum of at least one digit.
|
||||
if (minInt == 0 && maxFrac != 0) {
|
||||
// Force a digit after the decimal point.
|
||||
minFrac = minFrac <= 0 ? 1 : minFrac;
|
||||
minFrac = (minFrac < 0 || (minFrac == 0 && maxInt == 0)) ? 1 : minFrac;
|
||||
maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac;
|
||||
minInt = 0;
|
||||
maxInt = maxInt < 0 ? -1 : maxInt > kMaxIntFracSig ? -1 : maxInt;
|
||||
|
|
|
@ -74,6 +74,7 @@ static void TestParseCases(void);
|
|||
static void TestSetMaxFracAndRoundIncr(void);
|
||||
static void TestIgnorePadding(void);
|
||||
static void TestSciNotationMaxFracCap(void);
|
||||
static void TestMinIntMinFracZero(void);
|
||||
|
||||
#define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
|
||||
|
||||
|
@ -114,6 +115,7 @@ void addNumForTest(TestNode** root)
|
|||
TESTCASE(TestSetMaxFracAndRoundIncr);
|
||||
TESTCASE(TestIgnorePadding);
|
||||
TESTCASE(TestSciNotationMaxFracCap);
|
||||
TESTCASE(TestMinIntMinFracZero);
|
||||
}
|
||||
|
||||
/* test Parse int 64 */
|
||||
|
@ -3475,4 +3477,103 @@ static void TestSciNotationMaxFracCap(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void TestMinIntMinFracZero(void) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UNumberFormat* unum = unum_open(UNUM_DECIMAL, NULL, 0, "en_US", NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_data_err("unum_open UNUM_DECIMAL for en_US fails with %s\n", u_errorName(status));
|
||||
} else {
|
||||
UChar ubuf[kUBufMax];
|
||||
char bbuf[kBBufMax];
|
||||
int minInt, minFrac, ulen;
|
||||
|
||||
unum_setAttribute(unum, UNUM_MIN_INTEGER_DIGITS, 0);
|
||||
unum_setAttribute(unum, UNUM_MIN_FRACTION_DIGITS, 0);
|
||||
minInt = unum_getAttribute(unum, UNUM_MIN_INTEGER_DIGITS);
|
||||
minFrac = unum_getAttribute(unum, UNUM_MIN_FRACTION_DIGITS);
|
||||
if (minInt != 0 || minFrac != 0) {
|
||||
log_err("after setting minInt=minFrac=0, get minInt %d, minFrac %d\n", minInt, minFrac);
|
||||
}
|
||||
|
||||
ulen = unum_toPattern(unum, FALSE, ubuf, kUBufMax, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("unum_toPattern fails with %s\n", u_errorName(status));
|
||||
} else if (ulen < 3 || u_strstr(ubuf, u"#.#")==NULL) {
|
||||
u_austrncpy(bbuf, ubuf, kUBufMax);
|
||||
log_info("after setting minInt=minFrac=0, expect pattern to contain \"#.#\", but get (%d): \"%s\"\n", ulen, bbuf);
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ulen = unum_formatDouble(unum, 10.0, ubuf, kUBufMax, NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("unum_formatDouble 10.0 ulen %d fails with %s\n", ulen, u_errorName(status));
|
||||
} else if (u_strcmp(ubuf, u"10") != 0) {
|
||||
u_austrncpy(bbuf, ubuf, kUBufMax);
|
||||
log_err("unum_formatDouble 10.0 expected \"10\", got \"%s\"\n", bbuf);
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ulen = unum_formatDouble(unum, 0.9, ubuf, kUBufMax, NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("unum_formatDouble 0.9 ulen %d fails with %s\n", ulen, u_errorName(status));
|
||||
} else if (u_strcmp(ubuf, u".9") != 0) {
|
||||
u_austrncpy(bbuf, ubuf, kUBufMax);
|
||||
log_err("unum_formatDouble 0.9 expected \".9\", got \"%s\"\n", bbuf);
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ulen = unum_formatDouble(unum, 0.0, ubuf, kUBufMax, NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("unum_formatDouble 0.0 ulen %d fails with %s\n", ulen, u_errorName(status));
|
||||
} else if (u_strcmp(ubuf, u"0") != 0) {
|
||||
u_austrncpy(bbuf, ubuf, kUBufMax);
|
||||
log_err("unum_formatDouble 0.0 expected \"0\", got \"%s\"\n", bbuf);
|
||||
}
|
||||
|
||||
unum_close(unum);
|
||||
status = U_ZERO_ERROR;
|
||||
unum = unum_open(UNUM_CURRENCY, NULL, 0, "en_US", NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_data_err("unum_open UNUM_CURRENCY for en_US fails with %s\n", u_errorName(status));
|
||||
} else {
|
||||
unum_setAttribute(unum, UNUM_MIN_INTEGER_DIGITS, 0);
|
||||
unum_setAttribute(unum, UNUM_MIN_FRACTION_DIGITS, 0);
|
||||
minInt = unum_getAttribute(unum, UNUM_MIN_INTEGER_DIGITS);
|
||||
minFrac = unum_getAttribute(unum, UNUM_MIN_FRACTION_DIGITS);
|
||||
if (minInt != 0 || minFrac != 0) {
|
||||
log_err("after setting CURRENCY minInt=minFrac=0, get minInt %d, minFrac %d\n", minInt, minFrac);
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ulen = unum_formatDouble(unum, 10.0, ubuf, kUBufMax, NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("unum_formatDouble (CURRRENCY) 10.0 ulen %d fails with %s\n", ulen, u_errorName(status));
|
||||
} else if (u_strcmp(ubuf, u"$10") != 0) {
|
||||
u_austrncpy(bbuf, ubuf, kUBufMax);
|
||||
log_err("unum_formatDouble (CURRRENCY) 10.0 expected \"$10\", got \"%s\"\n", bbuf);
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ulen = unum_formatDouble(unum, 0.9, ubuf, kUBufMax, NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("unum_formatDouble (CURRRENCY) 0.9 ulen %d fails with %s\n", ulen, u_errorName(status));
|
||||
} else if (u_strcmp(ubuf, u"$.9") != 0) {
|
||||
u_austrncpy(bbuf, ubuf, kUBufMax);
|
||||
log_err("unum_formatDouble (CURRRENCY) 0.9 expected \"$.9\", got \"%s\"\n", bbuf);
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ulen = unum_formatDouble(unum, 0.0, ubuf, kUBufMax, NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_err("unum_formatDouble (CURRRENCY) 0.0 ulen %d fails with %s\n", ulen, u_errorName(status));
|
||||
} else if (u_strcmp(ubuf, u"$0") != 0) {
|
||||
u_austrncpy(bbuf, ubuf, kUBufMax);
|
||||
log_err("unum_formatDouble (CURRRENCY) 0.0 expected \"$0\", got \"%s\"\n", bbuf);
|
||||
}
|
||||
|
||||
unum_close(unum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -1648,7 +1648,7 @@ void NumberFormatterApiTest::integerWidth() {
|
|||
u".8765",
|
||||
u".08765",
|
||||
u".008765",
|
||||
u""); // TODO: Avoid the empty string here?
|
||||
u"0"); // see ICU-20844
|
||||
|
||||
assertFormatDescending(
|
||||
u"Integer Width Zero Fill 3",
|
||||
|
|
Loading…
Add table
Reference in a new issue