diff --git a/icu4c/source/common/ucurr.cpp b/icu4c/source/common/ucurr.cpp index a2f4fb30e1f..70b1bbf2239 100644 --- a/icu4c/source/common/ucurr.cpp +++ b/icu4c/source/common/ucurr.cpp @@ -11,6 +11,8 @@ #if !UCONFIG_NO_FORMATTING +#include + #include "unicode/ucurr.h" #include "unicode/locid.h" #include "unicode/ures.h" @@ -602,11 +604,15 @@ ucurr_forLocale(const char* locale, if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) { // We don't know about it. Check to see if we support the variant. - uloc_getParent(locale, id, UPRV_LENGTHOF(id), ec); + CharString parent; + { + CharStringByteSink sink(&parent); + ulocimp_getParent(locale, sink, ec); + } *ec = U_USING_FALLBACK_WARNING; - // TODO: Loop over the shortened id rather than recursing and + // TODO: Loop over the parent rather than recursing and // looking again for a currency keyword. - return ucurr_forLocale(id, buff, buffCapacity, ec); + return ucurr_forLocale(parent.data(), buff, buffCapacity, ec); } if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) { // There is nothing to fallback to. Report the failure/warning if possible. @@ -629,20 +635,22 @@ ucurr_forLocale(const char* locale, * @return true if the fallback happened; false if locale is already * root (""). */ -static UBool fallback(char *loc) { - if (!*loc) { +static UBool fallback(CharString& loc) { + if (loc.isEmpty()) { return false; } UErrorCode status = U_ZERO_ERROR; - if (uprv_strcmp(loc, "en_GB") == 0) { + if (loc == "en_GB") { // HACK: See #13368. We need "en_GB" to fall back to "en_001" instead of "en" // in order to consume the correct data strings. This hack will be removed // when proper data sink loading is implemented here. - // NOTE: "001" adds 1 char over "GB". However, both call sites allocate - // arrays with length ULOC_FULLNAME_CAPACITY (plenty of room for en_001). - uprv_strcpy(loc + 3, "001"); + loc.truncate(3); + loc.append("001", status); } else { - uloc_getParent(loc, loc, (int32_t)uprv_strlen(loc), &status); + CharString tmp; + CharStringByteSink sink(&tmp); + ulocimp_getParent(loc.data(), sink, &status); + loc = std::move(tmp); } /* char *i = uprv_strrchr(loc, '_'); @@ -915,13 +923,17 @@ getCurrencyNameCount(const char* loc, int32_t* total_currency_name_count, int32_ *total_currency_name_count = 0; *total_currency_symbol_count = 0; const char16_t* s = nullptr; - char locale[ULOC_FULLNAME_CAPACITY] = ""; - uprv_strcpy(locale, loc); + CharString locale; + { + UErrorCode status = U_ZERO_ERROR; + locale.append(loc, status); + if (U_FAILURE(status)) { return; } + } const icu::Hashtable *currencySymbolsEquiv = getCurrSymbolsEquiv(); for (;;) { UErrorCode ec2 = U_ZERO_ERROR; // TODO: ures_openDirect? - UResourceBundle* rb = ures_open(U_ICUDATA_CURR, locale, &ec2); + UResourceBundle* rb = ures_open(U_ICUDATA_CURR, locale.data(), &ec2); UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, nullptr, &ec2); int32_t n = ures_getSize(curr); for (int32_t i=0; ilocaleToRuleSetNumMap, name); if (ruleSetNum == 0) { - // name and parentName can't be the same pointer, so fill in parent then copy to child. - uloc_getParent(name, parentName, ULOC_FULLNAME_CAPACITY, &errorCode); - if (*parentName == '\0') { + CharString parent; + CharStringByteSink sink(&parent); + ulocimp_getParent(name, sink, &errorCode); + if (parent.isEmpty()) { // Saves a lookup in the hash table. break; } - uprv_strcpy(name, parentName); + parent.extract(name, UPRV_LENGTHOF(name), errorCode); } else { break; } diff --git a/icu4c/source/i18n/gender.cpp b/icu4c/source/i18n/gender.cpp index 97d161de321..d023b50218a 100644 --- a/icu4c/source/i18n/gender.cpp +++ b/icu4c/source/i18n/gender.cpp @@ -19,15 +19,20 @@ #if !UCONFIG_NO_FORMATTING +#include + #include "unicode/gender.h" #include "unicode/ugender.h" #include "unicode/ures.h" +#include "bytesinkutil.h" +#include "charstr.h" #include "cmemory.h" #include "cstring.h" #include "mutex.h" #include "uassert.h" #include "ucln_in.h" +#include "ulocimp.h" #include "umutex.h" #include "uhash.h" @@ -148,12 +153,18 @@ const GenderInfo* GenderInfo::loadInstance(const Locale& locale, UErrorCode& sta const char16_t* s = ures_getStringByKey(locRes.getAlias(), curLocaleName, &resLen, &key_status); if (s == nullptr) { key_status = U_ZERO_ERROR; - char parentLocaleName[ULOC_FULLNAME_CAPACITY]; - uprv_strcpy(parentLocaleName, curLocaleName); - while (s == nullptr && uloc_getParent(parentLocaleName, parentLocaleName, ULOC_FULLNAME_CAPACITY, &key_status) > 0) { + CharString parentLocaleName(curLocaleName, key_status); + while (s == nullptr) { + { + CharString tmp; + CharStringByteSink sink(&tmp); + ulocimp_getParent(parentLocaleName.data(), sink, &status); + if (tmp.isEmpty()) break; + parentLocaleName = std::move(tmp); + } key_status = U_ZERO_ERROR; resLen = 0; - s = ures_getStringByKey(locRes.getAlias(), parentLocaleName, &resLen, &key_status); + s = ures_getStringByKey(locRes.getAlias(), parentLocaleName.data(), &resLen, &key_status); key_status = U_ZERO_ERROR; } } diff --git a/icu4c/source/i18n/plurrule.cpp b/icu4c/source/i18n/plurrule.cpp index 9c37b09e253..839d14147cc 100644 --- a/icu4c/source/i18n/plurrule.cpp +++ b/icu4c/source/i18n/plurrule.cpp @@ -12,6 +12,8 @@ #include #include +#include + #include "unicode/utypes.h" #include "unicode/localpointer.h" #include "unicode/plurrule.h" @@ -20,6 +22,7 @@ #include "unicode/numfmt.h" #include "unicode/decimfmt.h" #include "unicode/numberrangeformatter.h" +#include "bytesinkutil.h" #include "charstr.h" #include "cmemory.h" #include "cstring.h" @@ -40,6 +43,7 @@ #include "util.h" #include "pluralranges.h" #include "numrange_impl.h" +#include "ulocimp.h" #if !UCONFIG_NO_FORMATTING @@ -827,14 +831,19 @@ PluralRules::getRuleFromResource(const Locale& locale, UPluralType type, UErrorC if (s == nullptr) { // Check parent locales. UErrorCode status = U_ZERO_ERROR; - char parentLocaleName[ULOC_FULLNAME_CAPACITY]; const char *curLocaleName2=locale.getBaseName(); - uprv_strcpy(parentLocaleName, curLocaleName2); + CharString parentLocaleName(curLocaleName2, status); - while (uloc_getParent(parentLocaleName, parentLocaleName, - ULOC_FULLNAME_CAPACITY, &status) > 0) { + for (;;) { + { + CharString tmp; + CharStringByteSink sink(&tmp); + ulocimp_getParent(parentLocaleName.data(), sink, &status); + if (tmp.isEmpty()) break; + parentLocaleName = std::move(tmp); + } resLen=0; - s = ures_getStringByKey(locRes.getAlias(), parentLocaleName, &resLen, &status); + s = ures_getStringByKey(locRes.getAlias(), parentLocaleName.data(), &resLen, &status); if (s != nullptr) { errCode = U_ZERO_ERROR; break; diff --git a/icu4c/source/i18n/tmutfmt.cpp b/icu4c/source/i18n/tmutfmt.cpp index 87b509ea35c..dc48b2ee2a4 100644 --- a/icu4c/source/i18n/tmutfmt.cpp +++ b/icu4c/source/i18n/tmutfmt.cpp @@ -11,14 +11,18 @@ #if !UCONFIG_NO_FORMATTING +#include + #include "unicode/decimfmt.h" #include "unicode/localpointer.h" #include "plurrule_impl.h" #include "uvector.h" +#include "bytesinkutil.h" #include "charstr.h" #include "cmemory.h" #include "cstring.h" #include "hash.h" +#include "ulocimp.h" #include "uresimp.h" #include "ureslocs.h" #include "unicode/msgfmt.h" @@ -556,14 +560,17 @@ TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key, return; } UErrorCode status = U_ZERO_ERROR; - char parentLocale[ULOC_FULLNAME_CAPACITY]; - uprv_strcpy(parentLocale, localeName); - int32_t locNameLen; + CharString parentLocale(localeName, status); U_ASSERT(countToPatterns != nullptr); - while ((locNameLen = uloc_getParent(parentLocale, parentLocale, - ULOC_FULLNAME_CAPACITY, &status)) >= 0){ + for (;;) { + { + CharString tmp; + CharStringByteSink sink(&tmp); + ulocimp_getParent(parentLocale.data(), sink, &status); + parentLocale = std::move(tmp); + } // look for pattern for srcPluralCount in locale tree - LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_UNIT, parentLocale, &status)); + LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_UNIT, parentLocale.data(), &status)); LocalUResourceBundlePointer unitsRes(ures_getByKey(rb.getAlias(), key, nullptr, &status)); const char* timeUnitName = getTimeUnitName(srcTimeUnitField, status); LocalUResourceBundlePointer countsToPatternRB(ures_getByKey(unitsRes.getAlias(), timeUnitName, nullptr, &status)); @@ -594,14 +601,14 @@ TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key, return; } status = U_ZERO_ERROR; - if (locNameLen == 0) { + if (parentLocale.isEmpty()) { break; } } // if no unitsShort resource was found even after fallback to root locale // then search the units resource fallback from the current level to root - if ( locNameLen == 0 && uprv_strcmp(key, gShortUnitsTag) == 0) { + if ( parentLocale.isEmpty() && uprv_strcmp(key, gShortUnitsTag) == 0) { #ifdef TMUTFMT_DEBUG std::cout << "loop into searchInLocaleChain since Short-Long-Alternative \n"; #endif