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

Side by Side Diff: source/i18n/tznames_impl.cpp

Issue 845603002: Update ICU to 54.1 step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@master
Patch Set: remove unusued directories Created 5 years, 11 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 unified diff | Download patch
« no previous file with comments | « source/i18n/tznames_impl.h ('k') | source/i18n/ucln_in.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ******************************************************************************* 2 *******************************************************************************
3 * Copyright (C) 2011-2013, International Business Machines Corporation and 3 * Copyright (C) 2011-2014, International Business Machines Corporation and
4 * others. All Rights Reserved. 4 * others. All Rights Reserved.
5 ******************************************************************************* 5 *******************************************************************************
6 * 6 *
7 * File TZNAMES_IMPL.CPP 7 * File TZNAMES_IMPL.CPP
8 * 8 *
9 ******************************************************************************* 9 *******************************************************************************
10 */ 10 */
11 11
12 #include "unicode/utypes.h" 12 #include "unicode/utypes.h"
13 13
(...skipping 30 matching lines...) Expand all
44 44
45 static const char EMPTY[] = "<empty>"; // place holder for empty ZNames/TZNames 45 static const char EMPTY[] = "<empty>"; // place holder for empty ZNames/TZNames
46 46
47 static const UTimeZoneNameType ALL_NAME_TYPES[] = { 47 static const UTimeZoneNameType ALL_NAME_TYPES[] = {
48 UTZNM_LONG_GENERIC, UTZNM_LONG_STANDARD, UTZNM_LONG_DAYLIGHT, 48 UTZNM_LONG_GENERIC, UTZNM_LONG_STANDARD, UTZNM_LONG_DAYLIGHT,
49 UTZNM_SHORT_GENERIC, UTZNM_SHORT_STANDARD, UTZNM_SHORT_DAYLIGHT, 49 UTZNM_SHORT_GENERIC, UTZNM_SHORT_STANDARD, UTZNM_SHORT_DAYLIGHT,
50 UTZNM_EXEMPLAR_LOCATION, 50 UTZNM_EXEMPLAR_LOCATION,
51 UTZNM_UNKNOWN // unknown as the last one 51 UTZNM_UNKNOWN // unknown as the last one
52 }; 52 };
53 53
54 // stuff for TZDBTimeZoneNames
55 static const char* TZDBNAMES_KEYS[] = {"ss", "sd"};
56 static const int32_t TZDBNAMES_KEYS_SIZE = (sizeof TZDBNAMES_KEYS / sizeof TZDBN AMES_KEYS[0]);
57
58 static UMutex gTZDBNamesMapLock = U_MUTEX_INITIALIZER;
59
60 static UHashtable* gTZDBNamesMap = NULL;
61 static icu::UInitOnce gTZDBNamesMapInitOnce = U_INITONCE_INITIALIZER;
62
63 static TextTrieMap* gTZDBNamesTrie = NULL;
64 static icu::UInitOnce gTZDBNamesTrieInitOnce = U_INITONCE_INITIALIZER;
65
66 U_CDECL_BEGIN
67 static UBool U_CALLCONV tzdbTimeZoneNames_cleanup(void) {
68 if (gTZDBNamesMap != NULL) {
69 uhash_close(gTZDBNamesMap);
70 gTZDBNamesMap = NULL;
71 }
72 gTZDBNamesMapInitOnce.reset();
73
74 if (gTZDBNamesTrie != NULL) {
75 delete gTZDBNamesTrie;
76 gTZDBNamesTrie = NULL;
77 }
78 gTZDBNamesTrieInitOnce.reset();
79
80 return TRUE;
81 }
82 U_CDECL_END
83
54 #define DEFAULT_CHARACTERNODE_CAPACITY 1 84 #define DEFAULT_CHARACTERNODE_CAPACITY 1
55 85
56 // --------------------------------------------------- 86 // ---------------------------------------------------
57 // CharacterNode class implementation 87 // CharacterNode class implementation
58 // --------------------------------------------------- 88 // ---------------------------------------------------
59 void CharacterNode::clear() { 89 void CharacterNode::clear() {
60 uprv_memset(this, 0, sizeof(*this)); 90 uprv_memset(this, 0, sizeof(*this));
61 } 91 }
62 92
63 void CharacterNode::deleteValues(UObjectDeleter *valueDeleter) { 93 void CharacterNode::deleteValues(UObjectDeleter *valueDeleter) {
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 UBool 822 UBool
793 ZNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) { 823 ZNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
794 if (U_FAILURE(status)) { 824 if (U_FAILURE(status)) {
795 return FALSE; 825 return FALSE;
796 } 826 }
797 if (node->hasValues()) { 827 if (node->hasValues()) {
798 int32_t valuesCount = node->countValues(); 828 int32_t valuesCount = node->countValues();
799 for (int32_t i = 0; i < valuesCount; i++) { 829 for (int32_t i = 0; i < valuesCount; i++) {
800 ZNameInfo *nameinfo = (ZNameInfo *)node->getValue(i); 830 ZNameInfo *nameinfo = (ZNameInfo *)node->getValue(i);
801 if (nameinfo == NULL) { 831 if (nameinfo == NULL) {
802 break; 832 continue;
803 } 833 }
804 if ((nameinfo->type & fTypes) != 0) { 834 if ((nameinfo->type & fTypes) != 0) {
805 // matches a requested type 835 // matches a requested type
806 if (fResults == NULL) { 836 if (fResults == NULL) {
807 fResults = new TimeZoneNames::MatchInfoCollection(); 837 fResults = new TimeZoneNames::MatchInfoCollection();
808 if (fResults == NULL) { 838 if (fResults == NULL) {
809 status = U_MEMORY_ALLOCATION_ERROR; 839 status = U_MEMORY_ALLOCATION_ERROR;
810 } 840 }
811 } 841 }
812 if (U_SUCCESS(status)) { 842 if (U_SUCCESS(status)) {
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 } 1009 }
980 1010
981 TimeZoneNames* 1011 TimeZoneNames*
982 TimeZoneNamesImpl::clone() const { 1012 TimeZoneNamesImpl::clone() const {
983 UErrorCode status = U_ZERO_ERROR; 1013 UErrorCode status = U_ZERO_ERROR;
984 return new TimeZoneNamesImpl(fLocale, status); 1014 return new TimeZoneNamesImpl(fLocale, status);
985 } 1015 }
986 1016
987 StringEnumeration* 1017 StringEnumeration*
988 TimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const { 1018 TimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const {
1019 return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
1020 }
1021
1022 // static implementation of getAvailableMetaZoneIDs(UErrorCode&)
1023 StringEnumeration*
1024 TimeZoneNamesImpl::_getAvailableMetaZoneIDs(UErrorCode& status) {
989 if (U_FAILURE(status)) { 1025 if (U_FAILURE(status)) {
990 return NULL; 1026 return NULL;
991 } 1027 }
992 const UVector* mzIDs = ZoneMeta::getAvailableMetazoneIDs(); 1028 const UVector* mzIDs = ZoneMeta::getAvailableMetazoneIDs();
993 if (mzIDs == NULL) { 1029 if (mzIDs == NULL) {
994 return new MetaZoneIDsEnumeration(); 1030 return new MetaZoneIDsEnumeration();
995 } 1031 }
996 return new MetaZoneIDsEnumeration(*mzIDs); 1032 return new MetaZoneIDsEnumeration(*mzIDs);
997 } 1033 }
998 1034
999 StringEnumeration* 1035 StringEnumeration*
1000 TimeZoneNamesImpl::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode & status) const { 1036 TimeZoneNamesImpl::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode & status) const {
1037 return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(tzID, status);
1038 }
1039
1040 // static implementation of getAvailableMetaZoneIDs(const UnicodeString&, UError Code&)
1041 StringEnumeration*
1042 TimeZoneNamesImpl::_getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCod e& status) {
1001 if (U_FAILURE(status)) { 1043 if (U_FAILURE(status)) {
1002 return NULL; 1044 return NULL;
1003 } 1045 }
1004 const UVector* mappings = ZoneMeta::getMetazoneMappings(tzID); 1046 const UVector* mappings = ZoneMeta::getMetazoneMappings(tzID);
1005 if (mappings == NULL) { 1047 if (mappings == NULL) {
1006 return new MetaZoneIDsEnumeration(); 1048 return new MetaZoneIDsEnumeration();
1007 } 1049 }
1008 1050
1009 MetaZoneIDsEnumeration *senum = NULL; 1051 MetaZoneIDsEnumeration *senum = NULL;
1010 UVector* mzIDs = new UVector(NULL, uhash_compareUChars, status); 1052 UVector* mzIDs = new UVector(NULL, uhash_compareUChars, status);
(...skipping 14 matching lines...) Expand all
1025 senum = new MetaZoneIDsEnumeration(mzIDs); 1067 senum = new MetaZoneIDsEnumeration(mzIDs);
1026 } else { 1068 } else {
1027 delete mzIDs; 1069 delete mzIDs;
1028 } 1070 }
1029 } 1071 }
1030 return senum; 1072 return senum;
1031 } 1073 }
1032 1074
1033 UnicodeString& 1075 UnicodeString&
1034 TimeZoneNamesImpl::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeS tring& mzID) const { 1076 TimeZoneNamesImpl::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeS tring& mzID) const {
1077 return TimeZoneNamesImpl::_getMetaZoneID(tzID, date, mzID);
1078 }
1079
1080 // static implementation of getMetaZoneID
1081 UnicodeString&
1082 TimeZoneNamesImpl::_getMetaZoneID(const UnicodeString& tzID, UDate date, Unicode String& mzID) {
1035 ZoneMeta::getMetazoneID(tzID, date, mzID); 1083 ZoneMeta::getMetazoneID(tzID, date, mzID);
1036 return mzID; 1084 return mzID;
1037 } 1085 }
1038 1086
1039 UnicodeString& 1087 UnicodeString&
1040 TimeZoneNamesImpl::getReferenceZoneID(const UnicodeString& mzID, const char* reg ion, UnicodeString& tzID) const { 1088 TimeZoneNamesImpl::getReferenceZoneID(const UnicodeString& mzID, const char* reg ion, UnicodeString& tzID) const {
1089 return TimeZoneNamesImpl::_getReferenceZoneID(mzID, region, tzID);
1090 }
1091
1092 // static implementaion of getReferenceZoneID
1093 UnicodeString&
1094 TimeZoneNamesImpl::_getReferenceZoneID(const UnicodeString& mzID, const char* re gion, UnicodeString& tzID) {
1041 ZoneMeta::getZoneIdByMetazone(mzID, UnicodeString(region, -1, US_INV), tzID) ; 1095 ZoneMeta::getZoneIdByMetazone(mzID, UnicodeString(region, -1, US_INV), tzID) ;
1042 return tzID; 1096 return tzID;
1043 } 1097 }
1044 1098
1099
1045 UnicodeString& 1100 UnicodeString&
1046 TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID, 1101 TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID,
1047 UTimeZoneNameType type, 1102 UTimeZoneNameType type,
1048 UnicodeString& name) const { 1103 UnicodeString& name) const {
1049 name.setToBogus(); // cleanup result. 1104 name.setToBogus(); // cleanup result.
1050 if (mzID.isEmpty()) { 1105 if (mzID.isEmpty()) {
1051 return name; 1106 return name;
1052 } 1107 }
1053 1108
1054 ZNames *znames = NULL; 1109 ZNames *znames = NULL;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 cacheVal = znames; 1218 cacheVal = znames;
1164 } 1219 }
1165 // Use the persistent ID as the resource key, so we can 1220 // Use the persistent ID as the resource key, so we can
1166 // avoid duplications. 1221 // avoid duplications.
1167 const UChar* newKey = ZoneMeta::findMetaZoneID(mzID); 1222 const UChar* newKey = ZoneMeta::findMetaZoneID(mzID);
1168 if (newKey != NULL) { 1223 if (newKey != NULL) {
1169 uhash_put(fMZNamesMap, (void *)newKey, cacheVal, &status); 1224 uhash_put(fMZNamesMap, (void *)newKey, cacheVal, &status);
1170 if (U_FAILURE(status)) { 1225 if (U_FAILURE(status)) {
1171 if (znames != NULL) { 1226 if (znames != NULL) {
1172 delete znames; 1227 delete znames;
1228 znames = NULL;
1173 } 1229 }
1174 } else if (znames != NULL) { 1230 } else if (znames != NULL) {
1175 // put the name info into the trie 1231 // put the name info into the trie
1176 for (int32_t i = 0; ALL_NAME_TYPES[i] != UTZNM_UNKNOWN; i++) { 1232 for (int32_t i = 0; ALL_NAME_TYPES[i] != UTZNM_UNKNOWN; i++) {
1177 const UChar* name = znames->getName(ALL_NAME_TYPES[i]); 1233 const UChar* name = znames->getName(ALL_NAME_TYPES[i]);
1178 if (name != NULL) { 1234 if (name != NULL) {
1179 ZNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(ZN ameInfo)); 1235 ZNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(ZN ameInfo));
1180 if (nameinfo != NULL) { 1236 if (nameinfo != NULL) {
1181 nameinfo->type = ALL_NAME_TYPES[i]; 1237 nameinfo->type = ALL_NAME_TYPES[i];
1182 nameinfo->tzID = NULL; 1238 nameinfo->tzID = NULL;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 cacheVal = tznames; 1296 cacheVal = tznames;
1241 } 1297 }
1242 // Use the persistent ID as the resource key, so we can 1298 // Use the persistent ID as the resource key, so we can
1243 // avoid duplications. 1299 // avoid duplications.
1244 const UChar* newKey = ZoneMeta::findTimeZoneID(tzID); 1300 const UChar* newKey = ZoneMeta::findTimeZoneID(tzID);
1245 if (newKey != NULL) { 1301 if (newKey != NULL) {
1246 uhash_put(fTZNamesMap, (void *)newKey, cacheVal, &status); 1302 uhash_put(fTZNamesMap, (void *)newKey, cacheVal, &status);
1247 if (U_FAILURE(status)) { 1303 if (U_FAILURE(status)) {
1248 if (tznames != NULL) { 1304 if (tznames != NULL) {
1249 delete tznames; 1305 delete tznames;
1306 tznames = NULL;
1250 } 1307 }
1251 } else if (tznames != NULL) { 1308 } else if (tznames != NULL) {
1252 // put the name info into the trie 1309 // put the name info into the trie
1253 for (int32_t i = 0; ALL_NAME_TYPES[i] != UTZNM_UNKNOWN; i++) { 1310 for (int32_t i = 0; ALL_NAME_TYPES[i] != UTZNM_UNKNOWN; i++) {
1254 const UChar* name = tznames->getName(ALL_NAME_TYPES[i]); 1311 const UChar* name = tznames->getName(ALL_NAME_TYPES[i]);
1255 if (name != NULL) { 1312 if (name != NULL) {
1256 ZNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(ZN ameInfo)); 1313 ZNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(ZN ameInfo));
1257 if (nameinfo != NULL) { 1314 if (nameinfo != NULL) {
1258 nameinfo->type = ALL_NAME_TYPES[i]; 1315 nameinfo->type = ALL_NAME_TYPES[i];
1259 nameinfo->tzID = newKey; 1316 nameinfo->tzID = newKey;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 if (sep > 0 && sep + 1 < tzID.length()) { 1421 if (sep > 0 && sep + 1 < tzID.length()) {
1365 name.setTo(tzID, sep + 1); 1422 name.setTo(tzID, sep + 1);
1366 name.findAndReplace(UnicodeString((UChar)0x5f /* _ */), 1423 name.findAndReplace(UnicodeString((UChar)0x5f /* _ */),
1367 UnicodeString((UChar)0x20 /* space */)); 1424 UnicodeString((UChar)0x20 /* space */));
1368 } else { 1425 } else {
1369 name.setToBogus(); 1426 name.setToBogus();
1370 } 1427 }
1371 return name; 1428 return name;
1372 } 1429 }
1373 1430
1431 // ---------------------------------------------------
1432 // TZDBTimeZoneNames and its supporting classes
1433 //
1434 // TZDBTimeZoneNames is an implementation class of
1435 // TimeZoneNames holding the IANA tz database abbreviations.
1436 // ---------------------------------------------------
1437
1438 class TZDBNames : public UMemory {
1439 public:
1440 virtual ~TZDBNames();
1441
1442 static TZDBNames* createInstance(UResourceBundle* rb, const char* key);
1443 const UChar* getName(UTimeZoneNameType type) const;
1444 const char** getParseRegions(int32_t& numRegions) const;
1445
1446 protected:
1447 TZDBNames(const UChar** names, char** regions, int32_t numRegions);
1448
1449 private:
1450 const UChar** fNames;
1451 char** fRegions;
1452 int32_t fNumRegions;
1453 };
1454
1455 TZDBNames::TZDBNames(const UChar** names, char** regions, int32_t numRegions)
1456 : fNames(names),
1457 fRegions(regions),
1458 fNumRegions(numRegions) {
1459 }
1460
1461 TZDBNames::~TZDBNames() {
1462 if (fNames != NULL) {
1463 uprv_free(fNames);
1464 }
1465 if (fRegions != NULL) {
1466 char **p = fRegions;
1467 for (int32_t i = 0; i < fNumRegions; p++, i++) {
1468 uprv_free(*p);
1469 }
1470 uprv_free(fRegions);
1471 }
1472 }
1473
1474 TZDBNames*
1475 TZDBNames::createInstance(UResourceBundle* rb, const char* key) {
1476 if (rb == NULL || key == NULL || *key == 0) {
1477 return NULL;
1478 }
1479
1480 UErrorCode status = U_ZERO_ERROR;
1481
1482 const UChar **names = NULL;
1483 char** regions = NULL;
1484 int32_t numRegions = 0;
1485
1486 int32_t len = 0;
1487
1488 UResourceBundle* rbTable = NULL;
1489 rbTable = ures_getByKey(rb, key, rbTable, &status);
1490 if (U_FAILURE(status)) {
1491 return NULL;
1492 }
1493
1494 names = (const UChar **)uprv_malloc(sizeof(const UChar*) * TZDBNAMES_KEYS_SI ZE);
1495 UBool isEmpty = TRUE;
1496 if (names != NULL) {
1497 for (int32_t i = 0; i < TZDBNAMES_KEYS_SIZE; i++) {
1498 status = U_ZERO_ERROR;
1499 const UChar *value = ures_getStringByKey(rbTable, TZDBNAMES_KEYS[i], &len, &status);
1500 if (U_FAILURE(status) || len == 0) {
1501 names[i] = NULL;
1502 } else {
1503 names[i] = value;
1504 isEmpty = FALSE;
1505 }
1506 }
1507 }
1508
1509 if (isEmpty) {
1510 if (names != NULL) {
1511 uprv_free(names);
1512 }
1513 return NULL;
1514 }
1515
1516 UResourceBundle *regionsRes = ures_getByKey(rbTable, "parseRegions", NULL, & status);
1517 UBool regionError = FALSE;
1518 if (U_SUCCESS(status)) {
1519 numRegions = ures_getSize(regionsRes);
1520 if (numRegions > 0) {
1521 regions = (char**)uprv_malloc(sizeof(char*) * numRegions);
1522 if (regions != NULL) {
1523 char **pRegion = regions;
1524 for (int32_t i = 0; i < numRegions; i++, pRegion++) {
1525 *pRegion = NULL;
1526 }
1527 // filling regions
1528 pRegion = regions;
1529 for (int32_t i = 0; i < numRegions; i++, pRegion++) {
1530 status = U_ZERO_ERROR;
1531 const UChar *uregion = ures_getStringByIndex(regionsRes, i, &len, &status);
1532 if (U_FAILURE(status)) {
1533 regionError = TRUE;
1534 break;
1535 }
1536 *pRegion = (char*)uprv_malloc(sizeof(char) * (len + 1));
1537 if (*pRegion == NULL) {
1538 regionError = TRUE;
1539 break;
1540 }
1541 u_UCharsToChars(uregion, *pRegion, len);
1542 (*pRegion)[len] = 0;
1543 }
1544 }
1545 }
1546 }
1547 ures_close(regionsRes);
1548 ures_close(rbTable);
1549
1550 if (regionError) {
1551 if (names != NULL) {
1552 uprv_free(names);
1553 }
1554 if (regions != NULL) {
1555 char **p = regions;
1556 for (int32_t i = 0; i < numRegions; p++, i++) {
1557 uprv_free(p);
1558 }
1559 uprv_free(regions);
1560 }
1561 return NULL;
1562 }
1563
1564 return new TZDBNames(names, regions, numRegions);
1565 }
1566
1567 const UChar*
1568 TZDBNames::getName(UTimeZoneNameType type) const {
1569 if (fNames == NULL) {
1570 return NULL;
1571 }
1572 const UChar *name = NULL;
1573 switch(type) {
1574 case UTZNM_SHORT_STANDARD:
1575 name = fNames[0];
1576 break;
1577 case UTZNM_SHORT_DAYLIGHT:
1578 name = fNames[1];
1579 break;
1580 default:
1581 name = NULL;
1582 }
1583 return name;
1584 }
1585
1586 const char**
1587 TZDBNames::getParseRegions(int32_t& numRegions) const {
1588 if (fRegions == NULL) {
1589 numRegions = 0;
1590 } else {
1591 numRegions = fNumRegions;
1592 }
1593 return (const char**)fRegions;
1594 }
1595
1596 U_CDECL_BEGIN
1597 /**
1598 * TZDBNameInfo stores metazone name information for the IANA abbreviations
1599 * in the trie
1600 */
1601 typedef struct TZDBNameInfo {
1602 const UChar* mzID;
1603 UTimeZoneNameType type;
1604 UBool ambiguousType;
1605 const char** parseRegions;
1606 int32_t nRegions;
1607 } TZDBNameInfo;
1608 U_CDECL_END
1609
1610
1611 class TZDBNameSearchHandler : public TextTrieMapSearchResultHandler {
1612 public:
1613 TZDBNameSearchHandler(uint32_t types, const char* region);
1614 virtual ~TZDBNameSearchHandler();
1615
1616 UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
1617 TimeZoneNames::MatchInfoCollection* getMatches(int32_t& maxMatchLen);
1618
1619 private:
1620 uint32_t fTypes;
1621 int32_t fMaxMatchLen;
1622 TimeZoneNames::MatchInfoCollection* fResults;
1623 const char* fRegion;
1624 };
1625
1626 TZDBNameSearchHandler::TZDBNameSearchHandler(uint32_t types, const char* region)
1627 : fTypes(types), fMaxMatchLen(0), fResults(NULL), fRegion(region) {
1628 }
1629
1630 TZDBNameSearchHandler::~TZDBNameSearchHandler() {
1631 if (fResults != NULL) {
1632 delete fResults;
1633 }
1634 }
1635
1636 UBool
1637 TZDBNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *nod e, UErrorCode &status) {
1638 if (U_FAILURE(status)) {
1639 return FALSE;
1640 }
1641
1642 TZDBNameInfo *match = NULL;
1643 TZDBNameInfo *defaultRegionMatch = NULL;
1644
1645 if (node->hasValues()) {
1646 int32_t valuesCount = node->countValues();
1647 for (int32_t i = 0; i < valuesCount; i++) {
1648 TZDBNameInfo *ninfo = (TZDBNameInfo *)node->getValue(i);
1649 if (ninfo == NULL) {
1650 continue;
1651 }
1652 if ((ninfo->type & fTypes) != 0) {
1653 // Some tz database abbreviations are ambiguous. For example,
1654 // CST means either Central Standard Time or China Standard Time .
1655 // Unlike CLDR time zone display names, this implementation
1656 // does not use unique names. And TimeZoneFormat does not expect
1657 // multiple results returned for the same time zone type.
1658 // For this reason, this implementation resolve one among same
1659 // zone type with a same name at this level.
1660 if (ninfo->parseRegions == NULL) {
1661 // parseRegions == null means this is the default metazone
1662 // mapping for the abbreviation.
1663 if (defaultRegionMatch == NULL) {
1664 match = defaultRegionMatch = ninfo;
1665 }
1666 } else {
1667 UBool matchRegion = FALSE;
1668 // non-default metazone mapping for an abbreviation
1669 // comes with applicable regions. For example, the default
1670 // metazone mapping for "CST" is America_Central,
1671 // but if region is one of CN/MO/TW, "CST" is parsed
1672 // as metazone China (China Standard Time).
1673 for (int32_t i = 0; i < ninfo->nRegions; i++) {
1674 const char *region = ninfo->parseRegions[i];
1675 if (uprv_strcmp(fRegion, region) == 0) {
1676 match = ninfo;
1677 matchRegion = TRUE;
1678 break;
1679 }
1680 }
1681 if (matchRegion) {
1682 break;
1683 }
1684 if (match == NULL) {
1685 match = ninfo;
1686 }
1687 }
1688 }
1689 }
1690
1691 if (match != NULL) {
1692 UTimeZoneNameType ntype = match->type;
1693 // Note: Workaround for duplicated standard/daylight names
1694 // The tz database contains a few zones sharing a
1695 // same name for both standard time and daylight saving
1696 // time. For example, Australia/Sydney observes DST,
1697 // but "EST" is used for both standard and daylight.
1698 // When both SHORT_STANDARD and SHORT_DAYLIGHT are included
1699 // in the find operation, we cannot tell which one was
1700 // actually matched.
1701 // TimeZoneFormat#parse returns a matched name type (standard
1702 // or daylight) and DateFormat implementation uses the info to
1703 // to adjust actual time. To avoid false type information,
1704 // this implementation replaces the name type with SHORT_GENERIC.
1705 if (match->ambiguousType
1706 && (ntype == UTZNM_SHORT_STANDARD || ntype == UTZNM_SHORT_DA YLIGHT)
1707 && (fTypes & UTZNM_SHORT_STANDARD) != 0
1708 && (fTypes & UTZNM_SHORT_DAYLIGHT) != 0) {
1709 ntype = UTZNM_SHORT_GENERIC;
1710 }
1711
1712 if (fResults == NULL) {
1713 fResults = new TimeZoneNames::MatchInfoCollection();
1714 if (fResults == NULL) {
1715 status = U_MEMORY_ALLOCATION_ERROR;
1716 }
1717 }
1718 if (U_SUCCESS(status)) {
1719 U_ASSERT(fResults != NULL);
1720 U_ASSERT(match->mzID != NULL);
1721 fResults->addMetaZone(ntype, matchLength, UnicodeString(match->m zID, -1), status);
1722 if (U_SUCCESS(status) && matchLength > fMaxMatchLen) {
1723 fMaxMatchLen = matchLength;
1724 }
1725 }
1726 }
1727 }
1728 return TRUE;
1729 }
1730
1731 TimeZoneNames::MatchInfoCollection*
1732 TZDBNameSearchHandler::getMatches(int32_t& maxMatchLen) {
1733 // give the ownership to the caller
1734 TimeZoneNames::MatchInfoCollection* results = fResults;
1735 maxMatchLen = fMaxMatchLen;
1736
1737 // reset
1738 fResults = NULL;
1739 fMaxMatchLen = 0;
1740 return results;
1741 }
1742
1743 U_CDECL_BEGIN
1744 /**
1745 * Deleter for TZDBNames
1746 */
1747 static void U_CALLCONV
1748 deleteTZDBNames(void *obj) {
1749 if (obj != EMPTY) {
1750 delete (TZDBNames *)obj;
1751 }
1752 }
1753
1754 static void U_CALLCONV initTZDBNamesMap(UErrorCode &status) {
1755 gTZDBNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &sta tus);
1756 if (U_FAILURE(status)) {
1757 gTZDBNamesMap = NULL;
1758 return;
1759 }
1760 // no key deleters for tzdb name maps
1761 uhash_setValueDeleter(gTZDBNamesMap, deleteTZDBNames);
1762 ucln_i18n_registerCleanup(UCLN_I18N_TZDBTIMEZONENAMES, tzdbTimeZoneNames_cle anup);
1763 }
1764
1765 /**
1766 * Deleter for TZDBNameInfo
1767 */
1768 static void U_CALLCONV
1769 deleteTZDBNameInfo(void *obj) {
1770 if (obj != NULL) {
1771 uprv_free(obj);
1772 }
1773 }
1774
1775 static void U_CALLCONV prepareFind(UErrorCode &status) {
1776 if (U_FAILURE(status)) {
1777 return;
1778 }
1779 gTZDBNamesTrie = new TextTrieMap(TRUE, deleteTZDBNameInfo);
1780 if (gTZDBNamesTrie == NULL) {
1781 status = U_MEMORY_ALLOCATION_ERROR;
1782 return;
1783 }
1784
1785 const UnicodeString *mzID;
1786 StringEnumeration *mzIDs = TimeZoneNamesImpl::_getAvailableMetaZoneIDs(statu s);
1787 if (U_SUCCESS(status)) {
1788 while ((mzID = mzIDs->snext(status)) && U_SUCCESS(status)) {
1789 const TZDBNames *names = TZDBTimeZoneNames::getMetaZoneNames(*mzID, status);
1790 if (names == NULL) {
1791 continue;
1792 }
1793 const UChar *std = names->getName(UTZNM_SHORT_STANDARD);
1794 const UChar *dst = names->getName(UTZNM_SHORT_DAYLIGHT);
1795 if (std == NULL && dst == NULL) {
1796 continue;
1797 }
1798 int32_t numRegions = 0;
1799 const char **parseRegions = names->getParseRegions(numRegions);
1800
1801 // The tz database contains a few zones sharing a
1802 // same name for both standard time and daylight saving
1803 // time. For example, Australia/Sydney observes DST,
1804 // but "EST" is used for both standard and daylight.
1805 // we need to store the information for later processing.
1806 UBool ambiguousType = (std != NULL && dst != NULL && u_strcmp(std, d st) == 0);
1807
1808 const UChar *uMzID = ZoneMeta::findMetaZoneID(*mzID);
1809 if (std != NULL) {
1810 TZDBNameInfo *stdInf = (TZDBNameInfo *)uprv_malloc(sizeof(TZDBNa meInfo));
1811 if (stdInf == NULL) {
1812 status = U_MEMORY_ALLOCATION_ERROR;
1813 break;
1814 }
1815 stdInf->mzID = uMzID;
1816 stdInf->type = UTZNM_SHORT_STANDARD;
1817 stdInf->ambiguousType = ambiguousType;
1818 stdInf->parseRegions = parseRegions;
1819 stdInf->nRegions = numRegions;
1820 gTZDBNamesTrie->put(std, stdInf, status);
1821 }
1822 if (U_SUCCESS(status) && dst != NULL) {
1823 TZDBNameInfo *dstInf = (TZDBNameInfo *)uprv_malloc(sizeof(TZDBNa meInfo));
1824 if (dstInf == NULL) {
1825 status = U_MEMORY_ALLOCATION_ERROR;
1826 break;
1827 }
1828 dstInf->mzID = uMzID;
1829 dstInf->type = UTZNM_SHORT_DAYLIGHT;
1830 dstInf->ambiguousType = ambiguousType;
1831 dstInf->parseRegions = parseRegions;
1832 dstInf->nRegions = numRegions;
1833 gTZDBNamesTrie->put(dst, dstInf, status);
1834 }
1835 }
1836 }
1837 delete mzIDs;
1838
1839 if (U_FAILURE(status)) {
1840 delete gTZDBNamesTrie;
1841 gTZDBNamesTrie = NULL;
1842 return;
1843 }
1844
1845 ucln_i18n_registerCleanup(UCLN_I18N_TZDBTIMEZONENAMES, tzdbTimeZoneNames_cle anup);
1846 }
1847
1848 U_CDECL_END
1849
1850 TZDBTimeZoneNames::TZDBTimeZoneNames(const Locale& locale)
1851 : fLocale(locale) {
1852 UBool useWorld = TRUE;
1853 const char* region = fLocale.getCountry();
1854 int32_t regionLen = uprv_strlen(region);
1855 if (regionLen == 0) {
1856 UErrorCode status = U_ZERO_ERROR;
1857 char loc[ULOC_FULLNAME_CAPACITY];
1858 uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status);
1859 regionLen = uloc_getCountry(loc, fRegion, sizeof(fRegion), &status);
1860 if (U_SUCCESS(status) && regionLen < (int32_t)sizeof(fRegion)) {
1861 useWorld = FALSE;
1862 }
1863 } else if (regionLen < (int32_t)sizeof(fRegion)) {
1864 uprv_strcpy(fRegion, region);
1865 useWorld = FALSE;
1866 }
1867 if (useWorld) {
1868 uprv_strcpy(fRegion, "001");
1869 }
1870 }
1871
1872 TZDBTimeZoneNames::~TZDBTimeZoneNames() {
1873 }
1874
1875 UBool
1876 TZDBTimeZoneNames::operator==(const TimeZoneNames& other) const {
1877 if (this == &other) {
1878 return TRUE;
1879 }
1880 // No implementation for now
1881 return FALSE;
1882 }
1883
1884 TimeZoneNames*
1885 TZDBTimeZoneNames::clone() const {
1886 return new TZDBTimeZoneNames(fLocale);
1887 }
1888
1889 StringEnumeration*
1890 TZDBTimeZoneNames::getAvailableMetaZoneIDs(UErrorCode& status) const {
1891 return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
1892 }
1893
1894 StringEnumeration*
1895 TZDBTimeZoneNames::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode & status) const {
1896 return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(tzID, status);
1897 }
1898
1899 UnicodeString&
1900 TZDBTimeZoneNames::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeS tring& mzID) const {
1901 return TimeZoneNamesImpl::_getMetaZoneID(tzID, date, mzID);
1902 }
1903
1904 UnicodeString&
1905 TZDBTimeZoneNames::getReferenceZoneID(const UnicodeString& mzID, const char* reg ion, UnicodeString& tzID) const {
1906 return TimeZoneNamesImpl::_getReferenceZoneID(mzID, region, tzID);
1907 }
1908
1909 UnicodeString&
1910 TZDBTimeZoneNames::getMetaZoneDisplayName(const UnicodeString& mzID,
1911 UTimeZoneNameType type,
1912 UnicodeString& name) const {
1913 name.setToBogus();
1914 if (mzID.isEmpty()) {
1915 return name;
1916 }
1917
1918 UErrorCode status = U_ZERO_ERROR;
1919 const TZDBNames *tzdbNames = TZDBTimeZoneNames::getMetaZoneNames(mzID, statu s);
1920 if (U_SUCCESS(status)) {
1921 const UChar *s = tzdbNames->getName(type);
1922 if (s != NULL) {
1923 name.setTo(TRUE, s, -1);
1924 }
1925 }
1926
1927 return name;
1928 }
1929
1930 UnicodeString&
1931 TZDBTimeZoneNames::getTimeZoneDisplayName(const UnicodeString& /* tzID */, UTime ZoneNameType /* type */, UnicodeString& name) const {
1932 // No abbreviations associated a zone directly for now.
1933 name.setToBogus();
1934 return name;
1935 }
1936
1937 TZDBTimeZoneNames::MatchInfoCollection*
1938 TZDBTimeZoneNames::find(const UnicodeString& text, int32_t start, uint32_t types , UErrorCode& status) const {
1939 umtx_initOnce(gTZDBNamesTrieInitOnce, &prepareFind, status);
1940 if (U_FAILURE(status)) {
1941 return NULL;
1942 }
1943
1944 TZDBNameSearchHandler handler(types, fRegion);
1945 gTZDBNamesTrie->search(text, start, (TextTrieMapSearchResultHandler *)&handl er, status);
1946 if (U_FAILURE(status)) {
1947 return NULL;
1948 }
1949 int32_t maxLen = 0;
1950 return handler.getMatches(maxLen);
1951 }
1952
1953 const TZDBNames*
1954 TZDBTimeZoneNames::getMetaZoneNames(const UnicodeString& mzID, UErrorCode& statu s) {
1955 umtx_initOnce(gTZDBNamesMapInitOnce, &initTZDBNamesMap, status);
1956 if (U_FAILURE(status)) {
1957 return NULL;
1958 }
1959
1960 TZDBNames* tzdbNames = NULL;
1961
1962 UChar mzIDKey[ZID_KEY_MAX + 1];
1963 mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
1964 U_ASSERT(status == U_ZERO_ERROR); // already checked length above
1965 mzIDKey[mzID.length()] = 0;
1966
1967 umtx_lock(&gTZDBNamesMapLock);
1968 {
1969 void *cacheVal = uhash_get(gTZDBNamesMap, mzIDKey);
1970 if (cacheVal == NULL) {
1971 UResourceBundle *zoneStringsRes = ures_openDirect(U_ICUDATA_ZONE, "t zdbNames", &status);
1972 zoneStringsRes = ures_getByKey(zoneStringsRes, gZoneStrings, zoneStr ingsRes, &status);
1973 if (U_SUCCESS(status)) {
1974 char key[ZID_KEY_MAX + 1];
1975 mergeTimeZoneKey(mzID, key);
1976 tzdbNames = TZDBNames::createInstance(zoneStringsRes, key);
1977
1978 if (tzdbNames == NULL) {
1979 cacheVal = (void *)EMPTY;
1980 } else {
1981 cacheVal = tzdbNames;
1982 }
1983 // Use the persistent ID as the resource key, so we can
1984 // avoid duplications.
1985 const UChar* newKey = ZoneMeta::findMetaZoneID(mzID);
1986 if (newKey != NULL) {
1987 uhash_put(gTZDBNamesMap, (void *)newKey, cacheVal, &status);
1988 if (U_FAILURE(status)) {
1989 if (tzdbNames != NULL) {
1990 delete tzdbNames;
1991 tzdbNames = NULL;
1992 }
1993 }
1994 } else {
1995 // Should never happen with a valid input
1996 if (tzdbNames != NULL) {
1997 // It's not possible that we get a valid tzdbNames with unknown ID.
1998 // But just in case..
1999 delete tzdbNames;
2000 tzdbNames = NULL;
2001 }
2002 }
2003 }
2004 ures_close(zoneStringsRes);
2005 } else if (cacheVal != EMPTY) {
2006 tzdbNames = (TZDBNames *)cacheVal;
2007 }
2008 }
2009 umtx_unlock(&gTZDBNamesMapLock);
2010
2011 return tzdbNames;
2012 }
2013
1374 U_NAMESPACE_END 2014 U_NAMESPACE_END
1375 2015
1376 2016
1377 #endif /* #if !UCONFIG_NO_FORMATTING */ 2017 #endif /* #if !UCONFIG_NO_FORMATTING */
1378 2018
1379 //eof 2019 //eof
OLDNEW
« no previous file with comments | « source/i18n/tznames_impl.h ('k') | source/i18n/ucln_in.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698