2 *******************************************************************************
4 * Copyright (C) 1997-2016, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: locdispnames.cpp
10 * tab size: 8 (not used)
13 * created on: 2010feb25
14 * created by: Markus W. Scherer
16 * Code for locale display names, separated out from other .cpp files
17 * that then do not depend on resource bundle code and display name data.
20 #include "unicode/utypes.h"
21 #include "unicode/brkiter.h"
22 #include "unicode/locid.h"
23 #include "unicode/uloc.h"
24 #include "unicode/ures.h"
25 #include "unicode/ustring.h"
34 // C++ API ----------------------------------------------------------------- ***
39 Locale::getDisplayLanguage(UnicodeString
& dispLang
) const
41 return this->getDisplayLanguage(getDefault(), dispLang
);
44 /*We cannot make any assumptions on the size of the output display strings
45 * Yet, since we are calling through to a C API, we need to set limits on
46 * buffer size. For all the following getDisplay functions we first attempt
47 * to fill up a stack allocated buffer. If it is to small we heap allocated
48 * the exact buffer we need copy it to the UnicodeString and delete it*/
51 Locale::getDisplayLanguage(const Locale
&displayLocale
,
52 UnicodeString
&result
) const {
54 UErrorCode errorCode
=U_ZERO_ERROR
;
57 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
63 length
=uloc_getDisplayLanguage(fullName
, displayLocale
.fullName
,
64 buffer
, result
.getCapacity(),
66 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
68 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
69 buffer
=result
.getBuffer(length
);
74 errorCode
=U_ZERO_ERROR
;
75 length
=uloc_getDisplayLanguage(fullName
, displayLocale
.fullName
,
76 buffer
, result
.getCapacity(),
78 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
85 Locale::getDisplayScript(UnicodeString
& dispScript
) const
87 return this->getDisplayScript(getDefault(), dispScript
);
91 Locale::getDisplayScript(const Locale
&displayLocale
,
92 UnicodeString
&result
) const {
94 UErrorCode errorCode
=U_ZERO_ERROR
;
97 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
103 length
=uloc_getDisplayScript(fullName
, displayLocale
.fullName
,
104 buffer
, result
.getCapacity(),
106 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
108 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
109 buffer
=result
.getBuffer(length
);
114 errorCode
=U_ZERO_ERROR
;
115 length
=uloc_getDisplayScript(fullName
, displayLocale
.fullName
,
116 buffer
, result
.getCapacity(),
118 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
125 Locale::getDisplayCountry(UnicodeString
& dispCntry
) const
127 return this->getDisplayCountry(getDefault(), dispCntry
);
131 Locale::getDisplayCountry(const Locale
&displayLocale
,
132 UnicodeString
&result
) const {
134 UErrorCode errorCode
=U_ZERO_ERROR
;
137 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
143 length
=uloc_getDisplayCountry(fullName
, displayLocale
.fullName
,
144 buffer
, result
.getCapacity(),
146 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
148 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
149 buffer
=result
.getBuffer(length
);
154 errorCode
=U_ZERO_ERROR
;
155 length
=uloc_getDisplayCountry(fullName
, displayLocale
.fullName
,
156 buffer
, result
.getCapacity(),
158 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
165 Locale::getDisplayVariant(UnicodeString
& dispVar
) const
167 return this->getDisplayVariant(getDefault(), dispVar
);
171 Locale::getDisplayVariant(const Locale
&displayLocale
,
172 UnicodeString
&result
) const {
174 UErrorCode errorCode
=U_ZERO_ERROR
;
177 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
183 length
=uloc_getDisplayVariant(fullName
, displayLocale
.fullName
,
184 buffer
, result
.getCapacity(),
186 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
188 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
189 buffer
=result
.getBuffer(length
);
194 errorCode
=U_ZERO_ERROR
;
195 length
=uloc_getDisplayVariant(fullName
, displayLocale
.fullName
,
196 buffer
, result
.getCapacity(),
198 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
205 Locale::getDisplayName( UnicodeString
& name
) const
207 return this->getDisplayName(getDefault(), name
);
211 Locale::getDisplayName(const Locale
&displayLocale
,
212 UnicodeString
&result
) const {
214 UErrorCode errorCode
=U_ZERO_ERROR
;
217 buffer
=result
.getBuffer(ULOC_FULLNAME_CAPACITY
);
223 length
=uloc_getDisplayName(fullName
, displayLocale
.fullName
,
224 buffer
, result
.getCapacity(),
226 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
228 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
229 buffer
=result
.getBuffer(length
);
234 errorCode
=U_ZERO_ERROR
;
235 length
=uloc_getDisplayName(fullName
, displayLocale
.fullName
,
236 buffer
, result
.getCapacity(),
238 result
.releaseBuffer(U_SUCCESS(errorCode
) ? length
: 0);
244 #if ! UCONFIG_NO_BREAK_ITERATION
246 // -------------------------------------
247 // Gets the objectLocale display name in the default locale language.
248 UnicodeString
& U_EXPORT2
249 BreakIterator::getDisplayName(const Locale
& objectLocale
,
252 return objectLocale
.getDisplayName(name
);
255 // -------------------------------------
256 // Gets the objectLocale display name in the displayLocale language.
257 UnicodeString
& U_EXPORT2
258 BreakIterator::getDisplayName(const Locale
& objectLocale
,
259 const Locale
& displayLocale
,
262 return objectLocale
.getDisplayName(displayLocale
, name
);
270 // C API ------------------------------------------------------------------- ***
274 /* ### Constants **************************************************/
276 /* These strings describe the resources we attempt to load from
277 the locale ResourceBundle data file.*/
278 static const char _kLanguages
[] = "Languages";
279 static const char _kScripts
[] = "Scripts";
280 static const char _kScriptsStandAlone
[] = "Scripts%stand-alone";
281 static const char _kCountries
[] = "Countries";
282 static const char _kVariants
[] = "Variants";
283 static const char _kKeys
[] = "Keys";
284 static const char _kTypes
[] = "Types";
285 //static const char _kRootName[] = "root";
286 static const char _kCurrency
[] = "currency";
287 static const char _kCurrencies
[] = "Currencies";
288 static const char _kLocaleDisplayPattern
[] = "localeDisplayPattern";
289 static const char _kPattern
[] = "pattern";
290 static const char _kSeparator
[] = "separator";
292 /* ### Display name **************************************************/
295 _getStringOrCopyKey(const char *path
, const char *locale
,
296 const char *tableKey
,
297 const char* subTableKey
,
299 const char *substitute
,
300 UChar
*dest
, int32_t destCapacity
,
301 UErrorCode
*pErrorCode
) {
302 const UChar
*s
= NULL
;
306 /* top-level item: normal resource bundle access */
309 rb
=ures_open(path
, locale
, pErrorCode
);
311 if(U_SUCCESS(*pErrorCode
)) {
312 s
=ures_getStringByKey(rb
, tableKey
, &length
, pErrorCode
);
313 /* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */
317 /* Language code should not be a number. If it is, set the error code. */
318 if (!uprv_strncmp(tableKey
, "Languages", 9) && uprv_strtol(itemKey
, NULL
, 10)) {
319 *pErrorCode
= U_MISSING_RESOURCE_ERROR
;
321 /* second-level item, use special fallback */
322 s
=uloc_getTableStringWithFallback(path
, locale
,
331 if(U_SUCCESS(*pErrorCode
)) {
332 int32_t copyLength
=uprv_min(length
, destCapacity
);
333 if(copyLength
>0 && s
!= NULL
) {
334 u_memcpy(dest
, s
, copyLength
);
337 /* no string from a resource bundle: convert the substitute */
338 length
=(int32_t)uprv_strlen(substitute
);
339 u_charsToUChars(substitute
, dest
, uprv_min(length
, destCapacity
));
340 *pErrorCode
=U_USING_DEFAULT_WARNING
;
343 return u_terminateUChars(dest
, destCapacity
, length
, pErrorCode
);
346 typedef int32_t U_CALLCONV
UDisplayNameGetter(const char *, char *, int32_t, UErrorCode
*);
349 _getDisplayNameForComponent(const char *locale
,
350 const char *displayLocale
,
351 UChar
*dest
, int32_t destCapacity
,
352 UDisplayNameGetter
*getter
,
354 UErrorCode
*pErrorCode
) {
355 char localeBuffer
[ULOC_FULLNAME_CAPACITY
*4];
357 UErrorCode localStatus
;
358 const char* root
= NULL
;
360 /* argument checking */
361 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
365 if(destCapacity
<0 || (destCapacity
>0 && dest
==NULL
)) {
366 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
370 localStatus
= U_ZERO_ERROR
;
371 length
=(*getter
)(locale
, localeBuffer
, sizeof(localeBuffer
), &localStatus
);
372 if(U_FAILURE(localStatus
) || localStatus
==U_STRING_NOT_TERMINATED_WARNING
) {
373 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
377 return u_terminateUChars(dest
, destCapacity
, 0, pErrorCode
);
380 root
= tag
== _kCountries
? U_ICUDATA_REGION
: U_ICUDATA_LANG
;
382 return _getStringOrCopyKey(root
, displayLocale
,
383 tag
, NULL
, localeBuffer
,
389 U_CAPI
int32_t U_EXPORT2
390 uloc_getDisplayLanguage(const char *locale
,
391 const char *displayLocale
,
392 UChar
*dest
, int32_t destCapacity
,
393 UErrorCode
*pErrorCode
) {
394 return _getDisplayNameForComponent(locale
, displayLocale
, dest
, destCapacity
,
395 uloc_getLanguage
, _kLanguages
, pErrorCode
);
398 U_CAPI
int32_t U_EXPORT2
399 uloc_getDisplayScript(const char* locale
,
400 const char* displayLocale
,
401 UChar
*dest
, int32_t destCapacity
,
402 UErrorCode
*pErrorCode
)
404 UErrorCode err
= U_ZERO_ERROR
;
405 int32_t res
= _getDisplayNameForComponent(locale
, displayLocale
, dest
, destCapacity
,
406 uloc_getScript
, _kScriptsStandAlone
, &err
);
408 if ( err
== U_USING_DEFAULT_WARNING
) {
409 return _getDisplayNameForComponent(locale
, displayLocale
, dest
, destCapacity
,
410 uloc_getScript
, _kScripts
, pErrorCode
);
417 U_INTERNAL
int32_t U_EXPORT2
418 uloc_getDisplayScriptInContext(const char* locale
,
419 const char* displayLocale
,
420 UChar
*dest
, int32_t destCapacity
,
421 UErrorCode
*pErrorCode
)
423 return _getDisplayNameForComponent(locale
, displayLocale
, dest
, destCapacity
,
424 uloc_getScript
, _kScripts
, pErrorCode
);
427 U_CAPI
int32_t U_EXPORT2
428 uloc_getDisplayCountry(const char *locale
,
429 const char *displayLocale
,
430 UChar
*dest
, int32_t destCapacity
,
431 UErrorCode
*pErrorCode
) {
432 return _getDisplayNameForComponent(locale
, displayLocale
, dest
, destCapacity
,
433 uloc_getCountry
, _kCountries
, pErrorCode
);
437 * TODO separate variant1_variant2_variant3...
438 * by getting each tag's display string and concatenating them with ", "
439 * in between - similar to uloc_getDisplayName()
441 U_CAPI
int32_t U_EXPORT2
442 uloc_getDisplayVariant(const char *locale
,
443 const char *displayLocale
,
444 UChar
*dest
, int32_t destCapacity
,
445 UErrorCode
*pErrorCode
) {
446 return _getDisplayNameForComponent(locale
, displayLocale
, dest
, destCapacity
,
447 uloc_getVariant
, _kVariants
, pErrorCode
);
450 /* Instead of having a separate pass for 'special' patterns, reintegrate the two
451 * so we don't get bitten by preflight bugs again. We can be reasonably efficient
452 * without two separate code paths, this code isn't that performance-critical.
454 * This code is general enough to deal with patterns that have a prefix or swap the
455 * language and remainder components, since we gave developers enough rope to do such
456 * things if they futz with the pattern data. But since we don't give them a way to
457 * specify a pattern for arbitrary combinations of components, there's not much use in
458 * that. I don't think our data includes such patterns, the only variable I know if is
459 * whether there is a space before the open paren, or not. Oh, and zh uses different
460 * chars than the standard open/close paren (which ja and ko use, btw).
462 U_CAPI
int32_t U_EXPORT2
463 uloc_getDisplayName(const char *locale
,
464 const char *displayLocale
,
465 UChar
*dest
, int32_t destCapacity
,
466 UErrorCode
*pErrorCode
)
468 static const UChar defaultSeparator
[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */
469 static const UChar sub0
[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */
470 static const UChar sub1
[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */
471 static const int32_t subLen
= 3;
472 static const UChar defaultPattern
[10] = {
473 0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000
475 static const int32_t defaultPatLen
= 9;
476 static const int32_t defaultSub0Pos
= 0;
477 static const int32_t defaultSub1Pos
= 5;
479 int32_t length
; /* of formatted result */
481 const UChar
*separator
;
483 const UChar
*pattern
;
485 int32_t sub0Pos
, sub1Pos
;
487 UChar formatOpenParen
= 0x0028; // (
488 UChar formatReplaceOpenParen
= 0x005B; // [
489 UChar formatCloseParen
= 0x0029; // )
490 UChar formatReplaceCloseParen
= 0x005D; // ]
492 UBool haveLang
= TRUE
; /* assume true, set false if we find we don't have
493 a lang component in the locale */
494 UBool haveRest
= TRUE
; /* assume true, set false if we find we don't have
495 any other component in the locale */
496 UBool retry
= FALSE
; /* set true if we need to retry, see below */
498 int32_t langi
= 0; /* index of the language substitution (0 or 1), virtually always 0 */
500 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
504 if(destCapacity
<0 || (destCapacity
>0 && dest
==NULL
)) {
505 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
510 UErrorCode status
= U_ZERO_ERROR
;
511 UResourceBundle
* locbundle
=ures_open(U_ICUDATA_LANG
, displayLocale
, &status
);
512 UResourceBundle
* dspbundle
=ures_getByKeyWithFallback(locbundle
, _kLocaleDisplayPattern
,
515 separator
=ures_getStringByKeyWithFallback(dspbundle
, _kSeparator
, &sepLen
, &status
);
516 pattern
=ures_getStringByKeyWithFallback(dspbundle
, _kPattern
, &patLen
, &status
);
518 ures_close(dspbundle
);
519 ures_close(locbundle
);
522 /* If we couldn't find any data, then use the defaults */
524 separator
= defaultSeparator
;
526 /* #10244: Even though separator is now a pattern, it is awkward to handle it as such
527 * here since we are trying to build the display string in place in the dest buffer,
528 * and to handle it as a pattern would entail having separate storage for the
529 * substrings that need to be combined (the first of which may be the result of
530 * previous such combinations). So for now we continue to treat the portion between
531 * {0} and {1} as a string to be appended when joining substrings, ignoring anything
532 * that is before {0} or after {1} (no existing separator pattern has any such thing).
533 * This is similar to how pattern is handled below.
536 UChar
*p0
=u_strstr(separator
, sub0
);
537 UChar
*p1
=u_strstr(separator
, sub1
);
538 if (p0
==NULL
|| p1
==NULL
|| p1
<p0
) {
539 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
542 separator
= (const UChar
*)p0
+ subLen
;
543 sepLen
= p1
- separator
;
546 if(patLen
==0 || (patLen
==defaultPatLen
&& !u_strncmp(pattern
, defaultPattern
, patLen
))) {
547 pattern
=defaultPattern
;
548 patLen
=defaultPatLen
;
549 sub0Pos
=defaultSub0Pos
;
550 sub1Pos
=defaultSub1Pos
;
551 // use default formatOpenParen etc. set above
552 } else { /* non-default pattern */
553 UChar
*p0
=u_strstr(pattern
, sub0
);
554 UChar
*p1
=u_strstr(pattern
, sub1
);
555 if (p0
==NULL
|| p1
==NULL
) {
556 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
561 if (sub1Pos
< sub0Pos
) { /* a very odd pattern */
562 int32_t t
=sub0Pos
; sub0Pos
=sub1Pos
; sub1Pos
=t
;
565 if (u_strchr(pattern
, 0xFF08) != NULL
) {
566 formatOpenParen
= 0xFF08; // fullwidth (
567 formatReplaceOpenParen
= 0xFF3B; // fullwidth [
568 formatCloseParen
= 0xFF09; // fullwidth )
569 formatReplaceCloseParen
= 0xFF3D; // fullwidth ]
573 /* We loop here because there is one case in which after the first pass we could need to
574 * reextract the data. If there's initial padding before the first element, we put in
575 * the padding and then write that element. If it turns out there's no second element,
576 * we didn't need the padding. If we do need the data (no preflight), and the first element
577 * would have fit but for the padding, we need to reextract. In this case (only) we
578 * adjust the parameters so padding is not added, and repeat.
582 int32_t patPos
=0; /* position in the pattern, used for non-substitution portions */
583 int32_t langLen
=0; /* length of language substitution */
584 int32_t langPos
=0; /* position in output of language substitution */
585 int32_t restLen
=0; /* length of 'everything else' substitution */
586 int32_t restPos
=0; /* position in output of 'everything else' substitution */
587 UEnumeration
* kenum
= NULL
; /* keyword enumeration */
589 /* prefix of pattern, extremely likely to be empty */
591 if(destCapacity
>= sub0Pos
) {
592 while (patPos
< sub0Pos
) {
593 *p
++ = pattern
[patPos
++];
603 for(int32_t subi
=0,resti
=0;subi
<2;) { /* iterate through patterns 0 and 1*/
604 UBool subdone
= FALSE
; /* set true when ready to move to next substitution */
606 /* prep p and cap for calls to get display components, pin cap to 0 since
607 they complain if cap is negative */
608 int32_t cap
=destCapacity
-length
;
615 if (subi
== langi
) { /* {0}*/
618 langLen
=uloc_getDisplayLanguage(locale
, displayLocale
, p
, cap
, pErrorCode
);
627 int32_t len
; /* length of component (plus other stuff) we just fetched */
631 len
=uloc_getDisplayScriptInContext(locale
, displayLocale
, p
, cap
, pErrorCode
);
634 len
=uloc_getDisplayCountry(locale
, displayLocale
, p
, cap
, pErrorCode
);
637 len
=uloc_getDisplayVariant(locale
, displayLocale
, p
, cap
, pErrorCode
);
640 kenum
= uloc_openKeywords(locale
, pErrorCode
);
643 const char* kw
=uenum_next(kenum
, &len
, pErrorCode
);
646 len
=0; /* mark that we didn't add a component */
649 /* incorporating this behavior into the loop made it even more complex,
650 so just special case it here */
651 len
= uloc_getDisplayKeyword(kw
, displayLocale
, p
, cap
, pErrorCode
);
654 p
[len
]=0x3d; /* '=', assume we'll need it */
658 /* adjust for call to get keyword */
666 /* reset for call below */
667 if(*pErrorCode
== U_BUFFER_OVERFLOW_ERROR
) {
668 *pErrorCode
=U_ZERO_ERROR
;
670 int32_t vlen
= uloc_getDisplayKeywordValue(locale
, kw
, displayLocale
,
674 --len
; /* remove unneeded '=' */
676 /* restore cap and p to what they were at start */
677 cap
=destCapacity
-length
;
684 len
+=vlen
; /* total we added for key + '=' + value */
690 /* we addeed a component, so add separator and write it if there's room. */
691 if(len
+sepLen
<=cap
) {
692 const UChar
* plimit
= p
+ len
;
693 for (; p
< plimit
; p
++) {
694 if (*p
== formatOpenParen
) {
695 *p
= formatReplaceOpenParen
;
696 } else if (*p
== formatCloseParen
) {
697 *p
= formatReplaceCloseParen
;
700 for(int32_t i
=0;i
<sepLen
;++i
) {
706 /* remove separator if we added it */
707 if (length
!=restPos
) {
710 restLen
=length
-restPos
;
716 if(*pErrorCode
== U_BUFFER_OVERFLOW_ERROR
) {
717 *pErrorCode
=U_ZERO_ERROR
;
721 if(haveLang
&& haveRest
) {
722 /* append internal portion of pattern, the first time,
723 or last portion of pattern the second time */
726 padLen
=(subi
==0 ? sub1Pos
: patLen
)-patPos
;
727 if(length
+padLen
< destCapacity
) {
729 for(int32_t i
=0;i
<padLen
;++i
) {
730 *p
++=pattern
[patPos
++];
737 /* don't have first component, reset for second component */
740 } else if(length
>0) {
741 /* true length is the length of just the component we got. */
742 length
=haveLang
?langLen
:restLen
;
743 if(dest
&& sub0Pos
!=0) {
744 if (sub0Pos
+length
<=destCapacity
) {
745 /* first component not at start of result,
746 but we have full component in buffer. */
747 u_memmove(dest
, dest
+(haveLang
?langPos
:restPos
), length
);
749 /* would have fit, but didn't because of pattern prefix. */
750 sub0Pos
=0; /* stops initial padding (and a second retry,
751 so we won't end up here again) */
757 ++subi
; /* move on to next substitution */
762 return u_terminateUChars(dest
, destCapacity
, length
, pErrorCode
);
765 U_CAPI
int32_t U_EXPORT2
766 uloc_getDisplayKeyword(const char* keyword
,
767 const char* displayLocale
,
769 int32_t destCapacity
,
772 /* argument checking */
773 if(status
==NULL
|| U_FAILURE(*status
)) {
777 if(destCapacity
<0 || (destCapacity
>0 && dest
==NULL
)) {
778 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
783 /* pass itemKey=NULL to look for a top-level item */
784 return _getStringOrCopyKey(U_ICUDATA_LANG
, displayLocale
,
794 #define UCURRENCY_DISPLAY_NAME_INDEX 1
796 U_CAPI
int32_t U_EXPORT2
797 uloc_getDisplayKeywordValue( const char* locale
,
799 const char* displayLocale
,
801 int32_t destCapacity
,
805 char keywordValue
[ULOC_FULLNAME_CAPACITY
*4];
806 int32_t capacity
= ULOC_FULLNAME_CAPACITY
*4;
807 int32_t keywordValueLen
=0;
809 /* argument checking */
810 if(status
==NULL
|| U_FAILURE(*status
)) {
814 if(destCapacity
<0 || (destCapacity
>0 && dest
==NULL
)) {
815 *status
=U_ILLEGAL_ARGUMENT_ERROR
;
819 /* get the keyword value */
821 keywordValueLen
= uloc_getKeywordValue(locale
, keyword
, keywordValue
, capacity
, status
);
824 * if the keyword is equal to currency .. then to get the display name
825 * we need to do the fallback ourselves
827 if(uprv_stricmp(keyword
, _kCurrency
)==0){
829 int32_t dispNameLen
= 0;
830 const UChar
*dispName
= NULL
;
832 UResourceBundle
*bundle
= ures_open(U_ICUDATA_CURR
, displayLocale
, status
);
833 UResourceBundle
*currencies
= ures_getByKey(bundle
, _kCurrencies
, NULL
, status
);
834 UResourceBundle
*currency
= ures_getByKeyWithFallback(currencies
, keywordValue
, NULL
, status
);
836 dispName
= ures_getStringByIndex(currency
, UCURRENCY_DISPLAY_NAME_INDEX
, &dispNameLen
, status
);
838 /*close the bundles */
839 ures_close(currency
);
840 ures_close(currencies
);
843 if(U_FAILURE(*status
)){
844 if(*status
== U_MISSING_RESOURCE_ERROR
){
845 /* we just want to write the value over if nothing is available */
846 *status
= U_USING_DEFAULT_WARNING
;
852 /* now copy the dispName over if not NULL */
853 if(dispName
!= NULL
){
854 if(dispNameLen
<= destCapacity
){
855 uprv_memcpy(dest
, dispName
, dispNameLen
* U_SIZEOF_UCHAR
);
856 return u_terminateUChars(dest
, destCapacity
, dispNameLen
, status
);
858 *status
= U_BUFFER_OVERFLOW_ERROR
;
862 /* we have not found the display name for the value .. just copy over */
863 if(keywordValueLen
<= destCapacity
){
864 u_charsToUChars(keywordValue
, dest
, keywordValueLen
);
865 return u_terminateUChars(dest
, destCapacity
, keywordValueLen
, status
);
867 *status
= U_BUFFER_OVERFLOW_ERROR
;
868 return keywordValueLen
;
875 return _getStringOrCopyKey(U_ICUDATA_LANG
, displayLocale
,