]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/region.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / region.cpp
index b88453a453e5693cd06d8b22909bd08fc2a18e2d..66de31de8b326198f88b99e87658a865bb28abde 100644 (file)
@@ -1,6 +1,8 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
 *******************************************************************************
-* Copyright (C) 2014-2015, International Business Machines Corporation and
+* Copyright (C) 2014-2016, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 *
@@ -62,10 +64,12 @@ static UVector* availableRegions[URGN_LIMIT];
 static UHashtable *regionAliases = NULL;
 static UHashtable *regionIDMap = NULL;
 static UHashtable *numericCodeMap = NULL;
+static UVector *allRegions = NULL;
 
 static const UChar UNKNOWN_REGION_ID [] = { 0x5A, 0x5A, 0 };  /* "ZZ" */
 static const UChar OUTLYING_OCEANIA_REGION_ID [] = { 0x51, 0x4F, 0 };  /* "QO" */
 static const UChar WORLD_ID [] = { 0x30, 0x30, 0x31, 0 };  /* "001" */
+static const UChar RANGE_MARKER = 0x7E; /* '~' */
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration)
 
@@ -77,25 +81,31 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration)
  * If the region data has already loaded, then this method simply returns without doing
  * anything meaningful.
  */
-void Region::loadRegionData(UErrorCode &status) {
+void U_CALLCONV Region::loadRegionData(UErrorCode &status) {
+
     // Construct service objs first
     LocalUHashtablePointer newRegionIDMap(uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status));
     LocalUHashtablePointer newNumericCodeMap(uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status));
     LocalUHashtablePointer newRegionAliases(uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status));
-
     LocalPointer<DecimalFormat> df(new DecimalFormat(status), status);
 
     LocalPointer<UVector> continents(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status);
     LocalPointer<UVector> groupings(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status);
+    allRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status);
 
     LocalUResourceBundlePointer metadata(ures_openDirect(NULL,"metadata",&status));
-    LocalUResourceBundlePointer regionCodes(ures_getByKey(metadata.getAlias(),"regionCodes",NULL,&status));
     LocalUResourceBundlePointer metadataAlias(ures_getByKey(metadata.getAlias(),"alias",NULL,&status));
     LocalUResourceBundlePointer territoryAlias(ures_getByKey(metadataAlias.getAlias(),"territory",NULL,&status));
 
     LocalUResourceBundlePointer supplementalData(ures_openDirect(NULL,"supplementalData",&status));
     LocalUResourceBundlePointer codeMappings(ures_getByKey(supplementalData.getAlias(),"codeMappings",NULL,&status));
 
+    LocalUResourceBundlePointer idValidity(ures_getByKey(supplementalData.getAlias(),"idValidity",NULL,&status));
+    LocalUResourceBundlePointer regionList(ures_getByKey(idValidity.getAlias(),"region",NULL,&status));
+    LocalUResourceBundlePointer regionRegular(ures_getByKey(regionList.getAlias(),"regular",NULL,&status));
+    LocalUResourceBundlePointer regionMacro(ures_getByKey(regionList.getAlias(),"macroregion",NULL,&status));
+    LocalUResourceBundlePointer regionUnknown(ures_getByKey(regionList.getAlias(),"unknown",NULL,&status));
+
     LocalUResourceBundlePointer territoryContainment(ures_getByKey(supplementalData.getAlias(),"territoryContainment",NULL,&status));
     LocalUResourceBundlePointer worldContainment(ures_getByKey(territoryContainment.getAlias(),"001",NULL,&status));
     LocalUResourceBundlePointer groupingContainment(ures_getByKey(territoryContainment.getAlias(),"grouping",NULL,&status));
