Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2010-2011, International Business Machines Corporation and
      4 * others. All Rights Reserved.
      5 *******************************************************************************
      6 */
      7 
      8 #include "unicode/utypes.h"
      9 
     10 #if !UCONFIG_NO_FORMATTING
     11 
     12 #include "unicode/locdspnm.h"
     13 
     14 #include "unicode/msgfmt.h"
     15 
     16 #include "cmemory.h"
     17 #include "cstring.h"
     18 #include "ulocimp.h"
     19 #include "ureslocs.h"
     20 
     21 #include <stdarg.h>
     22 
     23 /**
     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).
     28  */
     29 static int32_t ncat(char *buffer, uint32_t buflen, ...) {
     30   va_list args;
     31   char *str;
     32   char *p = buffer;
     33   const char* e = buffer + buflen - 1;
     34 
     35   if (buffer == NULL || buflen < 1) {
     36     return -1;
     37   }
     38 
     39   va_start(args, buflen);
     40   while ((str = va_arg(args, char *))) {
     41     char c;
     42     while (p != e && (c = *str++)) {
     43       *p++ = c;
     44     }
     45   }
     46   *p = 0;
     47   va_end(args);
     48 
     49   return p - buffer;
     50 }
     51 
     52 U_NAMESPACE_BEGIN
     53 
     54 ////////////////////////////////////////////////////////////////////////////////////////////////////
     55 
     56 // Access resource data for locale components.
     57 // Wrap code in uloc.c for now.
     58 class ICUDataTable {
     59   const char* path;
     60   Locale locale;
     61 
     62 public:
     63   ICUDataTable(const char* path, const Locale& locale);
     64   ~ICUDataTable();
     65 
     66   const Locale& getLocale();
     67 
     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;
     72 
     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;
     77 };
     78 
     79 inline UnicodeString &
     80 ICUDataTable::get(const char* tableKey, const char* itemKey, UnicodeString& result) const {
     81   return get(tableKey, NULL, itemKey, result);
     82 }
     83 
     84 inline UnicodeString &
     85 ICUDataTable::getNoFallback(const char* tableKey, const char* itemKey, UnicodeString& result) const {
     86   return getNoFallback(tableKey, NULL, itemKey, result);
     87 }
     88 
     89 ICUDataTable::ICUDataTable(const char* path, const Locale& locale)
     90   : path(NULL), locale(Locale::getRoot())
     91 {
     92   if (path) {
     93     int32_t len = uprv_strlen(path);
     94     this->path = (const char*) uprv_malloc(len + 1);
     95     if (this->path) {
     96       uprv_strcpy((char *)this->path, path);
     97       this->locale = locale;
     98     }
     99   }
    100 }
    101 
    102 ICUDataTable::~ICUDataTable() {
    103   if (path) {
    104     uprv_free((void*) path);
    105     path = NULL;
    106   }
    107 }
    108 
    109 const Locale&
    110 ICUDataTable::getLocale() {
    111   return locale;
    112 }
    113 
    114 UnicodeString &
    115 ICUDataTable::get(const char* tableKey, const char* subTableKey, const char* itemKey,
    116                   UnicodeString &result) const {
    117   UErrorCode status = U_ZERO_ERROR;
    118   int32_t len = 0;
    119 
    120   const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(),
    121                                                    tableKey, subTableKey, itemKey,
    122                                                    &len, &status);
    123   if (U_SUCCESS(status) && len > 0) {
    124     return result.setTo(s, len);
    125   }
    126   return result.setTo(UnicodeString(itemKey, -1, US_INV));
    127 }
    128 
    129 UnicodeString &
    130 ICUDataTable::getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey,
    131                             UnicodeString& result) const {
    132   UErrorCode status = U_ZERO_ERROR;
    133   int32_t len = 0;
    134 
    135   const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(),
    136                                                    tableKey, subTableKey, itemKey,
    137                                                    &len, &status);
    138   if (U_SUCCESS(status)) {
    139     return result.setTo(s, len);
    140   }
    141 
    142   result.setToBogus();
    143   return result;
    144 }
    145 
    146 ////////////////////////////////////////////////////////////////////////////////////////////////////
    147 
    148 UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(LocaleDisplayNames)
    149 
    150 ////////////////////////////////////////////////////////////////////////////////////////////////////
    151 
    152 #if 0  // currently unused
    153 
    154 class DefaultLocaleDisplayNames : public LocaleDisplayNames {
    155   UDialectHandling dialectHandling;
    156 
    157 public:
    158   // constructor
    159   DefaultLocaleDisplayNames(UDialectHandling dialectHandling);
    160 
    161   virtual ~DefaultLocaleDisplayNames();
    162 
    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,
    182                                              const char* value,
    183                                              UnicodeString& result) const;
    184 };
    185 
    186 DefaultLocaleDisplayNames::DefaultLocaleDisplayNames(UDialectHandling dialectHandling)
    187     : dialectHandling(dialectHandling) {
    188 }
    189 
    190 DefaultLocaleDisplayNames::~DefaultLocaleDisplayNames() {
    191 }
    192 
    193 const Locale&
    194 DefaultLocaleDisplayNames::getLocale() const {
    195   return Locale::getRoot();
    196 }
    197 
    198 UDialectHandling
    199 DefaultLocaleDisplayNames::getDialectHandling() const {
    200   return dialectHandling;
    201 }
    202 
    203 UnicodeString&
    204 DefaultLocaleDisplayNames::localeDisplayName(const Locale& locale,
    205                                              UnicodeString& result) const {
    206   return result = UnicodeString(locale.getName(), -1, US_INV);
    207 }
    208 
    209 UnicodeString&
    210 DefaultLocaleDisplayNames::localeDisplayName(const char* localeId,
    211                                              UnicodeString& result) const {
    212   return result = UnicodeString(localeId, -1, US_INV);
    213 }
    214 
    215 UnicodeString&
    216 DefaultLocaleDisplayNames::languageDisplayName(const char* lang,
    217                                                UnicodeString& result) const {
    218   return result = UnicodeString(lang, -1, US_INV);
    219 }
    220 
    221 UnicodeString&
    222 DefaultLocaleDisplayNames::scriptDisplayName(const char* script,
    223                                              UnicodeString& result) const {
    224   return result = UnicodeString(script, -1, US_INV);
    225 }
    226 
    227 UnicodeString&
    228 DefaultLocaleDisplayNames::scriptDisplayName(UScriptCode scriptCode,
    229                                              UnicodeString& result) const {
    230   const char* name = uscript_getName(scriptCode);
    231   if (name) {
    232     return result = UnicodeString(name, -1, US_INV);
    233   }
    234   return result.remove();
    235 }
    236 
    237 UnicodeString&
    238 DefaultLocaleDisplayNames::regionDisplayName(const char* region,
    239                                              UnicodeString& result) const {
    240   return result = UnicodeString(region, -1, US_INV);
    241 }
    242 
    243 UnicodeString&
    244 DefaultLocaleDisplayNames::variantDisplayName(const char* variant,
    245                                               UnicodeString& result) const {
    246   return result = UnicodeString(variant, -1, US_INV);
    247 }
    248 
    249 UnicodeString&
    250 DefaultLocaleDisplayNames::keyDisplayName(const char* key,
    251                                           UnicodeString& result) const {
    252   return result = UnicodeString(key, -1, US_INV);
    253 }
    254 
    255 UnicodeString&
    256 DefaultLocaleDisplayNames::keyValueDisplayName(const char* /* key */,
    257                                                const char* value,
    258                                                UnicodeString& result) const {
    259   return result = UnicodeString(value, -1, US_INV);
    260 }
    261 
    262 #endif  // currently unused class DefaultLocaleDisplayNames
    263 
    264 ////////////////////////////////////////////////////////////////////////////////////////////////////
    265 
    266 class LocaleDisplayNamesImpl : public LocaleDisplayNames {
    267   Locale locale;
    268   UDialectHandling dialectHandling;
    269   ICUDataTable langData;
    270   ICUDataTable regionData;
    271   UnicodeString sep;
    272   MessageFormat *format;
    273 
    274 public:
    275   // constructor
    276   LocaleDisplayNamesImpl(const Locale& locale, UDialectHandling dialectHandling);
    277   virtual ~LocaleDisplayNamesImpl();
    278 
    279   virtual const Locale& getLocale() const;
    280   virtual UDialectHandling getDialectHandling() const;
    281 
    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,
    299                                              const char* value,
    300                                              UnicodeString& result) const;
    301 private:
    302   UnicodeString& localeIdName(const char* localeId,
    303                               UnicodeString& result) const;
    304   UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const;
    305 };
    306 
    307 LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
    308                                                UDialectHandling dialectHandling)
    309   : dialectHandling(dialectHandling)
    310   , langData(U_ICUDATA_LANG, locale)
    311   , regionData(U_ICUDATA_REGION, locale)
    312   , format(NULL)
    313 {
    314   LocaleDisplayNamesImpl *nonConstThis = (LocaleDisplayNamesImpl *)this;
    315   nonConstThis->locale = langData.getLocale() == Locale::getRoot()
    316     ? regionData.getLocale()
    317     : langData.getLocale();
    318 
    319   langData.getNoFallback("localeDisplayPattern", "separator", sep);
    320   if (sep.isBogus()) {
    321     sep = UnicodeString(", ", -1, US_INV);
    322   }
    323 
    324   UnicodeString pattern;
    325   langData.getNoFallback("localeDisplayPattern", "pattern", pattern);
    326   if (pattern.isBogus()) {
    327     pattern = UnicodeString("{0} ({1})", -1, US_INV);
    328   }
    329   UErrorCode status = U_ZERO_ERROR;
    330   format = new MessageFormat(pattern, status);
    331 }
    332 
    333 LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() {
    334   delete format;
    335 }
    336 
    337 const Locale&
    338 LocaleDisplayNamesImpl::getLocale() const {
    339   return locale;
    340 }
    341 
    342 UDialectHandling
    343 LocaleDisplayNamesImpl::getDialectHandling() const {
    344   return dialectHandling;
    345 }
    346 
    347 UnicodeString&
    348 LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale,
    349                                           UnicodeString& result) const {
    350   UnicodeString resultName;
    351 
    352   const char* lang = locale.getLanguage();
    353   if (uprv_strlen(lang) == 0) {
    354     lang = "root";
    355   }
    356   const char* script = locale.getScript();
    357   const char* country = locale.getCountry();
    358   const char* variant = locale.getVariant();
    359 
    360   UBool hasScript = uprv_strlen(script) > 0;
    361   UBool hasCountry = uprv_strlen(country) > 0;
    362   UBool hasVariant = uprv_strlen(variant) > 0;
    363 
    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()) {
    371           hasScript = FALSE;
    372           hasCountry = FALSE;
    373           break;
    374         }
    375       }
    376       if (hasScript) {
    377         ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0);
    378         localeIdName(buffer, resultName);
    379         if (!resultName.isBogus()) {
    380           hasScript = FALSE;
    381           break;
    382         }
    383       }
    384       if (hasCountry) {
    385         ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0);
    386         localeIdName(buffer, resultName);
    387         if (!resultName.isBogus()) {
    388           hasCountry = FALSE;
    389           break;
    390         }
    391       }
    392     } while (FALSE);
    393   }
    394   if (resultName.isBogus() || resultName.isEmpty()) {
    395     localeIdName(lang, resultName);
    396   }
    397 
    398   UnicodeString resultRemainder;
    399   UnicodeString temp;
    400   StringEnumeration *e = NULL;
    401   UErrorCode status = U_ZERO_ERROR;
    402 
    403   if (hasScript) {
    404     resultRemainder.append(scriptDisplayName(script, temp));
    405   }
    406   if (hasCountry) {
    407     appendWithSep(resultRemainder, regionDisplayName(country, temp));
    408   }
    409   if (hasVariant) {
    410     appendWithSep(resultRemainder, variantDisplayName(variant, temp));
    411   }
    412 
    413   e = locale.createKeywords(status);
    414   if (e && U_SUCCESS(status)) {
    415     UnicodeString temp2;
    416     char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY
    417     const char* key;
    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))
    421           .append((UChar)0x3d /* = */)
    422           .append(keyValueDisplayName(key, value, temp2));
    423     }
    424     delete e;
    425   }
    426 
    427   if (!resultRemainder.isEmpty()) {
    428     Formattable data[] = {
    429       resultName,
    430       resultRemainder
    431     };
    432     FieldPosition fpos;
    433     status = U_ZERO_ERROR;
    434     format->format(data, 2, result, fpos, status);
    435     return result;
    436   }
    437 
    438   return result = resultName;
    439 }
    440 
    441 UnicodeString&
    442 LocaleDisplayNamesImpl::appendWithSep(UnicodeString& buffer, const UnicodeString& src) const {
    443   if (!buffer.isEmpty()) {
    444     buffer.append(sep);
    445   }
    446   buffer.append(src);
    447   return buffer;
    448 }
    449 
    450 UnicodeString&
    451 LocaleDisplayNamesImpl::localeDisplayName(const char* localeId,
    452                                           UnicodeString& result) const {
    453   return localeDisplayName(Locale(localeId), result);
    454 }
    455 
    456 UnicodeString&
    457 LocaleDisplayNamesImpl::localeIdName(const char* localeId,
    458                                      UnicodeString& result) const {
    459   return langData.getNoFallback("Languages", localeId, result);
    460 }
    461 
    462 UnicodeString&
    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);
    467   }
    468   return langData.get("Languages", lang, result);
    469 }
    470 
    471 UnicodeString&
    472 LocaleDisplayNamesImpl::scriptDisplayName(const char* script,
    473                                           UnicodeString& result) const {
    474   return langData.get("Scripts", script, result);
    475 }
    476 
    477 UnicodeString&
    478 LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode,
    479                                           UnicodeString& result) const {
    480   const char* name = uscript_getName(scriptCode);
    481   return langData.get("Scripts", name, result);
    482 }
    483 
    484 UnicodeString&
    485 LocaleDisplayNamesImpl::regionDisplayName(const char* region,
    486                                           UnicodeString& result) const {
    487   return regionData.get("Countries", region, result);
    488 }
    489 
    490 UnicodeString&
    491 LocaleDisplayNamesImpl::variantDisplayName(const char* variant,
    492                                            UnicodeString& result) const {
    493   return langData.get("Variants", variant, result);
    494 }
    495 
    496 UnicodeString&
    497 LocaleDisplayNamesImpl::keyDisplayName(const char* key,
    498                                        UnicodeString& result) const {
    499   return langData.get("Keys", key, result);
    500 }
    501 
    502 UnicodeString&
    503 LocaleDisplayNamesImpl::keyValueDisplayName(const char* key,
    504                                             const char* value,
    505                                             UnicodeString& result) const {
    506   return langData.get("Types", key, value, result);
    507 }
    508 
    509 ////////////////////////////////////////////////////////////////////////////////////////////////////
    510 
    511 LocaleDisplayNames*
    512 LocaleDisplayNames::createInstance(const Locale& locale,
    513                                    UDialectHandling dialectHandling) {
    514   return new LocaleDisplayNamesImpl(locale, dialectHandling);
    515 }
    516 
    517 U_NAMESPACE_END
    518 
    519 ////////////////////////////////////////////////////////////////////////////////////////////////////
    520 
    521 U_NAMESPACE_USE
    522 
    523 U_DRAFT ULocaleDisplayNames * U_EXPORT2
    524 uldn_open(const char * locale,
    525           UDialectHandling dialectHandling,
    526           UErrorCode *pErrorCode) {
    527   if (U_FAILURE(*pErrorCode)) {
    528     return 0;
    529   }
    530   if (locale == NULL) {
    531     locale = uloc_getDefault();
    532   }
    533   return (ULocaleDisplayNames *)LocaleDisplayNames::createInstance(Locale(locale), dialectHandling);
    534 }
    535 
    536 U_DRAFT void U_EXPORT2
    537 uldn_close(ULocaleDisplayNames *ldn) {
    538   delete (LocaleDisplayNames *)ldn;
    539 }
    540 
    541 U_DRAFT const char * U_EXPORT2
    542 uldn_getLocale(const ULocaleDisplayNames *ldn) {
    543   if (ldn) {
    544     return ((const LocaleDisplayNames *)ldn)->getLocale().getName();
    545   }
    546   return NULL;
    547 }
    548 
    549 U_DRAFT UDialectHandling U_EXPORT2
    550 uldn_getDialectHandling(const ULocaleDisplayNames *ldn) {
    551   if (ldn) {
    552     return ((const LocaleDisplayNames *)ldn)->getDialectHandling();
    553   }
    554   return ULDN_STANDARD_NAMES;
    555 }
    556 
    557 U_DRAFT int32_t U_EXPORT2
    558 uldn_localeDisplayName(const ULocaleDisplayNames *ldn,
    559                        const char *locale,
    560                        UChar *result,
    561                        int32_t maxResultSize,
    562                        UErrorCode *pErrorCode) {
    563   if (U_FAILURE(*pErrorCode)) {
    564     return 0;
    565   }
    566   if (ldn == NULL || locale == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    567     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    568     return 0;
    569   }
    570   UnicodeString temp(result, 0, maxResultSize);
    571   ((const LocaleDisplayNames *)ldn)->localeDisplayName(locale, temp);
    572   return temp.extract(result, maxResultSize, *pErrorCode);
    573 }
    574 
    575 U_DRAFT int32_t U_EXPORT2
    576 uldn_languageDisplayName(const ULocaleDisplayNames *ldn,
    577                          const char *lang,
    578                          UChar *result,
    579                          int32_t maxResultSize,
    580                          UErrorCode *pErrorCode) {
    581   if (U_FAILURE(*pErrorCode)) {
    582     return 0;
    583   }
    584   if (ldn == NULL || lang == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    585     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    586     return 0;
    587   }
    588   UnicodeString temp(result, 0, maxResultSize);
    589   ((const LocaleDisplayNames *)ldn)->languageDisplayName(lang, temp);
    590   return temp.extract(result, maxResultSize, *pErrorCode);
    591 }
    592 
    593 U_DRAFT int32_t U_EXPORT2
    594 uldn_scriptDisplayName(const ULocaleDisplayNames *ldn,
    595                        const char *script,
    596                        UChar *result,
    597                        int32_t maxResultSize,
    598                        UErrorCode *pErrorCode) {
    599   if (U_FAILURE(*pErrorCode)) {
    600     return 0;
    601   }
    602   if (ldn == NULL || script == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    603     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    604     return 0;
    605   }
    606   UnicodeString temp(result, 0, maxResultSize);
    607   ((const LocaleDisplayNames *)ldn)->scriptDisplayName(script, temp);
    608   return temp.extract(result, maxResultSize, *pErrorCode);
    609 }
    610 
    611 U_DRAFT int32_t U_EXPORT2
    612 uldn_scriptCodeDisplayName(const ULocaleDisplayNames *ldn,
    613                            UScriptCode scriptCode,
    614                            UChar *result,
    615                            int32_t maxResultSize,
    616                            UErrorCode *pErrorCode) {
    617   return uldn_scriptDisplayName(ldn, uscript_getName(scriptCode), result, maxResultSize, pErrorCode);
    618 }
    619 
    620 U_DRAFT int32_t U_EXPORT2
    621 uldn_regionDisplayName(const ULocaleDisplayNames *ldn,
    622                        const char *region,
    623                        UChar *result,
    624                        int32_t maxResultSize,
    625                        UErrorCode *pErrorCode) {
    626   if (U_FAILURE(*pErrorCode)) {
    627     return 0;
    628   }
    629   if (ldn == NULL || region == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    630     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    631     return 0;
    632   }
    633   UnicodeString temp(result, 0, maxResultSize);
    634   ((const LocaleDisplayNames *)ldn)->regionDisplayName(region, temp);
    635   return temp.extract(result, maxResultSize, *pErrorCode);
    636 }
    637 
    638 U_DRAFT int32_t U_EXPORT2
    639 uldn_variantDisplayName(const ULocaleDisplayNames *ldn,
    640                         const char *variant,
    641                         UChar *result,
    642                         int32_t maxResultSize,
    643                         UErrorCode *pErrorCode) {
    644   if (U_FAILURE(*pErrorCode)) {
    645     return 0;
    646   }
    647   if (ldn == NULL || variant == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    648     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    649     return 0;
    650   }
    651   UnicodeString temp(result, 0, maxResultSize);
    652   ((const LocaleDisplayNames *)ldn)->variantDisplayName(variant, temp);
    653   return temp.extract(result, maxResultSize, *pErrorCode);
    654 }
    655 
    656 U_DRAFT int32_t U_EXPORT2
    657 uldn_keyDisplayName(const ULocaleDisplayNames *ldn,
    658                     const char *key,
    659                     UChar *result,
    660                     int32_t maxResultSize,
    661                     UErrorCode *pErrorCode) {
    662   if (U_FAILURE(*pErrorCode)) {
    663     return 0;
    664   }
    665   if (ldn == NULL || key == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    666     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    667     return 0;
    668   }
    669   UnicodeString temp(result, 0, maxResultSize);
    670   ((const LocaleDisplayNames *)ldn)->keyDisplayName(key, temp);
    671   return temp.extract(result, maxResultSize, *pErrorCode);
    672 }
    673 
    674 U_DRAFT int32_t U_EXPORT2
    675 uldn_keyValueDisplayName(const ULocaleDisplayNames *ldn,
    676                          const char *key,
    677                          const char *value,
    678                          UChar *result,
    679                          int32_t maxResultSize,
    680                          UErrorCode *pErrorCode) {
    681   if (U_FAILURE(*pErrorCode)) {
    682     return 0;
    683   }
    684   if (ldn == NULL || key == NULL || value == NULL || (result == NULL && maxResultSize > 0)
    685       || maxResultSize < 0) {
    686     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    687     return 0;
    688   }
    689   UnicodeString temp(result, 0, maxResultSize);
    690   ((const LocaleDisplayNames *)ldn)->keyValueDisplayName(key, value, temp);
    691   return temp.extract(result, maxResultSize, *pErrorCode);
    692 }
    693 
    694 #endif
    695