Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(691)

Unified Diff: source/i18n/measfmt.cpp

Issue 2440913002: Update ICU to 58.1
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « source/i18n/locdspnm.cpp ('k') | source/i18n/measunit.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(
« no previous file with comments | « source/i18n/locdspnm.cpp ('k') | source/i18n/measunit.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698