1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* Copyright (C) 2007-2010, International Business Machines Corporation and * 4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* others. All Rights Reserved. * 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h" 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "zonemeta.h" 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/timezone.h" 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h" 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h" 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h" 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uvector.h" 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h" 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h" 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h" 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_in.h" 2450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uassert.h" 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UMTX gZoneMetaLock = NULL; 2750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 2850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Metazone mapping table 29b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UHashtable *gOlsonToMeta = NULL; 30b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool gOlsonToMetaInitialized = FALSE; 31b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 3250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Country info vectors 3350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic U_NAMESPACE_QUALIFIER UVector *gSingleZoneCountries = NULL; 3450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic U_NAMESPACE_QUALIFIER UVector *gMultiZonesCountries = NULL; 3550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UBool gCountryInfoVectorsInitialized = FALSE; 36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 3750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CDECL_BEGIN 38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Cleanup callback func 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV zoneMeta_cleanup(void) 44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru umtx_destroy(&gZoneMetaLock); 46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (gOlsonToMeta != NULL) { 48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uhash_close(gOlsonToMeta); 49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru gOlsonToMeta = NULL; 50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru gOlsonToMetaInitialized = FALSE; 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 5350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gSingleZoneCountries; 5450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gMultiZonesCountries; 5550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gCountryInfoVectorsInitialized = FALSE; 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Deleter for UChar* string 62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void U_CALLCONV 64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerudeleteUCharString(void *obj) { 65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UChar *entry = (UChar*)obj; 66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(entry); 67b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 69b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/** 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Deleter for UVector 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerudeleteUVector(void *obj) { 74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete (U_NAMESPACE_QUALIFIER UVector*) obj; 75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Deleter for OlsonToMetaMappingEntry 79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerudeleteOlsonToMetaMappingEntry(void *obj) { 82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_NAMESPACE_QUALIFIER OlsonToMetaMappingEntry *entry = (U_NAMESPACE_QUALIFIER OlsonToMetaMappingEntry*)obj; 83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(entry); 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZID_KEY_MAX 128 91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 9250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gMetaZones[] = "metaZones"; 9350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gMetazoneInfo[] = "metazoneInfo"; 94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char gMapTimezonesTag[] = "mapTimezones"; 95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 9627f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gTimeZoneTypes[] = "timezoneTypes"; 9750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gTypeAliasTag[] = "typeAlias"; 9827f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gTypeMapTag[] = "typeMap"; 9950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gTimezoneTag[] = "timezone"; 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 10150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gWorldTag[] = "001"; 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gWorld[] = {0x30, 0x30, 0x31, 0x00}; // "001" 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 10550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar gDefaultFrom[] = {0x31, 0x39, 0x37, 0x30, 0x2D, 0x30, 0x31, 0x2D, 0x30, 0x31, 10650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x00}; // "1970-01-01 00:00" 10750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar gDefaultTo[] = {0x39, 0x39, 0x39, 0x39, 0x2D, 0x31, 0x32, 0x2D, 0x33, 0x31, 10850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, 0x32, 0x33, 0x3A, 0x35, 0x39, 0x00}; // "9999-12-31 23:59" 10950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ASCII_DIGIT(c) (((c)>=0x30 && (c)<=0x39) ? (c)-0x30 : -1) 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Convert a date string used by metazone mappings to UDate. 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The format used by CLDR metazone mapping is "yyyy-MM-dd HH:mm". 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 116c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic UDate 117c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruparseDate (const UChar *text, UErrorCode &status) { 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t len = u_strlen(text); 122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len != 16 && len != 10) { 123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It must be yyyy-MM-dd HH:mm (length 16) or yyyy-MM-dd (length 10) 124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year = 0, month = 0, day = 0, hour = 0, min = 0, n; 129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx; 130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "yyyy" (0 - 3) 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 0; idx <= 3 && U_SUCCESS(status); idx++) { 133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year = 10*year + n; 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "MM" (5 - 6) 141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 5; idx <= 6 && U_SUCCESS(status); idx++) { 142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru month = 10*month + n; 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "dd" (8 - 9) 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 8; idx <= 9 && U_SUCCESS(status); idx++) { 151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru day = 10*day + n; 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len == 16) { 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "HH" (11 - 12) 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 11; idx <= 12 && U_SUCCESS(status); idx++) { 161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru hour = 10*hour + n; 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "mm" (14 - 15) 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 14; idx <= 15 && U_SUCCESS(status); idx++) { 170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru min = 10*min + n; 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(status)) { 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate date = Grego::fieldsToDay(year, month - 1, day) * U_MILLIS_PER_DAY 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru + hour * U_MILLIS_PER_HOUR + min * U_MILLIS_PER_MINUTE; 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return date; 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 18750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 18850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getCanonicalSystemID(const UnicodeString &tzid, UnicodeString &systemID, UErrorCode& status) { 18927f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t len = tzid.length(); 19027f654740f2a26ad62a5c155af9199af9e69b889claireho if ( len >= ZID_KEY_MAX ) { 19127f654740f2a26ad62a5c155af9199af9e69b889claireho status = U_ILLEGAL_ARGUMENT_ERROR; 19227f654740f2a26ad62a5c155af9199af9e69b889claireho systemID.remove(); 19327f654740f2a26ad62a5c155af9199af9e69b889claireho return systemID; 19427f654740f2a26ad62a5c155af9199af9e69b889claireho } 195c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 19627f654740f2a26ad62a5c155af9199af9e69b889claireho char id[ZID_KEY_MAX]; 19727f654740f2a26ad62a5c155af9199af9e69b889claireho const UChar* idChars = tzid.getBuffer(); 19827f654740f2a26ad62a5c155af9199af9e69b889claireho 19927f654740f2a26ad62a5c155af9199af9e69b889claireho u_UCharsToChars(idChars,id,len); 20027f654740f2a26ad62a5c155af9199af9e69b889claireho id[len] = (char) 0; // Make sure it is null terminated. 20127f654740f2a26ad62a5c155af9199af9e69b889claireho 20227f654740f2a26ad62a5c155af9199af9e69b889claireho // replace '/' with ':' 20327f654740f2a26ad62a5c155af9199af9e69b889claireho char *p = id; 20427f654740f2a26ad62a5c155af9199af9e69b889claireho while (*p++) { 20527f654740f2a26ad62a5c155af9199af9e69b889claireho if (*p == '/') { 20627f654740f2a26ad62a5c155af9199af9e69b889claireho *p = ':'; 20750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 20927f654740f2a26ad62a5c155af9199af9e69b889claireho 21027f654740f2a26ad62a5c155af9199af9e69b889claireho 21127f654740f2a26ad62a5c155af9199af9e69b889claireho UErrorCode tmpStatus = U_ZERO_ERROR; 21227f654740f2a26ad62a5c155af9199af9e69b889claireho UResourceBundle *top = ures_openDirect(NULL, gTimeZoneTypes, &tmpStatus); 21327f654740f2a26ad62a5c155af9199af9e69b889claireho UResourceBundle *rb = ures_getByKey(top, gTypeMapTag, NULL, &tmpStatus); 21427f654740f2a26ad62a5c155af9199af9e69b889claireho ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus); 21527f654740f2a26ad62a5c155af9199af9e69b889claireho ures_getByKey(rb, id, rb, &tmpStatus); 21627f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_SUCCESS(tmpStatus)) { 21727f654740f2a26ad62a5c155af9199af9e69b889claireho // direct map found 21827f654740f2a26ad62a5c155af9199af9e69b889claireho systemID.setTo(tzid); 21927f654740f2a26ad62a5c155af9199af9e69b889claireho ures_close(rb); 22027f654740f2a26ad62a5c155af9199af9e69b889claireho ures_close(top); 22127f654740f2a26ad62a5c155af9199af9e69b889claireho return systemID; 22227f654740f2a26ad62a5c155af9199af9e69b889claireho } 22327f654740f2a26ad62a5c155af9199af9e69b889claireho 22427f654740f2a26ad62a5c155af9199af9e69b889claireho // If a map element not found, then look for an alias 22527f654740f2a26ad62a5c155af9199af9e69b889claireho tmpStatus = U_ZERO_ERROR; 22627f654740f2a26ad62a5c155af9199af9e69b889claireho ures_getByKey(top, gTypeAliasTag, rb, &tmpStatus); 22727f654740f2a26ad62a5c155af9199af9e69b889claireho ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus); 22827f654740f2a26ad62a5c155af9199af9e69b889claireho const UChar *alias = ures_getStringByKey(rb,id,NULL,&tmpStatus); 22927f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_SUCCESS(tmpStatus)) { 23027f654740f2a26ad62a5c155af9199af9e69b889claireho // alias found 23127f654740f2a26ad62a5c155af9199af9e69b889claireho ures_close(rb); 23227f654740f2a26ad62a5c155af9199af9e69b889claireho ures_close(top); 23327f654740f2a26ad62a5c155af9199af9e69b889claireho systemID.setTo(alias); 23427f654740f2a26ad62a5c155af9199af9e69b889claireho return systemID; 23527f654740f2a26ad62a5c155af9199af9e69b889claireho } 23627f654740f2a26ad62a5c155af9199af9e69b889claireho 23727f654740f2a26ad62a5c155af9199af9e69b889claireho // Dereference the input ID using the tz data 23827f654740f2a26ad62a5c155af9199af9e69b889claireho const UChar *derefer = TimeZone::dereferOlsonLink(tzid); 23927f654740f2a26ad62a5c155af9199af9e69b889claireho if (derefer == NULL) { 24050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho systemID.remove(); 24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ILLEGAL_ARGUMENT_ERROR; 24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 24327f654740f2a26ad62a5c155af9199af9e69b889claireho 24427f654740f2a26ad62a5c155af9199af9e69b889claireho len = u_strlen(derefer); 24527f654740f2a26ad62a5c155af9199af9e69b889claireho u_UCharsToChars(derefer,id,len); 24627f654740f2a26ad62a5c155af9199af9e69b889claireho id[len] = (char) 0; // Make sure it is null terminated. 24727f654740f2a26ad62a5c155af9199af9e69b889claireho 24827f654740f2a26ad62a5c155af9199af9e69b889claireho // replace '/' with ':' 24927f654740f2a26ad62a5c155af9199af9e69b889claireho char *p = id; 25027f654740f2a26ad62a5c155af9199af9e69b889claireho while (*p++) { 25127f654740f2a26ad62a5c155af9199af9e69b889claireho if (*p == '/') { 25227f654740f2a26ad62a5c155af9199af9e69b889claireho *p = ':'; 25327f654740f2a26ad62a5c155af9199af9e69b889claireho } 25427f654740f2a26ad62a5c155af9199af9e69b889claireho } 25527f654740f2a26ad62a5c155af9199af9e69b889claireho 25627f654740f2a26ad62a5c155af9199af9e69b889claireho // If a dereference turned something up then look for an alias. 25727f654740f2a26ad62a5c155af9199af9e69b889claireho // rb still points to the alias table, so we don't have to go looking 25827f654740f2a26ad62a5c155af9199af9e69b889claireho // for it. 25927f654740f2a26ad62a5c155af9199af9e69b889claireho tmpStatus = U_ZERO_ERROR; 26027f654740f2a26ad62a5c155af9199af9e69b889claireho const UChar *alias = ures_getStringByKey(rb,id,NULL,&tmpStatus); 26127f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_SUCCESS(tmpStatus)) { 26227f654740f2a26ad62a5c155af9199af9e69b889claireho // alias found 26327f654740f2a26ad62a5c155af9199af9e69b889claireho systemID.setTo(alias); 26427f654740f2a26ad62a5c155af9199af9e69b889claireho } else { 26527f654740f2a26ad62a5c155af9199af9e69b889claireho systemID.setTo(derefer); 26627f654740f2a26ad62a5c155af9199af9e69b889claireho } 267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 26927f654740f2a26ad62a5c155af9199af9e69b889claireho ures_close(rb); 27027f654740f2a26ad62a5c155af9199af9e69b889claireho ures_close(top); 27127f654740f2a26ad62a5c155af9199af9e69b889claireho return systemID; 27250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 27450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 27550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &canonicalCountry) { 27650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *region = TimeZone::getRegion(tzid); 27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (u_strcmp(gWorld, region) != 0) { 27850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho canonicalCountry.setTo(region, -1); 27950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho canonicalCountry.remove(); 28150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 28250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return canonicalCountry; 28350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 28550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 28650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getSingleCountry(const UnicodeString &tzid, UnicodeString &country) { 28750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Get canonical country for the zone 28850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *region = TimeZone::getRegion(tzid); 28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (u_strcmp(gWorld, region) == 0) { 29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // special case - "001" 29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho country.remove(); 29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Checking the cached results 29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool initialized; 29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UMTX_CHECK(&gZoneMetaLock, gCountryInfoVectorsInitialized, initialized); 29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!initialized) { 30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Create empty vectors 30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_lock(&gZoneMetaLock); 30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!gCountryInfoVectorsInitialized) { 30450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // No deleters for these UVectors, it's a reference to a resource bundle string. 30550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status); 30650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gSingleZoneCountries == NULL) { 30750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status); 31050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gMultiZonesCountries == NULL) { 31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 31450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 31550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gCountryInfoVectorsInitialized = TRUE; 31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gSingleZoneCountries; 31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gMultiZonesCountries; 31950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_unlock(&gZoneMetaLock); 323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho country.remove(); 32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 32850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Check if it was already cached 33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool cached = FALSE; 33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool multiZones = FALSE; 33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_lock(&gZoneMetaLock); 33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho multiZones = cached = gMultiZonesCountries->contains((void*)region); 33650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!multiZones) { 33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cached = gSingleZoneCountries->contains((void*)region); 338c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_unlock(&gZoneMetaLock); 341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!cached) { 34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // We need to go through all zones associated with the region. 34450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // This is relatively heavy operation. 34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(u_strlen(region) == 2); 34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char buf[] = {0, 0, 0}; 34950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_UCharsToChars(region, buf, 2); 35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho StringEnumeration *ids = TimeZone::createEnumeration(buf); 35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t idsLen = ids->count(status); 35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status) && idsLen > 1) { 35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // multiple zones are available for the region 35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString canonical, tmp; 35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UnicodeString *id = ids->snext(status); 35750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho getCanonicalSystemID(*id, canonical, status); 35850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 35950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // check if there are any other canonical zone in the group 36027f654740f2a26ad62a5c155af9199af9e69b889claireho while ((id = ids->snext(status))!=NULL) { 36150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho getCanonicalSystemID(*id, tmp, status); 36250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 36550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (canonical != tmp) { 36650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // another canonical zone was found 36750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho multiZones = TRUE; 36850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 36950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 371c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // no single country by default for any error cases 37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho multiZones = TRUE; 37650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete ids; 37850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 37950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Cache the result 38050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_lock(&gZoneMetaLock); 38150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 38250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode ec = U_ZERO_ERROR; 38350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (multiZones) { 38450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!gMultiZonesCountries->contains((void*)region)) { 38550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gMultiZonesCountries->addElement((void*)region, ec); 386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } else { 38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!gSingleZoneCountries->contains((void*)region)) { 38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gSingleZoneCountries->addElement((void*)region, ec); 39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 39350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_unlock(&gZoneMetaLock); 394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 39650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (multiZones) { 39750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho country.remove(); 39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho country.setTo(region, -1); 400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 40450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 40550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getMetazoneID(const UnicodeString &tzid, UDate date, UnicodeString &result) { 40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool isSet = FALSE; 40750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UVector *mappings = getMetazoneMappings(tzid); 40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mappings != NULL) { 40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (int32_t i = 0; i < mappings->size(); i++) { 41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho OlsonToMetaMappingEntry *mzm = (OlsonToMetaMappingEntry*)mappings->elementAt(i); 41150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzm->from <= date && mzm->to > date) { 41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result.setTo(mzm->mzid, -1); 41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isSet = TRUE; 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 41850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!isSet) { 41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result.remove(); 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 42450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UVector* U_EXPORT2 42550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getMetazoneMappings(const UnicodeString &tzid) { 426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UChar tzidUChars[ZID_KEY_MAX]; 42850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid.extract(tzidUChars, ZID_KEY_MAX, status); 42950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { 430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool initialized; 43450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UMTX_CHECK(&gZoneMetaLock, gOlsonToMetaInitialized, initialized); 43550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!initialized) { 43650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UHashtable *tmpOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 43850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_setKeyDeleter(tmpOlsonToMeta, deleteUCharString); 44150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_setValueDeleter(tmpOlsonToMeta, deleteUVector); 44250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 44350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_lock(&gZoneMetaLock); 44450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 44550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!gOlsonToMetaInitialized) { 44650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gOlsonToMeta = tmpOlsonToMeta; 44750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tmpOlsonToMeta = NULL; 44850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gOlsonToMetaInitialized = TRUE; 449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_unlock(&gZoneMetaLock); 452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 45350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // OK to call the following multiple times with the same function 45450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 45550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tmpOlsonToMeta != NULL) { 45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_close(tmpOlsonToMeta); 45750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 46050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // get the mapping from cache 46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UVector *result = NULL; 462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_lock(&gZoneMetaLock); 46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); 466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_unlock(&gZoneMetaLock); 468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 46950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result != NULL) { 47050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 47350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // miss the cache - create new one 47450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UVector *tmpResult = createMetazoneMappings(tzid); 47550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tmpResult == NULL) { 47650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // not available 47750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 479c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // put the new one into the cache 481c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru umtx_lock(&gZoneMetaLock); 48250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 48350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // make sure it's already created 48450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); 48550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result == NULL) { 48650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // add the one just created 48750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t tzidLen = tzid.length() + 1; 48850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UChar *key = (UChar*)uprv_malloc(tzidLen * sizeof(UChar)); 48950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (key == NULL) { 49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // memory allocation error.. just return NULL 49150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = NULL; 49250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 49350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid.extract(key, tzidLen, status); 49550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_put(gOlsonToMeta, key, tmpResult, &status); 49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // delete the mapping 49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = NULL; 49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 50050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 50150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = tmpResult; 50250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 50350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 50450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 50550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // another thread already put the one 50650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 50750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_unlock(&gZoneMetaLock); 510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 51150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 512c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru} 513c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 51450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUVector* 51550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::createMetazoneMappings(const UnicodeString &tzid) { 51650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UVector *mzMappings = NULL; 51750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString canonicalID; 52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 52150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, gMetazoneInfo, rb, &status); 52250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TimeZone::getCanonicalID(tzid, canonicalID, status); 523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 52450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 52550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char tzKey[ZID_KEY_MAX]; 52650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho canonicalID.extract(0, canonicalID.length(), tzKey, sizeof(tzKey), US_INV); 52750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 52850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // tzid keys are using ':' as separators 52950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *p = tzKey; 53050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (*p) { 53150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*p == '/') { 53250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p = ':'; 53350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 53450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p++; 535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, tzKey, rb, &status); 538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 54050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *mz = NULL; 54150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (ures_hasNext(rb)) { 54250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz = ures_getNextResource(rb, mz, &status); 543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 54450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_name = ures_getStringByIndex(mz, 0, NULL, &status); 54550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_from = gDefaultFrom; 54650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_to = gDefaultTo; 547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ures_getSize(mz) == 3) { 54950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz_from = ures_getStringByIndex(mz, 1, NULL, &status); 55050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz_to = ures_getStringByIndex(mz, 2, NULL, &status); 55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 55250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 55350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(U_FAILURE(status)){ 55450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 55550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 55650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 55750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // We do not want to use SimpleDateformat to parse boundary dates, 55850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // because this code could be triggered by the initialization code 55950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // used by SimpleDateFormat. 56050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UDate from = parseDate(mz_from, status); 56150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UDate to = parseDate(mz_to, status); 56250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 56350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 56450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 56650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 56750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho OlsonToMetaMappingEntry *entry = (OlsonToMetaMappingEntry*)uprv_malloc(sizeof(OlsonToMetaMappingEntry)); 56850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (entry == NULL) { 56950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 57250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->mzid = mz_name; 57350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->from = from; 57450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->to = to; 57550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 57650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzMappings == NULL) { 57750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status); 57850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 57950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete mzMappings; 58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho deleteOlsonToMetaMappingEntry(entry); 58150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(entry); 58250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 58350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 58450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 58650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings->addElement(entry, status); 58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 58850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 59050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 59150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(mz); 59250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 59350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzMappings != NULL) { 59450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete mzMappings; 59550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings = NULL; 59650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 60050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(rb); 60150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return mzMappings; 602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 604c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString& U_EXPORT2 60550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getZoneIdByMetazone(const UnicodeString &mzid, const UnicodeString ®ion, UnicodeString &result) { 60650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *tzid = NULL; 60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t tzidLen = 0; 60950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char keyBuf[ZID_KEY_MAX + 1]; 61050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t keyLen = 0; 61150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 61250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzid.length() >= ZID_KEY_MAX) { 613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.remove(); 61450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 61750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keyLen = mzid.extract(0, mzid.length(), keyBuf, ZID_KEY_MAX, US_INV); 618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 61950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 62050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, gMapTimezonesTag, rb, &status); 62150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, keyBuf, rb, &status); 62250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 62350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 62450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // check region mapping 62550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (region.length() == 2 || region.length() == 3) { 62650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho region.extract(0, region.length(), keyBuf, ZID_KEY_MAX, US_INV); 62750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid = ures_getStringByKey(rb, keyBuf, &tzidLen, &status); 62850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status == U_MISSING_RESOURCE_ERROR) { 62950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 63250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status) && tzid == NULL) { 63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // try "001" 63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid = ures_getStringByKey(rb, gWorldTag, &tzidLen, &status); 63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(rb); 63850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 63950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tzid == NULL) { 640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.remove(); 64150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 64250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result.setTo(tzid, tzidLen); 643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 64450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END 649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 651