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