11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 31cb0ef41Sopenharmony_ci/* 41cb0ef41Sopenharmony_ci******************************************************************************* 51cb0ef41Sopenharmony_ci* 61cb0ef41Sopenharmony_ci* Copyright (C) 1997-2016, International Business Machines 71cb0ef41Sopenharmony_ci* Corporation and others. All Rights Reserved. 81cb0ef41Sopenharmony_ci* 91cb0ef41Sopenharmony_ci******************************************************************************* 101cb0ef41Sopenharmony_ci* file name: locdispnames.cpp 111cb0ef41Sopenharmony_ci* encoding: UTF-8 121cb0ef41Sopenharmony_ci* tab size: 8 (not used) 131cb0ef41Sopenharmony_ci* indentation:4 141cb0ef41Sopenharmony_ci* 151cb0ef41Sopenharmony_ci* created on: 2010feb25 161cb0ef41Sopenharmony_ci* created by: Markus W. Scherer 171cb0ef41Sopenharmony_ci* 181cb0ef41Sopenharmony_ci* Code for locale display names, separated out from other .cpp files 191cb0ef41Sopenharmony_ci* that then do not depend on resource bundle code and display name data. 201cb0ef41Sopenharmony_ci*/ 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#include "unicode/utypes.h" 231cb0ef41Sopenharmony_ci#include "unicode/brkiter.h" 241cb0ef41Sopenharmony_ci#include "unicode/locid.h" 251cb0ef41Sopenharmony_ci#include "unicode/uenum.h" 261cb0ef41Sopenharmony_ci#include "unicode/uloc.h" 271cb0ef41Sopenharmony_ci#include "unicode/ures.h" 281cb0ef41Sopenharmony_ci#include "unicode/ustring.h" 291cb0ef41Sopenharmony_ci#include "bytesinkutil.h" 301cb0ef41Sopenharmony_ci#include "charstr.h" 311cb0ef41Sopenharmony_ci#include "cmemory.h" 321cb0ef41Sopenharmony_ci#include "cstring.h" 331cb0ef41Sopenharmony_ci#include "putilimp.h" 341cb0ef41Sopenharmony_ci#include "ulocimp.h" 351cb0ef41Sopenharmony_ci#include "uresimp.h" 361cb0ef41Sopenharmony_ci#include "ureslocs.h" 371cb0ef41Sopenharmony_ci#include "ustr_imp.h" 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci// C++ API ----------------------------------------------------------------- *** 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciU_NAMESPACE_BEGIN 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ciUnicodeString& 441cb0ef41Sopenharmony_ciLocale::getDisplayLanguage(UnicodeString& dispLang) const 451cb0ef41Sopenharmony_ci{ 461cb0ef41Sopenharmony_ci return this->getDisplayLanguage(getDefault(), dispLang); 471cb0ef41Sopenharmony_ci} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci/*We cannot make any assumptions on the size of the output display strings 501cb0ef41Sopenharmony_ci* Yet, since we are calling through to a C API, we need to set limits on 511cb0ef41Sopenharmony_ci* buffer size. For all the following getDisplay functions we first attempt 521cb0ef41Sopenharmony_ci* to fill up a stack allocated buffer. If it is to small we heap allocated 531cb0ef41Sopenharmony_ci* the exact buffer we need copy it to the UnicodeString and delete it*/ 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ciUnicodeString& 561cb0ef41Sopenharmony_ciLocale::getDisplayLanguage(const Locale &displayLocale, 571cb0ef41Sopenharmony_ci UnicodeString &result) const { 581cb0ef41Sopenharmony_ci char16_t *buffer; 591cb0ef41Sopenharmony_ci UErrorCode errorCode=U_ZERO_ERROR; 601cb0ef41Sopenharmony_ci int32_t length; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); 631cb0ef41Sopenharmony_ci if(buffer==0) { 641cb0ef41Sopenharmony_ci result.truncate(0); 651cb0ef41Sopenharmony_ci return result; 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci length=uloc_getDisplayLanguage(fullName, displayLocale.fullName, 691cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 701cb0ef41Sopenharmony_ci &errorCode); 711cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci if(errorCode==U_BUFFER_OVERFLOW_ERROR) { 741cb0ef41Sopenharmony_ci buffer=result.getBuffer(length); 751cb0ef41Sopenharmony_ci if(buffer==0) { 761cb0ef41Sopenharmony_ci result.truncate(0); 771cb0ef41Sopenharmony_ci return result; 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci errorCode=U_ZERO_ERROR; 801cb0ef41Sopenharmony_ci length=uloc_getDisplayLanguage(fullName, displayLocale.fullName, 811cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 821cb0ef41Sopenharmony_ci &errorCode); 831cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci return result; 871cb0ef41Sopenharmony_ci} 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ciUnicodeString& 901cb0ef41Sopenharmony_ciLocale::getDisplayScript(UnicodeString& dispScript) const 911cb0ef41Sopenharmony_ci{ 921cb0ef41Sopenharmony_ci return this->getDisplayScript(getDefault(), dispScript); 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ciUnicodeString& 961cb0ef41Sopenharmony_ciLocale::getDisplayScript(const Locale &displayLocale, 971cb0ef41Sopenharmony_ci UnicodeString &result) const { 981cb0ef41Sopenharmony_ci char16_t *buffer; 991cb0ef41Sopenharmony_ci UErrorCode errorCode=U_ZERO_ERROR; 1001cb0ef41Sopenharmony_ci int32_t length; 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); 1031cb0ef41Sopenharmony_ci if(buffer==0) { 1041cb0ef41Sopenharmony_ci result.truncate(0); 1051cb0ef41Sopenharmony_ci return result; 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci length=uloc_getDisplayScript(fullName, displayLocale.fullName, 1091cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 1101cb0ef41Sopenharmony_ci &errorCode); 1111cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci if(errorCode==U_BUFFER_OVERFLOW_ERROR) { 1141cb0ef41Sopenharmony_ci buffer=result.getBuffer(length); 1151cb0ef41Sopenharmony_ci if(buffer==0) { 1161cb0ef41Sopenharmony_ci result.truncate(0); 1171cb0ef41Sopenharmony_ci return result; 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci errorCode=U_ZERO_ERROR; 1201cb0ef41Sopenharmony_ci length=uloc_getDisplayScript(fullName, displayLocale.fullName, 1211cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 1221cb0ef41Sopenharmony_ci &errorCode); 1231cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci return result; 1271cb0ef41Sopenharmony_ci} 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ciUnicodeString& 1301cb0ef41Sopenharmony_ciLocale::getDisplayCountry(UnicodeString& dispCntry) const 1311cb0ef41Sopenharmony_ci{ 1321cb0ef41Sopenharmony_ci return this->getDisplayCountry(getDefault(), dispCntry); 1331cb0ef41Sopenharmony_ci} 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ciUnicodeString& 1361cb0ef41Sopenharmony_ciLocale::getDisplayCountry(const Locale &displayLocale, 1371cb0ef41Sopenharmony_ci UnicodeString &result) const { 1381cb0ef41Sopenharmony_ci char16_t *buffer; 1391cb0ef41Sopenharmony_ci UErrorCode errorCode=U_ZERO_ERROR; 1401cb0ef41Sopenharmony_ci int32_t length; 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); 1431cb0ef41Sopenharmony_ci if(buffer==0) { 1441cb0ef41Sopenharmony_ci result.truncate(0); 1451cb0ef41Sopenharmony_ci return result; 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci length=uloc_getDisplayCountry(fullName, displayLocale.fullName, 1491cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 1501cb0ef41Sopenharmony_ci &errorCode); 1511cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci if(errorCode==U_BUFFER_OVERFLOW_ERROR) { 1541cb0ef41Sopenharmony_ci buffer=result.getBuffer(length); 1551cb0ef41Sopenharmony_ci if(buffer==0) { 1561cb0ef41Sopenharmony_ci result.truncate(0); 1571cb0ef41Sopenharmony_ci return result; 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci errorCode=U_ZERO_ERROR; 1601cb0ef41Sopenharmony_ci length=uloc_getDisplayCountry(fullName, displayLocale.fullName, 1611cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 1621cb0ef41Sopenharmony_ci &errorCode); 1631cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci return result; 1671cb0ef41Sopenharmony_ci} 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ciUnicodeString& 1701cb0ef41Sopenharmony_ciLocale::getDisplayVariant(UnicodeString& dispVar) const 1711cb0ef41Sopenharmony_ci{ 1721cb0ef41Sopenharmony_ci return this->getDisplayVariant(getDefault(), dispVar); 1731cb0ef41Sopenharmony_ci} 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ciUnicodeString& 1761cb0ef41Sopenharmony_ciLocale::getDisplayVariant(const Locale &displayLocale, 1771cb0ef41Sopenharmony_ci UnicodeString &result) const { 1781cb0ef41Sopenharmony_ci char16_t *buffer; 1791cb0ef41Sopenharmony_ci UErrorCode errorCode=U_ZERO_ERROR; 1801cb0ef41Sopenharmony_ci int32_t length; 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); 1831cb0ef41Sopenharmony_ci if(buffer==0) { 1841cb0ef41Sopenharmony_ci result.truncate(0); 1851cb0ef41Sopenharmony_ci return result; 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci length=uloc_getDisplayVariant(fullName, displayLocale.fullName, 1891cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 1901cb0ef41Sopenharmony_ci &errorCode); 1911cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci if(errorCode==U_BUFFER_OVERFLOW_ERROR) { 1941cb0ef41Sopenharmony_ci buffer=result.getBuffer(length); 1951cb0ef41Sopenharmony_ci if(buffer==0) { 1961cb0ef41Sopenharmony_ci result.truncate(0); 1971cb0ef41Sopenharmony_ci return result; 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci errorCode=U_ZERO_ERROR; 2001cb0ef41Sopenharmony_ci length=uloc_getDisplayVariant(fullName, displayLocale.fullName, 2011cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 2021cb0ef41Sopenharmony_ci &errorCode); 2031cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci return result; 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ciUnicodeString& 2101cb0ef41Sopenharmony_ciLocale::getDisplayName( UnicodeString& name ) const 2111cb0ef41Sopenharmony_ci{ 2121cb0ef41Sopenharmony_ci return this->getDisplayName(getDefault(), name); 2131cb0ef41Sopenharmony_ci} 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ciUnicodeString& 2161cb0ef41Sopenharmony_ciLocale::getDisplayName(const Locale &displayLocale, 2171cb0ef41Sopenharmony_ci UnicodeString &result) const { 2181cb0ef41Sopenharmony_ci char16_t *buffer; 2191cb0ef41Sopenharmony_ci UErrorCode errorCode=U_ZERO_ERROR; 2201cb0ef41Sopenharmony_ci int32_t length; 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); 2231cb0ef41Sopenharmony_ci if(buffer==0) { 2241cb0ef41Sopenharmony_ci result.truncate(0); 2251cb0ef41Sopenharmony_ci return result; 2261cb0ef41Sopenharmony_ci } 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci length=uloc_getDisplayName(fullName, displayLocale.fullName, 2291cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 2301cb0ef41Sopenharmony_ci &errorCode); 2311cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci if(errorCode==U_BUFFER_OVERFLOW_ERROR) { 2341cb0ef41Sopenharmony_ci buffer=result.getBuffer(length); 2351cb0ef41Sopenharmony_ci if(buffer==0) { 2361cb0ef41Sopenharmony_ci result.truncate(0); 2371cb0ef41Sopenharmony_ci return result; 2381cb0ef41Sopenharmony_ci } 2391cb0ef41Sopenharmony_ci errorCode=U_ZERO_ERROR; 2401cb0ef41Sopenharmony_ci length=uloc_getDisplayName(fullName, displayLocale.fullName, 2411cb0ef41Sopenharmony_ci buffer, result.getCapacity(), 2421cb0ef41Sopenharmony_ci &errorCode); 2431cb0ef41Sopenharmony_ci result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci return result; 2471cb0ef41Sopenharmony_ci} 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci#if ! UCONFIG_NO_BREAK_ITERATION 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci// ------------------------------------- 2521cb0ef41Sopenharmony_ci// Gets the objectLocale display name in the default locale language. 2531cb0ef41Sopenharmony_ciUnicodeString& U_EXPORT2 2541cb0ef41Sopenharmony_ciBreakIterator::getDisplayName(const Locale& objectLocale, 2551cb0ef41Sopenharmony_ci UnicodeString& name) 2561cb0ef41Sopenharmony_ci{ 2571cb0ef41Sopenharmony_ci return objectLocale.getDisplayName(name); 2581cb0ef41Sopenharmony_ci} 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci// ------------------------------------- 2611cb0ef41Sopenharmony_ci// Gets the objectLocale display name in the displayLocale language. 2621cb0ef41Sopenharmony_ciUnicodeString& U_EXPORT2 2631cb0ef41Sopenharmony_ciBreakIterator::getDisplayName(const Locale& objectLocale, 2641cb0ef41Sopenharmony_ci const Locale& displayLocale, 2651cb0ef41Sopenharmony_ci UnicodeString& name) 2661cb0ef41Sopenharmony_ci{ 2671cb0ef41Sopenharmony_ci return objectLocale.getDisplayName(displayLocale, name); 2681cb0ef41Sopenharmony_ci} 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci#endif 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ciU_NAMESPACE_END 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci// C API ------------------------------------------------------------------- *** 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ciU_NAMESPACE_USE 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci/* ### Constants **************************************************/ 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci/* These strings describe the resources we attempt to load from 2821cb0ef41Sopenharmony_ci the locale ResourceBundle data file.*/ 2831cb0ef41Sopenharmony_cistatic const char _kLanguages[] = "Languages"; 2841cb0ef41Sopenharmony_cistatic const char _kScripts[] = "Scripts"; 2851cb0ef41Sopenharmony_cistatic const char _kScriptsStandAlone[] = "Scripts%stand-alone"; 2861cb0ef41Sopenharmony_cistatic const char _kCountries[] = "Countries"; 2871cb0ef41Sopenharmony_cistatic const char _kVariants[] = "Variants"; 2881cb0ef41Sopenharmony_cistatic const char _kKeys[] = "Keys"; 2891cb0ef41Sopenharmony_cistatic const char _kTypes[] = "Types"; 2901cb0ef41Sopenharmony_ci//static const char _kRootName[] = "root"; 2911cb0ef41Sopenharmony_cistatic const char _kCurrency[] = "currency"; 2921cb0ef41Sopenharmony_cistatic const char _kCurrencies[] = "Currencies"; 2931cb0ef41Sopenharmony_cistatic const char _kLocaleDisplayPattern[] = "localeDisplayPattern"; 2941cb0ef41Sopenharmony_cistatic const char _kPattern[] = "pattern"; 2951cb0ef41Sopenharmony_cistatic const char _kSeparator[] = "separator"; 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ci/* ### Display name **************************************************/ 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_cistatic int32_t 3001cb0ef41Sopenharmony_ci_getStringOrCopyKey(const char *path, const char *locale, 3011cb0ef41Sopenharmony_ci const char *tableKey, 3021cb0ef41Sopenharmony_ci const char* subTableKey, 3031cb0ef41Sopenharmony_ci const char *itemKey, 3041cb0ef41Sopenharmony_ci const char *substitute, 3051cb0ef41Sopenharmony_ci char16_t *dest, int32_t destCapacity, 3061cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) { 3071cb0ef41Sopenharmony_ci const char16_t *s = nullptr; 3081cb0ef41Sopenharmony_ci int32_t length = 0; 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci if(itemKey==nullptr) { 3111cb0ef41Sopenharmony_ci /* top-level item: normal resource bundle access */ 3121cb0ef41Sopenharmony_ci icu::LocalUResourceBundlePointer rb(ures_open(path, locale, pErrorCode)); 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci if(U_SUCCESS(*pErrorCode)) { 3151cb0ef41Sopenharmony_ci s=ures_getStringByKey(rb.getAlias(), tableKey, &length, pErrorCode); 3161cb0ef41Sopenharmony_ci /* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */ 3171cb0ef41Sopenharmony_ci } 3181cb0ef41Sopenharmony_ci } else { 3191cb0ef41Sopenharmony_ci bool isLanguageCode = (uprv_strncmp(tableKey, _kLanguages, 9) == 0); 3201cb0ef41Sopenharmony_ci /* Language code should not be a number. If it is, set the error code. */ 3211cb0ef41Sopenharmony_ci if (isLanguageCode && uprv_strtol(itemKey, nullptr, 10)) { 3221cb0ef41Sopenharmony_ci *pErrorCode = U_MISSING_RESOURCE_ERROR; 3231cb0ef41Sopenharmony_ci } else { 3241cb0ef41Sopenharmony_ci /* second-level item, use special fallback */ 3251cb0ef41Sopenharmony_ci s=uloc_getTableStringWithFallback(path, locale, 3261cb0ef41Sopenharmony_ci tableKey, 3271cb0ef41Sopenharmony_ci subTableKey, 3281cb0ef41Sopenharmony_ci itemKey, 3291cb0ef41Sopenharmony_ci &length, 3301cb0ef41Sopenharmony_ci pErrorCode); 3311cb0ef41Sopenharmony_ci if (U_FAILURE(*pErrorCode) && isLanguageCode && itemKey != nullptr) { 3321cb0ef41Sopenharmony_ci // convert itemKey locale code to canonical form and try again, ICU-20870 3331cb0ef41Sopenharmony_ci *pErrorCode = U_ZERO_ERROR; 3341cb0ef41Sopenharmony_ci Locale canonKey = Locale::createCanonical(itemKey); 3351cb0ef41Sopenharmony_ci s=uloc_getTableStringWithFallback(path, locale, 3361cb0ef41Sopenharmony_ci tableKey, 3371cb0ef41Sopenharmony_ci subTableKey, 3381cb0ef41Sopenharmony_ci canonKey.getName(), 3391cb0ef41Sopenharmony_ci &length, 3401cb0ef41Sopenharmony_ci pErrorCode); 3411cb0ef41Sopenharmony_ci } 3421cb0ef41Sopenharmony_ci } 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci if(U_SUCCESS(*pErrorCode)) { 3461cb0ef41Sopenharmony_ci int32_t copyLength=uprv_min(length, destCapacity); 3471cb0ef41Sopenharmony_ci if(copyLength>0 && s != nullptr) { 3481cb0ef41Sopenharmony_ci u_memcpy(dest, s, copyLength); 3491cb0ef41Sopenharmony_ci } 3501cb0ef41Sopenharmony_ci } else { 3511cb0ef41Sopenharmony_ci /* no string from a resource bundle: convert the substitute */ 3521cb0ef41Sopenharmony_ci length=(int32_t)uprv_strlen(substitute); 3531cb0ef41Sopenharmony_ci u_charsToUChars(substitute, dest, uprv_min(length, destCapacity)); 3541cb0ef41Sopenharmony_ci *pErrorCode=U_USING_DEFAULT_WARNING; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci return u_terminateUChars(dest, destCapacity, length, pErrorCode); 3581cb0ef41Sopenharmony_ci} 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_citypedef int32_t U_CALLCONV UDisplayNameGetter(const char *, char *, int32_t, UErrorCode *); 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_cistatic int32_t 3631cb0ef41Sopenharmony_ci_getDisplayNameForComponent(const char *locale, 3641cb0ef41Sopenharmony_ci const char *displayLocale, 3651cb0ef41Sopenharmony_ci char16_t *dest, int32_t destCapacity, 3661cb0ef41Sopenharmony_ci UDisplayNameGetter *getter, 3671cb0ef41Sopenharmony_ci const char *tag, 3681cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) { 3691cb0ef41Sopenharmony_ci char localeBuffer[ULOC_FULLNAME_CAPACITY*4]; 3701cb0ef41Sopenharmony_ci int32_t length; 3711cb0ef41Sopenharmony_ci UErrorCode localStatus; 3721cb0ef41Sopenharmony_ci const char* root = nullptr; 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci /* argument checking */ 3751cb0ef41Sopenharmony_ci if(pErrorCode==nullptr || U_FAILURE(*pErrorCode)) { 3761cb0ef41Sopenharmony_ci return 0; 3771cb0ef41Sopenharmony_ci } 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) { 3801cb0ef41Sopenharmony_ci *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 3811cb0ef41Sopenharmony_ci return 0; 3821cb0ef41Sopenharmony_ci } 3831cb0ef41Sopenharmony_ci 3841cb0ef41Sopenharmony_ci localStatus = U_ZERO_ERROR; 3851cb0ef41Sopenharmony_ci length=(*getter)(locale, localeBuffer, sizeof(localeBuffer), &localStatus); 3861cb0ef41Sopenharmony_ci if(U_FAILURE(localStatus) || localStatus==U_STRING_NOT_TERMINATED_WARNING) { 3871cb0ef41Sopenharmony_ci *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 3881cb0ef41Sopenharmony_ci return 0; 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci if(length==0) { 3911cb0ef41Sopenharmony_ci // For the display name, we treat this as unknown language (ICU-20273). 3921cb0ef41Sopenharmony_ci if (getter == uloc_getLanguage) { 3931cb0ef41Sopenharmony_ci uprv_strcpy(localeBuffer, "und"); 3941cb0ef41Sopenharmony_ci } else { 3951cb0ef41Sopenharmony_ci return u_terminateUChars(dest, destCapacity, 0, pErrorCode); 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci } 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci root = tag == _kCountries ? U_ICUDATA_REGION : U_ICUDATA_LANG; 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ci return _getStringOrCopyKey(root, displayLocale, 4021cb0ef41Sopenharmony_ci tag, nullptr, localeBuffer, 4031cb0ef41Sopenharmony_ci localeBuffer, 4041cb0ef41Sopenharmony_ci dest, destCapacity, 4051cb0ef41Sopenharmony_ci pErrorCode); 4061cb0ef41Sopenharmony_ci} 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 4091cb0ef41Sopenharmony_ciuloc_getDisplayLanguage(const char *locale, 4101cb0ef41Sopenharmony_ci const char *displayLocale, 4111cb0ef41Sopenharmony_ci char16_t *dest, int32_t destCapacity, 4121cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) { 4131cb0ef41Sopenharmony_ci return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, 4141cb0ef41Sopenharmony_ci uloc_getLanguage, _kLanguages, pErrorCode); 4151cb0ef41Sopenharmony_ci} 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 4181cb0ef41Sopenharmony_ciuloc_getDisplayScript(const char* locale, 4191cb0ef41Sopenharmony_ci const char* displayLocale, 4201cb0ef41Sopenharmony_ci char16_t *dest, int32_t destCapacity, 4211cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) 4221cb0ef41Sopenharmony_ci{ 4231cb0ef41Sopenharmony_ci UErrorCode err = U_ZERO_ERROR; 4241cb0ef41Sopenharmony_ci int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, 4251cb0ef41Sopenharmony_ci uloc_getScript, _kScriptsStandAlone, &err); 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ci if (destCapacity == 0 && err == U_BUFFER_OVERFLOW_ERROR) { 4281cb0ef41Sopenharmony_ci // For preflight, return the max of the value and the fallback. 4291cb0ef41Sopenharmony_ci int32_t fallback_res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, 4301cb0ef41Sopenharmony_ci uloc_getScript, _kScripts, pErrorCode); 4311cb0ef41Sopenharmony_ci return (fallback_res > res) ? fallback_res : res; 4321cb0ef41Sopenharmony_ci } 4331cb0ef41Sopenharmony_ci if ( err == U_USING_DEFAULT_WARNING ) { 4341cb0ef41Sopenharmony_ci return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, 4351cb0ef41Sopenharmony_ci uloc_getScript, _kScripts, pErrorCode); 4361cb0ef41Sopenharmony_ci } else { 4371cb0ef41Sopenharmony_ci *pErrorCode = err; 4381cb0ef41Sopenharmony_ci return res; 4391cb0ef41Sopenharmony_ci } 4401cb0ef41Sopenharmony_ci} 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_cistatic int32_t 4431cb0ef41Sopenharmony_ciuloc_getDisplayScriptInContext(const char* locale, 4441cb0ef41Sopenharmony_ci const char* displayLocale, 4451cb0ef41Sopenharmony_ci char16_t *dest, int32_t destCapacity, 4461cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) 4471cb0ef41Sopenharmony_ci{ 4481cb0ef41Sopenharmony_ci return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, 4491cb0ef41Sopenharmony_ci uloc_getScript, _kScripts, pErrorCode); 4501cb0ef41Sopenharmony_ci} 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 4531cb0ef41Sopenharmony_ciuloc_getDisplayCountry(const char *locale, 4541cb0ef41Sopenharmony_ci const char *displayLocale, 4551cb0ef41Sopenharmony_ci char16_t *dest, int32_t destCapacity, 4561cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) { 4571cb0ef41Sopenharmony_ci return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, 4581cb0ef41Sopenharmony_ci uloc_getCountry, _kCountries, pErrorCode); 4591cb0ef41Sopenharmony_ci} 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ci/* 4621cb0ef41Sopenharmony_ci * TODO separate variant1_variant2_variant3... 4631cb0ef41Sopenharmony_ci * by getting each tag's display string and concatenating them with ", " 4641cb0ef41Sopenharmony_ci * in between - similar to uloc_getDisplayName() 4651cb0ef41Sopenharmony_ci */ 4661cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 4671cb0ef41Sopenharmony_ciuloc_getDisplayVariant(const char *locale, 4681cb0ef41Sopenharmony_ci const char *displayLocale, 4691cb0ef41Sopenharmony_ci char16_t *dest, int32_t destCapacity, 4701cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) { 4711cb0ef41Sopenharmony_ci return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, 4721cb0ef41Sopenharmony_ci uloc_getVariant, _kVariants, pErrorCode); 4731cb0ef41Sopenharmony_ci} 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci/* Instead of having a separate pass for 'special' patterns, reintegrate the two 4761cb0ef41Sopenharmony_ci * so we don't get bitten by preflight bugs again. We can be reasonably efficient 4771cb0ef41Sopenharmony_ci * without two separate code paths, this code isn't that performance-critical. 4781cb0ef41Sopenharmony_ci * 4791cb0ef41Sopenharmony_ci * This code is general enough to deal with patterns that have a prefix or swap the 4801cb0ef41Sopenharmony_ci * language and remainder components, since we gave developers enough rope to do such 4811cb0ef41Sopenharmony_ci * things if they futz with the pattern data. But since we don't give them a way to 4821cb0ef41Sopenharmony_ci * specify a pattern for arbitrary combinations of components, there's not much use in 4831cb0ef41Sopenharmony_ci * that. I don't think our data includes such patterns, the only variable I know if is 4841cb0ef41Sopenharmony_ci * whether there is a space before the open paren, or not. Oh, and zh uses different 4851cb0ef41Sopenharmony_ci * chars than the standard open/close paren (which ja and ko use, btw). 4861cb0ef41Sopenharmony_ci */ 4871cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 4881cb0ef41Sopenharmony_ciuloc_getDisplayName(const char *locale, 4891cb0ef41Sopenharmony_ci const char *displayLocale, 4901cb0ef41Sopenharmony_ci char16_t *dest, int32_t destCapacity, 4911cb0ef41Sopenharmony_ci UErrorCode *pErrorCode) 4921cb0ef41Sopenharmony_ci{ 4931cb0ef41Sopenharmony_ci static const char16_t defaultSeparator[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */ 4941cb0ef41Sopenharmony_ci static const char16_t sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */ 4951cb0ef41Sopenharmony_ci static const char16_t sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */ 4961cb0ef41Sopenharmony_ci static const int32_t subLen = 3; 4971cb0ef41Sopenharmony_ci static const char16_t defaultPattern[10] = { 4981cb0ef41Sopenharmony_ci 0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000 4991cb0ef41Sopenharmony_ci }; /* {0} ({1}) */ 5001cb0ef41Sopenharmony_ci static const int32_t defaultPatLen = 9; 5011cb0ef41Sopenharmony_ci static const int32_t defaultSub0Pos = 0; 5021cb0ef41Sopenharmony_ci static const int32_t defaultSub1Pos = 5; 5031cb0ef41Sopenharmony_ci 5041cb0ef41Sopenharmony_ci int32_t length; /* of formatted result */ 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci const char16_t *separator; 5071cb0ef41Sopenharmony_ci int32_t sepLen = 0; 5081cb0ef41Sopenharmony_ci const char16_t *pattern; 5091cb0ef41Sopenharmony_ci int32_t patLen = 0; 5101cb0ef41Sopenharmony_ci int32_t sub0Pos, sub1Pos; 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci char16_t formatOpenParen = 0x0028; // ( 5131cb0ef41Sopenharmony_ci char16_t formatReplaceOpenParen = 0x005B; // [ 5141cb0ef41Sopenharmony_ci char16_t formatCloseParen = 0x0029; // ) 5151cb0ef41Sopenharmony_ci char16_t formatReplaceCloseParen = 0x005D; // ] 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci UBool haveLang = true; /* assume true, set false if we find we don't have 5181cb0ef41Sopenharmony_ci a lang component in the locale */ 5191cb0ef41Sopenharmony_ci UBool haveRest = true; /* assume true, set false if we find we don't have 5201cb0ef41Sopenharmony_ci any other component in the locale */ 5211cb0ef41Sopenharmony_ci UBool retry = false; /* set true if we need to retry, see below */ 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_ci int32_t langi = 0; /* index of the language substitution (0 or 1), virtually always 0 */ 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_ci if(pErrorCode==nullptr || U_FAILURE(*pErrorCode)) { 5261cb0ef41Sopenharmony_ci return 0; 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ci if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) { 5301cb0ef41Sopenharmony_ci *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 5311cb0ef41Sopenharmony_ci return 0; 5321cb0ef41Sopenharmony_ci } 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci { 5351cb0ef41Sopenharmony_ci UErrorCode status = U_ZERO_ERROR; 5361cb0ef41Sopenharmony_ci 5371cb0ef41Sopenharmony_ci icu::LocalUResourceBundlePointer locbundle( 5381cb0ef41Sopenharmony_ci ures_open(U_ICUDATA_LANG, displayLocale, &status)); 5391cb0ef41Sopenharmony_ci icu::LocalUResourceBundlePointer dspbundle( 5401cb0ef41Sopenharmony_ci ures_getByKeyWithFallback(locbundle.getAlias(), _kLocaleDisplayPattern, nullptr, &status)); 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ci separator=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kSeparator, &sepLen, &status); 5431cb0ef41Sopenharmony_ci pattern=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kPattern, &patLen, &status); 5441cb0ef41Sopenharmony_ci } 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci /* If we couldn't find any data, then use the defaults */ 5471cb0ef41Sopenharmony_ci if(sepLen == 0) { 5481cb0ef41Sopenharmony_ci separator = defaultSeparator; 5491cb0ef41Sopenharmony_ci } 5501cb0ef41Sopenharmony_ci /* #10244: Even though separator is now a pattern, it is awkward to handle it as such 5511cb0ef41Sopenharmony_ci * here since we are trying to build the display string in place in the dest buffer, 5521cb0ef41Sopenharmony_ci * and to handle it as a pattern would entail having separate storage for the 5531cb0ef41Sopenharmony_ci * substrings that need to be combined (the first of which may be the result of 5541cb0ef41Sopenharmony_ci * previous such combinations). So for now we continue to treat the portion between 5551cb0ef41Sopenharmony_ci * {0} and {1} as a string to be appended when joining substrings, ignoring anything 5561cb0ef41Sopenharmony_ci * that is before {0} or after {1} (no existing separator pattern has any such thing). 5571cb0ef41Sopenharmony_ci * This is similar to how pattern is handled below. 5581cb0ef41Sopenharmony_ci */ 5591cb0ef41Sopenharmony_ci { 5601cb0ef41Sopenharmony_ci char16_t *p0=u_strstr(separator, sub0); 5611cb0ef41Sopenharmony_ci char16_t *p1=u_strstr(separator, sub1); 5621cb0ef41Sopenharmony_ci if (p0==nullptr || p1==nullptr || p1<p0) { 5631cb0ef41Sopenharmony_ci *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 5641cb0ef41Sopenharmony_ci return 0; 5651cb0ef41Sopenharmony_ci } 5661cb0ef41Sopenharmony_ci separator = (const char16_t *)p0 + subLen; 5671cb0ef41Sopenharmony_ci sepLen = static_cast<int32_t>(p1 - separator); 5681cb0ef41Sopenharmony_ci } 5691cb0ef41Sopenharmony_ci 5701cb0ef41Sopenharmony_ci if(patLen==0 || (patLen==defaultPatLen && !u_strncmp(pattern, defaultPattern, patLen))) { 5711cb0ef41Sopenharmony_ci pattern=defaultPattern; 5721cb0ef41Sopenharmony_ci patLen=defaultPatLen; 5731cb0ef41Sopenharmony_ci sub0Pos=defaultSub0Pos; 5741cb0ef41Sopenharmony_ci sub1Pos=defaultSub1Pos; 5751cb0ef41Sopenharmony_ci // use default formatOpenParen etc. set above 5761cb0ef41Sopenharmony_ci } else { /* non-default pattern */ 5771cb0ef41Sopenharmony_ci char16_t *p0=u_strstr(pattern, sub0); 5781cb0ef41Sopenharmony_ci char16_t *p1=u_strstr(pattern, sub1); 5791cb0ef41Sopenharmony_ci if (p0==nullptr || p1==nullptr) { 5801cb0ef41Sopenharmony_ci *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 5811cb0ef41Sopenharmony_ci return 0; 5821cb0ef41Sopenharmony_ci } 5831cb0ef41Sopenharmony_ci sub0Pos = static_cast<int32_t>(p0-pattern); 5841cb0ef41Sopenharmony_ci sub1Pos = static_cast<int32_t>(p1-pattern); 5851cb0ef41Sopenharmony_ci if (sub1Pos < sub0Pos) { /* a very odd pattern */ 5861cb0ef41Sopenharmony_ci int32_t t=sub0Pos; sub0Pos=sub1Pos; sub1Pos=t; 5871cb0ef41Sopenharmony_ci langi=1; 5881cb0ef41Sopenharmony_ci } 5891cb0ef41Sopenharmony_ci if (u_strchr(pattern, 0xFF08) != nullptr) { 5901cb0ef41Sopenharmony_ci formatOpenParen = 0xFF08; // fullwidth ( 5911cb0ef41Sopenharmony_ci formatReplaceOpenParen = 0xFF3B; // fullwidth [ 5921cb0ef41Sopenharmony_ci formatCloseParen = 0xFF09; // fullwidth ) 5931cb0ef41Sopenharmony_ci formatReplaceCloseParen = 0xFF3D; // fullwidth ] 5941cb0ef41Sopenharmony_ci } 5951cb0ef41Sopenharmony_ci } 5961cb0ef41Sopenharmony_ci 5971cb0ef41Sopenharmony_ci /* We loop here because there is one case in which after the first pass we could need to 5981cb0ef41Sopenharmony_ci * reextract the data. If there's initial padding before the first element, we put in 5991cb0ef41Sopenharmony_ci * the padding and then write that element. If it turns out there's no second element, 6001cb0ef41Sopenharmony_ci * we didn't need the padding. If we do need the data (no preflight), and the first element 6011cb0ef41Sopenharmony_ci * would have fit but for the padding, we need to reextract. In this case (only) we 6021cb0ef41Sopenharmony_ci * adjust the parameters so padding is not added, and repeat. 6031cb0ef41Sopenharmony_ci */ 6041cb0ef41Sopenharmony_ci do { 6051cb0ef41Sopenharmony_ci char16_t* p=dest; 6061cb0ef41Sopenharmony_ci int32_t patPos=0; /* position in the pattern, used for non-substitution portions */ 6071cb0ef41Sopenharmony_ci int32_t langLen=0; /* length of language substitution */ 6081cb0ef41Sopenharmony_ci int32_t langPos=0; /* position in output of language substitution */ 6091cb0ef41Sopenharmony_ci int32_t restLen=0; /* length of 'everything else' substitution */ 6101cb0ef41Sopenharmony_ci int32_t restPos=0; /* position in output of 'everything else' substitution */ 6111cb0ef41Sopenharmony_ci icu::LocalUEnumerationPointer kenum; /* keyword enumeration */ 6121cb0ef41Sopenharmony_ci 6131cb0ef41Sopenharmony_ci /* prefix of pattern, extremely likely to be empty */ 6141cb0ef41Sopenharmony_ci if(sub0Pos) { 6151cb0ef41Sopenharmony_ci if(destCapacity >= sub0Pos) { 6161cb0ef41Sopenharmony_ci while (patPos < sub0Pos) { 6171cb0ef41Sopenharmony_ci *p++ = pattern[patPos++]; 6181cb0ef41Sopenharmony_ci } 6191cb0ef41Sopenharmony_ci } else { 6201cb0ef41Sopenharmony_ci patPos=sub0Pos; 6211cb0ef41Sopenharmony_ci } 6221cb0ef41Sopenharmony_ci length=sub0Pos; 6231cb0ef41Sopenharmony_ci } else { 6241cb0ef41Sopenharmony_ci length=0; 6251cb0ef41Sopenharmony_ci } 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ci for(int32_t subi=0,resti=0;subi<2;) { /* iterate through patterns 0 and 1*/ 6281cb0ef41Sopenharmony_ci UBool subdone = false; /* set true when ready to move to next substitution */ 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci /* prep p and cap for calls to get display components, pin cap to 0 since 6311cb0ef41Sopenharmony_ci they complain if cap is negative */ 6321cb0ef41Sopenharmony_ci int32_t cap=destCapacity-length; 6331cb0ef41Sopenharmony_ci if (cap <= 0) { 6341cb0ef41Sopenharmony_ci cap=0; 6351cb0ef41Sopenharmony_ci } else { 6361cb0ef41Sopenharmony_ci p=dest+length; 6371cb0ef41Sopenharmony_ci } 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ci if (subi == langi) { /* {0}*/ 6401cb0ef41Sopenharmony_ci if(haveLang) { 6411cb0ef41Sopenharmony_ci langPos=length; 6421cb0ef41Sopenharmony_ci langLen=uloc_getDisplayLanguage(locale, displayLocale, p, cap, pErrorCode); 6431cb0ef41Sopenharmony_ci length+=langLen; 6441cb0ef41Sopenharmony_ci haveLang=langLen>0; 6451cb0ef41Sopenharmony_ci } 6461cb0ef41Sopenharmony_ci subdone=true; 6471cb0ef41Sopenharmony_ci } else { /* {1} */ 6481cb0ef41Sopenharmony_ci if(!haveRest) { 6491cb0ef41Sopenharmony_ci subdone=true; 6501cb0ef41Sopenharmony_ci } else { 6511cb0ef41Sopenharmony_ci int32_t len; /* length of component (plus other stuff) we just fetched */ 6521cb0ef41Sopenharmony_ci switch(resti++) { 6531cb0ef41Sopenharmony_ci case 0: 6541cb0ef41Sopenharmony_ci restPos=length; 6551cb0ef41Sopenharmony_ci len=uloc_getDisplayScriptInContext(locale, displayLocale, p, cap, pErrorCode); 6561cb0ef41Sopenharmony_ci break; 6571cb0ef41Sopenharmony_ci case 1: 6581cb0ef41Sopenharmony_ci len=uloc_getDisplayCountry(locale, displayLocale, p, cap, pErrorCode); 6591cb0ef41Sopenharmony_ci break; 6601cb0ef41Sopenharmony_ci case 2: 6611cb0ef41Sopenharmony_ci len=uloc_getDisplayVariant(locale, displayLocale, p, cap, pErrorCode); 6621cb0ef41Sopenharmony_ci break; 6631cb0ef41Sopenharmony_ci case 3: 6641cb0ef41Sopenharmony_ci kenum.adoptInstead(uloc_openKeywords(locale, pErrorCode)); 6651cb0ef41Sopenharmony_ci U_FALLTHROUGH; 6661cb0ef41Sopenharmony_ci default: { 6671cb0ef41Sopenharmony_ci const char* kw=uenum_next(kenum.getAlias(), &len, pErrorCode); 6681cb0ef41Sopenharmony_ci if (kw == nullptr) { 6691cb0ef41Sopenharmony_ci len=0; /* mark that we didn't add a component */ 6701cb0ef41Sopenharmony_ci subdone=true; 6711cb0ef41Sopenharmony_ci } else { 6721cb0ef41Sopenharmony_ci /* incorporating this behavior into the loop made it even more complex, 6731cb0ef41Sopenharmony_ci so just special case it here */ 6741cb0ef41Sopenharmony_ci len = uloc_getDisplayKeyword(kw, displayLocale, p, cap, pErrorCode); 6751cb0ef41Sopenharmony_ci if(len) { 6761cb0ef41Sopenharmony_ci if(len < cap) { 6771cb0ef41Sopenharmony_ci p[len]=0x3d; /* '=', assume we'll need it */ 6781cb0ef41Sopenharmony_ci } 6791cb0ef41Sopenharmony_ci len+=1; 6801cb0ef41Sopenharmony_ci 6811cb0ef41Sopenharmony_ci /* adjust for call to get keyword */ 6821cb0ef41Sopenharmony_ci cap-=len; 6831cb0ef41Sopenharmony_ci if(cap <= 0) { 6841cb0ef41Sopenharmony_ci cap=0; 6851cb0ef41Sopenharmony_ci } else { 6861cb0ef41Sopenharmony_ci p+=len; 6871cb0ef41Sopenharmony_ci } 6881cb0ef41Sopenharmony_ci } 6891cb0ef41Sopenharmony_ci /* reset for call below */ 6901cb0ef41Sopenharmony_ci if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) { 6911cb0ef41Sopenharmony_ci *pErrorCode=U_ZERO_ERROR; 6921cb0ef41Sopenharmony_ci } 6931cb0ef41Sopenharmony_ci int32_t vlen = uloc_getDisplayKeywordValue(locale, kw, displayLocale, 6941cb0ef41Sopenharmony_ci p, cap, pErrorCode); 6951cb0ef41Sopenharmony_ci if(len) { 6961cb0ef41Sopenharmony_ci if(vlen==0) { 6971cb0ef41Sopenharmony_ci --len; /* remove unneeded '=' */ 6981cb0ef41Sopenharmony_ci } 6991cb0ef41Sopenharmony_ci /* restore cap and p to what they were at start */ 7001cb0ef41Sopenharmony_ci cap=destCapacity-length; 7011cb0ef41Sopenharmony_ci if(cap <= 0) { 7021cb0ef41Sopenharmony_ci cap=0; 7031cb0ef41Sopenharmony_ci } else { 7041cb0ef41Sopenharmony_ci p=dest+length; 7051cb0ef41Sopenharmony_ci } 7061cb0ef41Sopenharmony_ci } 7071cb0ef41Sopenharmony_ci len+=vlen; /* total we added for key + '=' + value */ 7081cb0ef41Sopenharmony_ci } 7091cb0ef41Sopenharmony_ci } break; 7101cb0ef41Sopenharmony_ci } /* end switch */ 7111cb0ef41Sopenharmony_ci 7121cb0ef41Sopenharmony_ci if (len>0) { 7131cb0ef41Sopenharmony_ci /* we added a component, so add separator and write it if there's room. */ 7141cb0ef41Sopenharmony_ci if(len+sepLen<=cap) { 7151cb0ef41Sopenharmony_ci const char16_t * plimit = p + len; 7161cb0ef41Sopenharmony_ci for (; p < plimit; p++) { 7171cb0ef41Sopenharmony_ci if (*p == formatOpenParen) { 7181cb0ef41Sopenharmony_ci *p = formatReplaceOpenParen; 7191cb0ef41Sopenharmony_ci } else if (*p == formatCloseParen) { 7201cb0ef41Sopenharmony_ci *p = formatReplaceCloseParen; 7211cb0ef41Sopenharmony_ci } 7221cb0ef41Sopenharmony_ci } 7231cb0ef41Sopenharmony_ci for(int32_t i=0;i<sepLen;++i) { 7241cb0ef41Sopenharmony_ci *p++=separator[i]; 7251cb0ef41Sopenharmony_ci } 7261cb0ef41Sopenharmony_ci } 7271cb0ef41Sopenharmony_ci length+=len+sepLen; 7281cb0ef41Sopenharmony_ci } else if(subdone) { 7291cb0ef41Sopenharmony_ci /* remove separator if we added it */ 7301cb0ef41Sopenharmony_ci if (length!=restPos) { 7311cb0ef41Sopenharmony_ci length-=sepLen; 7321cb0ef41Sopenharmony_ci } 7331cb0ef41Sopenharmony_ci restLen=length-restPos; 7341cb0ef41Sopenharmony_ci haveRest=restLen>0; 7351cb0ef41Sopenharmony_ci } 7361cb0ef41Sopenharmony_ci } 7371cb0ef41Sopenharmony_ci } 7381cb0ef41Sopenharmony_ci 7391cb0ef41Sopenharmony_ci if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) { 7401cb0ef41Sopenharmony_ci *pErrorCode=U_ZERO_ERROR; 7411cb0ef41Sopenharmony_ci } 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_ci if(subdone) { 7441cb0ef41Sopenharmony_ci if(haveLang && haveRest) { 7451cb0ef41Sopenharmony_ci /* append internal portion of pattern, the first time, 7461cb0ef41Sopenharmony_ci or last portion of pattern the second time */ 7471cb0ef41Sopenharmony_ci int32_t padLen; 7481cb0ef41Sopenharmony_ci patPos+=subLen; 7491cb0ef41Sopenharmony_ci padLen=(subi==0 ? sub1Pos : patLen)-patPos; 7501cb0ef41Sopenharmony_ci if(length+padLen <= destCapacity) { 7511cb0ef41Sopenharmony_ci p=dest+length; 7521cb0ef41Sopenharmony_ci for(int32_t i=0;i<padLen;++i) { 7531cb0ef41Sopenharmony_ci *p++=pattern[patPos++]; 7541cb0ef41Sopenharmony_ci } 7551cb0ef41Sopenharmony_ci } else { 7561cb0ef41Sopenharmony_ci patPos+=padLen; 7571cb0ef41Sopenharmony_ci } 7581cb0ef41Sopenharmony_ci length+=padLen; 7591cb0ef41Sopenharmony_ci } else if(subi==0) { 7601cb0ef41Sopenharmony_ci /* don't have first component, reset for second component */ 7611cb0ef41Sopenharmony_ci sub0Pos=0; 7621cb0ef41Sopenharmony_ci length=0; 7631cb0ef41Sopenharmony_ci } else if(length>0) { 7641cb0ef41Sopenharmony_ci /* true length is the length of just the component we got. */ 7651cb0ef41Sopenharmony_ci length=haveLang?langLen:restLen; 7661cb0ef41Sopenharmony_ci if(dest && sub0Pos!=0) { 7671cb0ef41Sopenharmony_ci if (sub0Pos+length<=destCapacity) { 7681cb0ef41Sopenharmony_ci /* first component not at start of result, 7691cb0ef41Sopenharmony_ci but we have full component in buffer. */ 7701cb0ef41Sopenharmony_ci u_memmove(dest, dest+(haveLang?langPos:restPos), length); 7711cb0ef41Sopenharmony_ci } else { 7721cb0ef41Sopenharmony_ci /* would have fit, but didn't because of pattern prefix. */ 7731cb0ef41Sopenharmony_ci sub0Pos=0; /* stops initial padding (and a second retry, 7741cb0ef41Sopenharmony_ci so we won't end up here again) */ 7751cb0ef41Sopenharmony_ci retry=true; 7761cb0ef41Sopenharmony_ci } 7771cb0ef41Sopenharmony_ci } 7781cb0ef41Sopenharmony_ci } 7791cb0ef41Sopenharmony_ci 7801cb0ef41Sopenharmony_ci ++subi; /* move on to next substitution */ 7811cb0ef41Sopenharmony_ci } 7821cb0ef41Sopenharmony_ci } 7831cb0ef41Sopenharmony_ci } while(retry); 7841cb0ef41Sopenharmony_ci 7851cb0ef41Sopenharmony_ci return u_terminateUChars(dest, destCapacity, length, pErrorCode); 7861cb0ef41Sopenharmony_ci} 7871cb0ef41Sopenharmony_ci 7881cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 7891cb0ef41Sopenharmony_ciuloc_getDisplayKeyword(const char* keyword, 7901cb0ef41Sopenharmony_ci const char* displayLocale, 7911cb0ef41Sopenharmony_ci char16_t* dest, 7921cb0ef41Sopenharmony_ci int32_t destCapacity, 7931cb0ef41Sopenharmony_ci UErrorCode* status){ 7941cb0ef41Sopenharmony_ci 7951cb0ef41Sopenharmony_ci /* argument checking */ 7961cb0ef41Sopenharmony_ci if(status==nullptr || U_FAILURE(*status)) { 7971cb0ef41Sopenharmony_ci return 0; 7981cb0ef41Sopenharmony_ci } 7991cb0ef41Sopenharmony_ci 8001cb0ef41Sopenharmony_ci if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) { 8011cb0ef41Sopenharmony_ci *status=U_ILLEGAL_ARGUMENT_ERROR; 8021cb0ef41Sopenharmony_ci return 0; 8031cb0ef41Sopenharmony_ci } 8041cb0ef41Sopenharmony_ci 8051cb0ef41Sopenharmony_ci 8061cb0ef41Sopenharmony_ci /* pass itemKey=nullptr to look for a top-level item */ 8071cb0ef41Sopenharmony_ci return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale, 8081cb0ef41Sopenharmony_ci _kKeys, nullptr, 8091cb0ef41Sopenharmony_ci keyword, 8101cb0ef41Sopenharmony_ci keyword, 8111cb0ef41Sopenharmony_ci dest, destCapacity, 8121cb0ef41Sopenharmony_ci status); 8131cb0ef41Sopenharmony_ci 8141cb0ef41Sopenharmony_ci} 8151cb0ef41Sopenharmony_ci 8161cb0ef41Sopenharmony_ci 8171cb0ef41Sopenharmony_ci#define UCURRENCY_DISPLAY_NAME_INDEX 1 8181cb0ef41Sopenharmony_ci 8191cb0ef41Sopenharmony_ciU_CAPI int32_t U_EXPORT2 8201cb0ef41Sopenharmony_ciuloc_getDisplayKeywordValue( const char* locale, 8211cb0ef41Sopenharmony_ci const char* keyword, 8221cb0ef41Sopenharmony_ci const char* displayLocale, 8231cb0ef41Sopenharmony_ci char16_t* dest, 8241cb0ef41Sopenharmony_ci int32_t destCapacity, 8251cb0ef41Sopenharmony_ci UErrorCode* status){ 8261cb0ef41Sopenharmony_ci 8271cb0ef41Sopenharmony_ci 8281cb0ef41Sopenharmony_ci /* argument checking */ 8291cb0ef41Sopenharmony_ci if(status==nullptr || U_FAILURE(*status)) { 8301cb0ef41Sopenharmony_ci return 0; 8311cb0ef41Sopenharmony_ci } 8321cb0ef41Sopenharmony_ci 8331cb0ef41Sopenharmony_ci if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) { 8341cb0ef41Sopenharmony_ci *status=U_ILLEGAL_ARGUMENT_ERROR; 8351cb0ef41Sopenharmony_ci return 0; 8361cb0ef41Sopenharmony_ci } 8371cb0ef41Sopenharmony_ci 8381cb0ef41Sopenharmony_ci /* get the keyword value */ 8391cb0ef41Sopenharmony_ci CharString keywordValue; 8401cb0ef41Sopenharmony_ci { 8411cb0ef41Sopenharmony_ci CharStringByteSink sink(&keywordValue); 8421cb0ef41Sopenharmony_ci ulocimp_getKeywordValue(locale, keyword, sink, status); 8431cb0ef41Sopenharmony_ci } 8441cb0ef41Sopenharmony_ci 8451cb0ef41Sopenharmony_ci /* 8461cb0ef41Sopenharmony_ci * if the keyword is equal to currency .. then to get the display name 8471cb0ef41Sopenharmony_ci * we need to do the fallback ourselves 8481cb0ef41Sopenharmony_ci */ 8491cb0ef41Sopenharmony_ci if(uprv_stricmp(keyword, _kCurrency)==0){ 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci int32_t dispNameLen = 0; 8521cb0ef41Sopenharmony_ci const char16_t *dispName = nullptr; 8531cb0ef41Sopenharmony_ci 8541cb0ef41Sopenharmony_ci icu::LocalUResourceBundlePointer bundle( 8551cb0ef41Sopenharmony_ci ures_open(U_ICUDATA_CURR, displayLocale, status)); 8561cb0ef41Sopenharmony_ci icu::LocalUResourceBundlePointer currencies( 8571cb0ef41Sopenharmony_ci ures_getByKey(bundle.getAlias(), _kCurrencies, nullptr, status)); 8581cb0ef41Sopenharmony_ci icu::LocalUResourceBundlePointer currency( 8591cb0ef41Sopenharmony_ci ures_getByKeyWithFallback(currencies.getAlias(), keywordValue.data(), nullptr, status)); 8601cb0ef41Sopenharmony_ci 8611cb0ef41Sopenharmony_ci dispName = ures_getStringByIndex(currency.getAlias(), UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status); 8621cb0ef41Sopenharmony_ci 8631cb0ef41Sopenharmony_ci if(U_FAILURE(*status)){ 8641cb0ef41Sopenharmony_ci if(*status == U_MISSING_RESOURCE_ERROR){ 8651cb0ef41Sopenharmony_ci /* we just want to write the value over if nothing is available */ 8661cb0ef41Sopenharmony_ci *status = U_USING_DEFAULT_WARNING; 8671cb0ef41Sopenharmony_ci }else{ 8681cb0ef41Sopenharmony_ci return 0; 8691cb0ef41Sopenharmony_ci } 8701cb0ef41Sopenharmony_ci } 8711cb0ef41Sopenharmony_ci 8721cb0ef41Sopenharmony_ci /* now copy the dispName over if not nullptr */ 8731cb0ef41Sopenharmony_ci if(dispName != nullptr){ 8741cb0ef41Sopenharmony_ci if(dispNameLen <= destCapacity){ 8751cb0ef41Sopenharmony_ci u_memcpy(dest, dispName, dispNameLen); 8761cb0ef41Sopenharmony_ci return u_terminateUChars(dest, destCapacity, dispNameLen, status); 8771cb0ef41Sopenharmony_ci }else{ 8781cb0ef41Sopenharmony_ci *status = U_BUFFER_OVERFLOW_ERROR; 8791cb0ef41Sopenharmony_ci return dispNameLen; 8801cb0ef41Sopenharmony_ci } 8811cb0ef41Sopenharmony_ci }else{ 8821cb0ef41Sopenharmony_ci /* we have not found the display name for the value .. just copy over */ 8831cb0ef41Sopenharmony_ci if(keywordValue.length() <= destCapacity){ 8841cb0ef41Sopenharmony_ci u_charsToUChars(keywordValue.data(), dest, keywordValue.length()); 8851cb0ef41Sopenharmony_ci return u_terminateUChars(dest, destCapacity, keywordValue.length(), status); 8861cb0ef41Sopenharmony_ci }else{ 8871cb0ef41Sopenharmony_ci *status = U_BUFFER_OVERFLOW_ERROR; 8881cb0ef41Sopenharmony_ci return keywordValue.length(); 8891cb0ef41Sopenharmony_ci } 8901cb0ef41Sopenharmony_ci } 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_ci 8931cb0ef41Sopenharmony_ci }else{ 8941cb0ef41Sopenharmony_ci 8951cb0ef41Sopenharmony_ci return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale, 8961cb0ef41Sopenharmony_ci _kTypes, keyword, 8971cb0ef41Sopenharmony_ci keywordValue.data(), 8981cb0ef41Sopenharmony_ci keywordValue.data(), 8991cb0ef41Sopenharmony_ci dest, destCapacity, 9001cb0ef41Sopenharmony_ci status); 9011cb0ef41Sopenharmony_ci } 9021cb0ef41Sopenharmony_ci} 903