12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci/* 42e5b6d6dSopenharmony_ci******************************************************************************* 52e5b6d6dSopenharmony_ci* Copyright (C) 2014-2016, International Business Machines Corporation and 62e5b6d6dSopenharmony_ci* others. All Rights Reserved. 72e5b6d6dSopenharmony_ci******************************************************************************* 82e5b6d6dSopenharmony_ci* 92e5b6d6dSopenharmony_ci* 102e5b6d6dSopenharmony_ci* File REGION.CPP 112e5b6d6dSopenharmony_ci* 122e5b6d6dSopenharmony_ci* Modification History:* 132e5b6d6dSopenharmony_ci* Date Name Description 142e5b6d6dSopenharmony_ci* 01/15/13 Emmons Original Port from ICU4J 152e5b6d6dSopenharmony_ci******************************************************************************** 162e5b6d6dSopenharmony_ci*/ 172e5b6d6dSopenharmony_ci 182e5b6d6dSopenharmony_ci/** 192e5b6d6dSopenharmony_ci * \file 202e5b6d6dSopenharmony_ci * \brief C++ API: Region classes (territory containment) 212e5b6d6dSopenharmony_ci */ 222e5b6d6dSopenharmony_ci 232e5b6d6dSopenharmony_ci#include "unicode/region.h" 242e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 252e5b6d6dSopenharmony_ci#include "unicode/uobject.h" 262e5b6d6dSopenharmony_ci#include "unicode/unistr.h" 272e5b6d6dSopenharmony_ci#include "unicode/ures.h" 282e5b6d6dSopenharmony_ci#include "ucln_in.h" 292e5b6d6dSopenharmony_ci#include "cstring.h" 302e5b6d6dSopenharmony_ci#include "mutex.h" 312e5b6d6dSopenharmony_ci#include "uhash.h" 322e5b6d6dSopenharmony_ci#include "umutex.h" 332e5b6d6dSopenharmony_ci#include "uresimp.h" 342e5b6d6dSopenharmony_ci#include "region_impl.h" 352e5b6d6dSopenharmony_ci#include "util.h" 362e5b6d6dSopenharmony_ci 372e5b6d6dSopenharmony_ci#if !UCONFIG_NO_FORMATTING 382e5b6d6dSopenharmony_ci 392e5b6d6dSopenharmony_ci 402e5b6d6dSopenharmony_ciU_CDECL_BEGIN 412e5b6d6dSopenharmony_ci 422e5b6d6dSopenharmony_ci/** 432e5b6d6dSopenharmony_ci * Cleanup callback func 442e5b6d6dSopenharmony_ci */ 452e5b6d6dSopenharmony_cistatic UBool U_CALLCONV region_cleanup(void) 462e5b6d6dSopenharmony_ci{ 472e5b6d6dSopenharmony_ci icu::Region::cleanupRegionData(); 482e5b6d6dSopenharmony_ci 492e5b6d6dSopenharmony_ci return true; 502e5b6d6dSopenharmony_ci} 512e5b6d6dSopenharmony_ci 522e5b6d6dSopenharmony_ciU_CDECL_END 532e5b6d6dSopenharmony_ci 542e5b6d6dSopenharmony_ciU_NAMESPACE_BEGIN 552e5b6d6dSopenharmony_ci 562e5b6d6dSopenharmony_cistatic UInitOnce gRegionDataInitOnce {}; 572e5b6d6dSopenharmony_cistatic UVector* availableRegions[URGN_LIMIT]; 582e5b6d6dSopenharmony_ci 592e5b6d6dSopenharmony_cistatic UHashtable *regionAliases = NULL; 602e5b6d6dSopenharmony_cistatic UHashtable *regionIDMap = NULL; 612e5b6d6dSopenharmony_cistatic UHashtable *numericCodeMap = NULL; 622e5b6d6dSopenharmony_cistatic UVector *allRegions = NULL; 632e5b6d6dSopenharmony_ci 642e5b6d6dSopenharmony_cistatic const UChar UNKNOWN_REGION_ID [] = { 0x5A, 0x5A, 0 }; /* "ZZ" */ 652e5b6d6dSopenharmony_cistatic const UChar OUTLYING_OCEANIA_REGION_ID [] = { 0x51, 0x4F, 0 }; /* "QO" */ 662e5b6d6dSopenharmony_cistatic const UChar WORLD_ID [] = { 0x30, 0x30, 0x31, 0 }; /* "001" */ 672e5b6d6dSopenharmony_cistatic const UChar RANGE_MARKER = 0x7E; /* '~' */ 682e5b6d6dSopenharmony_ci 692e5b6d6dSopenharmony_ciUOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration) 702e5b6d6dSopenharmony_ci 712e5b6d6dSopenharmony_ci/* 722e5b6d6dSopenharmony_ci * Initializes the region data from the ICU resource bundles. The region data 732e5b6d6dSopenharmony_ci * contains the basic relationships such as which regions are known, what the numeric 742e5b6d6dSopenharmony_ci * codes are, any known aliases, and the territory containment data. 752e5b6d6dSopenharmony_ci * 762e5b6d6dSopenharmony_ci * If the region data has already loaded, then this method simply returns without doing 772e5b6d6dSopenharmony_ci * anything meaningful. 782e5b6d6dSopenharmony_ci */ 792e5b6d6dSopenharmony_civoid U_CALLCONV Region::loadRegionData(UErrorCode &status) { 802e5b6d6dSopenharmony_ci 812e5b6d6dSopenharmony_ci // Construct service objs first 822e5b6d6dSopenharmony_ci LocalUHashtablePointer newRegionIDMap(uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status)); 832e5b6d6dSopenharmony_ci LocalUHashtablePointer newNumericCodeMap(uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status)); 842e5b6d6dSopenharmony_ci LocalUHashtablePointer newRegionAliases(uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status)); 852e5b6d6dSopenharmony_ci 862e5b6d6dSopenharmony_ci LocalPointer<UVector> continents(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); 872e5b6d6dSopenharmony_ci LocalPointer<UVector> groupings(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); 882e5b6d6dSopenharmony_ci LocalPointer<UVector> lpAllRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); 892e5b6d6dSopenharmony_ci allRegions = lpAllRegions.orphan(); 902e5b6d6dSopenharmony_ci 912e5b6d6dSopenharmony_ci LocalUResourceBundlePointer metadata(ures_openDirect(NULL,"metadata",&status)); 922e5b6d6dSopenharmony_ci LocalUResourceBundlePointer metadataAlias(ures_getByKey(metadata.getAlias(),"alias",NULL,&status)); 932e5b6d6dSopenharmony_ci LocalUResourceBundlePointer territoryAlias(ures_getByKey(metadataAlias.getAlias(),"territory",NULL,&status)); 942e5b6d6dSopenharmony_ci 952e5b6d6dSopenharmony_ci LocalUResourceBundlePointer supplementalData(ures_openDirect(NULL,"supplementalData",&status)); 962e5b6d6dSopenharmony_ci LocalUResourceBundlePointer codeMappings(ures_getByKey(supplementalData.getAlias(),"codeMappings",NULL,&status)); 972e5b6d6dSopenharmony_ci 982e5b6d6dSopenharmony_ci LocalUResourceBundlePointer idValidity(ures_getByKey(supplementalData.getAlias(),"idValidity",NULL,&status)); 992e5b6d6dSopenharmony_ci LocalUResourceBundlePointer regionList(ures_getByKey(idValidity.getAlias(),"region",NULL,&status)); 1002e5b6d6dSopenharmony_ci LocalUResourceBundlePointer regionRegular(ures_getByKey(regionList.getAlias(),"regular",NULL,&status)); 1012e5b6d6dSopenharmony_ci LocalUResourceBundlePointer regionMacro(ures_getByKey(regionList.getAlias(),"macroregion",NULL,&status)); 1022e5b6d6dSopenharmony_ci LocalUResourceBundlePointer regionUnknown(ures_getByKey(regionList.getAlias(),"unknown",NULL,&status)); 1032e5b6d6dSopenharmony_ci 1042e5b6d6dSopenharmony_ci LocalUResourceBundlePointer territoryContainment(ures_getByKey(supplementalData.getAlias(),"territoryContainment",NULL,&status)); 1052e5b6d6dSopenharmony_ci LocalUResourceBundlePointer worldContainment(ures_getByKey(territoryContainment.getAlias(),"001",NULL,&status)); 1062e5b6d6dSopenharmony_ci LocalUResourceBundlePointer groupingContainment(ures_getByKey(territoryContainment.getAlias(),"grouping",NULL,&status)); 1072e5b6d6dSopenharmony_ci 1082e5b6d6dSopenharmony_ci ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); 1092e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 1102e5b6d6dSopenharmony_ci return; 1112e5b6d6dSopenharmony_ci } 1122e5b6d6dSopenharmony_ci 1132e5b6d6dSopenharmony_ci // now, initialize 1142e5b6d6dSopenharmony_ci uhash_setValueDeleter(newRegionIDMap.getAlias(), uprv_deleteUObject); // regionIDMap owns objs 1152e5b6d6dSopenharmony_ci uhash_setKeyDeleter(newRegionAliases.getAlias(), uprv_deleteUObject); // regionAliases owns the string keys 1162e5b6d6dSopenharmony_ci 1172e5b6d6dSopenharmony_ci 1182e5b6d6dSopenharmony_ci while (U_SUCCESS(status) && ures_hasNext(regionRegular.getAlias())) { 1192e5b6d6dSopenharmony_ci UnicodeString regionName = ures_getNextUnicodeString(regionRegular.getAlias(),NULL,&status); 1202e5b6d6dSopenharmony_ci int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); 1212e5b6d6dSopenharmony_ci UChar buf[6]; 1222e5b6d6dSopenharmony_ci regionName.extract(buf,6,status); 1232e5b6d6dSopenharmony_ci if ( rangeMarkerLocation > 0 ) { 1242e5b6d6dSopenharmony_ci UChar endRange = regionName.charAt(rangeMarkerLocation+1); 1252e5b6d6dSopenharmony_ci buf[rangeMarkerLocation] = 0; 1262e5b6d6dSopenharmony_ci while (U_SUCCESS(status) && buf[rangeMarkerLocation-1] <= endRange) { 1272e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status); 1282e5b6d6dSopenharmony_ci allRegions->adoptElement(newRegion.orphan(), status); 1292e5b6d6dSopenharmony_ci buf[rangeMarkerLocation-1]++; 1302e5b6d6dSopenharmony_ci } 1312e5b6d6dSopenharmony_ci } else { 1322e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status); 1332e5b6d6dSopenharmony_ci allRegions->adoptElement(newRegion.orphan(), status); 1342e5b6d6dSopenharmony_ci } 1352e5b6d6dSopenharmony_ci } 1362e5b6d6dSopenharmony_ci 1372e5b6d6dSopenharmony_ci while (U_SUCCESS(status) && ures_hasNext(regionMacro.getAlias())) { 1382e5b6d6dSopenharmony_ci UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),NULL,&status); 1392e5b6d6dSopenharmony_ci int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); 1402e5b6d6dSopenharmony_ci UChar buf[6]; 1412e5b6d6dSopenharmony_ci regionName.extract(buf,6,status); 1422e5b6d6dSopenharmony_ci if ( rangeMarkerLocation > 0 ) { 1432e5b6d6dSopenharmony_ci UChar endRange = regionName.charAt(rangeMarkerLocation+1); 1442e5b6d6dSopenharmony_ci buf[rangeMarkerLocation] = 0; 1452e5b6d6dSopenharmony_ci while ( buf[rangeMarkerLocation-1] <= endRange && U_SUCCESS(status)) { 1462e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status); 1472e5b6d6dSopenharmony_ci allRegions->adoptElement(newRegion.orphan(),status); 1482e5b6d6dSopenharmony_ci buf[rangeMarkerLocation-1]++; 1492e5b6d6dSopenharmony_ci } 1502e5b6d6dSopenharmony_ci } else { 1512e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status); 1522e5b6d6dSopenharmony_ci allRegions->adoptElement(newRegion.orphan(),status); 1532e5b6d6dSopenharmony_ci } 1542e5b6d6dSopenharmony_ci } 1552e5b6d6dSopenharmony_ci 1562e5b6d6dSopenharmony_ci while (U_SUCCESS(status) && ures_hasNext(regionUnknown.getAlias())) { 1572e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> regionName ( 1582e5b6d6dSopenharmony_ci new UnicodeString(ures_getNextUnicodeString(regionUnknown.getAlias(), nullptr, &status), status)); 1592e5b6d6dSopenharmony_ci allRegions->adoptElement(regionName.orphan(),status); 1602e5b6d6dSopenharmony_ci } 1612e5b6d6dSopenharmony_ci 1622e5b6d6dSopenharmony_ci while (U_SUCCESS(status) && ures_hasNext(worldContainment.getAlias())) { 1632e5b6d6dSopenharmony_ci UnicodeString *continentName = new UnicodeString(ures_getNextUnicodeString(worldContainment.getAlias(),NULL,&status)); 1642e5b6d6dSopenharmony_ci continents->adoptElement(continentName,status); 1652e5b6d6dSopenharmony_ci } 1662e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 1672e5b6d6dSopenharmony_ci return; 1682e5b6d6dSopenharmony_ci } 1692e5b6d6dSopenharmony_ci 1702e5b6d6dSopenharmony_ci for ( int32_t i = 0 ; i < allRegions->size() ; i++ ) { 1712e5b6d6dSopenharmony_ci LocalPointer<Region> r(new Region(), status); 1722e5b6d6dSopenharmony_ci if ( U_FAILURE(status) ) { 1732e5b6d6dSopenharmony_ci return; 1742e5b6d6dSopenharmony_ci } 1752e5b6d6dSopenharmony_ci UnicodeString *regionName = (UnicodeString *)allRegions->elementAt(i); 1762e5b6d6dSopenharmony_ci r->idStr = *regionName; 1772e5b6d6dSopenharmony_ci 1782e5b6d6dSopenharmony_ci r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV); 1792e5b6d6dSopenharmony_ci r->fType = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known. 1802e5b6d6dSopenharmony_ci 1812e5b6d6dSopenharmony_ci int32_t pos = 0; 1822e5b6d6dSopenharmony_ci int32_t result = ICU_Utility::parseAsciiInteger(r->idStr, pos); 1832e5b6d6dSopenharmony_ci if (pos > 0) { 1842e5b6d6dSopenharmony_ci r->code = result; // Convert string to number 1852e5b6d6dSopenharmony_ci uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)(r.getAlias()),&status); 1862e5b6d6dSopenharmony_ci r->fType = URGN_SUBCONTINENT; 1872e5b6d6dSopenharmony_ci } else { 1882e5b6d6dSopenharmony_ci r->code = -1; 1892e5b6d6dSopenharmony_ci } 1902e5b6d6dSopenharmony_ci void* idStrAlias = (void*)&(r->idStr); // about to orphan 'r'. Save this off. 1912e5b6d6dSopenharmony_ci uhash_put(newRegionIDMap.getAlias(),idStrAlias,(void *)(r.orphan()),&status); // regionIDMap takes ownership 1922e5b6d6dSopenharmony_ci } 1932e5b6d6dSopenharmony_ci 1942e5b6d6dSopenharmony_ci UResourceBundle *groupingBundle = nullptr; 1952e5b6d6dSopenharmony_ci while (U_SUCCESS(status) && ures_hasNext(groupingContainment.getAlias())) { 1962e5b6d6dSopenharmony_ci groupingBundle = ures_getNextResource(groupingContainment.getAlias(), groupingBundle, &status); 1972e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 1982e5b6d6dSopenharmony_ci break; 1992e5b6d6dSopenharmony_ci } 2002e5b6d6dSopenharmony_ci UnicodeString *groupingName = new UnicodeString(ures_getKey(groupingBundle), -1, US_INV); 2012e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> lpGroupingName(groupingName, status); 2022e5b6d6dSopenharmony_ci groupings->adoptElement(lpGroupingName.orphan(), status); 2032e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 2042e5b6d6dSopenharmony_ci break; 2052e5b6d6dSopenharmony_ci } 2062e5b6d6dSopenharmony_ci Region *grouping = (Region *) uhash_get(newRegionIDMap.getAlias(), groupingName); 2072e5b6d6dSopenharmony_ci if (grouping != NULL) { 2082e5b6d6dSopenharmony_ci for (int32_t i = 0; i < ures_getSize(groupingBundle) && U_SUCCESS(status); i++) { 2092e5b6d6dSopenharmony_ci UnicodeString child = ures_getUnicodeStringByIndex(groupingBundle, i, &status); 2102e5b6d6dSopenharmony_ci if (U_SUCCESS(status)) { 2112e5b6d6dSopenharmony_ci if (grouping->containedRegions == NULL) { 2122e5b6d6dSopenharmony_ci LocalPointer<UVector> lpContainedRegions( 2132e5b6d6dSopenharmony_ci new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); 2142e5b6d6dSopenharmony_ci grouping->containedRegions = lpContainedRegions.orphan(); 2152e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 2162e5b6d6dSopenharmony_ci break; 2172e5b6d6dSopenharmony_ci } 2182e5b6d6dSopenharmony_ci } 2192e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> lpChildCopy(new UnicodeString(child), status); 2202e5b6d6dSopenharmony_ci grouping->containedRegions->adoptElement(lpChildCopy.orphan(), status); 2212e5b6d6dSopenharmony_ci } 2222e5b6d6dSopenharmony_ci } 2232e5b6d6dSopenharmony_ci } 2242e5b6d6dSopenharmony_ci } 2252e5b6d6dSopenharmony_ci ures_close(groupingBundle); 2262e5b6d6dSopenharmony_ci 2272e5b6d6dSopenharmony_ci // Process the territory aliases 2282e5b6d6dSopenharmony_ci while (U_SUCCESS(status) && ures_hasNext(territoryAlias.getAlias())) { 2292e5b6d6dSopenharmony_ci LocalUResourceBundlePointer res(ures_getNextResource(territoryAlias.getAlias(),NULL,&status)); 2302e5b6d6dSopenharmony_ci const char *aliasFrom = ures_getKey(res.getAlias()); 2312e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> aliasFromStr(new UnicodeString(aliasFrom, -1, US_INV), status); 2322e5b6d6dSopenharmony_ci UnicodeString aliasTo = ures_getUnicodeStringByKey(res.getAlias(),"replacement",&status); 2332e5b6d6dSopenharmony_ci res.adoptInstead(NULL); 2342e5b6d6dSopenharmony_ci 2352e5b6d6dSopenharmony_ci const Region *aliasToRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),&aliasTo); 2362e5b6d6dSopenharmony_ci Region *aliasFromRegion = (Region *)uhash_get(newRegionIDMap.getAlias(),aliasFromStr.getAlias()); 2372e5b6d6dSopenharmony_ci 2382e5b6d6dSopenharmony_ci if ( aliasToRegion != NULL && aliasFromRegion == NULL ) { // This is just an alias from some string to a region 2392e5b6d6dSopenharmony_ci uhash_put(newRegionAliases.getAlias(),(void *)aliasFromStr.orphan(), (void *)aliasToRegion,&status); 2402e5b6d6dSopenharmony_ci } else { 2412e5b6d6dSopenharmony_ci if ( aliasFromRegion == NULL ) { // Deprecated region code not in the primary codes list - so need to create a deprecated region for it. 2422e5b6d6dSopenharmony_ci LocalPointer<Region> newRgn(new Region, status); 2432e5b6d6dSopenharmony_ci if ( U_SUCCESS(status) ) { 2442e5b6d6dSopenharmony_ci aliasFromRegion = newRgn.orphan(); 2452e5b6d6dSopenharmony_ci } else { 2462e5b6d6dSopenharmony_ci return; // error out 2472e5b6d6dSopenharmony_ci } 2482e5b6d6dSopenharmony_ci aliasFromRegion->idStr.setTo(*aliasFromStr); 2492e5b6d6dSopenharmony_ci aliasFromRegion->idStr.extract(0,aliasFromRegion->idStr.length(),aliasFromRegion->id,sizeof(aliasFromRegion->id),US_INV); 2502e5b6d6dSopenharmony_ci uhash_put(newRegionIDMap.getAlias(),(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status); 2512e5b6d6dSopenharmony_ci int32_t pos = 0; 2522e5b6d6dSopenharmony_ci int32_t result = ICU_Utility::parseAsciiInteger(aliasFromRegion->idStr, pos); 2532e5b6d6dSopenharmony_ci if ( pos > 0 ) { 2542e5b6d6dSopenharmony_ci aliasFromRegion->code = result; // Convert string to number 2552e5b6d6dSopenharmony_ci uhash_iput(newNumericCodeMap.getAlias(),aliasFromRegion->code,(void *)aliasFromRegion,&status); 2562e5b6d6dSopenharmony_ci } else { 2572e5b6d6dSopenharmony_ci aliasFromRegion->code = -1; 2582e5b6d6dSopenharmony_ci } 2592e5b6d6dSopenharmony_ci aliasFromRegion->fType = URGN_DEPRECATED; 2602e5b6d6dSopenharmony_ci } else { 2612e5b6d6dSopenharmony_ci aliasFromRegion->fType = URGN_DEPRECATED; 2622e5b6d6dSopenharmony_ci } 2632e5b6d6dSopenharmony_ci 2642e5b6d6dSopenharmony_ci { 2652e5b6d6dSopenharmony_ci LocalPointer<UVector> newPreferredValues(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); 2662e5b6d6dSopenharmony_ci aliasFromRegion->preferredValues = newPreferredValues.orphan(); 2672e5b6d6dSopenharmony_ci } 2682e5b6d6dSopenharmony_ci if( U_FAILURE(status)) { 2692e5b6d6dSopenharmony_ci return; 2702e5b6d6dSopenharmony_ci } 2712e5b6d6dSopenharmony_ci UnicodeString currentRegion; 2722e5b6d6dSopenharmony_ci //currentRegion.remove(); TODO: was already 0 length? 2732e5b6d6dSopenharmony_ci for (int32_t i = 0 ; i < aliasTo.length() && U_SUCCESS(status); i++ ) { 2742e5b6d6dSopenharmony_ci if ( aliasTo.charAt(i) != 0x0020 ) { 2752e5b6d6dSopenharmony_ci currentRegion.append(aliasTo.charAt(i)); 2762e5b6d6dSopenharmony_ci } 2772e5b6d6dSopenharmony_ci if ( aliasTo.charAt(i) == 0x0020 || i+1 == aliasTo.length() ) { 2782e5b6d6dSopenharmony_ci Region *target = (Region *)uhash_get(newRegionIDMap.getAlias(),(void *)¤tRegion); 2792e5b6d6dSopenharmony_ci if (target) { 2802e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> preferredValue(new UnicodeString(target->idStr), status); 2812e5b6d6dSopenharmony_ci aliasFromRegion->preferredValues->adoptElement(preferredValue.orphan(),status); // may add null if err 2822e5b6d6dSopenharmony_ci } 2832e5b6d6dSopenharmony_ci currentRegion.remove(); 2842e5b6d6dSopenharmony_ci } 2852e5b6d6dSopenharmony_ci } 2862e5b6d6dSopenharmony_ci } 2872e5b6d6dSopenharmony_ci } 2882e5b6d6dSopenharmony_ci 2892e5b6d6dSopenharmony_ci // Process the code mappings - This will allow us to assign numeric codes to most of the territories. 2902e5b6d6dSopenharmony_ci while (U_SUCCESS(status) && ures_hasNext(codeMappings.getAlias())) { 2912e5b6d6dSopenharmony_ci UResourceBundle *mapping = ures_getNextResource(codeMappings.getAlias(),NULL,&status); 2922e5b6d6dSopenharmony_ci if (U_SUCCESS(status) && ures_getType(mapping) == URES_ARRAY && ures_getSize(mapping) == 3) { 2932e5b6d6dSopenharmony_ci UnicodeString codeMappingID = ures_getUnicodeStringByIndex(mapping,0,&status); 2942e5b6d6dSopenharmony_ci UnicodeString codeMappingNumber = ures_getUnicodeStringByIndex(mapping,1,&status); 2952e5b6d6dSopenharmony_ci UnicodeString codeMapping3Letter = ures_getUnicodeStringByIndex(mapping,2,&status); 2962e5b6d6dSopenharmony_ci 2972e5b6d6dSopenharmony_ci Region *r = (Region *)uhash_get(newRegionIDMap.getAlias(),(void *)&codeMappingID); 2982e5b6d6dSopenharmony_ci if ( r ) { 2992e5b6d6dSopenharmony_ci int32_t pos = 0; 3002e5b6d6dSopenharmony_ci int32_t result = ICU_Utility::parseAsciiInteger(codeMappingNumber, pos); 3012e5b6d6dSopenharmony_ci if ( pos > 0 ) { 3022e5b6d6dSopenharmony_ci r->code = result; // Convert string to number 3032e5b6d6dSopenharmony_ci uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)r,&status); 3042e5b6d6dSopenharmony_ci } 3052e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> code3(new UnicodeString(codeMapping3Letter), status); 3062e5b6d6dSopenharmony_ci uhash_put(newRegionAliases.getAlias(),(void *)code3.orphan(), (void *)r,&status); 3072e5b6d6dSopenharmony_ci } 3082e5b6d6dSopenharmony_ci } 3092e5b6d6dSopenharmony_ci ures_close(mapping); 3102e5b6d6dSopenharmony_ci } 3112e5b6d6dSopenharmony_ci 3122e5b6d6dSopenharmony_ci // Now fill in the special cases for WORLD, UNKNOWN, CONTINENTS, and GROUPINGS 3132e5b6d6dSopenharmony_ci Region *r; 3142e5b6d6dSopenharmony_ci UnicodeString WORLD_ID_STRING(WORLD_ID); 3152e5b6d6dSopenharmony_ci r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&WORLD_ID_STRING); 3162e5b6d6dSopenharmony_ci if ( r ) { 3172e5b6d6dSopenharmony_ci r->fType = URGN_WORLD; 3182e5b6d6dSopenharmony_ci } 3192e5b6d6dSopenharmony_ci 3202e5b6d6dSopenharmony_ci UnicodeString UNKNOWN_REGION_ID_STRING(UNKNOWN_REGION_ID); 3212e5b6d6dSopenharmony_ci r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&UNKNOWN_REGION_ID_STRING); 3222e5b6d6dSopenharmony_ci if ( r ) { 3232e5b6d6dSopenharmony_ci r->fType = URGN_UNKNOWN; 3242e5b6d6dSopenharmony_ci } 3252e5b6d6dSopenharmony_ci 3262e5b6d6dSopenharmony_ci for ( int32_t i = 0 ; i < continents->size() ; i++ ) { 3272e5b6d6dSopenharmony_ci r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)continents->elementAt(i)); 3282e5b6d6dSopenharmony_ci if ( r ) { 3292e5b6d6dSopenharmony_ci r->fType = URGN_CONTINENT; 3302e5b6d6dSopenharmony_ci } 3312e5b6d6dSopenharmony_ci } 3322e5b6d6dSopenharmony_ci 3332e5b6d6dSopenharmony_ci for ( int32_t i = 0 ; i < groupings->size() ; i++ ) { 3342e5b6d6dSopenharmony_ci r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)groupings->elementAt(i)); 3352e5b6d6dSopenharmony_ci if ( r ) { 3362e5b6d6dSopenharmony_ci r->fType = URGN_GROUPING; 3372e5b6d6dSopenharmony_ci } 3382e5b6d6dSopenharmony_ci } 3392e5b6d6dSopenharmony_ci 3402e5b6d6dSopenharmony_ci // Special case: The region code "QO" (Outlying Oceania) is a subcontinent code added by CLDR 3412e5b6d6dSopenharmony_ci // even though it looks like a territory code. Need to handle it here. 3422e5b6d6dSopenharmony_ci 3432e5b6d6dSopenharmony_ci UnicodeString OUTLYING_OCEANIA_REGION_ID_STRING(OUTLYING_OCEANIA_REGION_ID); 3442e5b6d6dSopenharmony_ci r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&OUTLYING_OCEANIA_REGION_ID_STRING); 3452e5b6d6dSopenharmony_ci if ( r ) { 3462e5b6d6dSopenharmony_ci r->fType = URGN_SUBCONTINENT; 3472e5b6d6dSopenharmony_ci } 3482e5b6d6dSopenharmony_ci 3492e5b6d6dSopenharmony_ci // Load territory containment info from the supplemental data. 3502e5b6d6dSopenharmony_ci while ( ures_hasNext(territoryContainment.getAlias()) ) { 3512e5b6d6dSopenharmony_ci LocalUResourceBundlePointer mapping(ures_getNextResource(territoryContainment.getAlias(),NULL,&status)); 3522e5b6d6dSopenharmony_ci if( U_FAILURE(status) ) { 3532e5b6d6dSopenharmony_ci return; // error out 3542e5b6d6dSopenharmony_ci } 3552e5b6d6dSopenharmony_ci const char *parent = ures_getKey(mapping.getAlias()); 3562e5b6d6dSopenharmony_ci if (uprv_strcmp(parent, "containedGroupings") == 0 || uprv_strcmp(parent, "deprecated") == 0) { 3572e5b6d6dSopenharmony_ci continue; // handle new pseudo-parent types added in ICU data per cldrbug 7808; for now just skip. 3582e5b6d6dSopenharmony_ci // #11232 is to do something useful with these. 3592e5b6d6dSopenharmony_ci } 3602e5b6d6dSopenharmony_ci UnicodeString parentStr = UnicodeString(parent, -1 , US_INV); 3612e5b6d6dSopenharmony_ci Region *parentRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&parentStr); 3622e5b6d6dSopenharmony_ci 3632e5b6d6dSopenharmony_ci for ( int j = 0 ; j < ures_getSize(mapping.getAlias()); j++ ) { 3642e5b6d6dSopenharmony_ci UnicodeString child = ures_getUnicodeStringByIndex(mapping.getAlias(),j,&status); 3652e5b6d6dSopenharmony_ci Region *childRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&child); 3662e5b6d6dSopenharmony_ci if ( parentRegion != NULL && childRegion != NULL ) { 3672e5b6d6dSopenharmony_ci 3682e5b6d6dSopenharmony_ci // Add the child region to the set of regions contained by the parent 3692e5b6d6dSopenharmony_ci if (parentRegion->containedRegions == NULL) { 3702e5b6d6dSopenharmony_ci LocalPointer<UVector> lpContainedRegions( 3712e5b6d6dSopenharmony_ci new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); 3722e5b6d6dSopenharmony_ci parentRegion->containedRegions = lpContainedRegions.orphan(); 3732e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 3742e5b6d6dSopenharmony_ci return; 3752e5b6d6dSopenharmony_ci } 3762e5b6d6dSopenharmony_ci } 3772e5b6d6dSopenharmony_ci 3782e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> childStr(new UnicodeString(), status); 3792e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 3802e5b6d6dSopenharmony_ci return; // error out 3812e5b6d6dSopenharmony_ci } 3822e5b6d6dSopenharmony_ci childStr->fastCopyFrom(childRegion->idStr); 3832e5b6d6dSopenharmony_ci parentRegion->containedRegions->adoptElement(childStr.orphan(),status); 3842e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 3852e5b6d6dSopenharmony_ci return; 3862e5b6d6dSopenharmony_ci } 3872e5b6d6dSopenharmony_ci 3882e5b6d6dSopenharmony_ci // Set the parent region to be the containing region of the child. 3892e5b6d6dSopenharmony_ci // Regions of type GROUPING can't be set as the parent, since another region 3902e5b6d6dSopenharmony_ci // such as a SUBCONTINENT, CONTINENT, or WORLD must always be the parent. 3912e5b6d6dSopenharmony_ci if ( parentRegion->fType != URGN_GROUPING) { 3922e5b6d6dSopenharmony_ci childRegion->containingRegion = parentRegion; 3932e5b6d6dSopenharmony_ci } 3942e5b6d6dSopenharmony_ci } 3952e5b6d6dSopenharmony_ci } 3962e5b6d6dSopenharmony_ci } 3972e5b6d6dSopenharmony_ci 3982e5b6d6dSopenharmony_ci // Create the availableRegions lists 3992e5b6d6dSopenharmony_ci int32_t pos = UHASH_FIRST; 4002e5b6d6dSopenharmony_ci while ( const UHashElement* element = uhash_nextElement(newRegionIDMap.getAlias(),&pos)) { 4012e5b6d6dSopenharmony_ci Region *ar = (Region *)element->value.pointer; 4022e5b6d6dSopenharmony_ci if ( availableRegions[ar->fType] == NULL ) { 4032e5b6d6dSopenharmony_ci LocalPointer<UVector> newAr(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); 4042e5b6d6dSopenharmony_ci availableRegions[ar->fType] = newAr.orphan(); 4052e5b6d6dSopenharmony_ci } 4062e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> arString(new UnicodeString(ar->idStr), status); 4072e5b6d6dSopenharmony_ci if( U_FAILURE(status) ) { 4082e5b6d6dSopenharmony_ci return; // error out 4092e5b6d6dSopenharmony_ci } 4102e5b6d6dSopenharmony_ci availableRegions[ar->fType]->adoptElement(arString.orphan(), status); 4112e5b6d6dSopenharmony_ci } 4122e5b6d6dSopenharmony_ci 4132e5b6d6dSopenharmony_ci // copy hashtables 4142e5b6d6dSopenharmony_ci numericCodeMap = newNumericCodeMap.orphan(); 4152e5b6d6dSopenharmony_ci regionIDMap = newRegionIDMap.orphan(); 4162e5b6d6dSopenharmony_ci regionAliases = newRegionAliases.orphan(); 4172e5b6d6dSopenharmony_ci} 4182e5b6d6dSopenharmony_ci 4192e5b6d6dSopenharmony_civoid Region::cleanupRegionData() { 4202e5b6d6dSopenharmony_ci for (int32_t i = 0 ; i < URGN_LIMIT ; i++ ) { 4212e5b6d6dSopenharmony_ci if ( availableRegions[i] ) { 4222e5b6d6dSopenharmony_ci delete availableRegions[i]; 4232e5b6d6dSopenharmony_ci availableRegions[i] = nullptr; 4242e5b6d6dSopenharmony_ci } 4252e5b6d6dSopenharmony_ci } 4262e5b6d6dSopenharmony_ci 4272e5b6d6dSopenharmony_ci if (regionAliases) { 4282e5b6d6dSopenharmony_ci uhash_close(regionAliases); 4292e5b6d6dSopenharmony_ci } 4302e5b6d6dSopenharmony_ci 4312e5b6d6dSopenharmony_ci if (numericCodeMap) { 4322e5b6d6dSopenharmony_ci uhash_close(numericCodeMap); 4332e5b6d6dSopenharmony_ci } 4342e5b6d6dSopenharmony_ci 4352e5b6d6dSopenharmony_ci if (regionIDMap) { 4362e5b6d6dSopenharmony_ci uhash_close(regionIDMap); 4372e5b6d6dSopenharmony_ci } 4382e5b6d6dSopenharmony_ci if (allRegions) { 4392e5b6d6dSopenharmony_ci delete allRegions; 4402e5b6d6dSopenharmony_ci allRegions = NULL; 4412e5b6d6dSopenharmony_ci } 4422e5b6d6dSopenharmony_ci 4432e5b6d6dSopenharmony_ci regionAliases = numericCodeMap = regionIDMap = NULL; 4442e5b6d6dSopenharmony_ci 4452e5b6d6dSopenharmony_ci gRegionDataInitOnce.reset(); 4462e5b6d6dSopenharmony_ci} 4472e5b6d6dSopenharmony_ci 4482e5b6d6dSopenharmony_ciRegion::Region () 4492e5b6d6dSopenharmony_ci : code(-1), 4502e5b6d6dSopenharmony_ci fType(URGN_UNKNOWN), 4512e5b6d6dSopenharmony_ci containingRegion(NULL), 4522e5b6d6dSopenharmony_ci containedRegions(NULL), 4532e5b6d6dSopenharmony_ci preferredValues(NULL) { 4542e5b6d6dSopenharmony_ci id[0] = 0; 4552e5b6d6dSopenharmony_ci} 4562e5b6d6dSopenharmony_ci 4572e5b6d6dSopenharmony_ciRegion::~Region () { 4582e5b6d6dSopenharmony_ci if (containedRegions) { 4592e5b6d6dSopenharmony_ci delete containedRegions; 4602e5b6d6dSopenharmony_ci } 4612e5b6d6dSopenharmony_ci if (preferredValues) { 4622e5b6d6dSopenharmony_ci delete preferredValues; 4632e5b6d6dSopenharmony_ci } 4642e5b6d6dSopenharmony_ci} 4652e5b6d6dSopenharmony_ci 4662e5b6d6dSopenharmony_ci/** 4672e5b6d6dSopenharmony_ci * Returns true if the two regions are equal. 4682e5b6d6dSopenharmony_ci * Per PMC, just use pointer compare, since we have at most one instance of each Region. 4692e5b6d6dSopenharmony_ci */ 4702e5b6d6dSopenharmony_cibool 4712e5b6d6dSopenharmony_ciRegion::operator==(const Region &that) const { 4722e5b6d6dSopenharmony_ci return (idStr == that.idStr); 4732e5b6d6dSopenharmony_ci} 4742e5b6d6dSopenharmony_ci 4752e5b6d6dSopenharmony_ci/** 4762e5b6d6dSopenharmony_ci * Returns true if the two regions are NOT equal; that is, if operator ==() returns false. 4772e5b6d6dSopenharmony_ci * Per PMC, just use pointer compare, since we have at most one instance of each Region. 4782e5b6d6dSopenharmony_ci */ 4792e5b6d6dSopenharmony_cibool 4802e5b6d6dSopenharmony_ciRegion::operator!=(const Region &that) const { 4812e5b6d6dSopenharmony_ci return (idStr != that.idStr); 4822e5b6d6dSopenharmony_ci} 4832e5b6d6dSopenharmony_ci 4842e5b6d6dSopenharmony_ci/** 4852e5b6d6dSopenharmony_ci * Returns a pointer to a Region using the given region code. The region code can be either 2-letter ISO code, 4862e5b6d6dSopenharmony_ci * 3-letter ISO code, UNM.49 numeric code, or other valid Unicode Region Code as defined by the LDML specification. 4872e5b6d6dSopenharmony_ci * The identifier will be canonicalized internally using the supplemental metadata as defined in the CLDR. 4882e5b6d6dSopenharmony_ci * If the region code is NULL or not recognized, the appropriate error code will be set ( U_ILLEGAL_ARGUMENT_ERROR ) 4892e5b6d6dSopenharmony_ci */ 4902e5b6d6dSopenharmony_ciconst Region* U_EXPORT2 4912e5b6d6dSopenharmony_ciRegion::getInstance(const char *region_code, UErrorCode &status) { 4922e5b6d6dSopenharmony_ci 4932e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); 4942e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 4952e5b6d6dSopenharmony_ci return NULL; 4962e5b6d6dSopenharmony_ci } 4972e5b6d6dSopenharmony_ci 4982e5b6d6dSopenharmony_ci if ( !region_code ) { 4992e5b6d6dSopenharmony_ci status = U_ILLEGAL_ARGUMENT_ERROR; 5002e5b6d6dSopenharmony_ci return NULL; 5012e5b6d6dSopenharmony_ci } 5022e5b6d6dSopenharmony_ci 5032e5b6d6dSopenharmony_ci UnicodeString regionCodeString = UnicodeString(region_code, -1, US_INV); 5042e5b6d6dSopenharmony_ci Region *r = (Region *)uhash_get(regionIDMap,(void *)®ionCodeString); 5052e5b6d6dSopenharmony_ci 5062e5b6d6dSopenharmony_ci if ( !r ) { 5072e5b6d6dSopenharmony_ci r = (Region *)uhash_get(regionAliases,(void *)®ionCodeString); 5082e5b6d6dSopenharmony_ci } 5092e5b6d6dSopenharmony_ci 5102e5b6d6dSopenharmony_ci if ( !r ) { // Unknown region code 5112e5b6d6dSopenharmony_ci status = U_ILLEGAL_ARGUMENT_ERROR; 5122e5b6d6dSopenharmony_ci return NULL; 5132e5b6d6dSopenharmony_ci } 5142e5b6d6dSopenharmony_ci 5152e5b6d6dSopenharmony_ci if ( r->fType == URGN_DEPRECATED && r->preferredValues->size() == 1) { 5162e5b6d6dSopenharmony_ci StringEnumeration *pv = r->getPreferredValues(status); 5172e5b6d6dSopenharmony_ci pv->reset(status); 5182e5b6d6dSopenharmony_ci const UnicodeString *ustr = pv->snext(status); 5192e5b6d6dSopenharmony_ci r = (Region *)uhash_get(regionIDMap,(void *)ustr); 5202e5b6d6dSopenharmony_ci delete pv; 5212e5b6d6dSopenharmony_ci } 5222e5b6d6dSopenharmony_ci 5232e5b6d6dSopenharmony_ci return r; 5242e5b6d6dSopenharmony_ci 5252e5b6d6dSopenharmony_ci} 5262e5b6d6dSopenharmony_ci 5272e5b6d6dSopenharmony_ci/** 5282e5b6d6dSopenharmony_ci * Returns a pointer to a Region using the given numeric region code. If the numeric region code is not recognized, 5292e5b6d6dSopenharmony_ci * the appropriate error code will be set ( U_ILLEGAL_ARGUMENT_ERROR ). 5302e5b6d6dSopenharmony_ci */ 5312e5b6d6dSopenharmony_ciconst Region* U_EXPORT2 5322e5b6d6dSopenharmony_ciRegion::getInstance (int32_t code, UErrorCode &status) { 5332e5b6d6dSopenharmony_ci 5342e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); 5352e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 5362e5b6d6dSopenharmony_ci return NULL; 5372e5b6d6dSopenharmony_ci } 5382e5b6d6dSopenharmony_ci 5392e5b6d6dSopenharmony_ci Region *r = (Region *)uhash_iget(numericCodeMap,code); 5402e5b6d6dSopenharmony_ci 5412e5b6d6dSopenharmony_ci if ( !r ) { // Just in case there's an alias that's numeric, try to find it. 5422e5b6d6dSopenharmony_ci UnicodeString id; 5432e5b6d6dSopenharmony_ci ICU_Utility::appendNumber(id, code, 10, 1); 5442e5b6d6dSopenharmony_ci r = (Region *)uhash_get(regionAliases,&id); 5452e5b6d6dSopenharmony_ci } 5462e5b6d6dSopenharmony_ci 5472e5b6d6dSopenharmony_ci if( U_FAILURE(status) ) { 5482e5b6d6dSopenharmony_ci return NULL; 5492e5b6d6dSopenharmony_ci } 5502e5b6d6dSopenharmony_ci 5512e5b6d6dSopenharmony_ci if ( !r ) { 5522e5b6d6dSopenharmony_ci status = U_ILLEGAL_ARGUMENT_ERROR; 5532e5b6d6dSopenharmony_ci return NULL; 5542e5b6d6dSopenharmony_ci } 5552e5b6d6dSopenharmony_ci 5562e5b6d6dSopenharmony_ci if ( r->fType == URGN_DEPRECATED && r->preferredValues->size() == 1) { 5572e5b6d6dSopenharmony_ci StringEnumeration *pv = r->getPreferredValues(status); 5582e5b6d6dSopenharmony_ci pv->reset(status); 5592e5b6d6dSopenharmony_ci const UnicodeString *ustr = pv->snext(status); 5602e5b6d6dSopenharmony_ci r = (Region *)uhash_get(regionIDMap,(void *)ustr); 5612e5b6d6dSopenharmony_ci delete pv; 5622e5b6d6dSopenharmony_ci } 5632e5b6d6dSopenharmony_ci 5642e5b6d6dSopenharmony_ci return r; 5652e5b6d6dSopenharmony_ci} 5662e5b6d6dSopenharmony_ci 5672e5b6d6dSopenharmony_ci 5682e5b6d6dSopenharmony_ci/** 5692e5b6d6dSopenharmony_ci * Returns an enumeration over the IDs of all known regions that match the given type. 5702e5b6d6dSopenharmony_ci */ 5712e5b6d6dSopenharmony_ciStringEnumeration* U_EXPORT2 5722e5b6d6dSopenharmony_ciRegion::getAvailable(URegionType type, UErrorCode &status) { 5732e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) 5742e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 5752e5b6d6dSopenharmony_ci return NULL; 5762e5b6d6dSopenharmony_ci } 5772e5b6d6dSopenharmony_ci return new RegionNameEnumeration(availableRegions[type],status); 5782e5b6d6dSopenharmony_ci} 5792e5b6d6dSopenharmony_ci 5802e5b6d6dSopenharmony_ci/** 5812e5b6d6dSopenharmony_ci * Returns a pointer to the region that contains this region. Returns NULL if this region is code "001" (World) 5822e5b6d6dSopenharmony_ci * or "ZZ" (Unknown region). For example, calling this method with region "IT" (Italy) returns the 5832e5b6d6dSopenharmony_ci * region "039" (Southern Europe). 5842e5b6d6dSopenharmony_ci */ 5852e5b6d6dSopenharmony_ciconst Region* 5862e5b6d6dSopenharmony_ciRegion::getContainingRegion() const { 5872e5b6d6dSopenharmony_ci UErrorCode status = U_ZERO_ERROR; 5882e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); 5892e5b6d6dSopenharmony_ci return containingRegion; 5902e5b6d6dSopenharmony_ci} 5912e5b6d6dSopenharmony_ci 5922e5b6d6dSopenharmony_ci/** 5932e5b6d6dSopenharmony_ci * Return a pointer to the region that geographically contains this region and matches the given type, 5942e5b6d6dSopenharmony_ci * moving multiple steps up the containment chain if necessary. Returns NULL if no containing region can be found 5952e5b6d6dSopenharmony_ci * that matches the given type. Note: The URegionTypes = "URGN_GROUPING", "URGN_DEPRECATED", or "URGN_UNKNOWN" 5962e5b6d6dSopenharmony_ci * are not appropriate for use in this API. NULL will be returned in this case. For example, calling this method 5972e5b6d6dSopenharmony_ci * with region "IT" (Italy) for type "URGN_CONTINENT" returns the region "150" ( Europe ). 5982e5b6d6dSopenharmony_ci */ 5992e5b6d6dSopenharmony_ciconst Region* 6002e5b6d6dSopenharmony_ciRegion::getContainingRegion(URegionType type) const { 6012e5b6d6dSopenharmony_ci UErrorCode status = U_ZERO_ERROR; 6022e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); 6032e5b6d6dSopenharmony_ci if ( containingRegion == NULL ) { 6042e5b6d6dSopenharmony_ci return NULL; 6052e5b6d6dSopenharmony_ci } 6062e5b6d6dSopenharmony_ci 6072e5b6d6dSopenharmony_ci return ( containingRegion->fType == type)? containingRegion: containingRegion->getContainingRegion(type); 6082e5b6d6dSopenharmony_ci} 6092e5b6d6dSopenharmony_ci 6102e5b6d6dSopenharmony_ci/** 6112e5b6d6dSopenharmony_ci * Return an enumeration over the IDs of all the regions that are immediate children of this region in the 6122e5b6d6dSopenharmony_ci * region hierarchy. These returned regions could be either macro regions, territories, or a mixture of the two, 6132e5b6d6dSopenharmony_ci * depending on the containment data as defined in CLDR. This API may return NULL if this region doesn't have 6142e5b6d6dSopenharmony_ci * any sub-regions. For example, calling this method with region "150" (Europe) returns an enumeration containing 6152e5b6d6dSopenharmony_ci * the various sub regions of Europe - "039" (Southern Europe) - "151" (Eastern Europe) - "154" (Northern Europe) 6162e5b6d6dSopenharmony_ci * and "155" (Western Europe). 6172e5b6d6dSopenharmony_ci */ 6182e5b6d6dSopenharmony_ciStringEnumeration* 6192e5b6d6dSopenharmony_ciRegion::getContainedRegions(UErrorCode &status) const { 6202e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) 6212e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 6222e5b6d6dSopenharmony_ci return NULL; 6232e5b6d6dSopenharmony_ci } 6242e5b6d6dSopenharmony_ci return new RegionNameEnumeration(containedRegions,status); 6252e5b6d6dSopenharmony_ci} 6262e5b6d6dSopenharmony_ci 6272e5b6d6dSopenharmony_ci/** 6282e5b6d6dSopenharmony_ci * Returns an enumeration over the IDs of all the regions that are children of this region anywhere in the region 6292e5b6d6dSopenharmony_ci * hierarchy and match the given type. This API may return an empty enumeration if this region doesn't have any 6302e5b6d6dSopenharmony_ci * sub-regions that match the given type. For example, calling this method with region "150" (Europe) and type 6312e5b6d6dSopenharmony_ci * "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR" (France) - "IT" (Italy) - "DE" (Germany) etc. ) 6322e5b6d6dSopenharmony_ci */ 6332e5b6d6dSopenharmony_ciStringEnumeration* 6342e5b6d6dSopenharmony_ciRegion::getContainedRegions( URegionType type, UErrorCode &status ) const { 6352e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) 6362e5b6d6dSopenharmony_ci 6372e5b6d6dSopenharmony_ci UVector result(nullptr, uhash_compareChars, status); 6382e5b6d6dSopenharmony_ci LocalPointer<StringEnumeration> cr(getContainedRegions(status), status); 6392e5b6d6dSopenharmony_ci if (U_FAILURE(status)) { 6402e5b6d6dSopenharmony_ci return nullptr; 6412e5b6d6dSopenharmony_ci } 6422e5b6d6dSopenharmony_ci 6432e5b6d6dSopenharmony_ci const char *regionId; 6442e5b6d6dSopenharmony_ci while((regionId = cr->next(nullptr, status)) != nullptr && U_SUCCESS(status)) { 6452e5b6d6dSopenharmony_ci const Region *r = Region::getInstance(regionId, status); 6462e5b6d6dSopenharmony_ci if ( r->getType() == type) { 6472e5b6d6dSopenharmony_ci result.addElement(const_cast<UnicodeString *>(&r->idStr), status); 6482e5b6d6dSopenharmony_ci } else { 6492e5b6d6dSopenharmony_ci LocalPointer<StringEnumeration> children(r->getContainedRegions(type, status)); 6502e5b6d6dSopenharmony_ci const char *id2; 6512e5b6d6dSopenharmony_ci while(U_SUCCESS(status) && ((id2 = children->next(nullptr, status)) != nullptr)) { 6522e5b6d6dSopenharmony_ci const Region *r2 = Region::getInstance(id2,status); 6532e5b6d6dSopenharmony_ci result.addElement(const_cast<UnicodeString *>(&r2->idStr), status); 6542e5b6d6dSopenharmony_ci } 6552e5b6d6dSopenharmony_ci } 6562e5b6d6dSopenharmony_ci } 6572e5b6d6dSopenharmony_ci LocalPointer<StringEnumeration> resultEnumeration( 6582e5b6d6dSopenharmony_ci new RegionNameEnumeration(&result, status), status); 6592e5b6d6dSopenharmony_ci return U_SUCCESS(status) ? resultEnumeration.orphan() : nullptr; 6602e5b6d6dSopenharmony_ci} 6612e5b6d6dSopenharmony_ci 6622e5b6d6dSopenharmony_ci/** 6632e5b6d6dSopenharmony_ci * Returns true if this region contains the supplied other region anywhere in the region hierarchy. 6642e5b6d6dSopenharmony_ci */ 6652e5b6d6dSopenharmony_ciUBool 6662e5b6d6dSopenharmony_ciRegion::contains(const Region &other) const { 6672e5b6d6dSopenharmony_ci UErrorCode status = U_ZERO_ERROR; 6682e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); 6692e5b6d6dSopenharmony_ci 6702e5b6d6dSopenharmony_ci if (!containedRegions) { 6712e5b6d6dSopenharmony_ci return false; 6722e5b6d6dSopenharmony_ci } 6732e5b6d6dSopenharmony_ci if (containedRegions->contains((void *)&other.idStr)) { 6742e5b6d6dSopenharmony_ci return true; 6752e5b6d6dSopenharmony_ci } else { 6762e5b6d6dSopenharmony_ci for ( int32_t i = 0 ; i < containedRegions->size() ; i++ ) { 6772e5b6d6dSopenharmony_ci UnicodeString *crStr = (UnicodeString *)containedRegions->elementAt(i); 6782e5b6d6dSopenharmony_ci Region *cr = (Region *) uhash_get(regionIDMap,(void *)crStr); 6792e5b6d6dSopenharmony_ci if ( cr && cr->contains(other) ) { 6802e5b6d6dSopenharmony_ci return true; 6812e5b6d6dSopenharmony_ci } 6822e5b6d6dSopenharmony_ci } 6832e5b6d6dSopenharmony_ci } 6842e5b6d6dSopenharmony_ci 6852e5b6d6dSopenharmony_ci return false; 6862e5b6d6dSopenharmony_ci} 6872e5b6d6dSopenharmony_ci 6882e5b6d6dSopenharmony_ci/** 6892e5b6d6dSopenharmony_ci * For deprecated regions, return an enumeration over the IDs of the regions that are the preferred replacement 6902e5b6d6dSopenharmony_ci * regions for this region. Returns NULL for a non-deprecated region. For example, calling this method with region 6912e5b6d6dSopenharmony_ci * "SU" (Soviet Union) would return a list of the regions containing "RU" (Russia), "AM" (Armenia), "AZ" (Azerbaijan), etc... 6922e5b6d6dSopenharmony_ci */ 6932e5b6d6dSopenharmony_ciStringEnumeration* 6942e5b6d6dSopenharmony_ciRegion::getPreferredValues(UErrorCode &status) const { 6952e5b6d6dSopenharmony_ci umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) 6962e5b6d6dSopenharmony_ci if (U_FAILURE(status) || fType != URGN_DEPRECATED) { 6972e5b6d6dSopenharmony_ci return NULL; 6982e5b6d6dSopenharmony_ci } 6992e5b6d6dSopenharmony_ci return new RegionNameEnumeration(preferredValues,status); 7002e5b6d6dSopenharmony_ci} 7012e5b6d6dSopenharmony_ci 7022e5b6d6dSopenharmony_ci 7032e5b6d6dSopenharmony_ci/** 7042e5b6d6dSopenharmony_ci * Return this region's canonical region code. 7052e5b6d6dSopenharmony_ci */ 7062e5b6d6dSopenharmony_ciconst char* 7072e5b6d6dSopenharmony_ciRegion::getRegionCode() const { 7082e5b6d6dSopenharmony_ci return id; 7092e5b6d6dSopenharmony_ci} 7102e5b6d6dSopenharmony_ci 7112e5b6d6dSopenharmony_ciint32_t 7122e5b6d6dSopenharmony_ciRegion::getNumericCode() const { 7132e5b6d6dSopenharmony_ci return code; 7142e5b6d6dSopenharmony_ci} 7152e5b6d6dSopenharmony_ci 7162e5b6d6dSopenharmony_ci/** 7172e5b6d6dSopenharmony_ci * Returns the region type of this region. 7182e5b6d6dSopenharmony_ci */ 7192e5b6d6dSopenharmony_ciURegionType 7202e5b6d6dSopenharmony_ciRegion::getType() const { 7212e5b6d6dSopenharmony_ci return fType; 7222e5b6d6dSopenharmony_ci} 7232e5b6d6dSopenharmony_ci 7242e5b6d6dSopenharmony_ciRegionNameEnumeration::RegionNameEnumeration(UVector *nameList, UErrorCode& status) : 7252e5b6d6dSopenharmony_ci pos(0), fRegionNames(nullptr) { 7262e5b6d6dSopenharmony_ci // TODO: https://unicode-org.atlassian.net/browse/ICU-21829 7272e5b6d6dSopenharmony_ci // Is all of the copying going on here really necessary? 7282e5b6d6dSopenharmony_ci if (nameList && U_SUCCESS(status)) { 7292e5b6d6dSopenharmony_ci LocalPointer<UVector> regionNames( 7302e5b6d6dSopenharmony_ci new UVector(uprv_deleteUObject, uhash_compareUnicodeString, nameList->size(), status), status); 7312e5b6d6dSopenharmony_ci for ( int32_t i = 0 ; U_SUCCESS(status) && i < nameList->size() ; i++ ) { 7322e5b6d6dSopenharmony_ci UnicodeString* this_region_name = (UnicodeString *)nameList->elementAt(i); 7332e5b6d6dSopenharmony_ci LocalPointer<UnicodeString> new_region_name(new UnicodeString(*this_region_name), status); 7342e5b6d6dSopenharmony_ci regionNames->adoptElement(new_region_name.orphan(), status); 7352e5b6d6dSopenharmony_ci } 7362e5b6d6dSopenharmony_ci if (U_SUCCESS(status)) { 7372e5b6d6dSopenharmony_ci fRegionNames = regionNames.orphan(); 7382e5b6d6dSopenharmony_ci } 7392e5b6d6dSopenharmony_ci } 7402e5b6d6dSopenharmony_ci} 7412e5b6d6dSopenharmony_ci 7422e5b6d6dSopenharmony_ciconst UnicodeString* 7432e5b6d6dSopenharmony_ciRegionNameEnumeration::snext(UErrorCode& status) { 7442e5b6d6dSopenharmony_ci if (U_FAILURE(status) || (fRegionNames==NULL)) { 7452e5b6d6dSopenharmony_ci return NULL; 7462e5b6d6dSopenharmony_ci } 7472e5b6d6dSopenharmony_ci const UnicodeString* nextStr = (const UnicodeString *)fRegionNames->elementAt(pos); 7482e5b6d6dSopenharmony_ci if (nextStr!=NULL) { 7492e5b6d6dSopenharmony_ci pos++; 7502e5b6d6dSopenharmony_ci } 7512e5b6d6dSopenharmony_ci return nextStr; 7522e5b6d6dSopenharmony_ci} 7532e5b6d6dSopenharmony_ci 7542e5b6d6dSopenharmony_civoid 7552e5b6d6dSopenharmony_ciRegionNameEnumeration::reset(UErrorCode& /*status*/) { 7562e5b6d6dSopenharmony_ci pos=0; 7572e5b6d6dSopenharmony_ci} 7582e5b6d6dSopenharmony_ci 7592e5b6d6dSopenharmony_ciint32_t 7602e5b6d6dSopenharmony_ciRegionNameEnumeration::count(UErrorCode& /*status*/) const { 7612e5b6d6dSopenharmony_ci return (fRegionNames==NULL) ? 0 : fRegionNames->size(); 7622e5b6d6dSopenharmony_ci} 7632e5b6d6dSopenharmony_ci 7642e5b6d6dSopenharmony_ciRegionNameEnumeration::~RegionNameEnumeration() { 7652e5b6d6dSopenharmony_ci delete fRegionNames; 7662e5b6d6dSopenharmony_ci} 7672e5b6d6dSopenharmony_ci 7682e5b6d6dSopenharmony_ciU_NAMESPACE_END 7692e5b6d6dSopenharmony_ci 7702e5b6d6dSopenharmony_ci#endif /* #if !UCONFIG_NO_FORMATTING */ 7712e5b6d6dSopenharmony_ci 7722e5b6d6dSopenharmony_ci//eof 773