+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
*
-* Copyright (C) 1997-2012, International Business Machines
+* Copyright (C) 1997-2016, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: locdispnames.cpp
-* encoding: US-ASCII
+* encoding: UTF-8
* tab size: 8 (not used)
* indentation:4
*
#include "unicode/utypes.h"
#include "unicode/brkiter.h"
#include "unicode/locid.h"
+#include "unicode/uenum.h"
#include "unicode/uloc.h"
#include "unicode/ures.h"
#include "unicode/ustring.h"
+#include "unicode/uldnames.h"
+#include "charstr.h"
#include "cmemory.h"
#include "cstring.h"
#include "putilimp.h"
if(itemKey==NULL) {
/* top-level item: normal resource bundle access */
- UResourceBundle *rb;
-
- rb=ures_open(path, locale, pErrorCode);
+ icu::LocalUResourceBundlePointer rb(ures_open(path, locale, pErrorCode));
if(U_SUCCESS(*pErrorCode)) {
- s=ures_getStringByKey(rb, tableKey, &length, pErrorCode);
+ s=ures_getStringByKey(rb.getAlias(), tableKey, &length, pErrorCode);
/* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */
- ures_close(rb);
}
} else {
/* Language code should not be a number. If it is, set the error code. */
UChar *dest, int32_t destCapacity,
UErrorCode *pErrorCode)
{
- static const UChar defaultSeparator[3] = { 0x002c, 0x0020, 0x0000 }; /* comma + space */
- static const int32_t defaultSepLen = 2;
+ static const UChar defaultSeparator[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */
static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */
static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */
static const int32_t subLen = 3;
const UChar *pattern;
int32_t patLen = 0;
int32_t sub0Pos, sub1Pos;
+
+ UChar formatOpenParen = 0x0028; // (
+ UChar formatReplaceOpenParen = 0x005B; // [
+ UChar formatCloseParen = 0x0029; // )
+ UChar formatReplaceCloseParen = 0x005D; // ]
UBool haveLang = TRUE; /* assume true, set false if we find we don't have
a lang component in the locale */
return 0;
}
+ { // For select languages + script, route to uldn_localeDisplayName <rdar://problem/51418203>
+ char lang[ULOC_LANG_CAPACITY];
+ char script[ULOC_SCRIPT_CAPACITY ];
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t langlen = uloc_getLanguage(locale, lang, ULOC_LANG_CAPACITY, &status);
+ int32_t scriptlen = uloc_getScript(locale, script, ULOC_SCRIPT_CAPACITY, &status);
+ if ( U_SUCCESS(status) && scriptlen>0 && (uprv_strcmp(lang, "zh") == 0 || uprv_strcmp(lang, "yue") == 0 ||
+ uprv_strcmp(lang, "ks") == 0 || uprv_strcmp(lang, "pa") == 0 || uprv_strcmp(lang, "ur") == 0) ) {
+ ULocaleDisplayNames* uldn = uldn_open(displayLocale, ULDN_STANDARD_NAMES, &status);
+ if ( U_SUCCESS(status) ) {
+ int32_t namelen = uldn_localeDisplayName(uldn, locale, dest, destCapacity, pErrorCode);
+ uldn_close(uldn);
+ return namelen;
+ }
+ }
+ }
+
{
UErrorCode status = U_ZERO_ERROR;
- UResourceBundle* locbundle=ures_open(U_ICUDATA_LANG, displayLocale, &status);
- UResourceBundle* dspbundle=ures_getByKeyWithFallback(locbundle, _kLocaleDisplayPattern,
- NULL, &status);
- separator=ures_getStringByKeyWithFallback(dspbundle, _kSeparator, &sepLen, &status);
- pattern=ures_getStringByKeyWithFallback(dspbundle, _kPattern, &patLen, &status);
+ icu::LocalUResourceBundlePointer locbundle(
+ ures_open(U_ICUDATA_LANG, displayLocale, &status));
+ icu::LocalUResourceBundlePointer dspbundle(
+ ures_getByKeyWithFallback(locbundle.getAlias(), _kLocaleDisplayPattern, NULL, &status));
- ures_close(dspbundle);
- ures_close(locbundle);
+ separator=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kSeparator, &sepLen, &status);
+ pattern=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kPattern, &patLen, &status);
}
/* If we couldn't find any data, then use the defaults */
if(sepLen == 0) {
separator = defaultSeparator;
- sepLen = defaultSepLen;
+ }
+ /* #10244: Even though separator is now a pattern, it is awkward to handle it as such
+ * here since we are trying to build the display string in place in the dest buffer,
+ * and to handle it as a pattern would entail having separate storage for the
+ * substrings that need to be combined (the first of which may be the result of
+ * previous such combinations). So for now we continue to treat the portion between
+ * {0} and {1} as a string to be appended when joining substrings, ignoring anything
+ * that is before {0} or after {1} (no existing separator pattern has any such thing).
+ * This is similar to how pattern is handled below.
+ */
+ {
+ UChar *p0=u_strstr(separator, sub0);
+ UChar *p1=u_strstr(separator, sub1);
+ if (p0==NULL || p1==NULL || p1<p0) {
+ *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ separator = (const UChar *)p0 + subLen;
+ sepLen = static_cast<int32_t>(p1 - separator);
}
if(patLen==0 || (patLen==defaultPatLen && !u_strncmp(pattern, defaultPattern, patLen))) {
patLen=defaultPatLen;
sub0Pos=defaultSub0Pos;
sub1Pos=defaultSub1Pos;
+ // use default formatOpenParen etc. set above
} else { /* non-default pattern */
UChar *p0=u_strstr(pattern, sub0);
UChar *p1=u_strstr(pattern, sub1);
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
- sub0Pos=p0-pattern;
- sub1Pos=p1-pattern;
+ sub0Pos = static_cast<int32_t>(p0-pattern);
+ sub1Pos = static_cast<int32_t>(p1-pattern);
if (sub1Pos < sub0Pos) { /* a very odd pattern */
int32_t t=sub0Pos; sub0Pos=sub1Pos; sub1Pos=t;
langi=1;
}
+ if (u_strchr(pattern, 0xFF08) != NULL) {
+ formatOpenParen = 0xFF08; // fullwidth (
+ formatReplaceOpenParen = 0xFF3B; // fullwidth [
+ formatCloseParen = 0xFF09; // fullwidth )
+ formatReplaceCloseParen = 0xFF3D; // fullwidth ]
+ }
}
/* We loop here because there is one case in which after the first pass we could need to
int32_t langPos=0; /* position in output of language substitution */
int32_t restLen=0; /* length of 'everything else' substitution */
int32_t restPos=0; /* position in output of 'everything else' substitution */
- UEnumeration* kenum = NULL; /* keyword enumeration */
+ icu::LocalUEnumerationPointer kenum; /* keyword enumeration */
/* prefix of pattern, extremely likely to be empty */
if(sub0Pos) {
len=uloc_getDisplayVariant(locale, displayLocale, p, cap, pErrorCode);
break;
case 3:
- kenum = uloc_openKeywords(locale, pErrorCode);
- /* fall through */
+ kenum.adoptInstead(uloc_openKeywords(locale, pErrorCode));
+ U_FALLTHROUGH;
default: {
- const char* kw=uenum_next(kenum, &len, pErrorCode);
+ const char* kw=uenum_next(kenum.getAlias(), &len, pErrorCode);
if (kw == NULL) {
- uenum_close(kenum);
len=0; /* mark that we didn't add a component */
subdone=TRUE;
} else {
if (len>0) {
/* we addeed a component, so add separator and write it if there's room. */
if(len+sepLen<=cap) {
- p+=len;
+ const UChar * plimit = p + len;
+ for (; p < plimit; p++) {
+ if (*p == formatOpenParen) {
+ *p = formatReplaceOpenParen;
+ } else if (*p == formatCloseParen) {
+ *p = formatReplaceCloseParen;
+ }
+ }
for(int32_t i=0;i<sepLen;++i) {
*p++=separator[i];
}
/* 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;
/*
* if the keyword is equal to currency .. then to get the display name
int32_t dispNameLen = 0;
const UChar *dispName = NULL;
-
- UResourceBundle *bundle = ures_open(U_ICUDATA_CURR, displayLocale, status);
- UResourceBundle *currencies = ures_getByKey(bundle, _kCurrencies, NULL, status);
- UResourceBundle *currency = ures_getByKeyWithFallback(currencies, keywordValue, NULL, status);
-
- dispName = ures_getStringByIndex(currency, UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status);
-
- /*close the bundles */
- ures_close(currency);
- ures_close(currencies);
- ures_close(bundle);
-
+
+ icu::LocalUResourceBundlePointer bundle(
+ ures_open(U_ICUDATA_CURR, displayLocale, status));
+ icu::LocalUResourceBundlePointer currencies(
+ ures_getByKey(bundle.getAlias(), _kCurrencies, NULL, status));
+ icu::LocalUResourceBundlePointer currency(
+ ures_getByKeyWithFallback(currencies.getAlias(), keywordValue, NULL, status));
+
+ dispName = ures_getStringByIndex(currency.getAlias(), UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status);
+
if(U_FAILURE(*status)){
if(*status == U_MISSING_RESOURCE_ERROR){
/* we just want to write the value over if nothing is available */
/* now copy the dispName over if not NULL */
if(dispName != NULL){
if(dispNameLen <= destCapacity){
- uprv_memcpy(dest, dispName, dispNameLen * U_SIZEOF_UCHAR);
+ u_memcpy(dest, dispName, dispNameLen);
return u_terminateUChars(dest, destCapacity, dispNameLen, status);
}else{
*status = U_BUFFER_OVERFLOW_ERROR;