From 936f53a1f1da7690d5e8237b50e8864d2f8ca65b Mon Sep 17 00:00:00 2001 From: Fredrik Roubert Date: Wed, 2 Sep 2020 21:24:36 +0200 Subject: [PATCH] ICU-21035 Update locale implementation to use ulocimp_getKeywordValue(). --- icu4c/source/common/locdispnames.cpp | 29 ++++++++-------- icu4c/source/common/locmap.cpp | 12 +++++-- icu4c/source/common/uloc.cpp | 14 ++++---- icu4c/source/common/uloc_tag.cpp | 49 +++++++++------------------- 4 files changed, 45 insertions(+), 59 deletions(-) diff --git a/icu4c/source/common/locdispnames.cpp b/icu4c/source/common/locdispnames.cpp index 655c32ba8d1..47c0667417c 100644 --- a/icu4c/source/common/locdispnames.cpp +++ b/icu4c/source/common/locdispnames.cpp @@ -26,6 +26,8 @@ #include "unicode/uloc.h" #include "unicode/ures.h" #include "unicode/ustring.h" +#include "bytesinkutil.h" +#include "charstr.h" #include "cmemory.h" #include "cstring.h" #include "putilimp.h" @@ -811,10 +813,6 @@ uloc_getDisplayKeywordValue( const char* locale, UErrorCode* status){ - char keywordValue[ULOC_FULLNAME_CAPACITY*4]; - int32_t capacity = ULOC_FULLNAME_CAPACITY*4; - int32_t keywordValueLen =0; - /* argument checking */ if(status==NULL || U_FAILURE(*status)) { return 0; @@ -826,10 +824,11 @@ uloc_getDisplayKeywordValue( const char* locale, } /* get the keyword value */ - keywordValue[0]=0; - keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, capacity, status); - if (*status == U_STRING_NOT_TERMINATED_WARNING) - *status = U_BUFFER_OVERFLOW_ERROR; + CharString keywordValue; + { + CharStringByteSink sink(&keywordValue); + ulocimp_getKeywordValue(locale, keyword, sink, status); + } /* * if the keyword is equal to currency .. then to get the display name @@ -845,7 +844,7 @@ uloc_getDisplayKeywordValue( const char* locale, icu::LocalUResourceBundlePointer currencies( ures_getByKey(bundle.getAlias(), _kCurrencies, NULL, status)); icu::LocalUResourceBundlePointer currency( - ures_getByKeyWithFallback(currencies.getAlias(), keywordValue, NULL, status)); + ures_getByKeyWithFallback(currencies.getAlias(), keywordValue.data(), NULL, status)); dispName = ures_getStringByIndex(currency.getAlias(), UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status); @@ -869,12 +868,12 @@ uloc_getDisplayKeywordValue( const char* locale, } }else{ /* we have not found the display name for the value .. just copy over */ - if(keywordValueLen <= destCapacity){ - u_charsToUChars(keywordValue, dest, keywordValueLen); - return u_terminateUChars(dest, destCapacity, keywordValueLen, status); + if(keywordValue.length() <= destCapacity){ + u_charsToUChars(keywordValue.data(), dest, keywordValue.length()); + return u_terminateUChars(dest, destCapacity, keywordValue.length(), status); }else{ *status = U_BUFFER_OVERFLOW_ERROR; - return keywordValueLen; + return keywordValue.length(); } } @@ -883,8 +882,8 @@ uloc_getDisplayKeywordValue( const char* locale, return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale, _kTypes, keyword, - keywordValue, - keywordValue, + keywordValue.data(), + keywordValue.data(), dest, destCapacity, status); } diff --git a/icu4c/source/common/locmap.cpp b/icu4c/source/common/locmap.cpp index a6311343551..29a5646385e 100644 --- a/icu4c/source/common/locmap.cpp +++ b/icu4c/source/common/locmap.cpp @@ -28,8 +28,11 @@ */ #include "locmap.h" +#include "bytesinkutil.h" +#include "charstr.h" #include "cstring.h" #include "cmemory.h" +#include "ulocimp.h" #include "unicode/uloc.h" #if U_PLATFORM_HAS_WIN32_API && UCONFIG_USE_WINDOWS_LCID_MAPPING_API @@ -1167,15 +1170,18 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status) // conversion functionality when available. #if U_PLATFORM_HAS_WIN32_API && UCONFIG_USE_WINDOWS_LCID_MAPPING_API int32_t len; - char collVal[ULOC_KEYWORDS_CAPACITY] = {}; char baseName[ULOC_FULLNAME_CAPACITY] = {}; const char * mylocaleID = localeID; // Check any for keywords. if (uprv_strchr(localeID, '@')) { - len = uloc_getKeywordValue(localeID, "collation", collVal, UPRV_LENGTHOF(collVal) - 1, status); - if (U_SUCCESS(*status) && len > 0) + icu::CharString collVal; + { + icu::CharStringByteSink sink(&collVal); + ulocimp_getKeywordValue(localeID, "collation", sink, status); + } + if (U_SUCCESS(*status) && !collVal.isEmpty()) { // If it contains the keyword collation, return 0 so that the LCID lookup table will be used. return 0; diff --git a/icu4c/source/common/uloc.cpp b/icu4c/source/common/uloc.cpp index 07660d7e629..42cbe4be7ce 100644 --- a/icu4c/source/common/uloc.cpp +++ b/icu4c/source/common/uloc.cpp @@ -1995,22 +1995,22 @@ uloc_getLCID(const char* localeID) // uprv_convertToLCID does not support keywords other than collation. // Remove all keywords except collation. int32_t len; - char collVal[ULOC_KEYWORDS_CAPACITY]; char tmpLocaleID[ULOC_FULLNAME_CAPACITY]; - len = uloc_getKeywordValue(localeID, "collation", collVal, - UPRV_LENGTHOF(collVal) - 1, &status); - - if (U_SUCCESS(status) && len > 0) { - collVal[len] = 0; + CharString collVal; + { + CharStringByteSink sink(&collVal); + ulocimp_getKeywordValue(localeID, "collation", sink, &status); + } + if (U_SUCCESS(status) && !collVal.isEmpty()) { len = uloc_getBaseName(localeID, tmpLocaleID, UPRV_LENGTHOF(tmpLocaleID) - 1, &status); if (U_SUCCESS(status) && len > 0) { tmpLocaleID[len] = 0; - len = uloc_setKeywordValue("collation", collVal, tmpLocaleID, + len = uloc_setKeywordValue("collation", collVal.data(), tmpLocaleID, UPRV_LENGTHOF(tmpLocaleID) - len - 1, &status); if (U_SUCCESS(status) && len > 0) { diff --git a/icu4c/source/common/uloc_tag.cpp b/icu4c/source/common/uloc_tag.cpp index 9e9365041d5..b4e3c922ca9 100644 --- a/icu4c/source/common/uloc_tag.cpp +++ b/icu4c/source/common/uloc_tag.cpp @@ -15,6 +15,7 @@ #include "unicode/uenum.h" #include "unicode/uloc.h" #include "ustr_imp.h" +#include "bytesinkutil.h" #include "charstr.h" #include "cmemory.h" #include "cstring.h" @@ -1269,35 +1270,17 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st UBool isBcpUExt; while (TRUE) { - icu::CharString buf; key = uenum_next(keywordEnum.getAlias(), NULL, status); if (key == NULL) { break; } - char* buffer; - int32_t resultCapacity = ULOC_KEYWORD_AND_VALUES_CAPACITY; - - for (;;) { - buffer = buf.getAppendBuffer( - /*minCapacity=*/resultCapacity, - /*desiredCapacityHint=*/resultCapacity, - resultCapacity, - tmpStatus); - - if (U_FAILURE(tmpStatus)) { - break; - } - len = uloc_getKeywordValue( - localeID, key, buffer, resultCapacity, &tmpStatus); - - if (tmpStatus != U_BUFFER_OVERFLOW_ERROR) { - break; - } - - resultCapacity = len; - tmpStatus = U_ZERO_ERROR; + icu::CharString buf; + { + icu::CharStringByteSink sink(&buf); + ulocimp_getKeywordValue(localeID, key, sink, &tmpStatus); } + len = buf.length(); if (U_FAILURE(tmpStatus)) { if (tmpStatus == U_MEMORY_ALLOCATION_ERROR) { @@ -1313,11 +1296,6 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st continue; } - buf.append(buffer, len, tmpStatus); - if (tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { - tmpStatus = U_ZERO_ERROR; // Terminators provided by CharString. - } - keylen = (int32_t)uprv_strlen(key); isBcpUExt = (keylen > 1); @@ -2707,14 +2685,17 @@ ulocimp_toLanguageTag(const char* localeID, key = uenum_next(kwdEnum.getAlias(), &len, &tmpStatus); if (len == 1 && *key == PRIVATEUSE) { - char buf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; - buf[0] = PRIVATEUSE; - buf[1] = SEP; - len = uloc_getKeywordValue(localeID, key, &buf[2], sizeof(buf) - 2, &tmpStatus); + icu::CharString buf; + { + icu::CharStringByteSink sink(&buf); + ulocimp_getKeywordValue(localeID, key, sink, &tmpStatus); + } if (U_SUCCESS(tmpStatus)) { - if (ultag_isPrivateuseValueSubtags(&buf[2], len)) { + if (ultag_isPrivateuseValueSubtags(buf.data(), buf.length())) { /* return private use only tag */ - sink.Append(buf, len + 2); + static const char PREFIX[] = { PRIVATEUSE, SEP }; + sink.Append(PREFIX, sizeof(PREFIX)); + sink.Append(buf.data(), buf.length()); done = TRUE; } else if (strict) { *status = U_ILLEGAL_ARGUMENT_ERROR; -- 2.40.0