| Index: source/i18n/measfmt.cpp
|
| diff --git a/source/i18n/measfmt.cpp b/source/i18n/measfmt.cpp
|
| index 1af72e9da8d2344a1828ecf3862c37b1e3ec7a52..b5a9156ec2cee7a3114c37f4878573a1280964c6 100644
|
| --- a/source/i18n/measfmt.cpp
|
| +++ b/source/i18n/measfmt.cpp
|
| @@ -1,6 +1,8 @@
|
| +// Copyright (C) 2016 and later: Unicode, Inc. and others.
|
| +// License & terms of use: http://www.unicode.org/copyright.html
|
| /*
|
| **********************************************************************
|
| -* Copyright (c) 2004-2015, International Business Machines
|
| +* Copyright (c) 2004-2016, International Business Machines
|
| * Corporation and others. All Rights Reserved.
|
| **********************************************************************
|
| * Author: Alan Liu
|
| @@ -18,7 +20,7 @@
|
| #include "currfmt.h"
|
| #include "unicode/localpointer.h"
|
| #include "resource.h"
|
| -#include "simplepatternformatter.h"
|
| +#include "unicode/simpleformatter.h"
|
| #include "quantityformatter.h"
|
| #include "unicode/plurrule.h"
|
| #include "unicode/decimfmt.h"
|
| @@ -39,7 +41,7 @@
|
| #include "standardplural.h"
|
| #include "unifiedcache.h"
|
|
|
| -#define MEAS_UNIT_COUNT 129
|
| +#define MEAS_UNIT_COUNT 138
|
| #define WIDTH_INDEX_COUNT (UMEASFMT_WIDTH_NARROW + 1)
|
|
|
| U_NAMESPACE_BEGIN
|
| @@ -107,8 +109,9 @@ public:
|
| */
|
| UMeasureFormatWidth widthFallback[WIDTH_INDEX_COUNT];
|
| /** Measure unit -> format width -> array of patterns ("{0} meters") (plurals + PER_UNIT_INDEX) */
|
| - SimplePatternFormatter *patterns[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT][PATTERN_COUNT];
|
| - SimplePatternFormatter perFormatters[WIDTH_INDEX_COUNT];
|
| + SimpleFormatter *patterns[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT][PATTERN_COUNT];
|
| + const UChar* dnams[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT];
|
| + SimpleFormatter perFormatters[WIDTH_INDEX_COUNT];
|
|
|
| MeasureFormatCacheData();
|
| virtual ~MeasureFormatCacheData();
|
| @@ -116,7 +119,7 @@ public:
|
| UBool hasPerFormatter(int32_t width) const {
|
| // TODO: Create a more obvious way to test if the per-formatter has been set?
|
| // Use pointers, check for NULL? Or add an isValid() method?
|
| - return perFormatters[width].getPlaceholderCount() == 2;
|
| + return perFormatters[width].getArgumentLimit() == 2;
|
| }
|
|
|
| void adoptCurrencyFormat(int32_t widthIndex, NumberFormat *nfToAdopt) {
|
| @@ -157,6 +160,7 @@ MeasureFormatCacheData::MeasureFormatCacheData() {
|
| currencyFormats[i] = NULL;
|
| }
|
| uprv_memset(patterns, 0, sizeof(patterns));
|
| + uprv_memset(dnams, 0, sizeof(dnams));
|
| integerFormat = NULL;
|
| numericDateFormatters = NULL;
|
| }
|
| @@ -172,6 +176,7 @@ MeasureFormatCacheData::~MeasureFormatCacheData() {
|
| }
|
| }
|
| }
|
| + // Note: the contents of 'dnams' are pointers into the resource bundle
|
| delete integerFormat;
|
| delete numericDateFormatters;
|
| }
|
| @@ -213,117 +218,135 @@ static const UChar gNarrow[] = { 0x4E, 0x61, 0x72, 0x72, 0x6F, 0x77 };
|
| * C++: Each inner sink class has a reference to the main outer sink.
|
| * Java: Use non-static inner classes instead.
|
| */
|
| -struct UnitDataSink : public ResourceTableSink {
|
| - /**
|
| - * Sink for a table of display patterns. For example,
|
| - * unitsShort/duration/hour contains other{"{0} hrs"}.
|
| - */
|
| - struct UnitPatternSink : public ResourceTableSink {
|
| - UnitPatternSink(UnitDataSink &sink) : outer(sink) {}
|
| - ~UnitPatternSink();
|
| -
|
| - void setFormatterIfAbsent(int32_t index, const ResourceValue &value,
|
| - int32_t minPlaceholders, UErrorCode &errorCode) {
|
| - SimplePatternFormatter **patterns =
|
| - &outer.cacheData.patterns[outer.unitIndex][outer.width][0];
|
| +struct UnitDataSink : public ResourceSink {
|
| +
|
| + // Output data.
|
| + MeasureFormatCacheData &cacheData;
|
| +
|
| + // Path to current data.
|
| + UMeasureFormatWidth width;
|
| + const char *type;
|
| + int32_t unitIndex;
|
| +
|
| + UnitDataSink(MeasureFormatCacheData &outputData)
|
| + : cacheData(outputData),
|
| + width(UMEASFMT_WIDTH_COUNT), type(NULL), unitIndex(0) {}
|
| + ~UnitDataSink();
|
| +
|
| + void setFormatterIfAbsent(int32_t index, const ResourceValue &value,
|
| + int32_t minPlaceholders, UErrorCode &errorCode) {
|
| + SimpleFormatter **patterns = &cacheData.patterns[unitIndex][width][0];
|
| + if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
|
| + if (minPlaceholders >= 0) {
|
| + patterns[index] = new SimpleFormatter(
|
| + value.getUnicodeString(errorCode), minPlaceholders, 1, errorCode);
|
| + }
|
| if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
|
| - patterns[index] = new SimplePatternFormatter(
|
| - value.getUnicodeString(errorCode), minPlaceholders, 1, errorCode);
|
| - if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
|
| - errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| - }
|
| + errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| }
|
| }
|
| + }
|
|
|
| - virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
| - if (U_FAILURE(errorCode)) { return; }
|
| - if (uprv_strcmp(key, "dnam") == 0) {
|
| - // Skip the unit display name for now.
|
| - } else if (uprv_strcmp(key, "per") == 0) {
|
| - // For example, "{0}/h".
|
| - setFormatterIfAbsent(MeasureFormatCacheData::PER_UNIT_INDEX, value, 1, errorCode);
|
| - } else {
|
| - // The key must be one of the plural form strings. For example:
|
| - // one{"{0} hr"}
|
| - // other{"{0} hrs"}
|
| - setFormatterIfAbsent(StandardPlural::indexFromString(key, errorCode), value, 0,
|
| - errorCode);
|
| - }
|
| + void setDnamIfAbsent(const ResourceValue &value, UErrorCode& errorCode) {
|
| + if (cacheData.dnams[unitIndex][width] == NULL) {
|
| + int32_t length;
|
| + cacheData.dnams[unitIndex][width] = value.getString(length, errorCode);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Consume a display pattern. For example,
|
| + * unitsShort/duration/hour contains other{"{0} hrs"}.
|
| + */
|
| + void consumePattern(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
| + if (U_FAILURE(errorCode)) { return; }
|
| + if (uprv_strcmp(key, "dnam") == 0) {
|
| + // The display name for the unit in the current width.
|
| + setDnamIfAbsent(value, errorCode);
|
| + } else if (uprv_strcmp(key, "per") == 0) {
|
| + // For example, "{0}/h".
|
| + setFormatterIfAbsent(MeasureFormatCacheData::PER_UNIT_INDEX, value, 1, errorCode);
|
| + } else {
|
| + // The key must be one of the plural form strings. For example:
|
| + // one{"{0} hr"}
|
| + // other{"{0} hrs"}
|
| + setFormatterIfAbsent(StandardPlural::indexFromString(key, errorCode), value, 0,
|
| + errorCode);
|
| }
|
| - UnitDataSink &outer;
|
| - } patternSink;
|
| + }
|
|
|
| /**
|
| - * Sink for a table of per-unit tables. For example,
|
| + * Consume a table of per-unit tables. For example,
|
| * unitsShort/duration contains tables for duration-unit subtypes day & hour.
|
| */
|
| - struct UnitSubtypeSink : public ResourceTableSink {
|
| - UnitSubtypeSink(UnitDataSink &sink) : outer(sink) {}
|
| - ~UnitSubtypeSink();
|
| - virtual ResourceTableSink *getOrCreateTableSink(
|
| - const char *key, int32_t /* initialSize */, UErrorCode &errorCode) {
|
| - if (U_FAILURE(errorCode)) { return NULL; }
|
| - outer.unitIndex = MeasureUnit::internalGetIndexForTypeAndSubtype(outer.type, key);
|
| - if (outer.unitIndex >= 0) {
|
| - return &outer.patternSink;
|
| + void consumeSubtypeTable(const char *key, ResourceValue &value, UErrorCode &errorCode) {
|
| + if (U_FAILURE(errorCode)) { return; }
|
| + unitIndex = MeasureUnit::internalGetIndexForTypeAndSubtype(type, key);
|
| + if (unitIndex < 0) {
|
| + // TODO: How to handle unexpected data?
|
| + // See http://bugs.icu-project.org/trac/ticket/12597
|
| + return;
|
| + }
|
| +
|
| + if (value.getType() == URES_STRING) {
|
| + // Units like "coordinate" that don't have plural variants
|
| + setFormatterIfAbsent(StandardPlural::OTHER, value, 0, errorCode);
|
| + } else if (value.getType() == URES_TABLE) {
|
| + // Units that have plural variants
|
| + ResourceTable patternTableTable = value.getTable(errorCode);
|
| + if (U_FAILURE(errorCode)) { return; }
|
| + for (int i = 0; patternTableTable.getKeyAndValue(i, key, value); ++i) {
|
| + consumePattern(key, value, errorCode);
|
| }
|
| - return NULL;
|
| + } else {
|
| + // TODO: How to handle unexpected data?
|
| + // See http://bugs.icu-project.org/trac/ticket/12597
|
| + return;
|
| }
|
| - UnitDataSink &outer;
|
| - } subtypeSink;
|
| + }
|
|
|
| /**
|
| - * Sink for compound x-per-y display pattern. For example,
|
| + * Consume compound x-per-y display pattern. For example,
|
| * unitsShort/compound/per may be "{0}/{1}".
|
| */
|
| - struct UnitCompoundSink : public ResourceTableSink {
|
| - UnitCompoundSink(UnitDataSink &sink) : outer(sink) {}
|
| - ~UnitCompoundSink();
|
| - virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
| - if (U_SUCCESS(errorCode) && uprv_strcmp(key, "per") == 0) {
|
| - outer.cacheData.perFormatters[outer.width].
|
| - compileMinMaxPlaceholders(value.getUnicodeString(errorCode), 2, 2, errorCode);
|
| - }
|
| + void consumeCompoundPattern(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
| + if (U_SUCCESS(errorCode) && uprv_strcmp(key, "per") == 0) {
|
| + cacheData.perFormatters[width].
|
| + applyPatternMinMaxArguments(value.getUnicodeString(errorCode), 2, 2, errorCode);
|
| }
|
| - UnitDataSink &outer;
|
| - } compoundSink;
|
| + }
|
|
|
| /**
|
| - * Sink for a table of unit type tables. For example,
|
| + * Consume a table of unit type tables. For example,
|
| * unitsShort contains tables for area & duration.
|
| * It also contains a table for the compound/per pattern.
|
| */
|
| - struct UnitTypeSink : public ResourceTableSink {
|
| - UnitTypeSink(UnitDataSink &sink) : outer(sink) {}
|
| - ~UnitTypeSink();
|
| - virtual ResourceTableSink *getOrCreateTableSink(
|
| - const char *key, int32_t /* initialSize */, UErrorCode &errorCode) {
|
| - if (U_FAILURE(errorCode)) { return NULL; }
|
| - if (uprv_strcmp(key, "currency") == 0) {
|
| - // Skip.
|
| - } else if (uprv_strcmp(key, "compound") == 0) {
|
| - if (!outer.cacheData.hasPerFormatter(outer.width)) {
|
| - return &outer.compoundSink;
|
| + void consumeUnitTypesTable(const char *key, ResourceValue &value, UErrorCode &errorCode) {
|
| + if (U_FAILURE(errorCode)) { return; }
|
| + if (uprv_strcmp(key, "currency") == 0) {
|
| + // Skip.
|
| + } else if (uprv_strcmp(key, "compound") == 0) {
|
| + if (!cacheData.hasPerFormatter(width)) {
|
| + ResourceTable compoundTable = value.getTable(errorCode);
|
| + if (U_FAILURE(errorCode)) { return; }
|
| + for (int i = 0; compoundTable.getKeyAndValue(i, key, value); ++i) {
|
| + consumeCompoundPattern(key, value, errorCode);
|
| }
|
| - } else {
|
| - outer.type = key;
|
| - return &outer.subtypeSink;
|
| }
|
| - return NULL;
|
| + } else {
|
| + type = key;
|
| + ResourceTable subtypeTable = value.getTable(errorCode);
|
| + if (U_FAILURE(errorCode)) { return; }
|
| + for (int i = 0; subtypeTable.getKeyAndValue(i, key, value); ++i) {
|
| + consumeSubtypeTable(key, value, errorCode);
|
| + }
|
| }
|
| - UnitDataSink &outer;
|
| - } typeSink;
|
| + }
|
|
|
| - UnitDataSink(MeasureFormatCacheData &outputData)
|
| - : patternSink(*this), subtypeSink(*this), compoundSink(*this), typeSink(*this),
|
| - cacheData(outputData),
|
| - width(UMEASFMT_WIDTH_COUNT), type(NULL), unitIndex(0) {}
|
| - ~UnitDataSink();
|
| - virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
| + void consumeAlias(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
| // Handle aliases like
|
| // units:alias{"/LOCALE/unitsShort"}
|
| // which should only occur in the root bundle.
|
| - if (U_FAILURE(errorCode) || value.getType() != URES_ALIAS) { return; }
|
| UMeasureFormatWidth sourceWidth = widthFromKey(key);
|
| if (sourceWidth == UMEASFMT_WIDTH_COUNT) {
|
| // Alias from something we don't care about.
|
| @@ -342,12 +365,15 @@ struct UnitDataSink : public ResourceTableSink {
|
| }
|
| cacheData.widthFallback[sourceWidth] = targetWidth;
|
| }
|
| - virtual ResourceTableSink *getOrCreateTableSink(
|
| - const char *key, int32_t /* initialSize */, UErrorCode &errorCode) {
|
| +
|
| + void consumeTable(const char *key, ResourceValue &value, UErrorCode &errorCode) {
|
| if (U_SUCCESS(errorCode) && (width = widthFromKey(key)) != UMEASFMT_WIDTH_COUNT) {
|
| - return &typeSink;
|
| + ResourceTable unitTypesTable = value.getTable(errorCode);
|
| + if (U_FAILURE(errorCode)) { return; }
|
| + for (int i = 0; unitTypesTable.getKeyAndValue(i, key, value); ++i) {
|
| + consumeUnitTypesTable(key, value, errorCode);
|
| + }
|
| }
|
| - return NULL;
|
| }
|
|
|
| static UMeasureFormatWidth widthFromKey(const char *key) {
|
| @@ -382,20 +408,22 @@ struct UnitDataSink : public ResourceTableSink {
|
| return UMEASFMT_WIDTH_COUNT;
|
| }
|
|
|
| - // Output data.
|
| - MeasureFormatCacheData &cacheData;
|
| -
|
| - // Path to current data.
|
| - UMeasureFormatWidth width;
|
| - const char *type;
|
| - int32_t unitIndex;
|
| + virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
|
| + UErrorCode &errorCode) {
|
| + // Main entry point to sink
|
| + ResourceTable widthsTable = value.getTable(errorCode);
|
| + if (U_FAILURE(errorCode)) { return; }
|
| + for (int i = 0; widthsTable.getKeyAndValue(i, key, value); ++i) {
|
| + if (value.getType() == URES_ALIAS) {
|
| + consumeAlias(key, value, errorCode);
|
| + } else {
|
| + consumeTable(key, value, errorCode);
|
| + }
|
| + }
|
| + }
|
| };
|
|
|
| // Virtual destructors must be defined out of line.
|
| -UnitDataSink::UnitPatternSink::~UnitPatternSink() {}
|
| -UnitDataSink::UnitSubtypeSink::~UnitSubtypeSink() {}
|
| -UnitDataSink::UnitCompoundSink::~UnitCompoundSink() {}
|
| -UnitDataSink::UnitTypeSink::~UnitTypeSink() {}
|
| UnitDataSink::~UnitDataSink() {}
|
|
|
| } // namespace
|
| @@ -405,7 +433,7 @@ static UBool loadMeasureUnitData(
|
| MeasureFormatCacheData &cacheData,
|
| UErrorCode &status) {
|
| UnitDataSink sink(cacheData);
|
| - ures_getAllTableItemsWithFallback(resource, "", sink, status);
|
| + ures_getAllItemsWithFallback(resource, "", sink, status);
|
| return U_SUCCESS(status);
|
| }
|
|
|
| @@ -484,8 +512,14 @@ const MeasureFormatCacheData *LocaleCacheKey<MeasureFormatCacheData>::createObje
|
| }
|
|
|
| for (int32_t i = 0; i < WIDTH_INDEX_COUNT; ++i) {
|
| + // NumberFormat::createInstance can erase warning codes from status, so pass it
|
| + // a separate status instance
|
| + UErrorCode localStatus = U_ZERO_ERROR;
|
| result->adoptCurrencyFormat(i, NumberFormat::createInstance(
|
| - localeId, currencyStyles[i], status));
|
| + localeId, currencyStyles[i], localStatus));
|
| + if (localStatus != U_ZERO_ERROR) {
|
| + status = localStatus;
|
| + }
|
| if (U_FAILURE(status)) {
|
| return NULL;
|
| }
|
| @@ -791,10 +825,28 @@ UnicodeString &MeasureFormat::formatMeasures(
|
| status);
|
| }
|
| listFormatter->format(results, measureCount, appendTo, status);
|
| - delete [] results;
|
| + delete [] results;
|
| return appendTo;
|
| }
|
|
|
| +UnicodeString MeasureFormat::getUnitDisplayName(const MeasureUnit& unit, UErrorCode& /*status*/) const {
|
| + UMeasureFormatWidth width = getRegularWidth(this->width);
|
| + const UChar* const* styleToDnam = cache->dnams[unit.getIndex()];
|
| + const UChar* dnam = styleToDnam[width];
|
| + if (dnam == NULL) {
|
| + int32_t fallbackWidth = cache->widthFallback[width];
|
| + dnam = styleToDnam[fallbackWidth];
|
| + }
|
| +
|
| + UnicodeString result;
|
| + if (dnam == NULL) {
|
| + result.setToBogus();
|
| + } else {
|
| + result.setTo(dnam, -1);
|
| + }
|
| + return result;
|
| +}
|
| +
|
| void MeasureFormat::initMeasureFormat(
|
| const Locale &locale,
|
| UMeasureFormatWidth w,
|
| @@ -904,7 +956,7 @@ UnicodeString &MeasureFormat::formatMeasure(
|
| UnicodeString formattedNumber;
|
| StandardPlural::Form pluralForm = QuantityFormatter::selectPlural(
|
| amtNumber, nf, **pluralRules, formattedNumber, pos, status);
|
| - const SimplePatternFormatter *formatter = getPluralFormatter(amtUnit, width, pluralForm, status);
|
| + const SimpleFormatter *formatter = getPluralFormatter(amtUnit, width, pluralForm, status);
|
| return QuantityFormatter::format(*formatter, formattedNumber, appendTo, pos, status);
|
| }
|
|
|
| @@ -1037,10 +1089,10 @@ UnicodeString &MeasureFormat::formatNumeric(
|
| return appendTo;
|
| }
|
|
|
| -const SimplePatternFormatter *MeasureFormat::getFormatterOrNull(
|
| +const SimpleFormatter *MeasureFormat::getFormatterOrNull(
|
| const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index) const {
|
| width = getRegularWidth(width);
|
| - SimplePatternFormatter *const (*unitPatterns)[MeasureFormatCacheData::PATTERN_COUNT] =
|
| + SimpleFormatter *const (*unitPatterns)[MeasureFormatCacheData::PATTERN_COUNT] =
|
| &cache->patterns[unit.getIndex()][0];
|
| if (unitPatterns[width][index] != NULL) {
|
| return unitPatterns[width][index];
|
| @@ -1052,27 +1104,27 @@ const SimplePatternFormatter *MeasureFormat::getFormatterOrNull(
|
| return NULL;
|
| }
|
|
|
| -const SimplePatternFormatter *MeasureFormat::getFormatter(
|
| +const SimpleFormatter *MeasureFormat::getFormatter(
|
| const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index,
|
| UErrorCode &errorCode) const {
|
| if (U_FAILURE(errorCode)) {
|
| return NULL;
|
| }
|
| - const SimplePatternFormatter *pattern = getFormatterOrNull(unit, width, index);
|
| + const SimpleFormatter *pattern = getFormatterOrNull(unit, width, index);
|
| if (pattern == NULL) {
|
| errorCode = U_MISSING_RESOURCE_ERROR;
|
| }
|
| return pattern;
|
| }
|
|
|
| -const SimplePatternFormatter *MeasureFormat::getPluralFormatter(
|
| +const SimpleFormatter *MeasureFormat::getPluralFormatter(
|
| const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index,
|
| UErrorCode &errorCode) const {
|
| if (U_FAILURE(errorCode)) {
|
| return NULL;
|
| }
|
| if (index != StandardPlural::OTHER) {
|
| - const SimplePatternFormatter *pattern = getFormatterOrNull(unit, width, index);
|
| + const SimpleFormatter *pattern = getFormatterOrNull(unit, width, index);
|
| if (pattern != NULL) {
|
| return pattern;
|
| }
|
| @@ -1080,20 +1132,20 @@ const SimplePatternFormatter *MeasureFormat::getPluralFormatter(
|
| return getFormatter(unit, width, StandardPlural::OTHER, errorCode);
|
| }
|
|
|
| -const SimplePatternFormatter *MeasureFormat::getPerFormatter(
|
| +const SimpleFormatter *MeasureFormat::getPerFormatter(
|
| UMeasureFormatWidth width,
|
| UErrorCode &status) const {
|
| if (U_FAILURE(status)) {
|
| return NULL;
|
| }
|
| width = getRegularWidth(width);
|
| - const SimplePatternFormatter * perFormatters = cache->perFormatters;
|
| - if (perFormatters[width].getPlaceholderCount() == 2) {
|
| + const SimpleFormatter * perFormatters = cache->perFormatters;
|
| + if (perFormatters[width].getArgumentLimit() == 2) {
|
| return &perFormatters[width];
|
| }
|
| int32_t fallbackWidth = cache->widthFallback[width];
|
| if (fallbackWidth != UMEASFMT_WIDTH_COUNT &&
|
| - perFormatters[fallbackWidth].getPlaceholderCount() == 2) {
|
| + perFormatters[fallbackWidth].getArgumentLimit() == 2) {
|
| return &perFormatters[fallbackWidth];
|
| }
|
| status = U_MISSING_RESOURCE_ERROR;
|
| @@ -1109,7 +1161,7 @@ int32_t MeasureFormat::withPerUnitAndAppend(
|
| if (U_FAILURE(status)) {
|
| return offset;
|
| }
|
| - const SimplePatternFormatter *perUnitFormatter =
|
| + const SimpleFormatter *perUnitFormatter =
|
| getFormatterOrNull(perUnit, width, MeasureFormatCacheData::PER_UNIT_INDEX);
|
| if (perUnitFormatter != NULL) {
|
| const UnicodeString *params[] = {&formatted};
|
| @@ -1122,13 +1174,13 @@ int32_t MeasureFormat::withPerUnitAndAppend(
|
| status);
|
| return offset;
|
| }
|
| - const SimplePatternFormatter *perFormatter = getPerFormatter(width, status);
|
| - const SimplePatternFormatter *pattern =
|
| + const SimpleFormatter *perFormatter = getPerFormatter(width, status);
|
| + const SimpleFormatter *pattern =
|
| getPluralFormatter(perUnit, width, StandardPlural::ONE, status);
|
| if (U_FAILURE(status)) {
|
| return offset;
|
| }
|
| - UnicodeString perUnitString = pattern->getPatternWithNoPlaceholders();
|
| + UnicodeString perUnitString = pattern->getTextWithNoArguments();
|
| perUnitString.trim();
|
| const UnicodeString *params[] = {&formatted, &perUnitString};
|
| perFormatter->formatAndAppend(
|
|
|