mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-22520 Replace char arrays with icu::CharString.
This commit is contained in:
parent
930b4d9ab9
commit
d28e12b1f2
10 changed files with 152 additions and 189 deletions
|
@ -357,7 +357,7 @@ _getStringOrCopyKey(const char *path, const char *locale,
|
|||
return u_terminateUChars(dest, destCapacity, length, pErrorCode);
|
||||
}
|
||||
|
||||
typedef int32_t U_CALLCONV UDisplayNameGetter(const char *, char *, int32_t, UErrorCode *);
|
||||
using UDisplayNameGetter = icu::CharString(const char*, UErrorCode&);
|
||||
|
||||
static int32_t
|
||||
_getDisplayNameForComponent(const char *locale,
|
||||
|
@ -366,8 +366,6 @@ _getDisplayNameForComponent(const char *locale,
|
|||
UDisplayNameGetter *getter,
|
||||
const char *tag,
|
||||
UErrorCode *pErrorCode) {
|
||||
char localeBuffer[ULOC_FULLNAME_CAPACITY*4];
|
||||
int32_t length;
|
||||
UErrorCode localStatus;
|
||||
const char* root = nullptr;
|
||||
|
||||
|
@ -382,15 +380,15 @@ _getDisplayNameForComponent(const char *locale,
|
|||
}
|
||||
|
||||
localStatus = U_ZERO_ERROR;
|
||||
length=(*getter)(locale, localeBuffer, sizeof(localeBuffer), &localStatus);
|
||||
if(U_FAILURE(localStatus) || localStatus==U_STRING_NOT_TERMINATED_WARNING) {
|
||||
icu::CharString localeBuffer = (*getter)(locale, localStatus);
|
||||
if (U_FAILURE(localStatus)) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if(length==0) {
|
||||
if (localeBuffer.isEmpty()) {
|
||||
// For the display name, we treat this as unknown language (ICU-20273).
|
||||
if (getter == uloc_getLanguage) {
|
||||
uprv_strcpy(localeBuffer, "und");
|
||||
if (getter == ulocimp_getLanguage) {
|
||||
localeBuffer.append("und", *pErrorCode);
|
||||
} else {
|
||||
return u_terminateUChars(dest, destCapacity, 0, pErrorCode);
|
||||
}
|
||||
|
@ -399,8 +397,8 @@ _getDisplayNameForComponent(const char *locale,
|
|||
root = tag == _kCountries ? U_ICUDATA_REGION : U_ICUDATA_LANG;
|
||||
|
||||
return _getStringOrCopyKey(root, displayLocale,
|
||||
tag, nullptr, localeBuffer,
|
||||
localeBuffer,
|
||||
tag, nullptr, localeBuffer.data(),
|
||||
localeBuffer.data(),
|
||||
dest, destCapacity,
|
||||
pErrorCode);
|
||||
}
|
||||
|
@ -411,7 +409,7 @@ uloc_getDisplayLanguage(const char *locale,
|
|||
char16_t *dest, int32_t destCapacity,
|
||||
UErrorCode *pErrorCode) {
|
||||
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
|
||||
uloc_getLanguage, _kLanguages, pErrorCode);
|
||||
ulocimp_getLanguage, _kLanguages, pErrorCode);
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
|
@ -422,17 +420,17 @@ uloc_getDisplayScript(const char* locale,
|
|||
{
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
|
||||
uloc_getScript, _kScriptsStandAlone, &err);
|
||||
ulocimp_getScript, _kScriptsStandAlone, &err);
|
||||
|
||||
if (destCapacity == 0 && err == U_BUFFER_OVERFLOW_ERROR) {
|
||||
// For preflight, return the max of the value and the fallback.
|
||||
int32_t fallback_res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
|
||||
uloc_getScript, _kScripts, pErrorCode);
|
||||
ulocimp_getScript, _kScripts, pErrorCode);
|
||||
return (fallback_res > res) ? fallback_res : res;
|
||||
}
|
||||
if ( err == U_USING_DEFAULT_WARNING ) {
|
||||
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
|
||||
uloc_getScript, _kScripts, pErrorCode);
|
||||
ulocimp_getScript, _kScripts, pErrorCode);
|
||||
} else {
|
||||
*pErrorCode = err;
|
||||
return res;
|
||||
|
@ -446,7 +444,7 @@ uloc_getDisplayScriptInContext(const char* locale,
|
|||
UErrorCode *pErrorCode)
|
||||
{
|
||||
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
|
||||
uloc_getScript, _kScripts, pErrorCode);
|
||||
ulocimp_getScript, _kScripts, pErrorCode);
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
|
@ -455,7 +453,7 @@ uloc_getDisplayCountry(const char *locale,
|
|||
char16_t *dest, int32_t destCapacity,
|
||||
UErrorCode *pErrorCode) {
|
||||
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
|
||||
uloc_getCountry, _kCountries, pErrorCode);
|
||||
ulocimp_getRegion, _kCountries, pErrorCode);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -469,7 +467,7 @@ uloc_getDisplayVariant(const char *locale,
|
|||
char16_t *dest, int32_t destCapacity,
|
||||
UErrorCode *pErrorCode) {
|
||||
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
|
||||
uloc_getVariant, _kVariants, pErrorCode);
|
||||
ulocimp_getVariant, _kVariants, pErrorCode);
|
||||
}
|
||||
|
||||
/* Instead of having a separate pass for 'special' patterns, reintegrate the two
|
||||
|
|
|
@ -509,22 +509,16 @@ static const char LANG_DIR_STRING[] =
|
|||
U_CAPI UBool U_EXPORT2
|
||||
uloc_isRightToLeft(const char *locale) {
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
char script[8];
|
||||
int32_t scriptLength = uloc_getScript(locale, script, UPRV_LENGTHOF(script), &errorCode);
|
||||
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING ||
|
||||
scriptLength == 0) {
|
||||
icu::CharString lang;
|
||||
icu::CharString script;
|
||||
ulocimp_getSubtags(locale, &lang, &script, nullptr, nullptr, nullptr, errorCode);
|
||||
if (U_FAILURE(errorCode) || script.isEmpty()) {
|
||||
// Fastpath: We know the likely scripts and their writing direction
|
||||
// for some common languages.
|
||||
errorCode = U_ZERO_ERROR;
|
||||
char lang[8];
|
||||
int32_t langLength = uloc_getLanguage(locale, lang, UPRV_LENGTHOF(lang), &errorCode);
|
||||
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
return false;
|
||||
}
|
||||
if (langLength > 0) {
|
||||
const char* langPtr = uprv_strstr(LANG_DIR_STRING, lang);
|
||||
if (!lang.isEmpty()) {
|
||||
const char* langPtr = uprv_strstr(LANG_DIR_STRING, lang.data());
|
||||
if (langPtr != nullptr) {
|
||||
switch (langPtr[langLength]) {
|
||||
switch (langPtr[lang.length()]) {
|
||||
case '-': return false;
|
||||
case '+': return true;
|
||||
default: break; // partial match of a longer code
|
||||
|
@ -538,16 +532,15 @@ uloc_isRightToLeft(const char *locale) {
|
|||
icu::CharStringByteSink sink(&likely);
|
||||
ulocimp_addLikelySubtags(locale, sink, &errorCode);
|
||||
}
|
||||
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
if (U_FAILURE(errorCode)) {
|
||||
return false;
|
||||
}
|
||||
scriptLength = uloc_getScript(likely.data(), script, UPRV_LENGTHOF(script), &errorCode);
|
||||
if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING ||
|
||||
scriptLength == 0) {
|
||||
ulocimp_getSubtags(likely.data(), nullptr, &script, nullptr, nullptr, nullptr, errorCode);
|
||||
if (U_FAILURE(errorCode) || script.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script);
|
||||
UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script.data());
|
||||
return uscript_isRightToLeft(scriptCode);
|
||||
}
|
||||
|
||||
|
@ -560,36 +553,30 @@ Locale::isRightToLeft() const {
|
|||
|
||||
U_NAMESPACE_END
|
||||
|
||||
// The following must at least allow for rg key value (6) plus terminator (1).
|
||||
#define ULOC_RG_BUFLEN 8
|
||||
|
||||
namespace {
|
||||
int GetRegionFromKey(const char *localeID, const char* key, char* buf) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::CharString
|
||||
GetRegionFromKey(const char* localeID, const char* key, UErrorCode& status) {
|
||||
icu::CharString result;
|
||||
|
||||
// First check for rg keyword value
|
||||
icu::CharString rg;
|
||||
// First check for keyword value
|
||||
icu::CharString kw;
|
||||
{
|
||||
icu::CharStringByteSink sink(&rg);
|
||||
icu::CharStringByteSink sink(&kw);
|
||||
ulocimp_getKeywordValue(localeID, key, sink, &status);
|
||||
}
|
||||
int32_t len = rg.length();
|
||||
if (U_FAILURE(status) || len < 3 || len > 7) {
|
||||
len = 0;
|
||||
} else {
|
||||
int32_t len = kw.length();
|
||||
if (U_SUCCESS(status) && len >= 3 && len <= 7) {
|
||||
// chop off the subdivision code (which will generally be "zzzz" anyway)
|
||||
const char* const data = rg.data();
|
||||
const char* const data = kw.data();
|
||||
if (uprv_isASCIILetter(data[0])) {
|
||||
len = 2;
|
||||
buf[0] = uprv_toupper(data[0]);
|
||||
buf[1] = uprv_toupper(data[1]);
|
||||
result.append(uprv_toupper(data[0]), status);
|
||||
result.append(uprv_toupper(data[1]), status);
|
||||
} else {
|
||||
// assume three-digit region code
|
||||
len = 3;
|
||||
uprv_memcpy(buf, data, len);
|
||||
result.append(data, 3, status);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
@ -599,17 +586,14 @@ ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion,
|
|||
if (U_FAILURE(*status)) {
|
||||
return 0;
|
||||
}
|
||||
char rgBuf[ULOC_RG_BUFLEN];
|
||||
int32_t rgLen = GetRegionFromKey(localeID, "rg", rgBuf);
|
||||
if (rgLen == 0) {
|
||||
icu::CharString rgBuf = GetRegionFromKey(localeID, "rg", *status);
|
||||
if (U_SUCCESS(*status) && rgBuf.isEmpty()) {
|
||||
// No valid rg keyword value, try for unicode_region_subtag
|
||||
rgLen = uloc_getCountry(localeID, rgBuf, ULOC_RG_BUFLEN, status);
|
||||
if (U_FAILURE(*status)) {
|
||||
rgLen = 0;
|
||||
} else if (rgLen == 0 && inferRegion) {
|
||||
rgBuf = ulocimp_getRegion(localeID, *status);
|
||||
if (U_SUCCESS(*status) && rgBuf.isEmpty() && inferRegion) {
|
||||
// Second check for sd keyword value
|
||||
rgLen = GetRegionFromKey(localeID, "sd", rgBuf);
|
||||
if (rgLen == 0) {
|
||||
rgBuf = GetRegionFromKey(localeID, "sd", *status);
|
||||
if (U_SUCCESS(*status) && rgBuf.isEmpty()) {
|
||||
// no unicode_region_subtag but inferRegion true, try likely subtags
|
||||
UErrorCode rgStatus = U_ZERO_ERROR;
|
||||
icu::CharString locBuf;
|
||||
|
@ -618,17 +602,11 @@ ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion,
|
|||
ulocimp_addLikelySubtags(localeID, sink, &rgStatus);
|
||||
}
|
||||
if (U_SUCCESS(rgStatus)) {
|
||||
rgLen = uloc_getCountry(locBuf.data(), rgBuf, ULOC_RG_BUFLEN, status);
|
||||
if (U_FAILURE(*status)) {
|
||||
rgLen = 0;
|
||||
}
|
||||
rgBuf = ulocimp_getRegion(locBuf.data(), *status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rgBuf[rgLen] = 0;
|
||||
uprv_strncpy(region, rgBuf, regionCapacity);
|
||||
return u_terminateChars(region, regionCapacity, rgLen, status);
|
||||
return rgBuf.extract(region, regionCapacity, *status);
|
||||
}
|
||||
|
||||
|
|
|
@ -2143,17 +2143,16 @@ U_CAPI const char* U_EXPORT2
|
|||
uloc_getISO3Language(const char* localeID)
|
||||
{
|
||||
int16_t offset;
|
||||
char lang[ULOC_LANG_CAPACITY];
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
|
||||
if (localeID == nullptr)
|
||||
{
|
||||
localeID = uloc_getDefault();
|
||||
}
|
||||
uloc_getLanguage(localeID, lang, ULOC_LANG_CAPACITY, &err);
|
||||
CharString lang = ulocimp_getLanguage(localeID, err);
|
||||
if (U_FAILURE(err))
|
||||
return "";
|
||||
offset = _findIndex(LANGUAGES, lang);
|
||||
offset = _findIndex(LANGUAGES, lang.data());
|
||||
if (offset < 0)
|
||||
return "";
|
||||
return LANGUAGES_3[offset];
|
||||
|
@ -2163,17 +2162,16 @@ U_CAPI const char* U_EXPORT2
|
|||
uloc_getISO3Country(const char* localeID)
|
||||
{
|
||||
int16_t offset;
|
||||
char cntry[ULOC_LANG_CAPACITY];
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
|
||||
if (localeID == nullptr)
|
||||
{
|
||||
localeID = uloc_getDefault();
|
||||
}
|
||||
uloc_getCountry(localeID, cntry, ULOC_LANG_CAPACITY, &err);
|
||||
CharString cntry = ulocimp_getRegion(localeID, err);
|
||||
if (U_FAILURE(err))
|
||||
return "";
|
||||
offset = _findIndex(COUNTRIES, cntry);
|
||||
offset = _findIndex(COUNTRIES, cntry.data());
|
||||
if (offset < 0)
|
||||
return "";
|
||||
|
||||
|
@ -2184,7 +2182,6 @@ U_CAPI uint32_t U_EXPORT2
|
|||
uloc_getLCID(const char* localeID)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
char langID[ULOC_FULLNAME_CAPACITY];
|
||||
uint32_t lcid = 0;
|
||||
|
||||
/* Check for incomplete id. */
|
||||
|
@ -2203,8 +2200,8 @@ uloc_getLCID(const char* localeID)
|
|||
return lcid;
|
||||
}
|
||||
|
||||
uloc_getLanguage(localeID, langID, sizeof(langID), &status);
|
||||
if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
CharString langID = ulocimp_getLanguage(localeID, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2224,7 +2221,7 @@ uloc_getLCID(const char* localeID)
|
|||
}
|
||||
ulocimp_setKeywordValue("collation", collVal.data(), tmpLocaleID, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
return uprv_convertToLCID(langID, tmpLocaleID.data(), &status);
|
||||
return uprv_convertToLCID(langID.data(), tmpLocaleID.data(), &status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2232,7 +2229,7 @@ uloc_getLCID(const char* localeID)
|
|||
status = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
return uprv_convertToLCID(langID, localeID, &status);
|
||||
return uprv_convertToLCID(langID.data(), localeID, &status);
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
|
|
|
@ -1012,28 +1012,25 @@ _initializeULanguageTag(ULanguageTag* langtag) {
|
|||
|
||||
static void
|
||||
_appendLanguageToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UErrorCode* status) {
|
||||
char buf[ULOC_LANG_CAPACITY];
|
||||
UErrorCode tmpStatus = U_ZERO_ERROR;
|
||||
int32_t len, i;
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = uloc_getLanguage(localeID, buf, sizeof(buf), &tmpStatus);
|
||||
if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
icu::CharString buf = ulocimp_getLanguage(localeID, tmpStatus);
|
||||
if (U_FAILURE(tmpStatus)) {
|
||||
if (strict) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/* Note: returned language code is in lower case letters */
|
||||
|
||||
if (len == 0) {
|
||||
if (buf.isEmpty()) {
|
||||
sink.Append(LANG_UND, LANG_UND_LEN);
|
||||
} else if (!ultag_isLanguageSubtag(buf, len)) {
|
||||
} else if (!ultag_isLanguageSubtag(buf.data(), buf.length())) {
|
||||
/* invalid language code */
|
||||
if (strict) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -1042,42 +1039,40 @@ _appendLanguageToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st
|
|||
sink.Append(LANG_UND, LANG_UND_LEN);
|
||||
} else {
|
||||
/* resolve deprecated */
|
||||
for (i = 0; i < UPRV_LENGTHOF(DEPRECATEDLANGS); i += 2) {
|
||||
for (int32_t i = 0; i < UPRV_LENGTHOF(DEPRECATEDLANGS); i += 2) {
|
||||
// 2-letter deprecated subtags are listede before 3-letter
|
||||
// ones in DEPRECATEDLANGS[]. Get out of loop on coming
|
||||
// across the 1st 3-letter subtag, if the input is a 2-letter code.
|
||||
// to avoid continuing to try when there's no match.
|
||||
if (uprv_strlen(buf) < uprv_strlen(DEPRECATEDLANGS[i])) break;
|
||||
if (uprv_compareInvCharsAsAscii(buf, DEPRECATEDLANGS[i]) == 0) {
|
||||
uprv_strcpy(buf, DEPRECATEDLANGS[i + 1]);
|
||||
len = (int32_t)uprv_strlen(buf);
|
||||
break;
|
||||
if (buf.length() < (int32_t)uprv_strlen(DEPRECATEDLANGS[i])) break;
|
||||
if (uprv_compareInvCharsAsAscii(buf.data(), DEPRECATEDLANGS[i]) == 0) {
|
||||
const char* const resolved = DEPRECATEDLANGS[i + 1];
|
||||
sink.Append(resolved, (int32_t)uprv_strlen(resolved));
|
||||
return;
|
||||
}
|
||||
}
|
||||
sink.Append(buf, len);
|
||||
sink.Append(buf.data(), buf.length());
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_appendScriptToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UErrorCode* status) {
|
||||
char buf[ULOC_SCRIPT_CAPACITY];
|
||||
UErrorCode tmpStatus = U_ZERO_ERROR;
|
||||
int32_t len;
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = uloc_getScript(localeID, buf, sizeof(buf), &tmpStatus);
|
||||
if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
icu::CharString buf = ulocimp_getScript(localeID, tmpStatus);
|
||||
if (U_FAILURE(tmpStatus)) {
|
||||
if (strict) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if (!ultag_isScriptSubtag(buf, len)) {
|
||||
if (!buf.isEmpty()) {
|
||||
if (!ultag_isScriptSubtag(buf.data(), buf.length())) {
|
||||
/* invalid script code */
|
||||
if (strict) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -1085,31 +1080,29 @@ _appendScriptToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool stri
|
|||
return;
|
||||
} else {
|
||||
sink.Append("-", 1);
|
||||
sink.Append(buf, len);
|
||||
sink.Append(buf.data(), buf.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_appendRegionToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UErrorCode* status) {
|
||||
char buf[ULOC_COUNTRY_CAPACITY];
|
||||
UErrorCode tmpStatus = U_ZERO_ERROR;
|
||||
int32_t len;
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = uloc_getCountry(localeID, buf, sizeof(buf), &tmpStatus);
|
||||
if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
icu::CharString buf = ulocimp_getRegion(localeID, tmpStatus);
|
||||
if (U_FAILURE(tmpStatus)) {
|
||||
if (strict) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if (!ultag_isRegionSubtag(buf, len)) {
|
||||
if (!buf.isEmpty()) {
|
||||
if (!ultag_isRegionSubtag(buf.data(), buf.length())) {
|
||||
/* invalid region code */
|
||||
if (strict) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -1118,14 +1111,14 @@ _appendRegionToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool stri
|
|||
} else {
|
||||
sink.Append("-", 1);
|
||||
/* resolve deprecated */
|
||||
for (int i = 0; i < UPRV_LENGTHOF(DEPRECATEDREGIONS); i += 2) {
|
||||
if (uprv_compareInvCharsAsAscii(buf, DEPRECATEDREGIONS[i]) == 0) {
|
||||
uprv_strcpy(buf, DEPRECATEDREGIONS[i + 1]);
|
||||
len = (int32_t)uprv_strlen(buf);
|
||||
break;
|
||||
for (int32_t i = 0; i < UPRV_LENGTHOF(DEPRECATEDREGIONS); i += 2) {
|
||||
if (uprv_compareInvCharsAsAscii(buf.data(), DEPRECATEDREGIONS[i]) == 0) {
|
||||
const char* const resolved = DEPRECATEDREGIONS[i + 1];
|
||||
sink.Append(resolved, (int32_t)uprv_strlen(resolved));
|
||||
return;
|
||||
}
|
||||
}
|
||||
sink.Append(buf, len);
|
||||
sink.Append(buf.data(), buf.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1145,15 +1138,13 @@ static void _sortVariants(VariantListEntry* first) {
|
|||
|
||||
static void
|
||||
_appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UBool *hadPosix, UErrorCode* status) {
|
||||
char buf[ULOC_FULLNAME_CAPACITY];
|
||||
UErrorCode tmpStatus = U_ZERO_ERROR;
|
||||
int32_t len, i;
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = uloc_getVariant(localeID, buf, sizeof(buf), &tmpStatus);
|
||||
icu::CharString buf = ulocimp_getVariant(localeID, tmpStatus);
|
||||
if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
if (strict) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -1161,13 +1152,13 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st
|
|||
return;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if (!buf.isEmpty()) {
|
||||
char *p, *pVar;
|
||||
UBool bNext = true;
|
||||
VariantListEntry *varFirst = nullptr;
|
||||
|
||||
pVar = nullptr;
|
||||
p = buf;
|
||||
p = buf.data();
|
||||
while (bNext) {
|
||||
if (*p == SEP || *p == LOCALE_SEP || *p == 0) {
|
||||
if (*p == 0) {
|
||||
|
@ -1184,13 +1175,13 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool st
|
|||
} else {
|
||||
/* ICU uses upper case letters for variants, but
|
||||
the canonical format is lowercase in BCP47 */
|
||||
for (i = 0; *(pVar + i) != 0; i++) {
|
||||
for (int32_t i = 0; *(pVar + i) != 0; i++) {
|
||||
*(pVar + i) = uprv_tolower(*(pVar + i));
|
||||
}
|
||||
|
||||
/* validate */
|
||||
if (_isVariantSubtag(pVar, -1)) {
|
||||
if (uprv_strcmp(pVar,POSIX_VALUE) || len != (int32_t)uprv_strlen(POSIX_VALUE)) {
|
||||
if (uprv_strcmp(pVar,POSIX_VALUE) || buf.length() != (int32_t)uprv_strlen(POSIX_VALUE)) {
|
||||
/* emit the variant to the list */
|
||||
icu::LocalPointer<VariantListEntry> var(new VariantListEntry, *status);
|
||||
if (U_FAILURE(*status)) {
|
||||
|
@ -1858,30 +1849,28 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode* status)
|
|||
static void
|
||||
_appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool strict, UBool hadPosix, UErrorCode* status) {
|
||||
(void)hadPosix;
|
||||
char buf[ULOC_FULLNAME_CAPACITY];
|
||||
UErrorCode tmpStatus = U_ZERO_ERROR;
|
||||
int32_t len, i;
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = uloc_getVariant(localeID, buf, sizeof(buf), &tmpStatus);
|
||||
if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
icu::CharString buf = ulocimp_getVariant(localeID, tmpStatus);
|
||||
if (U_FAILURE(tmpStatus)) {
|
||||
if (strict) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if (!buf.isEmpty()) {
|
||||
char *p, *pPriv;
|
||||
UBool bNext = true;
|
||||
UBool firstValue = true;
|
||||
UBool writeValue;
|
||||
|
||||
pPriv = nullptr;
|
||||
p = buf;
|
||||
p = buf.data();
|
||||
while (bNext) {
|
||||
writeValue = false;
|
||||
if (*p == SEP || *p == LOCALE_SEP || *p == 0) {
|
||||
|
@ -1892,7 +1881,7 @@ _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool
|
|||
}
|
||||
if (pPriv != nullptr) {
|
||||
/* Private use in the canonical format is lowercase in BCP47 */
|
||||
for (i = 0; *(pPriv + i) != 0; i++) {
|
||||
for (int32_t i = 0; *(pPriv + i) != 0; i++) {
|
||||
*(pPriv + i) = uprv_tolower(*(pPriv + i));
|
||||
}
|
||||
|
||||
|
@ -1923,7 +1912,7 @@ _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, UBool
|
|||
firstValue = false;
|
||||
}
|
||||
|
||||
len = (int32_t)uprv_strlen(pPriv);
|
||||
int32_t len = (int32_t)uprv_strlen(pPriv);
|
||||
sink.Append(pPriv, len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,8 +94,16 @@ static UBool chopLocale(char *name) {
|
|||
|
||||
static UBool hasVariant(const char* localeID) {
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
int32_t variantLength = uloc_getVariant(localeID, nullptr, 0, &err);
|
||||
return variantLength != 0;
|
||||
CheckedArrayByteSink sink(nullptr, 0);
|
||||
ulocimp_getSubtags(
|
||||
localeID,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&sink,
|
||||
nullptr,
|
||||
err);
|
||||
return sink.NumberOfBytesAppended() != 0;
|
||||
}
|
||||
|
||||
// This file contains the tables for doing locale fallback, which are generated
|
||||
|
@ -3249,11 +3257,9 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity,
|
|||
if (res != NULL && uprv_strcmp(resName, "collations") == 0) {
|
||||
const char *validLoc = ures_getLocaleByType(res, ULOC_VALID_LOCALE, &subStatus);
|
||||
if (U_SUCCESS(subStatus) && validLoc != NULL && validLoc[0] != 0 && uprv_strcmp(validLoc, "root") != 0) {
|
||||
char validLang[ULOC_LANG_CAPACITY];
|
||||
char parentLang[ULOC_LANG_CAPACITY];
|
||||
uloc_getLanguage(validLoc, validLang, ULOC_LANG_CAPACITY, &subStatus);
|
||||
uloc_getLanguage(parent.data(), parentLang, ULOC_LANG_CAPACITY, &subStatus);
|
||||
if (U_SUCCESS(subStatus) && uprv_strcmp(validLang, parentLang) != 0) {
|
||||
CharString validLang = ulocimp_getLanguage(validLoc, subStatus);
|
||||
CharString parentLang = ulocimp_getLanguage(parent.data(), subStatus);
|
||||
if (U_SUCCESS(subStatus) && validLang != parentLang) {
|
||||
// validLoc is not root and has a different language than parent, use it instead
|
||||
found.clear().append(validLoc, subStatus);
|
||||
haveFound = true;
|
||||
|
|
|
@ -57,33 +57,25 @@ setOneCode(UScriptCode script, UScriptCode *scripts, int32_t capacity, UErrorCod
|
|||
static int32_t
|
||||
getCodesFromLocale(const char *locale,
|
||||
UScriptCode *scripts, int32_t capacity, UErrorCode *err) {
|
||||
UErrorCode internalErrorCode = U_ZERO_ERROR;
|
||||
char lang[8] = {0};
|
||||
char script[8] = {0};
|
||||
int32_t scriptLength;
|
||||
if(U_FAILURE(*err)) { return 0; }
|
||||
if (U_FAILURE(*err)) { return 0; }
|
||||
icu::CharString lang;
|
||||
icu::CharString script;
|
||||
ulocimp_getSubtags(locale, &lang, &script, nullptr, nullptr, nullptr, *err);
|
||||
if (U_FAILURE(*err)) { return 0; }
|
||||
// Multi-script languages, equivalent to the LocaleScript data
|
||||
// that we used to load from locale resource bundles.
|
||||
/*length = */ uloc_getLanguage(locale, lang, UPRV_LENGTHOF(lang), &internalErrorCode);
|
||||
if(U_FAILURE(internalErrorCode) || internalErrorCode == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
return 0;
|
||||
}
|
||||
if(0 == uprv_strcmp(lang, "ja")) {
|
||||
if (lang == "ja") {
|
||||
return setCodes(JAPANESE, UPRV_LENGTHOF(JAPANESE), scripts, capacity, err);
|
||||
}
|
||||
if(0 == uprv_strcmp(lang, "ko")) {
|
||||
if (lang == "ko") {
|
||||
return setCodes(KOREAN, UPRV_LENGTHOF(KOREAN), scripts, capacity, err);
|
||||
}
|
||||
scriptLength = uloc_getScript(locale, script, UPRV_LENGTHOF(script), &internalErrorCode);
|
||||
if(U_FAILURE(internalErrorCode) || internalErrorCode == U_STRING_NOT_TERMINATED_WARNING) {
|
||||
return 0;
|
||||
}
|
||||
if(0 == uprv_strcmp(lang, "zh") && 0 == uprv_strcmp(script, "Hant")) {
|
||||
if (lang == "zh" && script == "Hant") {
|
||||
return setCodes(HAN_BOPO, UPRV_LENGTHOF(HAN_BOPO), scripts, capacity, err);
|
||||
}
|
||||
// Explicit script code.
|
||||
if(scriptLength != 0) {
|
||||
UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script);
|
||||
if (!script.isEmpty()) {
|
||||
UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script.data());
|
||||
if(scriptCode != USCRIPT_INVALID_CODE) {
|
||||
if(scriptCode == USCRIPT_SIMPLIFIED_HAN || scriptCode == USCRIPT_TRADITIONAL_HAN) {
|
||||
scriptCode = USCRIPT_HAN;
|
||||
|
|
|
@ -1561,7 +1561,6 @@ RuleBasedCollator::internalGetShortDefinitionString(const char *locale,
|
|||
|
||||
// Append items in alphabetic order of their short definition letters.
|
||||
CharString result;
|
||||
char subtag[ULOC_KEYWORD_AND_VALUES_CAPACITY];
|
||||
|
||||
if(attributeHasBeenSetExplicitly(UCOL_ALTERNATE_HANDLING)) {
|
||||
appendAttribute(result, 'A', getAttribute(UCOL_ALTERNATE_HANDLING, errorCode), errorCode);
|
||||
|
@ -1587,24 +1586,25 @@ RuleBasedCollator::internalGetShortDefinitionString(const char *locale,
|
|||
ulocimp_getKeywordValue(resultLocale, "collation", sink, &errorCode);
|
||||
appendSubtag(result, 'K', collation.data(), collation.length(), errorCode);
|
||||
}
|
||||
length = uloc_getLanguage(resultLocale, subtag, UPRV_LENGTHOF(subtag), &errorCode);
|
||||
if (length == 0) {
|
||||
CharString language;
|
||||
CharString script;
|
||||
CharString region;
|
||||
CharString variant;
|
||||
ulocimp_getSubtags(resultLocale, &language, &script, ®ion, &variant, nullptr, errorCode);
|
||||
if (language.isEmpty()) {
|
||||
appendSubtag(result, 'L', "root", 4, errorCode);
|
||||
} else {
|
||||
appendSubtag(result, 'L', subtag, length, errorCode);
|
||||
appendSubtag(result, 'L', language.data(), language.length(), errorCode);
|
||||
}
|
||||
if(attributeHasBeenSetExplicitly(UCOL_NORMALIZATION_MODE)) {
|
||||
appendAttribute(result, 'N', getAttribute(UCOL_NORMALIZATION_MODE, errorCode), errorCode);
|
||||
}
|
||||
length = uloc_getCountry(resultLocale, subtag, UPRV_LENGTHOF(subtag), &errorCode);
|
||||
appendSubtag(result, 'R', subtag, length, errorCode);
|
||||
appendSubtag(result, 'R', region.data(), region.length(), errorCode);
|
||||
if(attributeHasBeenSetExplicitly(UCOL_STRENGTH)) {
|
||||
appendAttribute(result, 'S', getAttribute(UCOL_STRENGTH, errorCode), errorCode);
|
||||
}
|
||||
length = uloc_getVariant(resultLocale, subtag, UPRV_LENGTHOF(subtag), &errorCode);
|
||||
appendSubtag(result, 'V', subtag, length, errorCode);
|
||||
length = uloc_getScript(resultLocale, subtag, UPRV_LENGTHOF(subtag), &errorCode);
|
||||
appendSubtag(result, 'Z', subtag, length, errorCode);
|
||||
appendSubtag(result, 'V', variant.data(), variant.length(), errorCode);
|
||||
appendSubtag(result, 'Z', script.data(), script.length(), errorCode);
|
||||
|
||||
if(U_FAILURE(errorCode)) { return 0; }
|
||||
return result.extract(buffer, capacity, errorCode);
|
||||
|
|
|
@ -299,7 +299,7 @@ private:
|
|||
TextTrieMap fGNamesTrie;
|
||||
UBool fGNamesTrieFullyLoaded;
|
||||
|
||||
char fTargetRegion[ULOC_COUNTRY_CAPACITY];
|
||||
CharString fTargetRegion;
|
||||
|
||||
void initialize(const Locale& locale, UErrorCode& status);
|
||||
void cleanup();
|
||||
|
@ -339,7 +339,8 @@ TZGNCore::TZGNCore(const Locale& locale, UErrorCode& status)
|
|||
fLocaleDisplayNames(nullptr),
|
||||
fStringPool(status),
|
||||
fGNamesTrie(true, deleteGNameInfo),
|
||||
fGNamesTrieFullyLoaded(false) {
|
||||
fGNamesTrieFullyLoaded(false),
|
||||
fTargetRegion() {
|
||||
initialize(locale, status);
|
||||
}
|
||||
|
||||
|
@ -415,17 +416,13 @@ TZGNCore::initialize(const Locale& locale, UErrorCode& status) {
|
|||
ulocimp_addLikelySubtags(fLocale.getName(), sink, &status);
|
||||
}
|
||||
|
||||
regionLen = uloc_getCountry(loc.data(), fTargetRegion, sizeof(fTargetRegion), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
fTargetRegion[regionLen] = 0;
|
||||
} else {
|
||||
ulocimp_getSubtags(loc.data(), nullptr, nullptr, &fTargetRegion, nullptr, nullptr, status);
|
||||
if (U_FAILURE(status)) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
} else if (regionLen < (int32_t)sizeof(fTargetRegion)) {
|
||||
uprv_strcpy(fTargetRegion, region);
|
||||
} else {
|
||||
fTargetRegion[0] = 0;
|
||||
fTargetRegion.append(region, regionLen, status);
|
||||
}
|
||||
|
||||
// preload generic names for the default zone
|
||||
|
@ -704,7 +701,7 @@ TZGNCore::formatGenericNonLocationName(const TimeZone& tz, UTimeZoneGenericNameT
|
|||
// golden zone at the given date.
|
||||
char16_t idBuf[32];
|
||||
UnicodeString goldenID(idBuf, 0, UPRV_LENGTHOF(idBuf));
|
||||
fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion, goldenID);
|
||||
fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion.data(), goldenID);
|
||||
if (!goldenID.isEmpty() && goldenID != tzID) {
|
||||
TimeZone *goldenZone = TimeZone::createTimeZone(goldenID);
|
||||
int32_t raw1, sav1;
|
||||
|
@ -866,7 +863,7 @@ TZGNCore::loadStrings(const UnicodeString& tzCanonicalID) {
|
|||
// if this time zone is not the golden zone of the meta zone,
|
||||
// partial location name (such as "PT (Los Angeles)") might be
|
||||
// available.
|
||||
fTimeZoneNames->getReferenceZoneID(*mzID, fTargetRegion, goldenID);
|
||||
fTimeZoneNames->getReferenceZoneID(*mzID, fTargetRegion.data(), goldenID);
|
||||
if (tzCanonicalID != goldenID) {
|
||||
for (int32_t i = 0; genNonLocTypes[i] != UTZNM_UNKNOWN; i++) {
|
||||
fTimeZoneNames->getMetaZoneDisplayName(*mzID, genNonLocTypes[i], mzGenName);
|
||||
|
@ -914,7 +911,7 @@ TZGNCore::findBestMatch(const UnicodeString& text, int32_t start, uint32_t types
|
|||
if (!tznamesMatches->getTimeZoneIDAt(i, bestMatchTzID)) {
|
||||
// name for a meta zone
|
||||
if (tznamesMatches->getMetaZoneIDAt(i, mzID)) {
|
||||
fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion, bestMatchTzID);
|
||||
fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion.data(), bestMatchTzID);
|
||||
}
|
||||
}
|
||||
UTimeZoneNameType nameType = tznamesMatches->getNameTypeAt(i);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/strenum.h"
|
||||
#include "unicode/stringpiece.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "unicode/timezone.h"
|
||||
#include "unicode/utf16.h"
|
||||
|
@ -1912,7 +1913,7 @@ U_CDECL_END
|
|||
|
||||
class TZDBNameSearchHandler : public TextTrieMapSearchResultHandler {
|
||||
public:
|
||||
TZDBNameSearchHandler(uint32_t types, const char* region);
|
||||
TZDBNameSearchHandler(uint32_t types, StringPiece region);
|
||||
virtual ~TZDBNameSearchHandler();
|
||||
|
||||
UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) override;
|
||||
|
@ -1922,10 +1923,10 @@ private:
|
|||
uint32_t fTypes;
|
||||
int32_t fMaxMatchLen;
|
||||
TimeZoneNames::MatchInfoCollection* fResults;
|
||||
const char* fRegion;
|
||||
StringPiece fRegion;
|
||||
};
|
||||
|
||||
TZDBNameSearchHandler::TZDBNameSearchHandler(uint32_t types, const char* region)
|
||||
TZDBNameSearchHandler::TZDBNameSearchHandler(uint32_t types, StringPiece region)
|
||||
: fTypes(types), fMaxMatchLen(0), fResults(nullptr), fRegion(region) {
|
||||
}
|
||||
|
||||
|
@ -1974,7 +1975,7 @@ TZDBNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *nod
|
|||
// as metazone China (China Standard Time).
|
||||
for (int32_t j = 0; j < ninfo->nRegions; j++) {
|
||||
const char *region = ninfo->parseRegions[j];
|
||||
if (uprv_strcmp(fRegion, region) == 0) {
|
||||
if (fRegion == region) {
|
||||
match = ninfo;
|
||||
matchRegion = true;
|
||||
break;
|
||||
|
@ -2153,7 +2154,7 @@ static void U_CALLCONV prepareFind(UErrorCode &status) {
|
|||
U_CDECL_END
|
||||
|
||||
TZDBTimeZoneNames::TZDBTimeZoneNames(const Locale& locale)
|
||||
: fLocale(locale) {
|
||||
: fLocale(locale), fRegion() {
|
||||
UBool useWorld = true;
|
||||
const char* region = fLocale.getCountry();
|
||||
int32_t regionLen = static_cast<int32_t>(uprv_strlen(region));
|
||||
|
@ -2164,16 +2165,20 @@ TZDBTimeZoneNames::TZDBTimeZoneNames(const Locale& locale)
|
|||
CharStringByteSink sink(&loc);
|
||||
ulocimp_addLikelySubtags(fLocale.getName(), sink, &status);
|
||||
}
|
||||
regionLen = uloc_getCountry(loc.data(), fRegion, sizeof(fRegion), &status);
|
||||
if (U_SUCCESS(status) && regionLen < (int32_t)sizeof(fRegion)) {
|
||||
ulocimp_getSubtags(loc.data(), nullptr, nullptr, &fRegion, nullptr, nullptr, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
useWorld = false;
|
||||
}
|
||||
} else if (regionLen < (int32_t)sizeof(fRegion)) {
|
||||
uprv_strcpy(fRegion, region);
|
||||
} else {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fRegion.append(region, regionLen, status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
useWorld = false;
|
||||
}
|
||||
if (useWorld) {
|
||||
uprv_strcpy(fRegion, "001");
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fRegion.append("001", status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2251,7 +2256,7 @@ TZDBTimeZoneNames::find(const UnicodeString& text, int32_t start, uint32_t types
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
TZDBNameSearchHandler handler(types, fRegion);
|
||||
TZDBNameSearchHandler handler(types, fRegion.toStringPiece());
|
||||
gTZDBNamesTrie->search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return nullptr;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "uhash.h"
|
||||
#include "uvector.h"
|
||||
#include "umutex.h"
|
||||
#include "charstr.h"
|
||||
|
||||
// Some zone display names involving supplementary characters can be over 50 chars, 100 UTF-16 code units, 200 UTF-8 bytes
|
||||
#define ZONE_NAME_U16_MAX 128
|
||||
|
@ -255,7 +256,7 @@ public:
|
|||
|
||||
private:
|
||||
Locale fLocale;
|
||||
char fRegion[ULOC_COUNTRY_CAPACITY];
|
||||
CharString fRegion;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
Loading…
Add table
Reference in a new issue