Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2010, 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)) {
    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_ABSTRACT_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   static UClassID U_EXPORT2 getStaticClassID();
    302   virtual UClassID getDynamicClassID() const;
    303 private:
    304   UnicodeString& localeIdName(const char* localeId,
    305                               UnicodeString& result) const;
    306   UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const;
    307 };
    308 
    309 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocaleDisplayNamesImpl)
    310 
    311 LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
    312                                                UDialectHandling dialectHandling)
    313   : dialectHandling(dialectHandling)
    314   , langData(U_ICUDATA_LANG, locale)
    315   , regionData(U_ICUDATA_REGION, locale)
    316   , format(NULL)
    317 {
    318   LocaleDisplayNamesImpl *nonConstThis = (LocaleDisplayNamesImpl *)this;
    319   nonConstThis->locale = langData.getLocale() == Locale::getRoot()
    320     ? regionData.getLocale()
    321     : langData.getLocale();
    322 
    323   langData.getNoFallback("localeDisplayPattern", "separator", sep);
    324   if (sep.isBogus()) {
    325     sep = UnicodeString(", ", -1, US_INV);
    326   }
    327 
    328   UnicodeString pattern;
    329   langData.getNoFallback("localeDisplayPattern", "pattern", pattern);
    330   if (pattern.isBogus()) {
    331     pattern = UnicodeString("{0} ({1})", -1, US_INV);
    332   }
    333   UErrorCode status = U_ZERO_ERROR;
    334   format = new MessageFormat(pattern, status);
    335 }
    336 
    337 LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() {
    338   delete format;
    339 }
    340 
    341 const Locale&
    342 LocaleDisplayNamesImpl::getLocale() const {
    343   return locale;
    344 }
    345 
    346 UDialectHandling
    347 LocaleDisplayNamesImpl::getDialectHandling() const {
    348   return dialectHandling;
    349 }
    350 
    351 UnicodeString&
    352 LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale,
    353                                           UnicodeString& result) const {
    354   UnicodeString resultName;
    355 
    356   const char* lang = locale.getLanguage();
    357   if (uprv_strlen(lang) == 0) {
    358     lang = "root";
    359   }
    360   const char* script = locale.getScript();
    361   const char* country = locale.getCountry();
    362   const char* variant = locale.getVariant();
    363 
    364   UBool hasScript = uprv_strlen(script) > 0;
    365   UBool hasCountry = uprv_strlen(country) > 0;
    366   UBool hasVariant = uprv_strlen(variant) > 0;
    367 
    368   if (dialectHandling == ULDN_DIALECT_NAMES) {
    369     char buffer[ULOC_FULLNAME_CAPACITY];
    370     do { // loop construct is so we can break early out of search
    371       if (hasScript && hasCountry) {
    372         ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0);
    373         localeIdName(buffer, resultName);
    374         if (!resultName.isBogus()) {
    375           hasScript = FALSE;
    376           hasCountry = FALSE;
    377           break;
    378         }
    379       }
    380       if (hasScript) {
    381         ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0);
    382         localeIdName(buffer, resultName);
    383         if (!resultName.isBogus()) {
    384           hasScript = FALSE;
    385           break;
    386         }
    387       }
    388       if (hasCountry) {
    389         ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0);
    390         localeIdName(buffer, resultName);
    391         if (!resultName.isBogus()) {
    392           hasCountry = FALSE;
    393           break;
    394         }
    395       }
    396     } while (FALSE);
    397   }
    398   if (resultName.isBogus() || resultName.isEmpty()) {
    399     localeIdName(lang, resultName);
    400   }
    401 
    402   UnicodeString resultRemainder;
    403   UnicodeString temp;
    404   StringEnumeration *e = NULL;
    405   UErrorCode status = U_ZERO_ERROR;
    406 
    407   if (hasScript) {
    408     resultRemainder.append(scriptDisplayName(script, temp));
    409   }
    410   if (hasCountry) {
    411     appendWithSep(resultRemainder, regionDisplayName(country, temp));
    412   }
    413   if (hasVariant) {
    414     appendWithSep(resultRemainder, variantDisplayName(variant, temp));
    415   }
    416 
    417   e = locale.createKeywords(status);
    418   if (e && U_SUCCESS(status)) {
    419     UnicodeString temp2;
    420     char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY
    421     const char* key;
    422     while ((key = e->next((int32_t *)0, status)) != NULL) {
    423       locale.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status);
    424       appendWithSep(resultRemainder, keyDisplayName(key, temp))
    425           .append("=")
    426           .append(keyValueDisplayName(key, value, temp2));
    427     }
    428     delete e;
    429   }
    430 
    431   if (!resultRemainder.isEmpty()) {
    432     Formattable data[] = {
    433       resultName,
    434       resultRemainder
    435     };
    436     FieldPosition fpos;
    437     status = U_ZERO_ERROR;
    438     format->format(data, 2, result, fpos, status);
    439     return result;
    440   }
    441 
    442   return result = resultName;
    443 }
    444 
    445 UnicodeString&
    446 LocaleDisplayNamesImpl::appendWithSep(UnicodeString& buffer, const UnicodeString& src) const {
    447   if (!buffer.isEmpty()) {
    448     buffer.append(sep);
    449   }
    450   buffer.append(src);
    451   return buffer;
    452 }
    453 
    454 UnicodeString&
    455 LocaleDisplayNamesImpl::localeDisplayName(const char* localeId,
    456                                           UnicodeString& result) const {
    457   return localeDisplayName(Locale(localeId), result);
    458 }
    459 
    460 UnicodeString&
    461 LocaleDisplayNamesImpl::localeIdName(const char* localeId,
    462                                      UnicodeString& result) const {
    463   return langData.getNoFallback("Languages", localeId, result);
    464 }
    465 
    466 UnicodeString&
    467 LocaleDisplayNamesImpl::languageDisplayName(const char* lang,
    468                                             UnicodeString& result) const {
    469   if (uprv_strcmp("root", lang) == 0 || uprv_strchr(lang, '_') != NULL) {
    470     return result = UnicodeString(lang, -1, US_INV);
    471   }
    472   return langData.get("Languages", lang, result);
    473 }
    474 
    475 UnicodeString&
    476 LocaleDisplayNamesImpl::scriptDisplayName(const char* script,
    477                                           UnicodeString& result) const {
    478   return langData.get("Scripts", script, result);
    479 }
    480 
    481 UnicodeString&
    482 LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode,
    483                                           UnicodeString& result) const {
    484   const char* name = uscript_getName(scriptCode);
    485   return langData.get("Scripts", name, result);
    486 }
    487 
    488 UnicodeString&
    489 LocaleDisplayNamesImpl::regionDisplayName(const char* region,
    490                                           UnicodeString& result) const {
    491   return regionData.get("Countries", region, result);
    492 }
    493 
    494 UnicodeString&
    495 LocaleDisplayNamesImpl::variantDisplayName(const char* variant,
    496                                            UnicodeString& result) const {
    497   return langData.get("Variants", variant, result);
    498 }
    499 
    500 UnicodeString&
    501 LocaleDisplayNamesImpl::keyDisplayName(const char* key,
    502                                        UnicodeString& result) const {
    503   return langData.get("Keys", key, result);
    504 }
    505 
    506 UnicodeString&
    507 LocaleDisplayNamesImpl::keyValueDisplayName(const char* key,
    508                                             const char* value,
    509                                             UnicodeString& result) const {
    510   return langData.get("Types", key, value, result);
    511 }
    512 
    513 ////////////////////////////////////////////////////////////////////////////////////////////////////
    514 
    515 LocaleDisplayNames*
    516 LocaleDisplayNames::createInstance(const Locale& locale,
    517                                    UDialectHandling dialectHandling) {
    518   return new LocaleDisplayNamesImpl(locale, dialectHandling);
    519 }
    520 
    521 U_NAMESPACE_END
    522 
    523 ////////////////////////////////////////////////////////////////////////////////////////////////////
    524 
    525 U_NAMESPACE_USE
    526 
    527 U_DRAFT ULocaleDisplayNames * U_EXPORT2
    528 uldn_open(const char * locale,
    529           UDialectHandling dialectHandling,
    530           UErrorCode *pErrorCode) {
    531   if (U_FAILURE(*pErrorCode)) {
    532     return 0;
    533   }
    534   if (locale == NULL) {
    535     locale = uloc_getDefault();
    536   }
    537   return (ULocaleDisplayNames *)LocaleDisplayNames::createInstance(Locale(locale), dialectHandling);
    538 }
    539 
    540 U_DRAFT void U_EXPORT2
    541 uldn_close(ULocaleDisplayNames *ldn) {
    542   delete (LocaleDisplayNames *)ldn;
    543 }
    544 
    545 U_DRAFT const char * U_EXPORT2
    546 uldn_getLocale(const ULocaleDisplayNames *ldn) {
    547   if (ldn) {
    548     return ((const LocaleDisplayNames *)ldn)->getLocale().getName();
    549   }
    550   return NULL;
    551 }
    552 
    553 U_DRAFT UDialectHandling U_EXPORT2
    554 uldn_getDialectHandling(const ULocaleDisplayNames *ldn) {
    555   if (ldn) {
    556     return ((const LocaleDisplayNames *)ldn)->getDialectHandling();
    557   }
    558   return ULDN_STANDARD_NAMES;
    559 }
    560 
    561 U_DRAFT int32_t U_EXPORT2
    562 uldn_localeDisplayName(const ULocaleDisplayNames *ldn,
    563                        const char *locale,
    564                        UChar *result,
    565                        int32_t maxResultSize,
    566                        UErrorCode *pErrorCode) {
    567   if (U_FAILURE(*pErrorCode)) {
    568     return 0;
    569   }
    570   if (ldn == NULL || locale == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    571     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    572     return 0;
    573   }
    574   UnicodeString temp(result, 0, maxResultSize);
    575   ((const LocaleDisplayNames *)ldn)->localeDisplayName(locale, temp);
    576   return temp.extract(result, maxResultSize, *pErrorCode);
    577 }
    578 
    579 U_DRAFT int32_t U_EXPORT2
    580 uldn_languageDisplayName(const ULocaleDisplayNames *ldn,
    581                          const char *lang,
    582                          UChar *result,
    583                          int32_t maxResultSize,
    584                          UErrorCode *pErrorCode) {
    585   if (U_FAILURE(*pErrorCode)) {
    586     return 0;
    587   }
    588   if (ldn == NULL || lang == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    589     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    590     return 0;
    591   }
    592   UnicodeString temp(result, 0, maxResultSize);
    593   ((const LocaleDisplayNames *)ldn)->languageDisplayName(lang, temp);
    594   return temp.extract(result, maxResultSize, *pErrorCode);
    595 }
    596 
    597 U_DRAFT int32_t U_EXPORT2
    598 uldn_scriptDisplayName(const ULocaleDisplayNames *ldn,
    599                        const char *script,
    600                        UChar *result,
    601                        int32_t maxResultSize,
    602                        UErrorCode *pErrorCode) {
    603   if (U_FAILURE(*pErrorCode)) {
    604     return 0;
    605   }
    606   if (ldn == NULL || script == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    607     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    608     return 0;
    609   }
    610   UnicodeString temp(result, 0, maxResultSize);
    611   ((const LocaleDisplayNames *)ldn)->scriptDisplayName(script, temp);
    612   return temp.extract(result, maxResultSize, *pErrorCode);
    613 }
    614 
    615 U_DRAFT int32_t U_EXPORT2
    616 uldn_scriptCodeDisplayName(const ULocaleDisplayNames *ldn,
    617                            UScriptCode scriptCode,
    618                            UChar *result,
    619                            int32_t maxResultSize,
    620                            UErrorCode *pErrorCode) {
    621   return uldn_scriptDisplayName(ldn, uscript_getName(scriptCode), result, maxResultSize, pErrorCode);
    622 }
    623 
    624 U_DRAFT int32_t U_EXPORT2
    625 uldn_regionDisplayName(const ULocaleDisplayNames *ldn,
    626                        const char *region,
    627                        UChar *result,
    628                        int32_t maxResultSize,
    629                        UErrorCode *pErrorCode) {
    630   if (U_FAILURE(*pErrorCode)) {
    631     return 0;
    632   }
    633   if (ldn == NULL || region == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    634     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    635     return 0;
    636   }
    637   UnicodeString temp(result, 0, maxResultSize);
    638   ((const LocaleDisplayNames *)ldn)->regionDisplayName(region, temp);
    639   return temp.extract(result, maxResultSize, *pErrorCode);
    640 }
    641 
    642 U_DRAFT int32_t U_EXPORT2
    643 uldn_variantDisplayName(const ULocaleDisplayNames *ldn,
    644                         const char *variant,
    645                         UChar *result,
    646                         int32_t maxResultSize,
    647                         UErrorCode *pErrorCode) {
    648   if (U_FAILURE(*pErrorCode)) {
    649     return 0;
    650   }
    651   if (ldn == NULL || variant == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    652     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    653     return 0;
    654   }
    655   UnicodeString temp(result, 0, maxResultSize);
    656   ((const LocaleDisplayNames *)ldn)->variantDisplayName(variant, temp);
    657   return temp.extract(result, maxResultSize, *pErrorCode);
    658 }
    659 
    660 U_DRAFT int32_t U_EXPORT2
    661 uldn_keyDisplayName(const ULocaleDisplayNames *ldn,
    662                     const char *key,
    663                     UChar *result,
    664                     int32_t maxResultSize,
    665                     UErrorCode *pErrorCode) {
    666   if (U_FAILURE(*pErrorCode)) {
    667     return 0;
    668   }
    669   if (ldn == NULL || key == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) {
    670     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    671     return 0;
    672   }
    673   UnicodeString temp(result, 0, maxResultSize);
    674   ((const LocaleDisplayNames *)ldn)->keyDisplayName(key, temp);
    675   return temp.extract(result, maxResultSize, *pErrorCode);
    676 }
    677 
    678 U_DRAFT int32_t U_EXPORT2
    679 uldn_keyValueDisplayName(const ULocaleDisplayNames *ldn,
    680                          const char *key,
    681                          const char *value,
    682                          UChar *result,
    683                          int32_t maxResultSize,
    684                          UErrorCode *pErrorCode) {
    685   if (U_FAILURE(*pErrorCode)) {
    686     return 0;
    687   }
    688   if (ldn == NULL || key == NULL || value == NULL || (result == NULL && maxResultSize > 0)
    689       || maxResultSize < 0) {
    690     *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
    691     return 0;
    692   }
    693   UnicodeString temp(result, 0, maxResultSize);
    694   ((const LocaleDisplayNames *)ldn)->keyValueDisplayName(key, value, temp);
    695   return temp.extract(result, maxResultSize, *pErrorCode);
    696 }
    697 
    698 #endif
    699