OLD | NEW |
1 /* | 1 /* |
2 ******************************************************************************* | 2 ******************************************************************************* |
3 * Copyright (C) 2013, International Business Machines Corporation and | 3 * Copyright (C) 2014, International Business Machines Corporation and |
4 * others. All Rights Reserved. | 4 * others. All Rights Reserved. |
5 ******************************************************************************* | 5 ******************************************************************************* |
6 * | 6 * |
7 * | 7 * |
8 * File REGION.CPP | 8 * File REGION.CPP |
9 * | 9 * |
10 * Modification History:* | 10 * Modification History:* |
11 * Date Name Description | 11 * Date Name Description |
12 * 01/15/13 Emmons Original Port from ICU4J | 12 * 01/15/13 Emmons Original Port from ICU4J |
13 ******************************************************************************** | 13 ******************************************************************************** |
14 */ | 14 */ |
15 | 15 |
16 /** | 16 /** |
17 * \file | 17 * \file |
18 * \brief C++ API: Region classes (territory containment) | 18 * \brief C++ API: Region classes (territory containment) |
19 */ | 19 */ |
20 | 20 |
21 #include "unicode/region.h" | 21 #include "unicode/region.h" |
22 #include "unicode/utypes.h" | 22 #include "unicode/utypes.h" |
23 #include "unicode/uobject.h" | 23 #include "unicode/uobject.h" |
24 #include "unicode/unistr.h" | 24 #include "unicode/unistr.h" |
25 #include "unicode/ures.h" | 25 #include "unicode/ures.h" |
26 #include "unicode/decimfmt.h" | 26 #include "unicode/decimfmt.h" |
27 #include "ucln_in.h" | 27 #include "ucln_in.h" |
28 #include "cstring.h" | 28 #include "cstring.h" |
| 29 #include "mutex.h" |
29 #include "uhash.h" | 30 #include "uhash.h" |
30 #include "umutex.h" | 31 #include "umutex.h" |
31 #include "uresimp.h" | 32 #include "uresimp.h" |
32 #include "region_impl.h" | 33 #include "region_impl.h" |
33 | 34 |
34 #if !UCONFIG_NO_FORMATTING | 35 #if !UCONFIG_NO_FORMATTING |
35 | 36 |
36 | 37 |
37 U_CDECL_BEGIN | 38 U_CDECL_BEGIN |
38 | 39 |
39 static void U_CALLCONV | 40 static void U_CALLCONV |
40 deleteRegion(void *obj) { | 41 deleteRegion(void *obj) { |
41 delete (icu::Region *)obj; | 42 delete (icu::Region *)obj; |
42 } | 43 } |
43 | 44 |
44 /** | 45 /** |
45 * Cleanup callback func | 46 * Cleanup callback func |
46 */ | 47 */ |
47 static UBool U_CALLCONV region_cleanup(void) | 48 static UBool U_CALLCONV region_cleanup(void) |
48 { | 49 { |
49 icu::Region::cleanupRegionData(); | 50 icu::Region::cleanupRegionData(); |
50 | 51 |
51 return TRUE; | 52 return TRUE; |
52 } | 53 } |
53 | 54 |
54 U_CDECL_END | 55 U_CDECL_END |
55 | 56 |
56 U_NAMESPACE_BEGIN | 57 U_NAMESPACE_BEGIN |
57 | 58 |
58 static UMutex gRegionDataLock = U_MUTEX_INITIALIZER; | 59 static UInitOnce gRegionDataInitOnce = U_INITONCE_INITIALIZER; |
59 static UBool regionDataIsLoaded = false; | |
60 static UVector* availableRegions[URGN_LIMIT]; | 60 static UVector* availableRegions[URGN_LIMIT]; |
61 | 61 |
62 static UHashtable *regionAliases; | 62 static UHashtable *regionAliases; |
63 static UHashtable *regionIDMap; | 63 static UHashtable *regionIDMap; |
64 static UHashtable *numericCodeMap; | 64 static UHashtable *numericCodeMap; |
65 | 65 |
66 static const UChar UNKNOWN_REGION_ID [] = { 0x5A, 0x5A, 0 }; /* "ZZ" */ | 66 static const UChar UNKNOWN_REGION_ID [] = { 0x5A, 0x5A, 0 }; /* "ZZ" */ |
67 static const UChar OUTLYING_OCEANIA_REGION_ID [] = { 0x51, 0x4F, 0 }; /* "QO" *
/ | 67 static const UChar OUTLYING_OCEANIA_REGION_ID [] = { 0x51, 0x4F, 0 }; /* "QO" *
/ |
68 static const UChar WORLD_ID [] = { 0x30, 0x30, 0x31, 0 }; /* "001" */ | 68 static const UChar WORLD_ID [] = { 0x30, 0x30, 0x31, 0 }; /* "001" */ |
69 | 69 |
70 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration) | 70 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration) |
71 | 71 |
72 /* | 72 /* |
73 * Initializes the region data from the ICU resource bundles. The region data | 73 * Initializes the region data from the ICU resource bundles. The region data |
74 * contains the basic relationships such as which regions are known, what the nu
meric | 74 * contains the basic relationships such as which regions are known, what the nu
meric |
75 * codes are, any known aliases, and the territory containment data. | 75 * codes are, any known aliases, and the territory containment data. |
76 * | 76 * |
77 * If the region data has already loaded, then this method simply returns withou
t doing | 77 * If the region data has already loaded, then this method simply returns withou
t doing |
78 * anything meaningful. | 78 * anything meaningful. |
79 */ | 79 */ |
80 void Region::loadRegionData() { | 80 void Region::loadRegionData(UErrorCode &status) { |
81 | 81 LocalPointer<DecimalFormat> df(new DecimalFormat(status)); |
82 if (regionDataIsLoaded) { | 82 if (U_FAILURE(status)) { |
83 return; | 83 return; |
84 } | 84 } |
85 | 85 if (df == NULL) { |
86 umtx_lock(&gRegionDataLock); | 86 status = U_MEMORY_ALLOCATION_ERROR; |
87 | |
88 if (regionDataIsLoaded) { // In case another thread gets to it before we do.
.. | |
89 umtx_unlock(&gRegionDataLock); | |
90 return; | |
91 } | |
92 | |
93 | |
94 UErrorCode status = U_ZERO_ERROR; | |
95 | |
96 UResourceBundle* regionCodes = NULL; | |
97 UResourceBundle* territoryAlias = NULL; | |
98 UResourceBundle* codeMappings = NULL; | |
99 UResourceBundle* worldContainment = NULL; | |
100 UResourceBundle* territoryContainment = NULL; | |
101 UResourceBundle* groupingContainment = NULL; | |
102 | |
103 DecimalFormat *df = new DecimalFormat(status); | |
104 if (U_FAILURE(status)) { | |
105 umtx_unlock(&gRegionDataLock); | |
106 return; | 87 return; |
107 } | 88 } |
108 df->setParseIntegerOnly(TRUE); | 89 df->setParseIntegerOnly(TRUE); |
109 | 90 |
110 regionIDMap = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,
NULL,&status); | 91 regionIDMap = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString
, NULL, &status); |
| 92 if (U_FAILURE(status)) { |
| 93 return; |
| 94 } |
| 95 if (regionIDMap == NULL) { |
| 96 status = U_MEMORY_ALLOCATION_ERROR; |
| 97 return; |
| 98 } |
111 uhash_setValueDeleter(regionIDMap, deleteRegion); | 99 uhash_setValueDeleter(regionIDMap, deleteRegion); |
112 | 100 |
113 numericCodeMap = uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status); | 101 numericCodeMap = uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status); |
114 | 102 |
115 regionAliases = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeStrin
g,NULL,&status); | 103 regionAliases = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeStrin
g,NULL,&status); |
| 104 if (U_FAILURE(status)) { |
| 105 return; |
| 106 } |
| 107 if (regionAliases == NULL) { |
| 108 status = U_MEMORY_ALLOCATION_ERROR; |
| 109 return; |
| 110 } |
116 uhash_setKeyDeleter(regionAliases,uprv_deleteUObject); | 111 uhash_setKeyDeleter(regionAliases,uprv_deleteUObject); |
117 | 112 |
118 UResourceBundle *rb = ures_openDirect(NULL,"metadata",&status); | 113 LocalUResourceBundlePointer rb(ures_openDirect(NULL,"metadata",&status)); |
119 regionCodes = ures_getByKey(rb,"regionCodes",NULL,&status); | 114 LocalUResourceBundlePointer regionCodes(ures_getByKey(rb.getAlias(),"regionC
odes",NULL,&status)); |
120 territoryAlias = ures_getByKey(rb,"territoryAlias",NULL,&status); | 115 LocalUResourceBundlePointer territoryAlias(ures_getByKey(rb.getAlias(),"terr
itoryAlias",NULL,&status)); |
121 | 116 |
122 UResourceBundle *rb2 = ures_openDirect(NULL,"supplementalData",&status); | 117 LocalUResourceBundlePointer rb2(ures_openDirect(NULL,"supplementalData",&sta
tus)); |
123 codeMappings = ures_getByKey(rb2,"codeMappings",NULL,&status); | 118 LocalUResourceBundlePointer codeMappings(ures_getByKey(rb2.getAlias(),"codeM
appings",NULL,&status)); |
124 | 119 |
125 territoryContainment = ures_getByKey(rb2,"territoryContainment",NULL,&status
); | 120 LocalUResourceBundlePointer territoryContainment(ures_getByKey(rb2.getAlias(
),"territoryContainment",NULL,&status)); |
126 worldContainment = ures_getByKey(territoryContainment,"001",NULL,&status); | 121 LocalUResourceBundlePointer worldContainment(ures_getByKey(territoryContainm
ent.getAlias(),"001",NULL,&status)); |
127 groupingContainment = ures_getByKey(territoryContainment,"grouping",NULL,&st
atus); | 122 LocalUResourceBundlePointer groupingContainment(ures_getByKey(territoryConta
inment.getAlias(),"grouping",NULL,&status)); |
128 | 123 |
129 UVector *continents = new UVector(uprv_deleteUObject, uhash_compareUnicodeSt
ring, status); | 124 UVector *continents = new UVector(uprv_deleteUObject, uhash_compareUnicodeSt
ring, status); |
130 | 125 |
131 while ( ures_hasNext(worldContainment) ) { | 126 while ( ures_hasNext(worldContainment.getAlias()) ) { |
132 UnicodeString *continentName = new UnicodeString(ures_getNextUnicodeStri
ng(worldContainment,NULL,&status)); | 127 UnicodeString *continentName = new UnicodeString(ures_getNextUnicodeStri
ng(worldContainment.getAlias(),NULL,&status)); |
133 continents->addElement(continentName,status); | 128 continents->addElement(continentName,status); |
134 } | 129 } |
135 | 130 |
136 UVector *groupings = new UVector(uprv_deleteUObject, uhash_compareUnicodeStr
ing, status); | 131 UVector *groupings = new UVector(uprv_deleteUObject, uhash_compareUnicodeStr
ing, status); |
137 while ( ures_hasNext(groupingContainment) ) { | 132 while ( ures_hasNext(groupingContainment.getAlias()) ) { |
138 UnicodeString *groupingName = new UnicodeString(ures_getNextUnicodeStrin
g(groupingContainment,NULL,&status)); | 133 UnicodeString *groupingName = new UnicodeString(ures_getNextUnicodeStrin
g(groupingContainment.getAlias(),NULL,&status)); |
139 groupings->addElement(groupingName,status); | 134 groupings->addElement(groupingName,status); |
140 } | 135 } |
141 | 136 |
142 while ( ures_hasNext(regionCodes) ) { | 137 while ( ures_hasNext(regionCodes.getAlias()) ) { |
143 UnicodeString regionID = ures_getNextUnicodeString(regionCodes,NULL,&sta
tus); | 138 UnicodeString regionID = ures_getNextUnicodeString(regionCodes.getAlias(
), NULL, &status); |
144 Region *r = new Region(); | 139 Region *r = new Region(); |
145 r->idStr = regionID; | 140 r->idStr = regionID; |
146 r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV); | 141 r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV); |
147 r->type = URGN_TERRITORY; // Only temporary - figure out the real type l
ater once the aliases are known. | 142 r->type = URGN_TERRITORY; // Only temporary - figure out the real type l
ater once the aliases are known. |
148 | 143 |
149 uhash_put(regionIDMap,(void *)&(r->idStr),(void *)r,&status); | 144 uhash_put(regionIDMap,(void *)&(r->idStr),(void *)r,&status); |
150 Formattable result; | 145 Formattable result; |
151 UErrorCode ps = U_ZERO_ERROR; | 146 UErrorCode ps = U_ZERO_ERROR; |
152 df->parse(r->idStr,result,ps); | 147 df->parse(r->idStr,result,ps); |
153 if ( U_SUCCESS(ps) ) { | 148 if ( U_SUCCESS(ps) ) { |
154 r->code = result.getLong(); // Convert string to number | 149 r->code = result.getLong(); // Convert string to number |
155 uhash_iput(numericCodeMap,r->code,(void *)r,&status); | 150 uhash_iput(numericCodeMap,r->code,(void *)r,&status); |
156 r->type = URGN_SUBCONTINENT; | 151 r->type = URGN_SUBCONTINENT; |
157 } else { | 152 } else { |
158 r->code = -1; | 153 r->code = -1; |
159 } | 154 } |
160 } | 155 } |
161 | 156 |
162 | 157 |
163 // Process the territory aliases | 158 // Process the territory aliases |
164 while ( ures_hasNext(territoryAlias) ) { | 159 while ( ures_hasNext(territoryAlias.getAlias()) ) { |
165 UResourceBundle *res = ures_getNextResource(territoryAlias,NULL,&status)
; | 160 UResourceBundle *res = ures_getNextResource(territoryAlias.getAlias(),NU
LL,&status); |
166 const char *aliasFrom = ures_getKey(res); | 161 const char *aliasFrom = ures_getKey(res); |
167 UnicodeString* aliasFromStr = new UnicodeString(aliasFrom, -1, US_INV); | 162 UnicodeString* aliasFromStr = new UnicodeString(aliasFrom, -1, US_INV); |
168 UnicodeString aliasTo = ures_getUnicodeString(res,&status); | 163 UnicodeString aliasTo = ures_getUnicodeString(res,&status); |
169 ures_close(res); | 164 ures_close(res); |
170 | 165 |
171 Region *aliasToRegion = (Region *) uhash_get(regionIDMap,&aliasTo); | 166 Region *aliasToRegion = (Region *) uhash_get(regionIDMap,&aliasTo); |
172 Region *aliasFromRegion = (Region *)uhash_get(regionIDMap,aliasFromStr); | 167 Region *aliasFromRegion = (Region *)uhash_get(regionIDMap,aliasFromStr); |
173 | 168 |
174 if ( aliasToRegion != NULL && aliasFromRegion == NULL ) { // This is jus
t an alias from some string to a region | 169 if ( aliasToRegion != NULL && aliasFromRegion == NULL ) { // This is jus
t an alias from some string to a region |
175 uhash_put(regionAliases,(void *)aliasFromStr, (void *)aliasToRegion,
&status); | 170 uhash_put(regionAliases,(void *)aliasFromStr, (void *)aliasToRegion,
&status); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 UnicodeString *preferredValue = new UnicodeString(target
->idStr); | 202 UnicodeString *preferredValue = new UnicodeString(target
->idStr); |
208 aliasFromRegion->preferredValues->addElement((void *)pre
ferredValue,status); | 203 aliasFromRegion->preferredValues->addElement((void *)pre
ferredValue,status); |
209 } | 204 } |
210 currentRegion.remove(); | 205 currentRegion.remove(); |
211 } | 206 } |
212 } | 207 } |
213 } | 208 } |
214 } | 209 } |
215 | 210 |
216 // Process the code mappings - This will allow us to assign numeric codes to
most of the territories. | 211 // Process the code mappings - This will allow us to assign numeric codes to
most of the territories. |
217 while ( ures_hasNext(codeMappings) ) { | 212 while ( ures_hasNext(codeMappings.getAlias()) ) { |
218 UResourceBundle *mapping = ures_getNextResource(codeMappings,NULL,&statu
s); | 213 UResourceBundle *mapping = ures_getNextResource(codeMappings.getAlias(),
NULL,&status); |
219 if ( ures_getType(mapping) == URES_ARRAY && ures_getSize(mapping) == 3)
{ | 214 if ( ures_getType(mapping) == URES_ARRAY && ures_getSize(mapping) == 3)
{ |
220 UnicodeString codeMappingID = ures_getUnicodeStringByIndex(mapping,0
,&status); | 215 UnicodeString codeMappingID = ures_getUnicodeStringByIndex(mapping,0
,&status); |
221 UnicodeString codeMappingNumber = ures_getUnicodeStringByIndex(mappi
ng,1,&status); | 216 UnicodeString codeMappingNumber = ures_getUnicodeStringByIndex(mappi
ng,1,&status); |
222 UnicodeString codeMapping3Letter = ures_getUnicodeStringByIndex(mapp
ing,2,&status); | 217 UnicodeString codeMapping3Letter = ures_getUnicodeStringByIndex(mapp
ing,2,&status); |
223 | 218 |
224 Region *r = (Region *)uhash_get(regionIDMap,(void *)&codeMappingID); | 219 Region *r = (Region *)uhash_get(regionIDMap,(void *)&codeMappingID); |
225 if ( r ) { | 220 if ( r ) { |
226 Formattable result; | 221 Formattable result; |
227 UErrorCode ps = U_ZERO_ERROR; | 222 UErrorCode ps = U_ZERO_ERROR; |
228 df->parse(codeMappingNumber,result,ps); | 223 df->parse(codeMappingNumber,result,ps); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 // Special case: The region code "QO" (Outlying Oceania) is a subcontinent c
ode added by CLDR | 265 // Special case: The region code "QO" (Outlying Oceania) is a subcontinent c
ode added by CLDR |
271 // even though it looks like a territory code. Need to handle it here. | 266 // even though it looks like a territory code. Need to handle it here. |
272 | 267 |
273 UnicodeString OUTLYING_OCEANIA_REGION_ID_STRING(OUTLYING_OCEANIA_REGION_
ID); | 268 UnicodeString OUTLYING_OCEANIA_REGION_ID_STRING(OUTLYING_OCEANIA_REGION_
ID); |
274 r = (Region *) uhash_get(regionIDMap,(void *)&OUTLYING_OCEANIA_REGION_ID_STR
ING); | 269 r = (Region *) uhash_get(regionIDMap,(void *)&OUTLYING_OCEANIA_REGION_ID_STR
ING); |
275 if ( r ) { | 270 if ( r ) { |
276 r->type = URGN_SUBCONTINENT; | 271 r->type = URGN_SUBCONTINENT; |
277 } | 272 } |
278 | 273 |
279 // Load territory containment info from the supplemental data. | 274 // Load territory containment info from the supplemental data. |
280 while ( ures_hasNext(territoryContainment) ) { | 275 while ( ures_hasNext(territoryContainment.getAlias()) ) { |
281 UResourceBundle *mapping = ures_getNextResource(territoryContainment,NUL
L,&status); | 276 UResourceBundle *mapping = ures_getNextResource(territoryContainment.get
Alias(),NULL,&status); |
282 const char *parent = ures_getKey(mapping); | 277 const char *parent = ures_getKey(mapping); |
| 278 if (uprv_strcmp(parent, "containedGroupings") == 0 || uprv_strcmp(parent
, "deprecated") == 0) { |
| 279 ures_close(mapping); |
| 280 continue; // handle new pseudo-parent types added in ICU data per cl
drbug 7808; for now just skip. |
| 281 // #11232 is to do something useful with these. |
| 282 } |
283 UnicodeString parentStr = UnicodeString(parent, -1 , US_INV); | 283 UnicodeString parentStr = UnicodeString(parent, -1 , US_INV); |
284 Region *parentRegion = (Region *) uhash_get(regionIDMap,(void *)&parentS
tr); | 284 Region *parentRegion = (Region *) uhash_get(regionIDMap,(void *)&parentS
tr); |
285 | 285 |
286 for ( int j = 0 ; j < ures_getSize(mapping); j++ ) { | 286 for ( int j = 0 ; j < ures_getSize(mapping); j++ ) { |
287 UnicodeString child = ures_getUnicodeStringByIndex(mapping,j,&status
); | 287 UnicodeString child = ures_getUnicodeStringByIndex(mapping,j,&status
); |
288 Region *childRegion = (Region *) uhash_get(regionIDMap,(void *)&chil
d); | 288 Region *childRegion = (Region *) uhash_get(regionIDMap,(void *)&chil
d); |
289 if ( parentRegion != NULL && childRegion != NULL ) { | 289 if ( parentRegion != NULL && childRegion != NULL ) { |
290 | 290 |
291 // Add the child region to the set of regions contained by the p
arent | 291 // Add the child region to the set of regions contained by the p
arent |
292 if (parentRegion->containedRegions == NULL) { | 292 if (parentRegion->containedRegions == NULL) { |
(...skipping 19 matching lines...) Expand all Loading... |
312 int32_t pos = -1; | 312 int32_t pos = -1; |
313 while ( const UHashElement* element = uhash_nextElement(regionIDMap,&pos)) { | 313 while ( const UHashElement* element = uhash_nextElement(regionIDMap,&pos)) { |
314 Region *ar = (Region *)element->value.pointer; | 314 Region *ar = (Region *)element->value.pointer; |
315 if ( availableRegions[ar->type] == NULL ) { | 315 if ( availableRegions[ar->type] == NULL ) { |
316 availableRegions[ar->type] = new UVector(uprv_deleteUObject, uhash_c
ompareUnicodeString, status); | 316 availableRegions[ar->type] = new UVector(uprv_deleteUObject, uhash_c
ompareUnicodeString, status); |
317 } | 317 } |
318 UnicodeString *arString = new UnicodeString(ar->idStr); | 318 UnicodeString *arString = new UnicodeString(ar->idStr); |
319 availableRegions[ar->type]->addElement((void *)arString,status); | 319 availableRegions[ar->type]->addElement((void *)arString,status); |
320 } | 320 } |
321 | 321 |
322 ures_close(territoryContainment); | |
323 ures_close(worldContainment); | |
324 ures_close(groupingContainment); | |
325 | |
326 ures_close(codeMappings); | |
327 ures_close(rb2); | |
328 ures_close(territoryAlias); | |
329 ures_close(regionCodes); | |
330 ures_close(rb); | |
331 | |
332 delete df; | |
333 | |
334 ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); | 322 ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); |
335 | |
336 regionDataIsLoaded = true; | |
337 umtx_unlock(&gRegionDataLock); | |
338 | |
339 } | 323 } |
340 | 324 |
341 void Region::cleanupRegionData() { | 325 void Region::cleanupRegionData() { |
342 | |
343 for (int32_t i = 0 ; i < URGN_LIMIT ; i++ ) { | 326 for (int32_t i = 0 ; i < URGN_LIMIT ; i++ ) { |
344 if ( availableRegions[i] ) { | 327 if ( availableRegions[i] ) { |
345 delete availableRegions[i]; | 328 delete availableRegions[i]; |
346 } | 329 } |
347 } | 330 } |
348 | 331 |
349 if (regionAliases) { | 332 if (regionAliases) { |
350 uhash_close(regionAliases); | 333 uhash_close(regionAliases); |
351 } | 334 } |
352 | 335 |
353 if (numericCodeMap) { | 336 if (numericCodeMap) { |
354 uhash_close(numericCodeMap); | 337 uhash_close(numericCodeMap); |
355 } | 338 } |
356 | 339 |
357 if (regionIDMap) { | 340 if (regionIDMap) { |
358 uhash_close(regionIDMap); | 341 uhash_close(regionIDMap); |
359 } | 342 } |
| 343 gRegionDataInitOnce.reset(); |
360 } | 344 } |
361 | 345 |
362 Region::Region () | 346 Region::Region () |
363 : code(-1), | 347 : code(-1), |
364 type(URGN_UNKNOWN), | 348 type(URGN_UNKNOWN), |
365 containingRegion(NULL), | 349 containingRegion(NULL), |
366 containedRegions(NULL), | 350 containedRegions(NULL), |
367 preferredValues(NULL) { | 351 preferredValues(NULL) { |
368 id[0] = 0; | 352 id[0] = 0; |
369 } | 353 } |
(...skipping 25 matching lines...) Expand all Loading... |
395 | 379 |
396 /** | 380 /** |
397 * Returns a pointer to a Region using the given region code. The region code c
an be either 2-letter ISO code, | 381 * Returns a pointer to a Region using the given region code. The region code c
an be either 2-letter ISO code, |
398 * 3-letter ISO code, UNM.49 numeric code, or other valid Unicode Region Code a
s defined by the LDML specification. | 382 * 3-letter ISO code, UNM.49 numeric code, or other valid Unicode Region Code a
s defined by the LDML specification. |
399 * The identifier will be canonicalized internally using the supplemental metada
ta as defined in the CLDR. | 383 * The identifier will be canonicalized internally using the supplemental metada
ta as defined in the CLDR. |
400 * If the region code is NULL or not recognized, the appropriate error code will
be set ( U_ILLEGAL_ARGUMENT_ERROR ) | 384 * If the region code is NULL or not recognized, the appropriate error code will
be set ( U_ILLEGAL_ARGUMENT_ERROR ) |
401 */ | 385 */ |
402 const Region* U_EXPORT2 | 386 const Region* U_EXPORT2 |
403 Region::getInstance(const char *region_code, UErrorCode &status) { | 387 Region::getInstance(const char *region_code, UErrorCode &status) { |
404 | 388 |
| 389 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
| 390 if (U_FAILURE(status)) { |
| 391 return NULL; |
| 392 } |
| 393 |
405 if ( !region_code ) { | 394 if ( !region_code ) { |
406 status = U_ILLEGAL_ARGUMENT_ERROR; | 395 status = U_ILLEGAL_ARGUMENT_ERROR; |
407 return NULL; | 396 return NULL; |
408 } | 397 } |
409 | |
410 loadRegionData(); | |
411 | |
412 if (regionIDMap == NULL) { | |
413 status = U_ILLEGAL_ARGUMENT_ERROR; | |
414 return NULL; | |
415 } | |
416 | 398 |
417 UnicodeString regionCodeString = UnicodeString(region_code, -1, US_INV); | 399 UnicodeString regionCodeString = UnicodeString(region_code, -1, US_INV); |
418 Region *r = (Region *)uhash_get(regionIDMap,(void *)®ionCodeString); | 400 Region *r = (Region *)uhash_get(regionIDMap,(void *)®ionCodeString); |
419 | 401 |
420 if ( !r ) { | 402 if ( !r ) { |
421 r = (Region *)uhash_get(regionAliases,(void *)®ionCodeString); | 403 r = (Region *)uhash_get(regionAliases,(void *)®ionCodeString); |
422 } | 404 } |
423 | 405 |
424 if ( !r ) { // Unknown region code | 406 if ( !r ) { // Unknown region code |
425 status = U_ILLEGAL_ARGUMENT_ERROR; | 407 status = U_ILLEGAL_ARGUMENT_ERROR; |
(...skipping 12 matching lines...) Expand all Loading... |
438 | 420 |
439 } | 421 } |
440 | 422 |
441 /** | 423 /** |
442 * Returns a pointer to a Region using the given numeric region code. If the num
eric region code is not recognized, | 424 * Returns a pointer to a Region using the given numeric region code. If the num
eric region code is not recognized, |
443 * the appropriate error code will be set ( U_ILLEGAL_ARGUMENT_ERROR ). | 425 * the appropriate error code will be set ( U_ILLEGAL_ARGUMENT_ERROR ). |
444 */ | 426 */ |
445 const Region* U_EXPORT2 | 427 const Region* U_EXPORT2 |
446 Region::getInstance (int32_t code, UErrorCode &status) { | 428 Region::getInstance (int32_t code, UErrorCode &status) { |
447 | 429 |
448 loadRegionData(); | 430 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
449 | 431 if (U_FAILURE(status)) { |
450 if (numericCodeMap == NULL) { | |
451 status = U_ILLEGAL_ARGUMENT_ERROR; | |
452 return NULL; | 432 return NULL; |
453 } | 433 } |
454 | 434 |
455 Region *r = (Region *)uhash_iget(numericCodeMap,code); | 435 Region *r = (Region *)uhash_iget(numericCodeMap,code); |
456 | 436 |
457 if ( !r ) { // Just in case there's an alias that's numeric, try to find it. | 437 if ( !r ) { // Just in case there's an alias that's numeric, try to find it. |
458 UErrorCode fs = U_ZERO_ERROR; | 438 UErrorCode fs = U_ZERO_ERROR; |
459 UnicodeString pat = UNICODE_STRING_SIMPLE("00#"); | 439 UnicodeString pat = UNICODE_STRING_SIMPLE("00#"); |
460 DecimalFormat *df = new DecimalFormat(pat,fs); | 440 DecimalFormat *df = new DecimalFormat(pat,fs); |
461 | 441 |
(...skipping 19 matching lines...) Expand all Loading... |
481 | 461 |
482 return r; | 462 return r; |
483 } | 463 } |
484 | 464 |
485 | 465 |
486 /** | 466 /** |
487 * Returns an enumeration over the IDs of all known regions that match the given
type. | 467 * Returns an enumeration over the IDs of all known regions that match the given
type. |
488 */ | 468 */ |
489 StringEnumeration* U_EXPORT2 | 469 StringEnumeration* U_EXPORT2 |
490 Region::getAvailable(URegionType type) { | 470 Region::getAvailable(URegionType type) { |
491 | |
492 loadRegionData(); | |
493 UErrorCode status = U_ZERO_ERROR; | 471 UErrorCode status = U_ZERO_ERROR; |
| 472 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
| 473 if (U_FAILURE(status)) { |
| 474 return NULL; |
| 475 } |
494 return new RegionNameEnumeration(availableRegions[type],status); | 476 return new RegionNameEnumeration(availableRegions[type],status); |
495 | |
496 return NULL; | |
497 } | 477 } |
498 | 478 |
499 /** | 479 /** |
500 * Returns a pointer to the region that contains this region. Returns NULL if t
his region is code "001" (World) | 480 * Returns a pointer to the region that contains this region. Returns NULL if t
his region is code "001" (World) |
501 * or "ZZ" (Unknown region). For example, calling this method with region "IT" (
Italy) returns the | 481 * or "ZZ" (Unknown region). For example, calling this method with region "IT" (
Italy) returns the |
502 * region "039" (Southern Europe). | 482 * region "039" (Southern Europe). |
503 */ | 483 */ |
504 const Region* | 484 const Region* |
505 Region::getContainingRegion() const { | 485 Region::getContainingRegion() const { |
506 loadRegionData(); | 486 UErrorCode status = U_ZERO_ERROR; |
| 487 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
507 return containingRegion; | 488 return containingRegion; |
508 } | 489 } |
509 | 490 |
510 /** | 491 /** |
511 * Return a pointer to the region that geographically contains this region and m
atches the given type, | 492 * Return a pointer to the region that geographically contains this region and m
atches the given type, |
512 * moving multiple steps up the containment chain if necessary. Returns NULL if
no containing region can be found | 493 * moving multiple steps up the containment chain if necessary. Returns NULL if
no containing region can be found |
513 * that matches the given type. Note: The URegionTypes = "URGN_GROUPING", "URGN_
DEPRECATED", or "URGN_UNKNOWN" | 494 * that matches the given type. Note: The URegionTypes = "URGN_GROUPING", "URGN_
DEPRECATED", or "URGN_UNKNOWN" |
514 * are not appropriate for use in this API. NULL will be returned in this case.
For example, calling this method | 495 * are not appropriate for use in this API. NULL will be returned in this case.
For example, calling this method |
515 * with region "IT" (Italy) for type "URGN_CONTINENT" returns the region "150" (
Europe ). | 496 * with region "IT" (Italy) for type "URGN_CONTINENT" returns the region "150" (
Europe ). |
516 */ | 497 */ |
517 const Region* | 498 const Region* |
518 Region::getContainingRegion(URegionType type) const { | 499 Region::getContainingRegion(URegionType type) const { |
519 loadRegionData(); | 500 UErrorCode status = U_ZERO_ERROR; |
| 501 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
520 if ( containingRegion == NULL ) { | 502 if ( containingRegion == NULL ) { |
521 return NULL; | 503 return NULL; |
522 } | 504 } |
523 | 505 |
524 if ( containingRegion->type == type ) { | 506 if ( containingRegion->type == type ) { |
525 return containingRegion; | 507 return containingRegion; |
526 } else { | 508 } else { |
527 return containingRegion->getContainingRegion(type); | 509 return containingRegion->getContainingRegion(type); |
528 } | 510 } |
529 } | 511 } |
530 | 512 |
531 /** | 513 /** |
532 * Return an enumeration over the IDs of all the regions that are immediate chil
dren of this region in the | 514 * Return an enumeration over the IDs of all the regions that are immediate chil
dren of this region in the |
533 * region hierarchy. These returned regions could be either macro regions, terri
tories, or a mixture of the two, | 515 * region hierarchy. These returned regions could be either macro regions, terri
tories, or a mixture of the two, |
534 * depending on the containment data as defined in CLDR. This API may return NU
LL if this region doesn't have | 516 * depending on the containment data as defined in CLDR. This API may return NU
LL if this region doesn't have |
535 * any sub-regions. For example, calling this method with region "150" (Europe)
returns an enumeration containing | 517 * any sub-regions. For example, calling this method with region "150" (Europe)
returns an enumeration containing |
536 * the various sub regions of Europe - "039" (Southern Europe) - "151" (Eastern
Europe) - "154" (Northern Europe) | 518 * the various sub regions of Europe - "039" (Southern Europe) - "151" (Eastern
Europe) - "154" (Northern Europe) |
537 * and "155" (Western Europe). | 519 * and "155" (Western Europe). |
538 */ | 520 */ |
539 StringEnumeration* | 521 StringEnumeration* |
540 Region::getContainedRegions() const { | 522 Region::getContainedRegions() const { |
541 loadRegionData(); | |
542 UErrorCode status = U_ZERO_ERROR; | 523 UErrorCode status = U_ZERO_ERROR; |
| 524 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
543 return new RegionNameEnumeration(containedRegions,status); | 525 return new RegionNameEnumeration(containedRegions,status); |
544 } | 526 } |
545 | 527 |
546 /** | 528 /** |
547 * Returns an enumeration over the IDs of all the regions that are children of t
his region anywhere in the region | 529 * Returns an enumeration over the IDs of all the regions that are children of t
his region anywhere in the region |
548 * hierarchy and match the given type. This API may return an empty enumeration
if this region doesn't have any | 530 * hierarchy and match the given type. This API may return an empty enumeration
if this region doesn't have any |
549 * sub-regions that match the given type. For example, calling this method with
region "150" (Europe) and type | 531 * sub-regions that match the given type. For example, calling this method with
region "150" (Europe) and type |
550 * "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR
" (France) - "IT" (Italy) - "DE" (Germany) etc. ) | 532 * "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR
" (France) - "IT" (Italy) - "DE" (Germany) etc. ) |
551 */ | 533 */ |
552 StringEnumeration* | 534 StringEnumeration* |
553 Region::getContainedRegions( URegionType type ) const { | 535 Region::getContainedRegions( URegionType type ) const { |
554 loadRegionData(); | 536 UErrorCode status = U_ZERO_ERROR; |
| 537 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
| 538 if (U_FAILURE(status)) { |
| 539 return NULL; |
| 540 } |
555 | 541 |
556 UErrorCode status = U_ZERO_ERROR; | |
557 UVector *result = new UVector(NULL, uhash_compareChars, status); | 542 UVector *result = new UVector(NULL, uhash_compareChars, status); |
558 | 543 |
559 StringEnumeration *cr = getContainedRegions(); | 544 StringEnumeration *cr = getContainedRegions(); |
560 | 545 |
561 for ( int32_t i = 0 ; i < cr->count(status) ; i++ ) { | 546 for ( int32_t i = 0 ; i < cr->count(status) ; i++ ) { |
562 const char *id = cr->next(NULL,status); | 547 const char *id = cr->next(NULL,status); |
563 const Region *r = Region::getInstance(id,status); | 548 const Region *r = Region::getInstance(id,status); |
564 if ( r->getType() == type ) { | 549 if ( r->getType() == type ) { |
565 result->addElement((void *)&r->idStr,status); | 550 result->addElement((void *)&r->idStr,status); |
566 } else { | 551 } else { |
(...skipping 10 matching lines...) Expand all Loading... |
577 StringEnumeration* resultEnumeration = new RegionNameEnumeration(result,stat
us); | 562 StringEnumeration* resultEnumeration = new RegionNameEnumeration(result,stat
us); |
578 delete result; | 563 delete result; |
579 return resultEnumeration; | 564 return resultEnumeration; |
580 } | 565 } |
581 | 566 |
582 /** | 567 /** |
583 * Returns true if this region contains the supplied other region anywhere in th
e region hierarchy. | 568 * Returns true if this region contains the supplied other region anywhere in th
e region hierarchy. |
584 */ | 569 */ |
585 UBool | 570 UBool |
586 Region::contains(const Region &other) const { | 571 Region::contains(const Region &other) const { |
587 loadRegionData(); | 572 UErrorCode status = U_ZERO_ERROR; |
| 573 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
588 | 574 |
589 if (!containedRegions) { | 575 if (!containedRegions) { |
590 return FALSE; | 576 return FALSE; |
591 } | 577 } |
592 if (containedRegions->contains((void *)&other.idStr)) { | 578 if (containedRegions->contains((void *)&other.idStr)) { |
593 return TRUE; | 579 return TRUE; |
594 } else { | 580 } else { |
595 for ( int32_t i = 0 ; i < containedRegions->size() ; i++ ) { | 581 for ( int32_t i = 0 ; i < containedRegions->size() ; i++ ) { |
596 UnicodeString *crStr = (UnicodeString *)containedRegions->elementAt(
i); | 582 UnicodeString *crStr = (UnicodeString *)containedRegions->elementAt(
i); |
597 Region *cr = (Region *) uhash_get(regionIDMap,(void *)crStr); | 583 Region *cr = (Region *) uhash_get(regionIDMap,(void *)crStr); |
598 if ( cr && cr->contains(other) ) { | 584 if ( cr && cr->contains(other) ) { |
599 return TRUE; | 585 return TRUE; |
600 } | 586 } |
601 } | 587 } |
602 } | 588 } |
603 | 589 |
604 return FALSE; | 590 return FALSE; |
605 } | 591 } |
606 | 592 |
607 /** | 593 /** |
608 * For deprecated regions, return an enumeration over the IDs of the regions tha
t are the preferred replacement | 594 * For deprecated regions, return an enumeration over the IDs of the regions tha
t are the preferred replacement |
609 * regions for this region. Returns NULL for a non-deprecated region. For exam
ple, calling this method with region | 595 * regions for this region. Returns NULL for a non-deprecated region. For exam
ple, calling this method with region |
610 * "SU" (Soviet Union) would return a list of the regions containing "RU" (Russi
a), "AM" (Armenia), "AZ" (Azerbaijan), etc... | 596 * "SU" (Soviet Union) would return a list of the regions containing "RU" (Russi
a), "AM" (Armenia), "AZ" (Azerbaijan), etc... |
611 */ | 597 */ |
612 StringEnumeration* | 598 StringEnumeration* |
613 Region::getPreferredValues() const { | 599 Region::getPreferredValues() const { |
614 loadRegionData(); | |
615 UErrorCode status = U_ZERO_ERROR; | 600 UErrorCode status = U_ZERO_ERROR; |
| 601 umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
616 if ( type == URGN_DEPRECATED ) { | 602 if ( type == URGN_DEPRECATED ) { |
617 return new RegionNameEnumeration(preferredValues,status); | 603 return new RegionNameEnumeration(preferredValues,status); |
618 } else { | 604 } else { |
619 return NULL; | 605 return NULL; |
620 } | 606 } |
621 } | 607 } |
622 | 608 |
623 | 609 |
624 /** | 610 /** |
625 * Return this region's canonical region code. | 611 * Return this region's canonical region code. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 | 667 |
682 RegionNameEnumeration::~RegionNameEnumeration() { | 668 RegionNameEnumeration::~RegionNameEnumeration() { |
683 delete fRegionNames; | 669 delete fRegionNames; |
684 } | 670 } |
685 | 671 |
686 U_NAMESPACE_END | 672 U_NAMESPACE_END |
687 | 673 |
688 #endif /* #if !UCONFIG_NO_FORMATTING */ | 674 #endif /* #if !UCONFIG_NO_FORMATTING */ |
689 | 675 |
690 //eof | 676 //eof |
OLD | NEW |