18584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne/*
28584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne*******************************************************************************
38584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne* Copyright (C) 2010, International Business Machines Corporation and         *
48584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne* others. All Rights Reserved.                                                *
58584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne*******************************************************************************
68584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne*/
78584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne
88584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#include "unicode/utypes.h"
98584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne
108584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#if !UCONFIG_NO_FORMATTING
118584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne
128584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#include "unicode/locdspnm.h"
138584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne
148584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#include "unicode/msgfmt.h"
158584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne
168584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#include "cmemory.h"
178584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#include "cstring.h"
188584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#include "ulocimp.h"
198584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#include "ureslocs.h"
208584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne
218584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne#include <stdarg.h>
228584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne
238584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne/**
248584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne * Concatenate a number of null-terminated strings to buffer, leaving a
258584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne * null-terminated string.  The last argument should be the null pointer.
268584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne * Return the length of the string in the buffer, not counting the trailing
278584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne * null.  Return -1 if there is an error (buffer is null, or buflen < 1).
288584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne */
298584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunnestatic int32_t ncat(char *buffer, uint32_t buflen, ...) {
308584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne  va_list args;
318584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne  char *str;
328584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne  char *p = buffer;
338584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne  const char* e = buffer + buflen - 1;
348584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne
358584909e7fa0fba19077b789f9b5482d7feafbfdGilles Debunne  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
52U_NAMESPACE_BEGIN
53
54////////////////////////////////////////////////////////////////////////////////////////////////////
55
56// Access resource data for locale components.
57// Wrap code in uloc.c for now.
58class ICUDataTable {
59  const char* path;
60  Locale locale;
61
62public:
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
79inline UnicodeString &
80ICUDataTable::get(const char* tableKey, const char* itemKey, UnicodeString& result) const {
81  return get(tableKey, NULL, itemKey, result);
82}
83
84inline UnicodeString &
85ICUDataTable::getNoFallback(const char* tableKey, const char* itemKey, UnicodeString& result) const {
86  return getNoFallback(tableKey, NULL, itemKey, result);
87}
88
89ICUDataTable::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
102ICUDataTable::~ICUDataTable() {
103  if (path) {
104    uprv_free((void*) path);
105    path = NULL;
106  }
107}
108
109const Locale&
110ICUDataTable::getLocale() {
111  return locale;
112}
113
114UnicodeString &
115ICUDataTable::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
129UnicodeString &
130ICUDataTable::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
148UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(LocaleDisplayNames)
149
150////////////////////////////////////////////////////////////////////////////////////////////////////
151
152#if 0  // currently unused
153
154class DefaultLocaleDisplayNames : public LocaleDisplayNames {
155  UDialectHandling dialectHandling;
156
157public:
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
186DefaultLocaleDisplayNames::DefaultLocaleDisplayNames(UDialectHandling dialectHandling)
187    : dialectHandling(dialectHandling) {
188}
189
190DefaultLocaleDisplayNames::~DefaultLocaleDisplayNames() {
191}
192
193const Locale&
194DefaultLocaleDisplayNames::getLocale() const {
195  return Locale::getRoot();
196}
197
198UDialectHandling
199DefaultLocaleDisplayNames::getDialectHandling() const {
200  return dialectHandling;
201}
202
203UnicodeString&
204DefaultLocaleDisplayNames::localeDisplayName(const Locale& locale,
205                                             UnicodeString& result) const {
206  return result = UnicodeString(locale.getName(), -1, US_INV);
207}
208
209UnicodeString&
210DefaultLocaleDisplayNames::localeDisplayName(const char* localeId,
211                                             UnicodeString& result) const {
212  return result = UnicodeString(localeId, -1, US_INV);
213}
214
215UnicodeString&
216DefaultLocaleDisplayNames::languageDisplayName(const char* lang,
217                                               UnicodeString& result) const {
218  return result = UnicodeString(lang, -1, US_INV);
219}
220
221UnicodeString&
222DefaultLocaleDisplayNames::scriptDisplayName(const char* script,
223                                             UnicodeString& result) const {
224  return result = UnicodeString(script, -1, US_INV);
225}
226
227UnicodeString&
228DefaultLocaleDisplayNames::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
237UnicodeString&
238DefaultLocaleDisplayNames::regionDisplayName(const char* region,
239                                             UnicodeString& result) const {
240  return result = UnicodeString(region, -1, US_INV);
241}
242
243UnicodeString&
244DefaultLocaleDisplayNames::variantDisplayName(const char* variant,
245                                              UnicodeString& result) const {
246  return result = UnicodeString(variant, -1, US_INV);
247}
248
249UnicodeString&
250DefaultLocaleDisplayNames::keyDisplayName(const char* key,
251                                          UnicodeString& result) const {
252  return result = UnicodeString(key, -1, US_INV);
253}
254
255UnicodeString&
256DefaultLocaleDisplayNames::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
266class LocaleDisplayNamesImpl : public LocaleDisplayNames {
267  Locale locale;
268  UDialectHandling dialectHandling;
269  ICUDataTable langData;
270  ICUDataTable regionData;
271  UnicodeString sep;
272  MessageFormat *format;
273
274public:
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;
301private:
302  UnicodeString& localeIdName(const char* localeId,
303                              UnicodeString& result) const;
304  UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const;
305};
306
307LocaleDisplayNamesImpl::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
333LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() {
334  delete format;
335}
336
337const Locale&
338LocaleDisplayNamesImpl::getLocale() const {
339  return locale;
340}
341
342UDialectHandling
343LocaleDisplayNamesImpl::getDialectHandling() const {
344  return dialectHandling;
345}
346
347UnicodeString&
348LocaleDisplayNamesImpl::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("=")
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
441UnicodeString&
442LocaleDisplayNamesImpl::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
450UnicodeString&
451LocaleDisplayNamesImpl::localeDisplayName(const char* localeId,
452                                          UnicodeString& result) const {
453  return localeDisplayName(Locale(localeId), result);
454}
455
456UnicodeString&
457LocaleDisplayNamesImpl::localeIdName(const char* localeId,
458                                     UnicodeString& result) const {
459  return langData.getNoFallback("Languages", localeId, result);
460}
461
462UnicodeString&
463LocaleDisplayNamesImpl::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
471UnicodeString&
472LocaleDisplayNamesImpl::scriptDisplayName(const char* script,
473                                          UnicodeString& result) const {
474  return langData.get("Scripts", script, result);
475}
476
477UnicodeString&
478LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode,
479                                          UnicodeString& result) const {
480  const char* name = uscript_getName(scriptCode);
481  return langData.get("Scripts", name, result);
482}
483
484UnicodeString&
485LocaleDisplayNamesImpl::regionDisplayName(const char* region,
486                                          UnicodeString& result) const {
487  return regionData.get("Countries", region, result);
488}
489
490UnicodeString&
491LocaleDisplayNamesImpl::variantDisplayName(const char* variant,
492                                           UnicodeString& result) const {
493  return langData.get("Variants", variant, result);
494}
495
496UnicodeString&
497LocaleDisplayNamesImpl::keyDisplayName(const char* key,
498                                       UnicodeString& result) const {
499  return langData.get("Keys", key, result);
500}
501
502UnicodeString&
503LocaleDisplayNamesImpl::keyValueDisplayName(const char* key,
504                                            const char* value,
505                                            UnicodeString& result) const {
506  return langData.get("Types", key, value, result);
507}
508
509////////////////////////////////////////////////////////////////////////////////////////////////////
510
511LocaleDisplayNames*
512LocaleDisplayNames::createInstance(const Locale& locale,
513                                   UDialectHandling dialectHandling) {
514  return new LocaleDisplayNamesImpl(locale, dialectHandling);
515}
516
517U_NAMESPACE_END
518
519////////////////////////////////////////////////////////////////////////////////////////////////////
520
521U_NAMESPACE_USE
522
523U_DRAFT ULocaleDisplayNames * U_EXPORT2
524uldn_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
536U_DRAFT void U_EXPORT2
537uldn_close(ULocaleDisplayNames *ldn) {
538  delete (LocaleDisplayNames *)ldn;
539}
540
541U_DRAFT const char * U_EXPORT2
542uldn_getLocale(const ULocaleDisplayNames *ldn) {
543  if (ldn) {
544    return ((const LocaleDisplayNames *)ldn)->getLocale().getName();
545  }
546  return NULL;
547}
548
549U_DRAFT UDialectHandling U_EXPORT2
550uldn_getDialectHandling(const ULocaleDisplayNames *ldn) {
551  if (ldn) {
552    return ((const LocaleDisplayNames *)ldn)->getDialectHandling();
553  }
554  return ULDN_STANDARD_NAMES;
555}
556
557U_DRAFT int32_t U_EXPORT2
558uldn_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
575U_DRAFT int32_t U_EXPORT2
576uldn_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
593U_DRAFT int32_t U_EXPORT2
594uldn_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
611U_DRAFT int32_t U_EXPORT2
612uldn_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
620U_DRAFT int32_t U_EXPORT2
621uldn_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
638U_DRAFT int32_t U_EXPORT2
639uldn_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
656U_DRAFT int32_t U_EXPORT2
657uldn_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
674U_DRAFT int32_t U_EXPORT2
675uldn_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