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_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("=") 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