ICU-4019 add message format syntax for spelled-out numbers

X-SVN-Rev: 16105
This commit is contained in:
Doug Felt 2004-08-04 05:57:45 +00:00
parent 1b339e97db
commit 4255cf1f45
3 changed files with 113 additions and 11 deletions

View File

@ -31,6 +31,7 @@
#include "unicode/ustring.h"
#include "unicode/ucnv_err.h"
#include "unicode/uchar.h"
#include "unicode/rbnf.h"
#include "ustrfmt.h"
#include "cmemory.h"
#include "uprops.h"
@ -48,6 +49,10 @@
//---------------------------------------
// static data
static const UChar ID_EMPTY[] = {
0 /* empty string, used for default so that null can mark end of list */
};
static const UChar ID_NUMBER[] = {
0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0 /* "number" */
};
@ -60,14 +65,27 @@ static const UChar ID_TIME[] = {
static const UChar ID_CHOICE[] = {
0x63, 0x68, 0x6F, 0x69, 0x63, 0x65, 0 /* "choice" */
};
static const UChar ID_SPELLOUT[] = {
0x73, 0x70, 0x65, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0 /* "spellout" */
};
static const UChar ID_ORDINAL[] = {
0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0 /* "ordinal" */
};
static const UChar ID_DURATION[] = {
0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0 /* "duration" */
};
// MessageFormat Type List Number, Date, Time or Choice
static const UChar * const TYPE_IDS[] = {
NULL,
ID_EMPTY,
ID_NUMBER,
ID_DATE,
ID_TIME,
ID_CHOICE
ID_CHOICE,
ID_SPELLOUT,
ID_ORDINAL,
ID_DURATION,
NULL,
};
static const UChar ID_CURRENCY[] = {
@ -82,7 +100,7 @@ static const UChar ID_INTEGER[] = {
// NumberFormat modifier list, default, currency, percent or integer
static const UChar * const NUMBER_STYLE_IDS[] = {
NULL,
ID_EMPTY,
ID_CURRENCY,
ID_PERCENT,
ID_INTEGER,
@ -104,11 +122,12 @@ static const UChar ID_FULL[] = {
// DateFormat modifier list, default, short, medium, long or full
static const UChar * const DATE_STYLE_IDS[] = {
NULL,
ID_EMPTY,
ID_SHORT,
ID_MEDIUM,
ID_LONG,
ID_FULL
ID_FULL,
NULL,
};
static const DateFormat::EStyle DATE_STYLES[] = {
@ -119,8 +138,6 @@ static const DateFormat::EStyle DATE_STYLES[] = {
DateFormat::kFull,
};
static const int32_t ID_LIST_LENGTH = 5;
static const int32_t DEFAULT_INITIAL_CAPACITY = 10;
U_NAMESPACE_BEGIN
@ -1154,6 +1171,17 @@ MessageFormat::parseObject( const UnicodeString& source,
// -------------------------------------
static Format* makeRBNF(URBNFRuleSetTag tag, const Locale& locale, const UnicodeString& defaultRuleSet, UErrorCode& ec) {
RuleBasedNumberFormat* fmt = new RuleBasedNumberFormat(tag, locale, ec);
if (U_SUCCESS(ec) && defaultRuleSet.length() > 0) {
fmt->setDefaultRuleSet(defaultRuleSet, ec);
if (U_FAILURE(ec)) { // ignore unrecognized default rule set
ec = U_ZERO_ERROR;
}
}
return fmt;
}
/**
* Reads the segments[] array (see applyPattern()) and parses the
* segments[1..3] into a Format* object. Stores the format object in
@ -1246,6 +1274,18 @@ MessageFormat::makeFormat(int32_t formatNumber,
fmt = new ChoiceFormat(segments[3], parseError, ec);
break;
case 5: // spellout
argType = Formattable::kDouble;
fmt = makeRBNF(URBNF_SPELLOUT, fLocale, segments[3], ec);
break;
case 6: // ordinal
argType = Formattable::kDouble;
fmt = makeRBNF(URBNF_ORDINAL, fLocale, segments[3], ec);
break;
case 7: // duration
argType = Formattable::kDouble;
fmt = makeRBNF(URBNF_DURATION, fLocale, segments[3], ec);
break;
default:
argType = Formattable::kString;
ec = U_ILLEGAL_ARGUMENT_ERROR;
@ -1286,16 +1326,17 @@ int32_t MessageFormat::findKeyword(const UnicodeString& s,
const UChar * const *list)
{
if (s.length() == 0)
return 0;
return 0; // default
UnicodeString buffer = s;
// Trims the space characters and turns all characters
// in s to lower case.
buffer.trim().toLower();
for (int32_t i = 0; i < ID_LIST_LENGTH; ++i) {
if (list[i] && !buffer.compare(list[i], u_strlen(list[i])))
for (int32_t i = 0; list[i]; ++i) {
if (!buffer.compare(list[i], u_strlen(list[i]))) {
return i;
}
}
return -1;
}

View File

@ -51,6 +51,7 @@ TestMessageFormat::runIndexedTest(int32_t index, UBool exec,
TESTCASE(15,testAdopt);
TESTCASE(16,testCopyConstructor2);
TESTCASE(17,TestUnlimitedArgsAndSubformats);
TESTCASE(18,TestRBNF);
default: name = ""; break;
}
}
@ -1116,4 +1117,59 @@ void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
}
}
// test RBNF extensions to message format
void TestMessageFormat::TestRBNF(void) {
// WARNING: this depends on the RBNF formats for en_US
Locale locale("en", "US", "");
UErrorCode ec = U_ZERO_ERROR;
UnicodeString values[] = {
// decimal values do not format completely for ordinal or duration, and
// do not always parse, so do not include them
"0", "1", "12", "100", "123", "1001", "123,456", "-17",
};
int32_t values_count = sizeof(values)/sizeof(values[0]);
UnicodeString formats[] = {
"There are {0,spellout} files to search.",
"There are {0,spellout,%simplified} files to search.",
"The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
"This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
"Searching this file will take {0,duration} to complete.",
"Searching this file will take {0,duration,%with-words} to complete.",
};
int32_t formats_count = sizeof(formats)/sizeof(formats[0]);
Formattable args[1];
NumberFormat* numFmt = NumberFormat::createInstance(locale, ec);
for (int i = 0; i < formats_count; ++i) {
MessageFormat* fmt = new MessageFormat(formats[i], locale, ec);
logln((UnicodeString)"Testing format pattern: '" + formats[i] + "'");
for (int j = 0; j < values_count; ++j) {
ec = U_ZERO_ERROR;
numFmt->parse(values[j], args[0], ec);
if (U_FAILURE(ec)) {
errln((UnicodeString)"Failed to parse test argument " + values[j]);
} else {
FieldPosition fp(0);
UnicodeString result;
fmt->format(args, 1, result, fp, ec);
logln((UnicodeString)"value: " + toString(args[0]) + " --> " + result + " ec: " + ec);
if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
int32_t count = 0;
Formattable* parseResult = fmt->parse(result, count, ec);
if (count != 1) {
errln((UnicodeString)"parse returned " + count + " args");
} else if (parseResult[0] != args[0]) {
errln((UnicodeString)"parsed argument " + toString(parseResult[0]) + " != " + toString(args[0]));
}
}
}
}
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View File

@ -63,6 +63,11 @@ public:
*/
void TestUnlimitedArgsAndSubformats();
/**
* Test RBNF extensions to MessageFormat.
*/
void TestRBNF();
//
/**
* ------------ API tests ----------