/*
*******************************************************************************
-* Copyright (C) 2011, International Business Machines
+* Copyright (C) 2011-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
* file name: messagepattern.cpp
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;
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;
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);
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);
} 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;
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;
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
((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;
*/
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
* 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
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.
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"}
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"}
}
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2011, International Business Machines Corporation and
+ * Copyright (c) 1997-2012, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************
*
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);
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);
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);
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;
fLocale = theLocale;
setLocaleIDs(fLocale.getName(), fLocale.getName());
pluralProvider.reset(&fLocale);
+ ordinalProvider.reset(&fLocale);
}
}
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,
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;
}
case UMSGPAT_ARG_TYPE_CHOICE:
case UMSGPAT_ARG_TYPE_PLURAL:
+ case UMSGPAT_ARG_TYPE_ORDINAL:
formattableType = Formattable::kDouble;
break;
case UMSGPAT_ARG_TYPE_SELECT:
}
-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() {
}
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);
}
msgPattern(status),
numberFormat(NULL),
offset(0) {
- init(NULL, status);
+ init(NULL, UPLURAL_TYPE_CARDINAL, status);
}
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)
msgPattern(status),
numberFormat(NULL),
offset(0) {
- init(&rules, status);
+ init(&rules, UPLURAL_TYPE_COUNT, status);
}
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,
msgPattern(status),
numberFormat(NULL),
offset(0) {
- init(NULL, status);
+ init(NULL, UPLURAL_TYPE_CARDINAL, status);
applyPattern(pat, status);
}
msgPattern(status),
numberFormat(NULL),
offset(0) {
- init(NULL, status);
+ init(NULL, UPLURAL_TYPE_CARDINAL, status);
applyPattern(pat, status);
}
msgPattern(status),
numberFormat(NULL),
offset(0) {
- init(&rules, status);
+ init(&rules, UPLURAL_TYPE_COUNT, status);
applyPattern(pat, status);
}
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);
}
}
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) {
offset = 0;
numberFormat = NULL;
pluralRulesWrapper.reset();
- init(NULL, status);
+ init(NULL, UPLURAL_TYPE_CARDINAL, status);
}
void
/*
*******************************************************************************
-* 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"
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)) {
}
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.
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;
}
}
if (s==NULL) {
- ures_close(locRes);
- ures_close(rb);
return emptyStr;
}
// 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;
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);
}
* <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}
*/
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;
private:
const Locale* locale;
PluralRules* rules;
+ UPluralType type;
};
/**
UHashtable* customFormatArgStarts;
PluralSelectorProvider pluralProvider;
+ PluralSelectorProvider ordinalProvider;
/**
* Method to retrieve default formats (or NULL on failure).
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
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.
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>.
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.
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
* 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.
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.
#if !UCONFIG_NO_FORMATTING
#include "unicode/format.h"
+#include "unicode/upluralrules.h"
/**
* Value returned by PluralRules::getUniqueKeywordValue() when there is no
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.
*/
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
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;
* 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
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);
+
+/**
+ * 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);
/**
- * Close a UPluralRules object. Once closed it may no longer be used.
+ * Closes a UPluralRules object. Once closed it may no longer be used.
* @param uplrules The UPluralRules object to close.
* @stable ICU 4.8
*/
/*
*****************************************************************************************
-* Copyright (C) 2010-2011, International Business Machines
+* Copyright (C) 2010-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*****************************************************************************************
*/
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
/********************************************************************
- * 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 */
#include "cmemory.h"
static void TestPluralRules(void);
+static void TestOrdinalRules(void);
void addPluralRulesTest(TestNode** root);
void addPluralRulesTest(TestNode** root)
{
TESTCASE(TestPluralRules);
+ TESTCASE(TestOrdinalRules);
}
typedef struct {
}
}
+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 */
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 2007-2011, International Business Machines Corporation and
+ * Copyright (c) 2007-2012, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
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;
}
/**
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.");
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.");
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.");
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.");
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.");
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.");
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.");
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.");
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).");
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).");
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
}
}
+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,
void
-PluralFormatTest::helperTestRusults(const char** localeArray,
+PluralFormatTest::helperTestResults(const char** localeArray,
int32_t capacityOfArray,
UnicodeString& testPattern,
int8_t *expResults) {
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2011, International Business Machines Corporation and
+ * Copyright (c) 1997-2012, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
void pluralFormatLocaleTest(/* char* par */);
void pluralFormatExtendedTest();
void pluralFormatExtendedParseTest();
+ void ordinalFormatTest();
void numberFormatTest(PluralFormat* plFmt,
NumberFormat *numFmt,
int32_t start,
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);
/*
*******************************************************************************
-* Copyright (C) 2007-2011, International Business Machines Corporation and
+* Copyright (C) 2007-2012, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************************
#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
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
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 ) {
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);
errln("ERROR: empty plural rules test failed! - exitting");
}
}
- if (empRule!=NULL) {
- delete empRule;
- }
// ======= Test simple plural rules
logln("Testing Simple PluralRules");
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
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 };
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;
}
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) {
}
-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;
}
#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"),
}
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) {
}
}
+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 */
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2011, International Business Machines Corporation and
+ * Copyright (c) 1997-2012, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
void testGetSamples();
void testWithin();
void testGetAllKeywordValues();
+ void testOrdinal();
void assertRuleValue(const UnicodeString& rule, double expected);
void assertRuleKeyValue(const UnicodeString& rule, const UnicodeString& key,
/********************************************************************
* 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
TESTCASE_AUTO(TestCompatibleApostrophe);
TESTCASE_AUTO(testCoverage);
TESTCASE_AUTO(TestTrimArgumentName);
+ TESTCASE_AUTO(TestOrdinalPlural);
TESTCASE_AUTO_END;
}
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 */
/********************************************************************
* 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
void TestTurkishCasing(void);
void testAutoQuoteApostrophe(void);
void TestTrimArgumentName();
+ void TestOrdinalPlural();
/* Provide better code coverage */
void testCoverage(void);