+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
*
-* Copyright (C) 1997-2010, 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"
the locale ResourceBundle data file.*/
static const char _kLanguages[] = "Languages";
static const char _kScripts[] = "Scripts";
+static const char _kScriptsStandAlone[] = "Scripts%stand-alone";
static const char _kCountries[] = "Countries";
static const char _kVariants[] = "Variants";
static const char _kKeys[] = "Keys";
static const char _kTypes[] = "Types";
-static const char _kRootName[] = "root";
+//static const char _kRootName[] = "root";
static const char _kCurrency[] = "currency";
static const char _kCurrencies[] = "Currencies";
static const char _kLocaleDisplayPattern[] = "localeDisplayPattern";
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. */
const char* displayLocale,
UChar *dest, int32_t destCapacity,
UErrorCode *pErrorCode)
+{
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
+ uloc_getScript, _kScriptsStandAlone, &err);
+
+ if ( err == U_USING_DEFAULT_WARNING ) {
+ return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
+ uloc_getScript, _kScripts, pErrorCode);
+ } else {
+ *pErrorCode = err;
+ return res;
+ }
+}
+
+U_INTERNAL int32_t U_EXPORT2
+uloc_getDisplayScriptInContext(const char* locale,
+ const char* displayLocale,
+ UChar *dest, int32_t destCapacity,
+ UErrorCode *pErrorCode)
{
return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
- uloc_getScript, _kScripts, pErrorCode);
+ uloc_getScript, _kScripts, pErrorCode);
}
U_CAPI int32_t U_EXPORT2
uloc_getVariant, _kVariants, pErrorCode);
}
+/* Instead of having a separate pass for 'special' patterns, reintegrate the two
+ * so we don't get bitten by preflight bugs again. We can be reasonably efficient
+ * without two separate code paths, this code isn't that performance-critical.
+ *
+ * This code is general enough to deal with patterns that have a prefix or swap the
+ * language and remainder components, since we gave developers enough rope to do such
+ * things if they futz with the pattern data. But since we don't give them a way to
+ * specify a pattern for arbitrary combinations of components, there's not much use in
+ * that. I don't think our data includes such patterns, the only variable I know if is
+ * whether there is a space before the open paren, or not. Oh, and zh uses different
+ * chars than the standard open/close paren (which ja and ko use, btw).
+ */
U_CAPI int32_t U_EXPORT2
uloc_getDisplayName(const char *locale,
const char *displayLocale,
UChar *dest, int32_t destCapacity,
UErrorCode *pErrorCode)
{
- int32_t length, length2, length3 = 0;
- UBool hasLanguage, hasScript, hasCountry, hasVariant, hasKeywords;
- UEnumeration* keywordEnum = NULL;
- int32_t keywordCount = 0;
- const char *keyword = NULL;
- int32_t keywordLen = 0;
- char keywordValue[256];
- int32_t keywordValueLen = 0;
-
- int32_t locSepLen = 0;
- int32_t locPatLen = 0;
- int32_t p0Len = 0;
- int32_t defaultPatternLen = 9;
- const UChar *dispLocSeparator;
- const UChar *dispLocPattern;
- static const UChar defaultSeparator[3] = { 0x002c, 0x0020 , 0x0000 }; /* comma + space */
- static const UChar defaultPattern[10] = { 0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000 }; /* {0} ({1}) */
- static const UChar pat0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */
- static const UChar pat1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */
-
- UResourceBundle *bundle = NULL;
- UResourceBundle *locdsppat = NULL;
+ 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;
+ static const UChar defaultPattern[10] = {
+ 0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000
+ }; /* {0} ({1}) */
+ static const int32_t defaultPatLen = 9;
+ static const int32_t defaultSub0Pos = 0;
+ static const int32_t defaultSub1Pos = 5;
+
+ int32_t length; /* of formatted result */
+
+ const UChar *separator;
+ int32_t sepLen = 0;
+ const UChar *pattern;
+ int32_t patLen = 0;
+ int32_t sub0Pos, sub1Pos;
- UErrorCode status = U_ZERO_ERROR;
+ 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 */
+ UBool haveRest = TRUE; /* assume true, set false if we find we don't have
+ any other component in the locale */
+ UBool retry = FALSE; /* set true if we need to retry, see below */
+
+ int32_t langi = 0; /* index of the language substitution (0 or 1), virtually always 0 */
- /* argument checking */
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
return 0;
}
return 0;
}
- bundle = ures_open(U_ICUDATA_LANG, displayLocale, &status);
+ { // 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;
+ }
+ }
+ }
- locdsppat = ures_getByKeyWithFallback(bundle, _kLocaleDisplayPattern, NULL, &status);
- dispLocSeparator = ures_getStringByKeyWithFallback(locdsppat, _kSeparator, &locSepLen, &status);
- dispLocPattern = ures_getStringByKeyWithFallback(locdsppat, _kPattern, &locPatLen, &status);
-
- /*close the bundles */
- ures_close(locdsppat);
- ures_close(bundle);
+ {
+ UErrorCode status = U_ZERO_ERROR;
- /* If we couldn't find any data, then use the defaults */
- if ( locSepLen == 0) {
- dispLocSeparator = defaultSeparator;
- locSepLen = 2;
- }
+ icu::LocalUResourceBundlePointer locbundle(
+ ures_open(U_ICUDATA_LANG, displayLocale, &status));
+ icu::LocalUResourceBundlePointer dspbundle(
+ ures_getByKeyWithFallback(locbundle.getAlias(), _kLocaleDisplayPattern, NULL, &status));
- if ( locPatLen == 0) {
- dispLocPattern = defaultPattern;
- locPatLen = 9;
+ separator=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kSeparator, &sepLen, &status);
+ pattern=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kPattern, &patLen, &status);
}
- /*
- * if there is a language, then write "language (country, variant)"
- * otherwise write "country, variant"
+ /* If we couldn't find any data, then use the defaults */
+ if(sepLen == 0) {
+ separator = defaultSeparator;
+ }
+ /* #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.
*/
-
- /* write the language */
- length=uloc_getDisplayLanguage(locale, displayLocale,
- dest, destCapacity,
- pErrorCode);
- hasLanguage= length>0;
-
- if(hasLanguage) {
- p0Len = length;
-
- /* append " (" */
- if(length<destCapacity) {
- dest[length]=0x20;
+ {
+ 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;
}
- ++length;
- if(length<destCapacity) {
- dest[length]=0x28;
+ separator = (const UChar *)p0 + subLen;
+ sepLen = static_cast<int32_t>(p1 - separator);
+ }
+
+ if(patLen==0 || (patLen==defaultPatLen && !u_strncmp(pattern, defaultPattern, patLen))) {
+ pattern=defaultPattern;
+ 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);
+ if (p0==NULL || p1==NULL) {
+ *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
}
- ++length;
- }
-
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- /* keep preflighting */
- *pErrorCode=U_ZERO_ERROR;
- }
-
- /* append the script */
- if(length<destCapacity) {
- length2=uloc_getDisplayScript(locale, displayLocale,
- dest+length, destCapacity-length,
- pErrorCode);
- } else {
- length2=uloc_getDisplayScript(locale, displayLocale,
- NULL, 0,
- pErrorCode);
- }
- hasScript= length2>0;
- length+=length2;
-
- if(hasScript) {
- /* append separator */
- if(length+locSepLen<=destCapacity) {
- u_memcpy(dest+length,dispLocSeparator,locSepLen);
+ 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;
}
- length+=locSepLen;
- }
-
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- /* keep preflighting */
- *pErrorCode=U_ZERO_ERROR;
- }
-
- /* append the country */
- if(length<destCapacity) {
- length2=uloc_getDisplayCountry(locale, displayLocale,
- dest+length, destCapacity-length,
- pErrorCode);
- } else {
- length2=uloc_getDisplayCountry(locale, displayLocale,
- NULL, 0,
- pErrorCode);
- }
- hasCountry= length2>0;
- length+=length2;
-
- if(hasCountry) {
- /* append separator */
- if(length+locSepLen<=destCapacity) {
- u_memcpy(dest+length,dispLocSeparator,locSepLen);
+ if (u_strchr(pattern, 0xFF08) != NULL) {
+ formatOpenParen = 0xFF08; // fullwidth (
+ formatReplaceOpenParen = 0xFF3B; // fullwidth [
+ formatCloseParen = 0xFF09; // fullwidth )
+ formatReplaceCloseParen = 0xFF3D; // fullwidth ]
}
- length+=locSepLen;
}
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- /* keep preflighting */
- *pErrorCode=U_ZERO_ERROR;
- }
-
- /* append the variant */
- if(length<destCapacity) {
- length2=uloc_getDisplayVariant(locale, displayLocale,
- dest+length, destCapacity-length,
- pErrorCode);
- } else {
- length2=uloc_getDisplayVariant(locale, displayLocale,
- NULL, 0,
- pErrorCode);
- }
- hasVariant= length2>0;
- length+=length2;
-
- if(hasVariant) {
- /* append separator */
- if(length+locSepLen<=destCapacity) {
- u_memcpy(dest+length,dispLocSeparator,locSepLen);
+ /* We loop here because there is one case in which after the first pass we could need to
+ * reextract the data. If there's initial padding before the first element, we put in
+ * the padding and then write that element. If it turns out there's no second element,
+ * we didn't need the padding. If we do need the data (no preflight), and the first element
+ * would have fit but for the padding, we need to reextract. In this case (only) we
+ * adjust the parameters so padding is not added, and repeat.
+ */
+ do {
+ UChar* p=dest;
+ int32_t patPos=0; /* position in the pattern, used for non-substitution portions */
+ int32_t langLen=0; /* length of language substitution */
+ 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 */
+ icu::LocalUEnumerationPointer kenum; /* keyword enumeration */
+
+ /* prefix of pattern, extremely likely to be empty */
+ if(sub0Pos) {
+ if(destCapacity >= sub0Pos) {
+ while (patPos < sub0Pos) {
+ *p++ = pattern[patPos++];
+ }
+ } else {
+ patPos=sub0Pos;
+ }
+ length=sub0Pos;
+ } else {
+ length=0;
}
- length+=locSepLen;
- }
- keywordEnum = uloc_openKeywords(locale, pErrorCode);
-
- for(keywordCount = uenum_count(keywordEnum, pErrorCode); keywordCount > 0 ; keywordCount--){
- if(U_FAILURE(*pErrorCode)){
- break;
- }
- /* the uenum_next returns NUL terminated string */
- keyword = uenum_next(keywordEnum, &keywordLen, pErrorCode);
- if(length + length3 < destCapacity) {
- length3 += uloc_getDisplayKeyword(keyword, displayLocale, dest+length+length3, destCapacity-length-length3, pErrorCode);
- } else {
- length3 += uloc_getDisplayKeyword(keyword, displayLocale, NULL, 0, pErrorCode);
- }
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- /* keep preflighting */
- *pErrorCode=U_ZERO_ERROR;
- }
- keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, 256, pErrorCode);
- if(keywordValueLen) {
- if(length + length3 < destCapacity) {
- dest[length + length3] = 0x3D;
- }
- length3++;
- if(length + length3 < destCapacity) {
- length3 += uloc_getDisplayKeywordValue(locale, keyword, displayLocale, dest+length+length3, destCapacity-length-length3, pErrorCode);
+ for(int32_t subi=0,resti=0;subi<2;) { /* iterate through patterns 0 and 1*/
+ UBool subdone = FALSE; /* set true when ready to move to next substitution */
+
+ /* prep p and cap for calls to get display components, pin cap to 0 since
+ they complain if cap is negative */
+ int32_t cap=destCapacity-length;
+ if (cap <= 0) {
+ cap=0;
} else {
- length3 += uloc_getDisplayKeywordValue(locale, keyword, displayLocale, NULL, 0, pErrorCode);
- }
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- /* keep preflighting */
- *pErrorCode=U_ZERO_ERROR;
+ p=dest+length;
}
- }
- if(keywordCount > 1) {
- if(length + length3 + locSepLen <= destCapacity && keywordCount) {
- u_memcpy(dest+length+length3,dispLocSeparator,locSepLen);
- length3+=locSepLen;
- }
- }
- }
- uenum_close(keywordEnum);
-
- hasKeywords = length3 > 0;
- length += length3;
+ if (subi == langi) { /* {0}*/
+ if(haveLang) {
+ langPos=length;
+ langLen=uloc_getDisplayLanguage(locale, displayLocale, p, cap, pErrorCode);
+ length+=langLen;
+ haveLang=langLen>0;
+ }
+ subdone=TRUE;
+ } else { /* {1} */
+ if(!haveRest) {
+ subdone=TRUE;
+ } else {
+ int32_t len; /* length of component (plus other stuff) we just fetched */
+ switch(resti++) {
+ case 0:
+ restPos=length;
+ len=uloc_getDisplayScriptInContext(locale, displayLocale, p, cap, pErrorCode);
+ break;
+ case 1:
+ len=uloc_getDisplayCountry(locale, displayLocale, p, cap, pErrorCode);
+ break;
+ case 2:
+ len=uloc_getDisplayVariant(locale, displayLocale, p, cap, pErrorCode);
+ break;
+ case 3:
+ kenum.adoptInstead(uloc_openKeywords(locale, pErrorCode));
+ U_FALLTHROUGH;
+ default: {
+ const char* kw=uenum_next(kenum.getAlias(), &len, pErrorCode);
+ if (kw == NULL) {
+ len=0; /* mark that we didn't add a component */
+ subdone=TRUE;
+ } else {
+ /* incorporating this behavior into the loop made it even more complex,
+ so just special case it here */
+ len = uloc_getDisplayKeyword(kw, displayLocale, p, cap, pErrorCode);
+ if(len) {
+ if(len < cap) {
+ p[len]=0x3d; /* '=', assume we'll need it */
+ }
+ len+=1;
+
+ /* adjust for call to get keyword */
+ cap-=len;
+ if(cap <= 0) {
+ cap=0;
+ } else {
+ p+=len;
+ }
+ }
+ /* reset for call below */
+ if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) {
+ *pErrorCode=U_ZERO_ERROR;
+ }
+ int32_t vlen = uloc_getDisplayKeywordValue(locale, kw, displayLocale,
+ p, cap, pErrorCode);
+ if(len) {
+ if(vlen==0) {
+ --len; /* remove unneeded '=' */
+ }
+ /* restore cap and p to what they were at start */
+ cap=destCapacity-length;
+ if(cap <= 0) {
+ cap=0;
+ } else {
+ p=dest+length;
+ }
+ }
+ len+=vlen; /* total we added for key + '=' + value */
+ }
+ } break;
+ } /* end switch */
+
+ if (len>0) {
+ /* we addeed a component, so add separator and write it if there's room. */
+ if(len+sepLen<=cap) {
+ 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];
+ }
+ }
+ length+=len+sepLen;
+ } else if(subdone) {
+ /* remove separator if we added it */
+ if (length!=restPos) {
+ length-=sepLen;
+ }
+ restLen=length-restPos;
+ haveRest=restLen>0;
+ }
+ }
+ }
- if ((hasScript && !hasCountry)
- || ((hasScript || hasCountry) && !hasVariant && !hasKeywords)
- || ((hasScript || hasCountry || hasVariant) && !hasKeywords)) {
- /* Remove separator */
- length -= locSepLen;
- } else if (hasLanguage && !hasScript && !hasCountry && !hasVariant && !hasKeywords) {
- /* Remove " (" */
- length-=2;
- }
+ if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) {
+ *pErrorCode=U_ZERO_ERROR;
+ }
- if (hasLanguage && (hasScript || hasCountry || hasVariant || hasKeywords)) {
- /* append ")" */
- if(length<destCapacity) {
- dest[length]=0x29;
- }
- ++length;
-
- /* If the localized display pattern is something other than the default pattern of "{0} ({1})", then
- * then we need to do the formatting here. It would be easier to use a messageFormat to do this, but we
- * can't since we don't have the APIs in the i18n library available to us at this point.
- */
- if (locPatLen != defaultPatternLen || u_strcmp(dispLocPattern,defaultPattern)) { /* Something other than the default pattern */
- UChar *p0 = u_strstr(dispLocPattern,pat0);
- UChar *p1 = u_strstr(dispLocPattern,pat1);
- u_terminateUChars(dest, destCapacity, length, pErrorCode);
-
- if ( p0 != NULL && p1 != NULL ) { /* The pattern is well formed */
- if ( dest ) {
- int32_t destLen = 0;
- UChar *result = (UChar *)uprv_malloc((length+1)*sizeof(UChar));
- UChar *upos = (UChar *)dispLocPattern;
- u_strcpy(result,dest);
- dest[0] = 0;
- while ( *upos ) {
- if ( upos == p0 ) { /* Handle {0} substitution */
- u_strncat(dest,result,p0Len);
- destLen += p0Len;
- dest[destLen] = 0; /* Null terminate */
- upos += 3;
- } else if ( upos == p1 ) { /* Handle {1} substitution */
- UChar *p1Start = &result[p0Len+2];
- u_strncat(dest,p1Start,length-p0Len-3);
- destLen += (length-p0Len-3);
- dest[destLen] = 0; /* Null terminate */
- upos += 3;
- } else { /* Something from the pattern not {0} or {1} */
- u_strncat(dest,upos,1);
- upos++;
- destLen++;
- dest[destLen] = 0; /* Null terminate */
- }
- }
- length = destLen;
- uprv_free(result);
- }
- }
+ if(subdone) {
+ if(haveLang && haveRest) {
+ /* append internal portion of pattern, the first time,
+ or last portion of pattern the second time */
+ int32_t padLen;
+ patPos+=subLen;
+ padLen=(subi==0 ? sub1Pos : patLen)-patPos;
+ if(length+padLen < destCapacity) {
+ p=dest+length;
+ for(int32_t i=0;i<padLen;++i) {
+ *p++=pattern[patPos++];
+ }
+ } else {
+ patPos+=padLen;
+ }
+ length+=padLen;
+ } else if(subi==0) {
+ /* don't have first component, reset for second component */
+ sub0Pos=0;
+ length=0;
+ } else if(length>0) {
+ /* true length is the length of just the component we got. */
+ length=haveLang?langLen:restLen;
+ if(dest && sub0Pos!=0) {
+ if (sub0Pos+length<=destCapacity) {
+ /* first component not at start of result,
+ but we have full component in buffer. */
+ u_memmove(dest, dest+(haveLang?langPos:restPos), length);
+ } else {
+ /* would have fit, but didn't because of pattern prefix. */
+ sub0Pos=0; /* stops initial padding (and a second retry,
+ so we won't end up here again) */
+ retry=TRUE;
+ }
+ }
+ }
+
+ ++subi; /* move on to next substitution */
+ }
}
- }
- if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
- /* keep preflighting */
- *pErrorCode=U_ZERO_ERROR;
- }
+ } while(retry);
return u_terminateUChars(dest, destCapacity, length, pErrorCode);
}
/* 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;