intl/icu/source/i18n/coll.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2  ******************************************************************************
     3  * Copyright (C) 1996-2013, International Business Machines Corporation and
     4  * others. All Rights Reserved.
     5  ******************************************************************************
     6  */
     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  */
    40 #include "utypeinfo.h"  // for 'typeid' to work
    42 #include "unicode/utypes.h"
    44 #if !UCONFIG_NO_COLLATION
    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"
    58 static icu::Locale* availableLocaleList = NULL;
    59 static int32_t  availableLocaleListCount;
    60 static icu::ICULocaleService* gService = NULL;
    61 static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
    62 static icu::UInitOnce gAvailableLocaleListInitOnce;
    64 /**
    65  * Release all static memory held by collator.
    66  */
    67 U_CDECL_BEGIN
    68 static 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 }
    85 U_CDECL_END
    87 U_NAMESPACE_BEGIN
    89 #if !UCONFIG_NO_SERVICE
    91 // ------------------------------------------
    92 //
    93 // Registration
    94 //
    96 //-------------------------------------------
    98 CollatorFactory::~CollatorFactory() {}
   100 //-------------------------------------------
   102 UBool
   103 CollatorFactory::visible(void) const {
   104     return TRUE;
   105 }
   107 //-------------------------------------------
   109 UnicodeString& 
   110 CollatorFactory::getDisplayName(const Locale& objectLocale, 
   111                                 const Locale& displayLocale,
   112                                 UnicodeString& result)
   113 {
   114   return objectLocale.getDisplayName(displayLocale, result);
   115 }
   117 // -------------------------------------
   119 class 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 };
   127 ICUCollatorFactory::~ICUCollatorFactory() {}
   129 UObject*
   130 ICUCollatorFactory::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);
   139         return Collator::makeInstance(loc, status);
   140     }
   141     return NULL;
   142 }
   144 // -------------------------------------
   146 class ICUCollatorService : public ICULocaleService {
   147 public:
   148     ICUCollatorService()
   149         : ICULocaleService(UNICODE_STRING_SIMPLE("Collator"))
   150     {
   151         UErrorCode status = U_ZERO_ERROR;
   152         registerFactory(new ICUCollatorFactory(), status);
   153     }
   155     virtual ~ICUCollatorService();
   157     virtual UObject* cloneInstance(UObject* instance) const {
   158         return ((Collator*)instance)->clone();
   159     }
   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     }
   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("");
   191             LocaleUtility::initLocaleFromName(*actualReturn, currentLocale);
   192             result->setLocales(lkey.canonicalLocale(canonicalLocale), currentLocale, currentLocale);
   193         }
   194         return result;
   195     }
   197     virtual UBool isDefault() const {
   198         return countFactories() == 1;
   199     }
   200 };
   202 ICUCollatorService::~ICUCollatorService() {}
   204 // -------------------------------------
   206 static void U_CALLCONV initService() {
   207     gService = new ICUCollatorService();
   208     ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
   209 }
   212 static ICULocaleService* 
   213 getService(void)
   214 {
   215     umtx_initOnce(gServiceInitOnce, &initService);
   216     return gService;
   217 }
   219 // -------------------------------------
   221 static inline UBool
   222 hasService(void) 
   223 {
   224     UBool retVal = !gServiceInitOnce.isReset() && (getService() != NULL);
   225     return retVal;
   226 }
   228 // -------------------------------------
   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         } 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 */
   264 static void U_CALLCONV 
   265 initAvailableLocaleList(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;
   273     ures_initStackObject(&installed);
   274     index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
   275     ures_getByKey(index, "InstalledLocales", &installed, &status);
   277     if(U_SUCCESS(status)) {
   278         availableLocaleListCount = ures_getSize(&installed);
   279         availableLocaleList = new Locale[availableLocaleListCount];
   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 }
   296 static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
   297     umtx_initOnce(gAvailableLocaleListInitOnce, &initAvailableLocaleList, status);
   298     return U_SUCCESS(status);
   299 }
   302 // Collator public methods -----------------------------------------------
   304 Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success) 
   305 {
   306     return createInstance(Locale::getDefault(), success);
   307 }
   309 Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale,
   310                                    UErrorCode& status)
   311 {
   312     if (U_FAILURE(status)) 
   313         return 0;
   315 #if !UCONFIG_NO_SERVICE
   316     if (hasService()) {
   317         Locale actualLoc;
   318         Collator *result =
   319             (Collator*)gService->get(desiredLocale, &actualLoc, status);
   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 }
   337 Collator* 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.
   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 }
   376 #ifdef U_USE_COLLATION_OBSOLETE_2_6
   377 // !!! dlf the following is obsolete, ignore registration for this
   379 Collator *
   380 Collator::createInstance(const Locale &loc,
   381                          UVersionInfo version,
   382                          UErrorCode &status)
   383 {
   384     Collator *collator;
   385     UVersionInfo info;
   387     collator=new RuleBasedCollator(loc, status);
   388     /* test for NULL */
   389     if (collator == 0) {
   390         status = U_MEMORY_ALLOCATION_ERROR;
   391         return 0;
   392     }
   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
   406 Collator *
   407 Collator::safeClone() const {
   408     return clone();
   409 }
   411 // implement deprecated, previously abstract method
   412 Collator::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 }
   419 // implement deprecated, previously abstract method
   420 Collator::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 }
   428 // implement deprecated, previously abstract method
   429 Collator::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 }
   437 UCollationResult 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 }
   447 UCollationResult 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 }
   459 UBool 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 }
   466 UBool 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 }
   473 UBool 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 }
   480 // this API  ignores registered collators, since it returns an
   481 // array of indefinite lifetime
   482 const 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 }
   495 UnicodeString& 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 }
   509 UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale,
   510                                         UnicodeString& name)
   511 {   
   512     return getDisplayName(objectLocale, Locale::getDefault(), name);
   513 }
   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 */
   523 // UCollator protected constructor destructor ----------------------------
   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 */
   531 Collator::Collator()
   532 : UObject()
   533 {
   534 }
   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 */
   546 Collator::Collator(UCollationStrength, UNormalizationMode )
   547 : UObject()
   548 {
   549 }
   551 Collator::~Collator()
   552 {
   553 }
   555 Collator::Collator(const Collator &other)
   556     : UObject(other)
   557 {
   558 }
   560 UBool 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 }
   566 UBool Collator::operator!=(const Collator& other) const
   567 {
   568     return (UBool)!(*this == other);
   569 }
   571 int32_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 }
   582 void
   583 Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) {
   584 }
   586 UnicodeSet *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 }
   595 // -------------------------------------
   597 #if !UCONFIG_NO_SERVICE
   598 URegistryKey U_EXPORT2
   599 Collator::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 }
   607 // -------------------------------------
   609 class CFactory : public LocaleKeyFactory {
   610 private:
   611     CollatorFactory* _delegate;
   612     Hashtable* _ids;
   614 public:
   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     }
   639     virtual ~CFactory();
   641     virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
   643 protected:
   644     virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
   645     {
   646         if (U_SUCCESS(status)) {
   647             return _ids;
   648         }
   649         return NULL;
   650     }
   652     virtual UnicodeString&
   653         getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const;
   654 };
   656 CFactory::~CFactory()
   657 {
   658     delete _delegate;
   659     delete _ids;
   660 }
   662 UObject* 
   663 CFactory::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 }
   674 UnicodeString&
   675 CFactory::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 }
   690 URegistryKey U_EXPORT2
   691 Collator::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 }
   703 // -------------------------------------
   705 UBool U_EXPORT2
   706 Collator::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 */
   718 class CollationLocaleListEnumeration : public StringEnumeration {
   719 private:
   720     int32_t index;
   721 public:
   722     static UClassID U_EXPORT2 getStaticClassID(void);
   723     virtual UClassID getDynamicClassID(void) const;
   724 public:
   725     CollationLocaleListEnumeration()
   726         : index(0)
   727     {
   728         // The global variables should already be initialized.
   729         //isAvailableLocaleListInitialized(status);
   730     }
   732     virtual ~CollationLocaleListEnumeration();
   734     virtual StringEnumeration * clone() const
   735     {
   736         CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration();
   737         if (result) {
   738             result->index = index;
   739         }
   740         return result;
   741     }
   743     virtual int32_t count(UErrorCode &/*status*/) const {
   744         return availableLocaleListCount;
   745     }
   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     }
   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     }
   769     virtual void reset(UErrorCode& /*status*/) {
   770         index = 0;
   771     }
   772 };
   774 CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {}
   776 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration)
   779 // -------------------------------------
   781 StringEnumeration* U_EXPORT2
   782 Collator::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 }
   796 StringEnumeration* U_EXPORT2
   797 Collator::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 }
   807 StringEnumeration* U_EXPORT2
   808 Collator::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 }
   818 StringEnumeration* U_EXPORT2
   819 Collator::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 }
   831 Locale U_EXPORT2
   832 Collator::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 }
   844 Collator::ECollationStrength
   845 Collator::getStrength(void) const {
   846     UErrorCode intStatus = U_ZERO_ERROR;
   847     return (ECollationStrength)getAttribute(UCOL_STRENGTH, intStatus);
   848 }
   850 void
   851 Collator::setStrength(ECollationStrength newStrength) {
   852     UErrorCode intStatus = U_ZERO_ERROR;
   853     setAttribute(UCOL_STRENGTH, (UColAttributeValue)newStrength, intStatus);
   854 }
   856 int32_t
   857 Collator::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 }
   867 void
   868 Collator::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 }
   877 int32_t U_EXPORT2
   878 Collator::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 }
   889 int32_t
   890 Collator::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 }
   900 // UCollator private data members ----------------------------------------
   902 /* This is useless information */
   903 /*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/
   905 // -------------------------------------
   907 U_NAMESPACE_END
   909 #endif /* #if !UCONFIG_NO_COLLATION */
   911 /* eof */

mercurial