diff --git a/icu4c/source/common/brkiter.cpp b/icu4c/source/common/brkiter.cpp index 4d945cc17e2b..ed0963f6078d 100644 --- a/icu4c/source/common/brkiter.cpp +++ b/icu4c/source/common/brkiter.cpp @@ -59,7 +59,7 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st { char fnbuff[256]; char ext[4]={'\0'}; - CharString actualLocale; + CharString actual; int32_t size; const char16_t* brkfname = nullptr; UResourceBundle brkRulesStack; @@ -94,7 +94,7 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st // Use the string if we found it if (U_SUCCESS(status) && brkfname) { - actualLocale.append(ures_getLocaleInternal(brkName, &status), -1, status); + actual.append(ures_getLocaleInternal(brkName, &status), -1, status); char16_t* extStart=u_strchr(brkfname, 0x002e); int len = 0; @@ -123,10 +123,16 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st if (U_SUCCESS(status) && result != nullptr) { U_LOCALE_BASED(locBased, *(BreakIterator*)result); - locBased.setLocaleIDs(ures_getLocaleByType(b, ULOC_VALID_LOCALE, &status), - actualLocale.data()); - uprv_strncpy(result->requestLocale, loc.getName(), ULOC_FULLNAME_CAPACITY); - result->requestLocale[ULOC_FULLNAME_CAPACITY-1] = 0; // always terminate + locBased.setLocaleIDs(ures_getLocaleByType(b, ULOC_VALID_LOCALE, &status), + actual.data(), status); + if (result->requestLocale == nullptr) { + result->requestLocale = new CharString(loc.getName(), status); + if (result->requestLocale == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } + } else { + result->requestLocale->copyFrom(loc.getName(), status); + } } ures_close(b); @@ -204,28 +210,50 @@ BreakIterator::getAvailableLocales(int32_t& count) // //------------------------------------------- -BreakIterator::BreakIterator() +BreakIterator::BreakIterator() : actualLocale(nullptr), validLocale(nullptr), requestLocale(nullptr) { - *validLocale = *actualLocale = *requestLocale = 0; } -BreakIterator::BreakIterator(const BreakIterator &other) : UObject(other) { - uprv_strncpy(actualLocale, other.actualLocale, sizeof(actualLocale)); - uprv_strncpy(validLocale, other.validLocale, sizeof(validLocale)); - uprv_strncpy(requestLocale, other.requestLocale, sizeof(requestLocale)); +BreakIterator::BreakIterator(const BreakIterator &other) : UObject(other), actualLocale(nullptr), validLocale(nullptr), requestLocale(nullptr) { + UErrorCode status = U_ZERO_ERROR; + U_LOCALE_BASED(locBased, *this); + locBased.setLocaleIDs(other.validLocale, other.actualLocale, status); + if (other.requestLocale == nullptr) { + delete requestLocale; + requestLocale = nullptr; + } else { + requestLocale = new CharString(*(other.requestLocale), status); + if (requestLocale == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } + } + U_ASSERT(U_SUCCESS(status)); } BreakIterator &BreakIterator::operator =(const BreakIterator &other) { if (this != &other) { - uprv_strncpy(actualLocale, other.actualLocale, sizeof(actualLocale)); - uprv_strncpy(validLocale, other.validLocale, sizeof(validLocale)); - uprv_strncpy(requestLocale, other.requestLocale, sizeof(requestLocale)); + UErrorCode status = U_ZERO_ERROR; + U_LOCALE_BASED(locBased, *this); + locBased.setLocaleIDs(other.validLocale, other.actualLocale, status); + if (other.requestLocale == nullptr) { + delete requestLocale; + requestLocale = nullptr; + } else { + requestLocale = new CharString(*(other.requestLocale), status); + if (requestLocale == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } + } + U_ASSERT(U_SUCCESS(status)); } return *this; } BreakIterator::~BreakIterator() { + delete validLocale; + delete actualLocale; + delete requestLocale; } // ------------------------------------------ @@ -394,7 +422,7 @@ BreakIterator::createInstance(const Locale& loc, int32_t kind, UErrorCode& statu // revisit this in ICU 3.0 and clean it up/fix it/remove it. if (U_SUCCESS(status) && (result != nullptr) && *actualLoc.getName() != 0) { U_LOCALE_BASED(locBased, *result); - locBased.setLocaleIDs(actualLoc.getName(), actualLoc.getName()); + locBased.setLocaleIDs(actualLoc.getName(), actualLoc.getName(), status); } return result; } @@ -496,19 +524,31 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) Locale BreakIterator::getLocale(ULocDataLocaleType type, UErrorCode& status) const { + if (U_FAILURE(status)) { + return {""}; + } if (type == ULOC_REQUESTED_LOCALE) { - return {requestLocale}; + if (requestLocale == nullptr) { + return {""}; + } + return {requestLocale->data()}; } - U_LOCALE_BASED(locBased, *this); + U_LOCALE_BASED(locBased, *const_cast(this)); return locBased.getLocale(type, status); } const char * BreakIterator::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { + if (U_FAILURE(status)) { + return {""}; + } if (type == ULOC_REQUESTED_LOCALE) { - return requestLocale; + if (requestLocale == nullptr) { + return {""}; + } + return requestLocale->data(); } - U_LOCALE_BASED(locBased, *this); + U_LOCALE_BASED(locBased, *const_cast(this)); return locBased.getLocaleID(type, status); } @@ -535,9 +575,11 @@ int32_t BreakIterator::getRuleStatusVec(int32_t *fillInVec, int32_t capacity, UE return 1; } -BreakIterator::BreakIterator (const Locale& valid, const Locale& actual) { +BreakIterator::BreakIterator (const Locale& valid, const Locale& actual) : actualLocale(nullptr), validLocale(nullptr), requestLocale(nullptr) { + UErrorCode status = U_ZERO_ERROR; U_LOCALE_BASED(locBased, (*this)); - locBased.setLocaleIDs(valid, actual); + locBased.setLocaleIDs(valid.getName(), actual.getName(), status); + U_ASSERT(U_SUCCESS(status)); } U_NAMESPACE_END diff --git a/icu4c/source/common/charstr.cpp b/icu4c/source/common/charstr.cpp index f76cc8a4dc90..88c75382bdb4 100644 --- a/icu4c/source/common/charstr.cpp +++ b/icu4c/source/common/charstr.cpp @@ -70,6 +70,15 @@ CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { return *this; } +CharString &CharString::copyFrom(StringPiece s, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { + return *this; + } + len = 0; + append(s, errorCode); + return *this; +} + int32_t CharString::lastIndexOf(char c) const { for(int32_t i=len; i>0;) { if(buffer[--i]==c) { diff --git a/icu4c/source/common/charstr.h b/icu4c/source/common/charstr.h index 08283ca452ce..7cc6de122dd1 100644 --- a/icu4c/source/common/charstr.h +++ b/icu4c/source/common/charstr.h @@ -74,6 +74,7 @@ class U_COMMON_API CharString : public UMemory { * use a UErrorCode where memory allocations might be needed. */ CharString ©From(const CharString &other, UErrorCode &errorCode); + CharString ©From(StringPiece s, UErrorCode &errorCode); UBool isEmpty() const { return len==0; } int32_t length() const { return len; } diff --git a/icu4c/source/common/locbased.cpp b/icu4c/source/common/locbased.cpp index 832bc3e88b14..b459a8442ac2 100644 --- a/icu4c/source/common/locbased.cpp +++ b/icu4c/source/common/locbased.cpp @@ -12,6 +12,7 @@ */ #include "locbased.h" #include "cstring.h" +#include "charstr.h" U_NAMESPACE_BEGIN @@ -27,29 +28,74 @@ const char* LocaleBased::getLocaleID(ULocDataLocaleType type, UErrorCode& status switch(type) { case ULOC_VALID_LOCALE: - return valid; + return valid->data(); case ULOC_ACTUAL_LOCALE: - return actual; + return actual->data(); default: status = U_ILLEGAL_ARGUMENT_ERROR; return nullptr; } } -void LocaleBased::setLocaleIDs(const char* validID, const char* actualID) { - if (validID != nullptr) { - uprv_strncpy(valid, validID, ULOC_FULLNAME_CAPACITY); - valid[ULOC_FULLNAME_CAPACITY-1] = 0; // always terminate +void LocaleBased::setLocaleIDs(const CharString* validID, const CharString* actualID, UErrorCode& status) { + if (validID == nullptr) { + delete valid; + valid = nullptr; + } else { + if (valid == nullptr) { + valid = new CharString(*validID, status); + if (valid == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + } else { + valid->copyFrom(*validID, status); + } } - if (actualID != nullptr) { - uprv_strncpy(actual, actualID, ULOC_FULLNAME_CAPACITY); - actual[ULOC_FULLNAME_CAPACITY-1] = 0; // always terminate + if (actualID == nullptr) { + delete actual; + actual = nullptr; + } else { + if (actual == nullptr) { + actual = new CharString(*actualID, status); + if (actual == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + } else { + actual->copyFrom(*actualID, status); + } } } - -void LocaleBased::setLocaleIDs(const Locale& validID, const Locale& actualID) { - uprv_strcpy(valid, validID.getName()); - uprv_strcpy(actual, actualID.getName()); +void LocaleBased::setLocaleIDs(const char* validID, const char* actualID, UErrorCode& status) { + if (validID == nullptr) { + delete valid; + valid = nullptr; + } else { + if (valid == nullptr) { + valid = new CharString(validID, status); + if (valid == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + } else { + valid->copyFrom(validID, status); + } + } + if (actualID == nullptr) { + delete actual; + actual = nullptr; + } else { + if (actual == nullptr) { + actual = new CharString(actualID, status); + if (actual == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + } else { + actual->copyFrom(actualID, status); + } + } } U_NAMESPACE_END diff --git a/icu4c/source/common/locbased.h b/icu4c/source/common/locbased.h index 2d260b527873..e14bd717e353 100644 --- a/icu4c/source/common/locbased.h +++ b/icu4c/source/common/locbased.h @@ -19,13 +19,14 @@ /** * Macro to declare a locale LocaleBased wrapper object for the given * object, which must have two members named `validLocale' and - * `actualLocale' of size ULOC_FULLNAME_CAPACITY + * `actualLocale' of which are pointers to the internal icu::CharString. */ #define U_LOCALE_BASED(varname, objname) \ LocaleBased varname((objname).validLocale, (objname).actualLocale) U_NAMESPACE_BEGIN +class CharString; /** * A utility class that unifies the implementation of getLocale() by * various ICU services. This class is likely to be removed in the @@ -41,13 +42,7 @@ class U_COMMON_API LocaleBased : public UMemory { * Construct a LocaleBased wrapper around the two pointers. These * will be aliased for the lifetime of this object. */ - inline LocaleBased(char* validAlias, char* actualAlias); - - /** - * Construct a LocaleBased wrapper around the two const pointers. - * These will be aliased for the lifetime of this object. - */ - inline LocaleBased(const char* validAlias, const char* actualAlias); + inline LocaleBased(CharString*& validAlias, CharString*& actualAlias); /** * Return locale meta-data for the service object wrapped by this @@ -75,33 +70,19 @@ class U_COMMON_API LocaleBased : public UMemory { * @param valid the ID of the valid locale * @param actual the ID of the actual locale */ - void setLocaleIDs(const char* valid, const char* actual); - - /** - * Set the locale meta-data for the service object wrapped by this - * object. - * @param valid the ID of the valid locale - * @param actual the ID of the actual locale - */ - void setLocaleIDs(const Locale& valid, const Locale& actual); + void setLocaleIDs(const char* valid, const char* actual, UErrorCode& status); + void setLocaleIDs(const CharString* valid, const CharString* actual, UErrorCode& status); private: - char* valid; - - char* actual; + CharString*& valid; + CharString*& actual; }; -inline LocaleBased::LocaleBased(char* validAlias, char* actualAlias) : +inline LocaleBased::LocaleBased(CharString*& validAlias, CharString*& actualAlias) : valid(validAlias), actual(actualAlias) { } -inline LocaleBased::LocaleBased(const char* validAlias, - const char* actualAlias) : - // ugh: cast away const - valid(const_cast(validAlias)), actual(const_cast(actualAlias)) { -} - U_NAMESPACE_END #endif diff --git a/icu4c/source/common/unicode/brkiter.h b/icu4c/source/common/unicode/brkiter.h index 30c59c4a94ac..332451554a0d 100644 --- a/icu4c/source/common/unicode/brkiter.h +++ b/icu4c/source/common/unicode/brkiter.h @@ -58,6 +58,8 @@ U_NAMESPACE_END U_NAMESPACE_BEGIN +class CharString; + /** * The BreakIterator class implements methods for finding the location * of boundaries in text. BreakIterator is an abstract base class. @@ -646,9 +648,9 @@ class U_COMMON_API BreakIterator : public UObject { private: /** @internal (private) */ - char actualLocale[ULOC_FULLNAME_CAPACITY]; - char validLocale[ULOC_FULLNAME_CAPACITY]; - char requestLocale[ULOC_FULLNAME_CAPACITY]; + CharString* actualLocale; + CharString* validLocale; + CharString* requestLocale; }; #ifndef U_HIDE_DEPRECATED_API diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp index 637e7f84c40d..51b95213e72a 100644 --- a/icu4c/source/i18n/calendar.cpp +++ b/icu4c/source/i18n/calendar.cpp @@ -705,10 +705,10 @@ fTime(0), fLenient(true), fZone(nullptr), fRepeatedWallTime(UCAL_WALLTIME_LAST), -fSkippedWallTime(UCAL_WALLTIME_LAST) +fSkippedWallTime(UCAL_WALLTIME_LAST), +validLocale(nullptr), +actualLocale(nullptr) { - validLocale[0] = 0; - actualLocale[0] = 0; clear(); if (U_FAILURE(success)) { return; @@ -722,7 +722,7 @@ fSkippedWallTime(UCAL_WALLTIME_LAST) // ------------------------------------- -Calendar::Calendar(TimeZone* zone, const Locale& aLocale, UErrorCode& success) +Calendar::Calendar(TimeZone* adoptZone, const Locale& aLocale, UErrorCode& success) : UObject(), fIsTimeSet(false), fAreFieldsSet(false), @@ -733,15 +733,15 @@ fTime(0), fLenient(true), fZone(nullptr), fRepeatedWallTime(UCAL_WALLTIME_LAST), -fSkippedWallTime(UCAL_WALLTIME_LAST) +fSkippedWallTime(UCAL_WALLTIME_LAST), +validLocale(nullptr), +actualLocale(nullptr) { - validLocale[0] = 0; - actualLocale[0] = 0; + LocalPointer zone(adoptZone, success); if (U_FAILURE(success)) { - delete zone; return; } - if (zone == nullptr) { + if (zone.isNull()) { #if defined (U_DEBUG_CAL) fprintf(stderr, "%s:%d: ILLEGAL ARG because timezone cannot be 0\n", __FILE__, __LINE__); @@ -751,7 +751,7 @@ fSkippedWallTime(UCAL_WALLTIME_LAST) } clear(); - fZone = zone; + fZone = zone.orphan(); setWeekData(aLocale, nullptr, success); } @@ -768,10 +768,10 @@ fTime(0), fLenient(true), fZone(nullptr), fRepeatedWallTime(UCAL_WALLTIME_LAST), -fSkippedWallTime(UCAL_WALLTIME_LAST) +fSkippedWallTime(UCAL_WALLTIME_LAST), +validLocale(nullptr), +actualLocale(nullptr) { - validLocale[0] = 0; - actualLocale[0] = 0; if (U_FAILURE(success)) { return; } @@ -779,6 +779,7 @@ fSkippedWallTime(UCAL_WALLTIME_LAST) fZone = zone.clone(); if (fZone == nullptr) { success = U_MEMORY_ALLOCATION_ERROR; + return; } setWeekData(aLocale, nullptr, success); } @@ -788,12 +789,14 @@ fSkippedWallTime(UCAL_WALLTIME_LAST) Calendar::~Calendar() { delete fZone; + delete actualLocale; + delete validLocale; } // ------------------------------------- Calendar::Calendar(const Calendar &source) -: UObject(source) +: UObject(source), validLocale(nullptr), actualLocale(nullptr) { fZone = nullptr; *this = source; @@ -828,10 +831,10 @@ Calendar::operator=(const Calendar &right) fWeekendCease = right.fWeekendCease; fWeekendCeaseMillis = right.fWeekendCeaseMillis; fNextStamp = right.fNextStamp; - uprv_strncpy(validLocale, right.validLocale, sizeof(validLocale)-1); - validLocale[sizeof(validLocale)-1] = 0; - uprv_strncpy(actualLocale, right.actualLocale, sizeof(actualLocale)-1); - actualLocale[sizeof(validLocale)-1] = 0; + UErrorCode status = U_ZERO_ERROR; + U_LOCALE_BASED(locBased, *this); + locBased.setLocaleIDs(right.validLocale, right.actualLocale, status); + U_ASSERT(U_SUCCESS(status)); } return *this; @@ -4137,7 +4140,7 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode& if (U_SUCCESS(status)) { U_LOCALE_BASED(locBased,*this); locBased.setLocaleIDs(ures_getLocaleByType(monthNames.getAlias(), ULOC_VALID_LOCALE, &status), - ures_getLocaleByType(monthNames.getAlias(), ULOC_ACTUAL_LOCALE, &status)); + ures_getLocaleByType(monthNames.getAlias(), ULOC_ACTUAL_LOCALE, &status), status); } else { status = U_USING_FALLBACK_WARNING; return; @@ -4225,13 +4228,13 @@ Calendar::updateTime(UErrorCode& status) Locale Calendar::getLocale(ULocDataLocaleType type, UErrorCode& status) const { - U_LOCALE_BASED(locBased, *this); + U_LOCALE_BASED(locBased, *const_cast(this)); return locBased.getLocale(type, status); } const char * Calendar::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { - U_LOCALE_BASED(locBased, *this); + U_LOCALE_BASED(locBased, *const_cast(this)); return locBased.getLocaleID(type, status); } diff --git a/icu4c/source/i18n/dcfmtsym.cpp b/icu4c/source/i18n/dcfmtsym.cpp index b4c90e6765a7..1a0ef093c0ea 100644 --- a/icu4c/source/i18n/dcfmtsym.cpp +++ b/icu4c/source/i18n/dcfmtsym.cpp @@ -99,7 +99,7 @@ static const char *gNumberElementKeys[DecimalFormatSymbols::kFormatSymbolCount] // Initializes this with the decimal format symbols in the default locale. DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status) - : UObject(), locale() { + : UObject(), locale(), actualLocale(nullptr), validLocale(nullptr) { initialize(locale, status, true); } @@ -107,18 +107,17 @@ DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status) // Initializes this with the decimal format symbols in the desired locale. DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status) - : UObject(), locale(loc) { + : UObject(), locale(loc), actualLocale(nullptr), validLocale(nullptr) { initialize(locale, status); } DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, const NumberingSystem& ns, UErrorCode& status) - : UObject(), locale(loc) { + : UObject(), locale(loc), actualLocale(nullptr), validLocale(nullptr) { initialize(locale, status, false, &ns); } DecimalFormatSymbols::DecimalFormatSymbols() - : UObject(), locale(Locale::getRoot()) { - *validLocale = *actualLocale = 0; + : UObject(), locale(Locale::getRoot()), actualLocale(nullptr), validLocale(nullptr) { initialize(); } @@ -136,13 +135,15 @@ DecimalFormatSymbols::createWithLastResortData(UErrorCode& status) { DecimalFormatSymbols::~DecimalFormatSymbols() { + delete actualLocale; + delete validLocale; } // ------------------------------------- // copy constructor DecimalFormatSymbols::DecimalFormatSymbols(const DecimalFormatSymbols &source) - : UObject(source) + : UObject(source), actualLocale(nullptr), validLocale(nullptr) { *this = source; } @@ -163,8 +164,12 @@ DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs) currencySpcAfterSym[i].fastCopyFrom(rhs.currencySpcAfterSym[i]); } locale = rhs.locale; - uprv_strcpy(validLocale, rhs.validLocale); - uprv_strcpy(actualLocale, rhs.actualLocale); + + UErrorCode status = U_ZERO_ERROR; + U_LOCALE_BASED(locBased, *this); + locBased.setLocaleIDs(rhs.validLocale, rhs.actualLocale, status); + U_ASSERT(U_SUCCESS(status)); + fIsCustomCurrencySymbol = rhs.fIsCustomCurrencySymbol; fIsCustomIntlCurrencySymbol = rhs.fIsCustomIntlCurrencySymbol; fCodePointZero = rhs.fCodePointZero; @@ -201,10 +206,37 @@ DecimalFormatSymbols::operator==(const DecimalFormatSymbols& that) const return false; } } + if (locale != that.locale) return false; + + if (validLocale == nullptr) { + if (that.validLocale != nullptr) { + return false; + } + } else { + if (that.validLocale == nullptr) { + return false; + } else { + if (*validLocale != *that.validLocale) { + return false; + } + } + } + + if (actualLocale == nullptr) { + if (that.actualLocale != nullptr) { + return false; + } + } else { + if (that.actualLocale == nullptr) { + return false; + } else { + if (*actualLocale != *that.actualLocale) { + return false; + } + } + } + return true; // No need to check fCodePointZero since it is based on fSymbols - return locale == that.locale && - uprv_strcmp(validLocale, that.validLocale) == 0 && - uprv_strcmp(actualLocale, that.actualLocale) == 0; } // ------------------------------------- @@ -353,7 +385,6 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData, const NumberingSystem* ns) { if (U_FAILURE(status)) { return; } - *validLocale = *actualLocale = 0; // First initialize all the symbols to the fallbacks for anything we can't find initialize(); @@ -409,7 +440,8 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, ULOC_VALID_LOCALE, &status), ures_getLocaleByType( numberElementsRes.getAlias(), - ULOC_ACTUAL_LOCALE, &status)); + ULOC_ACTUAL_LOCALE, &status), + status); // Now load the rest of the data from the data sink. // Start with loading this nsName if it is not Latin. @@ -568,7 +600,7 @@ void DecimalFormatSymbols::setCurrency(const char16_t* currency, UErrorCode& sta Locale DecimalFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const { - U_LOCALE_BASED(locBased, *this); + U_LOCALE_BASED(locBased, *const_cast(this)); return locBased.getLocale(type, status); } diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp index 23cea3eba20a..1277ed77e556 100644 --- a/icu4c/source/i18n/dtfmtsym.cpp +++ b/icu4c/source/i18n/dtfmtsym.cpp @@ -291,13 +291,13 @@ DateFormatSymbols::createForLocale( DateFormatSymbols::DateFormatSymbols(const Locale& locale, UErrorCode& status) - : UObject() + : UObject(), validLocale(nullptr), actualLocale(nullptr) { initializeData(locale, nullptr, status); } DateFormatSymbols::DateFormatSymbols(UErrorCode& status) - : UObject() + : UObject(), validLocale(nullptr), actualLocale(nullptr) { initializeData(Locale::getDefault(), nullptr, status, true); } @@ -306,19 +306,19 @@ DateFormatSymbols::DateFormatSymbols(UErrorCode& status) DateFormatSymbols::DateFormatSymbols(const Locale& locale, const char *type, UErrorCode& status) - : UObject() + : UObject(), validLocale(nullptr), actualLocale(nullptr) { initializeData(locale, type, status); } DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status) - : UObject() + : UObject(), validLocale(nullptr), actualLocale(nullptr) { initializeData(Locale::getDefault(), type, status, true); } DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other) - : UObject(other) + : UObject(other), validLocale(nullptr), actualLocale(nullptr) { copyData(other); } @@ -402,9 +402,8 @@ void DateFormatSymbols::copyData(const DateFormatSymbols& other) { UErrorCode status = U_ZERO_ERROR; U_LOCALE_BASED(locBased, *this); - locBased.setLocaleIDs( - other.getLocale(ULOC_VALID_LOCALE, status), - other.getLocale(ULOC_ACTUAL_LOCALE, status)); + locBased.setLocaleIDs(other.validLocale, other.actualLocale, status); + U_ASSERT(U_SUCCESS(status)); assignArray(fEras, fErasCount, other.fEras, other.fErasCount); assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount); assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount); @@ -497,6 +496,8 @@ DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other) DateFormatSymbols::~DateFormatSymbols() { dispose(); + delete actualLocale; + delete validLocale; } void DateFormatSymbols::dispose() @@ -536,6 +537,10 @@ void DateFormatSymbols::dispose() delete[] fStandaloneWideDayPeriods; delete[] fStandaloneNarrowDayPeriods; + delete actualLocale; + actualLocale = nullptr; + delete validLocale; + validLocale = nullptr; disposeZoneStrings(); } @@ -2302,7 +2307,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError // of it that we need except for the time-zone and localized-pattern data, which // are stored in a separate file locBased.setLocaleIDs(ures_getLocaleByType(cb.getAlias(), ULOC_VALID_LOCALE, &status), - ures_getLocaleByType(cb.getAlias(), ULOC_ACTUAL_LOCALE, &status)); + ures_getLocaleByType(cb.getAlias(), ULOC_ACTUAL_LOCALE, &status), status); // Load eras initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status); @@ -2528,7 +2533,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError Locale DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const { - U_LOCALE_BASED(locBased, *this); + U_LOCALE_BASED(locBased, *const_cast(this)); return locBased.getLocale(type, status); } diff --git a/icu4c/source/i18n/format.cpp b/icu4c/source/i18n/format.cpp index 10856a4acba2..05bd4f240a66 100644 --- a/icu4c/source/i18n/format.cpp +++ b/icu4c/source/i18n/format.cpp @@ -24,6 +24,7 @@ #include "utypeinfo.h" // for 'typeid' to work #include "unicode/utypes.h" +#include "charstr.h" #ifndef U_I18N_IMPLEMENTATION #error U_I18N_IMPLEMENTATION not set - must be set for all ICU source files in i18n/ - see https://unicode-org.github.io/icu/userguide/howtouseicu @@ -70,22 +71,23 @@ FieldPosition::clone() const { // default constructor Format::Format() - : UObject() + : UObject(), actualLocale(nullptr), validLocale(nullptr) { - *validLocale = *actualLocale = 0; } // ------------------------------------- Format::~Format() { + delete actualLocale; + delete validLocale; } // ------------------------------------- // copy constructor Format::Format(const Format &that) - : UObject(that) + : UObject(that), actualLocale(nullptr), validLocale(nullptr) { *this = that; } @@ -97,8 +99,10 @@ Format& Format::operator=(const Format& that) { if (this != &that) { - uprv_strcpy(validLocale, that.validLocale); - uprv_strcpy(actualLocale, that.actualLocale); + UErrorCode status = U_ZERO_ERROR; + U_LOCALE_BASED(locBased, *this); + locBased.setLocaleIDs(that.validLocale, that.actualLocale, status); + U_ASSERT(U_SUCCESS(status)); } return *this; } @@ -196,20 +200,22 @@ void Format::syntaxError(const UnicodeString& pattern, Locale Format::getLocale(ULocDataLocaleType type, UErrorCode& status) const { - U_LOCALE_BASED(locBased, *this); + U_LOCALE_BASED(locBased, *const_cast(this)); return locBased.getLocale(type, status); } const char * Format::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { - U_LOCALE_BASED(locBased, *this); + U_LOCALE_BASED(locBased, *const_cast(this)); return locBased.getLocaleID(type, status); } void Format::setLocaleIDs(const char* valid, const char* actual) { U_LOCALE_BASED(locBased, *this); - locBased.setLocaleIDs(valid, actual); + UErrorCode status = U_ZERO_ERROR; + locBased.setLocaleIDs(valid, actual, status); + U_ASSERT(U_SUCCESS(status)); } U_NAMESPACE_END diff --git a/icu4c/source/i18n/unicode/calendar.h b/icu4c/source/i18n/unicode/calendar.h index b965ca381e87..382b5f214a8e 100644 --- a/icu4c/source/i18n/unicode/calendar.h +++ b/icu4c/source/i18n/unicode/calendar.h @@ -55,6 +55,7 @@ class ICUServiceFactory; typedef int32_t UFieldResolutionTable[12][8]; class BasicTimeZone; +class CharString; /** * `Calendar` is an abstract base class for converting between * a `UDate` object and a set of integer fields such as @@ -2348,8 +2349,8 @@ class U_I18N_API Calendar : public UObject { #endif /* U_HIDE_INTERNAL_API */ private: - char validLocale[ULOC_FULLNAME_CAPACITY]; - char actualLocale[ULOC_FULLNAME_CAPACITY]; + CharString* validLocale; + CharString* actualLocale; public: #if !UCONFIG_NO_SERVICE diff --git a/icu4c/source/i18n/unicode/dcfmtsym.h b/icu4c/source/i18n/unicode/dcfmtsym.h index 02e12f9c39b2..7dd155641a79 100644 --- a/icu4c/source/i18n/unicode/dcfmtsym.h +++ b/icu4c/source/i18n/unicode/dcfmtsym.h @@ -48,6 +48,7 @@ U_NAMESPACE_BEGIN +class CharString; /** * This class represents the set of symbols needed by DecimalFormat * to format numbers. DecimalFormat creates for itself an instance of @@ -504,8 +505,8 @@ class U_I18N_API DecimalFormatSymbols : public UObject { Locale locale; - char actualLocale[ULOC_FULLNAME_CAPACITY]; - char validLocale[ULOC_FULLNAME_CAPACITY]; + CharString* actualLocale; + CharString* validLocale; const char16_t* currPattern = nullptr; UnicodeString currencySpcBeforeSym[UNUM_CURRENCY_SPACING_COUNT]; diff --git a/icu4c/source/i18n/unicode/dtfmtsym.h b/icu4c/source/i18n/unicode/dtfmtsym.h index df8da36d8153..45a2e88e4818 100644 --- a/icu4c/source/i18n/unicode/dtfmtsym.h +++ b/icu4c/source/i18n/unicode/dtfmtsym.h @@ -43,6 +43,7 @@ U_NAMESPACE_BEGIN /* forward declaration */ class SimpleDateFormat; class Hashtable; +class CharString; /** * DateFormatSymbols is a public class for encapsulating localizable date-time @@ -917,8 +918,8 @@ class U_I18N_API DateFormatSymbols final : public UObject { /** valid/actual locale information * these are always ICU locales, so the length should not be a problem */ - char validLocale[ULOC_FULLNAME_CAPACITY]; - char actualLocale[ULOC_FULLNAME_CAPACITY]; + CharString* validLocale; + CharString* actualLocale; DateFormatSymbols() = delete; // default constructor not implemented diff --git a/icu4c/source/i18n/unicode/format.h b/icu4c/source/i18n/unicode/format.h index a21e61ad56d8..e10d2cbbfea3 100644 --- a/icu4c/source/i18n/unicode/format.h +++ b/icu4c/source/i18n/unicode/format.h @@ -45,6 +45,7 @@ U_NAMESPACE_BEGIN +class CharString; /** * Base class for all formats. This is an abstract base class which * specifies the protocol for classes which convert other objects or @@ -297,8 +298,8 @@ class U_I18N_API Format : public UObject { UParseError& parseError); private: - char actualLocale[ULOC_FULLNAME_CAPACITY]; - char validLocale[ULOC_FULLNAME_CAPACITY]; + CharString* actualLocale; + CharString* validLocale; }; U_NAMESPACE_END