Index: source/i18n/quantityformatter.cpp |
diff --git a/source/i18n/quantityformatter.cpp b/source/i18n/quantityformatter.cpp |
index ed80b38b500d1465db2ec2388bbba08ad9ee1fb6..97c4c80fa82620f23d6974cccf3cbcf220ad7724 100644 |
--- a/source/i18n/quantityformatter.cpp |
+++ b/source/i18n/quantityformatter.cpp |
@@ -5,6 +5,11 @@ |
****************************************************************************** |
* quantityformatter.cpp |
*/ |
+ |
+#include "unicode/utypes.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+ |
#include "quantityformatter.h" |
#include "simplepatternformatter.h" |
#include "uassert.h" |
@@ -15,26 +20,12 @@ |
#include "charstr.h" |
#include "unicode/fmtable.h" |
#include "unicode/fieldpos.h" |
+#include "standardplural.h" |
#include "visibledigits.h" |
- |
-#if !UCONFIG_NO_FORMATTING |
+#include "uassert.h" |
U_NAMESPACE_BEGIN |
-// other must always be first. |
-static const char * const gPluralForms[] = { |
- "other", "zero", "one", "two", "few", "many"}; |
- |
-static int32_t getPluralIndex(const char *pluralForm) { |
- int32_t len = UPRV_LENGTHOF(gPluralForms); |
- for (int32_t i = 0; i < len; ++i) { |
- if (uprv_strcmp(pluralForm, gPluralForms[i]) == 0) { |
- return i; |
- } |
- } |
- return -1; |
-} |
- |
QuantityFormatter::QuantityFormatter() { |
for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { |
formatters[i] = NULL; |
@@ -80,112 +71,126 @@ void QuantityFormatter::reset() { |
} |
} |
-UBool QuantityFormatter::add( |
+UBool QuantityFormatter::addIfAbsent( |
const char *variant, |
const UnicodeString &rawPattern, |
UErrorCode &status) { |
+ int32_t pluralIndex = StandardPlural::indexFromString(variant, status); |
if (U_FAILURE(status)) { |
return FALSE; |
} |
- int32_t pluralIndex = getPluralIndex(variant); |
- if (pluralIndex == -1) { |
- status = U_ILLEGAL_ARGUMENT_ERROR; |
- return FALSE; |
+ if (formatters[pluralIndex] != NULL) { |
+ return TRUE; |
} |
- SimplePatternFormatter *newFmt = |
- new SimplePatternFormatter(rawPattern); |
+ SimplePatternFormatter *newFmt = new SimplePatternFormatter(rawPattern, 0, 1, status); |
if (newFmt == NULL) { |
status = U_MEMORY_ALLOCATION_ERROR; |
return FALSE; |
} |
- if (newFmt->getPlaceholderCount() > 1) { |
+ if (U_FAILURE(status)) { |
delete newFmt; |
- status = U_ILLEGAL_ARGUMENT_ERROR; |
return FALSE; |
} |
- delete formatters[pluralIndex]; |
formatters[pluralIndex] = newFmt; |
return TRUE; |
} |
UBool QuantityFormatter::isValid() const { |
- return formatters[0] != NULL; |
+ return formatters[StandardPlural::OTHER] != NULL; |
} |
const SimplePatternFormatter *QuantityFormatter::getByVariant( |
const char *variant) const { |
- int32_t pluralIndex = getPluralIndex(variant); |
- if (pluralIndex == -1) { |
- pluralIndex = 0; |
- } |
+ U_ASSERT(isValid()); |
+ int32_t pluralIndex = StandardPlural::indexOrOtherIndexFromString(variant); |
const SimplePatternFormatter *pattern = formatters[pluralIndex]; |
if (pattern == NULL) { |
- pattern = formatters[0]; |
+ pattern = formatters[StandardPlural::OTHER]; |
} |
return pattern; |
} |
UnicodeString &QuantityFormatter::format( |
- const Formattable& quantity, |
+ const Formattable &number, |
const NumberFormat &fmt, |
const PluralRules &rules, |
UnicodeString &appendTo, |
FieldPosition &pos, |
UErrorCode &status) const { |
+ UnicodeString formattedNumber; |
+ StandardPlural::Form p = selectPlural(number, fmt, rules, formattedNumber, pos, status); |
if (U_FAILURE(status)) { |
return appendTo; |
} |
- UnicodeString count; |
+ const SimplePatternFormatter *pattern = formatters[p]; |
+ if (pattern == NULL) { |
+ pattern = formatters[StandardPlural::OTHER]; |
+ if (pattern == NULL) { |
+ status = U_INVALID_STATE_ERROR; |
+ return appendTo; |
+ } |
+ } |
+ return format(*pattern, formattedNumber, appendTo, pos, status); |
+} |
+ |
+// The following methods live here so that class PluralRules does not depend on number formatting, |
+// and the SimplePatternFormatter does not depend on FieldPosition. |
+ |
+StandardPlural::Form QuantityFormatter::selectPlural( |
+ const Formattable &number, |
+ const NumberFormat &fmt, |
+ const PluralRules &rules, |
+ UnicodeString &formattedNumber, |
+ FieldPosition &pos, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return StandardPlural::OTHER; |
+ } |
+ UnicodeString pluralKeyword; |
VisibleDigitsWithExponent digits; |
const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt); |
if (decFmt != NULL) { |
- decFmt->initVisibleDigitsWithExponent(quantity, digits, status); |
+ decFmt->initVisibleDigitsWithExponent(number, digits, status); |
if (U_FAILURE(status)) { |
- return appendTo; |
+ return StandardPlural::OTHER; |
} |
- count = rules.select(digits); |
+ pluralKeyword = rules.select(digits); |
+ decFmt->format(digits, formattedNumber, pos, status); |
} else { |
- if (quantity.getType() == Formattable::kDouble) { |
- count = rules.select(quantity.getDouble()); |
- } else if (quantity.getType() == Formattable::kLong) { |
- count = rules.select(quantity.getLong()); |
- } else if (quantity.getType() == Formattable::kInt64) { |
- count = rules.select((double) quantity.getInt64()); |
+ if (number.getType() == Formattable::kDouble) { |
+ pluralKeyword = rules.select(number.getDouble()); |
+ } else if (number.getType() == Formattable::kLong) { |
+ pluralKeyword = rules.select(number.getLong()); |
+ } else if (number.getType() == Formattable::kInt64) { |
+ pluralKeyword = rules.select((double) number.getInt64()); |
} else { |
status = U_ILLEGAL_ARGUMENT_ERROR; |
- return appendTo; |
+ return StandardPlural::OTHER; |
} |
+ fmt.format(number, formattedNumber, pos, status); |
} |
- CharString buffer; |
- buffer.appendInvariantChars(count, status); |
+ return StandardPlural::orOtherFromString(pluralKeyword); |
+} |
+ |
+UnicodeString &QuantityFormatter::format( |
+ const SimplePatternFormatter &pattern, |
+ const UnicodeString &value, |
+ UnicodeString &appendTo, |
+ FieldPosition &pos, |
+ UErrorCode &status) { |
if (U_FAILURE(status)) { |
return appendTo; |
} |
- const SimplePatternFormatter *pattern = getByVariant(buffer.data()); |
- if (pattern == NULL) { |
- status = U_INVALID_STATE_ERROR; |
- return appendTo; |
- } |
- UnicodeString formattedNumber; |
- FieldPosition fpos(pos.getField()); |
- if (decFmt != NULL) { |
- decFmt->format(digits, formattedNumber, fpos, status); |
- } else { |
- fmt.format(quantity, formattedNumber, fpos, status); |
- } |
- const UnicodeString *params[1] = {&formattedNumber}; |
- int32_t offsets[1]; |
- pattern->formatAndAppend( |
- params, |
- UPRV_LENGTHOF(params), |
- appendTo, |
- offsets, |
- UPRV_LENGTHOF(offsets), |
- status); |
- if (offsets[0] != -1) { |
- if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) { |
- pos.setBeginIndex(fpos.getBeginIndex() + offsets[0]); |
- pos.setEndIndex(fpos.getEndIndex() + offsets[0]); |
+ const UnicodeString *param = &value; |
+ int32_t offset; |
+ pattern.formatAndAppend(¶m, 1, appendTo, &offset, 1, status); |
+ if (pos.getBeginIndex() != 0 || pos.getEndIndex() != 0) { |
+ if (offset >= 0) { |
+ pos.setBeginIndex(pos.getBeginIndex() + offset); |
+ pos.setEndIndex(pos.getEndIndex() + offset); |
+ } else { |
+ pos.setBeginIndex(0); |
+ pos.setEndIndex(0); |
} |
} |
return appendTo; |