| Index: source/i18n/tznames_impl.cpp
|
| diff --git a/source/i18n/tznames_impl.cpp b/source/i18n/tznames_impl.cpp
|
| index d11d787cfc7758756d11fa20a7b76d207ba43980..1595d89c549472c01f56da3e3aa7bc63226b7a01 100644
|
| --- a/source/i18n/tznames_impl.cpp
|
| +++ b/source/i18n/tznames_impl.cpp
|
| @@ -1,6 +1,6 @@
|
| /*
|
| *******************************************************************************
|
| -* Copyright (C) 2011-2013, International Business Machines Corporation and
|
| +* Copyright (C) 2011-2014, International Business Machines Corporation and
|
| * others. All Rights Reserved.
|
| *******************************************************************************
|
| *
|
| @@ -51,6 +51,36 @@ static const UTimeZoneNameType ALL_NAME_TYPES[] = {
|
| UTZNM_UNKNOWN // unknown as the last one
|
| };
|
|
|
| +// stuff for TZDBTimeZoneNames
|
| +static const char* TZDBNAMES_KEYS[] = {"ss", "sd"};
|
| +static const int32_t TZDBNAMES_KEYS_SIZE = (sizeof TZDBNAMES_KEYS / sizeof TZDBNAMES_KEYS[0]);
|
| +
|
| +static UMutex gTZDBNamesMapLock = U_MUTEX_INITIALIZER;
|
| +
|
| +static UHashtable* gTZDBNamesMap = NULL;
|
| +static icu::UInitOnce gTZDBNamesMapInitOnce = U_INITONCE_INITIALIZER;
|
| +
|
| +static TextTrieMap* gTZDBNamesTrie = NULL;
|
| +static icu::UInitOnce gTZDBNamesTrieInitOnce = U_INITONCE_INITIALIZER;
|
| +
|
| +U_CDECL_BEGIN
|
| +static UBool U_CALLCONV tzdbTimeZoneNames_cleanup(void) {
|
| + if (gTZDBNamesMap != NULL) {
|
| + uhash_close(gTZDBNamesMap);
|
| + gTZDBNamesMap = NULL;
|
| + }
|
| + gTZDBNamesMapInitOnce.reset();
|
| +
|
| + if (gTZDBNamesTrie != NULL) {
|
| + delete gTZDBNamesTrie;
|
| + gTZDBNamesTrie = NULL;
|
| + }
|
| + gTZDBNamesTrieInitOnce.reset();
|
| +
|
| + return TRUE;
|
| +}
|
| +U_CDECL_END
|
| +
|
| #define DEFAULT_CHARACTERNODE_CAPACITY 1
|
|
|
| // ---------------------------------------------------
|
| @@ -799,7 +829,7 @@ ZNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node,
|
| for (int32_t i = 0; i < valuesCount; i++) {
|
| ZNameInfo *nameinfo = (ZNameInfo *)node->getValue(i);
|
| if (nameinfo == NULL) {
|
| - break;
|
| + continue;
|
| }
|
| if ((nameinfo->type & fTypes) != 0) {
|
| // matches a requested type
|
| @@ -986,6 +1016,12 @@ TimeZoneNamesImpl::clone() const {
|
|
|
| StringEnumeration*
|
| TimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const {
|
| + return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
|
| +}
|
| +
|
| +// static implementation of getAvailableMetaZoneIDs(UErrorCode&)
|
| +StringEnumeration*
|
| +TimeZoneNamesImpl::_getAvailableMetaZoneIDs(UErrorCode& status) {
|
| if (U_FAILURE(status)) {
|
| return NULL;
|
| }
|
| @@ -998,6 +1034,12 @@ TimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const {
|
|
|
| StringEnumeration*
|
| TimeZoneNamesImpl::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const {
|
| + return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(tzID, status);
|
| +}
|
| +
|
| +// static implementation of getAvailableMetaZoneIDs(const UnicodeString&, UErrorCode&)
|
| +StringEnumeration*
|
| +TimeZoneNamesImpl::_getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) {
|
| if (U_FAILURE(status)) {
|
| return NULL;
|
| }
|
| @@ -1032,16 +1074,29 @@ TimeZoneNamesImpl::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode
|
|
|
| UnicodeString&
|
| TimeZoneNamesImpl::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const {
|
| + return TimeZoneNamesImpl::_getMetaZoneID(tzID, date, mzID);
|
| +}
|
| +
|
| +// static implementation of getMetaZoneID
|
| +UnicodeString&
|
| +TimeZoneNamesImpl::_getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) {
|
| ZoneMeta::getMetazoneID(tzID, date, mzID);
|
| return mzID;
|
| }
|
|
|
| UnicodeString&
|
| TimeZoneNamesImpl::getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const {
|
| + return TimeZoneNamesImpl::_getReferenceZoneID(mzID, region, tzID);
|
| +}
|
| +
|
| +// static implementaion of getReferenceZoneID
|
| +UnicodeString&
|
| +TimeZoneNamesImpl::_getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) {
|
| ZoneMeta::getZoneIdByMetazone(mzID, UnicodeString(region, -1, US_INV), tzID);
|
| return tzID;
|
| }
|
|
|
| +
|
| UnicodeString&
|
| TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID,
|
| UTimeZoneNameType type,
|
| @@ -1170,6 +1225,7 @@ TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID) {
|
| if (U_FAILURE(status)) {
|
| if (znames != NULL) {
|
| delete znames;
|
| + znames = NULL;
|
| }
|
| } else if (znames != NULL) {
|
| // put the name info into the trie
|
| @@ -1247,6 +1303,7 @@ TimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID) {
|
| if (U_FAILURE(status)) {
|
| if (tznames != NULL) {
|
| delete tznames;
|
| + tznames = NULL;
|
| }
|
| } else if (tznames != NULL) {
|
| // put the name info into the trie
|
| @@ -1371,6 +1428,589 @@ TimeZoneNamesImpl::getDefaultExemplarLocationName(const UnicodeString& tzID, Uni
|
| return name;
|
| }
|
|
|
| +// ---------------------------------------------------
|
| +// TZDBTimeZoneNames and its supporting classes
|
| +//
|
| +// TZDBTimeZoneNames is an implementation class of
|
| +// TimeZoneNames holding the IANA tz database abbreviations.
|
| +// ---------------------------------------------------
|
| +
|
| +class TZDBNames : public UMemory {
|
| +public:
|
| + virtual ~TZDBNames();
|
| +
|
| + static TZDBNames* createInstance(UResourceBundle* rb, const char* key);
|
| + const UChar* getName(UTimeZoneNameType type) const;
|
| + const char** getParseRegions(int32_t& numRegions) const;
|
| +
|
| +protected:
|
| + TZDBNames(const UChar** names, char** regions, int32_t numRegions);
|
| +
|
| +private:
|
| + const UChar** fNames;
|
| + char** fRegions;
|
| + int32_t fNumRegions;
|
| +};
|
| +
|
| +TZDBNames::TZDBNames(const UChar** names, char** regions, int32_t numRegions)
|
| + : fNames(names),
|
| + fRegions(regions),
|
| + fNumRegions(numRegions) {
|
| +}
|
| +
|
| +TZDBNames::~TZDBNames() {
|
| + if (fNames != NULL) {
|
| + uprv_free(fNames);
|
| + }
|
| + if (fRegions != NULL) {
|
| + char **p = fRegions;
|
| + for (int32_t i = 0; i < fNumRegions; p++, i++) {
|
| + uprv_free(*p);
|
| + }
|
| + uprv_free(fRegions);
|
| + }
|
| +}
|
| +
|
| +TZDBNames*
|
| +TZDBNames::createInstance(UResourceBundle* rb, const char* key) {
|
| + if (rb == NULL || key == NULL || *key == 0) {
|
| + return NULL;
|
| + }
|
| +
|
| + UErrorCode status = U_ZERO_ERROR;
|
| +
|
| + const UChar **names = NULL;
|
| + char** regions = NULL;
|
| + int32_t numRegions = 0;
|
| +
|
| + int32_t len = 0;
|
| +
|
| + UResourceBundle* rbTable = NULL;
|
| + rbTable = ures_getByKey(rb, key, rbTable, &status);
|
| + if (U_FAILURE(status)) {
|
| + return NULL;
|
| + }
|
| +
|
| + names = (const UChar **)uprv_malloc(sizeof(const UChar*) * TZDBNAMES_KEYS_SIZE);
|
| + UBool isEmpty = TRUE;
|
| + if (names != NULL) {
|
| + for (int32_t i = 0; i < TZDBNAMES_KEYS_SIZE; i++) {
|
| + status = U_ZERO_ERROR;
|
| + const UChar *value = ures_getStringByKey(rbTable, TZDBNAMES_KEYS[i], &len, &status);
|
| + if (U_FAILURE(status) || len == 0) {
|
| + names[i] = NULL;
|
| + } else {
|
| + names[i] = value;
|
| + isEmpty = FALSE;
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (isEmpty) {
|
| + if (names != NULL) {
|
| + uprv_free(names);
|
| + }
|
| + return NULL;
|
| + }
|
| +
|
| + UResourceBundle *regionsRes = ures_getByKey(rbTable, "parseRegions", NULL, &status);
|
| + UBool regionError = FALSE;
|
| + if (U_SUCCESS(status)) {
|
| + numRegions = ures_getSize(regionsRes);
|
| + if (numRegions > 0) {
|
| + regions = (char**)uprv_malloc(sizeof(char*) * numRegions);
|
| + if (regions != NULL) {
|
| + char **pRegion = regions;
|
| + for (int32_t i = 0; i < numRegions; i++, pRegion++) {
|
| + *pRegion = NULL;
|
| + }
|
| + // filling regions
|
| + pRegion = regions;
|
| + for (int32_t i = 0; i < numRegions; i++, pRegion++) {
|
| + status = U_ZERO_ERROR;
|
| + const UChar *uregion = ures_getStringByIndex(regionsRes, i, &len, &status);
|
| + if (U_FAILURE(status)) {
|
| + regionError = TRUE;
|
| + break;
|
| + }
|
| + *pRegion = (char*)uprv_malloc(sizeof(char) * (len + 1));
|
| + if (*pRegion == NULL) {
|
| + regionError = TRUE;
|
| + break;
|
| + }
|
| + u_UCharsToChars(uregion, *pRegion, len);
|
| + (*pRegion)[len] = 0;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + ures_close(regionsRes);
|
| + ures_close(rbTable);
|
| +
|
| + if (regionError) {
|
| + if (names != NULL) {
|
| + uprv_free(names);
|
| + }
|
| + if (regions != NULL) {
|
| + char **p = regions;
|
| + for (int32_t i = 0; i < numRegions; p++, i++) {
|
| + uprv_free(p);
|
| + }
|
| + uprv_free(regions);
|
| + }
|
| + return NULL;
|
| + }
|
| +
|
| + return new TZDBNames(names, regions, numRegions);
|
| +}
|
| +
|
| +const UChar*
|
| +TZDBNames::getName(UTimeZoneNameType type) const {
|
| + if (fNames == NULL) {
|
| + return NULL;
|
| + }
|
| + const UChar *name = NULL;
|
| + switch(type) {
|
| + case UTZNM_SHORT_STANDARD:
|
| + name = fNames[0];
|
| + break;
|
| + case UTZNM_SHORT_DAYLIGHT:
|
| + name = fNames[1];
|
| + break;
|
| + default:
|
| + name = NULL;
|
| + }
|
| + return name;
|
| +}
|
| +
|
| +const char**
|
| +TZDBNames::getParseRegions(int32_t& numRegions) const {
|
| + if (fRegions == NULL) {
|
| + numRegions = 0;
|
| + } else {
|
| + numRegions = fNumRegions;
|
| + }
|
| + return (const char**)fRegions;
|
| +}
|
| +
|
| +U_CDECL_BEGIN
|
| +/**
|
| + * TZDBNameInfo stores metazone name information for the IANA abbreviations
|
| + * in the trie
|
| + */
|
| +typedef struct TZDBNameInfo {
|
| + const UChar* mzID;
|
| + UTimeZoneNameType type;
|
| + UBool ambiguousType;
|
| + const char** parseRegions;
|
| + int32_t nRegions;
|
| +} TZDBNameInfo;
|
| +U_CDECL_END
|
| +
|
| +
|
| +class TZDBNameSearchHandler : public TextTrieMapSearchResultHandler {
|
| +public:
|
| + TZDBNameSearchHandler(uint32_t types, const char* region);
|
| + virtual ~TZDBNameSearchHandler();
|
| +
|
| + UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
|
| + TimeZoneNames::MatchInfoCollection* getMatches(int32_t& maxMatchLen);
|
| +
|
| +private:
|
| + uint32_t fTypes;
|
| + int32_t fMaxMatchLen;
|
| + TimeZoneNames::MatchInfoCollection* fResults;
|
| + const char* fRegion;
|
| +};
|
| +
|
| +TZDBNameSearchHandler::TZDBNameSearchHandler(uint32_t types, const char* region)
|
| +: fTypes(types), fMaxMatchLen(0), fResults(NULL), fRegion(region) {
|
| +}
|
| +
|
| +TZDBNameSearchHandler::~TZDBNameSearchHandler() {
|
| + if (fResults != NULL) {
|
| + delete fResults;
|
| + }
|
| +}
|
| +
|
| +UBool
|
| +TZDBNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
|
| + if (U_FAILURE(status)) {
|
| + return FALSE;
|
| + }
|
| +
|
| + TZDBNameInfo *match = NULL;
|
| + TZDBNameInfo *defaultRegionMatch = NULL;
|
| +
|
| + if (node->hasValues()) {
|
| + int32_t valuesCount = node->countValues();
|
| + for (int32_t i = 0; i < valuesCount; i++) {
|
| + TZDBNameInfo *ninfo = (TZDBNameInfo *)node->getValue(i);
|
| + if (ninfo == NULL) {
|
| + continue;
|
| + }
|
| + if ((ninfo->type & fTypes) != 0) {
|
| + // Some tz database abbreviations are ambiguous. For example,
|
| + // CST means either Central Standard Time or China Standard Time.
|
| + // Unlike CLDR time zone display names, this implementation
|
| + // does not use unique names. And TimeZoneFormat does not expect
|
| + // multiple results returned for the same time zone type.
|
| + // For this reason, this implementation resolve one among same
|
| + // zone type with a same name at this level.
|
| + if (ninfo->parseRegions == NULL) {
|
| + // parseRegions == null means this is the default metazone
|
| + // mapping for the abbreviation.
|
| + if (defaultRegionMatch == NULL) {
|
| + match = defaultRegionMatch = ninfo;
|
| + }
|
| + } else {
|
| + UBool matchRegion = FALSE;
|
| + // non-default metazone mapping for an abbreviation
|
| + // comes with applicable regions. For example, the default
|
| + // metazone mapping for "CST" is America_Central,
|
| + // but if region is one of CN/MO/TW, "CST" is parsed
|
| + // as metazone China (China Standard Time).
|
| + for (int32_t i = 0; i < ninfo->nRegions; i++) {
|
| + const char *region = ninfo->parseRegions[i];
|
| + if (uprv_strcmp(fRegion, region) == 0) {
|
| + match = ninfo;
|
| + matchRegion = TRUE;
|
| + break;
|
| + }
|
| + }
|
| + if (matchRegion) {
|
| + break;
|
| + }
|
| + if (match == NULL) {
|
| + match = ninfo;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (match != NULL) {
|
| + UTimeZoneNameType ntype = match->type;
|
| + // Note: Workaround for duplicated standard/daylight names
|
| + // The tz database contains a few zones sharing a
|
| + // same name for both standard time and daylight saving
|
| + // time. For example, Australia/Sydney observes DST,
|
| + // but "EST" is used for both standard and daylight.
|
| + // When both SHORT_STANDARD and SHORT_DAYLIGHT are included
|
| + // in the find operation, we cannot tell which one was
|
| + // actually matched.
|
| + // TimeZoneFormat#parse returns a matched name type (standard
|
| + // or daylight) and DateFormat implementation uses the info to
|
| + // to adjust actual time. To avoid false type information,
|
| + // this implementation replaces the name type with SHORT_GENERIC.
|
| + if (match->ambiguousType
|
| + && (ntype == UTZNM_SHORT_STANDARD || ntype == UTZNM_SHORT_DAYLIGHT)
|
| + && (fTypes & UTZNM_SHORT_STANDARD) != 0
|
| + && (fTypes & UTZNM_SHORT_DAYLIGHT) != 0) {
|
| + ntype = UTZNM_SHORT_GENERIC;
|
| + }
|
| +
|
| + if (fResults == NULL) {
|
| + fResults = new TimeZoneNames::MatchInfoCollection();
|
| + if (fResults == NULL) {
|
| + status = U_MEMORY_ALLOCATION_ERROR;
|
| + }
|
| + }
|
| + if (U_SUCCESS(status)) {
|
| + U_ASSERT(fResults != NULL);
|
| + U_ASSERT(match->mzID != NULL);
|
| + fResults->addMetaZone(ntype, matchLength, UnicodeString(match->mzID, -1), status);
|
| + if (U_SUCCESS(status) && matchLength > fMaxMatchLen) {
|
| + fMaxMatchLen = matchLength;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + return TRUE;
|
| +}
|
| +
|
| +TimeZoneNames::MatchInfoCollection*
|
| +TZDBNameSearchHandler::getMatches(int32_t& maxMatchLen) {
|
| + // give the ownership to the caller
|
| + TimeZoneNames::MatchInfoCollection* results = fResults;
|
| + maxMatchLen = fMaxMatchLen;
|
| +
|
| + // reset
|
| + fResults = NULL;
|
| + fMaxMatchLen = 0;
|
| + return results;
|
| +}
|
| +
|
| +U_CDECL_BEGIN
|
| +/**
|
| + * Deleter for TZDBNames
|
| + */
|
| +static void U_CALLCONV
|
| +deleteTZDBNames(void *obj) {
|
| + if (obj != EMPTY) {
|
| + delete (TZDBNames *)obj;
|
| + }
|
| +}
|
| +
|
| +static void U_CALLCONV initTZDBNamesMap(UErrorCode &status) {
|
| + gTZDBNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
|
| + if (U_FAILURE(status)) {
|
| + gTZDBNamesMap = NULL;
|
| + return;
|
| + }
|
| + // no key deleters for tzdb name maps
|
| + uhash_setValueDeleter(gTZDBNamesMap, deleteTZDBNames);
|
| + ucln_i18n_registerCleanup(UCLN_I18N_TZDBTIMEZONENAMES, tzdbTimeZoneNames_cleanup);
|
| +}
|
| +
|
| +/**
|
| + * Deleter for TZDBNameInfo
|
| + */
|
| +static void U_CALLCONV
|
| +deleteTZDBNameInfo(void *obj) {
|
| + if (obj != NULL) {
|
| + uprv_free(obj);
|
| + }
|
| +}
|
| +
|
| +static void U_CALLCONV prepareFind(UErrorCode &status) {
|
| + if (U_FAILURE(status)) {
|
| + return;
|
| + }
|
| + gTZDBNamesTrie = new TextTrieMap(TRUE, deleteTZDBNameInfo);
|
| + if (gTZDBNamesTrie == NULL) {
|
| + status = U_MEMORY_ALLOCATION_ERROR;
|
| + return;
|
| + }
|
| +
|
| + const UnicodeString *mzID;
|
| + StringEnumeration *mzIDs = TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
|
| + if (U_SUCCESS(status)) {
|
| + while ((mzID = mzIDs->snext(status)) && U_SUCCESS(status)) {
|
| + const TZDBNames *names = TZDBTimeZoneNames::getMetaZoneNames(*mzID, status);
|
| + if (names == NULL) {
|
| + continue;
|
| + }
|
| + const UChar *std = names->getName(UTZNM_SHORT_STANDARD);
|
| + const UChar *dst = names->getName(UTZNM_SHORT_DAYLIGHT);
|
| + if (std == NULL && dst == NULL) {
|
| + continue;
|
| + }
|
| + int32_t numRegions = 0;
|
| + const char **parseRegions = names->getParseRegions(numRegions);
|
| +
|
| + // The tz database contains a few zones sharing a
|
| + // same name for both standard time and daylight saving
|
| + // time. For example, Australia/Sydney observes DST,
|
| + // but "EST" is used for both standard and daylight.
|
| + // we need to store the information for later processing.
|
| + UBool ambiguousType = (std != NULL && dst != NULL && u_strcmp(std, dst) == 0);
|
| +
|
| + const UChar *uMzID = ZoneMeta::findMetaZoneID(*mzID);
|
| + if (std != NULL) {
|
| + TZDBNameInfo *stdInf = (TZDBNameInfo *)uprv_malloc(sizeof(TZDBNameInfo));
|
| + if (stdInf == NULL) {
|
| + status = U_MEMORY_ALLOCATION_ERROR;
|
| + break;
|
| + }
|
| + stdInf->mzID = uMzID;
|
| + stdInf->type = UTZNM_SHORT_STANDARD;
|
| + stdInf->ambiguousType = ambiguousType;
|
| + stdInf->parseRegions = parseRegions;
|
| + stdInf->nRegions = numRegions;
|
| + gTZDBNamesTrie->put(std, stdInf, status);
|
| + }
|
| + if (U_SUCCESS(status) && dst != NULL) {
|
| + TZDBNameInfo *dstInf = (TZDBNameInfo *)uprv_malloc(sizeof(TZDBNameInfo));
|
| + if (dstInf == NULL) {
|
| + status = U_MEMORY_ALLOCATION_ERROR;
|
| + break;
|
| + }
|
| + dstInf->mzID = uMzID;
|
| + dstInf->type = UTZNM_SHORT_DAYLIGHT;
|
| + dstInf->ambiguousType = ambiguousType;
|
| + dstInf->parseRegions = parseRegions;
|
| + dstInf->nRegions = numRegions;
|
| + gTZDBNamesTrie->put(dst, dstInf, status);
|
| + }
|
| + }
|
| + }
|
| + delete mzIDs;
|
| +
|
| + if (U_FAILURE(status)) {
|
| + delete gTZDBNamesTrie;
|
| + gTZDBNamesTrie = NULL;
|
| + return;
|
| + }
|
| +
|
| + ucln_i18n_registerCleanup(UCLN_I18N_TZDBTIMEZONENAMES, tzdbTimeZoneNames_cleanup);
|
| +}
|
| +
|
| +U_CDECL_END
|
| +
|
| +TZDBTimeZoneNames::TZDBTimeZoneNames(const Locale& locale)
|
| +: fLocale(locale) {
|
| + UBool useWorld = TRUE;
|
| + const char* region = fLocale.getCountry();
|
| + int32_t regionLen = uprv_strlen(region);
|
| + if (regionLen == 0) {
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + char loc[ULOC_FULLNAME_CAPACITY];
|
| + uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status);
|
| + regionLen = uloc_getCountry(loc, fRegion, sizeof(fRegion), &status);
|
| + if (U_SUCCESS(status) && regionLen < (int32_t)sizeof(fRegion)) {
|
| + useWorld = FALSE;
|
| + }
|
| + } else if (regionLen < (int32_t)sizeof(fRegion)) {
|
| + uprv_strcpy(fRegion, region);
|
| + useWorld = FALSE;
|
| + }
|
| + if (useWorld) {
|
| + uprv_strcpy(fRegion, "001");
|
| + }
|
| +}
|
| +
|
| +TZDBTimeZoneNames::~TZDBTimeZoneNames() {
|
| +}
|
| +
|
| +UBool
|
| +TZDBTimeZoneNames::operator==(const TimeZoneNames& other) const {
|
| + if (this == &other) {
|
| + return TRUE;
|
| + }
|
| + // No implementation for now
|
| + return FALSE;
|
| +}
|
| +
|
| +TimeZoneNames*
|
| +TZDBTimeZoneNames::clone() const {
|
| + return new TZDBTimeZoneNames(fLocale);
|
| +}
|
| +
|
| +StringEnumeration*
|
| +TZDBTimeZoneNames::getAvailableMetaZoneIDs(UErrorCode& status) const {
|
| + return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
|
| +}
|
| +
|
| +StringEnumeration*
|
| +TZDBTimeZoneNames::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const {
|
| + return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(tzID, status);
|
| +}
|
| +
|
| +UnicodeString&
|
| +TZDBTimeZoneNames::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const {
|
| + return TimeZoneNamesImpl::_getMetaZoneID(tzID, date, mzID);
|
| +}
|
| +
|
| +UnicodeString&
|
| +TZDBTimeZoneNames::getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const {
|
| + return TimeZoneNamesImpl::_getReferenceZoneID(mzID, region, tzID);
|
| +}
|
| +
|
| +UnicodeString&
|
| +TZDBTimeZoneNames::getMetaZoneDisplayName(const UnicodeString& mzID,
|
| + UTimeZoneNameType type,
|
| + UnicodeString& name) const {
|
| + name.setToBogus();
|
| + if (mzID.isEmpty()) {
|
| + return name;
|
| + }
|
| +
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + const TZDBNames *tzdbNames = TZDBTimeZoneNames::getMetaZoneNames(mzID, status);
|
| + if (U_SUCCESS(status)) {
|
| + const UChar *s = tzdbNames->getName(type);
|
| + if (s != NULL) {
|
| + name.setTo(TRUE, s, -1);
|
| + }
|
| + }
|
| +
|
| + return name;
|
| +}
|
| +
|
| +UnicodeString&
|
| +TZDBTimeZoneNames::getTimeZoneDisplayName(const UnicodeString& /* tzID */, UTimeZoneNameType /* type */, UnicodeString& name) const {
|
| + // No abbreviations associated a zone directly for now.
|
| + name.setToBogus();
|
| + return name;
|
| +}
|
| +
|
| +TZDBTimeZoneNames::MatchInfoCollection*
|
| +TZDBTimeZoneNames::find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
|
| + umtx_initOnce(gTZDBNamesTrieInitOnce, &prepareFind, status);
|
| + if (U_FAILURE(status)) {
|
| + return NULL;
|
| + }
|
| +
|
| + TZDBNameSearchHandler handler(types, fRegion);
|
| + gTZDBNamesTrie->search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
|
| + if (U_FAILURE(status)) {
|
| + return NULL;
|
| + }
|
| + int32_t maxLen = 0;
|
| + return handler.getMatches(maxLen);
|
| +}
|
| +
|
| +const TZDBNames*
|
| +TZDBTimeZoneNames::getMetaZoneNames(const UnicodeString& mzID, UErrorCode& status) {
|
| + umtx_initOnce(gTZDBNamesMapInitOnce, &initTZDBNamesMap, status);
|
| + if (U_FAILURE(status)) {
|
| + return NULL;
|
| + }
|
| +
|
| + TZDBNames* tzdbNames = NULL;
|
| +
|
| + UChar mzIDKey[ZID_KEY_MAX + 1];
|
| + mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
|
| + U_ASSERT(status == U_ZERO_ERROR); // already checked length above
|
| + mzIDKey[mzID.length()] = 0;
|
| +
|
| + umtx_lock(&gTZDBNamesMapLock);
|
| + {
|
| + void *cacheVal = uhash_get(gTZDBNamesMap, mzIDKey);
|
| + if (cacheVal == NULL) {
|
| + UResourceBundle *zoneStringsRes = ures_openDirect(U_ICUDATA_ZONE, "tzdbNames", &status);
|
| + zoneStringsRes = ures_getByKey(zoneStringsRes, gZoneStrings, zoneStringsRes, &status);
|
| + if (U_SUCCESS(status)) {
|
| + char key[ZID_KEY_MAX + 1];
|
| + mergeTimeZoneKey(mzID, key);
|
| + tzdbNames = TZDBNames::createInstance(zoneStringsRes, key);
|
| +
|
| + if (tzdbNames == NULL) {
|
| + cacheVal = (void *)EMPTY;
|
| + } else {
|
| + cacheVal = tzdbNames;
|
| + }
|
| + // Use the persistent ID as the resource key, so we can
|
| + // avoid duplications.
|
| + const UChar* newKey = ZoneMeta::findMetaZoneID(mzID);
|
| + if (newKey != NULL) {
|
| + uhash_put(gTZDBNamesMap, (void *)newKey, cacheVal, &status);
|
| + if (U_FAILURE(status)) {
|
| + if (tzdbNames != NULL) {
|
| + delete tzdbNames;
|
| + tzdbNames = NULL;
|
| + }
|
| + }
|
| + } else {
|
| + // Should never happen with a valid input
|
| + if (tzdbNames != NULL) {
|
| + // It's not possible that we get a valid tzdbNames with unknown ID.
|
| + // But just in case..
|
| + delete tzdbNames;
|
| + tzdbNames = NULL;
|
| + }
|
| + }
|
| + }
|
| + ures_close(zoneStringsRes);
|
| + } else if (cacheVal != EMPTY) {
|
| + tzdbNames = (TZDBNames *)cacheVal;
|
| + }
|
| + }
|
| + umtx_unlock(&gTZDBNamesMapLock);
|
| +
|
| + return tzdbNames;
|
| +}
|
| +
|
| U_NAMESPACE_END
|
|
|
|
|
|
|