--- /dev/null
+/*\r
+*******************************************************************************\r
+* Copyright (C) 2013, International Business Machines Corporation and\r
+* others. All Rights Reserved.\r
+*******************************************************************************\r
+*\r
+*\r
+* File REGION.CPP\r
+*\r
+* Modification History:*\r
+* Date Name Description\r
+* 01/15/13 Emmons Original Port from ICU4J\r
+********************************************************************************\r
+*/\r
+\r
+/**\r
+ * \file \r
+ * \brief C++ API: Region classes (territory containment)\r
+ */\r
+\r
+#include "unicode/region.h"\r
+#include "unicode/utypes.h"\r
+#include "unicode/uobject.h"\r
+#include "unicode/unistr.h"\r
+#include "unicode/ures.h"\r
+#include "unicode/decimfmt.h"\r
+#include "cstring.h"\r
+#include "uhash.h"\r
+#include "uresimp.h"\r
+#include "region_impl.h"\r
+\r
+#if !UCONFIG_NO_FORMATTING\r
+\r
+U_NAMESPACE_BEGIN\r
+\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
+\r
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Region)\r
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegionNameEnumeration)\r
+\r
+void addRegion( Region *r ) {\r
+\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ if ( regions == NULL ) {\r
+ regions = new UVector(NULL, NULL, status);\r
+ }\r
+ regions->addElement(r,status);\r
+}\r
+\r
+void addAvailableRegion( const Region *r , URegionType type) {\r
+\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ if ( availableRegions[type] == NULL ) {\r
+ availableRegions[type] = new UVector(NULL, uhash_compareChars, status);\r
+ }\r
+\r
+ availableRegions[type]->addElement((void *)r->getRegionCode(),status);\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
+ * codes are, any known aliases, and the territory containment data.\r
+ * \r
+ * If the region data has already loaded, then this method simply returns without doing\r
+ * anything meaningful.\r
+ */\r
+void Region::loadRegionData() {\r
+\r
+ if (regionDataIsLoaded) {\r
+ return;\r
+ }\r
+ \r
+ UErrorCode status = U_ZERO_ERROR;\r
+\r
+ UResourceBundle* regionCodes = NULL;\r
+ UResourceBundle* territoryAlias = NULL;\r
+ UResourceBundle* codeMappings = NULL;\r
+ UResourceBundle* worldContainment = NULL;\r
+ UResourceBundle* territoryContainment = NULL;\r
+ UResourceBundle* groupingContainment = NULL;\r
+\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
+ numericCodeMap = uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status);\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
+ \r
+ UResourceBundle *rb2 = ures_openDirect(NULL,"supplementalData",&status);\r
+ codeMappings = ures_getByKey(rb2,"codeMappings",NULL,&status);\r
+\r
+ territoryContainment = ures_getByKey(rb2,"territoryContainment",NULL,&status);\r
+ worldContainment = ures_getByKey(territoryContainment,"001",NULL,&status);\r
+ groupingContainment = ures_getByKey(territoryContainment,"grouping",NULL,&status);\r
+\r
+ UVector *continents = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status);\r
+\r
+ while ( ures_hasNext(worldContainment) ) {\r
+ UnicodeString *continentName = new UnicodeString(ures_getNextUnicodeString(worldContainment,NULL,&status));\r
+ continents->addElement(continentName,status);\r
+ }\r
+\r
+ UVector *groupings = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status);\r
+ while ( ures_hasNext(groupingContainment) ) {\r
+ UnicodeString *groupingName = new UnicodeString(ures_getNextUnicodeString(groupingContainment,NULL,&status));\r
+ groupings->addElement(groupingName,status);\r
+ }\r
+\r
+ while ( ures_hasNext(regionCodes) ) {\r
+ UnicodeString regionID = ures_getNextUnicodeString(regionCodes,NULL,&status);\r
+ Region *r = new Region();\r
+ r->idStr = regionID;\r
+ r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV);\r
+ r->type = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known.\r
+\r
+ uhash_put(regionIDMap,(void *)&(r->idStr),(void *)r,&status);\r
+ Formattable result;\r
+ UErrorCode ps = U_ZERO_ERROR;\r
+ df->parse(r->idStr,result,ps);\r
+ if ( U_SUCCESS(ps) ) {\r
+ r->code = result.getLong(); // Convert string to number\r
+ uhash_iput(numericCodeMap,r->code,(void *)r,&status);\r
+ r->type = URGN_SUBCONTINENT;\r
+ } else {\r
+ r->code = Region::UNDEFINED_NUMERIC_CODE;\r
+ }\r
+ addRegion(r);\r
+ }\r
+\r
+\r
+ // Process the territory aliases\r
+ int32_t territoryAliasSize = ures_getSize(territoryAlias);\r
+ while ( ures_hasNext(territoryAlias) ) {\r
+ UResourceBundle *res = ures_getNextResource(territoryAlias,NULL,&status);\r
+ const char *aliasFrom = ures_getKey(res);\r
+ UnicodeString* aliasFromStr = new UnicodeString(aliasFrom);\r
+ UnicodeString aliasTo = ures_getUnicodeString(res,&status);\r
+\r
+ Region *aliasToRegion = (Region *) uhash_get(regionIDMap,&aliasTo);\r
+ Region *aliasFromRegion = (Region *)uhash_get(regionIDMap,aliasFromStr);\r
+\r
+ if ( aliasToRegion != NULL && aliasFromRegion == NULL ) { // This is just an alias from some string to a region\r
+ uhash_put(regionAliases,(void *)aliasFromStr, (void *)aliasToRegion,&status);\r
+ } else {\r
+ if ( aliasFromRegion == NULL ) { // Deprecated region code not in the master codes list - so need to create a deprecated region for it.\r
+ aliasFromRegion = new Region();\r
+ aliasFromRegion->idStr.setTo(*aliasFromStr);\r
+ aliasFromRegion->idStr.extract(0,aliasFromRegion->idStr.length(),aliasFromRegion->id,sizeof(aliasFromRegion->id),US_INV);\r
+ uhash_put(regionIDMap,(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status);\r
+ Formattable result;\r
+ UErrorCode ps = U_ZERO_ERROR;\r
+ df->parse(aliasFromRegion->idStr,result,ps);\r
+ if ( U_SUCCESS(ps) ) {\r
+ aliasFromRegion->code = result.getLong(); // Convert string to number\r
+ uhash_iput(numericCodeMap,aliasFromRegion->code,(void *)aliasFromRegion,&status);\r
+ } else {\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
+ UnicodeString currentRegion;\r
+ currentRegion.remove();\r
+ for (int32_t i = 0 ; i < aliasTo.length() ; i++ ) {\r
+ if ( aliasTo.charAt(i) != 0x0020 ) {\r
+ currentRegion.append(aliasTo.charAt(i));\r
+ }\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
+ }\r
+ currentRegion.remove();\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // Process the code mappings - This will allow us to assign numeric codes to most of the territories.\r
+ while ( ures_hasNext(codeMappings) ) {\r
+ UResourceBundle *mapping = ures_getNextResource(codeMappings,NULL,&status);\r
+ if ( ures_getType(mapping) == URES_ARRAY && ures_getSize(mapping) == 3) {\r
+ UnicodeString codeMappingID = ures_getUnicodeStringByIndex(mapping,0,&status);\r
+ UnicodeString codeMappingNumber = ures_getUnicodeStringByIndex(mapping,1,&status);\r
+ UnicodeString codeMapping3Letter = ures_getUnicodeStringByIndex(mapping,2,&status);\r
+\r
+ Region *r = (Region *)uhash_get(regionIDMap,(void *)&codeMappingID);\r
+ if ( r ) {\r
+ Formattable result;\r
+ UErrorCode ps = U_ZERO_ERROR;\r
+ df->parse(codeMappingNumber,result,ps);\r
+ if ( U_SUCCESS(ps) ) {\r
+ r->code = result.getLong(); // Convert string to number\r
+ uhash_iput(numericCodeMap,r->code,(void *)r,&status);\r
+ }\r
+ UnicodeString *code3 = new UnicodeString(codeMapping3Letter);\r
+ uhash_put(regionAliases,(void *)code3, (void *)r,&status);\r
+ } \r
+ }\r
+ }\r
+\r
+ // Now fill in the special cases for WORLD, UNKNOWN, CONTINENTS, and GROUPINGS\r
+ Region *r;\r
+ r = (Region *) uhash_get(regionIDMap,(void *)&WORLD_ID);\r
+ if ( r ) {\r
+ r->type = URGN_WORLD;\r
+ }\r
+\r
+ r = (Region *) uhash_get(regionIDMap,(void *)&UNKNOWN_REGION_ID);\r
+ if ( r ) {\r
+ r->type = URGN_UNKNOWN;\r
+ }\r
+\r
+ for ( int32_t i = 0 ; i < continents->size() ; i++ ) {\r
+ r = (Region *) uhash_get(regionIDMap,(void *)continents->elementAt(i));\r
+ if ( r ) {\r
+ r->type = URGN_CONTINENT;\r
+ }\r
+ }\r
+ delete continents;\r
+\r
+ for ( int32_t i = 0 ; i < groupings->size() ; i++ ) {\r
+ r = (Region *) uhash_get(regionIDMap,(void *)groupings->elementAt(i));\r
+ if ( r ) {\r
+ r->type = URGN_GROUPING;\r
+ }\r
+ }\r
+ delete groupings;\r
+\r
+ // Special case: The region code "QO" (Outlying Oceania) is a subcontinent code added by CLDR\r
+ // even though it looks like a territory code. Need to handle it here.\r
+\r
+ r = (Region *) uhash_get(regionIDMap,(void *)&OUTLYING_OCEANIA_REGION_ID);\r
+ if ( r ) {\r
+ r->type = URGN_SUBCONTINENT;\r
+ }\r
+\r
+ // Load territory containment info from the supplemental data.\r
+ while ( ures_hasNext(territoryContainment) ) {\r
+ UResourceBundle *mapping = ures_getNextResource(territoryContainment,NULL,&status);\r
+ const char *parent = ures_getKey(mapping);\r
+ UnicodeString parentStr = UnicodeString(parent);\r
+ Region *parentRegion = (Region *) uhash_get(regionIDMap,(void *)&parentStr);\r
+\r
+ for ( int j = 0 ; j < ures_getSize(mapping); j++ ) {\r
+ UnicodeString child = ures_getUnicodeStringByIndex(mapping,j,&status);\r
+ Region *childRegion = (Region *) uhash_get(regionIDMap,(void *)&child);\r
+ if ( parentRegion != NULL && childRegion != NULL ) { \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
+ }\r
+ parentRegion->containedRegions->addElement((void *)childRegion->id,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
+ // such as a SUBCONTINENT, CONTINENT, or WORLD must always be the parent.\r
+ if ( parentRegion->type != URGN_GROUPING) {\r
+ childRegion->containingRegion = parentRegion;\r
+ }\r
+ }\r
+ }\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
+ }\r
+\r
+ regionDataIsLoaded = true;\r
+\r
+ ures_close(territoryContainment);\r
+ ures_close(worldContainment);\r
+ ures_close(groupingContainment);\r
+\r
+ ures_close(codeMappings);\r
+ ures_close(rb2);\r
+ ures_close(territoryAlias);\r
+ ures_close(regionCodes);\r
+ ures_close(rb);\r
+\r
+ delete df;\r
+}\r
+\r
+\r
+\r
+/*\r
+ * Default constructor. Use factory methods only.\r
+ * @internal\r
+ */\r
+\r
+Region::Region () {\r
+ idStr.remove();\r
+ code = UNDEFINED_NUMERIC_CODE;\r
+ type = URGN_UNKNOWN;\r
+ containingRegion = NULL;\r
+ containedRegions = NULL;\r
+ preferredValues = NULL;\r
+}\r
+\r
+\r
+/**\r
+ * Returns true if the two regions are equal.\r
+ */\r
+UBool U_EXPORT2\r
+Region::operator==(const Region &that) const {\r
+ return (idStr == that.idStr);\r
+}\r
+\r
+/**\r
+ * Returns true if the two regions are NOT equal; that is, if operator ==() returns false.\r
+ */\r
+UBool U_EXPORT2\r
+Region::operator!=(const Region &that) const {\r
+ return (idStr != that.idStr);\r
+}\r
+ \r
+/**\r
+ * Returns a pointer to a Region using the given region code. The region code can be either 2-letter ISO code,\r
+ * 3-letter ISO code, UNM.49 numeric code, or other valid Unicode Region Code as defined by the LDML specification.\r
+ * The identifier will be canonicalized internally using the supplemental metadata as defined in the CLDR.\r
+ * If the region code is NULL or not recognized, the appropriate error code will be set ( U_ILLEGAL_ARGUMENT_ERROR )\r
+ */\r
+const Region* U_EXPORT2\r
+Region::getInstance(const char *region_code, UErrorCode &status) {\r
+\r
+ if ( !region_code ) {\r
+ status = U_ILLEGAL_ARGUMENT_ERROR;\r
+ return NULL;\r
+ }\r
+\r
+ loadRegionData();\r
+\r
+ UnicodeString regionCodeString = UnicodeString(region_code);\r
+ Region *r = (Region *)uhash_get(regionIDMap,(void *)®ionCodeString);\r
+\r
+ if ( !r ) {\r
+ r = (Region *)uhash_get(regionAliases,(void *)®ionCodeString);\r
+ }\r
+\r
+ if ( !r ) { // Unknown region code\r
+ status = U_ILLEGAL_ARGUMENT_ERROR;\r
+ return NULL;\r
+ }\r
+\r
+ if ( r->type == URGN_DEPRECATED && r->preferredValues->size() == 1) {\r
+ StringEnumeration *pv = r->getPreferredValues();\r
+ pv->reset(status);\r
+ const UnicodeString *ustr = pv->snext(status);\r
+ r = (Region *)uhash_get(regionIDMap,(void *)ustr);\r
+ }\r
+\r
+ return r;\r
+\r
+}\r
+\r
+/**\r
+ * Returns a pointer to a Region using the given numeric region code. If the numeric region code is not recognized,\r
+ * the appropriate error code will be set ( U_ILLEGAL_ARGUMENT_ERROR ).\r
+ */\r
+const Region * U_EXPORT2\r
+Region::getInstance (int32_t code, UErrorCode &status) {\r
+\r
+ loadRegionData();\r
+\r
+ Region *r = (Region *)uhash_iget(numericCodeMap,code);\r
+\r
+ if ( !r ) { // Just in case there's an alias that's numeric, try to find it.\r
+ UErrorCode fs = U_ZERO_ERROR;\r
+ UnicodeString pat = UNICODE_STRING_SIMPLE("00#");\r
+ DecimalFormat *df = new DecimalFormat(pat,fs);\r
+ \r
+ UnicodeString id;\r
+ id.remove();\r
+ df->format(code,id);\r
+ delete df;\r
+ r = (Region *)uhash_get(regionAliases,&id);\r
+ }\r
+\r
+ if ( !r ) {\r
+ status = U_ILLEGAL_ARGUMENT_ERROR;\r
+ return NULL;\r
+ }\r
+\r
+ if ( r->type == URGN_DEPRECATED && r->preferredValues->size() == 1) {\r
+ StringEnumeration *pv = r->getPreferredValues();\r
+ pv->reset(status);\r
+ const UnicodeString *ustr = pv->snext(status);\r
+ r = (Region *)uhash_get(regionIDMap,(void *)ustr);\r
+ }\r
+\r
+ return r;\r
+}\r
+\r
+\r
+/**\r
+ * Returns an enumeration over the IDs of all known regions that match the given type.\r
+ */\r
+StringEnumeration * U_EXPORT2\r
+Region::getAvailable(URegionType type) {\r
+ \r
+ loadRegionData();\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ return new RegionNameEnumeration(availableRegions[type],status);\r
+\r
+ return NULL; \r
+}\r
+ \r
+/**\r
+ * Returns a pointer to the region that contains this region. Returns NULL if this region is code "001" (World)\r
+ * or "ZZ" (Unknown region). For example, calling this method with region "IT" (Italy) returns the\r
+ * region "039" (Southern Europe).\r
+ */\r
+const Region * U_EXPORT2\r
+Region::getContainingRegion() const {\r
+ loadRegionData();\r
+ return containingRegion;\r
+}\r
+\r
+/**\r
+ * Return a pointer to the region that geographically contains this region and matches the given type,\r
+ * moving multiple steps up the containment chain if necessary. Returns NULL if no containing region can be found\r
+ * that matches the given type. Note: The URegionTypes = "URGN_GROUPING", "URGN_DEPRECATED", or "URGN_UNKNOWN"\r
+ * are not appropriate for use in this API. NULL will be returned in this case. For example, calling this method\r
+ * with region "IT" (Italy) for type "URGN_CONTINENT" returns the region "150" ( Europe ).\r
+ */\r
+const Region* U_EXPORT2\r
+Region::getContainingRegion(URegionType type) const {\r
+ loadRegionData();\r
+ if ( containingRegion == NULL ) {\r
+ return NULL;\r
+ }\r
+\r
+ if ( containingRegion->type == type ) {\r
+ return containingRegion;\r
+ } else {\r
+ return containingRegion->getContainingRegion(type);\r
+ }\r
+}\r
+\r
+/**\r
+ * Return an enumeration over the IDs of all the regions that are immediate children of this region in the\r
+ * region hierarchy. These returned regions could be either macro regions, territories, or a mixture of the two,\r
+ * depending on the containment data as defined in CLDR. This API may return NULL if this region doesn't have\r
+ * any sub-regions. For example, calling this method with region "150" (Europe) returns an enumeration containing\r
+ * the various sub regions of Europe - "039" (Southern Europe) - "151" (Eastern Europe) - "154" (Northern Europe)\r
+ * and "155" (Western Europe).\r
+ */\r
+StringEnumeration * U_EXPORT2\r
+Region::getContainedRegions() const {\r
+ loadRegionData();\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ return new RegionNameEnumeration(containedRegions,status);\r
+}\r
+\r
+/**\r
+ * Returns an enumeration over the IDs of all the regions that are children of this region anywhere in the region\r
+ * hierarchy and match the given type. This API may return an empty enumeration if this region doesn't have any\r
+ * sub-regions that match the given type. For example, calling this method with region "150" (Europe) and type\r
+ * "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR" (France) - "IT" (Italy) - "DE" (Germany) etc. )\r
+ */\r
+StringEnumeration * U_EXPORT2\r
+Region::getContainedRegions( URegionType type ) const {\r
+ loadRegionData();\r
+\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ UVector *result = new UVector(uprv_deleteUObject, uhash_compareChars, status);\r
+ \r
+ StringEnumeration *cr = getContainedRegions();\r
+\r
+ for ( int32_t i = 0 ; i < cr->count(status) ; i++ ) {\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
+ } 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
+ }\r
+ }\r
+ }\r
+ return new RegionNameEnumeration(result,status);\r
+}\r
+ \r
+/**\r
+ * Returns true if this region contains the supplied other region anywhere in the region hierarchy.\r
+ */\r
+UBool U_EXPORT2\r
+Region::contains(const Region &other) const {\r
+ loadRegionData();\r
+\r
+ if (!containedRegions) {\r
+ return FALSE;\r
+ }\r
+ if (containedRegions->contains((void *)other.id)) {\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
+ if ( cr && cr->contains(other) ) {\r
+ return TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ * For deprecated regions, return an enumeration over the IDs of the regions that are the preferred replacement\r
+ * regions for this region. Returns NULL for a non-deprecated region. For example, calling this method with region\r
+ * "SU" (Soviet Union) would return a list of the regions containing "RU" (Russia), "AM" (Armenia), "AZ" (Azerbaijan), etc...\r
+ */\r
+StringEnumeration * U_EXPORT2\r
+Region::getPreferredValues() const {\r
+ loadRegionData();\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ if ( type == URGN_DEPRECATED ) {\r
+ return new RegionNameEnumeration(preferredValues,status);\r
+ } else {\r
+ return NULL;\r
+ }\r
+}\r
+ \r
+\r
+/**\r
+ * Return this region's canonical region code.\r
+ */\r
+const char * U_EXPORT2\r
+Region::getRegionCode() const {\r
+ return id;\r
+}\r
+\r
+/**\r
+ * Return this region's numeric code. Returns UNDEFINED_NUMERIC_CODE (-1) if the given region does not have a numeric code assigned to it.\r
+ */\r
+int32_t U_EXPORT2\r
+Region::getNumericCode() const {\r
+ return code;\r
+}\r
+\r
+/**\r
+ * Returns the region type of this region.\r
+ */\r
+URegionType U_EXPORT2\r
+Region::getType() const {\r
+ return type;\r
+}\r
+\r
+RegionNameEnumeration::RegionNameEnumeration(UVector *fNameList, UErrorCode& /*status*/) {\r
+ pos=0;\r
+ fRegionNames = fNameList;\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
+ }\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
+}\r
+\r
+void\r
+RegionNameEnumeration::reset(UErrorCode& /*status*/) {\r
+ pos=0;\r
+}\r
+\r
+int32_t\r
+RegionNameEnumeration::count(UErrorCode& /*status*/) const {\r
+ return (fRegionNames==NULL) ? 0 : fRegionNames->size();\r
+}\r
+\r
+RegionNameEnumeration::~RegionNameEnumeration() {\r
+ delete fRegionNames;\r
+}\r
+\r
+U_NAMESPACE_END\r
+\r
+#endif /* #if !UCONFIG_NO_FORMATTING */\r
+\r
+//eof\r
--- /dev/null
+/***********************************************************************\r
+ * COPYRIGHT: \r
+ * Copyright (c) 2013, International Business Machines Corporation\r
+ * and others. All Rights Reserved.\r
+ ***********************************************************************/\r
+ \r
+/***********************************************************************\r
+ * This testcase ported from ICU4J ( RegionTest.java ) to ICU4C *\r
+ * Try to keep them in sync if at all possible...! *\r
+ ***********************************************************************/\r
+\r
+#include "unicode/utypes.h"\r
+#include "cstring.h"\r
+\r
+#if !UCONFIG_NO_FORMATTING\r
+\r
+#include "unicode/region.h"\r
+#include "regiontst.h"\r
+\r
+typedef struct KnownRegion {\r
+ const char *code;\r
+ int32_t numeric;\r
+ const char *parent;\r
+ URegionType type;\r
+ const char *containingContinent;\r
+} KnownRegion;\r
+\r
+#define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0]))\r
+\r
+static KnownRegion knownRegions[] = {\r
+ // Code, Num, Parent, Type, Containing Continent\r
+ { "TP" , 626, "035", URGN_TERRITORY, "142" },\r
+ { "001", 1, NULL , URGN_WORLD, NULL },\r
+ { "002", 2, "001", URGN_CONTINENT, NULL },\r
+ { "003", 3, NULL, URGN_GROUPING, NULL },\r
+ { "005", 5, "019", URGN_SUBCONTINENT, "019" },\r
+ { "009", 9, "001", URGN_CONTINENT, NULL},\r
+ { "011", 11, "002", URGN_SUBCONTINENT, "002" },\r
+ { "013", 13, "019", URGN_SUBCONTINENT, "019" },\r
+ { "014", 14, "002", URGN_SUBCONTINENT, "002" },\r
+ { "015", 15, "002", URGN_SUBCONTINENT, "002" },\r
+ { "017", 17, "002", URGN_SUBCONTINENT, "002" },\r
+ { "018", 18, "002", URGN_SUBCONTINENT, "002" },\r
+ { "019", 19, "001", URGN_CONTINENT, NULL },\r
+ { "021", 21, "019", URGN_SUBCONTINENT, "019" },\r
+ { "029", 29, "019", URGN_SUBCONTINENT, "019" },\r
+ { "030", 30, "142", URGN_SUBCONTINENT, "142" },\r
+ { "034", 34, "142", URGN_SUBCONTINENT, "142" },\r
+ { "035", 35, "142", URGN_SUBCONTINENT, "142" },\r
+ { "039", 39, "150", URGN_SUBCONTINENT, "150"},\r
+ { "053", 53, "009", URGN_SUBCONTINENT, "009" },\r
+ { "054", 54, "009", URGN_SUBCONTINENT, "009" },\r
+ { "057", 57, "009", URGN_SUBCONTINENT, "009" },\r
+ { "061", 61, "009", URGN_SUBCONTINENT, "009" },\r
+ { "142", 142, "001", URGN_CONTINENT, NULL },\r
+ { "143", 143, "142", URGN_SUBCONTINENT, "142" },\r
+ { "145", 145, "142", URGN_SUBCONTINENT, "142" },\r
+ { "150", 150, "001", URGN_CONTINENT, NULL },\r
+ { "151", 151, "150", URGN_SUBCONTINENT, "150" },\r
+ { "154", 154, "150", URGN_SUBCONTINENT, "150" },\r
+ { "155", 155, "150", URGN_SUBCONTINENT, "150" },\r
+ { "419", 419, NULL, URGN_GROUPING , NULL},\r
+ { "AC" , -1, "QO" , URGN_TERRITORY, "009" },\r
+ { "AD" , 20, "039", URGN_TERRITORY, "150" },\r
+ { "AE" , 784, "145", URGN_TERRITORY, "142" },\r
+ { "AF" , 4, "034", URGN_TERRITORY, "142" },\r
+ { "AG" , 28, "029", URGN_TERRITORY, "019" },\r
+ { "AI" , 660, "029", URGN_TERRITORY, "019" },\r
+ { "AL" , 8, "039", URGN_TERRITORY, "150" },\r
+ { "AM" , 51, "145", URGN_TERRITORY, "142" },\r
+ { "AN" , 530, NULL, URGN_DEPRECATED, NULL },\r
+ { "AO" , 24, "017", URGN_TERRITORY, "002" },\r
+ { "AQ" , 10, "QO" , URGN_TERRITORY, "009" },\r
+ { "AR" , 32, "005", URGN_TERRITORY, "019" },\r
+ { "AS" , 16, "061", URGN_TERRITORY, "009" },\r
+ { "AT" , 40, "155", URGN_TERRITORY, "150" },\r
+ { "AU" , 36, "053", URGN_TERRITORY, "009" },\r
+ { "AW" , 533, "029", URGN_TERRITORY, "019" },\r
+ { "AX" , 248, "154", URGN_TERRITORY, "150" },\r
+ { "AZ" , 31, "145", URGN_TERRITORY, "142" },\r
+ { "BA" , 70, "039", URGN_TERRITORY, "150" },\r
+ { "BB" , 52, "029", URGN_TERRITORY, "019" },\r
+ { "BD" , 50, "034", URGN_TERRITORY, "142" },\r
+ { "BE" , 56, "155", URGN_TERRITORY, "150" },\r
+ { "BF" , 854, "011", URGN_TERRITORY, "002" },\r
+ { "BG" , 100, "151", URGN_TERRITORY, "150" },\r
+ { "BH" , 48, "145", URGN_TERRITORY, "142" },\r
+ { "BI" , 108, "014", URGN_TERRITORY, "002" },\r
+ { "BJ" , 204, "011", URGN_TERRITORY, "002" },\r
+ { "BL" , 652, "029", URGN_TERRITORY, "019" },\r
+ { "BM" , 60, "021", URGN_TERRITORY, "019" },\r
+ { "BN" , 96, "035", URGN_TERRITORY, "142" },\r
+ { "BO" , 68, "005", URGN_TERRITORY, "019" },\r
+ { "BQ" , 535, "029", URGN_TERRITORY, "019" },\r
+ { "BR" , 76, "005", URGN_TERRITORY, "019" },\r
+ { "BS" , 44, "029", URGN_TERRITORY, "019" },\r
+ { "BT" , 64, "034", URGN_TERRITORY, "142" },\r
+ { "BU" , 104, "035", URGN_TERRITORY, "142" },\r
+ { "BV" , 74, "QO" , URGN_TERRITORY, "009" },\r
+ { "BW" , 72, "018", URGN_TERRITORY, "002" },\r
+ { "BY" , 112, "151", URGN_TERRITORY, "150" },\r
+ { "BZ" , 84, "013", URGN_TERRITORY, "019" },\r
+ { "CA" , 124, "021", URGN_TERRITORY, "019" },\r
+ { "CC" , 166, "QO" , URGN_TERRITORY, "009" },\r
+ { "CD" , 180, "017", URGN_TERRITORY, "002" },\r
+ { "CF" , 140, "017", URGN_TERRITORY, "002" },\r
+ { "CG" , 178, "017", URGN_TERRITORY, "002" },\r
+ { "CH" , 756, "155", URGN_TERRITORY, "150" },\r
+ { "CI" , 384, "011", URGN_TERRITORY, "002" },\r
+ { "CK" , 184, "061", URGN_TERRITORY, "009" },\r
+ { "CL" , 152, "005", URGN_TERRITORY, "019" },\r
+ { "CM" , 120, "017", URGN_TERRITORY, "002" },\r
+ { "CN" , 156, "030", URGN_TERRITORY, "142" },\r
+ { "CO" , 170, "005", URGN_TERRITORY, "019" },\r
+ { "CP" , -1 , "QO" , URGN_TERRITORY, "009" },\r
+ { "CR" , 188, "013", URGN_TERRITORY, "019" },\r
+ { "CU" , 192, "029", URGN_TERRITORY, "019" },\r
+ { "CV" , 132, "011", URGN_TERRITORY, "002" },\r
+ { "CW" , 531, "029", URGN_TERRITORY, "019" },\r
+ { "CX" , 162, "QO" , URGN_TERRITORY, "009" },\r
+ { "CY" , 196, "145", URGN_TERRITORY, "142" },\r
+ { "CZ" , 203, "151", URGN_TERRITORY, "150" },\r
+ { "DD" , 276, "155", URGN_TERRITORY, "150" },\r
+ { "DE" , 276, "155", URGN_TERRITORY, "150" },\r
+ { "DG" , -1 , "QO" , URGN_TERRITORY, "009" },\r
+ { "DJ" , 262, "014", URGN_TERRITORY, "002" },\r
+ { "DK" , 208, "154", URGN_TERRITORY, "150" },\r
+ { "DM" , 212, "029", URGN_TERRITORY, "019" },\r
+ { "DO" , 214, "029", URGN_TERRITORY, "019" },\r
+ { "DZ" , 12, "015", URGN_TERRITORY, "002" },\r
+ { "EA" , -1, "015", URGN_TERRITORY, "002" },\r
+ { "EC" , 218, "005", URGN_TERRITORY, "019" },\r
+ { "EE" , 233, "154", URGN_TERRITORY, "150" },\r
+ { "EG" , 818, "015", URGN_TERRITORY, "002" },\r
+ { "EH" , 732, "015", URGN_TERRITORY, "002" },\r
+ { "ER" , 232, "014", URGN_TERRITORY, "002" },\r
+ { "ES" , 724, "039", URGN_TERRITORY, "150" },\r
+ { "ET" , 231, "014", URGN_TERRITORY, "002" },\r
+ { "EU" , 967, NULL, URGN_GROUPING, NULL },\r
+ { "FI" , 246, "154", URGN_TERRITORY, "150" },\r
+ { "FJ" , 242, "054", URGN_TERRITORY, "009" },\r
+ { "FK" , 238, "005", URGN_TERRITORY, "019" },\r
+ { "FM" , 583, "057", URGN_TERRITORY, "009" },\r
+ { "FO" , 234, "154", URGN_TERRITORY, "150" },\r
+ { "FR" , 250, "155", URGN_TERRITORY, "150" },\r
+ { "FX" , 250, "155", URGN_TERRITORY, "150" },\r
+ { "GA" , 266, "017", URGN_TERRITORY, "002" },\r
+ { "GB" , 826, "154", URGN_TERRITORY, "150" },\r
+ { "GD" , 308, "029", URGN_TERRITORY, "019" },\r
+ { "GE" , 268, "145", URGN_TERRITORY, "142" },\r
+ { "GF" , 254, "005", URGN_TERRITORY, "019" },\r
+ { "GG" , 831, "154", URGN_TERRITORY, "150" },\r
+ { "GH" , 288, "011", URGN_TERRITORY, "002" },\r
+ { "GI" , 292, "039", URGN_TERRITORY, "150" },\r
+ { "GL" , 304, "021", URGN_TERRITORY, "019" },\r
+ { "GM" , 270, "011", URGN_TERRITORY, "002" },\r
+ { "GN" , 324, "011", URGN_TERRITORY, "002" },\r
+ { "GP" , 312, "029", URGN_TERRITORY, "019" },\r
+ { "GQ" , 226, "017", URGN_TERRITORY, "002" },\r
+ { "GR" , 300, "039", URGN_TERRITORY, "150" },\r
+ { "GS" , 239, "QO" , URGN_TERRITORY, "009" },\r
+ { "GT" , 320, "013", URGN_TERRITORY, "019" },\r
+ { "GU" , 316, "057", URGN_TERRITORY, "009" },\r
+ { "GW" , 624, "011", URGN_TERRITORY, "002" },\r
+ { "GY" , 328, "005", URGN_TERRITORY, "019" },\r
+ { "HK" , 344, "030", URGN_TERRITORY, "142" },\r
+ { "HM" , 334, "QO" , URGN_TERRITORY, "009" },\r
+ { "HN" , 340, "013", URGN_TERRITORY, "019" },\r
+ { "HR" , 191, "039", URGN_TERRITORY, "150" },\r
+ { "HT" , 332, "029", URGN_TERRITORY, "019" },\r
+ { "HU" , 348, "151", URGN_TERRITORY, "150" },\r
+ { "IC" , -1, "015", URGN_TERRITORY, "002" },\r
+ { "ID" , 360, "035", URGN_TERRITORY, "142" },\r
+ { "IE" , 372, "154", URGN_TERRITORY, "150" },\r
+ { "IL" , 376, "145", URGN_TERRITORY, "142" },\r
+ { "IM" , 833, "154", URGN_TERRITORY, "150" },\r
+ { "IN" , 356, "034", URGN_TERRITORY, "142" },\r
+ { "IO" , 86, "QO" , URGN_TERRITORY, "009" },\r
+ { "IQ" , 368, "145", URGN_TERRITORY, "142" },\r
+ { "IR" , 364, "034", URGN_TERRITORY, "142" },\r
+ { "IS" , 352, "154", URGN_TERRITORY, "150" },\r
+ { "IT" , 380, "039", URGN_TERRITORY, "150" },\r
+ { "JE" , 832, "154", URGN_TERRITORY, "150" },\r
+ { "JM" , 388, "029", URGN_TERRITORY, "019" },\r
+ { "JO" , 400, "145", URGN_TERRITORY, "142" },\r
+ { "JP" , 392, "030", URGN_TERRITORY, "142" },\r
+ { "KE" , 404, "014", URGN_TERRITORY, "002" },\r
+ { "KG" , 417, "143", URGN_TERRITORY, "142" },\r
+ { "KH" , 116, "035", URGN_TERRITORY, "142" },\r
+ { "KI" , 296, "057", URGN_TERRITORY, "009" },\r
+ { "KM" , 174, "014", URGN_TERRITORY, "002" },\r
+ { "KN" , 659, "029", URGN_TERRITORY, "019" },\r
+ { "KP" , 408, "030", URGN_TERRITORY, "142" },\r
+ { "KR" , 410, "030", URGN_TERRITORY, "142" },\r
+ { "KW" , 414, "145", URGN_TERRITORY, "142" },\r
+ { "KY" , 136, "029", URGN_TERRITORY, "019" },\r
+ { "KZ" , 398, "143", URGN_TERRITORY, "142" },\r
+ { "LA" , 418, "035", URGN_TERRITORY, "142" },\r
+ { "LB" , 422, "145", URGN_TERRITORY, "142" },\r
+ { "LC" , 662, "029", URGN_TERRITORY, "019" },\r
+ { "LI" , 438, "155", URGN_TERRITORY, "150" },\r
+ { "LK" , 144, "034", URGN_TERRITORY, "142" },\r
+ { "LR" , 430, "011", URGN_TERRITORY, "002" },\r
+ { "LS" , 426, "018", URGN_TERRITORY, "002" },\r
+ { "LT" , 440, "154", URGN_TERRITORY, "150" },\r
+ { "LU" , 442, "155", URGN_TERRITORY, "150" },\r
+ { "LV" , 428, "154", URGN_TERRITORY, "150" },\r
+ { "LY" , 434, "015", URGN_TERRITORY, "002" },\r
+ { "MA" , 504, "015", URGN_TERRITORY, "002" },\r
+ { "MC" , 492, "155", URGN_TERRITORY, "150" },\r
+ { "MD" , 498, "151", URGN_TERRITORY, "150" },\r
+ { "ME" , 499, "039", URGN_TERRITORY, "150" },\r
+ { "MF" , 663, "029", URGN_TERRITORY, "019" },\r
+ { "MG" , 450, "014", URGN_TERRITORY, "002" },\r
+ { "MH" , 584, "057", URGN_TERRITORY, "009" },\r
+ { "MK" , 807, "039", URGN_TERRITORY, "150" },\r
+ { "ML" , 466, "011", URGN_TERRITORY, "002" },\r
+ { "MM" , 104, "035", URGN_TERRITORY, "142" },\r
+ { "MN" , 496, "030", URGN_TERRITORY, "142" },\r
+ { "MO" , 446, "030", URGN_TERRITORY, "142" },\r
+ { "MP" , 580, "057", URGN_TERRITORY, "009" },\r
+ { "MQ" , 474, "029", URGN_TERRITORY, "019" },\r
+ { "MR" , 478, "011", URGN_TERRITORY, "002" },\r
+ { "MS" , 500, "029", URGN_TERRITORY, "019" },\r
+ { "MT" , 470, "039", URGN_TERRITORY, "150" },\r
+ { "MU" , 480, "014", URGN_TERRITORY, "002" },\r
+ { "MV" , 462, "034", URGN_TERRITORY, "142" },\r
+ { "MW" , 454, "014", URGN_TERRITORY, "002" },\r
+ { "MX" , 484, "013", URGN_TERRITORY, "019"},\r
+ { "MY" , 458, "035", URGN_TERRITORY, "142" },\r
+ { "MZ" , 508, "014", URGN_TERRITORY, "002" },\r
+ { "NA" , 516, "018", URGN_TERRITORY, "002" },\r
+ { "NC" , 540, "054", URGN_TERRITORY, "009" },\r
+ { "NE" , 562, "011", URGN_TERRITORY, "002" },\r
+ { "NF" , 574, "053", URGN_TERRITORY, "009" },\r
+ { "NG" , 566, "011", URGN_TERRITORY, "002" },\r
+ { "NI" , 558, "013", URGN_TERRITORY, "019" },\r
+ { "NL" , 528, "155", URGN_TERRITORY, "150" },\r
+ { "NO" , 578, "154", URGN_TERRITORY, "150" },\r
+ { "NP" , 524, "034", URGN_TERRITORY, "142" },\r
+ { "NR" , 520, "057", URGN_TERRITORY, "009" },\r
+ { "NT" , 536, NULL , URGN_DEPRECATED, NULL },\r
+ { "NU" , 570, "061", URGN_TERRITORY, "009" },\r
+ { "NZ" , 554, "053", URGN_TERRITORY, "009" },\r
+ { "OM" , 512, "145", URGN_TERRITORY, "142" },\r
+ { "PA" , 591, "013", URGN_TERRITORY, "019" },\r
+ { "PE" , 604, "005", URGN_TERRITORY, "019" },\r
+ { "PF" , 258, "061", URGN_TERRITORY, "009" },\r
+ { "PG" , 598, "054", URGN_TERRITORY, "009" },\r
+ { "PH" , 608, "035", URGN_TERRITORY, "142" },\r
+ { "PK" , 586, "034", URGN_TERRITORY, "142" },\r
+ { "PL" , 616, "151", URGN_TERRITORY, "150" },\r
+ { "PM" , 666, "021", URGN_TERRITORY, "019" },\r
+ { "PN" , 612, "061", URGN_TERRITORY, "009" },\r
+ { "PR" , 630, "029", URGN_TERRITORY, "019" },\r
+ { "PS" , 275, "145", URGN_TERRITORY, "142" },\r
+ { "PT" , 620, "039", URGN_TERRITORY, "150" },\r
+ { "PW" , 585, "057", URGN_TERRITORY, "009" },\r
+ { "PY" , 600, "005", URGN_TERRITORY, "019" },\r
+ { "QA" , 634, "145", URGN_TERRITORY, "142" },\r
+ { "QO" , 961, "009", URGN_SUBCONTINENT, "009" },\r
+ { "QU" , 967, NULL, URGN_GROUPING, NULL },\r
+ { "RE" , 638, "014", URGN_TERRITORY, "002" },\r
+ { "RO" , 642, "151", URGN_TERRITORY, "150" },\r
+ { "RS" , 688, "039", URGN_TERRITORY, "150" },\r
+ { "RU" , 643, "151", URGN_TERRITORY, "150" },\r
+ { "RW" , 646, "014", URGN_TERRITORY, "002" },\r
+ { "SA" , 682, "145", URGN_TERRITORY, "142" },\r
+ { "SB" , 90, "054", URGN_TERRITORY, "009" },\r
+ { "SC" , 690, "014", URGN_TERRITORY, "002" },\r
+ { "SD" , 729, "015", URGN_TERRITORY, "002" },\r
+ { "SE" , 752, "154", URGN_TERRITORY, "150" },\r
+ { "SG" , 702, "035", URGN_TERRITORY, "142" },\r
+ { "SH" , 654, "011", URGN_TERRITORY, "002" },\r
+ { "SI" , 705, "039", URGN_TERRITORY, "150" },\r
+ { "SJ" , 744, "154", URGN_TERRITORY, "150" },\r
+ { "SK" , 703, "151", URGN_TERRITORY, "150" },\r
+ { "SL" , 694, "011", URGN_TERRITORY, "002" },\r
+ { "SM" , 674, "039", URGN_TERRITORY, "150" },\r
+ { "SN" , 686, "011", URGN_TERRITORY, "002" },\r
+ { "SO" , 706, "014", URGN_TERRITORY, "002" },\r
+ { "SR" , 740, "005", URGN_TERRITORY, "019" },\r
+ { "SS" , 728, "015", URGN_TERRITORY, "002" },\r
+ { "ST" , 678, "017", URGN_TERRITORY, "002" },\r
+ { "SU" , 810, NULL , URGN_DEPRECATED , NULL},\r
+ { "SV" , 222, "013", URGN_TERRITORY, "019" },\r
+ { "SX" , 534, "029", URGN_TERRITORY, "019" },\r
+ { "SY" , 760, "145", URGN_TERRITORY, "142" },\r
+ { "SZ" , 748, "018", URGN_TERRITORY, "002" },\r
+ { "TA" , -1, "QO", URGN_TERRITORY, "009" },\r
+ { "TC" , 796, "029", URGN_TERRITORY, "019" },\r
+ { "TD" , 148, "017", URGN_TERRITORY, "002" },\r
+ { "TF" , 260, "QO" , URGN_TERRITORY, "009" },\r
+ { "TG" , 768, "011", URGN_TERRITORY, "002" },\r
+ { "TH" , 764, "035", URGN_TERRITORY, "142" },\r
+ { "TJ" , 762, "143", URGN_TERRITORY, "142" },\r
+ { "TK" , 772, "061", URGN_TERRITORY, "009" },\r
+ { "TL" , 626, "035", URGN_TERRITORY, "142" },\r
+ { "TM" , 795, "143", URGN_TERRITORY, "142" },\r
+ { "TN" , 788, "015", URGN_TERRITORY, "002" },\r
+ { "TO" , 776, "061", URGN_TERRITORY, "009" },\r
+ { "TP" , 626, "035", URGN_TERRITORY, "142" },\r
+ { "TR" , 792, "145", URGN_TERRITORY, "142" },\r
+ { "TT" , 780, "029", URGN_TERRITORY, "019" },\r
+ { "TV" , 798, "061", URGN_TERRITORY, "009" },\r
+ { "TW" , 158, "030", URGN_TERRITORY, "142" },\r
+ { "TZ" , 834, "014", URGN_TERRITORY, "002" },\r
+ { "UA" , 804, "151", URGN_TERRITORY, "150" },\r
+ { "UG" , 800, "014", URGN_TERRITORY, "002" },\r
+ { "UM" , 581, "QO" , URGN_TERRITORY, "009" },\r
+ { "US" , 840, "021", URGN_TERRITORY, "019" },\r
+ { "UY" , 858, "005", URGN_TERRITORY, "019" },\r
+ { "UZ" , 860, "143", URGN_TERRITORY, "142" },\r
+ { "VA" , 336, "039", URGN_TERRITORY, "150" },\r
+ { "VC" , 670, "029", URGN_TERRITORY, "019" },\r
+ { "VE" , 862, "005", URGN_TERRITORY, "019" },\r
+ { "VG" , 92, "029", URGN_TERRITORY, "019" },\r
+ { "VI" , 850, "029", URGN_TERRITORY, "019" },\r
+ { "VN" , 704, "035", URGN_TERRITORY, "142" },\r
+ { "VU" , 548, "054", URGN_TERRITORY, "009" },\r
+ { "WF" , 876, "061", URGN_TERRITORY, "009" },\r
+ { "WS" , 882, "061", URGN_TERRITORY, "009" },\r
+ { "YD" , 887, "145", URGN_TERRITORY, "142" },\r
+ { "YE" , 887, "145", URGN_TERRITORY, "142" },\r
+ { "YT" , 175, "014", URGN_TERRITORY, "002" },\r
+ { "ZA" , 710, "018", URGN_TERRITORY, "002" },\r
+ { "ZM" , 894, "014", URGN_TERRITORY, "002" },\r
+ { "ZR" , 180, "017", URGN_TERRITORY, "002" },\r
+ { "ZW" , 716, "014", URGN_TERRITORY, "002" },\r
+ { "ZZ" , 999, NULL , URGN_UNKNOWN, NULL }\r
+ };\r
+\r
+// *****************************************************************************\r
+// class RegionTest\r
+// *****************************************************************************\r
+\r
+\r
+RegionTest::RegionTest() {\r
+}\r
+\r
+RegionTest::~RegionTest() {\r
+}\r
+\r
+#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break;\r
+\r
+void \r
+RegionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )\r
+{\r
+ optionv = (par && *par=='v');\r
+ switch (index) {\r
+ CASE(0, TestKnownRegions)\r
+ CASE(1, TestGetInstanceString)\r
+ CASE(2, TestGetInstanceInt)\r
+ CASE(3, TestGetContainedRegions)\r
+ CASE(4, TestGetContainedRegionsWithType)\r
+ CASE(5, TestGetContainingRegion)\r
+ CASE(6, TestGetContainingRegionWithType)\r
+ CASE(7, TestGetPreferredValues)\r
+ CASE(8, TestContains);\r
+ CASE(9, TestAvailableTerritories)\r
+ default: name = ""; break;\r
+ }\r
+}\r
+\r
+\r
+void RegionTest::TestKnownRegions() {\r
+\r
+ for (int32_t i = 0 ; i < LENGTHOF(knownRegions) ; i++ ) {\r
+ KnownRegion rd = knownRegions[i];\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ const Region *r = Region::getInstance(rd.code,status);\r
+ if ( r ) {\r
+ int32_t n = r->getNumericCode();\r
+ int32_t e = rd.numeric;\r
+ if ( n != e ) {\r
+ errln("Numeric code mismatch for region %s. Expected:%d Got:%d",r->getRegionCode(),e,n);\r
+ }\r
+\r
+ if (r->getType() != rd.type) {\r
+ errln("Expected region %s to be of type %d. Got: %d",r->getRegionCode(),rd.type,r->getType());\r
+ }\r
+\r
+ int32_t nc = rd.numeric;\r
+ if ( nc > 0 ) {\r
+ const Region *ncRegion = Region::getInstance(nc,status);\r
+ if ( *ncRegion != *r && nc != 891 ) { // 891 is special case - CS and YU both deprecated codes for region 891\r
+ errln("Creating region %s by its numeric code returned a different region. Got: %s instead.",r->getRegionCode(),ncRegion->getRegionCode());\r
+ }\r
+ }\r
+ } else {\r
+ errln("Known region %s was not recognized.",rd.code);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestGetInstanceString() {\r
+ typedef struct TestData {\r
+ const char *inputID;\r
+ const char *expectedID;\r
+ URegionType expectedType;\r
+ } TestData;\r
+\r
+ static TestData testData[] = {\r
+ // Input ID, Expected ID, Expected Type\r
+ { "DE", "DE", URGN_TERRITORY }, // Normal region\r
+ { "QU", "EU", URGN_GROUPING }, // Alias to a grouping\r
+ { "DD", "DE", URGN_TERRITORY }, // Alias to a deprecated region (East Germany) with single preferred value\r
+ { "276", "DE", URGN_TERRITORY }, // Numeric code for Germany\r
+ { "278", "DE", URGN_TERRITORY }, // Numeric code for East Germany (Deprecated)\r
+ { "SU", "SU", URGN_DEPRECATED }, // Alias to a deprecated region with multiple preferred values\r
+ { "AN", "AN", URGN_DEPRECATED }, // Deprecated region with multiple preferred values\r
+ { "SVK", "SK", URGN_TERRITORY } // 3-letter code - Slovakia\r
+ };\r
+\r
+\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ const Region *r = Region::getInstance(NULL,status);\r
+ if ( status != U_ILLEGAL_ARGUMENT_ERROR ) {\r
+ errln("Calling Region::getInstance(NULL) should have triggered an U_ILLEGAL_ARGUMENT_ERROR, but didn't.");\r
+ }\r
+\r
+ status = U_ZERO_ERROR;\r
+ r = Region::getInstance("BOGUS",status);\r
+ if ( status != U_ILLEGAL_ARGUMENT_ERROR ) {\r
+ errln("Calling Region::getInstance(\"BOGUS\") should have triggered an U_ILLEGAL_ARGUMENT_ERROR, but didn't.");\r
+ }\r
+\r
+\r
+ for (int32_t i = 0 ; i < LENGTHOF(testData) ; i++ ) {\r
+ TestData data = testData[i];\r
+ status = U_ZERO_ERROR;\r
+ r = Region::getInstance(data.inputID,status);\r
+ const char *id;\r
+ URegionType type;\r
+ if ( r ) {\r
+ id = r->getRegionCode();\r
+ type = r->getType();\r
+ } else {\r
+ id = "NULL";\r
+ type = URGN_UNKNOWN;\r
+ }\r
+ if ( uprv_strcmp(id,data.expectedID)) {\r
+ errln("Unexpected region ID for Region::getInstance(\"%s\"); Expected: %s Got: %s",data.inputID,data.expectedID,id);\r
+ }\r
+ if ( type != data.expectedType) {\r
+ errln("Unexpected region type for Region::getInstance(\"%s\"); Expected: %d Got: %d",data.inputID,data.expectedType,type);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestGetInstanceInt() {\r
+ typedef struct TestData {\r
+ int32_t inputID;\r
+ const char *expectedID;\r
+ URegionType expectedType;\r
+ } TestData;\r
+\r
+ static TestData testData[] = {\r
+ // Input ID, Expected ID, Expected Type\r
+ { 276, "DE", URGN_TERRITORY }, // Numeric code for Germany\r
+ { 278, "DE", URGN_TERRITORY }, // Numeric code for East Germany (Deprecated)\r
+ { 419, "419", URGN_GROUPING }, // Latin America\r
+ { 736, "SD", URGN_TERRITORY }, // Sudan (pre-2011) - changed numeric code after South Sudan split off\r
+ { 729, "SD", URGN_TERRITORY }, // Sudan (post-2011) - changed numeric code after South Sudan split off\r
+ };\r
+\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ const Region *r = Region::getInstance(-123,status);\r
+ if ( status != U_ILLEGAL_ARGUMENT_ERROR ) {\r
+ errln("Calling Region::getInstance(-123) should have triggered an U_ILLEGAL_ARGUMENT_ERROR, but didn't.");\r
+ }\r
+\r
+ for (int32_t i = 0 ; i < LENGTHOF(testData) ; i++ ) {\r
+ TestData data = testData[i];\r
+ status = U_ZERO_ERROR;\r
+ const Region *r = Region::getInstance(data.inputID,status);\r
+ const char *id;\r
+ URegionType type;\r
+ if ( r ) {\r
+ id = r->getRegionCode();\r
+ type = r->getType();\r
+ } else {\r
+ id = "NULL";\r
+ type = URGN_UNKNOWN;\r
+ }\r
+ if ( uprv_strcmp(data.expectedID,id)) {\r
+ errln("Unexpected region ID for Region.getInstance(%d)); Expected: %s Got: %s",data.inputID,data.expectedID,id);\r
+ }\r
+ if ( data.expectedType != type) {\r
+ errln("Unexpected region type for Region.getInstance(%d)); Expected: %d Got: %d",data.inputID,data.expectedType,type);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestGetContainedRegions() {\r
+ for (int32_t i = 0 ; i < LENGTHOF(knownRegions) ; i++ ) {\r
+ KnownRegion rd = knownRegions[i];\r
+ UErrorCode status = U_ZERO_ERROR;\r
+\r
+ const Region *r = Region::getInstance(rd.code,status);\r
+ if (r) {\r
+ if (r->getType() == URGN_GROUPING) {\r
+ continue;\r
+ }\r
+ StringEnumeration *containedRegions = r->getContainedRegions();\r
+ int32_t count = containedRegions->count(status);\r
+ for ( int32_t i = 0 ; i < containedRegions->count(status); i++ ) {\r
+ const char *crID = containedRegions->next(NULL,status);\r
+ const Region *cr = Region::getInstance(crID,status);\r
+ const Region *containingRegion = cr ? cr->getContainingRegion() : NULL;\r
+ if ( !containingRegion || *containingRegion != *r ) {\r
+ errln("Region: %s contains region %s. Expected containing region of this region to be the original region, but got %s",\r
+ r->getRegionCode(),cr->getRegionCode(),containingRegion?containingRegion->getRegionCode():"NULL"); \r
+ }\r
+ }\r
+ } else {\r
+ errln("Known region %s was not recognized.",rd.code);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestGetContainedRegionsWithType() {\r
+ for (int32_t i = 0 ; i < LENGTHOF(knownRegions) ; i++ ) {\r
+ KnownRegion rd = knownRegions[i];\r
+ UErrorCode status = U_ZERO_ERROR;\r
+\r
+ const Region *r = Region::getInstance(rd.code,status);\r
+ if (r) {\r
+ if (r->getType() != URGN_CONTINENT) {\r
+ continue;\r
+ }\r
+ StringEnumeration *containedRegions = r->getContainedRegions(URGN_TERRITORY);\r
+ for ( int32_t j = 0 ; j < containedRegions->count(status); j++ ) {\r
+ const char *crID = containedRegions->next(NULL,status);\r
+ const Region *cr = Region::getInstance(crID,status);\r
+ const Region *containingRegion = cr ? cr->getContainingRegion(URGN_CONTINENT) : NULL;\r
+ if ( !containingRegion || *containingRegion != *r ) {\r
+ errln("Continent: %s contains territory %s. Expected containing continent of this region to be the original region, but got %s",\r
+ r->getRegionCode(),cr->getRegionCode(),containingRegion?containingRegion->getRegionCode():"NULL"); \r
+ }\r
+ }\r
+ } else {\r
+ errln("Known region %s was not recognized.",rd.code);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestGetContainingRegion() { \r
+ for (int32_t i = 0 ; i < LENGTHOF(knownRegions) ; i++ ) {\r
+ KnownRegion rd = knownRegions[i];\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ const Region *r = Region::getInstance(rd.code,status);\r
+ if (r) {\r
+ const Region *c = r->getContainingRegion();\r
+ if (rd.parent == NULL) { \r
+ if ( c ) {\r
+ errln("Containing region for %s should have been NULL. Got: %s",r->getRegionCode(),c->getRegionCode());\r
+ }\r
+ } else {\r
+ const Region *p = Region::getInstance(rd.parent,status); \r
+ if ( !c || *p != *c ) {\r
+ errln("Expected containing continent of region %s to be %s. Got: %s",\r
+ r->getRegionCode(),p?p->getRegionCode():"NULL",c?c->getRegionCode():"NULL" );\r
+ }\r
+ }\r
+ } else {\r
+ errln("Known region %s was not recognized.",rd.code);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestGetContainingRegionWithType() { \r
+ for (int32_t i = 0 ; i < LENGTHOF(knownRegions) ; i++ ) {\r
+ KnownRegion rd = knownRegions[i];\r
+ UErrorCode status = U_ZERO_ERROR;\r
+\r
+ const Region *r = Region::getInstance(rd.code,status);\r
+ if (r) {\r
+ const Region *c = r->getContainingRegion(URGN_CONTINENT);\r
+ if (rd.containingContinent == NULL) {\r
+ if ( c != NULL) {\r
+ errln("Containing continent for %s should have been NULL. Got: %s",r->getRegionCode(), c->getRegionCode());\r
+ }\r
+ } else {\r
+ const Region *p = Region::getInstance(rd.containingContinent,status); \r
+ if ( *p != *c ) {\r
+ errln("Expected containing continent of region %s to be %s. Got: %s",\r
+ r->getRegionCode(),p?p->getRegionCode():"NULL",c?c->getRegionCode():"NULL" );\r
+ }\r
+ }\r
+ } else {\r
+ errln("Known region %s was not recognized.",rd.code);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestGetPreferredValues() {\r
+ static const char *testData[6][17] = {\r
+ // Input ID, Expected Preferred Values...\r
+ { "AN", "CW", "SX", "BQ", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, // Netherlands Antilles\r
+ { "CS", "RS", "ME", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, // Serbia & Montenegro\r
+ { "FQ", "AQ", "TF", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, // French Southern and Antarctic Territories\r
+ { "NT", "IQ", "SA", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, // Neutral Zone\r
+ { "PC", "FM", "MH", "MP", "PW", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }, // Pacific Islands Trust Territory\r
+ { "SU", "RU", "AM", "AZ", "BY", "EE", "GE", "KZ", "KG", "LV", "LT", "MD", "TJ", "TM", "UA", "UZ" , NULL}, // Soviet Union\r
+ };\r
+\r
+ for ( int32_t i = 0 ; i < 6 ; i++ ) {\r
+ const char **data = testData[i];\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ const Region *r = Region::getInstance(data[0],status);\r
+ if (r) {\r
+ StringEnumeration *preferredValues = r->getPreferredValues();\r
+ for ( int i = 1 ; data[i] ; i++ ) {\r
+ UBool found = FALSE;\r
+ preferredValues->reset(status);\r
+ while ( const char *check = preferredValues->next(NULL,status) ) {\r
+ if ( !uprv_strcmp(check,data[i]) ) {\r
+ found = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ if ( !found ) {\r
+ errln("Region::getPreferredValues() for region \"%s\" should have contained \"%s\" but it didn't.",r->getRegionCode(),data[i]);\r
+ }\r
+ }\r
+ } else {\r
+ errln("Known region %s was not recognized.",data[0]);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestContains() { \r
+ for (int32_t i = 0 ; i < LENGTHOF(knownRegions) ; i++ ) {\r
+ KnownRegion rd = knownRegions[i];\r
+ UErrorCode status = U_ZERO_ERROR;\r
+\r
+ const Region *r = Region::getInstance(rd.code,status);\r
+ if (r) {\r
+ const Region *c = r->getContainingRegion();\r
+ while ( c ) {\r
+ if ( !c->contains(*r)) {\r
+ errln("Region \"%s\" should have contained \"%s\" but it didn't.",c->getRegionCode(),r->getRegionCode());\r
+ }\r
+ c = c->getContainingRegion();\r
+ }\r
+ } else {\r
+ errln("Known region %s was not recognized.",rd.code);\r
+ }\r
+ }\r
+}\r
+\r
+void RegionTest::TestAvailableTerritories() {\r
+ // Test to make sure that the set of territories contained in World and the set of all available\r
+ // territories are one and the same.\r
+ UErrorCode status = U_ZERO_ERROR;\r
+ StringEnumeration *availableTerritories = Region::getAvailable(URGN_TERRITORY);\r
+ const Region *world = Region::getInstance("001",status);\r
+ StringEnumeration *containedInWorld = world->getContainedRegions(URGN_TERRITORY);\r
+ if ( !availableTerritories || !containedInWorld || *availableTerritories != *containedInWorld ) {\r
+ char availableTerritoriesString[1024] = "";\r
+ char containedInWorldString[1024] = "";\r
+ if ( availableTerritories ) {\r
+ for (int32_t i = 0 ; i < availableTerritories->count(status) ; i++ ) {\r
+ if ( i > 0 ) {\r
+ uprv_strcat(availableTerritoriesString," ");\r
+ }\r
+ uprv_strcat(availableTerritoriesString,availableTerritories->next(NULL,status));\r
+ }\r
+ } else {\r
+ uprv_strcpy(availableTerritoriesString,"NULL");\r
+ }\r
+ if ( containedInWorld ) {\r
+ for (int32_t i = 0 ; i < containedInWorld->count(status) ; i++ ) {\r
+ if ( i > 0 ) {\r
+ uprv_strcat(containedInWorldString," ");\r
+ }\r
+ uprv_strcat(containedInWorldString,containedInWorld->next(NULL,status));\r
+ }\r
+ } else {\r
+ uprv_strcpy(containedInWorldString,"NULL");\r
+ }\r
+ errln("Available territories and all territories contained in world should be the same set.\nAvailable = %s\nContained in World = %s",\r
+ availableTerritoriesString,containedInWorldString);\r
+ }\r
+ }\r
+#endif /* #if !UCONFIG_NO_FORMATTING */\r
+\r
+//eof\r