diff options
Diffstat (limited to 'deps/node/deps/icu-small/source/i18n/tmutfmt.cpp')
-rw-r--r-- | deps/node/deps/icu-small/source/i18n/tmutfmt.cpp | 806 |
1 files changed, 0 insertions, 806 deletions
diff --git a/deps/node/deps/icu-small/source/i18n/tmutfmt.cpp b/deps/node/deps/icu-small/source/i18n/tmutfmt.cpp deleted file mode 100644 index 50dac8b7..00000000 --- a/deps/node/deps/icu-small/source/i18n/tmutfmt.cpp +++ /dev/null @@ -1,806 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - ******************************************************************************* - * Copyright (C) 2008-2015, Google, International Business Machines Corporation - * and others. All Rights Reserved. - ******************************************************************************* - */ - -#include "unicode/tmutfmt.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/decimfmt.h" -#include "unicode/localpointer.h" -#include "plurrule_impl.h" -#include "uvector.h" -#include "charstr.h" -#include "cmemory.h" -#include "cstring.h" -#include "hash.h" -#include "uresimp.h" -#include "ureslocs.h" -#include "unicode/msgfmt.h" -#include "uassert.h" - -#define LEFT_CURLY_BRACKET ((UChar)0x007B) -#define RIGHT_CURLY_BRACKET ((UChar)0x007D) -#define SPACE ((UChar)0x0020) -#define DIGIT_ZERO ((UChar)0x0030) -#define LOW_S ((UChar)0x0073) -#define LOW_M ((UChar)0x006D) -#define LOW_I ((UChar)0x0069) -#define LOW_N ((UChar)0x006E) -#define LOW_H ((UChar)0x0068) -#define LOW_W ((UChar)0x0077) -#define LOW_D ((UChar)0x0064) -#define LOW_Y ((UChar)0x0079) -#define LOW_Z ((UChar)0x007A) -#define LOW_E ((UChar)0x0065) -#define LOW_R ((UChar)0x0072) -#define LOW_O ((UChar)0x006F) -#define LOW_N ((UChar)0x006E) -#define LOW_T ((UChar)0x0074) - - -//TODO: define in compile time -//#define TMUTFMT_DEBUG 1 - -#ifdef TMUTFMT_DEBUG -#include <iostream> -#endif - -U_NAMESPACE_BEGIN - - - -UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnitFormat) - -static const char gUnitsTag[] = "units"; -static const char gShortUnitsTag[] = "unitsShort"; -static const char gTimeUnitYear[] = "year"; -static const char gTimeUnitMonth[] = "month"; -static const char gTimeUnitDay[] = "day"; -static const char gTimeUnitWeek[] = "week"; -static const char gTimeUnitHour[] = "hour"; -static const char gTimeUnitMinute[] = "minute"; -static const char gTimeUnitSecond[] = "second"; -static const char gPluralCountOther[] = "other"; - -static const UChar DEFAULT_PATTERN_FOR_SECOND[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_S, 0}; -static const UChar DEFAULT_PATTERN_FOR_MINUTE[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_M, LOW_I, LOW_N, 0}; -static const UChar DEFAULT_PATTERN_FOR_HOUR[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_H, 0}; -static const UChar DEFAULT_PATTERN_FOR_WEEK[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_W, 0}; -static const UChar DEFAULT_PATTERN_FOR_DAY[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_D, 0}; -static const UChar DEFAULT_PATTERN_FOR_MONTH[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_M, 0}; -static const UChar DEFAULT_PATTERN_FOR_YEAR[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_Y, 0}; - -static const UChar PLURAL_COUNT_ZERO[] = {LOW_Z, LOW_E, LOW_R, LOW_O, 0}; -static const UChar PLURAL_COUNT_ONE[] = {LOW_O, LOW_N, LOW_E, 0}; -static const UChar PLURAL_COUNT_TWO[] = {LOW_T, LOW_W, LOW_O, 0}; - -TimeUnitFormat::TimeUnitFormat(UErrorCode& status) { - initMeasureFormat(Locale::getDefault(), UMEASFMT_WIDTH_WIDE, NULL, status); - create(UTMUTFMT_FULL_STYLE, status); -} - - -TimeUnitFormat::TimeUnitFormat(const Locale& locale, UErrorCode& status) { - initMeasureFormat(locale, UMEASFMT_WIDTH_WIDE, NULL, status); - create(UTMUTFMT_FULL_STYLE, status); -} - - -TimeUnitFormat::TimeUnitFormat(const Locale& locale, UTimeUnitFormatStyle style, UErrorCode& status) { - switch (style) { - case UTMUTFMT_FULL_STYLE: - initMeasureFormat(locale, UMEASFMT_WIDTH_WIDE, NULL, status); - break; - case UTMUTFMT_ABBREVIATED_STYLE: - initMeasureFormat(locale, UMEASFMT_WIDTH_SHORT, NULL, status); - break; - default: - initMeasureFormat(locale, UMEASFMT_WIDTH_WIDE, NULL, status); - break; - } - create(style, status); -} - -TimeUnitFormat::TimeUnitFormat(const TimeUnitFormat& other) -: MeasureFormat(other), - fStyle(other.fStyle) -{ - for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR; - i < TimeUnit::UTIMEUNIT_FIELD_COUNT; - i = (TimeUnit::UTimeUnitFields)(i+1)) { - UErrorCode status = U_ZERO_ERROR; - fTimeUnitToCountToPatterns[i] = initHash(status); - if (U_SUCCESS(status)) { - copyHash(other.fTimeUnitToCountToPatterns[i], fTimeUnitToCountToPatterns[i], status); - } else { - delete fTimeUnitToCountToPatterns[i]; - fTimeUnitToCountToPatterns[i] = NULL; - } - } -} - - -TimeUnitFormat::~TimeUnitFormat() { - for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR; - i < TimeUnit::UTIMEUNIT_FIELD_COUNT; - i = (TimeUnit::UTimeUnitFields)(i+1)) { - deleteHash(fTimeUnitToCountToPatterns[i]); - fTimeUnitToCountToPatterns[i] = NULL; - } -} - - -Format* -TimeUnitFormat::clone(void) const { - return new TimeUnitFormat(*this); -} - - -TimeUnitFormat& -TimeUnitFormat::operator=(const TimeUnitFormat& other) { - if (this == &other) { - return *this; - } - MeasureFormat::operator=(other); - for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR; - i < TimeUnit::UTIMEUNIT_FIELD_COUNT; - i = (TimeUnit::UTimeUnitFields)(i+1)) { - deleteHash(fTimeUnitToCountToPatterns[i]); - fTimeUnitToCountToPatterns[i] = NULL; - } - for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR; - i < TimeUnit::UTIMEUNIT_FIELD_COUNT; - i = (TimeUnit::UTimeUnitFields)(i+1)) { - UErrorCode status = U_ZERO_ERROR; - fTimeUnitToCountToPatterns[i] = initHash(status); - if (U_SUCCESS(status)) { - copyHash(other.fTimeUnitToCountToPatterns[i], fTimeUnitToCountToPatterns[i], status); - } else { - delete fTimeUnitToCountToPatterns[i]; - fTimeUnitToCountToPatterns[i] = NULL; - } - } - fStyle = other.fStyle; - return *this; -} - -void -TimeUnitFormat::parseObject(const UnicodeString& source, - Formattable& result, - ParsePosition& pos) const { - Formattable resultNumber(0.0); - UBool withNumberFormat = false; - TimeUnit::UTimeUnitFields resultTimeUnit = TimeUnit::UTIMEUNIT_FIELD_COUNT; - int32_t oldPos = pos.getIndex(); - int32_t newPos = -1; - int32_t longestParseDistance = 0; - UnicodeString* countOfLongestMatch = NULL; -#ifdef TMUTFMT_DEBUG - char res[1000]; - source.extract(0, source.length(), res, "UTF-8"); - std::cout << "parse source: " << res << "\n"; -#endif - // parse by iterating through all available patterns - // and looking for the longest match. - for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR; - i < TimeUnit::UTIMEUNIT_FIELD_COUNT; - i = (TimeUnit::UTimeUnitFields)(i+1)) { - Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i]; - int32_t elemPos = UHASH_FIRST; - const UHashElement* elem = NULL; - while ((elem = countToPatterns->nextElement(elemPos)) != NULL){ - const UHashTok keyTok = elem->key; - UnicodeString* count = (UnicodeString*)keyTok.pointer; -#ifdef TMUTFMT_DEBUG - count->extract(0, count->length(), res, "UTF-8"); - std::cout << "parse plural count: " << res << "\n"; -#endif - const UHashTok valueTok = elem->value; - // the value is a pair of MessageFormat* - MessageFormat** patterns = (MessageFormat**)valueTok.pointer; - for (UTimeUnitFormatStyle style = UTMUTFMT_FULL_STYLE; style < UTMUTFMT_FORMAT_STYLE_COUNT; - style = (UTimeUnitFormatStyle)(style + 1)) { - MessageFormat* pattern = patterns[style]; - pos.setErrorIndex(-1); - pos.setIndex(oldPos); - // see if we can parse - Formattable parsed; - pattern->parseObject(source, parsed, pos); - if (pos.getErrorIndex() != -1 || pos.getIndex() == oldPos) { - continue; - } - #ifdef TMUTFMT_DEBUG - std::cout << "parsed.getType: " << parsed.getType() << "\n"; - #endif - Formattable tmpNumber(0.0); - if (pattern->getArgTypeCount() != 0) { - Formattable& temp = parsed[0]; - if (temp.getType() == Formattable::kString) { - UnicodeString tmpString; - UErrorCode pStatus = U_ZERO_ERROR; - getNumberFormat().parse(temp.getString(tmpString), tmpNumber, pStatus); - if (U_FAILURE(pStatus)) { - continue; - } - } else if (temp.isNumeric()) { - tmpNumber = temp; - } else { - continue; - } - } - int32_t parseDistance = pos.getIndex() - oldPos; - if (parseDistance > longestParseDistance) { - if (pattern->getArgTypeCount() != 0) { - resultNumber = tmpNumber; - withNumberFormat = true; - } else { - withNumberFormat = false; - } - resultTimeUnit = i; - newPos = pos.getIndex(); - longestParseDistance = parseDistance; - countOfLongestMatch = count; - } - } - } - } - /* After find the longest match, parse the number. - * Result number could be null for the pattern without number pattern. - * such as unit pattern in Arabic. - * When result number is null, use plural rule to set the number. - */ - if (withNumberFormat == false && longestParseDistance != 0) { - // set the number using plurrual count - if (0 == countOfLongestMatch->compare(PLURAL_COUNT_ZERO, 4)) { - resultNumber = Formattable(0.0); - } else if (0 == countOfLongestMatch->compare(PLURAL_COUNT_ONE, 3)) { - resultNumber = Formattable(1.0); - } else if (0 == countOfLongestMatch->compare(PLURAL_COUNT_TWO, 3)) { - resultNumber = Formattable(2.0); - } else { - // should not happen. - // TODO: how to handle? - resultNumber = Formattable(3.0); - } - } - if (longestParseDistance == 0) { - pos.setIndex(oldPos); - pos.setErrorIndex(0); - } else { - UErrorCode status = U_ZERO_ERROR; - LocalPointer<TimeUnitAmount> tmutamt(new TimeUnitAmount(resultNumber, resultTimeUnit, status), status); - if (U_SUCCESS(status)) { - result.adoptObject(tmutamt.orphan()); - pos.setIndex(newPos); - pos.setErrorIndex(-1); - } else { - pos.setIndex(oldPos); - pos.setErrorIndex(0); - } - } -} - -void -TimeUnitFormat::create(UTimeUnitFormatStyle style, UErrorCode& status) { - // fTimeUnitToCountToPatterns[] must have its elements initialized to NULL first - // before checking for failure status. - for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR; - i < TimeUnit::UTIMEUNIT_FIELD_COUNT; - i = (TimeUnit::UTimeUnitFields)(i+1)) { - fTimeUnitToCountToPatterns[i] = NULL; - } - - if (U_FAILURE(status)) { - return; - } - if (style < UTMUTFMT_FULL_STYLE || style >= UTMUTFMT_FORMAT_STYLE_COUNT) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return; - } - fStyle = style; - - //TODO: format() and parseObj() are const member functions, - //so, can not do lazy initialization in C++. - //setup has to be done in constructors. - //and here, the behavior is not consistent with Java. - //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. - setup(status); -} - -void -TimeUnitFormat::setup(UErrorCode& err) { - initDataMembers(err); - - UVector pluralCounts(0, uhash_compareUnicodeString, 6, err); - LocalPointer<StringEnumeration> keywords(getPluralRules().getKeywords(err), err); - if (U_FAILURE(err)) { - return; - } - UnicodeString* pluralCount; - while ((pluralCount = const_cast<UnicodeString*>(keywords->snext(err))) != NULL) { - pluralCounts.addElement(pluralCount, err); - } - readFromCurrentLocale(UTMUTFMT_FULL_STYLE, gUnitsTag, pluralCounts, err); - checkConsistency(UTMUTFMT_FULL_STYLE, gUnitsTag, err); - readFromCurrentLocale(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, pluralCounts, err); - checkConsistency(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, err); -} - - -void -TimeUnitFormat::initDataMembers(UErrorCode& err){ - if (U_FAILURE(err)) { - return; - } - for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR; - i < TimeUnit::UTIMEUNIT_FIELD_COUNT; - i = (TimeUnit::UTimeUnitFields)(i+1)) { - deleteHash(fTimeUnitToCountToPatterns[i]); - fTimeUnitToCountToPatterns[i] = NULL; - } -} - -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) { - continue; - } - - TimeUnit::UTimeUnitFields timeUnitField = TimeUnit::UTIMEUNIT_FIELD_COUNT; - if ( uprv_strcmp(timeUnitName, gTimeUnitYear) == 0 ) { - timeUnitField = TimeUnit::UTIMEUNIT_YEAR; - } else if ( uprv_strcmp(timeUnitName, gTimeUnitMonth) == 0 ) { - timeUnitField = TimeUnit::UTIMEUNIT_MONTH; - } else if ( uprv_strcmp(timeUnitName, gTimeUnitDay) == 0 ) { - timeUnitField = TimeUnit::UTIMEUNIT_DAY; - } else if ( uprv_strcmp(timeUnitName, gTimeUnitHour) == 0 ) { - timeUnitField = TimeUnit::UTIMEUNIT_HOUR; - } else if ( uprv_strcmp(timeUnitName, gTimeUnitMinute) == 0 ) { - timeUnitField = TimeUnit::UTIMEUNIT_MINUTE; - } else if ( uprv_strcmp(timeUnitName, gTimeUnitSecond) == 0 ) { - timeUnitField = TimeUnit::UTIMEUNIT_SECOND; - } else if ( uprv_strcmp(timeUnitName, gTimeUnitWeek) == 0 ) { - timeUnitField = TimeUnit::UTIMEUNIT_WEEK; - } else { - continue; - } - LocalPointer<Hashtable> localCountToPatterns; - Hashtable *countToPatterns = - timeUnitFormatObj->fTimeUnitToCountToPatterns[timeUnitField]; - if (countToPatterns == NULL) { - localCountToPatterns.adoptInsteadAndCheckErrorCode( - timeUnitFormatObj->initHash(errorCode), errorCode); - countToPatterns = localCountToPatterns.getAlias(); - if (U_FAILURE(errorCode)) { - return; - } - } - - 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(key, -1, US_INV); - if (!pluralCounts.contains(&pluralCountUniStr)) { - continue; - } - 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 (timeUnitFormatObj->fTimeUnitToCountToPatterns[timeUnitField] == NULL) { - timeUnitFormatObj->fTimeUnitToCountToPatterns[timeUnitField] = localCountToPatterns.orphan(); - } - } - } - -}; - -TimeUnitFormatReadSink::~TimeUnitFormatReadSink() {} - -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 plural rule, following is unit pattern fall-back rule: - // ( for example: "one" hour ) - // look for its unit pattern in its locale tree. - // if pattern is not found in its own locale, such as de_DE, - // look for the pattern in its parent, such as de, - // keep looking till found or till root. - // if the pattern is not found in root either, - // 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". - // - // Following is consistency check to create pattern for each - // plural rule in each time unit using above fall-back rule. - // - 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. - } - } -} - - - -// srcPluralCount is the original plural count on which the pattern is -// searched for. -// 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", -// then, "other" is the searchPluralCount. -void -TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key, const char* localeName, - TimeUnit::UTimeUnitFields srcTimeUnitField, - const UnicodeString& srcPluralCount, - const char* searchPluralCount, - Hashtable* countToPatterns, - UErrorCode& err) { - if (U_FAILURE(err)) { - return; - } - UErrorCode status = U_ZERO_ERROR; - char parentLocale[ULOC_FULLNAME_CAPACITY]; - uprv_strcpy(parentLocale, localeName); - int32_t locNameLen; - U_ASSERT(countToPatterns != NULL); - while ((locNameLen = uloc_getParent(parentLocale, parentLocale, - ULOC_FULLNAME_CAPACITY, &status)) >= 0){ - // look for pattern for srcPluralCount in locale tree - LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_UNIT, parentLocale, &status)); - LocalUResourceBundlePointer unitsRes(ures_getByKey(rb.getAlias(), key, NULL, &status)); - const char* timeUnitName = getTimeUnitName(srcTimeUnitField, status); - LocalUResourceBundlePointer countsToPatternRB(ures_getByKey(unitsRes.getAlias(), timeUnitName, NULL, &status)); - const UChar* pattern; - int32_t ptLength; - pattern = ures_getStringByKeyWithFallback(countsToPatternRB.getAlias(), searchPluralCount, &ptLength, &status); - if (U_SUCCESS(status)) { - //found - 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; - } - } - //delete formatters[style]; - formatters[style] = messageFormat.orphan(); - return; - } - status = U_ZERO_ERROR; - if (locNameLen == 0) { - break; - } - } - - // if no unitsShort resource was found even after fallback to root locale - // then search the units resource fallback from the current level to root - if ( locNameLen == 0 && uprv_strcmp(key, gShortUnitsTag) == 0) { -#ifdef TMUTFMT_DEBUG - std::cout << "loop into searchInLocaleChain since Short-Long-Alternative \n"; -#endif - 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 - 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; - } - } - - // if not found the pattern for this plural count at all, - // fall-back to plural count "other" - if ( uprv_strcmp(searchPluralCount, gPluralCountOther) == 0 ) { - // set default fall back the same as the resource in root - LocalPointer<MessageFormat> messageFormat; - const UChar *pattern = NULL; - if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_SECOND ) { - pattern = DEFAULT_PATTERN_FOR_SECOND; - } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_MINUTE ) { - pattern = DEFAULT_PATTERN_FOR_MINUTE; - } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_HOUR ) { - pattern = DEFAULT_PATTERN_FOR_HOUR; - } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_WEEK ) { - pattern = DEFAULT_PATTERN_FOR_WEEK; - } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_DAY ) { - pattern = DEFAULT_PATTERN_FOR_DAY; - } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_MONTH ) { - pattern = DEFAULT_PATTERN_FOR_MONTH; - } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_YEAR ) { - pattern = DEFAULT_PATTERN_FOR_YEAR; - } - if (pattern != NULL) { - messageFormat.adoptInsteadAndCheckErrorCode( - new MessageFormat(UnicodeString(TRUE, pattern, -1), 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*))); - if (localFormatters.isNull()) { - err = U_MEMORY_ALLOCATION_ERROR; - return; - } - 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, - gPluralCountOther, countToPatterns, err); - } -} - -void -TimeUnitFormat::setLocale(const Locale& locale, UErrorCode& status) { - if (setMeasureFormatLocale(locale, status)) { - setup(status); - } -} - - -void -TimeUnitFormat::setNumberFormat(const NumberFormat& format, UErrorCode& status){ - if (U_FAILURE(status)) { - return; - } - adoptNumberFormat((NumberFormat *)format.clone(), status); -} - - -void -TimeUnitFormat::deleteHash(Hashtable* htable) { - int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - if ( htable ) { - while ( (element = htable->nextElement(pos)) != NULL ) { - const UHashTok valueTok = element->value; - const MessageFormat** value = (const MessageFormat**)valueTok.pointer; - delete value[UTMUTFMT_FULL_STYLE]; - delete value[UTMUTFMT_ABBREVIATED_STYLE]; - //delete[] value; - uprv_free(value); - } - } - delete htable; -} - - -void -TimeUnitFormat::copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status) { - if ( U_FAILURE(status) ) { - return; - } - int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - if ( source ) { - while ( (element = source->nextElement(pos)) != NULL ) { - const UHashTok keyTok = element->key; - const UnicodeString* key = (UnicodeString*)keyTok.pointer; - const UHashTok valueTok = element->value; - const MessageFormat** value = (const MessageFormat**)valueTok.pointer; - MessageFormat** newVal = (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*)); - newVal[0] = (MessageFormat*)value[0]->clone(); - newVal[1] = (MessageFormat*)value[1]->clone(); - target->put(UnicodeString(*key), newVal, status); - if ( U_FAILURE(status) ) { - delete newVal[0]; - delete newVal[1]; - uprv_free(newVal); - return; - } - } - } -} - - -U_CDECL_BEGIN - -/** - * set hash table value comparator - * - * @param val1 one value in comparison - * @param val2 the other value in comparison - * @return TRUE if 2 values are the same, FALSE otherwise - */ -static UBool U_CALLCONV tmutfmtHashTableValueComparator(UHashTok val1, UHashTok val2); - -static UBool -U_CALLCONV tmutfmtHashTableValueComparator(UHashTok val1, UHashTok val2) { - const MessageFormat** pattern1 = (const MessageFormat**)val1.pointer; - const MessageFormat** pattern2 = (const MessageFormat**)val2.pointer; - return *pattern1[0] == *pattern2[0] && *pattern1[1] == *pattern2[1]; -} - -U_CDECL_END - -Hashtable* -TimeUnitFormat::initHash(UErrorCode& status) { - if ( U_FAILURE(status) ) { - return NULL; - } - Hashtable* hTable; - if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - if ( U_FAILURE(status) ) { - delete hTable; - return NULL; - } - hTable->setValueComparator(tmutfmtHashTableValueComparator); - return hTable; -} - - -const char* -TimeUnitFormat::getTimeUnitName(TimeUnit::UTimeUnitFields unitField, - UErrorCode& status) { - if (U_FAILURE(status)) { - return NULL; - } - switch (unitField) { - case TimeUnit::UTIMEUNIT_YEAR: - return gTimeUnitYear; - case TimeUnit::UTIMEUNIT_MONTH: - return gTimeUnitMonth; - case TimeUnit::UTIMEUNIT_DAY: - return gTimeUnitDay; - case TimeUnit::UTIMEUNIT_WEEK: - return gTimeUnitWeek; - case TimeUnit::UTIMEUNIT_HOUR: - return gTimeUnitHour; - case TimeUnit::UTIMEUNIT_MINUTE: - return gTimeUnitMinute; - case TimeUnit::UTIMEUNIT_SECOND: - return gTimeUnitSecond; - default: - status = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; - } -} - -U_NAMESPACE_END - -#endif |