#include "unicode/unistr.h"\r
#include "unicode/ures.h"\r
#include "unicode/decimfmt.h"\r
+#include "ucln_in.h"\r
#include "cstring.h"\r
#include "uhash.h"\r
+#include "umutex.h"\r
#include "uresimp.h"\r
#include "region_impl.h"\r
\r
#if !UCONFIG_NO_FORMATTING\r
\r
-U_NAMESPACE_BEGIN\r
\r
+\r
+static UMutex gRegionDataLock = U_MUTEX_INITIALIZER;\r
static UBool regionDataIsLoaded = false;\r
-static UVector* regions = NULL;\r
static UVector* availableRegions[URGN_LIMIT];\r
\r
static UHashtable *regionAliases;\r
static UHashtable *regionIDMap;\r
static UHashtable *numericCodeMap;\r
\r
-static UnicodeString UNKNOWN_REGION_ID = UNICODE_STRING_SIMPLE("ZZ");\r
-static UnicodeString OUTLYING_OCEANIA_REGION_ID = UNICODE_STRING_SIMPLE("QO");\r
-static UnicodeString WORLD_ID = UNICODE_STRING_SIMPLE("001");\r
+U_CDECL_BEGIN\r
\r
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Region)\r
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration)\r
+static void U_CALLCONV\r
+deleteRegion(void *obj) {\r
+ delete (icu::Region *)obj;\r
+}\r
\r
-void addRegion( Region *r ) {\r
+/**\r
+ * Cleanup callback func\r
+ */\r
+static UBool U_CALLCONV region_cleanup(void)\r
+{\r
+ for (int32_t i = 0 ; i < URGN_LIMIT ; i++ ) {\r
+ if ( availableRegions[i] ) {\r
+ delete availableRegions[i];\r
+ }\r
+ }\r
\r
- UErrorCode status = U_ZERO_ERROR;\r
- if ( regions == NULL ) {\r
- regions = new UVector(NULL, NULL, status);\r
+ if (regionAliases) {\r
+ uhash_close(regionAliases);\r
}\r
- regions->addElement(r,status);\r
-}\r
\r
-void addAvailableRegion( const Region *r , URegionType type) {\r
+ if (numericCodeMap) {\r
+ uhash_close(numericCodeMap);\r
+ }\r
\r
- UErrorCode status = U_ZERO_ERROR;\r
- if ( availableRegions[type] == NULL ) {\r
- availableRegions[type] = new UVector(NULL, uhash_compareChars, status);\r
+ if (regionIDMap) {\r
+ uhash_close(regionIDMap);\r
}\r
\r
- availableRegions[type]->addElement((void *)r->getRegionCode(),status);\r
+ return TRUE;\r
}\r
+\r
+U_CDECL_END\r
+\r
+U_NAMESPACE_BEGIN\r
+\r
+static UnicodeString UNKNOWN_REGION_ID = UNICODE_STRING_SIMPLE("ZZ");\r
+static UnicodeString OUTLYING_OCEANIA_REGION_ID = UNICODE_STRING_SIMPLE("QO");\r
+static UnicodeString WORLD_ID = UNICODE_STRING_SIMPLE("001");\r
+\r
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Region)\r
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration)\r
+\r
/*\r
* Initializes the region data from the ICU resource bundles. The region data\r
* contains the basic relationships such as which regions are known, what the numeric\r
if (regionDataIsLoaded) {\r
return;\r
}\r
- \r
+\r
+ umtx_lock(&gRegionDataLock);\r
+\r
+ if (regionDataIsLoaded) { // In case another thread gets to it before we do...\r
+ umtx_unlock(&gRegionDataLock);\r
+ return;\r
+ }\r
+\r
+ \r
UErrorCode status = U_ZERO_ERROR;\r
\r
UResourceBundle* regionCodes = NULL;\r
DecimalFormat *df = new DecimalFormat(status);\r
df->setParseIntegerOnly(TRUE);\r
\r
- regionAliases = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status);\r
regionIDMap = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status);\r
+ uhash_setValueDeleter(regionIDMap, deleteRegion);\r
+\r
numericCodeMap = uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status);\r
\r
+ regionAliases = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status);\r
+ uhash_setKeyDeleter(regionAliases,uprv_deleteUObject);\r
+\r
UResourceBundle *rb = ures_openDirect(NULL,"metadata",&status);\r
regionCodes = ures_getByKey(rb,"regionCodes",NULL,&status);\r
territoryAlias = ures_getByKey(rb,"territoryAlias",NULL,&status);\r
} else {\r
r->code = Region::UNDEFINED_NUMERIC_CODE;\r
}\r
- addRegion(r);\r
}\r
\r
\r
aliasFromRegion->code = Region::UNDEFINED_NUMERIC_CODE;\r
}\r
aliasFromRegion->type = URGN_DEPRECATED;\r
- addRegion(aliasFromRegion);\r
} else {\r
aliasFromRegion->type = URGN_DEPRECATED;\r
}\r
delete aliasFromStr;\r
\r
- aliasFromRegion->preferredValues = new UVector(NULL, uhash_compareChars, status);\r
+ aliasFromRegion->preferredValues = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status);\r
UnicodeString currentRegion;\r
currentRegion.remove();\r
for (int32_t i = 0 ; i < aliasTo.length() ; i++ ) {\r
if ( aliasTo.charAt(i) == 0x0020 || i+1 == aliasTo.length() ) {\r
Region *target = (Region *)uhash_get(regionIDMap,(void *)¤tRegion);\r
if (target) {\r
- aliasFromRegion->preferredValues->addElement((void *)target->id,status);\r
+ UnicodeString *preferredValue = new UnicodeString(target->idStr);\r
+ aliasFromRegion->preferredValues->addElement((void *)preferredValue,status);\r
}\r
currentRegion.remove();\r
}\r
\r
// Add the child region to the set of regions contained by the parent\r
if (parentRegion->containedRegions == NULL) {\r
- parentRegion->containedRegions = new UVector(NULL, uhash_compareChars, status);\r
+ parentRegion->containedRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status);\r
}\r
- parentRegion->containedRegions->addElement((void *)childRegion->id,status);\r
+\r
+ UnicodeString *childStr = new UnicodeString(status);\r
+ childStr->fastCopyFrom(childRegion->idStr);\r
+ parentRegion->containedRegions->addElement((void *)childStr,status);\r
\r
// Set the parent region to be the containing region of the child.\r
// Regions of type GROUPING can't be set as the parent, since another region\r
}\r
}\r
}\r
+ ures_close(mapping);\r
} \r
\r
// Create the availableRegions lists\r
-\r
- for ( int32_t i = 0 ; i < regions->size() ; i++ ) {\r
- Region *ar = (Region *)regions->elementAt(i);\r
- addAvailableRegion(ar,ar->type);\r
+ int32_t pos = -1;\r
+ while ( const UHashElement* element = uhash_nextElement(regionIDMap,&pos)) {\r
+ Region *ar = (Region *)element->value.pointer;\r
+ if ( availableRegions[ar->type] == NULL ) {\r
+ availableRegions[ar->type] = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status);\r
+ }\r
+ UnicodeString *arString = new UnicodeString(ar->idStr);\r
+ availableRegions[ar->type]->addElement((void *)arString,status);\r
}\r
\r
- regionDataIsLoaded = true;\r
-\r
ures_close(territoryContainment);\r
ures_close(worldContainment);\r
ures_close(groupingContainment);\r
ures_close(rb);\r
\r
delete df;\r
+\r
+ ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup);\r
+\r
+ regionDataIsLoaded = true;\r
+ umtx_unlock(&gRegionDataLock);\r
+\r
}\r
\r
\r
preferredValues = NULL;\r
}\r
\r
+Region::~Region () {\r
+ if (containedRegions) {\r
+ delete containedRegions;\r
+ }\r
+ if (preferredValues) {\r
+ delete preferredValues;\r
+ }\r
+}\r
\r
/**\r
* Returns true if the two regions are equal.\r
const char *id = cr->next(NULL,status);\r
const Region *r = Region::getInstance(id,status);\r
if ( r->getType() == type ) {\r
- result->addElement((void *)r->id,status);\r
+ result->addElement((void *)&r->idStr,status);\r
} else {\r
StringEnumeration *children = r->getContainedRegions(type);\r
for ( int32_t j = 0 ; j < children->count(status) ; j++ ) {\r
const char *id2 = children->next(NULL,status);\r
const Region *r2 = Region::getInstance(id2,status);\r
- result->addElement((void *)r2->id,status);\r
+ result->addElement((void *)&r2->idStr,status);\r
}\r
delete children;\r
}\r
}\r
- return new RegionNameEnumeration(result,status);\r
+ delete cr;\r
+ StringEnumeration* resultEnumeration = new RegionNameEnumeration(result,status);\r
+ delete result;\r
+ return resultEnumeration;\r
}\r
\r
/**\r
if (!containedRegions) {\r
return FALSE;\r
}\r
- if (containedRegions->contains((void *)other.id)) {\r
+ if (containedRegions->contains((void *)&other.idStr)) {\r
return TRUE;\r
} else {\r
for ( int32_t i = 0 ; i < containedRegions->size() ; i++ ) {\r
- UErrorCode status = U_ZERO_ERROR;\r
- const Region *cr = Region::getInstance((const char *)containedRegions->elementAt(i),status);\r
+ UnicodeString *crStr = (UnicodeString *)containedRegions->elementAt(i);\r
+ Region *cr = (Region *) uhash_get(regionIDMap,(void *)crStr);\r
if ( cr && cr->contains(other) ) {\r
return TRUE;\r
}\r
RegionNameEnumeration::RegionNameEnumeration(UVector *fNameList, UErrorCode& status) {\r
pos=0;\r
if (fNameList) {\r
- fRegionNames = new UVector(NULL, uhash_compareChars, fNameList->size(),status);\r
+ fRegionNames = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, fNameList->size(),status);\r
for ( int32_t i = 0 ; i < fNameList->size() ; i++ ) {\r
- char *region_name = (char *) uprv_malloc(sizeof(fNameList->elementAt(i)));\r
- if (!region_name) {\r
- status = U_MEMORY_ALLOCATION_ERROR;\r
- delete fRegionNames;\r
- fRegionNames = NULL;\r
- return;\r
- }\r
- uprv_strcpy(region_name,(char *)fNameList->elementAt(i));\r
- fRegionNames->addElement(region_name,status);\r
- \r
+ UnicodeString* this_region_name = (UnicodeString *)fNameList->elementAt(i);\r
+ UnicodeString* new_region_name = new UnicodeString(*this_region_name);\r
+ fRegionNames->addElement((void *)new_region_name,status); \r
}\r
}\r
else { \r
- fRegionNames = fNameList;\r
- }\r
-}\r
-\r
-const char*\r
-RegionNameEnumeration::next(int32_t *resultLength, UErrorCode& status) {\r
- if (U_SUCCESS(status) && pos < fRegionNames->size()) {\r
- if (resultLength != NULL) {\r
- *resultLength = uprv_strlen((const char *)fRegionNames->elementAt(pos));\r
- }\r
- return (const char *)fRegionNames->elementAt(pos++);\r
+ fRegionNames = NULL;\r
}\r
- return NULL;\r
}\r
\r
const UnicodeString*\r
-RegionNameEnumeration::snext(UErrorCode& status) { \r
- int32_t resultLength=0;\r
- const char *s=next(&resultLength, status);\r
- return setChars(s, resultLength, status);\r
+RegionNameEnumeration::snext(UErrorCode& /*status*/) { \r
+ return (const UnicodeString *)fRegionNames->elementAt(pos++);\r
}\r
\r
void\r