From 724f7b5c10c52a850f2ef93eb5fff41a97f6e381 Mon Sep 17 00:00:00 2001 From: Markus Scherer Date: Thu, 19 Nov 2015 22:33:25 +0000 Subject: [PATCH] ICU-11986 const ResourceValue references, sink.leave(), some more specific types in MeasureFormat code X-SVN-Rev: 38094 --- icu4c/source/common/resource.cpp | 8 ++- icu4c/source/common/resource.h | 18 +++++- icu4c/source/common/uresdata.cpp | 2 + icu4c/source/i18n/measfmt.cpp | 78 ++++++++++++------------- icu4c/source/i18n/quantityformatter.cpp | 37 +++++++++--- icu4c/source/i18n/unicode/measfmt.h | 10 ++-- 6 files changed, 96 insertions(+), 57 deletions(-) diff --git a/icu4c/source/common/resource.cpp b/icu4c/source/common/resource.cpp index 2a61dbac65b..7a4c4181bf8 100644 --- a/icu4c/source/common/resource.cpp +++ b/icu4c/source/common/resource.cpp @@ -23,7 +23,7 @@ ResourceValue::~ResourceValue() {} ResourceArraySink::~ResourceArraySink() {} void ResourceArraySink::put( - int32_t /*index*/, ResourceValue & /*value*/, UErrorCode & /*errorCode*/) {} + int32_t /*index*/, const ResourceValue & /*value*/, UErrorCode & /*errorCode*/) {} ResourceArraySink *ResourceArraySink::getOrCreateArraySink( int32_t /*index*/, int32_t /*size*/, UErrorCode & /*errorCode*/) { @@ -35,11 +35,13 @@ ResourceTableSink *ResourceArraySink::getOrCreateTableSink( return NULL; } +void ResourceArraySink::leave(UErrorCode & /*errorCode*/) {} + ResourceTableSink::~ResourceTableSink() {} void ResourceTableSink::put( - const char * /*key*/, ResourceValue & /*value*/, UErrorCode & /*errorCode*/) {} + const char * /*key*/, const ResourceValue & /*value*/, UErrorCode & /*errorCode*/) {} void ResourceTableSink::putNoFallback(const char * /*key*/, UErrorCode & /*errorCode*/) {} @@ -53,4 +55,6 @@ ResourceTableSink *ResourceTableSink::getOrCreateTableSink( return NULL; } +void ResourceTableSink::leave(UErrorCode & /*errorCode*/) {} + U_NAMESPACE_END diff --git a/icu4c/source/common/resource.h b/icu4c/source/common/resource.h index 58e03df6ff2..042e298b798 100644 --- a/icu4c/source/common/resource.h +++ b/icu4c/source/common/resource.h @@ -126,7 +126,7 @@ public: * @param index of the resource array item * @param value resource value */ - virtual void put(int32_t index, ResourceValue &value, UErrorCode &errorCode); + virtual void put(int32_t index, const ResourceValue &value, UErrorCode &errorCode); /** * Returns a nested resource array at the array index as another sink. @@ -158,6 +158,13 @@ public: virtual ResourceTableSink *getOrCreateTableSink( int32_t index, int32_t initialSize, UErrorCode &errorCode); + /** + * "Leaves" the array. + * Indicates that all of the resources and sub-resources of the current array + * have been enumerated. + */ + virtual void leave(UErrorCode &errorCode); + private: ResourceArraySink(const ResourceArraySink &); // no copy constructor ResourceArraySink &operator=(const ResourceArraySink &); // no assignment operator @@ -181,7 +188,7 @@ public: * @param key resource key string * @param value resource value */ - virtual void put(const char *key, ResourceValue &value, UErrorCode &errorCode); + virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode); /** * Adds a no-fallback/no-inheritance marker for this key. @@ -224,6 +231,13 @@ public: virtual ResourceTableSink *getOrCreateTableSink( const char *key, int32_t initialSize, UErrorCode &errorCode); + /** + * "Leaves" the table. + * Indicates that all of the resources and sub-resources of the current table + * have been enumerated. + */ + virtual void leave(UErrorCode &errorCode); + private: ResourceTableSink(const ResourceTableSink &); // no copy constructor ResourceTableSink &operator=(const ResourceTableSink &); // no assignment operator diff --git a/icu4c/source/common/uresdata.cpp b/icu4c/source/common/uresdata.cpp index 91edd7c1afc..fbfb56de6b5 100644 --- a/icu4c/source/common/uresdata.cpp +++ b/icu4c/source/common/uresdata.cpp @@ -775,6 +775,7 @@ ures_getAllTableItems(const ResourceData *pResData, Resource table, } if(U_FAILURE(errorCode)) { return; } } + sink.leave(errorCode); } U_CAPI Resource U_EXPORT2 @@ -862,6 +863,7 @@ ures_getAllArrayItems(const ResourceData *pResData, Resource array, } if(U_FAILURE(errorCode)) { return; } } + sink.leave(errorCode); } U_CFUNC Resource diff --git a/icu4c/source/i18n/measfmt.cpp b/icu4c/source/i18n/measfmt.cpp index 623c272b7c2..5d7faa3fef6 100644 --- a/icu4c/source/i18n/measfmt.cpp +++ b/icu4c/source/i18n/measfmt.cpp @@ -77,6 +77,13 @@ private: NumericDateFormatters &operator=(const NumericDateFormatters &other); }; +static UMeasureFormatWidth getRegularWidth(UMeasureFormatWidth width) { + if (width >= WIDTH_INDEX_COUNT) { + return UMEASFMT_WIDTH_NARROW; + } + return width; +} + /** * Instances contain all MeasureFormat specific data for a particular locale. * This data is cached. It is never copied, but is shared via shared pointers. @@ -111,8 +118,8 @@ public: delete currencyFormats[widthIndex]; currencyFormats[widthIndex] = nfToAdopt; } - const NumberFormat *getCurrencyFormat(int32_t widthIndex) const { - return currencyFormats[widthIndex]; + const NumberFormat *getCurrencyFormat(UMeasureFormatWidth width) const { + return currencyFormats[getRegularWidth(width)]; } void adoptIntegerFormat(NumberFormat *nfToAdopt) { delete integerFormat; @@ -128,7 +135,7 @@ public: const NumericDateFormatters *getNumericDateFormatters() const { return numericDateFormatters; } - void setPerUnitFormatterIfAbsent(int32_t unitIndex, int32_t width, ResourceValue &value, + void setPerUnitFormatterIfAbsent(int32_t unitIndex, int32_t width, const ResourceValue &value, UErrorCode &errorCode) { if (perUnitFormatters[unitIndex][width] == NULL) { perUnitFormatters[unitIndex][width] = @@ -177,13 +184,6 @@ MeasureFormatCacheData::~MeasureFormatCacheData() { delete numericDateFormatters; } -static int32_t widthToIndex(UMeasureFormatWidth width) { - if (width >= WIDTH_INDEX_COUNT) { - return WIDTH_INDEX_COUNT - 1; - } - return width; -} - static UBool isCurrency(const MeasureUnit &unit) { return (uprv_strcmp(unit.getType(), "currency") == 0); } @@ -229,7 +229,7 @@ struct UnitDataSink : public ResourceTableSink { struct UnitPatternSink : public ResourceTableSink { UnitPatternSink(UnitDataSink &sink) : outer(sink) {} ~UnitPatternSink(); - virtual void put(const char *key, ResourceValue &value, UErrorCode &errorCode) { + 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. @@ -278,7 +278,7 @@ struct UnitDataSink : public ResourceTableSink { struct UnitCompoundSink : public ResourceTableSink { UnitCompoundSink(UnitDataSink &sink) : outer(sink) {} ~UnitCompoundSink(); - virtual void put(const char *key, ResourceValue &value, UErrorCode &errorCode) { + 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]. compile(value.getUnicodeString(errorCode), errorCode); @@ -318,7 +318,7 @@ struct UnitDataSink : public ResourceTableSink { cacheData(outputData), width(UMEASFMT_WIDTH_COUNT), type(NULL), unitIndex(0), hasPatterns(FALSE) {} ~UnitDataSink(); - virtual void put(const char *key, ResourceValue &value, UErrorCode &errorCode) { + virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) { // Handle aliases like // units:alias{"/LOCALE/unitsShort"} // which should only occur in the root bundle. @@ -834,7 +834,7 @@ void MeasureFormat::initMeasureFormat( delete listFormatter; listFormatter = ListFormatter::createInstance( locale, - listStyles[widthToIndex(width)], + listStyles[getRegularWidth(width)], status); } @@ -891,14 +891,13 @@ UnicodeString &MeasureFormat::formatMeasure( if (isCurrency(amtUnit)) { UChar isoCode[4]; u_charsToUChars(amtUnit.getSubtype(), isoCode, 4); - return cache->getCurrencyFormat(widthToIndex(width))->format( + return cache->getCurrencyFormat(width)->format( new CurrencyAmount(amtNumber, isoCode, status), appendTo, pos, status); } - const QuantityFormatter *quantityFormatter = getQuantityFormatter( - amtUnit.getIndex(), widthToIndex(width), status); + const QuantityFormatter *quantityFormatter = getQuantityFormatter(amtUnit, width, status); if (U_FAILURE(status)) { return appendTo; } @@ -1041,18 +1040,18 @@ UnicodeString &MeasureFormat::formatNumeric( } const QuantityFormatter *MeasureFormat::getQuantityFormatter( - int32_t index, - int32_t widthIndex, + const MeasureUnit &unit, + UMeasureFormatWidth width, UErrorCode &status) const { if (U_FAILURE(status)) { return NULL; } - const QuantityFormatter *formatters = - cache->formatters[index]; - if (formatters[widthIndex].isValid()) { - return &formatters[widthIndex]; + width = getRegularWidth(width); + const QuantityFormatter *formatters = cache->formatters[unit.getIndex()]; + if (formatters[width].isValid()) { + return &formatters[width]; } - int32_t fallbackWidth = cache->widthFallback[widthIndex]; + int32_t fallbackWidth = cache->widthFallback[width]; if (fallbackWidth != UMEASFMT_WIDTH_COUNT && formatters[fallbackWidth].isValid()) { return &formatters[fallbackWidth]; } @@ -1061,14 +1060,15 @@ const QuantityFormatter *MeasureFormat::getQuantityFormatter( } const SimplePatternFormatter *MeasureFormat::getPerUnitFormatter( - int32_t index, - int32_t widthIndex) const { + const MeasureUnit &unit, + UMeasureFormatWidth width) const { + width = getRegularWidth(width); const SimplePatternFormatter * const * perUnitFormatters = - cache->getPerUnitFormattersByIndex(index); - if (perUnitFormatters[widthIndex] != NULL) { - return perUnitFormatters[widthIndex]; + cache->getPerUnitFormattersByIndex(unit.getIndex()); + if (perUnitFormatters[width] != NULL) { + return perUnitFormatters[width]; } - int32_t fallbackWidth = cache->widthFallback[widthIndex]; + int32_t fallbackWidth = cache->widthFallback[width]; if (fallbackWidth != UMEASFMT_WIDTH_COUNT && perUnitFormatters[fallbackWidth] != NULL) { return perUnitFormatters[fallbackWidth]; } @@ -1076,16 +1076,17 @@ const SimplePatternFormatter *MeasureFormat::getPerUnitFormatter( } const SimplePatternFormatter *MeasureFormat::getPerFormatter( - int32_t widthIndex, + UMeasureFormatWidth width, UErrorCode &status) const { if (U_FAILURE(status)) { return NULL; } + width = getRegularWidth(width); const SimplePatternFormatter * perFormatters = cache->perFormatters; - if (perFormatters[widthIndex].getPlaceholderCount() == 2) { - return &perFormatters[widthIndex]; + if (perFormatters[width].getPlaceholderCount() == 2) { + return &perFormatters[width]; } - int32_t fallbackWidth = cache->widthFallback[widthIndex]; + int32_t fallbackWidth = cache->widthFallback[width]; if (fallbackWidth != UMEASFMT_WIDTH_COUNT && perFormatters[fallbackWidth].getPlaceholderCount() == 2) { return &perFormatters[fallbackWidth]; @@ -1110,8 +1111,7 @@ int32_t MeasureFormat::withPerUnitAndAppend( if (U_FAILURE(status)) { return offset; } - const SimplePatternFormatter *perUnitFormatter = getPerUnitFormatter( - perUnit.getIndex(), widthToIndex(width)); + const SimplePatternFormatter *perUnitFormatter = getPerUnitFormatter(perUnit, width); if (perUnitFormatter != NULL) { const UnicodeString *params[] = {&formatted}; perUnitFormatter->formatAndAppend( @@ -1123,10 +1123,8 @@ int32_t MeasureFormat::withPerUnitAndAppend( status); return offset; } - const SimplePatternFormatter *perFormatter = getPerFormatter( - widthToIndex(width), status); - const QuantityFormatter *qf = getQuantityFormatter( - perUnit.getIndex(), widthToIndex(width), status); + const SimplePatternFormatter *perFormatter = getPerFormatter(width, status); + const QuantityFormatter *qf = getQuantityFormatter(perUnit, width, status); if (U_FAILURE(status)) { return offset; } diff --git a/icu4c/source/i18n/quantityformatter.cpp b/icu4c/source/i18n/quantityformatter.cpp index ed80b38b500..22d19a95550 100644 --- a/icu4c/source/i18n/quantityformatter.cpp +++ b/icu4c/source/i18n/quantityformatter.cpp @@ -21,16 +21,37 @@ U_NAMESPACE_BEGIN -// other must always be first. -static const char * const gPluralForms[] = { - "other", "zero", "one", "two", "few", "many"}; - +/** + * Plural forms in index order: "other", "zero", "one", "two", "few", "many" + * "other" must be first. + */ 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; + switch (*pluralForm++) { + case 'f': + if (uprv_strcmp(pluralForm, "ew") == 0) { + return 4; } + case 'm': + if (uprv_strcmp(pluralForm, "any") == 0) { + return 5; + } + case 'o': + if (uprv_strcmp(pluralForm, "ther") == 0) { + return 0; + } else if (uprv_strcmp(pluralForm, "ne") == 0) { + return 2; + } + break; + case 't': + if (uprv_strcmp(pluralForm, "wo") == 0) { + return 3; + } + case 'z': + if (uprv_strcmp(pluralForm, "ero") == 0) { + return 1; + } + default: + break; } return -1; } diff --git a/icu4c/source/i18n/unicode/measfmt.h b/icu4c/source/i18n/unicode/measfmt.h index 61a1e86d9c4..b680a7dc713 100644 --- a/icu4c/source/i18n/unicode/measfmt.h +++ b/icu4c/source/i18n/unicode/measfmt.h @@ -328,16 +328,16 @@ class U_I18N_API MeasureFormat : public Format { ListFormatter *listFormatter; const QuantityFormatter *getQuantityFormatter( - int32_t index, - int32_t widthIndex, + const MeasureUnit &unit, + UMeasureFormatWidth width, UErrorCode &status) const; const SimplePatternFormatter *getPerUnitFormatter( - int32_t index, - int32_t widthIndex) const; + const MeasureUnit &unit, + UMeasureFormatWidth width) const; const SimplePatternFormatter *getPerFormatter( - int32_t widthIndex, + UMeasureFormatWidth width, UErrorCode &status) const; int32_t withPerUnitAndAppend(