ICU-20169 Use smart pointers in all locale code instead of u*_close().

Doing this consistently first will make it easier to then clean up
resource management and error handling later.
This commit is contained in:
Fredrik Roubert 2018-10-31 15:07:05 +01:00 committed by Fredrik Roubert
parent 47ecbc4915
commit 91d38d14e8
7 changed files with 81 additions and 84 deletions

View file

@ -125,7 +125,6 @@ static UBool U_CALLCONV uloc_cleanup(void) {
// via the initOnce mechanism.
static void U_CALLCONV loadInstalledLocales() {
UResourceBundle *indexLocale = NULL;
UResourceBundle installed;
UErrorCode status = U_ZERO_ERROR;
int32_t i = 0;
@ -136,9 +135,14 @@ static void U_CALLCONV loadInstalledLocales() {
_installedLocalesCount = 0;
ures_initStackObject(&installed);
indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status);
ures_getByKey(indexLocale, _kIndexTag, &installed, &status);
icu::LocalUResourceBundlePointer indexLocale(ures_openDirect(NULL, _kIndexLocaleName, &status));
// Automatically call ures_close() on this when it goes out of scope.
icu::LocalUResourceBundlePointer installedCloser(&installed);
ures_getByKey(indexLocale.getAlias(), _kIndexTag, &installed, &status);
if(U_SUCCESS(status)) {
localeCount = ures_getSize(&installed);
_installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1));
@ -152,8 +156,6 @@ static void U_CALLCONV loadInstalledLocales() {
ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup);
}
}
ures_close(&installed);
ures_close(indexLocale);
}
static void _load_installedLocales()

View file

