diff --git a/icu4c/source/i18n/uspoof.cpp b/icu4c/source/i18n/uspoof.cpp index b7f47ba6caf..551ba03d3a4 100644 --- a/icu4c/source/i18n/uspoof.cpp +++ b/icu4c/source/i18n/uspoof.cpp @@ -40,8 +40,8 @@ U_NAMESPACE_USE static UnicodeSet *gInclusionSet = NULL; static UnicodeSet *gRecommendedSet = NULL; static const Normalizer2 *gNfdNormalizer = NULL; +static SpoofData *gDefaultSpoofData = NULL; static UInitOnce gSpoofInitOnce = U_INITONCE_INITIALIZER; - static UBool U_CALLCONV uspoof_cleanup(void) { delete gInclusionSet; @@ -49,6 +49,10 @@ uspoof_cleanup(void) { delete gRecommendedSet; gRecommendedSet = NULL; gNfdNormalizer = NULL; + if (gDefaultSpoofData) { + gDefaultSpoofData->removeReference(); // Will delete, assuming all user-level spoof checkers were closed. + } + gDefaultSpoofData = NULL; gSpoofInitOnce.reset(); return TRUE; } @@ -125,17 +129,24 @@ static void U_CALLCONV initializeStatics(UErrorCode &status) { gRecommendedSet = new UnicodeSet(UnicodeString(recommendedPat, -1, US_INV), status); gRecommendedSet->freeze(); gNfdNormalizer = Normalizer2::getNFDInstance(status); + gDefaultSpoofData = SpoofData::getDefault(status); ucln_i18n_registerCleanup(UCLN_I18N_SPOOF, uspoof_cleanup); } U_CAPI USpoofChecker * U_EXPORT2 uspoof_open(UErrorCode *status) { + umtx_initOnce(gSpoofInitOnce, &initializeStatics, *status); if (U_FAILURE(*status)) { return NULL; } - umtx_initOnce(gSpoofInitOnce, &initializeStatics, *status); - SpoofImpl *si = new SpoofImpl(SpoofData::getDefault(*status), *status); + SpoofImpl *si = new SpoofImpl(gDefaultSpoofData, *status); + if (si) { + gDefaultSpoofData->addReference(); + } + if (U_SUCCESS(*status) && si == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + } if (U_FAILURE(*status)) { delete si; si = NULL; diff --git a/icu4c/source/i18n/uspoof_impl.cpp b/icu4c/source/i18n/uspoof_impl.cpp index 9c662f80483..e9077d3ac34 100644 --- a/icu4c/source/i18n/uspoof_impl.cpp +++ b/icu4c/source/i18n/uspoof_impl.cpp @@ -1,6 +1,6 @@ /* ********************************************************************** -* Copyright (C) 2008-2014, International Business Machines +* Copyright (C) 2008-2015, International Business Machines * Corporation and others. All Rights Reserved. ********************************************************************** */ @@ -28,12 +28,11 @@ U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SpoofImpl) SpoofImpl::SpoofImpl(SpoofData *data, UErrorCode &status) : - fMagic(0), fChecks(USPOOF_ALL_CHECKS), fSpoofData(NULL), fAllowedCharsSet(NULL) , + fMagic(0), fChecks(USPOOF_ALL_CHECKS), fSpoofData(data), fAllowedCharsSet(NULL) , fAllowedLocales(NULL), fCachedIdentifierInfo(NULL) { if (U_FAILURE(status)) { return; } - fSpoofData = data; fRestrictionLevel = USPOOF_HIGHLY_RESTRICTIVE; UnicodeSet *allowedCharsSet = new UnicodeSet(0, 0x10ffff); @@ -500,11 +499,12 @@ spoofDataIsAcceptable(void *context, // // SpoofData::getDefault() - return a wrapper around the spoof data that is -// baked into the default ICU data. +// baked into the default ICU data. +// +// Called once, from the initOnce() function in uspoof_impl.cpp; the resulting +// SpoofData is shared by all spoof checkers using the default data. // SpoofData *SpoofData::getDefault(UErrorCode &status) { - // TODO: Cache it. Lazy create, keep until cleanup. - UDataMemory *udm = udata_openChoice(NULL, "cfu", "confusables", spoofDataIsAcceptable, NULL, // context, would receive dataVersion if supplied. @@ -567,7 +567,6 @@ SpoofData::SpoofData(UErrorCode &status) { return; } fDataOwned = true; - fRefCount = 1; // The spoof header should already be sized to be a multiple of 16 bytes. // Just in case it's not, round it up.