ICU-9132 ordinal-plural formatting in C/C++
X-SVN-Rev: 31687
This commit is contained in:
parent
a89b4cc093
commit
8d7428d1b3
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines
|
||||
* Copyright (C) 2011-2012, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
* file name: messagepattern.cpp
|
||||
@ -41,10 +41,12 @@ static const UChar u_lessThan=0x3C;
|
||||
static const UChar u_equal=0x3D;
|
||||
static const UChar u_A=0x41;
|
||||
static const UChar u_C=0x43;
|
||||
static const UChar u_D=0x44;
|
||||
static const UChar u_E=0x45;
|
||||
static const UChar u_H=0x48;
|
||||
static const UChar u_I=0x49;
|
||||
static const UChar u_L=0x4C;
|
||||
static const UChar u_N=0x4E;
|
||||
static const UChar u_O=0x4F;
|
||||
static const UChar u_P=0x50;
|
||||
static const UChar u_R=0x52;
|
||||
@ -52,13 +54,16 @@ static const UChar u_S=0x53;
|
||||
static const UChar u_T=0x54;
|
||||
static const UChar u_U=0x55;
|
||||
static const UChar u_Z=0x5A;
|
||||
static const UChar u__=0x5F; // '_'
|
||||
static const UChar u_a=0x61;
|
||||
static const UChar u_c=0x63;
|
||||
static const UChar u_d=0x64;
|
||||
static const UChar u_e=0x65;
|
||||
static const UChar u_f=0x66;
|
||||
static const UChar u_h=0x68;
|
||||
static const UChar u_i=0x69;
|
||||
static const UChar u_l=0x6C;
|
||||
static const UChar u_n=0x6E;
|
||||
static const UChar u_o=0x6F;
|
||||
static const UChar u_p=0x70;
|
||||
static const UChar u_r=0x72;
|
||||
@ -459,7 +464,7 @@ MessagePattern::parseMessage(int32_t index, int32_t msgStartLength,
|
||||
aposMode==UMSGPAT_APOS_DOUBLE_REQUIRED ||
|
||||
c==u_leftCurlyBrace || c==u_rightCurlyBrace ||
|
||||
(parentType==UMSGPAT_ARG_TYPE_CHOICE && c==u_pipe) ||
|
||||
(parentType==UMSGPAT_ARG_TYPE_PLURAL && c==u_pound)
|
||||
(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(parentType) && c==u_pound)
|
||||
) {
|
||||
// skip the quote-starting apostrophe
|
||||
addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, index-1, 1, 0, errorCode);
|
||||
@ -494,7 +499,7 @@ MessagePattern::parseMessage(int32_t index, int32_t msgStartLength,
|
||||
needsAutoQuoting=TRUE;
|
||||
}
|
||||
}
|
||||
} else if(parentType==UMSGPAT_ARG_TYPE_PLURAL && c==u_pound) {
|
||||
} else if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(parentType) && c==u_pound) {
|
||||
// The unquoted # in a plural message fragment will be replaced
|
||||
// with the (number-offset).
|
||||
addPart(UMSGPAT_PART_TYPE_REPLACE_NUMBER, index-1, 1, 0, errorCode);
|
||||
@ -613,6 +618,10 @@ MessagePattern::parseArg(int32_t index, int32_t argStartLength, int32_t nestingL
|
||||
} else if(isSelect(typeIndex)) {
|
||||
argType=UMSGPAT_ARG_TYPE_SELECT;
|
||||
}
|
||||
} else if(length==9) {
|
||||
if(isOrdinal(typeIndex)) {
|
||||
argType=UMSGPAT_ARG_TYPE_ORDINAL;
|
||||
}
|
||||
}
|
||||
// change the ARG_START type from NONE to argType
|
||||
partsList->a[argStart].value=(int16_t)argType;
|
||||
@ -783,7 +792,7 @@ MessagePattern::parsePluralOrSelectStyle(UMessagePatternArgType argType,
|
||||
return index;
|
||||
}
|
||||
int32_t selectorIndex=index;
|
||||
if(argType==UMSGPAT_ARG_TYPE_PLURAL && msg.charAt(selectorIndex)==u_equal) {
|
||||
if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) && msg.charAt(selectorIndex)==u_equal) {
|
||||
// explicit-value plural selector: =double
|
||||
index=skipDouble(index+1);
|
||||
int32_t length=index-selectorIndex;
|
||||
@ -809,7 +818,7 @@ MessagePattern::parsePluralOrSelectStyle(UMessagePatternArgType argType,
|
||||
return 0;
|
||||
}
|
||||
// Note: The ':' in "offset:" is just beyond the skipIdentifier() range.
|
||||
if( argType==UMSGPAT_ARG_TYPE_PLURAL && length==6 && index<msg.length() &&
|
||||
if( UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) && length==6 && index<msg.length() &&
|
||||
0==msg.compare(selectorIndex, 7, kOffsetColon, 0, 7)
|
||||
) {
|
||||
// plural offset, not a selector
|
||||
@ -1060,6 +1069,21 @@ MessagePattern::isSelect(int32_t index) {
|
||||
((c=msg.charAt(index))==u_t || c==u_T);
|
||||
}
|
||||
|
||||
UBool
|
||||
MessagePattern::isOrdinal(int32_t index) {
|
||||
UChar c;
|
||||
return
|
||||
((c=msg.charAt(index++))==u_p || c==u_P) &&
|
||||
((c=msg.charAt(index++))==u_l || c==u_L) &&
|
||||
((c=msg.charAt(index++))==u_o || c==u_O) &&
|
||||
((c=msg.charAt(index++))==u_r || c==u_R) &&
|
||||
((c=msg.charAt(index++))==u_d || c==u_D) &&
|
||||
((c=msg.charAt(index++))==u_i || c==u_I) &&
|
||||
((c=msg.charAt(index++))==u_n || c==u_N) &&
|
||||
((c=msg.charAt(index++))==u_a || c==u_A) &&
|
||||
((c=msg.charAt(index))==u_l || c==u_L);
|
||||
}
|
||||
|
||||
UBool
|
||||
MessagePattern::inMessageFormatPattern(int32_t nestingLevel) {
|
||||
return nestingLevel>0 || partsList->a[0].type==UMSGPAT_PART_TYPE_MSG_START;
|
||||
|
@ -233,7 +233,7 @@ enum UMessagePatternArgType {
|
||||
*/
|
||||
UMSGPAT_ARG_TYPE_CHOICE,
|
||||
/**
|
||||
* The argument is a PluralFormat with an optional ARG_INT or ARG_DOUBLE offset
|
||||
* The argument is a cardinal-number PluralFormat with an optional ARG_INT or ARG_DOUBLE offset
|
||||
* (e.g., offset:1)
|
||||
* and one or more (ARG_SELECTOR [explicit-value] message) tuples.
|
||||
* If the selector has an explicit value (e.g., =2), then
|
||||
@ -246,13 +246,27 @@ enum UMessagePatternArgType {
|
||||
* The argument is a SelectFormat with one or more (ARG_SELECTOR, message) pairs.
|
||||
* @stable ICU 4.8
|
||||
*/
|
||||
UMSGPAT_ARG_TYPE_SELECT
|
||||
UMSGPAT_ARG_TYPE_SELECT,
|
||||
/**
|
||||
* The argument is an ordinal-number PluralFormat
|
||||
* with the same style parts sequence and semantics as UMSGPAT_ARG_TYPE_PLURAL.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
UMSGPAT_ARG_TYPE_ORDINAL
|
||||
};
|
||||
/**
|
||||
* @stable ICU 4.8
|
||||
*/
|
||||
typedef enum UMessagePatternArgType UMessagePatternArgType;
|
||||
|
||||
/**
|
||||
* Returns TRUE if the argument type has a plural style part sequence and semantics,
|
||||
* for example UMSGPAT_ARG_TYPE_PLURAL and UMSGPAT_ARG_TYPE_ORDINAL.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
#define UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) \
|
||||
((argType)==UMSGPAT_ARG_TYPE_PLURAL || (argType)==UMSGPAT_ARG_TYPE_ORDINAL)
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Return value from MessagePattern.validateArgumentName() for when
|
||||
@ -878,6 +892,8 @@ private:
|
||||
|
||||
UBool isSelect(int32_t index);
|
||||
|
||||
UBool isOrdinal(int32_t index);
|
||||
|
||||
/**
|
||||
* @return TRUE if we are inside a MessageFormat (sub-)pattern,
|
||||
* as opposed to inside a top-level choice/plural/select pattern.
|
||||
|
@ -179,6 +179,63 @@ plurals:table(nofallback){
|
||||
zh{""}
|
||||
zu{"set2"}
|
||||
}
|
||||
locales_ordinals{
|
||||
af{""}
|
||||
am{""}
|
||||
ar{""}
|
||||
bg{""}
|
||||
bn{"set31"}
|
||||
ca{"set28"}
|
||||
cs{""}
|
||||
da{""}
|
||||
de{""}
|
||||
el{""}
|
||||
en{"set26"}
|
||||
es{""}
|
||||
et{""}
|
||||
eu{""}
|
||||
fa{""}
|
||||
fi{""}
|
||||
fil{"set2"}
|
||||
fr{"set2"}
|
||||
gl{""}
|
||||
gu{"set30"}
|
||||
hi{"set30"}
|
||||
hr{""}
|
||||
hu{"set24"}
|
||||
id{""}
|
||||
is{""}
|
||||
it{"set27"}
|
||||
iw{""}
|
||||
ja{""}
|
||||
kn{""}
|
||||
ko{""}
|
||||
lt{""}
|
||||
lv{""}
|
||||
ml{""}
|
||||
mr{"set29"}
|
||||
ms{"set2"}
|
||||
nl{""}
|
||||
no{""}
|
||||
pl{""}
|
||||
pt{""}
|
||||
ro{"set2"}
|
||||
ru{""}
|
||||
sk{""}
|
||||
sl{""}
|
||||
sr{""}
|
||||
sv{"set25"}
|
||||
sw{""}
|
||||
ta{""}
|
||||
te{""}
|
||||
th{""}
|
||||
tr{""}
|
||||
uk{""}
|
||||
ur{""}
|
||||
vi{"set2"}
|
||||
zh{""}
|
||||
zu{"set32"}
|
||||
}
|
||||
rules{
|
||||
set1{
|
||||
few{"n mod 100 in 3..10"}
|
||||
@ -256,9 +313,50 @@ plurals:table(nofallback){
|
||||
one{"n in 1,11"}
|
||||
two{"n in 2,12"}
|
||||
}
|
||||
set24{
|
||||
one{"n in 1,5"}
|
||||
}
|
||||
set25{
|
||||
one{"n mod 10 in 1,2 and n mod 100 not in 11,12"}
|
||||
}
|
||||
set26{
|
||||
few{"n mod 10 is 3 and n mod 100 is not 13"}
|
||||
one{"n mod 10 is 1 and n mod 100 is not 11"}
|
||||
two{"n mod 10 is 2 and n mod 100 is not 12"}
|
||||
}
|
||||
set27{
|
||||
many{"n in 11,8,80,800"}
|
||||
}
|
||||
set28{
|
||||
few{"n is 4"}
|
||||
one{"n in 1,3"}
|
||||
two{"n is 2"}
|
||||
}
|
||||
set29{
|
||||
few{"n is 4"}
|
||||
one{"n is 1"}
|
||||
two{"n in 2,3"}
|
||||
}
|
||||
set3{
|
||||
one{"n in 0..1"}
|
||||
}
|
||||
set30{
|
||||
few{"n is 4"}
|
||||
many{"n is 6"}
|
||||
one{"n is 1"}
|
||||
two{"n in 2,3"}
|
||||
}
|
||||
set31{
|
||||
few{"n is 4"}
|
||||
many{"n is 6"}
|
||||
one{"n in 1,5,7,8,9,10"}
|
||||
two{"n in 2,3"}
|
||||
}
|
||||
set32{
|
||||
few{"n in 2..9"}
|
||||
many{"n in 10..19,100..199,1000..1999"}
|
||||
one{"n is 1"}
|
||||
}
|
||||
set4{
|
||||
one{"n within 0..2 and n is not 2"}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2011, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************
|
||||
*
|
||||
@ -230,7 +230,8 @@ MessageFormat::MessageFormat(const UnicodeString& pattern,
|
||||
defaultDateFormat(NULL),
|
||||
cachedFormatters(NULL),
|
||||
customFormatArgStarts(NULL),
|
||||
pluralProvider(&fLocale)
|
||||
pluralProvider(&fLocale, UPLURAL_TYPE_CARDINAL),
|
||||
ordinalProvider(&fLocale, UPLURAL_TYPE_ORDINAL)
|
||||
{
|
||||
setLocaleIDs(fLocale.getName(), fLocale.getName());
|
||||
applyPattern(pattern, success);
|
||||
@ -251,7 +252,8 @@ MessageFormat::MessageFormat(const UnicodeString& pattern,
|
||||
defaultDateFormat(NULL),
|
||||
cachedFormatters(NULL),
|
||||
customFormatArgStarts(NULL),
|
||||
pluralProvider(&fLocale)
|
||||
pluralProvider(&fLocale, UPLURAL_TYPE_CARDINAL),
|
||||
ordinalProvider(&fLocale, UPLURAL_TYPE_ORDINAL)
|
||||
{
|
||||
setLocaleIDs(fLocale.getName(), fLocale.getName());
|
||||
applyPattern(pattern, success);
|
||||
@ -273,7 +275,8 @@ MessageFormat::MessageFormat(const UnicodeString& pattern,
|
||||
defaultDateFormat(NULL),
|
||||
cachedFormatters(NULL),
|
||||
customFormatArgStarts(NULL),
|
||||
pluralProvider(&fLocale)
|
||||
pluralProvider(&fLocale, UPLURAL_TYPE_CARDINAL),
|
||||
ordinalProvider(&fLocale, UPLURAL_TYPE_ORDINAL)
|
||||
{
|
||||
setLocaleIDs(fLocale.getName(), fLocale.getName());
|
||||
applyPattern(pattern, parseError, success);
|
||||
@ -294,7 +297,8 @@ MessageFormat::MessageFormat(const MessageFormat& that)
|
||||
defaultDateFormat(NULL),
|
||||
cachedFormatters(NULL),
|
||||
customFormatArgStarts(NULL),
|
||||
pluralProvider(&fLocale)
|
||||
pluralProvider(&fLocale, UPLURAL_TYPE_CARDINAL),
|
||||
ordinalProvider(&fLocale, UPLURAL_TYPE_ORDINAL)
|
||||
{
|
||||
// This will take care of creating the hash tables (since they are NULL).
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
@ -438,6 +442,7 @@ MessageFormat::setLocale(const Locale& theLocale)
|
||||
fLocale = theLocale;
|
||||
setLocaleIDs(fLocale.getName(), fLocale.getName());
|
||||
pluralProvider.reset(&fLocale);
|
||||
ordinalProvider.reset(&fLocale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1057,15 +1062,17 @@ void MessageFormat::format(int32_t msgStart, double pluralNumber,
|
||||
int32_t subMsgStart = ChoiceFormat::findSubMessage(msgPattern, i, number);
|
||||
formatComplexSubMessage(subMsgStart, 0, arguments, argumentNames,
|
||||
cnt, appendTo, success);
|
||||
} else if (argType == UMSGPAT_ARG_TYPE_PLURAL) {
|
||||
} else if (UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType)) {
|
||||
if (!arg->isNumeric()) {
|
||||
success = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
const PluralFormat::PluralSelector &selector =
|
||||
argType == UMSGPAT_ARG_TYPE_PLURAL ? pluralProvider : ordinalProvider;
|
||||
// We must use the Formattable::getDouble() variant with the UErrorCode parameter
|
||||
// because only this one converts non-double numeric types to double.
|
||||
double number = arg->getDouble(success);
|
||||
int32_t subMsgStart = PluralFormat::findSubMessage(msgPattern, i, pluralProvider, number,
|
||||
int32_t subMsgStart = PluralFormat::findSubMessage(msgPattern, i, selector, number,
|
||||
success);
|
||||
double offset = msgPattern.getPluralOffset(i);
|
||||
formatComplexSubMessage(subMsgStart, number-offset, arguments, argumentNames,
|
||||
@ -1345,7 +1352,7 @@ MessageFormat::parse(int32_t msgStart,
|
||||
argResult.setDouble(choiceResult);
|
||||
haveArgResult = TRUE;
|
||||
sourceOffset = tempStatus.getIndex();
|
||||
} else if(argType==UMSGPAT_ARG_TYPE_PLURAL || argType==UMSGPAT_ARG_TYPE_SELECT) {
|
||||
} else if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) || argType==UMSGPAT_ARG_TYPE_SELECT) {
|
||||
// Parsing not supported.
|
||||
ec = U_UNSUPPORTED_ERROR;
|
||||
return NULL;
|
||||
@ -1524,6 +1531,7 @@ void MessageFormat::cacheExplicitFormats(UErrorCode& status) {
|
||||
}
|
||||
case UMSGPAT_ARG_TYPE_CHOICE:
|
||||
case UMSGPAT_ARG_TYPE_PLURAL:
|
||||
case UMSGPAT_ARG_TYPE_ORDINAL:
|
||||
formattableType = Formattable::kDouble;
|
||||
break;
|
||||
case UMSGPAT_ARG_TYPE_SELECT:
|
||||
@ -1770,8 +1778,8 @@ FormatNameEnumeration::~FormatNameEnumeration() {
|
||||
}
|
||||
|
||||
|
||||
MessageFormat::PluralSelectorProvider::PluralSelectorProvider(const Locale* loc)
|
||||
: locale(loc), rules(NULL) {
|
||||
MessageFormat::PluralSelectorProvider::PluralSelectorProvider(const Locale* loc, UPluralType t)
|
||||
: locale(loc), rules(NULL), type(t) {
|
||||
}
|
||||
|
||||
MessageFormat::PluralSelectorProvider::~PluralSelectorProvider() {
|
||||
@ -1785,7 +1793,7 @@ UnicodeString MessageFormat::PluralSelectorProvider::select(double number, UErro
|
||||
}
|
||||
MessageFormat::PluralSelectorProvider* t = const_cast<MessageFormat::PluralSelectorProvider*>(this);
|
||||
if(rules == NULL) {
|
||||
t->rules = PluralRules::forLocale(*locale, ec);
|
||||
t->rules = PluralRules::forLocale(*locale, type, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
return UnicodeString(FALSE, OTHER_STRING, 5);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ PluralFormat::PluralFormat(UErrorCode& status)
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(NULL, status);
|
||||
init(NULL, UPLURAL_TYPE_CARDINAL, status);
|
||||
}
|
||||
|
||||
PluralFormat::PluralFormat(const Locale& loc, UErrorCode& status)
|
||||
@ -45,7 +45,7 @@ PluralFormat::PluralFormat(const Locale& loc, UErrorCode& status)
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(NULL, status);
|
||||
init(NULL, UPLURAL_TYPE_CARDINAL, status);
|
||||
}
|
||||
|
||||
PluralFormat::PluralFormat(const PluralRules& rules, UErrorCode& status)
|
||||
@ -53,7 +53,7 @@ PluralFormat::PluralFormat(const PluralRules& rules, UErrorCode& status)
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(&rules, status);
|
||||
init(&rules, UPLURAL_TYPE_COUNT, status);
|
||||
}
|
||||
|
||||
PluralFormat::PluralFormat(const Locale& loc,
|
||||
@ -63,7 +63,17 @@ PluralFormat::PluralFormat(const Locale& loc,
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(&rules, status);
|
||||
init(&rules, UPLURAL_TYPE_COUNT, status);
|
||||
}
|
||||
|
||||
PluralFormat::PluralFormat(const Locale& loc,
|
||||
UPluralType type,
|
||||
UErrorCode& status)
|
||||
: locale(loc),
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(NULL, type, status);
|
||||
}
|
||||
|
||||
PluralFormat::PluralFormat(const UnicodeString& pat,
|
||||
@ -72,7 +82,7 @@ PluralFormat::PluralFormat(const UnicodeString& pat,
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(NULL, status);
|
||||
init(NULL, UPLURAL_TYPE_CARDINAL, status);
|
||||
applyPattern(pat, status);
|
||||
}
|
||||
|
||||
@ -83,7 +93,7 @@ PluralFormat::PluralFormat(const Locale& loc,
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(NULL, status);
|
||||
init(NULL, UPLURAL_TYPE_CARDINAL, status);
|
||||
applyPattern(pat, status);
|
||||
}
|
||||
|
||||
@ -94,7 +104,7 @@ PluralFormat::PluralFormat(const PluralRules& rules,
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(&rules, status);
|
||||
init(&rules, UPLURAL_TYPE_COUNT, status);
|
||||
applyPattern(pat, status);
|
||||
}
|
||||
|
||||
@ -106,7 +116,19 @@ PluralFormat::PluralFormat(const Locale& loc,
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(&rules, status);
|
||||
init(&rules, UPLURAL_TYPE_COUNT, status);
|
||||
applyPattern(pat, status);
|
||||
}
|
||||
|
||||
PluralFormat::PluralFormat(const Locale& loc,
|
||||
UPluralType type,
|
||||
const UnicodeString& pat,
|
||||
UErrorCode& status)
|
||||
: locale(loc),
|
||||
msgPattern(status),
|
||||
numberFormat(NULL),
|
||||
offset(0) {
|
||||
init(NULL, type, status);
|
||||
applyPattern(pat, status);
|
||||
}
|
||||
|
||||
@ -147,13 +169,13 @@ PluralFormat::~PluralFormat() {
|
||||
}
|
||||
|
||||
void
|
||||
PluralFormat::init(const PluralRules* rules, UErrorCode& status) {
|
||||
PluralFormat::init(const PluralRules* rules, UPluralType type, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rules==NULL) {
|
||||
pluralRulesWrapper.pluralRules = PluralRules::forLocale(locale, status);
|
||||
pluralRulesWrapper.pluralRules = PluralRules::forLocale(locale, type, status);
|
||||
} else {
|
||||
pluralRulesWrapper.pluralRules = rules->clone();
|
||||
if (pluralRulesWrapper.pluralRules == NULL) {
|
||||
@ -278,7 +300,7 @@ PluralFormat::setLocale(const Locale& loc, UErrorCode& status) {
|
||||
offset = 0;
|
||||
numberFormat = NULL;
|
||||
pluralRulesWrapper.reset();
|
||||
init(NULL, status);
|
||||
init(NULL, UPLURAL_TYPE_CARDINAL, status);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,21 +1,16 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007-2011, International Business Machines Corporation and
|
||||
* Copyright (C) 2007-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*
|
||||
* File PLURRULE.CPP
|
||||
*
|
||||
* Modification History:
|
||||
*
|
||||
* Date Name Description
|
||||
*******************************************************************************
|
||||
* File plurrule.cpp
|
||||
*/
|
||||
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/localpointer.h"
|
||||
#include "unicode/plurrule.h"
|
||||
#include "unicode/upluralrules.h"
|
||||
#include "unicode/ures.h"
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
@ -146,16 +141,25 @@ PluralRules::createDefaultRules(UErrorCode& status) {
|
||||
|
||||
PluralRules* U_EXPORT2
|
||||
PluralRules::forLocale(const Locale& locale, UErrorCode& status) {
|
||||
return forLocale(locale, UPLURAL_TYPE_CARDINAL, status);
|
||||
}
|
||||
|
||||
PluralRules* U_EXPORT2
|
||||
PluralRules::forLocale(const Locale& locale, UPluralType type, UErrorCode& status) {
|
||||
RuleChain rChain;
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
if (type >= UPLURAL_TYPE_COUNT) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
PluralRules *newObj = new PluralRules(status);
|
||||
if (newObj==NULL || U_FAILURE(status)) {
|
||||
delete newObj;
|
||||
return NULL;
|
||||
}
|
||||
UnicodeString locRule = newObj->getRuleFromResource(locale, status);
|
||||
UnicodeString locRule = newObj->getRuleFromResource(locale, type, status);
|
||||
if ((locRule.length() != 0) && U_SUCCESS(status)) {
|
||||
newObj->parseDescription(locRule, rChain, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
@ -660,25 +664,36 @@ PluralRules::addRules(RuleChain& rules) {
|
||||
}
|
||||
|
||||
UnicodeString
|
||||
PluralRules::getRuleFromResource(const Locale& locale, UErrorCode& errCode) {
|
||||
PluralRules::getRuleFromResource(const Locale& locale, UPluralType type, UErrorCode& errCode) {
|
||||
UnicodeString emptyStr;
|
||||
|
||||
if (U_FAILURE(errCode)) {
|
||||
return emptyStr;
|
||||
}
|
||||
UResourceBundle *rb=ures_openDirect(NULL, "plurals", &errCode);
|
||||
LocalUResourceBundlePointer rb(ures_openDirect(NULL, "plurals", &errCode));
|
||||
if(U_FAILURE(errCode)) {
|
||||
/* total failure, not even root could be opened */
|
||||
return emptyStr;
|
||||
}
|
||||
UResourceBundle *locRes=ures_getByKey(rb, "locales", NULL, &errCode);
|
||||
const char *typeKey;
|
||||
switch (type) {
|
||||
case UPLURAL_TYPE_CARDINAL:
|
||||
typeKey = "locales";
|
||||
break;
|
||||
case UPLURAL_TYPE_ORDINAL:
|
||||
typeKey = "locales_ordinals";
|
||||
break;
|
||||
default:
|
||||
// Must not occur: The caller should have checked for valid types.
|
||||
errCode = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return emptyStr;
|
||||
}
|
||||
LocalUResourceBundlePointer locRes(ures_getByKey(rb.getAlias(), typeKey, NULL, &errCode));
|
||||
if(U_FAILURE(errCode)) {
|
||||
ures_close(rb);
|
||||
return emptyStr;
|
||||
}
|
||||
int32_t resLen=0;
|
||||
const char *curLocaleName=locale.getName();
|
||||
const UChar* s = ures_getStringByKey(locRes, curLocaleName, &resLen, &errCode);
|
||||
const UChar* s = ures_getStringByKey(locRes.getAlias(), curLocaleName, &resLen, &errCode);
|
||||
|
||||
if (s == NULL) {
|
||||
// Check parent locales.
|
||||
@ -691,7 +706,7 @@ PluralRules::getRuleFromResource(const Locale& locale, UErrorCode& errCode) {
|
||||
while ((localeNameLen=uloc_getParent(parentLocaleName, parentLocaleName,
|
||||
ULOC_FULLNAME_CAPACITY, &status)) > 0) {
|
||||
resLen=0;
|
||||
s = ures_getStringByKey(locRes, parentLocaleName, &resLen, &status);
|
||||
s = ures_getStringByKey(locRes.getAlias(), parentLocaleName, &resLen, &status);
|
||||
if (s != NULL) {
|
||||
errCode = U_ZERO_ERROR;
|
||||
break;
|
||||
@ -700,8 +715,6 @@ PluralRules::getRuleFromResource(const Locale& locale, UErrorCode& errCode) {
|
||||
}
|
||||
}
|
||||
if (s==NULL) {
|
||||
ures_close(locRes);
|
||||
ures_close(rb);
|
||||
return emptyStr;
|
||||
}
|
||||
|
||||
@ -711,28 +724,23 @@ PluralRules::getRuleFromResource(const Locale& locale, UErrorCode& errCode) {
|
||||
// printf("\n PluralRule: %s\n", setKey);
|
||||
|
||||
|
||||
UResourceBundle *ruleRes=ures_getByKey(rb, "rules", NULL, &errCode);
|
||||
LocalUResourceBundlePointer ruleRes(ures_getByKey(rb.getAlias(), "rules", NULL, &errCode));
|
||||
if(U_FAILURE(errCode)) {
|
||||
ures_close(locRes);
|
||||
ures_close(rb);
|
||||
return emptyStr;
|
||||
}
|
||||
resLen=0;
|
||||
UResourceBundle *setRes = ures_getByKey(ruleRes, setKey, NULL, &errCode);
|
||||
LocalUResourceBundlePointer setRes(ures_getByKey(ruleRes.getAlias(), setKey, NULL, &errCode));
|
||||
if (U_FAILURE(errCode)) {
|
||||
ures_close(ruleRes);
|
||||
ures_close(locRes);
|
||||
ures_close(rb);
|
||||
return emptyStr;
|
||||
}
|
||||
|
||||
int32_t numberKeys = ures_getSize(setRes);
|
||||
int32_t numberKeys = ures_getSize(setRes.getAlias());
|
||||
char *key=NULL;
|
||||
int32_t len=0;
|
||||
for(int32_t i=0; i<numberKeys; ++i) {
|
||||
int32_t keyLen;
|
||||
resLen=0;
|
||||
s=ures_getNextString(setRes, &resLen, (const char**)&key, &errCode);
|
||||
s=ures_getNextString(setRes.getAlias(), &resLen, (const char**)&key, &errCode);
|
||||
keyLen = (int32_t)uprv_strlen(key);
|
||||
u_charsToUChars(key, result+len, keyLen);
|
||||
len += keyLen;
|
||||
@ -745,10 +753,6 @@ PluralRules::getRuleFromResource(const Locale& locale, UErrorCode& errCode) {
|
||||
u_UCharsToChars(result, setKey, len);
|
||||
// printf(" Rule: %s\n", setKey);
|
||||
|
||||
ures_close(setRes);
|
||||
ures_close(ruleRes);
|
||||
ures_close(locRes);
|
||||
ures_close(rb);
|
||||
return UnicodeString(result);
|
||||
}
|
||||
|
||||
|
@ -104,12 +104,13 @@ class NumberFormat;
|
||||
* <pre>
|
||||
* message = messageText (argument messageText)*
|
||||
* argument = noneArg | simpleArg | complexArg
|
||||
* complexArg = choiceArg | pluralArg | selectArg
|
||||
* complexArg = choiceArg | pluralArg | ordinalArg | selectArg
|
||||
*
|
||||
* noneArg = '{' argNameOrNumber '}'
|
||||
* simpleArg = '{' argNameOrNumber ',' argType [',' argStyle] '}'
|
||||
* choiceArg = '{' argNameOrNumber ',' "choice" ',' choiceStyle '}'
|
||||
* pluralArg = '{' argNameOrNumber ',' "plural" ',' pluralStyle '}'
|
||||
* ordinalArg = '{' argNameOrNumber ',' "plordinal" ',' pluralStyle '}'
|
||||
* selectArg = '{' argNameOrNumber ',' "select" ',' selectStyle '}'
|
||||
*
|
||||
* choiceStyle: see {@link ChoiceFormat}
|
||||
@ -892,7 +893,7 @@ private:
|
||||
*/
|
||||
class U_I18N_API PluralSelectorProvider : public PluralFormat::PluralSelector {
|
||||
public:
|
||||
PluralSelectorProvider(const Locale* loc);
|
||||
PluralSelectorProvider(const Locale* loc, UPluralType type);
|
||||
virtual ~PluralSelectorProvider();
|
||||
virtual UnicodeString select(double number, UErrorCode& ec) const;
|
||||
|
||||
@ -900,6 +901,7 @@ private:
|
||||
private:
|
||||
const Locale* locale;
|
||||
PluralRules* rules;
|
||||
UPluralType type;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -938,6 +940,7 @@ private:
|
||||
UHashtable* customFormatArgStarts;
|
||||
|
||||
PluralSelectorProvider pluralProvider;
|
||||
PluralSelectorProvider ordinalProvider;
|
||||
|
||||
/**
|
||||
* Method to retrieve default formats (or NULL on failure).
|
||||
|
@ -148,7 +148,7 @@ class U_I18N_API PluralFormat : public Format {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates a new <code>PluralFormat</code> for the default locale.
|
||||
* Creates a new cardinal-number <code>PluralFormat</code> for the default locale.
|
||||
* This locale will be used to get the set of plural rules and for standard
|
||||
* number formatting.
|
||||
* @param status output param set to success/failure code on exit, which
|
||||
@ -158,7 +158,7 @@ public:
|
||||
PluralFormat(UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Creates a new <code>PluralFormat</code> for a given locale.
|
||||
* Creates a new cardinal-number <code>PluralFormat</code> for a given locale.
|
||||
* @param locale the <code>PluralFormat</code> will be configured with
|
||||
* rules for this locale. This locale will also be used for
|
||||
* standard number formatting.
|
||||
@ -193,7 +193,19 @@ public:
|
||||
PluralFormat(const Locale& locale, const PluralRules& rules, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Creates a new <code>PluralFormat</code> for a given pattern string.
|
||||
* Creates a new <code>PluralFormat</code> for the plural type.
|
||||
* The standard number formatting will be done using the given locale.
|
||||
* @param locale the default number formatting will be done using this
|
||||
* locale.
|
||||
* @param type The plural type (e.g., cardinal or ordinal).
|
||||
* @param status output param set to success/failure code on exit, which
|
||||
* must not indicate a failure before the function call.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
PluralFormat(const Locale& locale, UPluralType type, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Creates a new cardinal-number <code>PluralFormat</code> for a given pattern string.
|
||||
* The default locale will be used to get the set of plural rules and for
|
||||
* standard number formatting.
|
||||
* @param pattern the pattern for this <code>PluralFormat</code>.
|
||||
@ -205,7 +217,7 @@ public:
|
||||
PluralFormat(const UnicodeString& pattern, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Creates a new <code>PluralFormat</code> for a given pattern string and
|
||||
* Creates a new cardinal-number <code>PluralFormat</code> for a given pattern string and
|
||||
* locale.
|
||||
* The locale will be used to get the set of plural rules and for
|
||||
* standard number formatting.
|
||||
@ -254,6 +266,24 @@ public:
|
||||
const UnicodeString& pattern,
|
||||
UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Creates a new <code>PluralFormat</code> for a plural type, a
|
||||
* pattern and a locale.
|
||||
* @param locale the <code>PluralFormat</code> will be configured with
|
||||
* rules for this locale. This locale will also be used for
|
||||
* standard number formatting.
|
||||
* @param type The plural type (e.g., cardinal or ordinal).
|
||||
* @param pattern the pattern for this <code>PluralFormat</code>.
|
||||
* errors are returned to status if the pattern is invalid.
|
||||
* @param status output param set to success/failure code on exit, which
|
||||
* must not indicate a failure before the function call.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
PluralFormat(const Locale& locale,
|
||||
UPluralType type,
|
||||
const UnicodeString& pattern,
|
||||
UErrorCode& status);
|
||||
|
||||
/**
|
||||
* copy constructor.
|
||||
* @stable ICU 4.0
|
||||
@ -359,7 +389,7 @@ public:
|
||||
* i.e., a pattern that was applied previously will be removed,
|
||||
* and the NumberFormat is set to the default number format for
|
||||
* the locale. The resulting format behaves the same as one
|
||||
* constructed from {@link #PluralFormat(const Locale& locale, UErrorCode& status)}.
|
||||
* constructed from {@link #PluralFormat(const Locale& locale, UPLURAL_TYPE_CARDINAL, UErrorCode& status)}.
|
||||
* @param locale the <code>locale</code> to use to configure the formatter.
|
||||
* @param status output param set to success/failure code on exit, which
|
||||
* must not indicate a failure before the function call.
|
||||
@ -532,7 +562,7 @@ private:
|
||||
PluralSelectorAdapter pluralRulesWrapper;
|
||||
|
||||
PluralFormat(); // default constructor not implemented
|
||||
void init(const PluralRules* rules, UErrorCode& status);
|
||||
void init(const PluralRules* rules, UPluralType type, UErrorCode& status);
|
||||
/**
|
||||
* Copies dynamically allocated values (pointer fields).
|
||||
* Others are copied using their copy constructors and assignment operators.
|
||||
|
@ -26,6 +26,7 @@
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/format.h"
|
||||
#include "unicode/upluralrules.h"
|
||||
|
||||
/**
|
||||
* Value returned by PluralRules::getUniqueKeywordValue() when there is no
|
||||
@ -183,8 +184,9 @@ public:
|
||||
static PluralRules* U_EXPORT2 createDefaultRules(UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Provides access to the predefined <code>PluralRules</code> for a given
|
||||
* Provides access to the predefined cardinal-number <code>PluralRules</code> for a given
|
||||
* locale.
|
||||
* Same as forLocale(locale, UPLURAL_TYPE_CARDINAL, status).
|
||||
*
|
||||
* @param locale The locale for which a <code>PluralRules</code> object is
|
||||
* returned.
|
||||
@ -199,6 +201,24 @@ public:
|
||||
*/
|
||||
static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Provides access to the predefined <code>PluralRules</code> for a given
|
||||
* locale and the plural type.
|
||||
*
|
||||
* @param locale The locale for which a <code>PluralRules</code> object is
|
||||
* returned.
|
||||
* @param type The plural type (e.g., cardinal or ordinal).
|
||||
* @param status Output param set to success/failure code on exit, which
|
||||
* must not indicate a failure before the function call.
|
||||
* @return The predefined <code>PluralRules</code> object pointer for
|
||||
* this locale. If there's no predefined rules for this locale,
|
||||
* the rules for the closest parent in the locale hierarchy
|
||||
* that has one will be returned. The final fallback always
|
||||
* returns the default 'other' rules.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UPluralType type, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Given a number, returns the keyword of the first rule that applies to
|
||||
* the number. This function can be used with isKeyword* functions to
|
||||
@ -359,7 +379,7 @@ private:
|
||||
void getNextLocale(const UnicodeString& localeData, int32_t* curIndex, UnicodeString& localeName);
|
||||
void addRules(RuleChain& rules);
|
||||
int32_t getNumberValue(const UnicodeString& token) const;
|
||||
UnicodeString getRuleFromResource(const Locale& locale, UErrorCode& status);
|
||||
UnicodeString getRuleFromResource(const Locale& locale, UPluralType type, UErrorCode& status);
|
||||
|
||||
static const int32_t MAX_SAMPLES = 3;
|
||||
|
||||
|
@ -37,6 +37,32 @@
|
||||
* http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* Type of plurals and PluralRules.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
enum UPluralType {
|
||||
/**
|
||||
* Plural rules for cardinal numbers: 1 file vs. 2 files.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
UPLURAL_TYPE_CARDINAL,
|
||||
/**
|
||||
* Plural rules for ordinal numbers: 1st file, 2nd file, 3rd file, 4th file, etc.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
UPLURAL_TYPE_ORDINAL,
|
||||
/**
|
||||
* Number of Plural rules types.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
UPLURAL_TYPE_COUNT
|
||||
};
|
||||
/**
|
||||
* @draft ICU 50
|
||||
*/
|
||||
typedef enum UPluralType UPluralType;
|
||||
|
||||
/**
|
||||
* Opaque UPluralRules object for use in C programs.
|
||||
* @stable ICU 4.8
|
||||
@ -45,19 +71,31 @@ struct UPluralRules;
|
||||
typedef struct UPluralRules UPluralRules; /**< C typedef for struct UPluralRules. @stable ICU 4.8 */
|
||||
|
||||
/**
|
||||
* Open a new UPluralRules object using the predefined plural rules for a
|
||||
* Opens a new UPluralRules object using the predefined cardinal-number plural rules for a
|
||||
* given locale.
|
||||
* Same as uplrules_openForType(locale, UPLURAL_TYPE_CARDINAL, status).
|
||||
* @param locale The locale for which the rules are desired.
|
||||
* @param status A pointer to a UErrorCode to receive any errors.
|
||||
* @return A UPluralRules for the specified locale, or 0 if an error occurred.
|
||||
* @return A UPluralRules for the specified locale, or NULL if an error occurred.
|
||||
* @stable ICU 4.8
|
||||
*/
|
||||
U_DRAFT UPluralRules* U_EXPORT2
|
||||
uplrules_open(const char *locale,
|
||||
UErrorCode *status);
|
||||
uplrules_open(const char *locale, UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Close a UPluralRules object. Once closed it may no longer be used.
|
||||
* Opens a new UPluralRules object using the predefined plural rules for a
|
||||
* given locale and the plural type.
|
||||
* @param locale The locale for which the rules are desired.
|
||||
* @param type The plural type (e.g., cardinal or ordinal).
|
||||
* @param status A pointer to a UErrorCode to receive any errors.
|
||||
* @return A UPluralRules for the specified locale, or NULL if an error occurred.
|
||||
* @draft ICU 50
|
||||
*/
|
||||
U_DRAFT UPluralRules* U_EXPORT2
|
||||
uplrules_openForType(const char *locale, UPluralType type, UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Closes a UPluralRules object. Once closed it may no longer be used.
|
||||
* @param uplrules The UPluralRules object to close.
|
||||
* @stable ICU 4.8
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*****************************************************************************************
|
||||
* Copyright (C) 2010-2011, International Business Machines
|
||||
* Copyright (C) 2010-2012, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*****************************************************************************************
|
||||
*/
|
||||
@ -18,10 +18,15 @@ U_NAMESPACE_USE
|
||||
|
||||
|
||||
U_CAPI UPluralRules* U_EXPORT2
|
||||
uplrules_open(const char *locale,
|
||||
UErrorCode *status)
|
||||
uplrules_open(const char *locale, UErrorCode *status)
|
||||
{
|
||||
return (UPluralRules*)PluralRules::forLocale(Locale(locale), *status);
|
||||
return uplrules_openForType(locale, UPLURAL_TYPE_CARDINAL, status);
|
||||
}
|
||||
|
||||
U_CAPI UPluralRules* U_EXPORT2
|
||||
uplrules_openForType(const char *locale, UPluralType type, UErrorCode *status)
|
||||
{
|
||||
return (UPluralRules*)PluralRules::forLocale(Locale(locale), type, *status);
|
||||
}
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
|
@ -1,5 +1,5 @@
|
||||
/********************************************************************
|
||||
* Copyright (c) 2011, International Business Machines Corporation
|
||||
* Copyright (c) 2011-2012, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
/* C API TEST FOR PLURAL RULES */
|
||||
@ -14,6 +14,7 @@
|
||||
#include "cmemory.h"
|
||||
|
||||
static void TestPluralRules(void);
|
||||
static void TestOrdinalRules(void);
|
||||
|
||||
void addPluralRulesTest(TestNode** root);
|
||||
|
||||
@ -22,6 +23,7 @@ void addPluralRulesTest(TestNode** root);
|
||||
void addPluralRulesTest(TestNode** root)
|
||||
{
|
||||
TESTCASE(TestPluralRules);
|
||||
TESTCASE(TestOrdinalRules);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@ -89,4 +91,22 @@ static void TestPluralRules()
|
||||
}
|
||||
}
|
||||
|
||||
static void TestOrdinalRules() {
|
||||
U_STRING_DECL(two, "two", 3);
|
||||
UChar keyword[8];
|
||||
int32_t length;
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
UPluralRules* upr = uplrules_openForType("en", UPLURAL_TYPE_ORDINAL, &errorCode);
|
||||
if (U_FAILURE(errorCode)) {
|
||||
log_err("uplrules_openForType(en, ordinal) failed - %s\n", u_errorName(errorCode));
|
||||
return;
|
||||
}
|
||||
U_STRING_INIT(two, "two", 3);
|
||||
length = uplrules_select(upr, 2., keyword, 8, &errorCode);
|
||||
if (U_FAILURE(errorCode) || u_strCompare(keyword, length, two, 3, FALSE) != 0) {
|
||||
log_err("uplrules_select(en-ordinal, 2) failed - %s\n", u_errorName(errorCode));
|
||||
}
|
||||
uplrules_close(upr);
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 2007-2011, International Business Machines Corporation and
|
||||
* Copyright (c) 2007-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
@ -31,15 +31,14 @@
|
||||
void PluralFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
|
||||
{
|
||||
if (exec) logln("TestSuite PluralFormat");
|
||||
switch (index) {
|
||||
TESTCASE(0, pluralFormatBasicTest);
|
||||
TESTCASE(1, pluralFormatUnitTest);
|
||||
TESTCASE(2, pluralFormatLocaleTest);
|
||||
TESTCASE(3, pluralFormatExtendedTest);
|
||||
TESTCASE(4, pluralFormatExtendedParseTest);
|
||||
default: name = "";
|
||||
break;
|
||||
}
|
||||
TESTCASE_AUTO_BEGIN;
|
||||
TESTCASE_AUTO(pluralFormatBasicTest);
|
||||
TESTCASE_AUTO(pluralFormatUnitTest);
|
||||
TESTCASE_AUTO(pluralFormatLocaleTest);
|
||||
TESTCASE_AUTO(pluralFormatExtendedTest);
|
||||
TESTCASE_AUTO(pluralFormatExtendedParseTest);
|
||||
TESTCASE_AUTO(ordinalFormatTest);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,7 +318,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
UnicodeString testPattern = UNICODE_STRING_SIMPLE("other{other}");
|
||||
uprv_memset(pluralResults, -1, sizeof(pluralResults));
|
||||
pluralResults[0]= PFT_OTHER; // other
|
||||
helperTestRusults(oneRuleLocales, 4, testPattern, pluralResults);
|
||||
helperTestResults(oneRuleLocales, 4, testPattern, pluralResults);
|
||||
|
||||
// ====== Test Singular1 locales.
|
||||
logln("Testing singular1 locales.");
|
||||
@ -332,7 +331,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[0]= PFT_OTHER;
|
||||
pluralResults[1]= PFT_ONE;
|
||||
pluralResults[2]= PFT_OTHER;
|
||||
helperTestRusults(singular1Locales, 52, testPattern, pluralResults);
|
||||
helperTestResults(singular1Locales, 52, testPattern, pluralResults);
|
||||
|
||||
// ======== Test Singular01 locales.
|
||||
logln("Testing singular1 locales.");
|
||||
@ -341,7 +340,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
uprv_memset(pluralResults, -1, sizeof(pluralResults));
|
||||
pluralResults[0]= PFT_ONE;
|
||||
pluralResults[2]= PFT_OTHER;
|
||||
helperTestRusults(singular01Locales, 3, testPattern, pluralResults);
|
||||
helperTestResults(singular01Locales, 3, testPattern, pluralResults);
|
||||
|
||||
// ======== Test ZeroSingular locales.
|
||||
logln("Testing singular1 locales.");
|
||||
@ -356,7 +355,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[i*10+1] = PFT_ONE;
|
||||
pluralResults[i*10+2] = PFT_OTHER;
|
||||
}
|
||||
helperTestRusults(zeroSingularLocales, 1, testPattern, pluralResults);
|
||||
helperTestResults(zeroSingularLocales, 1, testPattern, pluralResults);
|
||||
|
||||
// ======== Test singular dual locales.
|
||||
logln("Testing singular1 locales.");
|
||||
@ -367,7 +366,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[1]= PFT_ONE;
|
||||
pluralResults[2]= PFT_TWO;
|
||||
pluralResults[3]= PFT_OTHER;
|
||||
helperTestRusults(singularDualLocales, 1, testPattern, pluralResults);
|
||||
helperTestResults(singularDualLocales, 1, testPattern, pluralResults);
|
||||
|
||||
// ======== Test Singular Zero Some locales.
|
||||
logln("Testing singular1 locales.");
|
||||
@ -381,7 +380,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[100+i] = PFT_FEW;
|
||||
}
|
||||
pluralResults[1]= PFT_ONE;
|
||||
helperTestRusults(singularZeroSomeLocales, 1, testPattern, pluralResults);
|
||||
helperTestResults(singularZeroSomeLocales, 1, testPattern, pluralResults);
|
||||
|
||||
// ======== Test Special 12/19.
|
||||
logln("Testing special 12 and 19.");
|
||||
@ -398,7 +397,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[i*10+2] = PFT_FEW;
|
||||
pluralResults[(i+1)*10] = PFT_OTHER;
|
||||
}
|
||||
helperTestRusults(special12_19Locales, 1, testPattern, pluralResults);
|
||||
helperTestResults(special12_19Locales, 1, testPattern, pluralResults);
|
||||
|
||||
// ======== Test Paucal Except 11 14.
|
||||
logln("Testing Paucal Except 11 and 14.");
|
||||
@ -423,7 +422,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[i*10+8] = PFT_MANY;
|
||||
pluralResults[i*10+9] = PFT_MANY;
|
||||
}
|
||||
helperTestRusults(paucal01Locales, 4, testPattern, pluralResults);
|
||||
helperTestResults(paucal01Locales, 4, testPattern, pluralResults);
|
||||
|
||||
// ======== Test Singular Paucal.
|
||||
logln("Testing Singular Paucal.");
|
||||
@ -434,7 +433,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[1]= PFT_ONE;
|
||||
pluralResults[2]= PFT_FEW;
|
||||
pluralResults[5]= PFT_OTHER;
|
||||
helperTestRusults(singularPaucalLocales, 2, testPattern, pluralResults);
|
||||
helperTestResults(singularPaucalLocales, 2, testPattern, pluralResults);
|
||||
|
||||
// ======== Test Paucal (1), (2,3,4).
|
||||
logln("Testing Paucal (1), (2,3,4).");
|
||||
@ -457,7 +456,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[i*10+5] = PFT_OTHER;
|
||||
}
|
||||
}
|
||||
helperTestRusults(paucal02Locales, 1, testPattern, pluralResults);
|
||||
helperTestResults(paucal02Locales, 1, testPattern, pluralResults);
|
||||
|
||||
// ======== Test Paucal (1), (2), (3,4).
|
||||
logln("Testing Paucal (1), (2), (3,4).");
|
||||
@ -473,7 +472,7 @@ PluralFormatTest::pluralFormatLocaleTest(/*char *par*/)
|
||||
pluralResults[102]= PFT_TWO;
|
||||
pluralResults[103]= PFT_FEW;
|
||||
pluralResults[105]= PFT_OTHER;
|
||||
helperTestRusults(paucal03Locales, 1, testPattern, pluralResults);
|
||||
helperTestResults(paucal03Locales, 1, testPattern, pluralResults);
|
||||
|
||||
// TODO: move this test to Unit Test after CLDR 1.6 is final and we support float
|
||||
// ======= Test French "WITHIN rule
|
||||
@ -580,6 +579,48 @@ PluralFormatTest::pluralFormatExtendedParseTest(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluralFormatTest::ordinalFormatTest(void) {
|
||||
IcuTestErrorCode errorCode(*this, "ordinalFormatTest");
|
||||
UnicodeString pattern("one{#st file}two{#nd file}few{#rd file}other{#th file}");
|
||||
PluralFormat pf(Locale::getEnglish(), UPLURAL_TYPE_ORDINAL, pattern, errorCode);
|
||||
if (errorCode.logIfFailureAndReset("PluralFormat(en, UPLURAL_TYPE_ORDINAL, pattern) failed")) {
|
||||
return;
|
||||
}
|
||||
UnicodeString result = pf.format(321, errorCode);
|
||||
if (!errorCode.logIfFailureAndReset("PluralFormat.format(321) failed") &&
|
||||
result != UNICODE_STRING_SIMPLE("321st file")) {
|
||||
errln(UnicodeString("PluralFormat.format(321) wrong result string: ") + result);
|
||||
}
|
||||
result = pf.format(22, errorCode);
|
||||
if (!errorCode.logIfFailureAndReset("PluralFormat.format(22) failed") &&
|
||||
result != UNICODE_STRING_SIMPLE("22nd file")) {
|
||||
errln(UnicodeString("PluralFormat.format(22) wrong result string: ") + result);
|
||||
}
|
||||
result = pf.format(3, errorCode);
|
||||
if (!errorCode.logIfFailureAndReset("PluralFormat.format(3) failed") &&
|
||||
result != UNICODE_STRING_SIMPLE("3rd file")) {
|
||||
errln(UnicodeString("PluralFormat.format(3) wrong result string: ") + result);
|
||||
}
|
||||
|
||||
// Code coverage: Use the other new-for-UPluralType constructor as well.
|
||||
PluralFormat pf2(Locale::getEnglish(), UPLURAL_TYPE_ORDINAL, errorCode);
|
||||
pf2.applyPattern(pattern, errorCode);
|
||||
if (errorCode.logIfFailureAndReset("PluralFormat(en, UPLURAL_TYPE_ORDINAL, pattern) failed")) {
|
||||
return;
|
||||
}
|
||||
result = pf2.format(456, errorCode);
|
||||
if (!errorCode.logIfFailureAndReset("PluralFormat.format(456) failed") &&
|
||||
result != UNICODE_STRING_SIMPLE("456th file")) {
|
||||
errln(UnicodeString("PluralFormat.format(456) wrong result string: ") + result);
|
||||
}
|
||||
result = pf2.format(111, errorCode);
|
||||
if (!errorCode.logIfFailureAndReset("PluralFormat.format(111) failed") &&
|
||||
result != UNICODE_STRING_SIMPLE("111th file")) {
|
||||
errln(UnicodeString("PluralFormat.format(111) wrong result string: ") + result);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluralFormatTest::numberFormatTest(PluralFormat* plFmt,
|
||||
NumberFormat *numFmt,
|
||||
@ -634,7 +675,7 @@ PluralFormatTest::numberFormatTest(PluralFormat* plFmt,
|
||||
|
||||
|
||||
void
|
||||
PluralFormatTest::helperTestRusults(const char** localeArray,
|
||||
PluralFormatTest::helperTestResults(const char** localeArray,
|
||||
int32_t capacityOfArray,
|
||||
UnicodeString& testPattern,
|
||||
int8_t *expResults) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2011, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
@ -31,6 +31,7 @@ private:
|
||||
void pluralFormatLocaleTest(/* char* par */);
|
||||
void pluralFormatExtendedTest();
|
||||
void pluralFormatExtendedParseTest();
|
||||
void ordinalFormatTest();
|
||||
void numberFormatTest(PluralFormat* plFmt,
|
||||
NumberFormat *numFmt,
|
||||
int32_t start,
|
||||
@ -39,7 +40,7 @@ private:
|
||||
UnicodeString* numEvenAppendStr,
|
||||
UBool overwrite, // overwrite the numberFormat.format result
|
||||
UnicodeString *message);
|
||||
void helperTestRusults(const char** localeArray,
|
||||
void helperTestResults(const char** localeArray,
|
||||
int32_t capacityOfArray,
|
||||
UnicodeString& testPattern,
|
||||
int8_t *expectingResults);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007-2011, International Business Machines Corporation and
|
||||
* Copyright (C) 2007-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************************
|
||||
|
||||
@ -15,13 +15,14 @@
|
||||
|
||||
#include <stdlib.h> // for strtod
|
||||
#include "plurults.h"
|
||||
#include "unicode/localpointer.h"
|
||||
#include "unicode/plurrule.h"
|
||||
|
||||
#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof(array[0]))
|
||||
|
||||
void setupResult(const int32_t testSource[], char result[], int32_t* max);
|
||||
UBool checkEqual(PluralRules *test, char *result, int32_t max);
|
||||
UBool testEquality(PluralRules *test);
|
||||
UBool checkEqual(const PluralRules &test, char *result, int32_t max);
|
||||
UBool testEquality(const PluralRules &test);
|
||||
|
||||
// This is an API test, not a unit test. It doesn't test very many cases, and doesn't
|
||||
// try to test the full functionality. It just calls each function in the class and
|
||||
@ -30,14 +31,14 @@ UBool testEquality(PluralRules *test);
|
||||
void PluralRulesTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
|
||||
{
|
||||
if (exec) logln("TestSuite PluralRulesAPI");
|
||||
switch (index) {
|
||||
TESTCASE(0, testAPI);
|
||||
TESTCASE(1, testGetUniqueKeywordValue);
|
||||
TESTCASE(2, testGetSamples);
|
||||
TESTCASE(3, testWithin);
|
||||
TESTCASE(4, testGetAllKeywordValues);
|
||||
default: name = ""; break;
|
||||
}
|
||||
TESTCASE_AUTO_BEGIN;
|
||||
TESTCASE_AUTO(testAPI);
|
||||
TESTCASE_AUTO(testGetUniqueKeywordValue);
|
||||
TESTCASE_AUTO(testGetSamples);
|
||||
TESTCASE_AUTO(testWithin);
|
||||
TESTCASE_AUTO(testGetAllKeywordValues);
|
||||
TESTCASE_AUTO(testOrdinal);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
#define PLURAL_TEST_NUM 18
|
||||
@ -94,19 +95,17 @@ void PluralRulesTest::testAPI(/*char *par*/)
|
||||
logln("\n start default locale test case ..\n");
|
||||
|
||||
PluralRules defRule(status);
|
||||
PluralRules* test=new PluralRules(status);
|
||||
PluralRules* newEnPlural= test->forLocale(Locale::getEnglish(), status);
|
||||
LocalPointer<PluralRules> test(new PluralRules(status));
|
||||
LocalPointer<PluralRules> newEnPlural(test->forLocale(Locale::getEnglish(), status));
|
||||
if(U_FAILURE(status)) {
|
||||
dataerrln("ERROR: Could not create PluralRules (default) - exitting");
|
||||
delete test;
|
||||
return;
|
||||
}
|
||||
|
||||
// ======= Test clone, assignment operator && == operator.
|
||||
PluralRules *dupRule = defRule.clone();
|
||||
LocalPointer<PluralRules> dupRule(defRule.clone());
|
||||
if (dupRule==NULL) {
|
||||
errln("ERROR: clone plural rules test failed!");
|
||||
delete test;
|
||||
return;
|
||||
} else {
|
||||
if ( *dupRule != defRule ) {
|
||||
@ -118,15 +117,12 @@ void PluralRulesTest::testAPI(/*char *par*/)
|
||||
if ( *dupRule != *newEnPlural ) {
|
||||
errln("ERROR: clone plural rules test failed!");
|
||||
}
|
||||
delete dupRule;
|
||||
}
|
||||
|
||||
delete newEnPlural;
|
||||
|
||||
// ======= Test empty plural rules
|
||||
logln("Testing Simple PluralRules");
|
||||
|
||||
PluralRules* empRule = test->createRules(UNICODE_STRING_SIMPLE("a:n"), status);
|
||||
LocalPointer<PluralRules> empRule(test->createRules(UNICODE_STRING_SIMPLE("a:n"), status));
|
||||
UnicodeString key;
|
||||
for (int32_t i=0; i<10; ++i) {
|
||||
key = empRule->select(i);
|
||||
@ -134,9 +130,6 @@ void PluralRulesTest::testAPI(/*char *par*/)
|
||||
errln("ERROR: empty plural rules test failed! - exitting");
|
||||
}
|
||||
}
|
||||
if (empRule!=NULL) {
|
||||
delete empRule;
|
||||
}
|
||||
|
||||
// ======= Test simple plural rules
|
||||
logln("Testing Simple PluralRules");
|
||||
@ -145,19 +138,14 @@ void PluralRulesTest::testAPI(/*char *par*/)
|
||||
int32_t max;
|
||||
|
||||
for (int32_t i=0; i<PLURAL_TEST_NUM-1; ++i) {
|
||||
PluralRules *newRules = test->createRules(pluralTestData[i], status);
|
||||
LocalPointer<PluralRules> newRules(test->createRules(pluralTestData[i], status));
|
||||
setupResult(pluralTestResult[i], result, &max);
|
||||
if ( !checkEqual(newRules, result, max) ) {
|
||||
if ( !checkEqual(*newRules, result, max) ) {
|
||||
errln("ERROR: simple plural rules failed! - exitting");
|
||||
delete test;
|
||||
return;
|
||||
}
|
||||
if (newRules!=NULL) {
|
||||
delete newRules;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ======= Test complex plural rules
|
||||
logln("Testing Complex PluralRules");
|
||||
// TODO: the complex test data is hard coded. It's better to implement
|
||||
@ -179,35 +167,24 @@ void PluralRulesTest::testAPI(/*char *par*/)
|
||||
0x6F, // 'o'
|
||||
0x63 // 'c'
|
||||
};
|
||||
PluralRules *newRules = test->createRules(complexRule, status);
|
||||
if ( !checkEqual(newRules, cRuleResult, 12) ) {
|
||||
LocalPointer<PluralRules> newRules(test->createRules(complexRule, status));
|
||||
if ( !checkEqual(*newRules, cRuleResult, 12) ) {
|
||||
errln("ERROR: complex plural rules failed! - exitting");
|
||||
delete test;
|
||||
return;
|
||||
}
|
||||
if (newRules!=NULL) {
|
||||
delete newRules;
|
||||
newRules=NULL;
|
||||
}
|
||||
newRules = test->createRules(complexRule2, status);
|
||||
if ( !checkEqual(newRules, cRuleResult, 12) ) {
|
||||
newRules.adoptInstead(test->createRules(complexRule2, status));
|
||||
if ( !checkEqual(*newRules, cRuleResult, 12) ) {
|
||||
errln("ERROR: complex plural rules failed! - exitting");
|
||||
delete test;
|
||||
return;
|
||||
}
|
||||
if (newRules!=NULL) {
|
||||
delete newRules;
|
||||
newRules=NULL;
|
||||
}
|
||||
|
||||
// ======= Test decimal fractions plural rules
|
||||
UnicodeString decimalRule= UNICODE_STRING_SIMPLE("a: n not in 0..100;");
|
||||
UnicodeString KEYWORD_A = UNICODE_STRING_SIMPLE("a");
|
||||
status = U_ZERO_ERROR;
|
||||
newRules = test->createRules(decimalRule, status);
|
||||
newRules.adoptInstead(test->createRules(decimalRule, status));
|
||||
if (U_FAILURE(status)) {
|
||||
dataerrln("ERROR: Could not create PluralRules for testing fractions - exitting");
|
||||
delete test;
|
||||
return;
|
||||
}
|
||||
double fData[10] = {-100, -1, -0.0, 0, 0.1, 1, 1.999, 2.0, 100, 100.001 };
|
||||
@ -218,20 +195,12 @@ void PluralRulesTest::testAPI(/*char *par*/)
|
||||
errln("ERROR: plural rules for decimal fractions test failed!");
|
||||
}
|
||||
}
|
||||
if (newRules!=NULL) {
|
||||
delete newRules;
|
||||
newRules=NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ======= Test Equality
|
||||
logln("Testing Equality of PluralRules");
|
||||
|
||||
|
||||
if ( !testEquality(test) ) {
|
||||
if ( !testEquality(*test) ) {
|
||||
errln("ERROR: complex plural rules failed! - exitting");
|
||||
delete test;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -243,26 +212,21 @@ void PluralRulesTest::testAPI(/*char *par*/)
|
||||
errln("ERROR: getDynamicClassID() didn't return the expected value");
|
||||
}
|
||||
// ====== Test fallback to parent locale
|
||||
PluralRules *en_UK = test->forLocale(Locale::getUK(), status);
|
||||
PluralRules *en = test->forLocale(Locale::getEnglish(), status);
|
||||
if (en_UK != NULL && en != NULL) {
|
||||
LocalPointer<PluralRules> en_UK(test->forLocale(Locale::getUK(), status));
|
||||
LocalPointer<PluralRules> en(test->forLocale(Locale::getEnglish(), status));
|
||||
if (en_UK.isValid() && en.isValid()) {
|
||||
if ( *en_UK != *en ) {
|
||||
errln("ERROR: test locale fallback failed!");
|
||||
}
|
||||
}
|
||||
delete en;
|
||||
delete en_UK;
|
||||
|
||||
PluralRules *zh_Hant = test->forLocale(Locale::getTaiwan(), status);
|
||||
PluralRules *zh = test->forLocale(Locale::getChinese(), status);
|
||||
if (zh_Hant != NULL && zh != NULL) {
|
||||
LocalPointer<PluralRules> zh_Hant(test->forLocale(Locale::getTaiwan(), status));
|
||||
LocalPointer<PluralRules> zh(test->forLocale(Locale::getChinese(), status));
|
||||
if (zh_Hant.isValid() && zh.isValid()) {
|
||||
if ( *zh_Hant != *zh ) {
|
||||
errln("ERROR: test locale fallback failed!");
|
||||
}
|
||||
}
|
||||
delete zh_Hant;
|
||||
delete zh;
|
||||
delete test;
|
||||
}
|
||||
|
||||
void setupResult(const int32_t testSource[], char result[], int32_t* max) {
|
||||
@ -280,11 +244,11 @@ void setupResult(const int32_t testSource[], char result[], int32_t* max) {
|
||||
}
|
||||
|
||||
|
||||
UBool checkEqual(PluralRules *test, char *result, int32_t max) {
|
||||
UBool checkEqual(const PluralRules &test, char *result, int32_t max) {
|
||||
UnicodeString key;
|
||||
UBool isEqual = TRUE;
|
||||
for (int32_t i=0; i<max; ++i) {
|
||||
key= test->select(i);
|
||||
key= test.select(i);
|
||||
if ( key.charAt(0)!=result[i] ) {
|
||||
isEqual = FALSE;
|
||||
}
|
||||
@ -294,7 +258,7 @@ UBool checkEqual(PluralRules *test, char *result, int32_t max) {
|
||||
|
||||
#define MAX_EQ_ROW 2
|
||||
#define MAX_EQ_COL 5
|
||||
UBool testEquality(PluralRules *test) {
|
||||
UBool testEquality(const PluralRules &test) {
|
||||
UnicodeString testEquRules[MAX_EQ_ROW][MAX_EQ_COL] = {
|
||||
{ UNICODE_STRING_SIMPLE("a: n in 2..3"),
|
||||
UNICODE_STRING_SIMPLE("a: n is 2 or n is 3"),
|
||||
@ -318,7 +282,7 @@ UBool testEquality(PluralRules *test) {
|
||||
}
|
||||
int32_t totalRules=0;
|
||||
while((totalRules<MAX_EQ_COL) && (testEquRules[i][totalRules].length()>0) ) {
|
||||
rules[totalRules]=test->createRules(testEquRules[i][totalRules], status);
|
||||
rules[totalRules]=test.createRules(testEquRules[i][totalRules], status);
|
||||
totalRules++;
|
||||
}
|
||||
for (int32_t n=0; n<300 && ret ; ++n) {
|
||||
@ -572,4 +536,16 @@ PluralRulesTest::testGetAllKeywordValues() {
|
||||
}
|
||||
}
|
||||
|
||||
void PluralRulesTest::testOrdinal() {
|
||||
IcuTestErrorCode errorCode(*this, "testOrdinal");
|
||||
LocalPointer<PluralRules> pr(PluralRules::forLocale("en", UPLURAL_TYPE_ORDINAL, errorCode));
|
||||
if (errorCode.logIfFailureAndReset("PluralRules::forLocale(en, UPLURAL_TYPE_ORDINAL) failed")) {
|
||||
return;
|
||||
}
|
||||
UnicodeString keyword = pr->select(2.);
|
||||
if (keyword != UNICODE_STRING("two", 3)) {
|
||||
errln("PluralRules(en-ordinal).select(2) failed");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2011, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
@ -28,6 +28,7 @@ private:
|
||||
void testGetSamples();
|
||||
void testWithin();
|
||||
void testGetAllKeywordValues();
|
||||
void testOrdinal();
|
||||
|
||||
void assertRuleValue(const UnicodeString& rule, double expected);
|
||||
void assertRuleKeyValue(const UnicodeString& rule, const UnicodeString& key,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2011, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************
|
||||
* File TMSGFMT.CPP
|
||||
@ -64,6 +64,7 @@ TestMessageFormat::runIndexedTest(int32_t index, UBool exec,
|
||||
TESTCASE_AUTO(TestCompatibleApostrophe);
|
||||
TESTCASE_AUTO(testCoverage);
|
||||
TESTCASE_AUTO(TestTrimArgumentName);
|
||||
TESTCASE_AUTO(TestOrdinalPlural);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
@ -1812,4 +1813,34 @@ void TestMessageFormat::TestTrimArgumentName() {
|
||||
m.format(&argName, args, 1, result, errorCode));
|
||||
}
|
||||
|
||||
void TestMessageFormat::TestOrdinalPlural() {
|
||||
IcuTestErrorCode errorCode(*this, "TestOrdinalPlural");
|
||||
// Test plural & ordinal together,
|
||||
// to make sure that we get the correct cached PluralSelector for each.
|
||||
MessageFormat m(
|
||||
"{0,plural,one{1 file}other{# files}}, "
|
||||
"{0,plordinal,one{#st file}two{#nd file}few{#rd file}other{#th file}}",
|
||||
Locale::getEnglish(), errorCode);
|
||||
if (errorCode.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) {
|
||||
return;
|
||||
}
|
||||
Formattable args[1] = { (int32_t)21 };
|
||||
FieldPosition ignore(0);
|
||||
UnicodeString result;
|
||||
assertEquals("plural-ordinal format(21) failed", "21 files, 21st file",
|
||||
m.format(args, 1, result, ignore, errorCode));
|
||||
|
||||
args[0].setLong(2);
|
||||
assertEquals("plural-ordinal format(2) failed", "2 files, 2nd file",
|
||||
m.format(args, 1, result.remove(), ignore, errorCode));
|
||||
|
||||
args[0].setLong(1);
|
||||
assertEquals("plural-ordinal format(1) failed", "1 file, 1st file",
|
||||
m.format(args, 1, result.remove(), ignore, errorCode));
|
||||
|
||||
args[0].setLong(3);
|
||||
assertEquals("plural-ordinal format(3) failed", "3 files, 3rd file",
|
||||
m.format(args, 1, result.remove(), ignore, errorCode));
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2011, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
#ifndef _TESTMESSAGEFORMAT
|
||||
@ -114,6 +114,7 @@ public:
|
||||
void TestTurkishCasing(void);
|
||||
void testAutoQuoteApostrophe(void);
|
||||
void TestTrimArgumentName();
|
||||
void TestOrdinalPlural();
|
||||
|
||||
/* Provide better code coverage */
|
||||
void testCoverage(void);
|
||||
|
Loading…
Reference in New Issue
Block a user