@ -22,6 +22,7 @@
#include "unicode/utypes.h"
#include "unicode/brkiter.h"
#include "unicode/locid.h"
#include "unicode/uenum.h"
#include "unicode/uloc.h"
#include "unicode/ures.h"
#include "unicode/ustring.h"
@ -306,14 +307,11 @@ _getStringOrCopyKey(const char *path, const char *locale,
if(itemKey==NULL) {
/* top-level item: normal resource bundle access */
UResourceBundle *rb;
rb=ures_open(path, locale, pErrorCode);
icu::LocalUResourceBundlePointer rb(ures_open(path, locale, pErrorCode));
if(U_SUCCESS(*pErrorCode)) {
s=ures_getStringByKey(rb, tableKey, &length, pErrorCode);
s=ures_getStringByKey(rb.getAlias(), tableKey, &length, pErrorCode);
/* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */
ures_close(rb);
}
} else {
/* Language code should not be a number. If it is, set the error code. */
@ -510,15 +508,14 @@ uloc_getDisplayName(const char *locale,
{
UErrorCode status = U_ZERO_ERROR;
UResourceBundle* locbundle=ures_open(U_ICUDATA_LANG, displayLocale, &status);
UResourceBundle* dspbundle=ures_getByKeyWithFallback(locbundle, _kLocaleDisplayPattern,
NULL, &status);
separator=ures_getStringByKeyWithFallback(dspbundle, _kSeparator, &sepLen, &status);
pattern=ures_getStringByKeyWithFallback(dspbundle, _kPattern, &patLen, &status);
icu::LocalUResourceBundlePointer locbundle(
ures_open(U_ICUDATA_LANG, displayLocale, &status));
icu::LocalUResourceBundlePointer dspbundle(
ures_getByKeyWithFallback(locbundle.getAlias(), _kLocaleDisplayPattern, NULL, &status));
ures_close(dspbundle);
ures_close(locbundle);
separator=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kSeparator, &sepLen, &status);
pattern=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kPattern, &patLen, &status);
}
/* If we couldn't find any data, then use the defaults */
@ -586,7 +583,7 @@ uloc_getDisplayName(const char *locale,
int32_t langPos=0; /* position in output of language substitution */
int32_t restLen=0; /* length of 'everything else' substitution */
int32_t restPos=0; /* position in output of 'everything else' substitution */
UEnumeration* kenum = NULL; /* keyword enumeration */
icu::LocalUEnumerationPointer kenum; /* keyword enumeration */
/* prefix of pattern, extremely likely to be empty */
if(sub0Pos) {
@ -639,12 +636,11 @@ uloc_getDisplayName(const char *locale,
len=uloc_getDisplayVariant(locale, displayLocale, p, cap, pErrorCode);
break;
case 3:
kenum = uloc_openKeywords(locale, pErrorCode);
kenum.adoptInstead(uloc_openKeywords(locale, pErrorCode));
U_FALLTHROUGH;
default: {
const char* kw=uenum_next(kenum, &len, pErrorCode);
const char* kw=uenum_next(kenum.getAlias(), &len, pErrorCode);
if (kw == NULL) {
uenum_close(kenum);
len=0; /* mark that we didn't add a component */
subdone=TRUE;
} else {
@ -832,18 +828,16 @@ uloc_getDisplayKeywordValue( const char* locale,
int32_t dispNameLen = 0;
const UChar *dispName = NULL;
UResourceBundle *bundle = ures_open(U_ICUDATA_CURR, displayLocale, status);
UResourceBundle *currencies = ures_getByKey(bundle, _kCurrencies, NULL, status);
UResourceBundle *currency = ures_getByKeyWithFallback(currencies, keywordValue, NULL, status);
dispName = ures_getStringByIndex(currency, UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status);
/*close the bundles */
ures_close(currency);
ures_close(currencies);
ures_close(bundle);
icu::LocalUResourceBundlePointer bundle(
ures_open(U_ICUDATA_CURR, displayLocale, status));
icu::LocalUResourceBundlePointer currencies(
ures_getByKey(bundle.getAlias(), _kCurrencies, NULL, status));
icu::LocalUResourceBundlePointer currency(
ures_getByKeyWithFallback(currencies.getAlias(), keywordValue, NULL, status));
dispName = ures_getStringByIndex(currency.getAlias(), UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status);
if(U_FAILURE(*status)){
if(*status == U_MISSING_RESOURCE_ERROR){
/* we just want to write the value over if nothing is available */

View file

@ -50,9 +50,9 @@ findLikelySubtags(const char* localeID,
int32_t resLen = 0;
const UChar* s = NULL;
UErrorCode tmpErr = U_ZERO_ERROR;
UResourceBundle* subtags = ures_openDirect(NULL, "likelySubtags", &tmpErr);
icu::LocalUResourceBundlePointer subtags(ures_openDirect(NULL, "likelySubtags", &tmpErr));
if (U_SUCCESS(tmpErr)) {
s = ures_getStringByKey(subtags, localeID, &resLen, &tmpErr);
s = ures_getStringByKey(subtags.getAlias(), localeID, &resLen, &tmpErr);
if (U_FAILURE(tmpErr)) {
/*
@ -71,8 +71,6 @@ findLikelySubtags(const char* localeID,
u_UCharsToChars(s, buffer, resLen + 1);
result = buffer;
}
ures_close(subtags);
} else {
*err = tmpErr;
}

View file

@ -49,7 +49,7 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
UErrorCode *pErrorCode)
{
/* char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/
UResourceBundle *rb=NULL, table, subTable;
UResourceBundle table, subTable;
const UChar *item=NULL;
UErrorCode errorCode;
char explicitFallbackName[ULOC_FULLNAME_CAPACITY] = {0};
@ -59,7 +59,11 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
* this falls back through the locale's chain to root
*/
errorCode=U_ZERO_ERROR;
rb=ures_open(path, locale, &errorCode);
icu::LocalUResourceBundlePointer rb(ures_open(path, locale, &errorCode));
// Automatically call ures_close() on these when they go out of scope.
icu::LocalUResourceBundlePointer tableCloser(&table);
icu::LocalUResourceBundlePointer subTableCloser(&subTable);
if(U_FAILURE(errorCode)) {
/* total failure, not even root could be opened */
@ -75,7 +79,7 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
for(;;){
ures_initStackObject(&table);
ures_initStackObject(&subTable);
ures_getByKeyWithFallback(rb, tableKey, &table, &errorCode);
ures_getByKeyWithFallback(rb.getAlias(), tableKey, &table, &errorCode);
if (subTableKey != NULL) {
/*
@ -135,8 +139,7 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
*pErrorCode = U_INTERNAL_PROGRAM_ERROR;
break;
}
ures_close(rb);
rb = ures_open(path, explicitFallbackName, &errorCode);
rb.adoptInstead(ures_open(path, explicitFallbackName, &errorCode));
if(U_FAILURE(errorCode)){
*pErrorCode = errorCode;
break;
@ -146,10 +149,7 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
break;
}
}
/* done with the locale string - ready to close table and rb */
ures_close(&subTable);
ures_close(&table);
ures_close(rb);
return item;
}

View file

@ -11,6 +11,7 @@
#if !UCONFIG_NO_SERVICE || !UCONFIG_NO_TRANSLITERATION
#include "unicode/resbund.h"
#include "unicode/uenum.h"
#include "cmemory.h"
#include "ustrfmt.h"
#include "locutil.h"
@ -229,15 +230,14 @@ LocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID)
CharString cbundleID;
cbundleID.appendInvariantChars(bundleID, status);
const char* path = cbundleID.isEmpty() ? NULL : cbundleID.data();
UEnumeration *uenum = ures_openAvailableLocales(path, &status);
icu::LocalUEnumerationPointer uenum(ures_openAvailableLocales(path, &status));
for (;;) {
const UChar* id = uenum_unext(uenum, NULL, &status);
const UChar* id = uenum_unext(uenum.getAlias(), NULL, &status);
if (id == NULL) {
break;
}
htp->put(UnicodeString(id), (void*)htp, status);
}
uenum_close(uenum);
if (U_FAILURE(status)) {
delete htp;
return NULL;

View file

@ -36,13 +36,8 @@ typedef enum {
typedef struct LocExtKeyData {
const char* legacyId;
const char* bcpId;
UHashtable* typeMap;
icu::LocalUHashtablePointer typeMap;
uint32_t specialTypes;
~LocExtKeyData() {
if (typeMap != NULL) {
uhash_close(typeMap);
}
}
} LocExtKeyData;
typedef struct LocExtType {
@ -340,7 +335,7 @@ initFromResourceBundle(UErrorCode& sts) {
keyData->bcpId = bcpKeyId;
keyData->legacyId = legacyKeyId;
keyData->specialTypes = specialTypes;
keyData->typeMap = typeDataMap;
keyData->typeMap.adoptInstead(typeDataMap);
uhash_put(gLocExtKeyMap, (void*)legacyKeyId, keyData, &sts);
if (legacyKeyId != bcpKeyId) {
@ -465,7 +460,7 @@ ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* i
if (isKnownKey != NULL) {
*isKnownKey = TRUE;
}
LocExtType* t = (LocExtType*)uhash_get(keyData->typeMap, type);
LocExtType* t = (LocExtType*)uhash_get(keyData->typeMap.getAlias(), type);
if (t != NULL) {
return t->bcpId;
}
@ -510,7 +505,7 @@ ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool
if (isKnownKey != NULL) {
*isKnownKey = TRUE;
}
LocExtType* t = (LocExtType*)uhash_get(keyData->typeMap, type);
LocExtType* t = (LocExtType*)uhash_get(keyData->typeMap.getAlias(), type);
if (t != NULL) {
return t->legacyId;
}

View file

@ -10,7 +10,9 @@
#include "unicode/bytestream.h"
#include "unicode/utypes.h"
#include "unicode/ures.h"
#include "unicode/localpointer.h"
#include "unicode/putil.h"
#include "unicode/uenum.h"
#include "unicode/uloc.h"
#include "ustr_imp.h"
#include "charstr.h"
@ -347,6 +349,21 @@ static const char*
ultag_getGrandfathered(const ULanguageTag* langtag);
#endif
U_NAMESPACE_BEGIN
/**
* \class LocalULanguageTagPointer
* "Smart pointer" class, closes a ULanguageTag via ultag_close().
* For most methods see the LocalPointerBase base class.
*
* @see LocalPointerBase
* @see LocalPointer
* @internal
*/
U_DEFINE_LOCAL_OPEN_POINTER(LocalULanguageTagPointer, ULanguageTag, ultag_close);
U_NAMESPACE_END
/*
* -------------------------------------------------
*
@ -1048,14 +1065,12 @@ static void
_appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UBool hadPosix, UErrorCode* status) {
char attrBuf[ULOC_KEYWORD_AND_VALUES_CAPACITY] = { 0 };
int32_t attrBufLength = 0;
UEnumeration *keywordEnum = NULL;
keywordEnum = uloc_openKeywords(localeID, status);
icu::LocalUEnumerationPointer keywordEnum(uloc_openKeywords(localeID, status));
if (U_FAILURE(*status) && !hadPosix) {
uenum_close(keywordEnum);
return;
}
if (keywordEnum != NULL || hadPosix) {
if (keywordEnum.isValid() || hadPosix) {
/* reorder extensions */
int32_t len;
const char *key;
@ -1072,7 +1087,7 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st
while (TRUE) {
icu::CharString buf;
key = uenum_next(keywordEnum, NULL, status);
key = uenum_next(keywordEnum.getAlias(), NULL, status);
if (key == NULL) {
break;
}
@ -1334,8 +1349,6 @@ cleanup:
attr = tmpAttr;
}
uenum_close(keywordEnum);
if (U_FAILURE(*status)) {
return;
}
@ -2561,18 +2574,17 @@ ulocimp_toLanguageTag(const char* localeID,
/* For handling special case - private use only tag */
pKeywordStart = locale_getKeywordsStart(canonical.data());
if (pKeywordStart == canonical.data()) {
UEnumeration *kwdEnum;
int kwdCnt = 0;
UBool done = FALSE;
kwdEnum = uloc_openKeywords(canonical.data(), &tmpStatus);
if (kwdEnum != NULL) {
kwdCnt = uenum_count(kwdEnum, &tmpStatus);
icu::LocalUEnumerationPointer kwdEnum(uloc_openKeywords(canonical.data(), &tmpStatus));
if (U_SUCCESS(tmpStatus)) {
kwdCnt = uenum_count(kwdEnum.getAlias(), &tmpStatus);
if (kwdCnt == 1) {
const char *key;
int32_t len = 0;
key = uenum_next(kwdEnum, &len, &tmpStatus);
key = uenum_next(kwdEnum.getAlias(), &len, &tmpStatus);
if (len == 1 && *key == PRIVATEUSE) {
char buf[ULOC_KEYWORD_AND_VALUES_CAPACITY];
buf[0] = PRIVATEUSE;
@ -2594,7 +2606,6 @@ ulocimp_toLanguageTag(const char* localeID,
}
}
}
uenum_close(kwdEnum);
if (done) {
return;
}
@ -2645,20 +2656,19 @@ ulocimp_forLanguageTag(const char* langtag,
icu::ByteSink& sink,
int32_t* parsedLength,
UErrorCode* status) {
ULanguageTag *lt;
UBool isEmpty = TRUE;
const char *subtag, *p;
int32_t len;
int32_t i, n;
UBool noRegion = TRUE;
lt = ultag_parse(langtag, tagLen, parsedLength, status);
icu::LocalULanguageTagPointer lt(ultag_parse(langtag, tagLen, parsedLength, status));
if (U_FAILURE(*status)) {
return;
}
/* language */
subtag = ultag_getExtlangSize(lt) > 0 ? ultag_getExtlang(lt, 0) : ultag_getLanguage(lt);
subtag = ultag_getExtlangSize(lt.getAlias()) > 0 ? ultag_getExtlang(lt.getAlias(), 0) : ultag_getLanguage(lt.getAlias());
if (uprv_compareInvCharsAsAscii(subtag, LANG_UND) != 0) {
len = (int32_t)uprv_strlen(subtag);
if (len > 0) {
@ -2668,7 +2678,7 @@ ulocimp_forLanguageTag(const char* langtag,
}
/* script */
subtag = ultag_getScript(lt);
subtag = ultag_getScript(lt.getAlias());
len = (int32_t)uprv_strlen(subtag);
if (len > 0) {
sink.Append("_", 1);
@ -2681,7 +2691,7 @@ ulocimp_forLanguageTag(const char* langtag,
}
/* region */
subtag = ultag_getRegion(lt);
subtag = ultag_getRegion(lt.getAlias());
len = (int32_t)uprv_strlen(subtag);
if (len > 0) {
sink.Append("_", 1);
@ -2698,7 +2708,7 @@ ulocimp_forLanguageTag(const char* langtag,
}
/* variants */
n = ultag_getVariantsSize(lt);
n = ultag_getVariantsSize(lt.getAlias());
if (n > 0) {
if (noRegion) {
sink.Append("_", 1);
@ -2706,7 +2716,7 @@ ulocimp_forLanguageTag(const char* langtag,
}
for (i = 0; i < n; i++) {
subtag = ultag_getVariant(lt, i);
subtag = ultag_getVariant(lt.getAlias(), i);
sink.Append("_", 1);
/* write out the variant in upper case */
@ -2720,15 +2730,13 @@ ulocimp_forLanguageTag(const char* langtag,
}
/* keywords */
n = ultag_getExtensionsSize(lt);
subtag = ultag_getPrivateUse(lt);
n = ultag_getExtensionsSize(lt.getAlias());
subtag = ultag_getPrivateUse(lt.getAlias());
if (n > 0 || uprv_strlen(subtag) > 0) {
if (isEmpty && n > 0) {
/* need a language */
sink.Append(LANG_UND, LANG_UND_LEN);
}
_appendKeywords(lt, sink, status);
_appendKeywords(lt.getAlias(), sink, status);
}
ultag_close(lt);
}