2 *******************************************************************************
3 * Copyright (C) 2010, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_FORMATTING
12 #include "unicode/locdspnm.h"
14 #include "unicode/msgfmt.h"
24 * Concatenate a number of null-terminated strings to buffer, leaving a
25 * null-terminated string. The last argument should be the null pointer.
26 * Return the length of the string in the buffer, not counting the trailing
27 * null. Return -1 if there is an error (buffer is null, or buflen < 1).
29 static int32_t ncat(char *buffer
, uint32_t buflen
, ...) {
33 const char* e
= buffer
+ buflen
- 1;
35 if (buffer
== NULL
|| buflen
< 1) {
39 va_start(args
, buflen
);
40 while ((str
= va_arg(args
, char *))) {
42 while (p
!= e
&& (c
= *str
++)) {
54 ////////////////////////////////////////////////////////////////////////////////////////////////////
56 // Access resource data for locale components.
57 // Wrap code in uloc.c for now.
63 ICUDataTable(const char* path
, const Locale
& locale
);
66 const Locale
& getLocale();
68 UnicodeString
& get(const char* tableKey
, const char* itemKey
,
69 UnicodeString
& result
) const;
70 UnicodeString
& get(const char* tableKey
, const char* subTableKey
, const char* itemKey
,
71 UnicodeString
& result
) const;
73 UnicodeString
& getNoFallback(const char* tableKey
, const char* itemKey
,
74 UnicodeString
&result
) const;
75 UnicodeString
& getNoFallback(const char* tableKey
, const char* subTableKey
, const char* itemKey
,
76 UnicodeString
&result
) const;
79 inline UnicodeString
&
80 ICUDataTable::get(const char* tableKey
, const char* itemKey
, UnicodeString
& result
) const {
81 return get(tableKey
, NULL
, itemKey
, result
);
84 inline UnicodeString
&
85 ICUDataTable::getNoFallback(const char* tableKey
, const char* itemKey
, UnicodeString
& result
) const {
86 return getNoFallback(tableKey
, NULL
, itemKey
, result
);
89 ICUDataTable::ICUDataTable(const char* path
, const Locale
& locale
)
90 : path(NULL
), locale(Locale::getRoot())
93 int32_t len
= uprv_strlen(path
);
94 this->path
= (const char*) uprv_malloc(len
+ 1);
96 uprv_strcpy((char *)this->path
, path
);
97 this->locale
= locale
;
102 ICUDataTable::~ICUDataTable() {
104 uprv_free((void*) path
);
110 ICUDataTable::getLocale() {
115 ICUDataTable::get(const char* tableKey
, const char* subTableKey
, const char* itemKey
,
116 UnicodeString
&result
) const {
117 UErrorCode status
= U_ZERO_ERROR
;
120 const UChar
*s
= uloc_getTableStringWithFallback(path
, locale
.getName(),
121 tableKey
, subTableKey
, itemKey
,
123 if (U_SUCCESS(status
)) {
124 return result
.setTo(s
, len
);
126 return result
.setTo(UnicodeString(itemKey
, -1, US_INV
));
130 ICUDataTable::getNoFallback(const char* tableKey
, const char* subTableKey
, const char* itemKey
,
131 UnicodeString
& result
) const {
132 UErrorCode status
= U_ZERO_ERROR
;
135 const UChar
*s
= uloc_getTableStringWithFallback(path
, locale
.getName(),
136 tableKey
, subTableKey
, itemKey
,
138 if (U_SUCCESS(status
)) {
139 return result
.setTo(s
, len
);
146 ////////////////////////////////////////////////////////////////////////////////////////////////////
148 UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(LocaleDisplayNames
)
150 ////////////////////////////////////////////////////////////////////////////////////////////////////
152 #if 0 // currently unused
154 class DefaultLocaleDisplayNames
: public LocaleDisplayNames
{
155 UDialectHandling dialectHandling
;
159 DefaultLocaleDisplayNames(UDialectHandling dialectHandling
);
161 virtual ~DefaultLocaleDisplayNames();
163 virtual const Locale
& getLocale() const;
164 virtual UDialectHandling
getDialectHandling() const;
165 virtual UnicodeString
& localeDisplayName(const Locale
& locale
,
166 UnicodeString
& result
) const;
167 virtual UnicodeString
& localeDisplayName(const char* localeId
,
168 UnicodeString
& result
) const;
169 virtual UnicodeString
& languageDisplayName(const char* lang
,
170 UnicodeString
& result
) const;
171 virtual UnicodeString
& scriptDisplayName(const char* script
,
172 UnicodeString
& result
) const;
173 virtual UnicodeString
& scriptDisplayName(UScriptCode scriptCode
,
174 UnicodeString
& result
) const;
175 virtual UnicodeString
& regionDisplayName(const char* region
,
176 UnicodeString
& result
) const;
177 virtual UnicodeString
& variantDisplayName(const char* variant
,
178 UnicodeString
& result
) const;
179 virtual UnicodeString
& keyDisplayName(const char* key
,
180 UnicodeString
& result
) const;
181 virtual UnicodeString
& keyValueDisplayName(const char* key
,
183 UnicodeString
& result
) const;
186 DefaultLocaleDisplayNames::DefaultLocaleDisplayNames(UDialectHandling dialectHandling
)
187 : dialectHandling(dialectHandling
) {
190 DefaultLocaleDisplayNames::~DefaultLocaleDisplayNames() {
194 DefaultLocaleDisplayNames::getLocale() const {
195 return Locale::getRoot();
199 DefaultLocaleDisplayNames::getDialectHandling() const {
200 return dialectHandling
;
204 DefaultLocaleDisplayNames::localeDisplayName(const Locale
& locale
,
205 UnicodeString
& result
) const {
206 return result
= UnicodeString(locale
.getName(), -1, US_INV
);
210 DefaultLocaleDisplayNames::localeDisplayName(const char* localeId
,
211 UnicodeString
& result
) const {
212 return result
= UnicodeString(localeId
, -1, US_INV
);
216 DefaultLocaleDisplayNames::languageDisplayName(const char* lang
,
217 UnicodeString
& result
) const {
218 return result
= UnicodeString(lang
, -1, US_INV
);
222 DefaultLocaleDisplayNames::scriptDisplayName(const char* script
,
223 UnicodeString
& result
) const {
224 return result
= UnicodeString(script
, -1, US_INV
);
228 DefaultLocaleDisplayNames::scriptDisplayName(UScriptCode scriptCode
,
229 UnicodeString
& result
) const {
230 const char* name
= uscript_getName(scriptCode
);
232 return result
= UnicodeString(name
, -1, US_INV
);
234 return result
.remove();
238 DefaultLocaleDisplayNames::regionDisplayName(const char* region
,
239 UnicodeString
& result
) const {
240 return result
= UnicodeString(region
, -1, US_INV
);
244 DefaultLocaleDisplayNames::variantDisplayName(const char* variant
,
245 UnicodeString
& result
) const {
246 return result
= UnicodeString(variant
, -1, US_INV
);
250 DefaultLocaleDisplayNames::keyDisplayName(const char* key
,
251 UnicodeString
& result
) const {
252 return result
= UnicodeString(key
, -1, US_INV
);
256 DefaultLocaleDisplayNames::keyValueDisplayName(const char* /* key */,
258 UnicodeString
& result
) const {
259 return result
= UnicodeString(value
, -1, US_INV
);
262 #endif // currently unused class DefaultLocaleDisplayNames
264 ////////////////////////////////////////////////////////////////////////////////////////////////////
266 class LocaleDisplayNamesImpl
: public LocaleDisplayNames
{
268 UDialectHandling dialectHandling
;
269 ICUDataTable langData
;
270 ICUDataTable regionData
;
272 MessageFormat
*format
;
276 LocaleDisplayNamesImpl(const Locale
& locale
, UDialectHandling dialectHandling
);
277 virtual ~LocaleDisplayNamesImpl();
279 virtual const Locale
& getLocale() const;
280 virtual UDialectHandling
getDialectHandling() const;
282 virtual UnicodeString
& localeDisplayName(const Locale
& locale
,
283 UnicodeString
& result
) const;
284 virtual UnicodeString
& localeDisplayName(const char* localeId
,
285 UnicodeString
& result
) const;
286 virtual UnicodeString
& languageDisplayName(const char* lang
,
287 UnicodeString
& result
) const;
288 virtual UnicodeString
& scriptDisplayName(const char* script
,
289 UnicodeString
& result
) const;
290 virtual UnicodeString
& scriptDisplayName(UScriptCode scriptCode
,
291 UnicodeString
& result
) const;
292 virtual UnicodeString
& regionDisplayName(const char* region
,
293 UnicodeString
& result
) const;
294 virtual UnicodeString
& variantDisplayName(const char* variant
,
295 UnicodeString
& result
) const;
296 virtual UnicodeString
& keyDisplayName(const char* key
,
297 UnicodeString
& result
) const;
298 virtual UnicodeString
& keyValueDisplayName(const char* key
,
300 UnicodeString
& result
) const;
302 UnicodeString
& localeIdName(const char* localeId
,
303 UnicodeString
& result
) const;
304 UnicodeString
& appendWithSep(UnicodeString
& buffer
, const UnicodeString
& src
) const;
307 LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale
& locale
,
308 UDialectHandling dialectHandling
)
309 : dialectHandling(dialectHandling
)
310 , langData(U_ICUDATA_LANG
, locale
)
311 , regionData(U_ICUDATA_REGION
, locale
)
314 LocaleDisplayNamesImpl
*nonConstThis
= (LocaleDisplayNamesImpl
*)this;
315 nonConstThis
->locale
= langData
.getLocale() == Locale::getRoot()
316 ? regionData
.getLocale()
317 : langData
.getLocale();
319 langData
.getNoFallback("localeDisplayPattern", "separator", sep
);
321 sep
= UnicodeString(", ", -1, US_INV
);
324 UnicodeString pattern
;
325 langData
.getNoFallback("localeDisplayPattern", "pattern", pattern
);
326 if (pattern
.isBogus()) {
327 pattern
= UnicodeString("{0} ({1})", -1, US_INV
);
329 UErrorCode status
= U_ZERO_ERROR
;
330 format
= new MessageFormat(pattern
, status
);
333 LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() {
338 LocaleDisplayNamesImpl::getLocale() const {
343 LocaleDisplayNamesImpl::getDialectHandling() const {
344 return dialectHandling
;
348 LocaleDisplayNamesImpl::localeDisplayName(const Locale
& locale
,
349 UnicodeString
& result
) const {
350 UnicodeString resultName
;
352 const char* lang
= locale
.getLanguage();
353 if (uprv_strlen(lang
) == 0) {
356 const char* script
= locale
.getScript();
357 const char* country
= locale
.getCountry();
358 const char* variant
= locale
.getVariant();
360 UBool hasScript
= uprv_strlen(script
) > 0;
361 UBool hasCountry
= uprv_strlen(country
) > 0;
362 UBool hasVariant
= uprv_strlen(variant
) > 0;
364 if (dialectHandling
== ULDN_DIALECT_NAMES
) {
365 char buffer
[ULOC_FULLNAME_CAPACITY
];
366 do { // loop construct is so we can break early out of search
367 if (hasScript
&& hasCountry
) {
368 ncat(buffer
, ULOC_FULLNAME_CAPACITY
, lang
, "_", script
, "_", country
, (char *)0);
369 localeIdName(buffer
, resultName
);
370 if (!resultName
.isBogus()) {
377 ncat(buffer
, ULOC_FULLNAME_CAPACITY
, lang
, "_", script
, (char *)0);
378 localeIdName(buffer
, resultName
);
379 if (!resultName
.isBogus()) {
385 ncat(buffer
, ULOC_FULLNAME_CAPACITY
, lang
, "_", country
, (char*)0);
386 localeIdName(buffer
, resultName
);
387 if (!resultName
.isBogus()) {
394 if (resultName
.isBogus() || resultName
.isEmpty()) {
395 localeIdName(lang
, resultName
);
398 UnicodeString resultRemainder
;
400 StringEnumeration
*e
= NULL
;
401 UErrorCode status
= U_ZERO_ERROR
;
404 resultRemainder
.append(scriptDisplayName(script
, temp
));
407 appendWithSep(resultRemainder
, regionDisplayName(country
, temp
));
410 appendWithSep(resultRemainder
, variantDisplayName(variant
, temp
));
413 e
= locale
.createKeywords(status
);
414 if (e
&& U_SUCCESS(status
)) {
416 char value
[ULOC_KEYWORD_AND_VALUES_CAPACITY
]; // sigh, no ULOC_VALUE_CAPACITY
418 while ((key
= e
->next((int32_t *)0, status
)) != NULL
) {
419 locale
.getKeywordValue(key
, value
, ULOC_KEYWORD_AND_VALUES_CAPACITY
, status
);
420 appendWithSep(resultRemainder
, keyDisplayName(key
, temp
))
422 .append(keyValueDisplayName(key
, value
, temp2
));
427 if (!resultRemainder
.isEmpty()) {
428 Formattable data
[] = {
433 status
= U_ZERO_ERROR
;
434 format
->format(data
, 2, result
, fpos
, status
);
438 return result
= resultName
;
442 LocaleDisplayNamesImpl::appendWithSep(UnicodeString
& buffer
, const UnicodeString
& src
) const {
443 if (!buffer
.isEmpty()) {
451 LocaleDisplayNamesImpl::localeDisplayName(const char* localeId
,
452 UnicodeString
& result
) const {
453 return localeDisplayName(Locale(localeId
), result
);
457 LocaleDisplayNamesImpl::localeIdName(const char* localeId
,
458 UnicodeString
& result
) const {
459 return langData
.getNoFallback("Languages", localeId
, result
);
463 LocaleDisplayNamesImpl::languageDisplayName(const char* lang
,
464 UnicodeString
& result
) const {
465 if (uprv_strcmp("root", lang
) == 0 || uprv_strchr(lang
, '_') != NULL
) {
466 return result
= UnicodeString(lang
, -1, US_INV
);
468 return langData
.get("Languages", lang
, result
);
472 LocaleDisplayNamesImpl::scriptDisplayName(const char* script
,
473 UnicodeString
& result
) const {
474 return langData
.get("Scripts", script
, result
);
478 LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode
,
479 UnicodeString
& result
) const {
480 const char* name
= uscript_getName(scriptCode
);
481 return langData
.get("Scripts", name
, result
);
485 LocaleDisplayNamesImpl::regionDisplayName(const char* region
,
486 UnicodeString
& result
) const {
487 return regionData
.get("Countries", region
, result
);
491 LocaleDisplayNamesImpl::variantDisplayName(const char* variant
,
492 UnicodeString
& result
) const {
493 return langData
.get("Variants", variant
, result
);
497 LocaleDisplayNamesImpl::keyDisplayName(const char* key
,
498 UnicodeString
& result
) const {
499 return langData
.get("Keys", key
, result
);
503 LocaleDisplayNamesImpl::keyValueDisplayName(const char* key
,
505 UnicodeString
& result
) const {
506 return langData
.get("Types", key
, value
, result
);
509 ////////////////////////////////////////////////////////////////////////////////////////////////////
512 LocaleDisplayNames::createInstance(const Locale
& locale
,
513 UDialectHandling dialectHandling
) {
514 return new LocaleDisplayNamesImpl(locale
, dialectHandling
);
519 ////////////////////////////////////////////////////////////////////////////////////////////////////
523 U_DRAFT ULocaleDisplayNames
* U_EXPORT2
524 uldn_open(const char * locale
,
525 UDialectHandling dialectHandling
,
526 UErrorCode
*pErrorCode
) {
527 if (U_FAILURE(*pErrorCode
)) {
530 if (locale
== NULL
) {
531 locale
= uloc_getDefault();
533 return (ULocaleDisplayNames
*)LocaleDisplayNames::createInstance(Locale(locale
), dialectHandling
);
536 U_DRAFT
void U_EXPORT2
537 uldn_close(ULocaleDisplayNames
*ldn
) {
538 delete (LocaleDisplayNames
*)ldn
;
541 U_DRAFT
const char * U_EXPORT2
542 uldn_getLocale(const ULocaleDisplayNames
*ldn
) {
544 return ((const LocaleDisplayNames
*)ldn
)->getLocale().getName();
549 U_DRAFT UDialectHandling U_EXPORT2
550 uldn_getDialectHandling(const ULocaleDisplayNames
*ldn
) {
552 return ((const LocaleDisplayNames
*)ldn
)->getDialectHandling();
554 return ULDN_STANDARD_NAMES
;
557 U_DRAFT
int32_t U_EXPORT2
558 uldn_localeDisplayName(const ULocaleDisplayNames
*ldn
,
561 int32_t maxResultSize
,
562 UErrorCode
*pErrorCode
) {
563 if (U_FAILURE(*pErrorCode
)) {
566 if (ldn
== NULL
|| locale
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
567 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
570 UnicodeString
temp(result
, 0, maxResultSize
);
571 ((const LocaleDisplayNames
*)ldn
)->localeDisplayName(locale
, temp
);
572 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
575 U_DRAFT
int32_t U_EXPORT2
576 uldn_languageDisplayName(const ULocaleDisplayNames
*ldn
,
579 int32_t maxResultSize
,
580 UErrorCode
*pErrorCode
) {
581 if (U_FAILURE(*pErrorCode
)) {
584 if (ldn
== NULL
|| lang
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
585 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
588 UnicodeString
temp(result
, 0, maxResultSize
);
589 ((const LocaleDisplayNames
*)ldn
)->languageDisplayName(lang
, temp
);
590 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
593 U_DRAFT
int32_t U_EXPORT2
594 uldn_scriptDisplayName(const ULocaleDisplayNames
*ldn
,
597 int32_t maxResultSize
,
598 UErrorCode
*pErrorCode
) {
599 if (U_FAILURE(*pErrorCode
)) {
602 if (ldn
== NULL
|| script
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
603 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
606 UnicodeString
temp(result
, 0, maxResultSize
);
607 ((const LocaleDisplayNames
*)ldn
)->scriptDisplayName(script
, temp
);
608 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
611 U_DRAFT
int32_t U_EXPORT2
612 uldn_scriptCodeDisplayName(const ULocaleDisplayNames
*ldn
,
613 UScriptCode scriptCode
,
615 int32_t maxResultSize
,
616 UErrorCode
*pErrorCode
) {
617 return uldn_scriptDisplayName(ldn
, uscript_getName(scriptCode
), result
, maxResultSize
, pErrorCode
);
620 U_DRAFT
int32_t U_EXPORT2
621 uldn_regionDisplayName(const ULocaleDisplayNames
*ldn
,
624 int32_t maxResultSize
,
625 UErrorCode
*pErrorCode
) {
626 if (U_FAILURE(*pErrorCode
)) {
629 if (ldn
== NULL
|| region
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
630 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
633 UnicodeString
temp(result
, 0, maxResultSize
);
634 ((const LocaleDisplayNames
*)ldn
)->regionDisplayName(region
, temp
);
635 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
638 U_DRAFT
int32_t U_EXPORT2
639 uldn_variantDisplayName(const ULocaleDisplayNames
*ldn
,
642 int32_t maxResultSize
,
643 UErrorCode
*pErrorCode
) {
644 if (U_FAILURE(*pErrorCode
)) {
647 if (ldn
== NULL
|| variant
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
648 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
651 UnicodeString
temp(result
, 0, maxResultSize
);
652 ((const LocaleDisplayNames
*)ldn
)->variantDisplayName(variant
, temp
);
653 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
656 U_DRAFT
int32_t U_EXPORT2
657 uldn_keyDisplayName(const ULocaleDisplayNames
*ldn
,
660 int32_t maxResultSize
,
661 UErrorCode
*pErrorCode
) {
662 if (U_FAILURE(*pErrorCode
)) {
665 if (ldn
== NULL
|| key
== NULL
|| (result
== NULL
&& maxResultSize
> 0) || maxResultSize
< 0) {
666 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
669 UnicodeString
temp(result
, 0, maxResultSize
);
670 ((const LocaleDisplayNames
*)ldn
)->keyDisplayName(key
, temp
);
671 return temp
.extract(result
, maxResultSize
, *pErrorCode
);
674 U_DRAFT
int32_t U_EXPORT2
675 uldn_keyValueDisplayName(const ULocaleDisplayNames
*ldn
,
679 int32_t maxResultSize
,
680 UErrorCode
*pErrorCode
) {
681 if (U_FAILURE(*pErrorCode
)) {
684 if (ldn
== NULL
|| key
== NULL
|| value
== NULL
|| (result
== NULL
&& maxResultSize
> 0)
685 || maxResultSize
< 0) {
686 *pErrorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
689 UnicodeString
temp(result
, 0, maxResultSize
);
690 ((const LocaleDisplayNames
*)ldn
)->keyValueDisplayName(key
, value
, temp
);
691 return temp
.extract(result
, maxResultSize
, *pErrorCode
);