| Index: source/i18n/tmutfmt.cpp
|
| diff --git a/source/i18n/tmutfmt.cpp b/source/i18n/tmutfmt.cpp
|
| index b7c16e513bceb828c9ae7abcacb040bafa47eb28..1669546f7675354bbfc3538435e641dc9f174bd6 100644
|
| --- a/source/i18n/tmutfmt.cpp
|
| +++ b/source/i18n/tmutfmt.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) 2008-2014, Google, International Business Machines Corporation
|
| + * Copyright (C) 2008-2015, Google, International Business Machines Corporation
|
| * and others. All Rights Reserved.
|
| *******************************************************************************
|
| */
|
| @@ -10,6 +12,7 @@
|
| #if !UCONFIG_NO_FORMATTING
|
|
|
| #include "unicode/decimfmt.h"
|
| +#include "unicode/localpointer.h"
|
| #include "plurrule_impl.h"
|
| #include "uvector.h"
|
| #include "charstr.h"
|
| @@ -119,7 +122,7 @@ TimeUnitFormat::TimeUnitFormat(const TimeUnitFormat& other)
|
| delete fTimeUnitToCountToPatterns[i];
|
| fTimeUnitToCountToPatterns[i] = NULL;
|
| }
|
| - }
|
| + }
|
| }
|
|
|
|
|
| @@ -133,13 +136,13 @@ TimeUnitFormat::~TimeUnitFormat() {
|
| }
|
|
|
|
|
| -Format*
|
| +Format*
|
| TimeUnitFormat::clone(void) const {
|
| return new TimeUnitFormat(*this);
|
| }
|
|
|
|
|
| -TimeUnitFormat&
|
| +TimeUnitFormat&
|
| TimeUnitFormat::operator=(const TimeUnitFormat& other) {
|
| if (this == &other) {
|
| return *this;
|
| @@ -162,16 +165,16 @@ TimeUnitFormat::operator=(const TimeUnitFormat& other) {
|
| delete fTimeUnitToCountToPatterns[i];
|
| fTimeUnitToCountToPatterns[i] = NULL;
|
| }
|
| - }
|
| + }
|
| fStyle = other.fStyle;
|
| return *this;
|
| }
|
|
|
| -void
|
| -TimeUnitFormat::parseObject(const UnicodeString& source,
|
| +void
|
| +TimeUnitFormat::parseObject(const UnicodeString& source,
|
| Formattable& result,
|
| ParsePosition& pos) const {
|
| - Formattable resultNumber(0.0);
|
| + Formattable resultNumber(0.0);
|
| UBool withNumberFormat = false;
|
| TimeUnit::UTimeUnitFields resultTimeUnit = TimeUnit::UTIMEUNIT_FIELD_COUNT;
|
| int32_t oldPos = pos.getIndex();
|
| @@ -181,7 +184,7 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
|
| #ifdef TMUTFMT_DEBUG
|
| char res[1000];
|
| source.extract(0, source.length(), res, "UTF-8");
|
| - std::cout << "parse source: " << res << "\n";
|
| + std::cout << "parse source: " << res << "\n";
|
| #endif
|
| // parse by iterating through all available patterns
|
| // and looking for the longest match.
|
| @@ -196,7 +199,7 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
|
| UnicodeString* count = (UnicodeString*)keyTok.pointer;
|
| #ifdef TMUTFMT_DEBUG
|
| count->extract(0, count->length(), res, "UTF-8");
|
| - std::cout << "parse plural count: " << res << "\n";
|
| + std::cout << "parse plural count: " << res << "\n";
|
| #endif
|
| const UHashTok valueTok = elem->value;
|
| // the value is a pair of MessageFormat*
|
| @@ -271,9 +274,9 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
|
| pos.setErrorIndex(0);
|
| } else {
|
| UErrorCode status = U_ZERO_ERROR;
|
| - TimeUnitAmount* tmutamt = new TimeUnitAmount(resultNumber, resultTimeUnit, status);
|
| + LocalPointer<TimeUnitAmount> tmutamt(new TimeUnitAmount(resultNumber, resultTimeUnit, status), status);
|
| if (U_SUCCESS(status)) {
|
| - result.adoptObject(tmutamt);
|
| + result.adoptObject(tmutamt.orphan());
|
| pos.setIndex(newPos);
|
| pos.setErrorIndex(-1);
|
| } else {
|
| @@ -309,16 +312,16 @@ TimeUnitFormat::create(UTimeUnitFormatStyle style, UErrorCode& status) {
|
| //In Java, create an empty instance does not setup locale as
|
| //default locale. If it followed by setNumberFormat(),
|
| //in format(), the locale will set up as the locale in fNumberFormat.
|
| - //But in C++, this sets the locale as the default locale.
|
| + //But in C++, this sets the locale as the default locale.
|
| setup(status);
|
| }
|
|
|
| -void
|
| +void
|
| TimeUnitFormat::setup(UErrorCode& err) {
|
| initDataMembers(err);
|
|
|
| UVector pluralCounts(0, uhash_compareUnicodeString, 6, err);
|
| - StringEnumeration* keywords = getPluralRules().getKeywords(err);
|
| + LocalPointer<StringEnumeration> keywords(getPluralRules().getKeywords(err), err);
|
| if (U_FAILURE(err)) {
|
| return;
|
| }
|
| @@ -330,7 +333,6 @@ TimeUnitFormat::setup(UErrorCode& err) {
|
| checkConsistency(UTMUTFMT_FULL_STYLE, gUnitsTag, err);
|
| readFromCurrentLocale(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, pluralCounts, err);
|
| checkConsistency(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, err);
|
| - delete keywords;
|
| }
|
|
|
|
|
| @@ -347,45 +349,36 @@ TimeUnitFormat::initDataMembers(UErrorCode& err){
|
| }
|
| }
|
|
|
| -void
|
| -TimeUnitFormat::readFromCurrentLocale(UTimeUnitFormatStyle style, const char* key,
|
| - const UVector& pluralCounts, UErrorCode& err) {
|
| - if (U_FAILURE(err)) {
|
| - return;
|
| - }
|
| - // fill timeUnitToCountToPatterns from resource file
|
| - // err is used to indicate wrong status except missing resource.
|
| - // status is an error code used in resource lookup.
|
| - // status does not affect "err".
|
| - UErrorCode status = U_ZERO_ERROR;
|
| - UResourceBundle *rb, *unitsRes;
|
| - rb = ures_open(U_ICUDATA_UNIT, getLocaleID(status), &status);
|
| - unitsRes = ures_getByKey(rb, key, NULL, &status);
|
| - unitsRes = ures_getByKey(unitsRes, "duration", unitsRes, &status);
|
| - if (U_FAILURE(status)) {
|
| - ures_close(unitsRes);
|
| - ures_close(rb);
|
| - return;
|
| - }
|
| - int32_t size = ures_getSize(unitsRes);
|
| - for ( int32_t index = 0; index < size; ++index) {
|
| - // resource of one time unit
|
| - UResourceBundle* oneTimeUnit = ures_getByIndex(unitsRes, index,
|
| - NULL, &status);
|
| - if (U_SUCCESS(status)) {
|
| - const char* timeUnitName = ures_getKey(oneTimeUnit);
|
| +struct TimeUnitFormatReadSink : public ResourceSink {
|
| + TimeUnitFormat *timeUnitFormatObj;
|
| + const UVector &pluralCounts;
|
| + UTimeUnitFormatStyle style;
|
| + UBool beenHere;
|
| +
|
| + TimeUnitFormatReadSink(TimeUnitFormat *timeUnitFormatObj,
|
| + const UVector &pluralCounts, UTimeUnitFormatStyle style) :
|
| + timeUnitFormatObj(timeUnitFormatObj), pluralCounts(pluralCounts),
|
| + style(style), beenHere(FALSE){}
|
| +
|
| + virtual ~TimeUnitFormatReadSink();
|
| +
|
| + virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
|
| + // Skip all put() calls except the first one -- discard all fallback data.
|
| + if (beenHere) {
|
| + return;
|
| + } else {
|
| + beenHere = TRUE;
|
| + }
|
| +
|
| + ResourceTable units = value.getTable(errorCode);
|
| + if (U_FAILURE(errorCode)) { return; }
|
| +
|
| + for (int32_t i = 0; units.getKeyAndValue(i, key, value); ++i) {
|
| + const char* timeUnitName = key;
|
| if (timeUnitName == NULL) {
|
| - ures_close(oneTimeUnit);
|
| - continue;
|
| - }
|
| - UResourceBundle* countsToPatternRB = ures_getByKey(unitsRes,
|
| - timeUnitName,
|
| - NULL, &status);
|
| - if (countsToPatternRB == NULL || U_FAILURE(status)) {
|
| - ures_close(countsToPatternRB);
|
| - ures_close(oneTimeUnit);
|
| continue;
|
| }
|
| +
|
| TimeUnit::UTimeUnitFields timeUnitField = TimeUnit::UTIMEUNIT_FIELD_COUNT;
|
| if ( uprv_strcmp(timeUnitName, gTimeUnitYear) == 0 ) {
|
| timeUnitField = TimeUnit::UTIMEUNIT_YEAR;
|
| @@ -402,79 +395,99 @@ TimeUnitFormat::readFromCurrentLocale(UTimeUnitFormatStyle style, const char* ke
|
| } else if ( uprv_strcmp(timeUnitName, gTimeUnitWeek) == 0 ) {
|
| timeUnitField = TimeUnit::UTIMEUNIT_WEEK;
|
| } else {
|
| - ures_close(countsToPatternRB);
|
| - ures_close(oneTimeUnit);
|
| continue;
|
| }
|
| - Hashtable* countToPatterns = fTimeUnitToCountToPatterns[timeUnitField];
|
| + LocalPointer<Hashtable> localCountToPatterns;
|
| + Hashtable *countToPatterns =
|
| + timeUnitFormatObj->fTimeUnitToCountToPatterns[timeUnitField];
|
| if (countToPatterns == NULL) {
|
| - countToPatterns = initHash(err);
|
| - if (U_FAILURE(err)) {
|
| - ures_close(countsToPatternRB);
|
| - ures_close(oneTimeUnit);
|
| - delete countToPatterns;
|
| - break;
|
| + localCountToPatterns.adoptInsteadAndCheckErrorCode(
|
| + timeUnitFormatObj->initHash(errorCode), errorCode);
|
| + countToPatterns = localCountToPatterns.getAlias();
|
| + if (U_FAILURE(errorCode)) {
|
| + return;
|
| }
|
| }
|
| - int32_t count = ures_getSize(countsToPatternRB);
|
| - const char* pluralCount;
|
| - for ( int32_t pluralIndex = 0; pluralIndex < count; ++pluralIndex) {
|
| - // resource of count to pattern
|
| - UnicodeString pattern =
|
| - ures_getNextUnicodeString(countsToPatternRB, &pluralCount, &status);
|
| - if (U_FAILURE(status)) {
|
| +
|
| + ResourceTable countsToPatternTable = value.getTable(errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + continue;
|
| + }
|
| + for (int32_t j = 0; countsToPatternTable.getKeyAndValue(j, key, value); ++j) {
|
| + errorCode = U_ZERO_ERROR;
|
| + UnicodeString pattern = value.getUnicodeString(errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| continue;
|
| }
|
| - UnicodeString pluralCountUniStr(pluralCount, -1, US_INV);
|
| + UnicodeString pluralCountUniStr(key, -1, US_INV);
|
| if (!pluralCounts.contains(&pluralCountUniStr)) {
|
| - continue;
|
| + continue;
|
| }
|
| - MessageFormat* messageFormat = new MessageFormat(pattern, getLocale(err), err);
|
| - if ( U_SUCCESS(err) ) {
|
| - MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCountUniStr);
|
| - if (formatters == NULL) {
|
| - formatters = (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*));
|
| - formatters[UTMUTFMT_FULL_STYLE] = NULL;
|
| - formatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
|
| - countToPatterns->put(pluralCountUniStr, formatters, err);
|
| - if (U_FAILURE(err)) {
|
| - uprv_free(formatters);
|
| - }
|
| - }
|
| - if (U_SUCCESS(err)) {
|
| - //delete formatters[style];
|
| - formatters[style] = messageFormat;
|
| - }
|
| - }
|
| - if (U_FAILURE(err)) {
|
| - ures_close(countsToPatternRB);
|
| - ures_close(oneTimeUnit);
|
| - ures_close(unitsRes);
|
| - ures_close(rb);
|
| - delete messageFormat;
|
| - delete countToPatterns;
|
| + LocalPointer<MessageFormat> messageFormat(new MessageFormat(
|
| + pattern, timeUnitFormatObj->getLocale(errorCode), errorCode), errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| return;
|
| }
|
| + MessageFormat** formatters =
|
| + (MessageFormat**)countToPatterns->get(pluralCountUniStr);
|
| + if (formatters == NULL) {
|
| + LocalMemory<MessageFormat *> localFormatters(
|
| + (MessageFormat **)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*)));
|
| + if (localFormatters.isNull()) {
|
| + errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| + return;
|
| + }
|
| + localFormatters[UTMUTFMT_FULL_STYLE] = NULL;
|
| + localFormatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
|
| + countToPatterns->put(pluralCountUniStr, localFormatters.getAlias(), errorCode);
|
| + if (U_FAILURE(errorCode)) {
|
| + return;
|
| + }
|
| + formatters = localFormatters.orphan();
|
| + }
|
| + formatters[style] = messageFormat.orphan();
|
| }
|
| - if (fTimeUnitToCountToPatterns[timeUnitField] == NULL) {
|
| - fTimeUnitToCountToPatterns[timeUnitField] = countToPatterns;
|
| +
|
| + if (timeUnitFormatObj->fTimeUnitToCountToPatterns[timeUnitField] == NULL) {
|
| + timeUnitFormatObj->fTimeUnitToCountToPatterns[timeUnitField] = localCountToPatterns.orphan();
|
| }
|
| - ures_close(countsToPatternRB);
|
| }
|
| - ures_close(oneTimeUnit);
|
| }
|
| - ures_close(unitsRes);
|
| - ures_close(rb);
|
| -}
|
|
|
| +};
|
| +
|
| +TimeUnitFormatReadSink::~TimeUnitFormatReadSink() {}
|
|
|
| -void
|
| +void
|
| +TimeUnitFormat::readFromCurrentLocale(UTimeUnitFormatStyle style, const char* key,
|
| + const UVector& pluralCounts, UErrorCode& err) {
|
| + if (U_FAILURE(err)) {
|
| + return;
|
| + }
|
| + // fill timeUnitToCountToPatterns from resource file
|
| + // err is used to indicate wrong status except missing resource.
|
| + // status is an error code used in resource lookup.
|
| + // status does not affect "err".
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_UNIT, getLocaleID(status), &status));
|
| +
|
| + LocalUResourceBundlePointer unitsRes(ures_getByKey(rb.getAlias(), key, NULL, &status));
|
| + ures_getByKey(unitsRes.getAlias(), "duration", unitsRes.getAlias(), &status);
|
| + if (U_FAILURE(status)) {
|
| + return;
|
| + }
|
| +
|
| + TimeUnitFormatReadSink sink(this, pluralCounts, style);
|
| + ures_getAllItemsWithFallback(unitsRes.getAlias(), "", sink, status);
|
| +}
|
| +
|
| +void
|
| TimeUnitFormat::checkConsistency(UTimeUnitFormatStyle style, const char* key, UErrorCode& err) {
|
| if (U_FAILURE(err)) {
|
| return;
|
| }
|
| // there should be patterns for each plural rule in each time unit.
|
| - // For each time unit,
|
| + // For each time unit,
|
| // for each plural rule, following is unit pattern fall-back rule:
|
| // ( for example: "one" hour )
|
| // look for its unit pattern in its locale tree.
|
| @@ -485,45 +498,41 @@ TimeUnitFormat::checkConsistency(UTimeUnitFormatStyle style, const char* key, UE
|
| // fallback to plural count "other",
|
| // look for the pattern of "other" in the locale tree:
|
| // "de_DE" to "de" to "root".
|
| - // If not found, fall back to value of
|
| - // static variable DEFAULT_PATTERN_FOR_xxx, such as "{0} h".
|
| + // If not found, fall back to value of
|
| + // static variable DEFAULT_PATTERN_FOR_xxx, such as "{0} h".
|
| //
|
| // Following is consistency check to create pattern for each
|
| // plural rule in each time unit using above fall-back rule.
|
| //
|
| - StringEnumeration* keywords = getPluralRules().getKeywords(err);
|
| - if (U_SUCCESS(err)) {
|
| - const UnicodeString* pluralCount;
|
| - while ((pluralCount = keywords->snext(err)) != NULL) {
|
| - if ( U_SUCCESS(err) ) {
|
| - for (int32_t i = 0; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; ++i) {
|
| - // for each time unit,
|
| - // get all the patterns for each plural rule in this locale.
|
| - Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
|
| - if ( countToPatterns == NULL ) {
|
| - countToPatterns = initHash(err);
|
| - if (U_FAILURE(err)) {
|
| - delete countToPatterns;
|
| - return;
|
| - }
|
| - fTimeUnitToCountToPatterns[i] = countToPatterns;
|
| - }
|
| - MessageFormat** formatters = (MessageFormat**)countToPatterns->get(*pluralCount);
|
| - if( formatters == NULL || formatters[style] == NULL ) {
|
| - // look through parents
|
| - const char* localeName = getLocaleID(err);
|
| - CharString pluralCountChars;
|
| - pluralCountChars.appendInvariantChars(*pluralCount, err);
|
| - searchInLocaleChain(style, key, localeName,
|
| - (TimeUnit::UTimeUnitFields)i,
|
| - *pluralCount, pluralCountChars.data(),
|
| - countToPatterns, err);
|
| - }
|
| + LocalPointer<StringEnumeration> keywords(
|
| + getPluralRules().getKeywords(err), err);
|
| + const UnicodeString* pluralCount;
|
| + while (U_SUCCESS(err) && (pluralCount = keywords->snext(err)) != NULL) {
|
| + for (int32_t i = 0; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; ++i) {
|
| + // for each time unit,
|
| + // get all the patterns for each plural rule in this locale.
|
| + Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
|
| + if ( countToPatterns == NULL ) {
|
| + fTimeUnitToCountToPatterns[i] = countToPatterns = initHash(err);
|
| + if (U_FAILURE(err)) {
|
| + return;
|
| }
|
| }
|
| + MessageFormat** formatters = (MessageFormat**)countToPatterns->get(*pluralCount);
|
| + if( formatters == NULL || formatters[style] == NULL ) {
|
| + // look through parents
|
| + const char* localeName = getLocaleID(err);
|
| + CharString pluralCountChars;
|
| + pluralCountChars.appendInvariantChars(*pluralCount, err);
|
| + searchInLocaleChain(style, key, localeName,
|
| + (TimeUnit::UTimeUnitFields)i,
|
| + *pluralCount, pluralCountChars.data(),
|
| + countToPatterns, err);
|
| + }
|
| + // TODO: what to do with U_FAILURE(err) at this point.
|
| + // As is, the outer loop continues to run, but does nothing.
|
| }
|
| }
|
| - delete keywords;
|
| }
|
|
|
|
|
| @@ -533,14 +542,14 @@ TimeUnitFormat::checkConsistency(UTimeUnitFormatStyle style, const char* key, UE
|
| // searchPluralCount is the fallback plural count.
|
| // For example, to search for pattern for ""one" hour",
|
| // "one" is the srcPluralCount,
|
| -// if the pattern is not found even in root, fallback to
|
| -// using patterns of plural count "other",
|
| +// if the pattern is not found even in root, fallback to
|
| +// using patterns of plural count "other",
|
| // then, "other" is the searchPluralCount.
|
| -void
|
| +void
|
| TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key, const char* localeName,
|
| TimeUnit::UTimeUnitFields srcTimeUnitField,
|
| const UnicodeString& srcPluralCount,
|
| - const char* searchPluralCount,
|
| + const char* searchPluralCount,
|
| Hashtable* countToPatterns,
|
| UErrorCode& err) {
|
| if (U_FAILURE(err)) {
|
| @@ -554,46 +563,38 @@ TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key,
|
| while ((locNameLen = uloc_getParent(parentLocale, parentLocale,
|
| ULOC_FULLNAME_CAPACITY, &status)) >= 0){
|
| // look for pattern for srcPluralCount in locale tree
|
| - UResourceBundle *rb, *unitsRes, *countsToPatternRB;
|
| - rb = ures_open(U_ICUDATA_UNIT, parentLocale, &status);
|
| - unitsRes = ures_getByKey(rb, key, NULL, &status);
|
| + LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_UNIT, parentLocale, &status));
|
| + LocalUResourceBundlePointer unitsRes(ures_getByKey(rb.getAlias(), key, NULL, &status));
|
| const char* timeUnitName = getTimeUnitName(srcTimeUnitField, status);
|
| - countsToPatternRB = ures_getByKey(unitsRes, timeUnitName, NULL, &status);
|
| + LocalUResourceBundlePointer countsToPatternRB(ures_getByKey(unitsRes.getAlias(), timeUnitName, NULL, &status));
|
| const UChar* pattern;
|
| int32_t ptLength;
|
| - pattern = ures_getStringByKeyWithFallback(countsToPatternRB, searchPluralCount, &ptLength, &status);
|
| + pattern = ures_getStringByKeyWithFallback(countsToPatternRB.getAlias(), searchPluralCount, &ptLength, &status);
|
| if (U_SUCCESS(status)) {
|
| //found
|
| - MessageFormat* messageFormat = new MessageFormat(UnicodeString(TRUE, pattern, ptLength), getLocale(err), err);
|
| - if (U_SUCCESS(err)) {
|
| - MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
|
| - if (formatters == NULL) {
|
| - formatters = (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*));
|
| - formatters[UTMUTFMT_FULL_STYLE] = NULL;
|
| - formatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
|
| - countToPatterns->put(srcPluralCount, formatters, err);
|
| - if (U_FAILURE(err)) {
|
| - uprv_free(formatters);
|
| - delete messageFormat;
|
| - }
|
| - }
|
| - if (U_SUCCESS(err)) {
|
| - //delete formatters[style];
|
| - formatters[style] = messageFormat;
|
| + LocalPointer<MessageFormat> messageFormat(
|
| + new MessageFormat(UnicodeString(TRUE, pattern, ptLength), getLocale(err), err), err);
|
| + if (U_FAILURE(err)) {
|
| + return;
|
| + }
|
| + MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
|
| + if (formatters == NULL) {
|
| + LocalMemory<MessageFormat *> localFormatters(
|
| + (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*)));
|
| + formatters = localFormatters.getAlias();
|
| + localFormatters[UTMUTFMT_FULL_STYLE] = NULL;
|
| + localFormatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
|
| + countToPatterns->put(srcPluralCount, localFormatters.orphan(), err);
|
| + if (U_FAILURE(err)) {
|
| + return;
|
| }
|
| - } else {
|
| - delete messageFormat;
|
| }
|
| - ures_close(countsToPatternRB);
|
| - ures_close(unitsRes);
|
| - ures_close(rb);
|
| + //delete formatters[style];
|
| + formatters[style] = messageFormat.orphan();
|
| return;
|
| }
|
| - ures_close(countsToPatternRB);
|
| - ures_close(unitsRes);
|
| - ures_close(rb);
|
| status = U_ZERO_ERROR;
|
| - if ( locNameLen ==0 ) {
|
| + if (locNameLen == 0) {
|
| break;
|
| }
|
| }
|
| @@ -604,13 +605,15 @@ TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key,
|
| #ifdef TMUTFMT_DEBUG
|
| std::cout << "loop into searchInLocaleChain since Short-Long-Alternative \n";
|
| #endif
|
| - char pLocale[ULOC_FULLNAME_CAPACITY];
|
| - uprv_strcpy(pLocale, localeName);
|
| + CharString pLocale(localeName, -1, err);
|
| // Add an underscore at the tail of locale name,
|
| // so that searchInLocaleChain will check the current locale before falling back
|
| - uprv_strcat(pLocale, "_");
|
| - searchInLocaleChain(style, gUnitsTag, pLocale, srcTimeUnitField, srcPluralCount,
|
| + pLocale.append('_', err);
|
| + searchInLocaleChain(style, gUnitsTag, pLocale.data(), srcTimeUnitField, srcPluralCount,
|
| searchPluralCount, countToPatterns, err);
|
| + if (U_FAILURE(err)) {
|
| + return;
|
| + }
|
| MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
|
| if (formatters != NULL && formatters[style] != NULL) {
|
| return;
|
| @@ -621,7 +624,7 @@ TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key,
|
| // fall-back to plural count "other"
|
| if ( uprv_strcmp(searchPluralCount, gPluralCountOther) == 0 ) {
|
| // set default fall back the same as the resource in root
|
| - MessageFormat* messageFormat = NULL;
|
| + LocalPointer<MessageFormat> messageFormat;
|
| const UChar *pattern = NULL;
|
| if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_SECOND ) {
|
| pattern = DEFAULT_PATTERN_FOR_SECOND;
|
| @@ -639,35 +642,37 @@ TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key,
|
| pattern = DEFAULT_PATTERN_FOR_YEAR;
|
| }
|
| if (pattern != NULL) {
|
| - messageFormat = new MessageFormat(UnicodeString(TRUE, pattern, -1), getLocale(err), err);
|
| + messageFormat.adoptInsteadAndCheckErrorCode(
|
| + new MessageFormat(UnicodeString(TRUE, pattern, -1), getLocale(err), err), err);
|
| }
|
| - if (U_SUCCESS(err)) {
|
| - MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
|
| - if (formatters == NULL) {
|
| - formatters = (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*));
|
| - formatters[UTMUTFMT_FULL_STYLE] = NULL;
|
| - formatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
|
| - countToPatterns->put(srcPluralCount, formatters, err);
|
| - if (U_FAILURE(err)) {
|
| - uprv_free(formatters);
|
| - delete messageFormat;
|
| - }
|
| - }
|
| - if (U_SUCCESS(err)) {
|
| - //delete formatters[style];
|
| - formatters[style] = messageFormat;
|
| + if (U_FAILURE(err)) {
|
| + return;
|
| + }
|
| + MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
|
| + if (formatters == NULL) {
|
| + LocalMemory<MessageFormat *> localFormatters (
|
| + (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*)));
|
| + if (localFormatters.isNull()) {
|
| + err = U_MEMORY_ALLOCATION_ERROR;
|
| + return;
|
| }
|
| - } else {
|
| - delete messageFormat;
|
| + formatters = localFormatters.getAlias();
|
| + formatters[UTMUTFMT_FULL_STYLE] = NULL;
|
| + formatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
|
| + countToPatterns->put(srcPluralCount, localFormatters.orphan(), err);
|
| + }
|
| + if (U_SUCCESS(err)) {
|
| + //delete formatters[style];
|
| + formatters[style] = messageFormat.orphan();
|
| }
|
| } else {
|
| // fall back to rule "other", and search in parents
|
| - searchInLocaleChain(style, key, localeName, srcTimeUnitField, srcPluralCount,
|
| + searchInLocaleChain(style, key, localeName, srcTimeUnitField, srcPluralCount,
|
| gPluralCountOther, countToPatterns, err);
|
| }
|
| }
|
|
|
| -void
|
| +void
|
| TimeUnitFormat::setLocale(const Locale& locale, UErrorCode& status) {
|
| if (setMeasureFormatLocale(locale, status)) {
|
| setup(status);
|
| @@ -675,7 +680,7 @@ TimeUnitFormat::setLocale(const Locale& locale, UErrorCode& status) {
|
| }
|
|
|
|
|
| -void
|
| +void
|
| TimeUnitFormat::setNumberFormat(const NumberFormat& format, UErrorCode& status){
|
| if (U_FAILURE(status)) {
|
| return;
|
| @@ -730,7 +735,7 @@ TimeUnitFormat::copyHash(const Hashtable* source, Hashtable* target, UErrorCode&
|
| }
|
|
|
|
|
| -U_CDECL_BEGIN
|
| +U_CDECL_BEGIN
|
|
|
| /**
|
| * set hash table value comparator
|
| @@ -761,7 +766,7 @@ TimeUnitFormat::initHash(UErrorCode& status) {
|
| return NULL;
|
| }
|
| if ( U_FAILURE(status) ) {
|
| - delete hTable;
|
| + delete hTable;
|
| return NULL;
|
| }
|
| hTable->setValueComparator(tmutfmtHashTableValueComparator);
|
| @@ -770,7 +775,7 @@ TimeUnitFormat::initHash(UErrorCode& status) {
|
|
|
|
|
| const char*
|
| -TimeUnitFormat::getTimeUnitName(TimeUnit::UTimeUnitFields unitField,
|
| +TimeUnitFormat::getTimeUnitName(TimeUnit::UTimeUnitFields unitField,
|
| UErrorCode& status) {
|
| if (U_FAILURE(status)) {
|
| return NULL;
|
|
|