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