ICU-21035 Update locale implementation to use ulocimp_getKeywordValue().

This commit is contained in:
Fredrik Roubert 2020-09-02 21:24:36 +02:00 committed by Fredrik Roubert
parent 93feb5f70a
commit 936f53a1f1
4 changed files with 45 additions and 59 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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) {

View file

@ -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;