1 /* 2 ****************************************************************************** 3 * Copyright (C) 1996-2010, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ****************************************************************************** 6 */ 7 8 /** 9 * File coll.cpp 10 * 11 * Created by: Helena Shih 12 * 13 * Modification History: 14 * 15 * Date Name Description 16 * 2/5/97 aliu Modified createDefault to load collation data from 17 * binary files when possible. Added related methods 18 * createCollationFromFile, chopLocale, createPathName. 19 * 2/11/97 aliu Added methods addToCache, findInCache, which implement 20 * a Collation cache. Modified createDefault to look in 21 * cache first, and also to store newly created Collation 22 * objects in the cache. Modified to not use gLocPath. 23 * 2/12/97 aliu Modified to create objects from RuleBasedCollator cache. 24 * Moved cache out of Collation class. 25 * 2/13/97 aliu Moved several methods out of this class and into 26 * RuleBasedCollator, with modifications. Modified 27 * createDefault() to call new RuleBasedCollator(Locale&) 28 * constructor. General clean up and documentation. 29 * 2/20/97 helena Added clone, operator==, operator!=, operator=, and copy 30 * constructor. 31 * 05/06/97 helena Added memory allocation error detection. 32 * 05/08/97 helena Added createInstance(). 33 * 6/20/97 helena Java class name change. 34 * 04/23/99 stephen Removed EDecompositionMode, merged with 35 * Normalizer::EMode 36 * 11/23/9 srl Inlining of some critical functions 37 * 01/29/01 synwee Modified into a C++ wrapper calling C APIs (ucol.h) 38 */ 39 40 #include "unicode/utypes.h" 41 42 #if !UCONFIG_NO_COLLATION 43 44 #include "unicode/coll.h" 45 #include "unicode/tblcoll.h" 46 #include "ucol_imp.h" 47 #include "cstring.h" 48 #include "cmemory.h" 49 #include "umutex.h" 50 #include "servloc.h" 51 #include "ustrenum.h" 52 #include "uresimp.h" 53 #include "ucln_in.h" 54 55 static U_NAMESPACE_QUALIFIER Locale* availableLocaleList = NULL; 56 static int32_t availableLocaleListCount; 57 static U_NAMESPACE_QUALIFIER ICULocaleService* gService = NULL; 58 59 /** 60 * Release all static memory held by collator. 61 */ 62 U_CDECL_BEGIN 63 static UBool U_CALLCONV collator_cleanup(void) { 64 #if !UCONFIG_NO_SERVICE 65 if (gService) { 66 delete gService; 67 gService = NULL; 68 } 69 #endif 70 if (availableLocaleList) { 71 delete []availableLocaleList; 72 availableLocaleList = NULL; 73 } 74 availableLocaleListCount = 0; 75 76 return TRUE; 77 } 78 79 U_CDECL_END 80 81 U_NAMESPACE_BEGIN 82 83 #if !UCONFIG_NO_SERVICE 84 85 // ------------------------------------------ 86 // 87 // Registration 88 // 89 90 //------------------------------------------- 91 92 CollatorFactory::~CollatorFactory() {} 93 94 //------------------------------------------- 95 96 UBool 97 CollatorFactory::visible(void) const { 98 return TRUE; 99 } 100 101 //------------------------------------------- 102 103 UnicodeString& 104 CollatorFactory::getDisplayName(const Locale& objectLocale, 105 const Locale& displayLocale, 106 UnicodeString& result) 107 { 108 return objectLocale.getDisplayName(displayLocale, result); 109 } 110 111 // ------------------------------------- 112 113 class ICUCollatorFactory : public ICUResourceBundleFactory { 114 public: 115 ICUCollatorFactory(): ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL, -1, US_INV)) { } 116 protected: 117 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; 118 }; 119 120 UObject* 121 ICUCollatorFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const { 122 if (handlesKey(key, status)) { 123 const LocaleKey& lkey = (const LocaleKey&)key; 124 Locale loc; 125 // make sure the requested locale is correct 126 // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey 127 // but for ICU rb resources we use the actual one since it will fallback again 128 lkey.canonicalLocale(loc); 129 130 return Collator::makeInstance(loc, status); 131 } 132 return NULL; 133 } 134 135 // ------------------------------------- 136 137 class ICUCollatorService : public ICULocaleService { 138 public: 139 ICUCollatorService() 140 : ICULocaleService(UNICODE_STRING_SIMPLE("Collator")) 141 { 142 UErrorCode status = U_ZERO_ERROR; 143 registerFactory(new ICUCollatorFactory(), status); 144 } 145 146 virtual UObject* cloneInstance(UObject* instance) const { 147 return ((Collator*)instance)->clone(); 148 } 149 150 virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const { 151 LocaleKey& lkey = (LocaleKey&)key; 152 if (actualID) { 153 // Ugly Hack Alert! We return an empty actualID to signal 154 // to callers that this is a default object, not a "real" 155 // service-created object. (TODO remove in 3.0) [aliu] 156 actualID->truncate(0); 157 } 158 Locale loc(""); 159 lkey.canonicalLocale(loc); 160 return Collator::makeInstance(loc, status); 161 } 162 163 virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const { 164 UnicodeString ar; 165 if (actualReturn == NULL) { 166 actualReturn = &ar; 167 } 168 Collator* result = (Collator*)ICULocaleService::getKey(key, actualReturn, status); 169 // Ugly Hack Alert! If the actualReturn length is zero, this 170 // means we got a default object, not a "real" service-created 171 // object. We don't call setLocales() on a default object, 172 // because that will overwrite its correct built-in locale 173 // metadata (valid & actual) with our incorrect data (all we 174 // have is the requested locale). (TODO remove in 3.0) [aliu] 175 if (result && actualReturn->length() > 0) { 176 const LocaleKey& lkey = (const LocaleKey&)key; 177 Locale canonicalLocale(""); 178 Locale currentLocale(""); 179 180 LocaleUtility::initLocaleFromName(*actualReturn, currentLocale); 181 result->setLocales(lkey.canonicalLocale(canonicalLocale), currentLocale, currentLocale); 182 } 183 return result; 184 } 185 186 virtual UBool isDefault() const { 187 return countFactories() == 1; 188 } 189 }; 190 191 // ------------------------------------- 192 193 static ICULocaleService* 194 getService(void) 195 { 196 UBool needInit; 197 UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit); 198 if(needInit) { 199 ICULocaleService *newservice = new ICUCollatorService(); 200 if(newservice) { 201 umtx_lock(NULL); 202 if(gService == NULL) { 203 gService = newservice; 204 newservice = NULL; 205 } 206 umtx_unlock(NULL); 207 } 208 if(newservice) { 209 delete newservice; 210 } 211 else { 212 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); 213 } 214 } 215 return gService; 216 } 217 218 // ------------------------------------- 219 220 static inline UBool 221 hasService(void) 222 { 223 UBool retVal; 224 UMTX_CHECK(NULL, gService != NULL, retVal); 225 return retVal; 226 } 227 228 // ------------------------------------- 229 230 UCollator* 231 Collator::createUCollator(const char *loc, 232 UErrorCode *status) 233 { 234 UCollator *result = 0; 235 if (status && U_SUCCESS(*status) && hasService()) { 236 Locale desiredLocale(loc); 237 Collator *col = (Collator*)gService->get(desiredLocale, *status); 238 RuleBasedCollator *rbc; 239 if (col && (rbc = dynamic_cast<RuleBasedCollator *>(col))) { 240 if (!rbc->dataIsOwned) { 241 result = ucol_safeClone(rbc->ucollator, NULL, NULL, status); 242 } else { 243 result = rbc->ucollator; 244 rbc->ucollator = NULL; // to prevent free on delete 245 } 246 } 247 delete col; 248 } 249 return result; 250 } 251 #endif /* UCONFIG_NO_SERVICE */ 252 253 static UBool isAvailableLocaleListInitialized(UErrorCode &status) { 254 // for now, there is a hardcoded list, so just walk through that list and set it up. 255 UBool needInit; 256 UMTX_CHECK(NULL, availableLocaleList == NULL, needInit); 257 258 if (needInit) { 259 UResourceBundle *index = NULL; 260 UResourceBundle installed; 261 Locale * temp; 262 int32_t i = 0; 263 int32_t localeCount; 264 265 ures_initStackObject(&installed); 266 index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status); 267 ures_getByKey(index, "InstalledLocales", &installed, &status); 268 269 if(U_SUCCESS(status)) { 270 localeCount = ures_getSize(&installed); 271 temp = new Locale[localeCount]; 272 273 if (temp != NULL) { 274 ures_resetIterator(&installed); 275 while(ures_hasNext(&installed)) { 276 const char *tempKey = NULL; 277 ures_getNextString(&installed, NULL, &tempKey, &status); 278 temp[i++] = Locale(tempKey); 279 } 280 281 umtx_lock(NULL); 282 if (availableLocaleList == NULL) 283 { 284 availableLocaleListCount = localeCount; 285 availableLocaleList = temp; 286 temp = NULL; 287 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); 288 } 289 umtx_unlock(NULL); 290 291 needInit = FALSE; 292 if (temp) { 293 delete []temp; 294 } 295 } 296 297 ures_close(&installed); 298 } 299 ures_close(index); 300 } 301 return !needInit; 302 } 303 304 // Collator public methods ----------------------------------------------- 305 306 Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success) 307 { 308 return createInstance(Locale::getDefault(), success); 309 } 310 311 Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale, 312 UErrorCode& status) 313 { 314 if (U_FAILURE(status)) 315 return 0; 316 317 #if !UCONFIG_NO_SERVICE 318 if (hasService()) { 319 Locale actualLoc; 320 Collator *result = 321 (Collator*)gService->get(desiredLocale, &actualLoc, status); 322 // Ugly Hack Alert! If the returned locale is empty (not root, 323 // but empty -- getName() == "") then that means the service 324 // returned a default object, not a "real" service object. In 325 // that case, the locale metadata (valid & actual) is setup 326 // correctly already, and we don't want to overwrite it. (TODO 327 // remove in 3.0) [aliu] 328 if (*actualLoc.getName() != 0) { 329 result->setLocales(desiredLocale, actualLoc, actualLoc); 330 } 331 return result; 332 } 333 #endif 334 return makeInstance(desiredLocale, status); 335 } 336 337 338 Collator* Collator::makeInstance(const Locale& desiredLocale, 339 UErrorCode& status) 340 { 341 // A bit of explanation is required here. Although in the current 342 // implementation 343 // Collator::createInstance() is just turning around and calling 344 // RuleBasedCollator(Locale&), this will not necessarily always be the 345 // case. For example, suppose we modify this code to handle a 346 // non-table-based Collator, such as that for Thai. In this case, 347 // createInstance() will have to be modified to somehow determine this fact 348 // (perhaps a field in the resource bundle). Then it can construct the 349 // non-table-based Collator in some other way, when it sees that it needs 350 // to. 351 // The specific caution is this: RuleBasedCollator(Locale&) will ALWAYS 352 // return a valid collation object, if the system is functioning properly. 353 // The reason is that it will fall back, use the default locale, and even 354 // use the built-in default collation rules. THEREFORE, createInstance() 355 // should in general ONLY CALL RuleBasedCollator(Locale&) IF IT KNOWS IN 356 // ADVANCE that the given locale's collation is properly implemented as a 357 // RuleBasedCollator. 358 // Currently, we don't do this...we always return a RuleBasedCollator, 359 // whether it is strictly correct to do so or not, without checking, because 360 // we currently have no way of checking. 361 362 RuleBasedCollator* collation = new RuleBasedCollator(desiredLocale, 363 status); 364 /* test for NULL */ 365 if (collation == 0) { 366 status = U_MEMORY_ALLOCATION_ERROR; 367 return 0; 368 } 369 if (U_FAILURE(status)) 370 { 371 delete collation; 372 collation = 0; 373 } 374 return collation; 375 } 376 377 #ifdef U_USE_COLLATION_OBSOLETE_2_6 378 // !!! dlf the following is obsolete, ignore registration for this 379 380 Collator * 381 Collator::createInstance(const Locale &loc, 382 UVersionInfo version, 383 UErrorCode &status) 384 { 385 Collator *collator; 386 UVersionInfo info; 387 388 collator=new RuleBasedCollator(loc, status); 389 /* test for NULL */ 390 if (collator == 0) { 391 status = U_MEMORY_ALLOCATION_ERROR; 392 return 0; 393 } 394 395 if(U_SUCCESS(status)) { 396 collator->getVersion(info); 397 if(0!=uprv_memcmp(version, info, sizeof(UVersionInfo))) { 398 delete collator; 399 status=U_MISSING_RESOURCE_ERROR; 400 return 0; 401 } 402 } 403 return collator; 404 } 405 #endif 406 407 // implement deprecated, previously abstract method 408 Collator::EComparisonResult Collator::compare(const UnicodeString& source, 409 const UnicodeString& target) const 410 { 411 UErrorCode ec = U_ZERO_ERROR; 412 return (Collator::EComparisonResult)compare(source, target, ec); 413 } 414 415 // implement deprecated, previously abstract method 416 Collator::EComparisonResult Collator::compare(const UnicodeString& source, 417 const UnicodeString& target, 418 int32_t length) const 419 { 420 UErrorCode ec = U_ZERO_ERROR; 421 return (Collator::EComparisonResult)compare(source, target, length, ec); 422 } 423 424 // implement deprecated, previously abstract method 425 Collator::EComparisonResult Collator::compare(const UChar* source, int32_t sourceLength, 426 const UChar* target, int32_t targetLength) 427 const 428 { 429 UErrorCode ec = U_ZERO_ERROR; 430 return (Collator::EComparisonResult)compare(source, sourceLength, target, targetLength, ec); 431 } 432 433 UCollationResult Collator::compare(UCharIterator &/*sIter*/, 434 UCharIterator &/*tIter*/, 435 UErrorCode &status) const { 436 if(U_SUCCESS(status)) { 437 // Not implemented in the base class. 438 status = U_UNSUPPORTED_ERROR; 439 } 440 return UCOL_EQUAL; 441 } 442 443 UCollationResult Collator::compareUTF8(const StringPiece &source, 444 const StringPiece &target, 445 UErrorCode &status) const { 446 if(U_FAILURE(status)) { 447 return UCOL_EQUAL; 448 } 449 UCharIterator sIter, tIter; 450 uiter_setUTF8(&sIter, source.data(), source.length()); 451 uiter_setUTF8(&tIter, target.data(), target.length()); 452 return compare(sIter, tIter, status); 453 } 454 455 UBool Collator::equals(const UnicodeString& source, 456 const UnicodeString& target) const 457 { 458 UErrorCode ec = U_ZERO_ERROR; 459 return (compare(source, target, ec) == UCOL_EQUAL); 460 } 461 462 UBool Collator::greaterOrEqual(const UnicodeString& source, 463 const UnicodeString& target) const 464 { 465 UErrorCode ec = U_ZERO_ERROR; 466 return (compare(source, target, ec) != UCOL_LESS); 467 } 468 469 UBool Collator::greater(const UnicodeString& source, 470 const UnicodeString& target) const 471 { 472 UErrorCode ec = U_ZERO_ERROR; 473 return (compare(source, target, ec) == UCOL_GREATER); 474 } 475 476 // this API ignores registered collators, since it returns an 477 // array of indefinite lifetime 478 const Locale* U_EXPORT2 Collator::getAvailableLocales(int32_t& count) 479 { 480 UErrorCode status = U_ZERO_ERROR; 481 Locale *result = NULL; 482 count = 0; 483 if (isAvailableLocaleListInitialized(status)) 484 { 485 result = availableLocaleList; 486 count = availableLocaleListCount; 487 } 488 return result; 489 } 490 491 UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale, 492 const Locale& displayLocale, 493 UnicodeString& name) 494 { 495 #if !UCONFIG_NO_SERVICE 496 if (hasService()) { 497 UnicodeString locNameStr; 498 LocaleUtility::initNameFromLocale(objectLocale, locNameStr); 499 return gService->getDisplayName(locNameStr, name, displayLocale); 500 } 501 #endif 502 return objectLocale.getDisplayName(displayLocale, name); 503 } 504 505 UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale, 506 UnicodeString& name) 507 { 508 return getDisplayName(objectLocale, Locale::getDefault(), name); 509 } 510 511 /* This is useless information */ 512 /*void Collator::getVersion(UVersionInfo versionInfo) const 513 { 514 if (versionInfo!=NULL) 515 uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH); 516 } 517 */ 518 519 // UCollator protected constructor destructor ---------------------------- 520 521 /** 522 * Default constructor. 523 * Constructor is different from the old default Collator constructor. 524 * The task for determing the default collation strength and normalization mode 525 * is left to the child class. 526 */ 527 Collator::Collator() 528 : UObject() 529 { 530 } 531 532 /** 533 * Constructor. 534 * Empty constructor, does not handle the arguments. 535 * This constructor is done for backward compatibility with 1.7 and 1.8. 536 * The task for handling the argument collation strength and normalization 537 * mode is left to the child class. 538 * @param collationStrength collation strength 539 * @param decompositionMode 540 * @deprecated 2.4 use the default constructor instead 541 */ 542 Collator::Collator(UCollationStrength, UNormalizationMode ) 543 : UObject() 544 { 545 } 546 547 Collator::~Collator() 548 { 549 } 550 551 Collator::Collator(const Collator &other) 552 : UObject(other) 553 { 554 } 555 556 UBool Collator::operator==(const Collator& other) const 557 { 558 return (UBool)(this == &other); 559 } 560 561 UBool Collator::operator!=(const Collator& other) const 562 { 563 return (UBool)!(*this == other); 564 } 565 566 int32_t U_EXPORT2 Collator::getBound(const uint8_t *source, 567 int32_t sourceLength, 568 UColBoundMode boundType, 569 uint32_t noOfLevels, 570 uint8_t *result, 571 int32_t resultLength, 572 UErrorCode &status) 573 { 574 return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status); 575 } 576 577 void 578 Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) { 579 } 580 581 UnicodeSet *Collator::getTailoredSet(UErrorCode &status) const 582 { 583 if(U_FAILURE(status)) { 584 return NULL; 585 } 586 // everything can be changed 587 return new UnicodeSet(0, 0x10FFFF); 588 } 589 590 // ------------------------------------- 591 592 #if !UCONFIG_NO_SERVICE 593 URegistryKey U_EXPORT2 594 Collator::registerInstance(Collator* toAdopt, const Locale& locale, UErrorCode& status) 595 { 596 if (U_SUCCESS(status)) { 597 return getService()->registerInstance(toAdopt, locale, status); 598 } 599 return NULL; 600 } 601 602 // ------------------------------------- 603 604 class CFactory : public LocaleKeyFactory { 605 private: 606 CollatorFactory* _delegate; 607 Hashtable* _ids; 608 609 public: 610 CFactory(CollatorFactory* delegate, UErrorCode& status) 611 : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE) 612 , _delegate(delegate) 613 , _ids(NULL) 614 { 615 if (U_SUCCESS(status)) { 616 int32_t count = 0; 617 _ids = new Hashtable(status); 618 if (_ids) { 619 const UnicodeString * idlist = _delegate->getSupportedIDs(count, status); 620 for (int i = 0; i < count; ++i) { 621 _ids->put(idlist[i], (void*)this, status); 622 if (U_FAILURE(status)) { 623 delete _ids; 624 _ids = NULL; 625 return; 626 } 627 } 628 } else { 629 status = U_MEMORY_ALLOCATION_ERROR; 630 } 631 } 632 } 633 634 virtual ~CFactory() 635 { 636 delete _delegate; 637 delete _ids; 638 } 639 640 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; 641 642 protected: 643 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const 644 { 645 if (U_SUCCESS(status)) { 646 return _ids; 647 } 648 return NULL; 649 } 650 651 virtual UnicodeString& 652 getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const; 653 }; 654 655 UObject* 656 CFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const 657 { 658 if (handlesKey(key, status)) { 659 const LocaleKey& lkey = (const LocaleKey&)key; 660 Locale validLoc; 661 lkey.currentLocale(validLoc); 662 return _delegate->createCollator(validLoc); 663 } 664 return NULL; 665 } 666 667 UnicodeString& 668 CFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const 669 { 670 if ((_coverage & 0x1) == 0) { 671 UErrorCode status = U_ZERO_ERROR; 672 const Hashtable* ids = getSupportedIDs(status); 673 if (ids && (ids->get(id) != NULL)) { 674 Locale loc; 675 LocaleUtility::initLocaleFromName(id, loc); 676 return _delegate->getDisplayName(loc, locale, result); 677 } 678 } 679 result.setToBogus(); 680 return result; 681 } 682 683 URegistryKey U_EXPORT2 684 Collator::registerFactory(CollatorFactory* toAdopt, UErrorCode& status) 685 { 686 if (U_SUCCESS(status)) { 687 CFactory* f = new CFactory(toAdopt, status); 688 if (f) { 689 return getService()->registerFactory(f, status); 690 } 691 status = U_MEMORY_ALLOCATION_ERROR; 692 } 693 return NULL; 694 } 695 696 // ------------------------------------- 697 698 UBool U_EXPORT2 699 Collator::unregister(URegistryKey key, UErrorCode& status) 700 { 701 if (U_SUCCESS(status)) { 702 if (hasService()) { 703 return gService->unregister(key, status); 704 } 705 status = U_ILLEGAL_ARGUMENT_ERROR; 706 } 707 return FALSE; 708 } 709 #endif /* UCONFIG_NO_SERVICE */ 710 711 class CollationLocaleListEnumeration : public StringEnumeration { 712 private: 713 int32_t index; 714 public: 715 static UClassID U_EXPORT2 getStaticClassID(void); 716 virtual UClassID getDynamicClassID(void) const; 717 public: 718 CollationLocaleListEnumeration() 719 : index(0) 720 { 721 // The global variables should already be initialized. 722 //isAvailableLocaleListInitialized(status); 723 } 724 725 virtual ~CollationLocaleListEnumeration() { 726 } 727 728 virtual StringEnumeration * clone() const 729 { 730 CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration(); 731 if (result) { 732 result->index = index; 733 } 734 return result; 735 } 736 737 virtual int32_t count(UErrorCode &/*status*/) const { 738 return availableLocaleListCount; 739 } 740 741 virtual const char* next(int32_t* resultLength, UErrorCode& /*status*/) { 742 const char* result; 743 if(index < availableLocaleListCount) { 744 result = availableLocaleList[index++].getName(); 745 if(resultLength != NULL) { 746 *resultLength = (int32_t)uprv_strlen(result); 747 } 748 } else { 749 if(resultLength != NULL) { 750 *resultLength = 0; 751 } 752 result = NULL; 753 } 754 return result; 755 } 756 757 virtual const UnicodeString* snext(UErrorCode& status) { 758 int32_t resultLength = 0; 759 const char *s = next(&resultLength, status); 760 return setChars(s, resultLength, status); 761 } 762 763 virtual void reset(UErrorCode& /*status*/) { 764 index = 0; 765 } 766 }; 767 768 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration) 769 770 771 // ------------------------------------- 772 773 StringEnumeration* U_EXPORT2 774 Collator::getAvailableLocales(void) 775 { 776 #if !UCONFIG_NO_SERVICE 777 if (hasService()) { 778 return getService()->getAvailableLocales(); 779 } 780 #endif /* UCONFIG_NO_SERVICE */ 781 UErrorCode status = U_ZERO_ERROR; 782 if (isAvailableLocaleListInitialized(status)) { 783 return new CollationLocaleListEnumeration(); 784 } 785 return NULL; 786 } 787 788 StringEnumeration* U_EXPORT2 789 Collator::getKeywords(UErrorCode& status) { 790 // This is a wrapper over ucol_getKeywords 791 UEnumeration* uenum = ucol_getKeywords(&status); 792 if (U_FAILURE(status)) { 793 uenum_close(uenum); 794 return NULL; 795 } 796 return new UStringEnumeration(uenum); 797 } 798 799 StringEnumeration* U_EXPORT2 800 Collator::getKeywordValues(const char *keyword, UErrorCode& status) { 801 // This is a wrapper over ucol_getKeywordValues 802 UEnumeration* uenum = ucol_getKeywordValues(keyword, &status); 803 if (U_FAILURE(status)) { 804 uenum_close(uenum); 805 return NULL; 806 } 807 return new UStringEnumeration(uenum); 808 } 809 810 StringEnumeration* U_EXPORT2 811 Collator::getKeywordValuesForLocale(const char* key, const Locale& locale, 812 UBool commonlyUsed, UErrorCode& status) { 813 // This is a wrapper over ucol_getKeywordValuesForLocale 814 UEnumeration *uenum = ucol_getKeywordValuesForLocale(key, locale.getName(), 815 commonlyUsed, &status); 816 if (U_FAILURE(status)) { 817 uenum_close(uenum); 818 return NULL; 819 } 820 return new UStringEnumeration(uenum); 821 } 822 823 Locale U_EXPORT2 824 Collator::getFunctionalEquivalent(const char* keyword, const Locale& locale, 825 UBool& isAvailable, UErrorCode& status) { 826 // This is a wrapper over ucol_getFunctionalEquivalent 827 char loc[ULOC_FULLNAME_CAPACITY]; 828 /*int32_t len =*/ ucol_getFunctionalEquivalent(loc, sizeof(loc), 829 keyword, locale.getName(), &isAvailable, &status); 830 if (U_FAILURE(status)) { 831 *loc = 0; // root 832 } 833 return Locale::createFromName(loc); 834 } 835 836 int32_t Collator::getReorderCodes(int32_t *dest, 837 int32_t destCapacity, 838 UErrorCode& status) const 839 { 840 if (U_SUCCESS(status)) { 841 status = U_UNSUPPORTED_ERROR; 842 } 843 return 0; 844 } 845 846 void Collator::setReorderCodes(const int32_t *reorderCodes, 847 int32_t reorderCodesLength, 848 UErrorCode& status) 849 { 850 if (U_SUCCESS(status)) { 851 status = U_UNSUPPORTED_ERROR; 852 } 853 } 854 855 // UCollator private data members ---------------------------------------- 856 857 /* This is useless information */ 858 /*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/ 859 860 // ------------------------------------- 861 862 U_NAMESPACE_END 863 864 #endif /* #if !UCONFIG_NO_COLLATION */ 865 866 /* eof */ 867