diff --git a/icu4c/source/i18n/region.cpp b/icu4c/source/i18n/region.cpp index 9b4f3705aa9..67505035d45 100644 --- a/icu4c/source/i18n/region.cpp +++ b/icu4c/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. ******************************************************************************* * @@ -232,13 +232,13 @@ 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); + 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); + 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; @@ -261,7 +261,7 @@ void Region::loadRegionData(UErrorCode &status) { // 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); + 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; @@ -373,6 +373,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 { @@ -381,6 +382,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 { @@ -419,7 +421,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); @@ -468,7 +470,7 @@ Region::getInstance (int32_t 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); @@ -483,9 +485,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; } @@ -519,11 +520,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); } /** @@ -535,9 +532,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); } @@ -548,16 +547,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); @@ -565,7 +563,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); @@ -612,14 +610,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); } diff --git a/icu4c/source/i18n/unicode/region.h b/icu4c/source/i18n/unicode/region.h index c33681e7e79..cb75234bf9b 100644 --- a/icu4c/source/i18n/unicode/region.h +++ b/icu4c/source/i18n/unicode/region.h @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2014, International Business Machines Corporation and others. + * Copyright (C) 2014-2015, International Business Machines Corporation and others. * All Rights Reserved. ******************************************************************************* */ @@ -104,9 +104,9 @@ public: #ifndef U_HIDE_DRAFT_API /** * Returns an enumeration over the IDs of all known regions that match the given type. - * @draft ICU 51 + * @draft ICU 55 */ - static StringEnumeration* U_EXPORT2 getAvailable(URegionType type); + static StringEnumeration* U_EXPORT2 getAvailable(URegionType type, UErrorCode &status); #endif /* U_HIDE_DRAFT_API */ /** @@ -135,18 +135,18 @@ public: * any sub-regions. For example, calling this method with region "150" (Europe) returns an enumeration containing * the various sub regions of Europe - "039" (Southern Europe) - "151" (Eastern Europe) - "154" (Northern Europe) * and "155" (Western Europe). - * @draft ICU 51 + * @draft ICU 55 */ - StringEnumeration* getContainedRegions() const; + StringEnumeration* getContainedRegions(UErrorCode &status) const; /** * Returns an enumeration over the IDs of all the regions that are children of this region anywhere in the region * hierarchy and match the given type. This API may return an empty enumeration if this region doesn't have any * sub-regions that match the given type. For example, calling this method with region "150" (Europe) and type * "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR" (France) - "IT" (Italy) - "DE" (Germany) etc. ) - * @draft ICU 51 + * @draft ICU 55 */ - StringEnumeration* getContainedRegions( URegionType type ) const; + StringEnumeration* getContainedRegions( URegionType type, UErrorCode &status ) const; #endif /* U_HIDE_DRAFT_API */ /** @@ -160,9 +160,9 @@ public: * For deprecated regions, return an enumeration over the IDs of the regions that are the preferred replacement * regions for this region. Returns null for a non-deprecated region. For example, calling this method with region * "SU" (Soviet Union) would return a list of the regions containing "RU" (Russia), "AM" (Armenia), "AZ" (Azerbaijan), etc... - * @draft ICU 51 + * @draft ICU 55 */ - StringEnumeration* getPreferredValues() const; + StringEnumeration* getPreferredValues(UErrorCode &status) const; #endif /* U_HIDE_DRAFT_API */ /** diff --git a/icu4c/source/i18n/uregion.cpp b/icu4c/source/i18n/uregion.cpp index 5e4ba4ca528..58bd9d0a0cc 100644 --- a/icu4c/source/i18n/uregion.cpp +++ b/icu4c/source/i18n/uregion.cpp @@ -1,6 +1,6 @@ /* ***************************************************************************************** -* Copyright (C) 2013, International Business Machines Corporation and others. +* Copyright (C) 2013-2015, International Business Machines Corporation and others. * All Rights Reserved. ***************************************************************************************** */ @@ -12,6 +12,7 @@ #include "unicode/uregion.h" #include "unicode/region.h" #include "unicode/uenum.h" +#include "unicode/strenum.h" U_NAMESPACE_USE @@ -33,7 +34,8 @@ uregion_getRegionFromNumericCode (int32_t code, UErrorCode *status) U_CAPI UEnumeration* U_EXPORT2 uregion_getAvailable(URegionType type, UErrorCode *status) { - return uenum_openFromStringEnumeration( Region::getAvailable(type), status ); + StringEnumeration* strenum = Region::getAvailable(type, *status); + return uenum_openFromStringEnumeration( strenum, status ); } @@ -61,14 +63,16 @@ uregion_getContainingRegionOfType(const URegion* uregion, URegionType type) U_CAPI UEnumeration* U_EXPORT2 uregion_getContainedRegions(const URegion* uregion, UErrorCode *status) { - return uenum_openFromStringEnumeration( ((Region*)uregion)->getContainedRegions(), status); + StringEnumeration* strenum = ((Region*)uregion)->getContainedRegions(*status); + return uenum_openFromStringEnumeration( strenum, status); } U_CAPI UEnumeration* U_EXPORT2 uregion_getContainedRegionsOfType(const URegion* uregion, URegionType type, UErrorCode *status) { - return uenum_openFromStringEnumeration( ((Region*)uregion)->getContainedRegions(type), status); + StringEnumeration* strenum = ((Region*)uregion)->getContainedRegions(type, *status); + return uenum_openFromStringEnumeration( strenum, status); } @@ -82,7 +86,8 @@ uregion_contains(const URegion* uregion, const URegion* otherRegion) U_CAPI UEnumeration* U_EXPORT2 uregion_getPreferredValues(const URegion* uregion, UErrorCode *status) { - return uenum_openFromStringEnumeration( ((Region*)uregion)->getPreferredValues(), status); + StringEnumeration* strenum = ((Region*)uregion)->getPreferredValues(*status); + return uenum_openFromStringEnumeration( strenum, status); } diff --git a/icu4c/source/test/intltest/regiontst.cpp b/icu4c/source/test/intltest/regiontst.cpp index d2da87fec67..d8ce8bb661e 100644 --- a/icu4c/source/test/intltest/regiontst.cpp +++ b/icu4c/source/test/intltest/regiontst.cpp @@ -1,6 +1,6 @@ /*********************************************************************** * COPYRIGHT: - * Copyright (c) 2013-2014, International Business Machines Corporation + * Copyright (c) 2013-2015, International Business Machines Corporation * and others. All Rights Reserved. ***********************************************************************/ @@ -499,7 +499,11 @@ void RegionTest::TestGetContainedRegions() { if (r->getType() == URGN_GROUPING) { continue; } - StringEnumeration *containedRegions = r->getContainedRegions(); + StringEnumeration *containedRegions = r->getContainedRegions(status); + if (U_FAILURE(status)) { + errln("%s->getContainedRegions(status) failed: %s", r->getRegionCode(), u_errorName(status)); + continue; + } for ( int32_t i = 0 ; i < containedRegions->count(status); i++ ) { const char *crID = containedRegions->next(NULL,status); const Region *cr = Region::getInstance(crID,status); @@ -526,7 +530,11 @@ void RegionTest::TestGetContainedRegionsWithType() { if (r->getType() != URGN_CONTINENT) { continue; } - StringEnumeration *containedRegions = r->getContainedRegions(URGN_TERRITORY); + StringEnumeration *containedRegions = r->getContainedRegions(URGN_TERRITORY, status); + if (U_FAILURE(status)) { + errln("%s->getContainedRegions(URGN_TERRITORY, status) failed: %s", r->getRegionCode(), u_errorName(status)); + continue; + } for ( int32_t j = 0 ; j < containedRegions->count(status); j++ ) { const char *crID = containedRegions->next(NULL,status); const Region *cr = Region::getInstance(crID,status); @@ -608,7 +616,11 @@ void RegionTest::TestGetPreferredValues() { UErrorCode status = U_ZERO_ERROR; const Region *r = Region::getInstance(data[0],status); if (r) { - StringEnumeration *preferredValues = r->getPreferredValues(); + StringEnumeration *preferredValues = r->getPreferredValues(status); + if (U_FAILURE(status)) { + errln("%s->getPreferredValues(status) failed: %s", r->getRegionCode(), u_errorName(status)); + continue; + } for ( int i = 1 ; data[i] ; i++ ) { UBool found = FALSE; preferredValues->reset(status); @@ -653,13 +665,21 @@ void RegionTest::TestAvailableTerritories() { // Test to make sure that the set of territories contained in World and the set of all available // territories are one and the same. UErrorCode status = U_ZERO_ERROR; - StringEnumeration *availableTerritories = Region::getAvailable(URGN_TERRITORY); + StringEnumeration *availableTerritories = Region::getAvailable(URGN_TERRITORY, status); + if (U_FAILURE(status)) { + errln("Region::getAvailable(URGN_TERRITORY,status) failed: %s", u_errorName(status)); + return; + } const Region *world = Region::getInstance("001",status); if (U_FAILURE(status)) { dataerrln("Region::getInstance(\"001\",status) failed: %s", u_errorName(status)); return; } - StringEnumeration *containedInWorld = world->getContainedRegions(URGN_TERRITORY); + StringEnumeration *containedInWorld = world->getContainedRegions(URGN_TERRITORY, status); + if (U_FAILURE(status)) { + errln("world->getContainedRegions(URGN_TERRITORY, status) failed: %s", u_errorName(status)); + return; + } if ( !availableTerritories || !containedInWorld || *availableTerritories != *containedInWorld ) { char availableTerritoriesString[1024] = ""; char containedInWorldString[1024] = ""; @@ -697,7 +717,11 @@ void RegionTest::TestNoContainedRegions(void) { dataerrln("Fail called to Region::getInstance(\"BM\", status) - %s", u_errorName(status)); return; } - StringEnumeration *containedRegions = region->getContainedRegions(); + StringEnumeration *containedRegions = region->getContainedRegions(status); + if (U_FAILURE(status)) { + errln("%s->getContainedRegions(status) failed: %s", region->getRegionCode(), u_errorName(status)); + return; + } const char *emptyStr = containedRegions->next(NULL, status); if (U_FAILURE(status)||(emptyStr!=NULL)) { errln("Error, 'BM' should have no subregions, but returned str=%p, err=%s\n", emptyStr, u_errorName(status));