// The key must be one of the plural form strings. For example:
// one{"{0} hr"}
// other{"{0} hrs"}
- if (!outer.hasPatterns) {
- outer.cacheData.formatters[outer.unitIndex][outer.width].add(
- key, value.getUnicodeString(errorCode), errorCode);
- }
+ outer.cacheData.formatters[outer.unitIndex][outer.width].
+ addIfAbsent(key, value, errorCode);
}
}
UnitDataSink &outer;
if (U_FAILURE(errorCode)) { return NULL; }
outer.unitIndex = MeasureUnit::internalGetIndexForTypeAndSubtype(outer.type, key);
if (outer.unitIndex >= 0) {
- outer.hasPatterns =
- outer.cacheData.formatters[outer.unitIndex][outer.width].isValid();
return &outer.patternSink;
}
return NULL;
UnitDataSink(MeasureFormatCacheData &outputData)
: patternSink(*this), subtypeSink(*this), compoundSink(*this), typeSink(*this),
cacheData(outputData),
- width(UMEASFMT_WIDTH_COUNT), type(NULL), unitIndex(0), hasPatterns(FALSE) {}
+ width(UMEASFMT_WIDTH_COUNT), type(NULL), unitIndex(0) {}
~UnitDataSink();
virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
// Handle aliases like
UMeasureFormatWidth width;
const char *type;
int32_t unitIndex;
-
- /** True if we already have plural-form display patterns for width/type/unitIndex. */
- UBool hasPatterns;
};
// Virtual destructors must be defined out of line.
******************************************************************************
* quantityformatter.cpp
*/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
#include "quantityformatter.h"
#include "simplepatternformatter.h"
#include "uassert.h"
#include "charstr.h"
#include "unicode/fmtable.h"
#include "unicode/fieldpos.h"
+#include "resource.h"
#include "visibledigits.h"
-
-#if !UCONFIG_NO_FORMATTING
+#include "uassert.h"
U_NAMESPACE_BEGIN
}
}
-UBool QuantityFormatter::add(
+UBool QuantityFormatter::addIfAbsent(
const char *variant,
- const UnicodeString &rawPattern,
+ const UnicodeString *rawPattern,
+ const ResourceValue *patternValue,
UErrorCode &status) {
if (U_FAILURE(status)) {
return FALSE;
}
int32_t pluralIndex = getPluralIndex(variant);
- if (pluralIndex == -1) {
+ if (pluralIndex < 0) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return FALSE;
}
- SimplePatternFormatter *newFmt =
- new SimplePatternFormatter(rawPattern);
+ if (formatters[pluralIndex] != NULL) {
+ return TRUE;
+ }
+ const UnicodeString &pattern =
+ rawPattern != NULL ? *rawPattern : patternValue->getUnicodeString(status);
+ SimplePatternFormatter *newFmt = new SimplePatternFormatter(pattern);
if (newFmt == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return FALSE;
status = U_ILLEGAL_ARGUMENT_ERROR;
return FALSE;
}
- delete formatters[pluralIndex];
formatters[pluralIndex] = newFmt;
return TRUE;
}
const SimplePatternFormatter *QuantityFormatter::getByVariant(
const char *variant) const {
+ U_ASSERT(isValid());
int32_t pluralIndex = getPluralIndex(variant);
if (pluralIndex == -1) {
pluralIndex = 0;
/*
******************************************************************************
-* Copyright (C) 2014, International Business Machines
+* Copyright (C) 2014-2015, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* quantityformatter.h
#if !UCONFIG_NO_FORMATTING
+#include "resource.h"
+
U_NAMESPACE_BEGIN
class SimplePatternFormatter;
void reset();
/**
- * Adds a plural variant.
- *
- * @param variant "zero", "one", "two", "few", "many", "other"
- * @param rawPattern the pattern for the variant e.g "{0} meters"
- * @param status any error returned here.
- * @return TRUE on success; FALSE if status was set to a non zero error.
- */
- UBool add(
- const char *variant,
- const UnicodeString &rawPattern,
- UErrorCode &status);
+ * Adds a plural variant if there is none yet for the plural form.
+ *
+ * @param variant "zero", "one", "two", "few", "many", "other"
+ * @param rawPattern the pattern for the variant e.g "{0} meters"
+ * @param status any error returned here.
+ * @return TRUE on success; FALSE if status was set to a non zero error.
+ */
+ UBool addIfAbsent(const char *variant, const UnicodeString &rawPattern, UErrorCode &status) {
+ return addIfAbsent(variant, &rawPattern, NULL, status);
+ }
+
+ /**
+ * Adds a plural variant if there is none yet for the plural form.
+ * This version only calls ResourceValue::getString()
+ * if there is no template yet for the plural form.
+ *
+ * @param variant "zero", "one", "two", "few", "many", "other"
+ * @param rawPattern the pattern for the variant e.g "{0} meters"
+ * @param status any error returned here.
+ * @return TRUE on success; FALSE if status was set to a non zero error.
+ */
+ UBool addIfAbsent(const char *variant, const ResourceValue &rawPattern, UErrorCode &status) {
+ return addIfAbsent(variant, NULL, &rawPattern, status);
+ }
/**
* returns TRUE if this object has at least the "other" variant.
UErrorCode &status) const;
private:
+ UBool addIfAbsent(
+ const char *variant,
+ const UnicodeString *rawPattern,
+ const ResourceValue *patternValue,
+ UErrorCode &status);
+
SimplePatternFormatter *formatters[6];
};
/*
******************************************************************************
-* Copyright (C) 2014, International Business Machines Corporation and
-* others. All Rights Reserved.
+* Copyright (C) 2014-2015, International Business Machines Corporation and
+* others. All Rights Reserved.
******************************************************************************
-*
-* File RELDATEFMT.CPP
+*
+* File reldatefmt.cpp
******************************************************************************
*/
if (!getString(pluralBundle.getAlias(), rawPattern, status)) {
return;
}
- if (!formatter.add(
+ if (!formatter.addIfAbsent(
ures_getKey(pluralBundle.getAlias()),
rawPattern,
status)) {
LocalPointer<IntlTest> test(createQuantityFormatterTest());
callTest(*test, par);
}
+ break;
case 23:
name = "PluralMapTest";
if (exec) {
void TestGroupingSeparator();
void TestDoubleZero();
void TestUnitPerUnitResolution();
+ void TestIndividualPluralFallback();
void verifyFormat(
const char *description,
const MeasureFormat &fmt,
TESTCASE_AUTO(TestGroupingSeparator);
TESTCASE_AUTO(TestDoubleZero);
TESTCASE_AUTO(TestUnitPerUnitResolution);
+ TESTCASE_AUTO(TestIndividualPluralFallback);
TESTCASE_AUTO_END;
}
assertEquals("", "50 psi", actual);
}
+void MeasureFormatTest::TestIndividualPluralFallback() {
+ // See ticket #11986 "incomplete fallback in MeasureFormat".
+ // In CLDR 28, fr_CA temperature-generic/short has only the "one" form,
+ // and falls back to fr for the "other" form.
+ IcuTestErrorCode errorCode(*this, "TestIndividualPluralFallback");
+ MeasureFormat mf("fr_CA", UMEASFMT_WIDTH_SHORT, errorCode);
+ LocalPointer<Measure> twoDeg(
+ new Measure(2, MeasureUnit::createGenericTemperature(errorCode), errorCode), errorCode);
+ UnicodeString expected = UNICODE_STRING_SIMPLE("2\\u00B0").unescape();
+ UnicodeString actual;
+ assertEquals("2 deg temp in fr_CA", expected, mf.format(twoDeg.orphan(), actual, errorCode));
+}
+
void MeasureFormatTest::verifyFieldPosition(
const char *description,
const MeasureFormat &fmt,
/*
*******************************************************************************
-* Copyright (C) 2014, International Business Machines Corporation and *
-* others. All Rights Reserved. *
+* Copyright (C) 2014-2015, International Business Machines Corporation and
+* others. All Rights Reserved.
*******************************************************************************
*
* File QUANTITYFORMATTERTEST.CPP
QuantityFormatter fmt;
assertFalse(
"adding bad variant",
- fmt.add("a bad variant", "{0} pounds", status));
+ fmt.addIfAbsent("a bad variant", "{0} pounds", status));
assertEquals("adding bad variant status", U_ILLEGAL_ARGUMENT_ERROR, status);
status = U_ZERO_ERROR;
assertFalse(
"Adding bad pattern",
- fmt.add("other", "{0} {1} too many placeholders", status));
+ fmt.addIfAbsent("other", "{0} {1} too many placeholders", status));
assertEquals("adding bad pattern status", U_ILLEGAL_ARGUMENT_ERROR, status);
status = U_ZERO_ERROR;
assertFalse("isValid with no patterns", fmt.isValid());
assertTrue(
"Adding good pattern with no placeholders",
- fmt.add("other", "no placeholder", status));
+ fmt.addIfAbsent("zero", "no placeholder", status));
assertTrue(
"Adding good pattern",
- fmt.add("other", "{0} pounds", status));
+ fmt.addIfAbsent("other", "{0} pounds", status));
assertTrue("isValid with other", fmt.isValid());
assertTrue(
"Adding good pattern",
- fmt.add("one", "{0} pound", status));
+ fmt.addIfAbsent("one", "{0} pound", status));
assertEquals(
"getByVariant",
};
static WithQuantityExpected kSerbianNarrow[] = {
- {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 0 \\u043c\\u0435\\u0441."},
- {1.2, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 1,2 \\u043c\\u0435\\u0441."},
- {21.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 21 \\u043c\\u0435\\u0441."}
+ {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 0 \\u043c."},
+ {1.2, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 1,2 \\u043c."},
+ {21.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "\\u0437\\u0430 21 \\u043c."}
};
static WithoutQuantityExpected kEnglishNoQuantity[] = {