2 *******************************************************************************
3 * Copyright (C) 2014-2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *******************************************************************************
10 * Modification History:*
11 * Date Name Description
12 * 01/15/13 Emmons Original Port from ICU4J
13 ********************************************************************************
18 * \brief C++ API: Region classes (territory containment)
21 #include "unicode/region.h"
22 #include "unicode/utypes.h"
23 #include "unicode/uobject.h"
24 #include "unicode/unistr.h"
25 #include "unicode/ures.h"
26 #include "unicode/decimfmt.h"
33 #include "region_impl.h"
35 #if !UCONFIG_NO_FORMATTING
40 static void U_CALLCONV
41 deleteRegion(void *obj
) {
42 delete (icu::Region
*)obj
;
46 * Cleanup callback func
48 static UBool U_CALLCONV
region_cleanup(void)
50 icu::Region::cleanupRegionData();
59 static UInitOnce gRegionDataInitOnce
= U_INITONCE_INITIALIZER
;
60 static UVector
* availableRegions
[URGN_LIMIT
];
62 static UHashtable
*regionAliases
= NULL
;
63 static UHashtable
*regionIDMap
= NULL
;
64 static UHashtable
*numericCodeMap
= NULL
;
66 static const UChar UNKNOWN_REGION_ID
[] = { 0x5A, 0x5A, 0 }; /* "ZZ" */
67 static const UChar OUTLYING_OCEANIA_REGION_ID
[] = { 0x51, 0x4F, 0 }; /* "QO" */
68 static const UChar WORLD_ID
[] = { 0x30, 0x30, 0x31, 0 }; /* "001" */
70 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration
)
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 numeric
75 * codes are, any known aliases, and the territory containment data.
77 * If the region data has already loaded, then this method simply returns without doing
78 * anything meaningful.
80 void Region::loadRegionData(UErrorCode
&status
) {
81 // Construct service objs first
82 LocalUHashtablePointer
newRegionIDMap(uhash_open(uhash_hashUnicodeString
, uhash_compareUnicodeString
, NULL
, &status
));
83 LocalUHashtablePointer
newNumericCodeMap(uhash_open(uhash_hashLong
,uhash_compareLong
,NULL
,&status
));
84 LocalUHashtablePointer
newRegionAliases(uhash_open(uhash_hashUnicodeString
,uhash_compareUnicodeString
,NULL
,&status
));
86 LocalPointer
<DecimalFormat
> df(new DecimalFormat(status
), status
);
88 LocalPointer
<UVector
> continents(new UVector(uprv_deleteUObject
, uhash_compareUnicodeString
, status
), status
);
89 LocalPointer
<UVector
> groupings(new UVector(uprv_deleteUObject
, uhash_compareUnicodeString
, status
), status
);
91 LocalUResourceBundlePointer
metadata(ures_openDirect(NULL
,"metadata",&status
));
92 LocalUResourceBundlePointer
regionCodes(ures_getByKey(metadata
.getAlias(),"regionCodes",NULL
,&status
));
93 LocalUResourceBundlePointer
metadataAlias(ures_getByKey(metadata
.getAlias(),"alias",NULL
,&status
));
94 LocalUResourceBundlePointer
territoryAlias(ures_getByKey(metadataAlias
.getAlias(),"territory",NULL
,&status
));
96 LocalUResourceBundlePointer
supplementalData(ures_openDirect(NULL
,"supplementalData",&status
));
97 LocalUResourceBundlePointer
codeMappings(ures_getByKey(supplementalData
.getAlias(),"codeMappings",NULL
,&status
));
99 LocalUResourceBundlePointer
territoryContainment(ures_getByKey(supplementalData
.getAlias(),"territoryContainment",NULL
,&status
));
100 LocalUResourceBundlePointer
worldContainment(ures_getByKey(territoryContainment
.getAlias(),"001",NULL
,&status
));
101 LocalUResourceBundlePointer
groupingContainment(ures_getByKey(territoryContainment
.getAlias(),"grouping",NULL
,&status
));
103 if (U_FAILURE(status
)) {
108 df
->setParseIntegerOnly(TRUE
);
109 uhash_setValueDeleter(newRegionIDMap
.getAlias(), deleteRegion
); // regionIDMap owns objs
110 uhash_setKeyDeleter(newRegionAliases
.getAlias(), uprv_deleteUObject
); // regionAliases owns the string keys
112 while ( ures_hasNext(worldContainment
.getAlias()) ) {
113 UnicodeString
*continentName
= new UnicodeString(ures_getNextUnicodeString(worldContainment
.getAlias(),NULL
,&status
));
114 continents
->addElement(continentName
,status
);
117 while ( ures_hasNext(groupingContainment
.getAlias()) ) {
118 UnicodeString
*groupingName
= new UnicodeString(ures_getNextUnicodeString(groupingContainment
.getAlias(),NULL
,&status
));
119 groupings
->addElement(groupingName
,status
);
122 while ( ures_hasNext(regionCodes
.getAlias()) ) {
123 UnicodeString regionID
= ures_getNextUnicodeString(regionCodes
.getAlias(), NULL
, &status
);
124 LocalPointer
<Region
> r(new Region(), status
);
125 if ( U_FAILURE(status
) ) {
129 r
->idStr
.extract(0,r
->idStr
.length(),r
->id
,sizeof(r
->id
),US_INV
);
130 r
->type
= URGN_TERRITORY
; // Only temporary - figure out the real type later once the aliases are known.
133 UErrorCode ps
= U_ZERO_ERROR
;
134 df
->parse(r
->idStr
,result
,ps
);
135 if ( U_SUCCESS(ps
) ) {
136 r
->code
= result
.getLong(); // Convert string to number
137 uhash_iput(newNumericCodeMap
.getAlias(),r
->code
,(void *)(r
.getAlias()),&status
);
138 r
->type
= URGN_SUBCONTINENT
;
142 void* idStrAlias
= (void*)&(r
->idStr
); // about to orphan 'r'. Save this off.
143 uhash_put(newRegionIDMap
.getAlias(),idStrAlias
,(void *)(r
.orphan()),&status
); // regionIDMap takes ownership
147 // Process the territory aliases
148 while ( ures_hasNext(territoryAlias
.getAlias()) ) {
149 LocalUResourceBundlePointer
res(ures_getNextResource(territoryAlias
.getAlias(),NULL
,&status
));
150 const char *aliasFrom
= ures_getKey(res
.getAlias());
151 LocalPointer
<UnicodeString
> aliasFromStr(new UnicodeString(aliasFrom
, -1, US_INV
), status
);
152 UnicodeString aliasTo
= ures_getUnicodeStringByKey(res
.getAlias(),"replacement",&status
);
153 res
.adoptInstead(NULL
);
155 const Region
*aliasToRegion
= (Region
*) uhash_get(newRegionIDMap
.getAlias(),&aliasTo
);
156 Region
*aliasFromRegion
= (Region
*)uhash_get(newRegionIDMap
.getAlias(),aliasFromStr
.getAlias());
158 if ( aliasToRegion
!= NULL
&& aliasFromRegion
== NULL
) { // This is just an alias from some string to a region
159 uhash_put(newRegionAliases
.getAlias(),(void *)aliasFromStr
.orphan(), (void *)aliasToRegion
,&status
);
161 if ( aliasFromRegion
== NULL
) { // Deprecated region code not in the master codes list - so need to create a deprecated region for it.
162 LocalPointer
<Region
> newRgn(new Region
, status
);
163 if ( U_SUCCESS(status
) ) {
164 aliasFromRegion
= newRgn
.orphan();
168 aliasFromRegion
->idStr
.setTo(*aliasFromStr
);
169 aliasFromRegion
->idStr
.extract(0,aliasFromRegion
->idStr
.length(),aliasFromRegion
->id
,sizeof(aliasFromRegion
->id
),US_INV
);
170 uhash_put(newRegionIDMap
.getAlias(),(void *)&(aliasFromRegion
->idStr
),(void *)aliasFromRegion
,&status
);
172 UErrorCode ps
= U_ZERO_ERROR
;
173 df
->parse(aliasFromRegion
->idStr
,result
,ps
);
174 if ( U_SUCCESS(ps
) ) {
175 aliasFromRegion
->code
= result
.getLong(); // Convert string to number
176 uhash_iput(newNumericCodeMap
.getAlias(),aliasFromRegion
->code
,(void *)aliasFromRegion
,&status
);
178 aliasFromRegion
->code
= -1;
180 aliasFromRegion
->type
= URGN_DEPRECATED
;
182 aliasFromRegion
->type
= URGN_DEPRECATED
;
186 LocalPointer
<UVector
> newPreferredValues(new UVector(uprv_deleteUObject
, uhash_compareUnicodeString
, status
), status
);
187 aliasFromRegion
->preferredValues
= newPreferredValues
.orphan();
189 if( U_FAILURE(status
)) {
192 UnicodeString currentRegion
;
193 //currentRegion.remove(); TODO: was already 0 length?
194 for (int32_t i
= 0 ; i
< aliasTo
.length() ; i
++ ) {
195 if ( aliasTo
.charAt(i
) != 0x0020 ) {
196 currentRegion
.append(aliasTo
.charAt(i
));
198 if ( aliasTo
.charAt(i
) == 0x0020 || i
+1 == aliasTo
.length() ) {
199 Region
*target
= (Region
*)uhash_get(newRegionIDMap
.getAlias(),(void *)¤tRegion
);
201 LocalPointer
<UnicodeString
> preferredValue(new UnicodeString(target
->idStr
), status
);
202 aliasFromRegion
->preferredValues
->addElement((void *)preferredValue
.orphan(),status
); // may add null if err
204 currentRegion
.remove();
210 // Process the code mappings - This will allow us to assign numeric codes to most of the territories.
211 while ( ures_hasNext(codeMappings
.getAlias()) ) {
212 UResourceBundle
*mapping
= ures_getNextResource(codeMappings
.getAlias(),NULL
,&status
);
213 if ( ures_getType(mapping
) == URES_ARRAY
&& ures_getSize(mapping
) == 3) {
214 UnicodeString codeMappingID
= ures_getUnicodeStringByIndex(mapping
,0,&status
);
215 UnicodeString codeMappingNumber
= ures_getUnicodeStringByIndex(mapping
,1,&status
);
216 UnicodeString codeMapping3Letter
= ures_getUnicodeStringByIndex(mapping
,2,&status
);
218 Region
*r
= (Region
*)uhash_get(newRegionIDMap
.getAlias(),(void *)&codeMappingID
);
221 UErrorCode ps
= U_ZERO_ERROR
;
222 df
->parse(codeMappingNumber
,result
,ps
);
223 if ( U_SUCCESS(ps
) ) {
224 r
->code
= result
.getLong(); // Convert string to number
225 uhash_iput(newNumericCodeMap
.getAlias(),r
->code
,(void *)r
,&status
);
227 LocalPointer
<UnicodeString
> code3(new UnicodeString(codeMapping3Letter
), status
);
228 uhash_put(newRegionAliases
.getAlias(),(void *)code3
.orphan(), (void *)r
,&status
);
234 // Now fill in the special cases for WORLD, UNKNOWN, CONTINENTS, and GROUPINGS
236 UnicodeString
WORLD_ID_STRING(WORLD_ID
);
237 r
= (Region
*) uhash_get(newRegionIDMap
.getAlias(),(void *)&WORLD_ID_STRING
);
239 r
->type
= URGN_WORLD
;
242 UnicodeString
UNKNOWN_REGION_ID_STRING(UNKNOWN_REGION_ID
);
243 r
= (Region
*) uhash_get(newRegionIDMap
.getAlias(),(void *)&UNKNOWN_REGION_ID_STRING
);
245 r
->type
= URGN_UNKNOWN
;
248 for ( int32_t i
= 0 ; i
< continents
->size() ; i
++ ) {
249 r
= (Region
*) uhash_get(newRegionIDMap
.getAlias(),(void *)continents
->elementAt(i
));
251 r
->type
= URGN_CONTINENT
;
255 for ( int32_t i
= 0 ; i
< groupings
->size() ; i
++ ) {
256 r
= (Region
*) uhash_get(newRegionIDMap
.getAlias(),(void *)groupings
->elementAt(i
));
258 r
->type
= URGN_GROUPING
;
262 // Special case: The region code "QO" (Outlying Oceania) is a subcontinent code added by CLDR
263 // even though it looks like a territory code. Need to handle it here.
265 UnicodeString
OUTLYING_OCEANIA_REGION_ID_STRING(OUTLYING_OCEANIA_REGION_ID
);
266 r
= (Region
*) uhash_get(newRegionIDMap
.getAlias(),(void *)&OUTLYING_OCEANIA_REGION_ID_STRING
);
268 r
->type
= URGN_SUBCONTINENT
;
271 // Load territory containment info from the supplemental data.
272 while ( ures_hasNext(territoryContainment
.getAlias()) ) {
273 LocalUResourceBundlePointer
mapping(ures_getNextResource(territoryContainment
.getAlias(),NULL
,&status
));
274 if( U_FAILURE(status
) ) {
277 const char *parent
= ures_getKey(mapping
.getAlias());
278 if (uprv_strcmp(parent
, "containedGroupings") == 0 || uprv_strcmp(parent
, "deprecated") == 0) {
279 continue; // handle new pseudo-parent types added in ICU data per cldrbug 7808; for now just skip.
280 // #11232 is to do something useful with these.
282 UnicodeString parentStr
= UnicodeString(parent
, -1 , US_INV
);
283 Region
*parentRegion
= (Region
*) uhash_get(newRegionIDMap
.getAlias(),(void *)&parentStr
);
285 for ( int j
= 0 ; j
< ures_getSize(mapping
.getAlias()); j
++ ) {
286 UnicodeString child
= ures_getUnicodeStringByIndex(mapping
.getAlias(),j
,&status
);
287 Region
*childRegion
= (Region
*) uhash_get(newRegionIDMap
.getAlias(),(void *)&child
);
288 if ( parentRegion
!= NULL
&& childRegion
!= NULL
) {
290 // Add the child region to the set of regions contained by the parent
291 if (parentRegion
->containedRegions
== NULL
) {
292 parentRegion
->containedRegions
= new UVector(uprv_deleteUObject
, uhash_compareUnicodeString
, status
);
295 LocalPointer
<UnicodeString
> childStr(new UnicodeString(), status
);
296 if( U_FAILURE(status
) ) {
299 childStr
->fastCopyFrom(childRegion
->idStr
);
300 parentRegion
->containedRegions
->addElement((void *)childStr
.orphan(),status
);
302 // Set the parent region to be the containing region of the child.
303 // Regions of type GROUPING can't be set as the parent, since another region
304 // such as a SUBCONTINENT, CONTINENT, or WORLD must always be the parent.
305 if ( parentRegion
->type
!= URGN_GROUPING
) {
306 childRegion
->containingRegion
= parentRegion
;
312 // Create the availableRegions lists
313 int32_t pos
= UHASH_FIRST
;
314 while ( const UHashElement
* element
= uhash_nextElement(newRegionIDMap
.getAlias(),&pos
)) {
315 Region
*ar
= (Region
*)element
->value
.pointer
;
316 if ( availableRegions
[ar
->type
] == NULL
) {
317 LocalPointer
<UVector
> newAr(new UVector(uprv_deleteUObject
, uhash_compareUnicodeString
, status
), status
);
318 availableRegions
[ar
->type
] = newAr
.orphan();
320 LocalPointer
<UnicodeString
> arString(new UnicodeString(ar
->idStr
), status
);
321 if( U_FAILURE(status
) ) {
324 availableRegions
[ar
->type
]->addElement((void *)arString
.orphan(),status
);
327 ucln_i18n_registerCleanup(UCLN_I18N_REGION
, region_cleanup
);
329 numericCodeMap
= newNumericCodeMap
.orphan();
330 regionIDMap
= newRegionIDMap
.orphan();
331 regionAliases
= newRegionAliases
.orphan();
334 void Region::cleanupRegionData() {
335 for (int32_t i
= 0 ; i
< URGN_LIMIT
; i
++ ) {
336 if ( availableRegions
[i
] ) {
337 delete availableRegions
[i
];
342 uhash_close(regionAliases
);
345 if (numericCodeMap
) {
346 uhash_close(numericCodeMap
);
350 uhash_close(regionIDMap
);
352 regionAliases
= numericCodeMap
= regionIDMap
= NULL
;
354 gRegionDataInitOnce
.reset();
360 containingRegion(NULL
),
361 containedRegions(NULL
),
362 preferredValues(NULL
) {
367 if (containedRegions
) {
368 delete containedRegions
;
370 if (preferredValues
) {
371 delete preferredValues
;
376 * Returns true if the two regions are equal.
377 * Per PMC, just use pointer compare, since we have at most one instance of each Region.
380 Region::operator==(const Region
&that
) const {
381 return (idStr
== that
.idStr
);
385 * Returns true if the two regions are NOT equal; that is, if operator ==() returns false.
386 * Per PMC, just use pointer compare, since we have at most one instance of each Region.
389 Region::operator!=(const Region
&that
) const {
390 return (idStr
!= that
.idStr
);
394 * Returns a pointer to a Region using the given region code. The region code can be either 2-letter ISO code,
395 * 3-letter ISO code, UNM.49 numeric code, or other valid Unicode Region Code as defined by the LDML specification.
396 * The identifier will be canonicalized internally using the supplemental metadata as defined in the CLDR.
397 * If the region code is NULL or not recognized, the appropriate error code will be set ( U_ILLEGAL_ARGUMENT_ERROR )
399 const Region
* U_EXPORT2
400 Region::getInstance(const char *region_code
, UErrorCode
&status
) {
402 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
);
403 if (U_FAILURE(status
)) {
407 if ( !region_code
) {
408 status
= U_ILLEGAL_ARGUMENT_ERROR
;
412 UnicodeString regionCodeString
= UnicodeString(region_code
, -1, US_INV
);
413 Region
*r
= (Region
*)uhash_get(regionIDMap
,(void *)®ionCodeString
);
416 r
= (Region
*)uhash_get(regionAliases
,(void *)®ionCodeString
);
419 if ( !r
) { // Unknown region code
420 status
= U_ILLEGAL_ARGUMENT_ERROR
;
424 if ( r
->type
== URGN_DEPRECATED
&& r
->preferredValues
->size() == 1) {
425 StringEnumeration
*pv
= r
->getPreferredValues(status
);
427 const UnicodeString
*ustr
= pv
->snext(status
);
428 r
= (Region
*)uhash_get(regionIDMap
,(void *)ustr
);
437 * Returns a pointer to a Region using the given numeric region code. If the numeric region code is not recognized,
438 * the appropriate error code will be set ( U_ILLEGAL_ARGUMENT_ERROR ).
440 const Region
* U_EXPORT2
441 Region::getInstance (int32_t code
, UErrorCode
&status
) {
443 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
);
444 if (U_FAILURE(status
)) {
448 Region
*r
= (Region
*)uhash_iget(numericCodeMap
,code
);
450 if ( !r
) { // Just in case there's an alias that's numeric, try to find it.
451 UErrorCode fs
= U_ZERO_ERROR
;
452 UnicodeString pat
= UNICODE_STRING_SIMPLE("00#");
453 LocalPointer
<DecimalFormat
> df(new DecimalFormat(pat
,fs
), status
);
454 if( U_FAILURE(status
) ) {
459 FieldPosition posIter
;
460 df
->format(code
,id
, posIter
, status
);
461 r
= (Region
*)uhash_get(regionAliases
,&id
);
464 if( U_FAILURE(status
) ) {
469 status
= U_ILLEGAL_ARGUMENT_ERROR
;
473 if ( r
->type
== URGN_DEPRECATED
&& r
->preferredValues
->size() == 1) {
474 StringEnumeration
*pv
= r
->getPreferredValues(status
);
476 const UnicodeString
*ustr
= pv
->snext(status
);
477 r
= (Region
*)uhash_get(regionIDMap
,(void *)ustr
);
486 * Returns an enumeration over the IDs of all known regions that match the given type.
488 StringEnumeration
* U_EXPORT2
489 Region::getAvailable(URegionType type
, UErrorCode
&status
) {
490 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
); // returns immediately if U_FAILURE(status)
491 if (U_FAILURE(status
)) {
494 return new RegionNameEnumeration(availableRegions
[type
],status
);
498 * Returns a pointer to the region that contains this region. Returns NULL if this region is code "001" (World)
499 * or "ZZ" (Unknown region). For example, calling this method with region "IT" (Italy) returns the
500 * region "039" (Southern Europe).
503 Region::getContainingRegion() const {
504 UErrorCode status
= U_ZERO_ERROR
;
505 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
);
506 return containingRegion
;
510 * Return a pointer to the region that geographically contains this region and matches the given type,
511 * moving multiple steps up the containment chain if necessary. Returns NULL if no containing region can be found
512 * that matches the given type. Note: The URegionTypes = "URGN_GROUPING", "URGN_DEPRECATED", or "URGN_UNKNOWN"
513 * are not appropriate for use in this API. NULL will be returned in this case. For example, calling this method
514 * with region "IT" (Italy) for type "URGN_CONTINENT" returns the region "150" ( Europe ).
517 Region::getContainingRegion(URegionType type
) const {
518 UErrorCode status
= U_ZERO_ERROR
;
519 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
);
520 if ( containingRegion
== NULL
) {
524 return ( containingRegion
->type
== type
)? containingRegion
: containingRegion
->getContainingRegion(type
);
528 * Return an enumeration over the IDs of all the regions that are immediate children of this region in the
529 * region hierarchy. These returned regions could be either macro regions, territories, or a mixture of the two,
530 * depending on the containment data as defined in CLDR. This API may return NULL if this region doesn't have
531 * any sub-regions. For example, calling this method with region "150" (Europe) returns an enumeration containing
532 * the various sub regions of Europe - "039" (Southern Europe) - "151" (Eastern Europe) - "154" (Northern Europe)
533 * and "155" (Western Europe).
536 Region::getContainedRegions(UErrorCode
&status
) const {
537 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
); // returns immediately if U_FAILURE(status)
538 if (U_FAILURE(status
)) {
541 return new RegionNameEnumeration(containedRegions
,status
);
545 * Returns an enumeration over the IDs of all the regions that are children of this region anywhere in the region
546 * hierarchy and match the given type. This API may return an empty enumeration if this region doesn't have any
547 * sub-regions that match the given type. For example, calling this method with region "150" (Europe) and type
548 * "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR" (France) - "IT" (Italy) - "DE" (Germany) etc. )
551 Region::getContainedRegions( URegionType type
, UErrorCode
&status
) const {
552 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
); // returns immediately if U_FAILURE(status)
553 if (U_FAILURE(status
)) {
557 UVector
*result
= new UVector(NULL
, uhash_compareChars
, status
);
559 StringEnumeration
*cr
= getContainedRegions(status
);
561 for ( int32_t i
= 0 ; i
< cr
->count(status
) ; i
++ ) {
562 const char *id
= cr
->next(NULL
,status
);
563 const Region
*r
= Region::getInstance(id
,status
);
564 if ( r
->getType() == type
) {
565 result
->addElement((void *)&r
->idStr
,status
);
567 StringEnumeration
*children
= r
->getContainedRegions(type
, status
);
568 for ( int32_t j
= 0 ; j
< children
->count(status
) ; j
++ ) {
569 const char *id2
= children
->next(NULL
,status
);
570 const Region
*r2
= Region::getInstance(id2
,status
);
571 result
->addElement((void *)&r2
->idStr
,status
);
577 StringEnumeration
* resultEnumeration
= new RegionNameEnumeration(result
,status
);
579 return resultEnumeration
;
583 * Returns true if this region contains the supplied other region anywhere in the region hierarchy.
586 Region::contains(const Region
&other
) const {
587 UErrorCode status
= U_ZERO_ERROR
;
588 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
);
590 if (!containedRegions
) {
593 if (containedRegions
->contains((void *)&other
.idStr
)) {
596 for ( int32_t i
= 0 ; i
< containedRegions
->size() ; i
++ ) {
597 UnicodeString
*crStr
= (UnicodeString
*)containedRegions
->elementAt(i
);
598 Region
*cr
= (Region
*) uhash_get(regionIDMap
,(void *)crStr
);
599 if ( cr
&& cr
->contains(other
) ) {
609 * For deprecated regions, return an enumeration over the IDs of the regions that are the preferred replacement
610 * regions for this region. Returns NULL for a non-deprecated region. For example, calling this method with region
611 * "SU" (Soviet Union) would return a list of the regions containing "RU" (Russia), "AM" (Armenia), "AZ" (Azerbaijan), etc...
614 Region::getPreferredValues(UErrorCode
&status
) const {
615 umtx_initOnce(gRegionDataInitOnce
, &loadRegionData
, status
); // returns immediately if U_FAILURE(status)
616 if (U_FAILURE(status
) || type
!= URGN_DEPRECATED
) {
619 return new RegionNameEnumeration(preferredValues
,status
);
624 * Return this region's canonical region code.
627 Region::getRegionCode() const {
632 Region::getNumericCode() const {
637 * Returns the region type of this region.
640 Region::getType() const {
644 RegionNameEnumeration::RegionNameEnumeration(UVector
*fNameList
, UErrorCode
& status
) {
646 if (fNameList
&& U_SUCCESS(status
)) {
647 fRegionNames
= new UVector(uprv_deleteUObject
, uhash_compareUnicodeString
, fNameList
->size(),status
);
648 for ( int32_t i
= 0 ; i
< fNameList
->size() ; i
++ ) {
649 UnicodeString
* this_region_name
= (UnicodeString
*)fNameList
->elementAt(i
);
650 UnicodeString
* new_region_name
= new UnicodeString(*this_region_name
);
651 fRegionNames
->addElement((void *)new_region_name
,status
);
660 RegionNameEnumeration::snext(UErrorCode
& status
) {
661 if (U_FAILURE(status
) || (fRegionNames
==NULL
)) {
664 const UnicodeString
* nextStr
= (const UnicodeString
*)fRegionNames
->elementAt(pos
);
672 RegionNameEnumeration::reset(UErrorCode
& /*status*/) {
677 RegionNameEnumeration::count(UErrorCode
& /*status*/) const {
678 return (fRegionNames
==NULL
) ? 0 : fRegionNames
->size();
681 RegionNameEnumeration::~RegionNameEnumeration() {
687 #endif /* #if !UCONFIG_NO_FORMATTING */