@@ -109,6 +119,50 @@ void Region::loadRegionData(UErrorCode &status) {
     uhash_setValueDeleter(newRegionIDMap.getAlias(), deleteRegion);  // regionIDMap owns objs
     uhash_setKeyDeleter(newRegionAliases.getAlias(), uprv_deleteUObject); // regionAliases owns the string keys
 
+
+    while ( ures_hasNext(regionRegular.getAlias()) ) {
+        UnicodeString regionName = ures_getNextUnicodeString(regionRegular.getAlias(),NULL,&status);
+        int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER);
+        UChar buf[6];
+        regionName.extract(buf,6,status);
+        if ( rangeMarkerLocation > 0 ) {
+            UChar endRange = regionName.charAt(rangeMarkerLocation+1);
+            buf[rangeMarkerLocation] = 0;
+            while ( buf[rangeMarkerLocation-1] <= endRange ) {
+                LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status);
+                allRegions->addElement(newRegion.orphan(),status);
+                buf[rangeMarkerLocation-1]++;
+            }
+        } else {
+            LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status);
+            allRegions->addElement(newRegion.orphan(),status);
+        }
+    }
+
+    while ( ures_hasNext(regionMacro.getAlias()) ) {
+        UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),NULL,&status);
+        int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER);
+        UChar buf[6];
+        regionName.extract(buf,6,status);
+        if ( rangeMarkerLocation > 0 ) {
+            UChar endRange = regionName.charAt(rangeMarkerLocation+1);
+            buf[rangeMarkerLocation] = 0;
+            while ( buf[rangeMarkerLocation-1] <= endRange ) {
+                LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status);
+                allRegions->addElement(newRegion.orphan(),status);
+                buf[rangeMarkerLocation-1]++;
+            }
+        } else {
+            LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status);
+            allRegions->addElement(newRegion.orphan(),status);
+        }
+    }
+
+    while ( ures_hasNext(regionUnknown.getAlias()) ) {
+        LocalPointer<UnicodeString> regionName (new UnicodeString(ures_getNextUnicodeString(regionUnknown.getAlias(),NULL,&status),status));
+        allRegions->addElement(regionName.orphan(),status);
+    }
+
     while ( ures_hasNext(worldContainment.getAlias()) ) {
         UnicodeString *continentName = new UnicodeString(ures_getNextUnicodeString(worldContainment.getAlias(),NULL,&status));
         continents->addElement(continentName,status);
@@ -119,13 +173,14 @@ void Region::loadRegionData(UErrorCode &status) {
         groupings->addElement(groupingName,status);
     }
 
-    while ( ures_hasNext(regionCodes.getAlias()) ) {
-        UnicodeString regionID = ures_getNextUnicodeString(regionCodes.getAlias(), NULL, &status);
+    for ( int32_t i = 0 ; i < allRegions->size() ; i++ ) {
         LocalPointer<Region> r(new Region(), status);
         if ( U_FAILURE(status) ) {
            return;
         }
-        r->idStr = regionID;
+        UnicodeString *regionName = (UnicodeString *)allRegions->elementAt(i);
+        r->idStr = *regionName;
+
         r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV);
         r->type = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known.
 
@@ -143,7 +198,6 @@ void Region::loadRegionData(UErrorCode &status) {
         uhash_put(newRegionIDMap.getAlias(),idStrAlias,(void *)(r.orphan()),&status); // regionIDMap takes ownership
     }
 
-
     // Process the territory aliases
     while ( ures_hasNext(territoryAlias.getAlias()) ) {
         LocalUResourceBundlePointer res(ures_getNextResource(territoryAlias.getAlias(),NULL,&status));
@@ -349,6 +403,12 @@ void Region::cleanupRegionData() {
     if (regionIDMap) {
         uhash_close(regionIDMap);
     }
+    if (allRegions) {
+        allRegions->removeAllElements(); // Don't need the temporary list anymore.
+        delete allRegions;
+        allRegions = NULL;
+    }
+
     regionAliases = numericCodeMap = regionIDMap = NULL;
 
     gRegionDataInitOnce.reset();
@@ -448,9 +508,8 @@ Region::getInstance (int32_t code, UErrorCode &status) {
     Region *r = (Region *)uhash_iget(numericCodeMap,code);
 
     if ( !r ) { // Just in case there's an alias that's numeric, try to find it.
-        UErrorCode fs = U_ZERO_ERROR;
-        UnicodeString pat = UNICODE_STRING_SIMPLE("00#");
-        LocalPointer<DecimalFormat> df(new DecimalFormat(pat,fs), status);
+        UnicodeString pat = UNICODE_STRING_SIMPLE("0");
+        LocalPointer<DecimalFormat> df(new DecimalFormat(pat,status), status);
         if( U_FAILURE(status) ) {
             return NULL;
         }