1/* 2 ****************************************************************************** 3 * Copyright (C) 1996-2011, 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 55static U_NAMESPACE_QUALIFIER Locale* availableLocaleList = NULL; 56static int32_t availableLocaleListCount; 57static U_NAMESPACE_QUALIFIER ICULocaleService* gService = NULL; 58 59/** 60 * Release all static memory held by collator. 61 */ 62U_CDECL_BEGIN 63static 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 79U_CDECL_END 80 81U_NAMESPACE_BEGIN 82 83#if !UCONFIG_NO_SERVICE 84 85// ------------------------------------------ 86// 87// Registration 88// 89 90//------------------------------------------- 91 92CollatorFactory::~CollatorFactory() {} 93 94//------------------------------------------- 95 96UBool 97CollatorFactory::visible(void) const { 98 return TRUE; 99} 100 101//------------------------------------------- 102 103UnicodeString& 104CollatorFactory::getDisplayName(const Locale& objectLocale, 105 const Locale& displayLocale, 106 UnicodeString& result) 107{ 108 return objectLocale.getDisplayName(displayLocale, result); 109} 110 111// ------------------------------------- 112 113class 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 120UObject* 121ICUCollatorFactory::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 137class ICUCollatorService : public ICULocaleService { 138public: 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 193static ICULocaleService* 194getService(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 220static inline UBool 221hasService(void) 222{ 223 UBool retVal; 224 UMTX_CHECK(NULL, gService != NULL, retVal); 225 return retVal; 226} 227 228// ------------------------------------- 229 230UCollator* 231Collator::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 253static 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 306Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success) 307{ 308 return createInstance(Locale::getDefault(), success); 309} 310 311Collator* 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 338Collator* 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 380Collator * 381Collator::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 408Collator::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 416Collator::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 425Collator::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 433UCollationResult 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 443UCollationResult 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 455UBool 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 462UBool 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 469UBool 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 478const 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 491UnicodeString& 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 505UnicodeString& 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*/ 527Collator::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*/ 542Collator::Collator(UCollationStrength, UNormalizationMode ) 543: UObject() 544{ 545} 546 547Collator::~Collator() 548{ 549} 550 551Collator::Collator(const Collator &other) 552 : UObject(other) 553{ 554} 555 556UBool Collator::operator==(const Collator& other) const 557{ 558 return (UBool)(this == &other); 559} 560 561UBool Collator::operator!=(const Collator& other) const 562{ 563 return (UBool)!(*this == other); 564} 565 566int32_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 577void 578Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) { 579} 580 581UnicodeSet *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 593URegistryKey U_EXPORT2 594Collator::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 604class CFactory : public LocaleKeyFactory { 605private: 606 CollatorFactory* _delegate; 607 Hashtable* _ids; 608 609public: 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 642protected: 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 655UObject* 656CFactory::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 667UnicodeString& 668CFactory::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 683URegistryKey U_EXPORT2 684Collator::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 698UBool U_EXPORT2 699Collator::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 711class CollationLocaleListEnumeration : public StringEnumeration { 712private: 713 int32_t index; 714public: 715 static UClassID U_EXPORT2 getStaticClassID(void); 716 virtual UClassID getDynamicClassID(void) const; 717public: 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 768UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration) 769 770 771// ------------------------------------- 772 773StringEnumeration* U_EXPORT2 774Collator::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 788StringEnumeration* U_EXPORT2 789Collator::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 799StringEnumeration* U_EXPORT2 800Collator::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 810StringEnumeration* U_EXPORT2 811Collator::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 823Locale U_EXPORT2 824Collator::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 836int32_t U_EXPORT2 837Collator::getReorderCodes(int32_t* /* dest*/, 838 int32_t /* destCapacity*/, 839 UErrorCode& status) const 840{ 841 if (U_SUCCESS(status)) { 842 status = U_UNSUPPORTED_ERROR; 843 } 844 return 0; 845} 846 847void U_EXPORT2 848Collator::setReorderCodes(const int32_t* /* reorderCodes */, 849 int32_t /* reorderCodesLength */, 850 UErrorCode& status) 851{ 852 if (U_SUCCESS(status)) { 853 status = U_UNSUPPORTED_ERROR; 854 } 855} 856 857int32_t U_EXPORT2 858Collator::getEquivalentReorderCodes(int32_t /* reorderCode */, 859 int32_t* /* dest */, 860 int32_t /* destCapacity */, 861 UErrorCode& status) 862{ 863 if (U_SUCCESS(status)) { 864 status = U_UNSUPPORTED_ERROR; 865 } 866 return 0; 867} 868 869// UCollator private data members ---------------------------------------- 870 871/* This is useless information */ 872/*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/ 873 874// ------------------------------------- 875 876U_NAMESPACE_END 877 878#endif /* #if !UCONFIG_NO_COLLATION */ 879 880/* eof */ 881