ICU-11693 C support for CompactDecimalFormat, via UNumberFormatStyle additions

X-SVN-Rev: 37612
This commit is contained in:
Peter Edberg 2015-06-23 18:09:52 +00:00
parent 4cdffbd453
commit 15ee90b9a3
4 changed files with 233 additions and 5 deletions

View File

@ -1,6 +1,6 @@
/* /*
******************************************************************************* *******************************************************************************
* Copyright (C) 1997-2014, International Business Machines Corporation and * Copyright (C) 1997-2015, International Business Machines Corporation and
* others. All Rights Reserved. * others. All Rights Reserved.
******************************************************************************* *******************************************************************************
* *
@ -120,6 +120,8 @@ static const UChar * const gLastResortNumberPatterns[UNUM_FORMAT_STYLE_COUNT] =
gLastResortPluralCurrencyPat, // UNUM_CURRENCY_PLURAL gLastResortPluralCurrencyPat, // UNUM_CURRENCY_PLURAL
gLastResortAccountingCurrencyPat, // UNUM_CURRENCY_ACCOUNTING gLastResortAccountingCurrencyPat, // UNUM_CURRENCY_ACCOUNTING
gLastResortCurrencyPat, // UNUM_CASH_CURRENCY gLastResortCurrencyPat, // UNUM_CASH_CURRENCY
NULL, // UNUM_DECIMAL_COMPACT_SHORT
NULL, // UNUM_DECIMAL_COMPACT_LONG
}; };
// Keys used for accessing resource bundles // Keys used for accessing resource bundles
@ -145,7 +147,9 @@ static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = {
"currencyFormat", // UNUM_CURRENCY_ISO "currencyFormat", // UNUM_CURRENCY_ISO
"currencyFormat", // UNUM_CURRENCY_PLURAL "currencyFormat", // UNUM_CURRENCY_PLURAL
"accountingFormat", // UNUM_CURRENCY_ACCOUNTING "accountingFormat", // UNUM_CURRENCY_ACCOUNTING
"currencyFormat" // UNUM_CASH_CURRENCY "currencyFormat", // UNUM_CASH_CURRENCY
NULL, // UNUM_DECIMAL_COMPACT_SHORT
NULL, // UNUM_DECIMAL_COMPACT_LONG
}; };
// Static hashtable cache of NumberingSystem objects used by NumberFormat // Static hashtable cache of NumberingSystem objects used by NumberFormat

View File

@ -216,12 +216,28 @@ typedef enum UNumberFormatStyle {
*/ */
UNUM_CASH_CURRENCY=13, UNUM_CASH_CURRENCY=13,
#endif /* U_HIDE_DRAFT_API */ #endif /* U_HIDE_DRAFT_API */
#ifndef U_HIDE_DRAFT_API
/**
* Decimal format expressed using compact notation
* (short form, corresponds to UNumberCompactStyle=UNUM_SHORT)
* e.g. "23K", "45B"
* @draft ICU 56
*/
UNUM_DECIMAL_COMPACT_SHORT=14,
/**
* Decimal format expressed using compact notation
* (long form, corresponds to UNumberCompactStyle=UNUM_LONG)
* e.g. "23 thousand", "45 billion"
* @draft ICU 56
*/
UNUM_DECIMAL_COMPACT_LONG=15,
#endif /* U_HIDE_DRAFT_API */
/** /**
* One more than the highest number format style constant. * One more than the highest number format style constant.
* @stable ICU 4.8 * @stable ICU 4.8
*/ */
UNUM_FORMAT_STYLE_COUNT=14, UNUM_FORMAT_STYLE_COUNT=16,
/** /**
* Default format * Default format
@ -615,6 +631,8 @@ unum_formatUFormattable(const UNumberFormat* fmt,
/** /**
* Parse a string into an integer using a UNumberFormat. * Parse a string into an integer using a UNumberFormat.
* The string will be parsed according to the UNumberFormat's locale. * The string will be parsed according to the UNumberFormat's locale.
* Note: parsing is not supported for styles UNUM_DECIMAL_COMPACT_SHORT
* and UNUM_DECIMAL_COMPACT_LONG.
* @param fmt The formatter to use. * @param fmt The formatter to use.
* @param text The text to parse. * @param text The text to parse.
* @param textLength The length of text, or -1 if null-terminated. * @param textLength The length of text, or -1 if null-terminated.
@ -639,6 +657,8 @@ unum_parse( const UNumberFormat* fmt,
/** /**
* Parse a string into an int64 using a UNumberFormat. * Parse a string into an int64 using a UNumberFormat.
* The string will be parsed according to the UNumberFormat's locale. * The string will be parsed according to the UNumberFormat's locale.
* Note: parsing is not supported for styles UNUM_DECIMAL_COMPACT_SHORT
* and UNUM_DECIMAL_COMPACT_LONG.
* @param fmt The formatter to use. * @param fmt The formatter to use.
* @param text The text to parse. * @param text The text to parse.
* @param textLength The length of text, or -1 if null-terminated. * @param textLength The length of text, or -1 if null-terminated.
@ -663,6 +683,8 @@ unum_parseInt64(const UNumberFormat* fmt,
/** /**
* Parse a string into a double using a UNumberFormat. * Parse a string into a double using a UNumberFormat.
* The string will be parsed according to the UNumberFormat's locale. * The string will be parsed according to the UNumberFormat's locale.
* Note: parsing is not supported for styles UNUM_DECIMAL_COMPACT_SHORT
* and UNUM_DECIMAL_COMPACT_LONG.
* @param fmt The formatter to use. * @param fmt The formatter to use.
* @param text The text to parse. * @param text The text to parse.
* @param textLength The length of text, or -1 if null-terminated. * @param textLength The length of text, or -1 if null-terminated.
@ -691,6 +713,8 @@ unum_parseDouble( const UNumberFormat* fmt,
* The syntax of the output is a "numeric string" * The syntax of the output is a "numeric string"
* as defined in the Decimal Arithmetic Specification, available at * as defined in the Decimal Arithmetic Specification, available at
* http://speleotrove.com/decimal * http://speleotrove.com/decimal
* Note: parsing is not supported for styles UNUM_DECIMAL_COMPACT_SHORT
* and UNUM_DECIMAL_COMPACT_LONG.
* @param fmt The formatter to use. * @param fmt The formatter to use.
* @param text The text to parse. * @param text The text to parse.
* @param textLength The length of text, or -1 if null-terminated. * @param textLength The length of text, or -1 if null-terminated.
@ -750,6 +774,8 @@ unum_parseDoubleCurrency(const UNumberFormat* fmt,
* Parse a UChar string into a UFormattable. * Parse a UChar string into a UFormattable.
* Example code: * Example code:
* \snippet test/cintltst/cnumtst.c unum_parseToUFormattable * \snippet test/cintltst/cnumtst.c unum_parseToUFormattable
* Note: parsing is not supported for styles UNUM_DECIMAL_COMPACT_SHORT
* and UNUM_DECIMAL_COMPACT_LONG.
* @param fmt the formatter to use * @param fmt the formatter to use
* @param result the UFormattable to hold the result. If NULL, a new UFormattable will be allocated (which the caller must close with ufmt_close). * @param result the UFormattable to hold the result. If NULL, a new UFormattable will be allocated (which the caller must close with ufmt_close).
* @param text the text to parse * @param text the text to parse

View File

@ -1,6 +1,6 @@
/* /*
******************************************************************************* *******************************************************************************
* Copyright (C) 1996-2014, International Business Machines * Copyright (C) 1996-2015, International Business Machines
* Corporation and others. All Rights Reserved. * Corporation and others. All Rights Reserved.
******************************************************************************* *******************************************************************************
* Modification History: * Modification History:
@ -20,6 +20,7 @@
#include "unicode/numfmt.h" #include "unicode/numfmt.h"
#include "unicode/decimfmt.h" #include "unicode/decimfmt.h"
#include "unicode/rbnf.h" #include "unicode/rbnf.h"
#include "unicode/compactdecimalformat.h"
#include "unicode/ustring.h" #include "unicode/ustring.h"
#include "unicode/fmtable.h" #include "unicode/fmtable.h"
#include "unicode/dcfmtsym.h" #include "unicode/dcfmtsym.h"
@ -114,6 +115,14 @@ unum_open( UNumberFormatStyle style,
break; break;
#endif #endif
case UNUM_DECIMAL_COMPACT_SHORT:
retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status);
break;
case UNUM_DECIMAL_COMPACT_LONG:
retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status);
break;
default: default:
*status = U_UNSUPPORTED_ERROR; *status = U_UNSUPPORTED_ERROR;
return NULL; return NULL;

View File

@ -61,6 +61,7 @@ static void TestCurrencyIsoPluralFormat(void);
static void TestContext(void); static void TestContext(void);
static void TestCurrencyUsage(void); static void TestCurrencyUsage(void);
static void TestCurrFmtNegSameAsPositive(void); static void TestCurrFmtNegSameAsPositive(void);
static void TestVariousStylesAndAttributes(void);
#define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x) #define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
@ -89,6 +90,7 @@ void addNumForTest(TestNode** root)
TESTCASE(TestContext); TESTCASE(TestContext);
TESTCASE(TestCurrencyUsage); TESTCASE(TestCurrencyUsage);
TESTCASE(TestCurrFmtNegSameAsPositive); TESTCASE(TestCurrFmtNegSameAsPositive);
TESTCASE(TestVariousStylesAndAttributes);
} }
/* test Parse int 64 */ /* test Parse int 64 */
@ -2621,7 +2623,7 @@ static UChar currFmtResultExpected[] = /* "$100.00" */
static UChar emptyString[] = {0}; static UChar emptyString[] = {0};
enum { kUBufSize = 64 }; enum { kUBufSize = 64, kBBufSize = 128 };
static void TestCurrFmtNegSameAsPositive(void) { static void TestCurrFmtNegSameAsPositive(void) {
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
@ -2656,4 +2658,191 @@ static void TestCurrFmtNegSameAsPositive(void) {
} }
} }
typedef struct {
double value;
const char *expected;
} ValueAndExpectedString;
static const ValueAndExpectedString enShort[] = {
{0.0, "0"},
{0.17, "0.17"},
{1.0, "1"},
{1234.0, "1.23K"},
{12345.0, "12.3K"},
{123456.0, "123K"},
{1234567.0, "1.23M"},
{12345678.0, "12.3M"},
{123456789.0, "123M"},
{1.23456789E9, "1.23B"},
{1.23456789E10, "12.3B"},
{1.23456789E11, "123B"},
{1.23456789E12, "1.23T"},
{1.23456789E13, "12.3T"},
{1.23456789E14, "123T"},
{1.23456789E15, "1230T"},
{0.0, NULL}
};
static const ValueAndExpectedString enShortMax2[] = {
{0.0, "0"},
{0.17, "0.17"},
{1.0, "1"},
{1234.0, "1.2K"},
{12345.0, "12K"},
{123456.0, "120K"},
{1234567.0, "1.2M"},
{12345678.0, "12M"},
{123456789.0, "120M"},
{1.23456789E9, "1.2B"},
{1.23456789E10, "12B"},
{1.23456789E11, "120B"},
{1.23456789E12, "1.2T"},
{1.23456789E13, "12T"},
{1.23456789E14, "120T"},
{1.23456789E15, "1200T"},
{0.0, NULL}
};
static const ValueAndExpectedString enShortMax5[] = {
{0.0, "0"},
{0.17, "0.17"},
{1.0, "1"},
{1234.0, "1.234K"},
{12345.0, "12.345K"},
{123456.0, "123.46K"},
{1234567.0, "1.2346M"},
{12345678.0, "12.346M"},
{123456789.0, "123.46M"},
{1.23456789E9, "1.2346B"},
{1.23456789E10, "12.346B"},
{1.23456789E11, "123.46B"},
{1.23456789E12, "1.2346T"},
{1.23456789E13, "12.346T"},
{1.23456789E14, "123.46T"},
{1.23456789E15, "1234.6T"},
{0.0, NULL}
};
static const ValueAndExpectedString enShortMin3[] = {
{0.0, "0.00"},
{0.17, "0.170"},
{1.0, "1.00"},
{1234.0, "1.23K"},
{12345.0, "12.3K"},
{123456.0, "123K"},
{1234567.0, "1.23M"},
{12345678.0, "12.3M"},
{123456789.0, "123M"},
{1.23456789E9, "1.23B"},
{1.23456789E10, "12.3B"},
{1.23456789E11, "123B"},
{1.23456789E12, "1.23T"},
{1.23456789E13, "12.3T"},
{1.23456789E14, "123T"},
{1.23456789E15, "1230T"},
{0.0, NULL}
};
static const ValueAndExpectedString jaShortMax2[] = {
{1234.0, "1.2\\u5343"},
{12345.0, "1.2\\u4E07"},
{123456.0, "12\\u4E07"},
{1234567.0, "120\\u4E07"},
{12345678.0, "1200\\u4E07"},
{123456789.0, "1.2\\u5104"},
{1.23456789E9, "12\\u5104"},
{1.23456789E10, "120\\u5104"},
{1.23456789E11, "1200\\u5104"},
{1.23456789E12, "1.2\\u5146"},
{1.23456789E13, "12\\u5146"},
{1.23456789E14, "120\\u5146"},
{0.0, NULL}
};
static const ValueAndExpectedString srLongMax2[] = {
{1234.0, "1,2 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"}, // 10^3 few
{12345.0, "12 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"}, // 10^3 other
{21789.0, "22 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"}, // 10^3 few
{123456.0, "120 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"}, // 10^3 other
{999999.0, "1 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D"}, // 10^6 one
{1234567.0, "1,2 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 few
{12345678.0, "12 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 other
{123456789.0, "120 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 other
{1.23456789E9, "1,2 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"}, // 10^9 few
{1.23456789E10, "12 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"}, // 10^9 other
{2.08901234E10, "21 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0430"}, // 10^9 one
{2.18901234E10, "22 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"}, // 10^9 few
{1.23456789E11, "120 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"}, // 10^9 other
{-1234.0, "-1,2 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"},
{-12345.0, "-12 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"},
{-21789.0, "-22 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"},
{-123456.0, "-120 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"},
{-999999.0, "-1 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D"},
{-1234567.0, "-1,2 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
{-12345678.0, "-12 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
{-123456789.0, "-120 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
{-1.23456789E9, "-1,2 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"},
{-1.23456789E10, "-12 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"},
{-2.08901234E10, "-21 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0430"},
{-2.18901234E10, "-22 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"},
{-1.23456789E11, "-120 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"},
{0.0, NULL}
};
typedef struct {
const char * locale;
UNumberFormatStyle style;
int32_t attribute; // UNumberFormatAttribute, or -1 for none
int32_t attrValue; //
const ValueAndExpectedString * veItems;
} LocStyleAttributeTest;
static const LocStyleAttributeTest lsaTests[] = {
{ "en", UNUM_DECIMAL_COMPACT_SHORT, -1, 0, enShort },
{ "en", UNUM_DECIMAL_COMPACT_SHORT, UNUM_MAX_SIGNIFICANT_DIGITS, 2, enShortMax2 },
{ "en", UNUM_DECIMAL_COMPACT_SHORT, UNUM_MAX_SIGNIFICANT_DIGITS, 5, enShortMax5 },
{ "en", UNUM_DECIMAL_COMPACT_SHORT, UNUM_MIN_SIGNIFICANT_DIGITS, 3, enShortMin3 },
{ "ja", UNUM_DECIMAL_COMPACT_SHORT, UNUM_MAX_SIGNIFICANT_DIGITS, 2, jaShortMax2 },
{ "sr", UNUM_DECIMAL_COMPACT_LONG, UNUM_MAX_SIGNIFICANT_DIGITS, 2, srLongMax2 },
{ NULL, (UNumberFormatStyle)0, -1, 0, NULL }
};
static void TestVariousStylesAndAttributes(void) {
const LocStyleAttributeTest * lsaTestPtr;
for (lsaTestPtr = lsaTests; lsaTestPtr->locale != NULL; lsaTestPtr++) {
UErrorCode status = U_ZERO_ERROR;
UNumberFormat * unum = unum_open(lsaTestPtr->style, NULL, 0, lsaTestPtr->locale, NULL, &status);
if ( U_FAILURE(status) ) {
log_err("FAIL: unum_open style %d, locale %s: error %s\n", (int)lsaTestPtr->style, lsaTestPtr->locale, u_errorName(status));
} else {
const ValueAndExpectedString * veItemPtr;
if (lsaTestPtr->attribute >= 0) {
unum_setAttribute(unum, (UNumberFormatAttribute)lsaTestPtr->attribute, lsaTestPtr->attrValue);
}
for (veItemPtr = lsaTestPtr->veItems; veItemPtr->expected != NULL; veItemPtr++) {
UChar uexp[kUBufSize];
UChar uget[kUBufSize];
int32_t uexplen, ugetlen;
status = U_ZERO_ERROR;
uexplen = u_unescape(veItemPtr->expected, uexp, kUBufSize);
ugetlen = unum_formatDouble(unum, veItemPtr->value, uget, kUBufSize, NULL, &status);
if ( U_FAILURE(status) ) {
log_err("FAIL: unum_formatDouble style %d, locale %s, attr %d, value %.2f: error %s\n",
(int)lsaTestPtr->style, lsaTestPtr->locale, lsaTestPtr->attribute, veItemPtr->value, u_errorName(status));
} else if (ugetlen != uexplen || u_strncmp(uget, uexp, uexplen) != 0) {
char bexp[kBBufSize];
char bget[kBBufSize];
u_strToUTF8(bexp, kBBufSize, NULL, uexp, uexplen, &status);
u_strToUTF8(bget, kBBufSize, NULL, uget, ugetlen, &status);
log_err("FAIL: unum_formatDouble style %d, locale %s, attr %d, value %.2f: expect \"%s\", get \"%s\"\n",
(int)lsaTestPtr->style, lsaTestPtr->locale, lsaTestPtr->attribute, veItemPtr->value, bexp, bget);
}
}
unum_close(unum);
}
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */ #endif /* #if !UCONFIG_NO_FORMATTING */