diff --git a/icu4c/source/common/locavailable.cpp b/icu4c/source/common/locavailable.cpp index d99d48a5f6..5f06aff3a2 100644 --- a/icu4c/source/common/locavailable.cpp +++ b/icu4c/source/common/locavailable.cpp @@ -125,7 +125,6 @@ static UBool U_CALLCONV uloc_cleanup(void) { // via the initOnce mechanism. static void U_CALLCONV loadInstalledLocales() { - UResourceBundle installed; UErrorCode status = U_ZERO_ERROR; int32_t i = 0; int32_t localeCount; @@ -134,22 +133,19 @@ static void U_CALLCONV loadInstalledLocales() { U_ASSERT(_installedLocalesCount == 0); _installedLocalesCount = 0; - ures_initStackObject(&installed); icu::LocalUResourceBundlePointer indexLocale(ures_openDirect(NULL, _kIndexLocaleName, &status)); + icu::StackUResourceBundle installed; - // Automatically call ures_close() on this when it goes out of scope. - icu::LocalUResourceBundlePointer installedCloser(&installed); - - ures_getByKey(indexLocale.getAlias(), _kIndexTag, &installed, &status); + ures_getByKey(indexLocale.getAlias(), _kIndexTag, installed.getAlias(), &status); if(U_SUCCESS(status)) { - localeCount = ures_getSize(&installed); + localeCount = ures_getSize(installed.getAlias()); _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1)); if (_installedLocales != NULL) { - ures_resetIterator(&installed); - while(ures_hasNext(&installed)) { - ures_getNextString(&installed, NULL, (const char **)&_installedLocales[i++], &status); + ures_resetIterator(installed.getAlias()); + while(ures_hasNext(installed.getAlias())) { + ures_getNextString(installed.getAlias(), NULL, (const char **)&_installedLocales[i++], &status); } _installedLocales[i] = NULL; _installedLocalesCount = localeCount; diff --git a/icu4c/source/common/locresdata.cpp b/icu4c/source/common/locresdata.cpp index 5a51237a49..d1d9a4729f 100644 --- a/icu4c/source/common/locresdata.cpp +++ b/icu4c/source/common/locresdata.cpp @@ -49,7 +49,6 @@ uloc_getTableStringWithFallback(const char *path, const char *locale, UErrorCode *pErrorCode) { /* char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/ - UResourceBundle table, subTable; const UChar *item=NULL; UErrorCode errorCode; char explicitFallbackName[ULOC_FULLNAME_CAPACITY] = {0}; @@ -61,10 +60,6 @@ uloc_getTableStringWithFallback(const char *path, const char *locale, errorCode=U_ZERO_ERROR; 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 */ *pErrorCode=errorCode; @@ -77,24 +72,24 @@ uloc_getTableStringWithFallback(const char *path, const char *locale, } for(;;){ - ures_initStackObject(&table); - ures_initStackObject(&subTable); - ures_getByKeyWithFallback(rb.getAlias(), tableKey, &table, &errorCode); + icu::StackUResourceBundle table; + icu::StackUResourceBundle subTable; + ures_getByKeyWithFallback(rb.getAlias(), tableKey, table.getAlias(), &errorCode); if (subTableKey != NULL) { /* - ures_getByKeyWithFallback(&table,subTableKey, &subTable, &errorCode); - item = ures_getStringByKeyWithFallback(&subTable, itemKey, pLength, &errorCode); + ures_getByKeyWithFallback(table.getAlias(), subTableKey, subTable.getAlias(), &errorCode); + item = ures_getStringByKeyWithFallback(subTable.getAlias(), itemKey, pLength, &errorCode); if(U_FAILURE(errorCode)){ *pErrorCode = errorCode; } break;*/ - ures_getByKeyWithFallback(&table,subTableKey, &table, &errorCode); + ures_getByKeyWithFallback(table.getAlias(), subTableKey, table.getAlias(), &errorCode); } if(U_SUCCESS(errorCode)){ - item = ures_getStringByKeyWithFallback(&table, itemKey, pLength, &errorCode); + item = ures_getStringByKeyWithFallback(table.getAlias(), itemKey, pLength, &errorCode); if(U_FAILURE(errorCode)){ const char* replacement = NULL; *pErrorCode = errorCode; /*save the errorCode*/ @@ -107,7 +102,7 @@ uloc_getTableStringWithFallback(const char *path, const char *locale, } /*pointer comparison is ok since uloc_getCurrentCountryID & uloc_getCurrentLanguageID return the key itself is replacement is not found*/ if(replacement!=NULL && itemKey != replacement){ - item = ures_getStringByKeyWithFallback(&table, replacement, pLength, &errorCode); + item = ures_getStringByKeyWithFallback(table.getAlias(), replacement, pLength, &errorCode); if(U_SUCCESS(errorCode)){ *pErrorCode = errorCode; break; @@ -126,7 +121,7 @@ uloc_getTableStringWithFallback(const char *path, const char *locale, *pErrorCode = errorCode; errorCode = U_ZERO_ERROR; - fallbackLocale = ures_getStringByKeyWithFallback(&table, "Fallback", &len, &errorCode); + fallbackLocale = ures_getStringByKeyWithFallback(table.getAlias(), "Fallback", &len, &errorCode); if(U_FAILURE(errorCode)){ *pErrorCode = errorCode; break; diff --git a/icu4c/source/common/uresbund.cpp b/icu4c/source/common/uresbund.cpp index 656eeb7b44..8074d385ae 100644 --- a/icu4c/source/common/uresbund.cpp +++ b/icu4c/source/common/uresbund.cpp @@ -21,6 +21,7 @@ ****************************************************************************** */ +#include "unicode/ures.h" #include "unicode/ustring.h" #include "unicode/ucnv.h" #include "charstr.h" @@ -512,6 +513,18 @@ U_CFUNC void ures_initStackObject(UResourceBundle* resB) { ures_setIsStackObject(resB, TRUE); } +U_NAMESPACE_BEGIN + +StackUResourceBundle::StackUResourceBundle() { + ures_initStackObject(&bundle); +} + +StackUResourceBundle::~StackUResourceBundle() { + ures_close(&bundle); +} + +U_NAMESPACE_END + static UBool // returns U_SUCCESS(*status) loadParentsExceptRoot(UResourceDataEntry *&t1, char name[], int32_t nameCapacity, diff --git a/icu4c/source/common/uresimp.h b/icu4c/source/common/uresimp.h index e7fa3e1e36..6aa8b36dd9 100644 --- a/icu4c/source/common/uresimp.h +++ b/icu4c/source/common/uresimp.h @@ -11,6 +11,7 @@ #define URESIMP_H #include "unicode/ures.h" +#include "unicode/utypes.h" #include "uresdata.h" @@ -82,6 +83,57 @@ struct UResourceBundle { U_CAPI void U_EXPORT2 ures_initStackObject(UResourceBundle* resB); +#ifdef __cplusplus + +U_NAMESPACE_BEGIN + +/** + * \class StackUResourceBundle + * "Smart pointer" like class, closes a UResourceBundle via ures_close(). + * + * This code: + * + * StackUResourceBundle bundle; + * foo(bundle.getAlias()); + * + * Is equivalent to this code: + * + * UResourceBundle bundle; + * ures_initStackObject(&bundle); + * foo(&bundle); + * ures_close(&bundle); + * + * @see LocalUResourceBundlePointer + * @internal + */ +class StackUResourceBundle { +public: + StackUResourceBundle(); + ~StackUResourceBundle(); + + UResourceBundle* getAlias() { return &bundle; } + + StackUResourceBundle(const StackUResourceBundle&) = delete; + StackUResourceBundle& operator=(const StackUResourceBundle&) = delete; + + StackUResourceBundle(StackUResourceBundle&&) = delete; + StackUResourceBundle& operator=(StackUResourceBundle&&) = delete; + +private: + UResourceBundle bundle; + + // No heap allocation. Use only on the stack. + static void* U_EXPORT2 operator new(size_t); + static void* U_EXPORT2 operator new[](size_t); +#if U_HAVE_PLACEMENT_NEW + static void* U_EXPORT2 operator new(size_t, void*); +#endif +}; + +U_NAMESPACE_END + +#endif /* __cplusplus */ + /** * Opens a resource bundle for the locale; * if there is not even a base language bundle, then loads the root bundle;