LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - coll.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 407 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 82 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 2016 and later: Unicode, Inc. and others.
       2             : // License & terms of use: http://www.unicode.org/copyright.html
       3             : /*
       4             :  ******************************************************************************
       5             :  * Copyright (C) 1996-2014, International Business Machines Corporation and
       6             :  * others. All Rights Reserved.
       7             :  ******************************************************************************
       8             :  */
       9             : 
      10             : /**
      11             :  * File coll.cpp
      12             :  *
      13             :  * Created by: Helena Shih
      14             :  *
      15             :  * Modification History:
      16             :  *
      17             :  *  Date        Name        Description
      18             :  *  2/5/97      aliu        Modified createDefault to load collation data from
      19             :  *                          binary files when possible.  Added related methods
      20             :  *                          createCollationFromFile, chopLocale, createPathName.
      21             :  *  2/11/97     aliu        Added methods addToCache, findInCache, which implement
      22             :  *                          a Collation cache.  Modified createDefault to look in
      23             :  *                          cache first, and also to store newly created Collation
      24             :  *                          objects in the cache.  Modified to not use gLocPath.
      25             :  *  2/12/97     aliu        Modified to create objects from RuleBasedCollator cache.
      26             :  *                          Moved cache out of Collation class.
      27             :  *  2/13/97     aliu        Moved several methods out of this class and into
      28             :  *                          RuleBasedCollator, with modifications.  Modified
      29             :  *                          createDefault() to call new RuleBasedCollator(Locale&)
      30             :  *                          constructor.  General clean up and documentation.
      31             :  *  2/20/97     helena      Added clone, operator==, operator!=, operator=, and copy
      32             :  *                          constructor.
      33             :  * 05/06/97     helena      Added memory allocation error detection.
      34             :  * 05/08/97     helena      Added createInstance().
      35             :  *  6/20/97     helena      Java class name change.
      36             :  * 04/23/99     stephen     Removed EDecompositionMode, merged with 
      37             :  *                          Normalizer::EMode
      38             :  * 11/23/9      srl         Inlining of some critical functions
      39             :  * 01/29/01     synwee      Modified into a C++ wrapper calling C APIs (ucol.h)
      40             :  * 2012-2014    markus      Rewritten in C++ again.
      41             :  */
      42             : 
      43             : #include "utypeinfo.h"  // for 'typeid' to work 
      44             : 
      45             : #include "unicode/utypes.h"
      46             : 
      47             : #if !UCONFIG_NO_COLLATION
      48             : 
      49             : #include "unicode/coll.h"
      50             : #include "unicode/tblcoll.h"
      51             : #include "collationdata.h"
      52             : #include "collationroot.h"
      53             : #include "collationtailoring.h"
      54             : #include "ucol_imp.h"
      55             : #include "cstring.h"
      56             : #include "cmemory.h"
      57             : #include "umutex.h"
      58             : #include "servloc.h"
      59             : #include "uassert.h"
      60             : #include "ustrenum.h"
      61             : #include "uresimp.h"
      62             : #include "ucln_in.h"
      63             : 
      64             : static icu::Locale* availableLocaleList = NULL;
      65             : static int32_t  availableLocaleListCount;
      66             : static icu::ICULocaleService* gService = NULL;
      67             : static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
      68             : static icu::UInitOnce gAvailableLocaleListInitOnce;
      69             : 
      70             : /**
      71             :  * Release all static memory held by collator.
      72             :  */
      73             : U_CDECL_BEGIN
      74           0 : static UBool U_CALLCONV collator_cleanup(void) {
      75             : #if !UCONFIG_NO_SERVICE
      76           0 :     if (gService) {
      77           0 :         delete gService;
      78           0 :         gService = NULL;
      79             :     }
      80           0 :     gServiceInitOnce.reset();
      81             : #endif
      82           0 :     if (availableLocaleList) {
      83           0 :         delete []availableLocaleList;
      84           0 :         availableLocaleList = NULL;
      85             :     }
      86           0 :     availableLocaleListCount = 0;
      87           0 :     gAvailableLocaleListInitOnce.reset();
      88           0 :     return TRUE;
      89             : }
      90             : 
      91             : U_CDECL_END
      92             : 
      93             : U_NAMESPACE_BEGIN
      94             : 
      95             : #if !UCONFIG_NO_SERVICE
      96             : 
      97             : // ------------------------------------------
      98             : //
      99             : // Registration
     100             : //
     101             : 
     102             : //-------------------------------------------
     103             : 
     104           0 : CollatorFactory::~CollatorFactory() {}
     105             : 
     106             : //-------------------------------------------
     107             : 
     108             : UBool
     109           0 : CollatorFactory::visible(void) const {
     110           0 :     return TRUE;
     111             : }
     112             : 
     113             : //-------------------------------------------
     114             : 
     115             : UnicodeString& 
     116           0 : CollatorFactory::getDisplayName(const Locale& objectLocale, 
     117             :                                 const Locale& displayLocale,
     118             :                                 UnicodeString& result)
     119             : {
     120           0 :   return objectLocale.getDisplayName(displayLocale, result);
     121             : }
     122             : 
     123             : // -------------------------------------
     124             : 
     125             : class ICUCollatorFactory : public ICUResourceBundleFactory {
     126             :  public:
     127           0 :     ICUCollatorFactory() : ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL, -1, US_INV)) { }
     128             :     virtual ~ICUCollatorFactory();
     129             :  protected:
     130             :     virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
     131             : };
     132             : 
     133           0 : ICUCollatorFactory::~ICUCollatorFactory() {}
     134             : 
     135             : UObject*
     136           0 : ICUCollatorFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const {
     137           0 :     if (handlesKey(key, status)) {
     138           0 :         const LocaleKey& lkey = (const LocaleKey&)key;
     139           0 :         Locale loc;
     140             :         // make sure the requested locale is correct
     141             :         // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey
     142             :         // but for ICU rb resources we use the actual one since it will fallback again
     143           0 :         lkey.canonicalLocale(loc);
     144             :         
     145           0 :         return Collator::makeInstance(loc, status);
     146             :     }
     147           0 :     return NULL;
     148             : }
     149             : 
     150             : // -------------------------------------
     151             : 
     152             : class ICUCollatorService : public ICULocaleService {
     153             : public:
     154           0 :     ICUCollatorService()
     155           0 :         : ICULocaleService(UNICODE_STRING_SIMPLE("Collator"))
     156             :     {
     157           0 :         UErrorCode status = U_ZERO_ERROR;
     158           0 :         registerFactory(new ICUCollatorFactory(), status);
     159           0 :     }
     160             : 
     161             :     virtual ~ICUCollatorService();
     162             : 
     163           0 :     virtual UObject* cloneInstance(UObject* instance) const {
     164           0 :         return ((Collator*)instance)->clone();
     165             :     }
     166             :     
     167           0 :     virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const {
     168           0 :         LocaleKey& lkey = (LocaleKey&)key;
     169           0 :         if (actualID) {
     170             :             // Ugly Hack Alert! We return an empty actualID to signal
     171             :             // to callers that this is a default object, not a "real"
     172             :             // service-created object. (TODO remove in 3.0) [aliu]
     173           0 :             actualID->truncate(0);
     174             :         }
     175           0 :         Locale loc("");
     176           0 :         lkey.canonicalLocale(loc);
     177           0 :         return Collator::makeInstance(loc, status);
     178             :     }
     179             :     
     180           0 :     virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const {
     181           0 :         UnicodeString ar;
     182           0 :         if (actualReturn == NULL) {
     183           0 :             actualReturn = &ar;
     184             :         }
     185           0 :         return (Collator*)ICULocaleService::getKey(key, actualReturn, status);
     186             :     }
     187             : 
     188           0 :     virtual UBool isDefault() const {
     189           0 :         return countFactories() == 1;
     190             :     }
     191             : };
     192             : 
     193           0 : ICUCollatorService::~ICUCollatorService() {}
     194             : 
     195             : // -------------------------------------
     196             : 
     197           0 : static void U_CALLCONV initService() {
     198           0 :     gService = new ICUCollatorService();
     199           0 :     ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
     200           0 : }
     201             : 
     202             : 
     203             : static ICULocaleService* 
     204           0 : getService(void)
     205             : {
     206           0 :     umtx_initOnce(gServiceInitOnce, &initService);
     207           0 :     return gService;
     208             : }
     209             : 
     210             : // -------------------------------------
     211             : 
     212             : static inline UBool
     213           0 : hasService(void) 
     214             : {
     215           0 :     UBool retVal = !gServiceInitOnce.isReset() && (getService() != NULL);
     216           0 :     return retVal;
     217             : }
     218             : 
     219             : #endif /* UCONFIG_NO_SERVICE */
     220             : 
     221             : static void U_CALLCONV 
     222           0 : initAvailableLocaleList(UErrorCode &status) {
     223           0 :     U_ASSERT(availableLocaleListCount == 0);
     224           0 :     U_ASSERT(availableLocaleList == NULL);
     225             :     // for now, there is a hardcoded list, so just walk through that list and set it up.
     226           0 :     UResourceBundle *index = NULL;
     227             :     UResourceBundle installed;
     228           0 :     int32_t i = 0;
     229             :     
     230           0 :     ures_initStackObject(&installed);
     231           0 :     index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
     232           0 :     ures_getByKey(index, "InstalledLocales", &installed, &status);
     233             :     
     234           0 :     if(U_SUCCESS(status)) {
     235           0 :         availableLocaleListCount = ures_getSize(&installed);
     236           0 :         availableLocaleList = new Locale[availableLocaleListCount];
     237             :         
     238           0 :         if (availableLocaleList != NULL) {
     239           0 :             ures_resetIterator(&installed);
     240           0 :             while(ures_hasNext(&installed)) {
     241           0 :                 const char *tempKey = NULL;
     242           0 :                 ures_getNextString(&installed, NULL, &tempKey, &status);
     243           0 :                 availableLocaleList[i++] = Locale(tempKey);
     244             :             }
     245             :         }
     246           0 :         U_ASSERT(availableLocaleListCount == i);
     247           0 :         ures_close(&installed);
     248             :     }
     249           0 :     ures_close(index);
     250           0 :     ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
     251           0 : }
     252             : 
     253           0 : static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
     254           0 :     umtx_initOnce(gAvailableLocaleListInitOnce, &initAvailableLocaleList, status);
     255           0 :     return U_SUCCESS(status);
     256             : }
     257             : 
     258             : 
     259             : // Collator public methods -----------------------------------------------
     260             : 
     261             : namespace {
     262             : 
     263             : static const struct {
     264             :     const char *name;
     265             :     UColAttribute attr;
     266             : } collAttributes[] = {
     267             :     { "colStrength", UCOL_STRENGTH },
     268             :     { "colBackwards", UCOL_FRENCH_COLLATION },
     269             :     { "colCaseLevel", UCOL_CASE_LEVEL },
     270             :     { "colCaseFirst", UCOL_CASE_FIRST },
     271             :     { "colAlternate", UCOL_ALTERNATE_HANDLING },
     272             :     { "colNormalization", UCOL_NORMALIZATION_MODE },
     273             :     { "colNumeric", UCOL_NUMERIC_COLLATION }
     274             : };
     275             : 
     276             : static const struct {
     277             :     const char *name;
     278             :     UColAttributeValue value;
     279             : } collAttributeValues[] = {
     280             :     { "primary", UCOL_PRIMARY },
     281             :     { "secondary", UCOL_SECONDARY },
     282             :     { "tertiary", UCOL_TERTIARY },
     283             :     { "quaternary", UCOL_QUATERNARY },
     284             :     // Note: Not supporting typo "quarternary" because it was never supported in locale IDs.
     285             :     { "identical", UCOL_IDENTICAL },
     286             :     { "no", UCOL_OFF },
     287             :     { "yes", UCOL_ON },
     288             :     { "shifted", UCOL_SHIFTED },
     289             :     { "non-ignorable", UCOL_NON_IGNORABLE },
     290             :     { "lower", UCOL_LOWER_FIRST },
     291             :     { "upper", UCOL_UPPER_FIRST }
     292             : };
     293             : 
     294             : static const char *collReorderCodes[UCOL_REORDER_CODE_LIMIT - UCOL_REORDER_CODE_FIRST] = {
     295             :     "space", "punct", "symbol", "currency", "digit"
     296             : };
     297             : 
     298           0 : int32_t getReorderCode(const char *s) {
     299           0 :     for (int32_t i = 0; i < UPRV_LENGTHOF(collReorderCodes); ++i) {
     300           0 :         if (uprv_stricmp(s, collReorderCodes[i]) == 0) {
     301           0 :             return UCOL_REORDER_CODE_FIRST + i;
     302             :         }
     303             :     }
     304             :     // Not supporting "others" = UCOL_REORDER_CODE_OTHERS
     305             :     // as a synonym for Zzzz = USCRIPT_UNKNOWN for now:
     306             :     // Avoid introducing synonyms/aliases.
     307           0 :     return -1;
     308             : }
     309             : 
     310             : /**
     311             :  * Sets collation attributes according to locale keywords. See
     312             :  * http://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Settings
     313             :  *
     314             :  * Using "alias" keywords and values where defined:
     315             :  * http://www.unicode.org/reports/tr35/tr35.html#Old_Locale_Extension_Syntax
     316             :  * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml
     317             :  */
     318           0 : void setAttributesFromKeywords(const Locale &loc, Collator &coll, UErrorCode &errorCode) {
     319           0 :     if (U_FAILURE(errorCode)) {
     320           0 :         return;
     321             :     }
     322           0 :     if (uprv_strcmp(loc.getName(), loc.getBaseName()) == 0) {
     323             :         // No keywords.
     324           0 :         return;
     325             :     }
     326             :     char value[1024];  // The reordering value could be long.
     327             :     // Check for collation keywords that were already deprecated
     328             :     // before any were supported in createInstance() (except for "collation").
     329           0 :     int32_t length = loc.getKeywordValue("colHiraganaQuaternary", value, UPRV_LENGTHOF(value), errorCode);
     330           0 :     if (U_FAILURE(errorCode)) {
     331           0 :         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     332           0 :         return;
     333             :     }
     334           0 :     if (length != 0) {
     335           0 :         errorCode = U_UNSUPPORTED_ERROR;
     336           0 :         return;
     337             :     }
     338           0 :     length = loc.getKeywordValue("variableTop", value, UPRV_LENGTHOF(value), errorCode);
     339           0 :     if (U_FAILURE(errorCode)) {
     340           0 :         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     341           0 :         return;
     342             :     }
     343           0 :     if (length != 0) {
     344           0 :         errorCode = U_UNSUPPORTED_ERROR;
     345           0 :         return;
     346             :     }
     347             :     // Parse known collation keywords, ignore others.
     348           0 :     if (errorCode == U_STRING_NOT_TERMINATED_WARNING) {
     349           0 :         errorCode = U_ZERO_ERROR;
     350             :     }
     351           0 :     for (int32_t i = 0; i < UPRV_LENGTHOF(collAttributes); ++i) {
     352           0 :         length = loc.getKeywordValue(collAttributes[i].name, value, UPRV_LENGTHOF(value), errorCode);
     353           0 :         if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
     354           0 :             errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     355           0 :             return;
     356             :         }
     357           0 :         if (length == 0) { continue; }
     358           0 :         for (int32_t j = 0;; ++j) {
     359           0 :             if (j == UPRV_LENGTHOF(collAttributeValues)) {
     360           0 :                 errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     361           0 :                 return;
     362             :             }
     363           0 :             if (uprv_stricmp(value, collAttributeValues[j].name) == 0) {
     364           0 :                 coll.setAttribute(collAttributes[i].attr, collAttributeValues[j].value, errorCode);
     365           0 :                 break;
     366             :             }
     367             :         }
     368             :     }
     369           0 :     length = loc.getKeywordValue("colReorder", value, UPRV_LENGTHOF(value), errorCode);
     370           0 :     if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
     371           0 :         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     372           0 :         return;
     373             :     }
     374           0 :     if (length != 0) {
     375             :         int32_t codes[USCRIPT_CODE_LIMIT + UCOL_REORDER_CODE_LIMIT - UCOL_REORDER_CODE_FIRST];
     376           0 :         int32_t codesLength = 0;
     377           0 :         char *scriptName = value;
     378             :         for (;;) {
     379           0 :             if (codesLength == UPRV_LENGTHOF(codes)) {
     380           0 :                 errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     381           0 :                 return;
     382             :             }
     383           0 :             char *limit = scriptName;
     384             :             char c;
     385           0 :             while ((c = *limit) != 0 && c != '-') { ++limit; }
     386           0 :             *limit = 0;
     387             :             int32_t code;
     388           0 :             if ((limit - scriptName) == 4) {
     389             :                 // Strict parsing, accept only 4-letter script codes, not long names.
     390           0 :                 code = u_getPropertyValueEnum(UCHAR_SCRIPT, scriptName);
     391             :             } else {
     392           0 :                 code = getReorderCode(scriptName);
     393             :             }
     394           0 :             if (code < 0) {
     395           0 :                 errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     396           0 :                 return;
     397             :             }
     398           0 :             codes[codesLength++] = code;
     399           0 :             if (c == 0) { break; }
     400           0 :             scriptName = limit + 1;
     401           0 :         }
     402           0 :         coll.setReorderCodes(codes, codesLength, errorCode);
     403             :     }
     404           0 :     length = loc.getKeywordValue("kv", value, UPRV_LENGTHOF(value), errorCode);
     405           0 :     if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
     406           0 :         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     407           0 :         return;
     408             :     }
     409           0 :     if (length != 0) {
     410           0 :         int32_t code = getReorderCode(value);
     411           0 :         if (code < 0) {
     412           0 :             errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     413           0 :             return;
     414             :         }
     415           0 :         coll.setMaxVariable((UColReorderCode)code, errorCode);
     416             :     }
     417           0 :     if (U_FAILURE(errorCode)) {
     418           0 :         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     419             :     }
     420             : }
     421             : 
     422             : }  // namespace
     423             : 
     424           0 : Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success) 
     425             : {
     426           0 :     return createInstance(Locale::getDefault(), success);
     427             : }
     428             : 
     429           0 : Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale,
     430             :                                    UErrorCode& status)
     431             : {
     432           0 :     if (U_FAILURE(status)) 
     433           0 :         return 0;
     434           0 :     if (desiredLocale.isBogus()) {
     435             :         // Locale constructed from malformed locale ID or language tag.
     436           0 :         status = U_ILLEGAL_ARGUMENT_ERROR;
     437           0 :         return NULL;
     438             :     }
     439             : 
     440             :     Collator* coll;
     441             : #if !UCONFIG_NO_SERVICE
     442           0 :     if (hasService()) {
     443           0 :         Locale actualLoc;
     444           0 :         coll = (Collator*)gService->get(desiredLocale, &actualLoc, status);
     445             :     } else
     446             : #endif
     447             :     {
     448           0 :         coll = makeInstance(desiredLocale, status);
     449             :     }
     450           0 :     setAttributesFromKeywords(desiredLocale, *coll, status);
     451           0 :     if (U_FAILURE(status)) {
     452           0 :         delete coll;
     453           0 :         return NULL;
     454             :     }
     455           0 :     return coll;
     456             : }
     457             : 
     458             : 
     459           0 : Collator* Collator::makeInstance(const Locale&  desiredLocale, UErrorCode& status) {
     460           0 :     const CollationCacheEntry *entry = CollationLoader::loadTailoring(desiredLocale, status);
     461           0 :     if (U_SUCCESS(status)) {
     462           0 :         Collator *result = new RuleBasedCollator(entry);
     463           0 :         if (result != NULL) {
     464             :             // Both the unified cache's get() and the RBC constructor
     465             :             // did addRef(). Undo one of them.
     466           0 :             entry->removeRef();
     467           0 :             return result;
     468             :         }
     469           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     470             :     }
     471           0 :     if (entry != NULL) {
     472             :         // Undo the addRef() from the cache.get().
     473           0 :         entry->removeRef();
     474             :     }
     475           0 :     return NULL;
     476             : }
     477             : 
     478             : Collator *
     479           0 : Collator::safeClone() const {
     480           0 :     return clone();
     481             : }
     482             : 
     483             : // implement deprecated, previously abstract method
     484           0 : Collator::EComparisonResult Collator::compare(const UnicodeString& source, 
     485             :                                     const UnicodeString& target) const
     486             : {
     487           0 :     UErrorCode ec = U_ZERO_ERROR;
     488           0 :     return (EComparisonResult)compare(source, target, ec);
     489             : }
     490             : 
     491             : // implement deprecated, previously abstract method
     492           0 : Collator::EComparisonResult Collator::compare(const UnicodeString& source,
     493             :                                     const UnicodeString& target,
     494             :                                     int32_t length) const
     495             : {
     496           0 :     UErrorCode ec = U_ZERO_ERROR;
     497           0 :     return (EComparisonResult)compare(source, target, length, ec);
     498             : }
     499             : 
     500             : // implement deprecated, previously abstract method
     501           0 : Collator::EComparisonResult Collator::compare(const UChar* source, int32_t sourceLength,
     502             :                                     const UChar* target, int32_t targetLength) 
     503             :                                     const
     504             : {
     505           0 :     UErrorCode ec = U_ZERO_ERROR;
     506           0 :     return (EComparisonResult)compare(source, sourceLength, target, targetLength, ec);
     507             : }
     508             : 
     509           0 : UCollationResult Collator::compare(UCharIterator &/*sIter*/,
     510             :                                    UCharIterator &/*tIter*/,
     511             :                                    UErrorCode &status) const {
     512           0 :     if(U_SUCCESS(status)) {
     513             :         // Not implemented in the base class.
     514           0 :         status = U_UNSUPPORTED_ERROR;
     515             :     }
     516           0 :     return UCOL_EQUAL;
     517             : }
     518             : 
     519           0 : UCollationResult Collator::compareUTF8(const StringPiece &source,
     520             :                                        const StringPiece &target,
     521             :                                        UErrorCode &status) const {
     522           0 :     if(U_FAILURE(status)) {
     523           0 :         return UCOL_EQUAL;
     524             :     }
     525             :     UCharIterator sIter, tIter;
     526           0 :     uiter_setUTF8(&sIter, source.data(), source.length());
     527           0 :     uiter_setUTF8(&tIter, target.data(), target.length());
     528           0 :     return compare(sIter, tIter, status);
     529             : }
     530             : 
     531           0 : UBool Collator::equals(const UnicodeString& source, 
     532             :                        const UnicodeString& target) const
     533             : {
     534           0 :     UErrorCode ec = U_ZERO_ERROR;
     535           0 :     return (compare(source, target, ec) == UCOL_EQUAL);
     536             : }
     537             : 
     538           0 : UBool Collator::greaterOrEqual(const UnicodeString& source, 
     539             :                                const UnicodeString& target) const
     540             : {
     541           0 :     UErrorCode ec = U_ZERO_ERROR;
     542           0 :     return (compare(source, target, ec) != UCOL_LESS);
     543             : }
     544             : 
     545           0 : UBool Collator::greater(const UnicodeString& source, 
     546             :                         const UnicodeString& target) const
     547             : {
     548           0 :     UErrorCode ec = U_ZERO_ERROR;
     549           0 :     return (compare(source, target, ec) == UCOL_GREATER);
     550             : }
     551             : 
     552             : // this API  ignores registered collators, since it returns an
     553             : // array of indefinite lifetime
     554           0 : const Locale* U_EXPORT2 Collator::getAvailableLocales(int32_t& count) 
     555             : {
     556           0 :     UErrorCode status = U_ZERO_ERROR;
     557           0 :     Locale *result = NULL;
     558           0 :     count = 0;
     559           0 :     if (isAvailableLocaleListInitialized(status))
     560             :     {
     561           0 :         result = availableLocaleList;
     562           0 :         count = availableLocaleListCount;
     563             :     }
     564           0 :     return result;
     565             : }
     566             : 
     567           0 : UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale,
     568             :                                         const Locale& displayLocale,
     569             :                                         UnicodeString& name)
     570             : {
     571             : #if !UCONFIG_NO_SERVICE
     572           0 :     if (hasService()) {
     573           0 :         UnicodeString locNameStr;
     574           0 :         LocaleUtility::initNameFromLocale(objectLocale, locNameStr);
     575           0 :         return gService->getDisplayName(locNameStr, name, displayLocale);
     576             :     }
     577             : #endif
     578           0 :     return objectLocale.getDisplayName(displayLocale, name);
     579             : }
     580             : 
     581           0 : UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale,
     582             :                                         UnicodeString& name)
     583             : {   
     584           0 :     return getDisplayName(objectLocale, Locale::getDefault(), name);
     585             : }
     586             : 
     587             : /* This is useless information */
     588             : /*void Collator::getVersion(UVersionInfo versionInfo) const
     589             : {
     590             :   if (versionInfo!=NULL)
     591             :     uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH);
     592             : }
     593             : */
     594             : 
     595             : // UCollator protected constructor destructor ----------------------------
     596             : 
     597             : /**
     598             : * Default constructor.
     599             : * Constructor is different from the old default Collator constructor.
     600             : * The task for determing the default collation strength and normalization mode
     601             : * is left to the child class.
     602             : */
     603           0 : Collator::Collator()
     604           0 : : UObject()
     605             : {
     606           0 : }
     607             : 
     608             : /**
     609             : * Constructor.
     610             : * Empty constructor, does not handle the arguments.
     611             : * This constructor is done for backward compatibility with 1.7 and 1.8.
     612             : * The task for handling the argument collation strength and normalization 
     613             : * mode is left to the child class.
     614             : * @param collationStrength collation strength
     615             : * @param decompositionMode
     616             : * @deprecated 2.4 use the default constructor instead
     617             : */
     618           0 : Collator::Collator(UCollationStrength, UNormalizationMode )
     619           0 : : UObject()
     620             : {
     621           0 : }
     622             : 
     623           0 : Collator::~Collator()
     624             : {
     625           0 : }
     626             : 
     627           0 : Collator::Collator(const Collator &other)
     628           0 :     : UObject(other)
     629             : {
     630           0 : }
     631             : 
     632           0 : UBool Collator::operator==(const Collator& other) const
     633             : {
     634             :     // Subclasses: Call this method and then add more specific checks.
     635           0 :     return typeid(*this) == typeid(other);
     636             : }
     637             : 
     638           0 : UBool Collator::operator!=(const Collator& other) const
     639             : {
     640           0 :     return (UBool)!(*this == other);
     641             : }
     642             : 
     643           0 : int32_t U_EXPORT2 Collator::getBound(const uint8_t       *source,
     644             :                            int32_t             sourceLength,
     645             :                            UColBoundMode       boundType,
     646             :                            uint32_t            noOfLevels,
     647             :                            uint8_t             *result,
     648             :                            int32_t             resultLength,
     649             :                            UErrorCode          &status)
     650             : {
     651           0 :     return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status);
     652             : }
     653             : 
     654             : void
     655           0 : Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) {
     656           0 : }
     657             : 
     658           0 : UnicodeSet *Collator::getTailoredSet(UErrorCode &status) const
     659             : {
     660           0 :     if(U_FAILURE(status)) {
     661           0 :         return NULL;
     662             :     }
     663             :     // everything can be changed
     664           0 :     return new UnicodeSet(0, 0x10FFFF);
     665             : }
     666             : 
     667             : // -------------------------------------
     668             : 
     669             : #if !UCONFIG_NO_SERVICE
     670             : URegistryKey U_EXPORT2
     671           0 : Collator::registerInstance(Collator* toAdopt, const Locale& locale, UErrorCode& status) 
     672             : {
     673           0 :     if (U_SUCCESS(status)) {
     674             :         // Set the collator locales while registering so that createInstance()
     675             :         // need not guess whether the collator's locales are already set properly
     676             :         // (as they are by the data loader).
     677           0 :         toAdopt->setLocales(locale, locale, locale);
     678           0 :         return getService()->registerInstance(toAdopt, locale, status);
     679             :     }
     680           0 :     return NULL;
     681             : }
     682             : 
     683             : // -------------------------------------
     684             : 
     685             : class CFactory : public LocaleKeyFactory {
     686             : private:
     687             :     CollatorFactory* _delegate;
     688             :     Hashtable* _ids;
     689             :     
     690             : public:
     691           0 :     CFactory(CollatorFactory* delegate, UErrorCode& status) 
     692           0 :         : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
     693             :         , _delegate(delegate)
     694           0 :         , _ids(NULL)
     695             :     {
     696           0 :         if (U_SUCCESS(status)) {
     697           0 :             int32_t count = 0;
     698           0 :             _ids = new Hashtable(status);
     699           0 :             if (_ids) {
     700           0 :                 const UnicodeString * idlist = _delegate->getSupportedIDs(count, status);
     701           0 :                 for (int i = 0; i < count; ++i) {
     702           0 :                     _ids->put(idlist[i], (void*)this, status);
     703           0 :                     if (U_FAILURE(status)) {
     704           0 :                         delete _ids;
     705           0 :                         _ids = NULL;
     706           0 :                         return;
     707             :                     }
     708             :                 }
     709             :             } else {
     710           0 :                 status = U_MEMORY_ALLOCATION_ERROR;
     711             :             }
     712             :         }
     713             :     }
     714             : 
     715             :     virtual ~CFactory();
     716             : 
     717             :     virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
     718             :     
     719             : protected:
     720           0 :     virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
     721             :     {
     722           0 :         if (U_SUCCESS(status)) {
     723           0 :             return _ids;
     724             :         }
     725           0 :         return NULL;
     726             :     }
     727             :     
     728             :     virtual UnicodeString&
     729             :         getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const;
     730             : };
     731             : 
     732           0 : CFactory::~CFactory()
     733             : {
     734           0 :     delete _delegate;
     735           0 :     delete _ids;
     736           0 : }
     737             : 
     738             : UObject* 
     739           0 : CFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const
     740             : {
     741           0 :     if (handlesKey(key, status)) {
     742           0 :         const LocaleKey& lkey = (const LocaleKey&)key;
     743           0 :         Locale validLoc;
     744           0 :         lkey.currentLocale(validLoc);
     745           0 :         return _delegate->createCollator(validLoc);
     746             :     }
     747           0 :     return NULL;
     748             : }
     749             : 
     750             : UnicodeString&
     751           0 : CFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const 
     752             : {
     753           0 :     if ((_coverage & 0x1) == 0) {
     754           0 :         UErrorCode status = U_ZERO_ERROR;
     755           0 :         const Hashtable* ids = getSupportedIDs(status);
     756           0 :         if (ids && (ids->get(id) != NULL)) {
     757           0 :             Locale loc;
     758           0 :             LocaleUtility::initLocaleFromName(id, loc);
     759           0 :             return _delegate->getDisplayName(loc, locale, result);
     760             :         }
     761             :     }
     762           0 :     result.setToBogus();
     763           0 :     return result;
     764             : }
     765             : 
     766             : URegistryKey U_EXPORT2
     767           0 : Collator::registerFactory(CollatorFactory* toAdopt, UErrorCode& status)
     768             : {
     769           0 :     if (U_SUCCESS(status)) {
     770           0 :         CFactory* f = new CFactory(toAdopt, status);
     771           0 :         if (f) {
     772           0 :             return getService()->registerFactory(f, status);
     773             :         }
     774           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     775             :     }
     776           0 :     return NULL;
     777             : }
     778             : 
     779             : // -------------------------------------
     780             : 
     781             : UBool U_EXPORT2
     782           0 : Collator::unregister(URegistryKey key, UErrorCode& status) 
     783             : {
     784           0 :     if (U_SUCCESS(status)) {
     785           0 :         if (hasService()) {
     786           0 :             return gService->unregister(key, status);
     787             :         }
     788           0 :         status = U_ILLEGAL_ARGUMENT_ERROR;
     789             :     }
     790           0 :     return FALSE;
     791             : }
     792             : #endif /* UCONFIG_NO_SERVICE */
     793             : 
     794             : class CollationLocaleListEnumeration : public StringEnumeration {
     795             : private:
     796             :     int32_t index;
     797             : public:
     798             :     static UClassID U_EXPORT2 getStaticClassID(void);
     799             :     virtual UClassID getDynamicClassID(void) const;
     800             : public:
     801           0 :     CollationLocaleListEnumeration()
     802           0 :         : index(0)
     803             :     {
     804             :         // The global variables should already be initialized.
     805             :         //isAvailableLocaleListInitialized(status);
     806           0 :     }
     807             : 
     808             :     virtual ~CollationLocaleListEnumeration();
     809             : 
     810           0 :     virtual StringEnumeration * clone() const
     811             :     {
     812           0 :         CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration();
     813           0 :         if (result) {
     814           0 :             result->index = index;
     815             :         }
     816           0 :         return result;
     817             :     }
     818             : 
     819           0 :     virtual int32_t count(UErrorCode &/*status*/) const {
     820           0 :         return availableLocaleListCount;
     821             :     }
     822             : 
     823           0 :     virtual const char* next(int32_t* resultLength, UErrorCode& /*status*/) {
     824             :         const char* result;
     825           0 :         if(index < availableLocaleListCount) {
     826           0 :             result = availableLocaleList[index++].getName();
     827           0 :             if(resultLength != NULL) {
     828           0 :                 *resultLength = (int32_t)uprv_strlen(result);
     829             :             }
     830             :         } else {
     831           0 :             if(resultLength != NULL) {
     832           0 :                 *resultLength = 0;
     833             :             }
     834           0 :             result = NULL;
     835             :         }
     836           0 :         return result;
     837             :     }
     838             : 
     839           0 :     virtual const UnicodeString* snext(UErrorCode& status) {
     840           0 :         int32_t resultLength = 0;
     841           0 :         const char *s = next(&resultLength, status);
     842           0 :         return setChars(s, resultLength, status);
     843             :     }
     844             : 
     845           0 :     virtual void reset(UErrorCode& /*status*/) {
     846           0 :         index = 0;
     847           0 :     }
     848             : };
     849             : 
     850           0 : CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {}
     851             : 
     852           0 : UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration)
     853             : 
     854             : 
     855             : // -------------------------------------
     856             : 
     857             : StringEnumeration* U_EXPORT2
     858           0 : Collator::getAvailableLocales(void)
     859             : {
     860             : #if !UCONFIG_NO_SERVICE
     861           0 :     if (hasService()) {
     862           0 :         return getService()->getAvailableLocales();
     863             :     }
     864             : #endif /* UCONFIG_NO_SERVICE */
     865           0 :     UErrorCode status = U_ZERO_ERROR;
     866           0 :     if (isAvailableLocaleListInitialized(status)) {
     867           0 :         return new CollationLocaleListEnumeration();
     868             :     }
     869           0 :     return NULL;
     870             : }
     871             : 
     872             : StringEnumeration* U_EXPORT2
     873           0 : Collator::getKeywords(UErrorCode& status) {
     874           0 :     return UStringEnumeration::fromUEnumeration(
     875           0 :             ucol_getKeywords(&status), status);
     876             : }
     877             : 
     878             : StringEnumeration* U_EXPORT2
     879           0 : Collator::getKeywordValues(const char *keyword, UErrorCode& status) {
     880           0 :     return UStringEnumeration::fromUEnumeration(
     881           0 :             ucol_getKeywordValues(keyword, &status), status);
     882             : }
     883             : 
     884             : StringEnumeration* U_EXPORT2
     885           0 : Collator::getKeywordValuesForLocale(const char* key, const Locale& locale,
     886             :                                     UBool commonlyUsed, UErrorCode& status) {
     887           0 :     return UStringEnumeration::fromUEnumeration(
     888             :             ucol_getKeywordValuesForLocale(
     889             :                     key, locale.getName(), commonlyUsed, &status),
     890           0 :             status);
     891             : }
     892             : 
     893             : Locale U_EXPORT2
     894           0 : Collator::getFunctionalEquivalent(const char* keyword, const Locale& locale,
     895             :                                   UBool& isAvailable, UErrorCode& status) {
     896             :     // This is a wrapper over ucol_getFunctionalEquivalent
     897             :     char loc[ULOC_FULLNAME_CAPACITY];
     898           0 :     /*int32_t len =*/ ucol_getFunctionalEquivalent(loc, sizeof(loc),
     899           0 :                     keyword, locale.getName(), &isAvailable, &status);
     900           0 :     if (U_FAILURE(status)) {
     901           0 :         *loc = 0; // root
     902             :     }
     903           0 :     return Locale::createFromName(loc);
     904             : }
     905             : 
     906             : Collator::ECollationStrength
     907           0 : Collator::getStrength(void) const {
     908           0 :     UErrorCode intStatus = U_ZERO_ERROR;
     909           0 :     return (ECollationStrength)getAttribute(UCOL_STRENGTH, intStatus);
     910             : }
     911             : 
     912             : void
     913           0 : Collator::setStrength(ECollationStrength newStrength) {
     914           0 :     UErrorCode intStatus = U_ZERO_ERROR;
     915           0 :     setAttribute(UCOL_STRENGTH, (UColAttributeValue)newStrength, intStatus);
     916           0 : }
     917             : 
     918             : Collator &
     919           0 : Collator::setMaxVariable(UColReorderCode /*group*/, UErrorCode &errorCode) {
     920           0 :     if (U_SUCCESS(errorCode)) {
     921           0 :         errorCode = U_UNSUPPORTED_ERROR;
     922             :     }
     923           0 :     return *this;
     924             : }
     925             : 
     926             : UColReorderCode
     927           0 : Collator::getMaxVariable() const {
     928           0 :     return UCOL_REORDER_CODE_PUNCTUATION;
     929             : }
     930             : 
     931             : int32_t
     932           0 : Collator::getReorderCodes(int32_t* /* dest*/,
     933             :                           int32_t /* destCapacity*/,
     934             :                           UErrorCode& status) const
     935             : {
     936           0 :     if (U_SUCCESS(status)) {
     937           0 :         status = U_UNSUPPORTED_ERROR;
     938             :     }
     939           0 :     return 0;
     940             : }
     941             : 
     942             : void
     943           0 : Collator::setReorderCodes(const int32_t* /* reorderCodes */,
     944             :                           int32_t /* reorderCodesLength */,
     945             :                           UErrorCode& status)
     946             : {
     947           0 :     if (U_SUCCESS(status)) {
     948           0 :         status = U_UNSUPPORTED_ERROR;
     949             :     }
     950           0 : }
     951             : 
     952             : int32_t
     953           0 : Collator::getEquivalentReorderCodes(int32_t reorderCode,
     954             :                                     int32_t *dest, int32_t capacity,
     955             :                                     UErrorCode &errorCode) {
     956           0 :     if(U_FAILURE(errorCode)) { return 0; }
     957           0 :     if(capacity < 0 || (dest == NULL && capacity > 0)) {
     958           0 :         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     959           0 :         return 0;
     960             :     }
     961           0 :     const CollationData *baseData = CollationRoot::getData(errorCode);
     962           0 :     if(U_FAILURE(errorCode)) { return 0; }
     963           0 :     return baseData->getEquivalentScripts(reorderCode, dest, capacity, errorCode);
     964             : }
     965             : 
     966             : int32_t
     967           0 : Collator::internalGetShortDefinitionString(const char * /*locale*/,
     968             :                                                              char * /*buffer*/,
     969             :                                                              int32_t /*capacity*/,
     970             :                                                              UErrorCode &status) const {
     971           0 :   if(U_SUCCESS(status)) {
     972           0 :     status = U_UNSUPPORTED_ERROR; /* Shouldn't happen, internal function */
     973             :   }
     974           0 :   return 0;
     975             : }
     976             : 
     977             : UCollationResult
     978           0 : Collator::internalCompareUTF8(const char *left, int32_t leftLength,
     979             :                               const char *right, int32_t rightLength,
     980             :                               UErrorCode &errorCode) const {
     981           0 :     if(U_FAILURE(errorCode)) { return UCOL_EQUAL; }
     982           0 :     if((left == NULL && leftLength != 0) || (right == NULL && rightLength != 0)) {
     983           0 :         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     984           0 :         return UCOL_EQUAL;
     985             :     }
     986             :     return compareUTF8(
     987           0 :             StringPiece(left, (leftLength < 0) ? uprv_strlen(left) : leftLength),
     988           0 :             StringPiece(right, (rightLength < 0) ? uprv_strlen(right) : rightLength),
     989           0 :             errorCode);
     990             : }
     991             : 
     992             : int32_t
     993           0 : Collator::internalNextSortKeyPart(UCharIterator * /*iter*/, uint32_t /*state*/[2],
     994             :                                   uint8_t * /*dest*/, int32_t /*count*/, UErrorCode &errorCode) const {
     995           0 :     if (U_SUCCESS(errorCode)) {
     996           0 :         errorCode = U_UNSUPPORTED_ERROR;
     997             :     }
     998           0 :     return 0;
     999             : }
    1000             : 
    1001             : // UCollator private data members ----------------------------------------
    1002             : 
    1003             : /* This is useless information */
    1004             : /*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/
    1005             : 
    1006             : // -------------------------------------
    1007             : 
    1008             : U_NAMESPACE_END
    1009             : 
    1010             : #endif /* #if !UCONFIG_NO_COLLATION */
    1011             : 
    1012             : /* eof */

Generated by: LCOV version 1.13