Index: source/i18n/region.cpp |
diff --git a/source/i18n/region.cpp b/source/i18n/region.cpp |
index 21123a16322845b84d5f1a8248727ff4571d8fbd..085f70434997836de40783d9fa5ba8a352e0bafb 100644 |
--- a/source/i18n/region.cpp |
+++ b/source/i18n/region.cpp |
@@ -1,6 +1,6 @@ |
/* |
******************************************************************************* |
-* Copyright (C) 2014, International Business Machines Corporation and |
+* Copyright (C) 2014-2015, International Business Machines Corporation and |
* others. All Rights Reserved. |
******************************************************************************* |
* |
@@ -59,13 +59,16 @@ U_NAMESPACE_BEGIN |
static UInitOnce gRegionDataInitOnce = U_INITONCE_INITIALIZER; |
static UVector* availableRegions[URGN_LIMIT]; |
-static UHashtable *regionAliases; |
-static UHashtable *regionIDMap; |
-static UHashtable *numericCodeMap; |
+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, 0 }; /* "~" */ |
+static const UnicodeString RANGE_MARKER_STRING(RANGE_MARKER); |
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration) |
@@ -78,108 +81,152 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration) |
* anything meaningful. |
*/ |
void Region::loadRegionData(UErrorCode &status) { |
- LocalPointer<DecimalFormat> df(new DecimalFormat(status)); |
- if (U_FAILURE(status)) { |
- return; |
- } |
- if (df == NULL) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
- } |
- df->setParseIntegerOnly(TRUE); |
- regionIDMap = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status); |
- if (U_FAILURE(status)) { |
- return; |
- } |
- if (regionIDMap == NULL) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
- } |
- uhash_setValueDeleter(regionIDMap, deleteRegion); |
+ // 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); |
- numericCodeMap = uhash_open(uhash_hashLong,uhash_compareLong,NULL,&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); |
- regionAliases = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status); |
- if (U_FAILURE(status)) { |
- return; |
- } |
- if (regionAliases == NULL) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
- } |
- uhash_setKeyDeleter(regionAliases,uprv_deleteUObject); |
+ LocalUResourceBundlePointer metadata(ures_openDirect(NULL,"metadata",&status)); |
+ LocalUResourceBundlePointer metadataAlias(ures_getByKey(metadata.getAlias(),"alias",NULL,&status)); |
+ LocalUResourceBundlePointer territoryAlias(ures_getByKey(metadataAlias.getAlias(),"territory",NULL,&status)); |
- LocalUResourceBundlePointer rb(ures_openDirect(NULL,"metadata",&status)); |
- LocalUResourceBundlePointer regionCodes(ures_getByKey(rb.getAlias(),"regionCodes",NULL,&status)); |
- LocalUResourceBundlePointer territoryAlias(ures_getByKey(rb.getAlias(),"territoryAlias",NULL,&status)); |
+ LocalUResourceBundlePointer supplementalData(ures_openDirect(NULL,"supplementalData",&status)); |
+ LocalUResourceBundlePointer codeMappings(ures_getByKey(supplementalData.getAlias(),"codeMappings",NULL,&status)); |
- LocalUResourceBundlePointer rb2(ures_openDirect(NULL,"supplementalData",&status)); |
- LocalUResourceBundlePointer codeMappings(ures_getByKey(rb2.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(rb2.getAlias(),"territoryContainment",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)); |
- UVector *continents = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ |
+ // now, initialize |
+ df->setParseIntegerOnly(TRUE); |
+ 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_STRING); |
+ 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_STRING); |
+ 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); |
} |
- UVector *groupings = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); |
while ( ures_hasNext(groupingContainment.getAlias()) ) { |
UnicodeString *groupingName = new UnicodeString(ures_getNextUnicodeString(groupingContainment.getAlias(),NULL,&status)); |
groupings->addElement(groupingName,status); |
} |
- while ( ures_hasNext(regionCodes.getAlias()) ) { |
- UnicodeString regionID = ures_getNextUnicodeString(regionCodes.getAlias(), NULL, &status); |
- Region *r = new Region(); |
- r->idStr = regionID; |
+ for ( int32_t i = 0 ; i < allRegions->size() ; i++ ) { |
+ LocalPointer<Region> r(new Region(), status); |
+ if ( U_FAILURE(status) ) { |
+ return; |
+ } |
+ 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. |
- uhash_put(regionIDMap,(void *)&(r->idStr),(void *)r,&status); |
Formattable result; |
UErrorCode ps = U_ZERO_ERROR; |
df->parse(r->idStr,result,ps); |
if ( U_SUCCESS(ps) ) { |
r->code = result.getLong(); // Convert string to number |
- uhash_iput(numericCodeMap,r->code,(void *)r,&status); |
+ uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)(r.getAlias()),&status); |
r->type = URGN_SUBCONTINENT; |
} else { |
r->code = -1; |
} |
+ void* idStrAlias = (void*)&(r->idStr); // about to orphan 'r'. Save this off. |
+ uhash_put(newRegionIDMap.getAlias(),idStrAlias,(void *)(r.orphan()),&status); // regionIDMap takes ownership |
} |
- |
// Process the territory aliases |
while ( ures_hasNext(territoryAlias.getAlias()) ) { |
- UResourceBundle *res = ures_getNextResource(territoryAlias.getAlias(),NULL,&status); |
- const char *aliasFrom = ures_getKey(res); |
- UnicodeString* aliasFromStr = new UnicodeString(aliasFrom, -1, US_INV); |
- UnicodeString aliasTo = ures_getUnicodeString(res,&status); |
- ures_close(res); |
+ LocalUResourceBundlePointer res(ures_getNextResource(territoryAlias.getAlias(),NULL,&status)); |
+ const char *aliasFrom = ures_getKey(res.getAlias()); |
+ LocalPointer<UnicodeString> aliasFromStr(new UnicodeString(aliasFrom, -1, US_INV), status); |
+ UnicodeString aliasTo = ures_getUnicodeStringByKey(res.getAlias(),"replacement",&status); |
+ res.adoptInstead(NULL); |
- Region *aliasToRegion = (Region *) uhash_get(regionIDMap,&aliasTo); |
- Region *aliasFromRegion = (Region *)uhash_get(regionIDMap,aliasFromStr); |
+ const Region *aliasToRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),&aliasTo); |
+ Region *aliasFromRegion = (Region *)uhash_get(newRegionIDMap.getAlias(),aliasFromStr.getAlias()); |
if ( aliasToRegion != NULL && aliasFromRegion == NULL ) { // This is just an alias from some string to a region |
- uhash_put(regionAliases,(void *)aliasFromStr, (void *)aliasToRegion,&status); |
+ uhash_put(newRegionAliases.getAlias(),(void *)aliasFromStr.orphan(), (void *)aliasToRegion,&status); |
} else { |
if ( aliasFromRegion == NULL ) { // Deprecated region code not in the master codes list - so need to create a deprecated region for it. |
- aliasFromRegion = new Region(); |
+ LocalPointer<Region> newRgn(new Region, status); |
+ if ( U_SUCCESS(status) ) { |
+ aliasFromRegion = newRgn.orphan(); |
+ } else { |
+ return; // error out |
+ } |
aliasFromRegion->idStr.setTo(*aliasFromStr); |
aliasFromRegion->idStr.extract(0,aliasFromRegion->idStr.length(),aliasFromRegion->id,sizeof(aliasFromRegion->id),US_INV); |
- uhash_put(regionIDMap,(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status); |
+ uhash_put(newRegionIDMap.getAlias(),(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status); |
Formattable result; |
UErrorCode ps = U_ZERO_ERROR; |
df->parse(aliasFromRegion->idStr,result,ps); |
if ( U_SUCCESS(ps) ) { |
aliasFromRegion->code = result.getLong(); // Convert string to number |
- uhash_iput(numericCodeMap,aliasFromRegion->code,(void *)aliasFromRegion,&status); |
+ uhash_iput(newNumericCodeMap.getAlias(),aliasFromRegion->code,(void *)aliasFromRegion,&status); |
} else { |
aliasFromRegion->code = -1; |
} |
@@ -187,20 +234,25 @@ void Region::loadRegionData(UErrorCode &status) { |
} else { |
aliasFromRegion->type = URGN_DEPRECATED; |
} |
- delete aliasFromStr; |
- aliasFromRegion->preferredValues = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); |
+ { |
+ LocalPointer<UVector> newPreferredValues(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); |
+ aliasFromRegion->preferredValues = newPreferredValues.orphan(); |
+ } |
+ if( U_FAILURE(status)) { |
+ return; |
+ } |
UnicodeString currentRegion; |
- currentRegion.remove(); |
+ //currentRegion.remove(); TODO: was already 0 length? |
for (int32_t i = 0 ; i < aliasTo.length() ; i++ ) { |
if ( aliasTo.charAt(i) != 0x0020 ) { |
currentRegion.append(aliasTo.charAt(i)); |
} |
if ( aliasTo.charAt(i) == 0x0020 || i+1 == aliasTo.length() ) { |
- Region *target = (Region *)uhash_get(regionIDMap,(void *)¤tRegion); |
+ Region *target = (Region *)uhash_get(newRegionIDMap.getAlias(),(void *)¤tRegion); |
if (target) { |
- UnicodeString *preferredValue = new UnicodeString(target->idStr); |
- aliasFromRegion->preferredValues->addElement((void *)preferredValue,status); |
+ LocalPointer<UnicodeString> preferredValue(new UnicodeString(target->idStr), status); |
+ aliasFromRegion->preferredValues->addElement((void *)preferredValue.orphan(),status); // may add null if err |
} |
currentRegion.remove(); |
} |
@@ -216,17 +268,17 @@ void Region::loadRegionData(UErrorCode &status) { |
UnicodeString codeMappingNumber = ures_getUnicodeStringByIndex(mapping,1,&status); |
UnicodeString codeMapping3Letter = ures_getUnicodeStringByIndex(mapping,2,&status); |
- Region *r = (Region *)uhash_get(regionIDMap,(void *)&codeMappingID); |
+ Region *r = (Region *)uhash_get(newRegionIDMap.getAlias(),(void *)&codeMappingID); |
if ( r ) { |
Formattable result; |
UErrorCode ps = U_ZERO_ERROR; |
df->parse(codeMappingNumber,result,ps); |
if ( U_SUCCESS(ps) ) { |
r->code = result.getLong(); // Convert string to number |
- uhash_iput(numericCodeMap,r->code,(void *)r,&status); |
+ uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)r,&status); |
} |
- UnicodeString *code3 = new UnicodeString(codeMapping3Letter); |
- uhash_put(regionAliases,(void *)code3, (void *)r,&status); |
+ LocalPointer<UnicodeString> code3(new UnicodeString(codeMapping3Letter), status); |
+ uhash_put(newRegionAliases.getAlias(),(void *)code3.orphan(), (void *)r,&status); |
} |
} |
ures_close(mapping); |
@@ -234,58 +286,58 @@ void Region::loadRegionData(UErrorCode &status) { |
// Now fill in the special cases for WORLD, UNKNOWN, CONTINENTS, and GROUPINGS |
Region *r; |
- UnicodeString WORLD_ID_STRING(WORLD_ID); |
- r = (Region *) uhash_get(regionIDMap,(void *)&WORLD_ID_STRING); |
+ UnicodeString WORLD_ID_STRING(WORLD_ID); |
+ r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&WORLD_ID_STRING); |
if ( r ) { |
r->type = URGN_WORLD; |
} |
- UnicodeString UNKNOWN_REGION_ID_STRING(UNKNOWN_REGION_ID); |
- r = (Region *) uhash_get(regionIDMap,(void *)&UNKNOWN_REGION_ID_STRING); |
+ UnicodeString UNKNOWN_REGION_ID_STRING(UNKNOWN_REGION_ID); |
+ r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&UNKNOWN_REGION_ID_STRING); |
if ( r ) { |
r->type = URGN_UNKNOWN; |
} |
for ( int32_t i = 0 ; i < continents->size() ; i++ ) { |
- r = (Region *) uhash_get(regionIDMap,(void *)continents->elementAt(i)); |
+ r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)continents->elementAt(i)); |
if ( r ) { |
r->type = URGN_CONTINENT; |
} |
} |
- delete continents; |
for ( int32_t i = 0 ; i < groupings->size() ; i++ ) { |
- r = (Region *) uhash_get(regionIDMap,(void *)groupings->elementAt(i)); |
+ r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)groupings->elementAt(i)); |
if ( r ) { |
r->type = URGN_GROUPING; |
} |
} |
- delete groupings; |
// Special case: The region code "QO" (Outlying Oceania) is a subcontinent code added by CLDR |
// even though it looks like a territory code. Need to handle it here. |
- UnicodeString OUTLYING_OCEANIA_REGION_ID_STRING(OUTLYING_OCEANIA_REGION_ID); |
- r = (Region *) uhash_get(regionIDMap,(void *)&OUTLYING_OCEANIA_REGION_ID_STRING); |
+ UnicodeString OUTLYING_OCEANIA_REGION_ID_STRING(OUTLYING_OCEANIA_REGION_ID); |
+ r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&OUTLYING_OCEANIA_REGION_ID_STRING); |
if ( r ) { |
r->type = URGN_SUBCONTINENT; |
} |
// Load territory containment info from the supplemental data. |
while ( ures_hasNext(territoryContainment.getAlias()) ) { |
- UResourceBundle *mapping = ures_getNextResource(territoryContainment.getAlias(),NULL,&status); |
- const char *parent = ures_getKey(mapping); |
+ LocalUResourceBundlePointer mapping(ures_getNextResource(territoryContainment.getAlias(),NULL,&status)); |
+ if( U_FAILURE(status) ) { |
+ return; // error out |
+ } |
+ const char *parent = ures_getKey(mapping.getAlias()); |
if (uprv_strcmp(parent, "containedGroupings") == 0 || uprv_strcmp(parent, "deprecated") == 0) { |
- ures_close(mapping); |
continue; // handle new pseudo-parent types added in ICU data per cldrbug 7808; for now just skip. |
// #11232 is to do something useful with these. |
} |
UnicodeString parentStr = UnicodeString(parent, -1 , US_INV); |
- Region *parentRegion = (Region *) uhash_get(regionIDMap,(void *)&parentStr); |
+ Region *parentRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&parentStr); |
- for ( int j = 0 ; j < ures_getSize(mapping); j++ ) { |
- UnicodeString child = ures_getUnicodeStringByIndex(mapping,j,&status); |
- Region *childRegion = (Region *) uhash_get(regionIDMap,(void *)&child); |
+ for ( int j = 0 ; j < ures_getSize(mapping.getAlias()); j++ ) { |
+ UnicodeString child = ures_getUnicodeStringByIndex(mapping.getAlias(),j,&status); |
+ Region *childRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&child); |
if ( parentRegion != NULL && childRegion != NULL ) { |
// Add the child region to the set of regions contained by the parent |
@@ -293,9 +345,12 @@ void Region::loadRegionData(UErrorCode &status) { |
parentRegion->containedRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); |
} |
- UnicodeString *childStr = new UnicodeString(); |
+ LocalPointer<UnicodeString> childStr(new UnicodeString(), status); |
+ if( U_FAILURE(status) ) { |
+ return; // error out |
+ } |
childStr->fastCopyFrom(childRegion->idStr); |
- parentRegion->containedRegions->addElement((void *)childStr,status); |
+ parentRegion->containedRegions->addElement((void *)childStr.orphan(),status); |
// Set the parent region to be the containing region of the child. |
// Regions of type GROUPING can't be set as the parent, since another region |
@@ -305,21 +360,28 @@ void Region::loadRegionData(UErrorCode &status) { |
} |
} |
} |
- ures_close(mapping); |
} |
// Create the availableRegions lists |
- int32_t pos = -1; |
- while ( const UHashElement* element = uhash_nextElement(regionIDMap,&pos)) { |
+ int32_t pos = UHASH_FIRST; |
+ while ( const UHashElement* element = uhash_nextElement(newRegionIDMap.getAlias(),&pos)) { |
Region *ar = (Region *)element->value.pointer; |
if ( availableRegions[ar->type] == NULL ) { |
- availableRegions[ar->type] = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); |
+ LocalPointer<UVector> newAr(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); |
+ availableRegions[ar->type] = newAr.orphan(); |
} |
- UnicodeString *arString = new UnicodeString(ar->idStr); |
- availableRegions[ar->type]->addElement((void *)arString,status); |
+ LocalPointer<UnicodeString> arString(new UnicodeString(ar->idStr), status); |
+ if( U_FAILURE(status) ) { |
+ return; // error out |
+ } |
+ availableRegions[ar->type]->addElement((void *)arString.orphan(),status); |
} |
- |
+ |
ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); |
+ // copy hashtables |
+ numericCodeMap = newNumericCodeMap.orphan(); |
+ regionIDMap = newRegionIDMap.orphan(); |
+ regionAliases = newRegionAliases.orphan(); |
} |
void Region::cleanupRegionData() { |
@@ -340,6 +402,14 @@ 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(); |
} |
@@ -363,6 +433,7 @@ Region::~Region () { |
/** |
* Returns true if the two regions are equal. |
+ * Per PMC, just use pointer compare, since we have at most one instance of each Region. |
*/ |
UBool |
Region::operator==(const Region &that) const { |
@@ -371,6 +442,7 @@ Region::operator==(const Region &that) const { |
/** |
* Returns true if the two regions are NOT equal; that is, if operator ==() returns false. |
+ * Per PMC, just use pointer compare, since we have at most one instance of each Region. |
*/ |
UBool |
Region::operator!=(const Region &that) const { |
@@ -409,7 +481,7 @@ Region::getInstance(const char *region_code, UErrorCode &status) { |
} |
if ( r->type == URGN_DEPRECATED && r->preferredValues->size() == 1) { |
- StringEnumeration *pv = r->getPreferredValues(); |
+ StringEnumeration *pv = r->getPreferredValues(status); |
pv->reset(status); |
const UnicodeString *ustr = pv->snext(status); |
r = (Region *)uhash_get(regionIDMap,(void *)ustr); |
@@ -435,24 +507,29 @@ 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#"); |
- DecimalFormat *df = new DecimalFormat(pat,fs); |
- |
+ UnicodeString pat = UNICODE_STRING_SIMPLE("0"); |
+ LocalPointer<DecimalFormat> df(new DecimalFormat(pat,status), status); |
+ if( U_FAILURE(status) ) { |
+ return NULL; |
+ } |
UnicodeString id; |
id.remove(); |
- df->format(code,id); |
- delete df; |
+ FieldPosition posIter; |
+ df->format(code,id, posIter, status); |
r = (Region *)uhash_get(regionAliases,&id); |
} |
+ if( U_FAILURE(status) ) { |
+ return NULL; |
+ } |
+ |
if ( !r ) { |
status = U_ILLEGAL_ARGUMENT_ERROR; |
return NULL; |
} |
if ( r->type == URGN_DEPRECATED && r->preferredValues->size() == 1) { |
- StringEnumeration *pv = r->getPreferredValues(); |
+ StringEnumeration *pv = r->getPreferredValues(status); |
pv->reset(status); |
const UnicodeString *ustr = pv->snext(status); |
r = (Region *)uhash_get(regionIDMap,(void *)ustr); |
@@ -467,9 +544,8 @@ Region::getInstance (int32_t code, UErrorCode &status) { |
* Returns an enumeration over the IDs of all known regions that match the given type. |
*/ |
StringEnumeration* U_EXPORT2 |
-Region::getAvailable(URegionType type) { |
- UErrorCode status = U_ZERO_ERROR; |
- umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
+Region::getAvailable(URegionType type, UErrorCode &status) { |
+ umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) |
if (U_FAILURE(status)) { |
return NULL; |
} |
@@ -503,11 +579,7 @@ Region::getContainingRegion(URegionType type) const { |
return NULL; |
} |
- if ( containingRegion->type == type ) { |
- return containingRegion; |
- } else { |
- return containingRegion->getContainingRegion(type); |
- } |
+ return ( containingRegion->type == type )? containingRegion: containingRegion->getContainingRegion(type); |
} |
/** |
@@ -519,9 +591,11 @@ Region::getContainingRegion(URegionType type) const { |
* and "155" (Western Europe). |
*/ |
StringEnumeration* |
-Region::getContainedRegions() const { |
- UErrorCode status = U_ZERO_ERROR; |
- umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
+Region::getContainedRegions(UErrorCode &status) const { |
+ umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) |
+ if (U_FAILURE(status)) { |
+ return NULL; |
+ } |
return new RegionNameEnumeration(containedRegions,status); |
} |
@@ -532,16 +606,15 @@ Region::getContainedRegions() const { |
* "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR" (France) - "IT" (Italy) - "DE" (Germany) etc. ) |
*/ |
StringEnumeration* |
-Region::getContainedRegions( URegionType type ) const { |
- UErrorCode status = U_ZERO_ERROR; |
- umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
+Region::getContainedRegions( URegionType type, UErrorCode &status ) const { |
+ umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) |
if (U_FAILURE(status)) { |
return NULL; |
} |
UVector *result = new UVector(NULL, uhash_compareChars, status); |
- StringEnumeration *cr = getContainedRegions(); |
+ StringEnumeration *cr = getContainedRegions(status); |
for ( int32_t i = 0 ; i < cr->count(status) ; i++ ) { |
const char *id = cr->next(NULL,status); |
@@ -549,7 +622,7 @@ Region::getContainedRegions( URegionType type ) const { |
if ( r->getType() == type ) { |
result->addElement((void *)&r->idStr,status); |
} else { |
- StringEnumeration *children = r->getContainedRegions(type); |
+ StringEnumeration *children = r->getContainedRegions(type, status); |
for ( int32_t j = 0 ; j < children->count(status) ; j++ ) { |
const char *id2 = children->next(NULL,status); |
const Region *r2 = Region::getInstance(id2,status); |
@@ -596,14 +669,12 @@ Region::contains(const Region &other) const { |
* "SU" (Soviet Union) would return a list of the regions containing "RU" (Russia), "AM" (Armenia), "AZ" (Azerbaijan), etc... |
*/ |
StringEnumeration* |
-Region::getPreferredValues() const { |
- UErrorCode status = U_ZERO_ERROR; |
- umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); |
- if ( type == URGN_DEPRECATED ) { |
- return new RegionNameEnumeration(preferredValues,status); |
- } else { |
+Region::getPreferredValues(UErrorCode &status) const { |
+ umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) |
+ if (U_FAILURE(status) || type != URGN_DEPRECATED) { |
return NULL; |
} |
+ return new RegionNameEnumeration(preferredValues,status); |
} |