137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang/* 22da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang ****************************************************************************** 32da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Copyright (C) 1996-2014, International Business Machines Corporation and 437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * others. All Rights Reserved. 537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang ****************************************************************************** 637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang */ 72da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang 82da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang/** 937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * File coll.cpp 1037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 1137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Created by: Helena Shih 1237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 1337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Modification History: 1437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 1537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Date Name Description 162da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * 2/5/97 aliu Modified createDefault to load collation data from 172da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * binary files when possible. Added related methods 182da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * createCollationFromFile, chopLocale, createPathName. 192da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * 2/11/97 aliu Added methods addToCache, findInCache, which implement 2037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * a Collation cache. Modified createDefault to look in 2137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * cache first, and also to store newly created Collation 2237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * objects in the cache. Modified to not use gLocPath. 2337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 2/12/97 aliu Modified to create objects from RuleBasedCollator cache. 2437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Moved cache out of Collation class. 2537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 2/13/97 aliu Moved several methods out of this class and into 2637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * RuleBasedCollator, with modifications. Modified 2737fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * createDefault() to call new RuleBasedCollator(Locale&) 2837fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * constructor. General clean up and documentation. 2937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 2/20/97 helena Added clone, operator==, operator!=, operator=, and copy 3037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * constructor. 3137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 05/06/97 helena Added memory allocation error detection. 3237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 05/08/97 helena Added createInstance(). 337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * 6/20/97 helena Java class name change. 347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * 04/23/99 stephen Removed EDecompositionMode, merged with 357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * Normalizer::EMode 3637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 11/23/9 srl Inlining of some critical functions 377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * 01/29/01 synwee Modified into a C++ wrapper calling C APIs (ucol.h) 387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * 2012-2014 markus Rewritten in C++ again. 397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "utypeinfo.h" // for 'typeid' to work 427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "unicode/utypes.h" 447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#if !UCONFIG_NO_COLLATION 467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "unicode/coll.h" 487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "unicode/tblcoll.h" 497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "collationdata.h" 507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "collationroot.h" 517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "collationtailoring.h" 527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "ucol_imp.h" 537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "cstring.h" 547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "cmemory.h" 557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "umutex.h" 561a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber#include "servloc.h" 577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "uassert.h" 587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "ustrenum.h" 597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "uresimp.h" 607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "ucln_in.h" 617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic icu::Locale* availableLocaleList = NULL; 657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int32_t availableLocaleListCount; 667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic icu::ICULocaleService* gService = NULL; 677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER; 687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic icu::UInitOnce gAvailableLocaleListInitOnce; 697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/** 717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * Release all static memory held by collator. 727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangU_CDECL_BEGIN 747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic UBool U_CALLCONV collator_cleanup(void) { 757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#if !UCONFIG_NO_SERVICE 767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (gService) { 777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang delete gService; 787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang gService = NULL; 797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang gServiceInitOnce.reset(); 817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (availableLocaleList) { 837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang delete []availableLocaleList; 847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang availableLocaleList = NULL; 857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang availableLocaleListCount = 0; 877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang gAvailableLocaleListInitOnce.reset(); 887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return TRUE; 897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangU_CDECL_END 927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangU_NAMESPACE_BEGIN 947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#if !UCONFIG_NO_SERVICE 967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang// ------------------------------------------ 987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang// 997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang// Registration 1007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang// 1017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang//------------------------------------------- 1037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangCollatorFactory::~CollatorFactory() {} 1057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang//------------------------------------------- 1077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangUBool 1097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangCollatorFactory::visible(void) const { 1107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return TRUE; 1117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang//------------------------------------------- 1147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangUnicodeString& 1167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangCollatorFactory::getDisplayName(const Locale& objectLocale, 1177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang const Locale& displayLocale, 1187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang UnicodeString& result) 1197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 1207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return objectLocale.getDisplayName(displayLocale, result); 1217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1221a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber 1231a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber// ------------------------------------- 1247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1251a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huberclass ICUCollatorFactory : public ICUResourceBundleFactory { 1261a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber public: 1277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ICUCollatorFactory() : ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL, -1, US_INV)) { } 1281a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber virtual ~ICUCollatorFactory(); 1291a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber protected: 1307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; 1311a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber}; 1321a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber 1331a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas HuberICUCollatorFactory::~ICUCollatorFactory() {} 1341a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber 1351a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas HuberUObject* 1361a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas HuberICUCollatorFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const { 1377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (handlesKey(key, status)) { 1387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang const LocaleKey& lkey = (const LocaleKey&)key; 1397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang Locale loc; 1407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // make sure the requested locale is correct 1417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey 1427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // but for ICU rb resources we use the actual one since it will fallback again 1437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang lkey.canonicalLocale(loc); 1447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1451a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber return Collator::makeInstance(loc, status); 1467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return NULL; 1487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang// ------------------------------------- 1517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangclass ICUCollatorService : public ICULocaleService { 1537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangpublic: 1547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ICUCollatorService() 1557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang : ICULocaleService(UNICODE_STRING_SIMPLE("Collator")) 1567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 1571a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber UErrorCode status = U_ZERO_ERROR; 1587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang registerFactory(new ICUCollatorFactory(), status); 1597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang virtual ~ICUCollatorService(); 1627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang virtual UObject* cloneInstance(UObject* instance) const { 1647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ((Collator*)instance)->clone(); 1657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const { 1687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang LocaleKey& lkey = (LocaleKey&)key; 1697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (actualID) { 1707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // Ugly Hack Alert! We return an empty actualID to signal 1717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // to callers that this is a default object, not a "real" 1727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // service-created object. (TODO remove in 3.0) [aliu] 1737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang actualID->truncate(0); 1747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang Locale loc(""); 1767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang lkey.canonicalLocale(loc); 1777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return Collator::makeInstance(loc, status); 1787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const { 1817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang UnicodeString ar; 1827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (actualReturn == NULL) { 1837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang actualReturn = &ar; 1847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return (Collator*)ICULocaleService::getKey(key, actualReturn, status); 1867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang virtual UBool isDefault() const { 1897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return countFactories() == 1; 1907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}; 1927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WangICUCollatorService::~ICUCollatorService() {} 1947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang// ------------------------------------- 1967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void U_CALLCONV initService() { 1987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang gService = new ICUCollatorService(); 1997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); 2007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic ICULocaleService* 2047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WanggetService(void) 2057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 2067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang umtx_initOnce(gServiceInitOnce, &initService); 2077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return gService; 2087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang// ------------------------------------- 2117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline UBool 2137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WanghasService(void) 2147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 2157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang UBool retVal = !gServiceInitOnce.isReset() && (getService() != NULL); 2167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return retVal; 2177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif /* UCONFIG_NO_SERVICE */ 2207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void U_CALLCONV 2227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria WanginitAvailableLocaleList(UErrorCode &status) { 2237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang U_ASSERT(availableLocaleListCount == 0); 2247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang U_ASSERT(availableLocaleList == NULL); 2257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // for now, there is a hardcoded list, so just walk through that list and set it up. 2267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang UResourceBundle *index = NULL; 2277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang UResourceBundle installed; 2287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int32_t i = 0; 2297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ures_initStackObject(&installed); 2317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status); 2327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ures_getByKey(index, "InstalledLocales", &installed, &status); 2337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(U_SUCCESS(status)) { 2357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang availableLocaleListCount = ures_getSize(&installed); 2367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang availableLocaleList = new Locale[availableLocaleListCount]; 2377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (availableLocaleList != NULL) { 2397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ures_resetIterator(&installed); 2407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(ures_hasNext(&installed)) { 2417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang const char *tempKey = NULL; 2427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ures_getNextString(&installed, NULL, &tempKey, &status); 2437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang availableLocaleList[i++] = Locale(tempKey); 2447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang U_ASSERT(availableLocaleListCount == i); 2477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ures_close(&installed); 2487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ures_close(index); 2507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); 2517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic UBool isAvailableLocaleListInitialized(UErrorCode &status) { 2547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang umtx_initOnce(gAvailableLocaleListInitOnce, &initAvailableLocaleList, status); 2557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return U_SUCCESS(status); 2567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang// Collator public methods ----------------------------------------------- 2607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangnamespace { 2627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic const struct { 2647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang const char *name; 2657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang UColAttribute attr; 2667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} collAttributes[] = { 2677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "colStrength", UCOL_STRENGTH }, 2687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "colBackwards", UCOL_FRENCH_COLLATION }, 2697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "colCaseLevel", UCOL_CASE_LEVEL }, 2707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "colCaseFirst", UCOL_CASE_FIRST }, 2717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "colAlternate", UCOL_ALTERNATE_HANDLING }, 2727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "colNormalization", UCOL_NORMALIZATION_MODE }, 2737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "colNumeric", UCOL_NUMERIC_COLLATION } 2747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}; 2757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic const struct { 2777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang const char *name; 2787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang UColAttributeValue value; 2797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} collAttributeValues[] = { 2807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "primary", UCOL_PRIMARY }, 2817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "secondary", UCOL_SECONDARY }, 2827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "tertiary", UCOL_TERTIARY }, 2837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "quaternary", UCOL_QUATERNARY }, 2847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // Note: Not supporting typo "quarternary" because it was never supported in locale IDs. 2857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "identical", UCOL_IDENTICAL }, 2867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "no", UCOL_OFF }, 2877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "yes", UCOL_ON }, 2887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "shifted", UCOL_SHIFTED }, 2897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "non-ignorable", UCOL_NON_IGNORABLE }, 2907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "lower", UCOL_LOWER_FIRST }, 2917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { "upper", UCOL_UPPER_FIRST } 2927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}; 2937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic const char *collReorderCodes[UCOL_REORDER_CODE_LIMIT - UCOL_REORDER_CODE_FIRST] = { 2957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang "space", "punct", "symbol", "currency", "digit" 2967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}; 2977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint32_t getReorderCode(const char *s) { 2997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for (int32_t i = 0; i < LENGTHOF(collReorderCodes); ++i) { 3007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (uprv_stricmp(s, collReorderCodes[i]) == 0) { 3017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return UCOL_REORDER_CODE_FIRST + i; 3027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return -1; 3057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 3061a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber 3071a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber/** 3087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * Sets collation attributes according to locale keywords. See 3097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * http://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Settings 3107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * 3117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * Using "alias" keywords and values where defined: 3127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * http://www.unicode.org/reports/tr35/tr35.html#Old_Locale_Extension_Syntax 3131a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml 3147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 3157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvoid setAttributesFromKeywords(const Locale &loc, Collator &coll, UErrorCode &errorCode) { 3167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (U_FAILURE(errorCode)) { 3177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3191a7ca64dd19ab9a5af3c4c3c58c815f764877bf7Andreas Huber if (uprv_strcmp(loc.getName(), loc.getBaseName()) == 0) { 3207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // No keywords. 3217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang char value[1024]; // The reordering value could be long. 3247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // Check for collation keywords that were already deprecated 3257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // before any were supported in createInstance() (except for "collation"). 3267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int32_t length = loc.getKeywordValue("colHiraganaQuaternary", value, LENGTHOF(value), errorCode); 3277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (U_FAILURE(errorCode)) { 3287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ILLEGAL_ARGUMENT_ERROR; 3297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (length != 0) { 3327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_UNSUPPORTED_ERROR; 3337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang length = loc.getKeywordValue("variableTop", value, LENGTHOF(value), errorCode); 3367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (U_FAILURE(errorCode)) { 3377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ILLEGAL_ARGUMENT_ERROR; 3387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (length != 0) { 3417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_UNSUPPORTED_ERROR; 3427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // Parse known collation keywords, ignore others. 3457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (errorCode == U_STRING_NOT_TERMINATED_WARNING) { 3467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ZERO_ERROR; 3477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for (int32_t i = 0; i < LENGTHOF(collAttributes); ++i) { 3497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang length = loc.getKeywordValue(collAttributes[i].name, value, LENGTHOF(value), errorCode); 3507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) { 3517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ILLEGAL_ARGUMENT_ERROR; 3527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (length == 0) { continue; } 3557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for (int32_t j = 0;; ++j) { 3567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (j == LENGTHOF(collAttributeValues)) { 3577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ILLEGAL_ARGUMENT_ERROR; 3587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (uprv_stricmp(value, collAttributeValues[j].name) == 0) { 3617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang coll.setAttribute(collAttributes[i].attr, collAttributeValues[j].value, errorCode); 3627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 3637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang length = loc.getKeywordValue("colReorder", value, LENGTHOF(value), errorCode); 3677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) { 3687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ILLEGAL_ARGUMENT_ERROR; 3697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (length != 0) { 3727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int32_t codes[USCRIPT_CODE_LIMIT + UCOL_REORDER_CODE_LIMIT - UCOL_REORDER_CODE_FIRST]; 3737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int32_t codesLength = 0; 3747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang char *scriptName = value; 3757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for (;;) { 3767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (codesLength == LENGTHOF(codes)) { 3777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ILLEGAL_ARGUMENT_ERROR; 3787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang char *limit = scriptName; 3817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang char c; 3827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while ((c = *limit) != 0 && c != '-') { ++limit; } 3837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *limit = 0; 3847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int32_t code; 3857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if ((limit - scriptName) == 4) { 3867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang // Strict parsing, accept only 4-letter script codes, not long names. 3877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang code = u_getPropertyValueEnum(UCHAR_SCRIPT, scriptName); 3887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } else { 3897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang code = getReorderCode(scriptName); 3907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (code < 0) { 3927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ILLEGAL_ARGUMENT_ERROR; 3937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 3947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang codes[codesLength++] = code; 3967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (c == 0) { break; } 3977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang scriptName = limit + 1; 3987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang coll.setReorderCodes(codes, codesLength, errorCode); 4007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang length = loc.getKeywordValue("kv", value, LENGTHOF(value), errorCode); 4027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) { 4037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang errorCode = U_ILLEGAL_ARGUMENT_ERROR; 4047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 4057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if (length != 0) { 407 int32_t code = getReorderCode(value); 408 if (code < 0) { 409 errorCode = U_ILLEGAL_ARGUMENT_ERROR; 410 return; 411 } 412 coll.setMaxVariable((UColReorderCode)code, errorCode); 413 } 414 if (U_FAILURE(errorCode)) { 415 errorCode = U_ILLEGAL_ARGUMENT_ERROR; 416 } 417} 418 419} // namespace 420 421Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success) 422{ 423 return createInstance(Locale::getDefault(), success); 424} 425 426Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale, 427 UErrorCode& status) 428{ 429 if (U_FAILURE(status)) 430 return 0; 431 if (desiredLocale.isBogus()) { 432 // Locale constructed from malformed locale ID or language tag. 433 status = U_ILLEGAL_ARGUMENT_ERROR; 434 return NULL; 435 } 436 437 Collator* coll; 438#if !UCONFIG_NO_SERVICE 439 if (hasService()) { 440 Locale actualLoc; 441 coll = (Collator*)gService->get(desiredLocale, &actualLoc, status); 442 } else 443#endif 444 { 445 coll = makeInstance(desiredLocale, status); 446 } 447 setAttributesFromKeywords(desiredLocale, *coll, status); 448 if (U_FAILURE(status)) { 449 delete coll; 450 return NULL; 451 } 452 return coll; 453} 454 455 456Collator* Collator::makeInstance(const Locale& desiredLocale, 457 UErrorCode& status) 458{ 459 Locale validLocale(""); 460 const CollationTailoring *t = 461 CollationLoader::loadTailoring(desiredLocale, validLocale, status); 462 if (U_SUCCESS(status)) { 463 Collator *result = new RuleBasedCollator(t, validLocale); 464 if (result != NULL) { 465 return result; 466 } 467 status = U_MEMORY_ALLOCATION_ERROR; 468 } 469 if (t != NULL) { 470 t->deleteIfZeroRefCount(); 471 } 472 return NULL; 473} 474 475Collator * 476Collator::safeClone() const { 477 return clone(); 478} 479 480// implement deprecated, previously abstract method 481Collator::EComparisonResult Collator::compare(const UnicodeString& source, 482 const UnicodeString& target) const 483{ 484 UErrorCode ec = U_ZERO_ERROR; 485 return (EComparisonResult)compare(source, target, ec); 486} 487 488// implement deprecated, previously abstract method 489Collator::EComparisonResult Collator::compare(const UnicodeString& source, 490 const UnicodeString& target, 491 int32_t length) const 492{ 493 UErrorCode ec = U_ZERO_ERROR; 494 return (EComparisonResult)compare(source, target, length, ec); 495} 496 497// implement deprecated, previously abstract method 498Collator::EComparisonResult Collator::compare(const UChar* source, int32_t sourceLength, 499 const UChar* target, int32_t targetLength) 500 const 501{ 502 UErrorCode ec = U_ZERO_ERROR; 503 return (EComparisonResult)compare(source, sourceLength, target, targetLength, ec); 504} 505 506UCollationResult Collator::compare(UCharIterator &/*sIter*/, 507 UCharIterator &/*tIter*/, 508 UErrorCode &status) const { 509 if(U_SUCCESS(status)) { 510 // Not implemented in the base class. 511 status = U_UNSUPPORTED_ERROR; 512 } 513 return UCOL_EQUAL; 514} 515 516UCollationResult Collator::compareUTF8(const StringPiece &source, 517 const StringPiece &target, 518 UErrorCode &status) const { 519 if(U_FAILURE(status)) { 520 return UCOL_EQUAL; 521 } 522 UCharIterator sIter, tIter; 523 uiter_setUTF8(&sIter, source.data(), source.length()); 524 uiter_setUTF8(&tIter, target.data(), target.length()); 525 return compare(sIter, tIter, status); 526} 527 528UBool Collator::equals(const UnicodeString& source, 529 const UnicodeString& target) const 530{ 531 UErrorCode ec = U_ZERO_ERROR; 532 return (compare(source, target, ec) == UCOL_EQUAL); 533} 534 535UBool Collator::greaterOrEqual(const UnicodeString& source, 536 const UnicodeString& target) const 537{ 538 UErrorCode ec = U_ZERO_ERROR; 539 return (compare(source, target, ec) != UCOL_LESS); 540} 541 542UBool Collator::greater(const UnicodeString& source, 543 const UnicodeString& target) const 544{ 545 UErrorCode ec = U_ZERO_ERROR; 546 return (compare(source, target, ec) == UCOL_GREATER); 547} 548 549// this API ignores registered collators, since it returns an 550// array of indefinite lifetime 551const Locale* U_EXPORT2 Collator::getAvailableLocales(int32_t& count) 552{ 553 UErrorCode status = U_ZERO_ERROR; 554 Locale *result = NULL; 555 count = 0; 556 if (isAvailableLocaleListInitialized(status)) 557 { 558 result = availableLocaleList; 559 count = availableLocaleListCount; 560 } 561 return result; 562} 563 564UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale, 565 const Locale& displayLocale, 566 UnicodeString& name) 567{ 568#if !UCONFIG_NO_SERVICE 569 if (hasService()) { 570 UnicodeString locNameStr; 571 LocaleUtility::initNameFromLocale(objectLocale, locNameStr); 572 return gService->getDisplayName(locNameStr, name, displayLocale); 573 } 574#endif 575 return objectLocale.getDisplayName(displayLocale, name); 576} 577 578UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale, 579 UnicodeString& name) 580{ 581 return getDisplayName(objectLocale, Locale::getDefault(), name); 582} 583 584/* This is useless information */ 585/*void Collator::getVersion(UVersionInfo versionInfo) const 586{ 587 if (versionInfo!=NULL) 588 uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH); 589} 590*/ 591 592// UCollator protected constructor destructor ---------------------------- 593 594/** 595* Default constructor. 596* Constructor is different from the old default Collator constructor. 597* The task for determing the default collation strength and normalization mode 598* is left to the child class. 599*/ 600Collator::Collator() 601: UObject() 602{ 603} 604 605/** 606* Constructor. 607* Empty constructor, does not handle the arguments. 608* This constructor is done for backward compatibility with 1.7 and 1.8. 609* The task for handling the argument collation strength and normalization 610* mode is left to the child class. 611* @param collationStrength collation strength 612* @param decompositionMode 613* @deprecated 2.4 use the default constructor instead 614*/ 615Collator::Collator(UCollationStrength, UNormalizationMode ) 616: UObject() 617{ 618} 619 620Collator::~Collator() 621{ 622} 623 624Collator::Collator(const Collator &other) 625 : UObject(other) 626{ 627} 628 629UBool Collator::operator==(const Collator& other) const 630{ 631 // Subclasses: Call this method and then add more specific checks. 632 return typeid(*this) == typeid(other); 633} 634 635UBool Collator::operator!=(const Collator& other) const 636{ 637 return (UBool)!(*this == other); 638} 639 640int32_t U_EXPORT2 Collator::getBound(const uint8_t *source, 641 int32_t sourceLength, 642 UColBoundMode boundType, 643 uint32_t noOfLevels, 644 uint8_t *result, 645 int32_t resultLength, 646 UErrorCode &status) 647{ 648 return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status); 649} 650 651void 652Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) { 653} 654 655UnicodeSet *Collator::getTailoredSet(UErrorCode &status) const 656{ 657 if(U_FAILURE(status)) { 658 return NULL; 659 } 660 // everything can be changed 661 return new UnicodeSet(0, 0x10FFFF); 662} 663 664// ------------------------------------- 665 666#if !UCONFIG_NO_SERVICE 667URegistryKey U_EXPORT2 668Collator::registerInstance(Collator* toAdopt, const Locale& locale, UErrorCode& status) 669{ 670 if (U_SUCCESS(status)) { 671 // Set the collator locales while registering so that createInstance() 672 // need not guess whether the collator's locales are already set properly 673 // (as they are by the data loader). 674 toAdopt->setLocales(locale, locale, locale); 675 return getService()->registerInstance(toAdopt, locale, status); 676 } 677 return NULL; 678} 679 680// ------------------------------------- 681 682class CFactory : public LocaleKeyFactory { 683private: 684 CollatorFactory* _delegate; 685 Hashtable* _ids; 686 687public: 688 CFactory(CollatorFactory* delegate, UErrorCode& status) 689 : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE) 690 , _delegate(delegate) 691 , _ids(NULL) 692 { 693 if (U_SUCCESS(status)) { 694 int32_t count = 0; 695 _ids = new Hashtable(status); 696 if (_ids) { 697 const UnicodeString * idlist = _delegate->getSupportedIDs(count, status); 698 for (int i = 0; i < count; ++i) { 699 _ids->put(idlist[i], (void*)this, status); 700 if (U_FAILURE(status)) { 701 delete _ids; 702 _ids = NULL; 703 return; 704 } 705 } 706 } else { 707 status = U_MEMORY_ALLOCATION_ERROR; 708 } 709 } 710 } 711 712 virtual ~CFactory(); 713 714 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; 715 716protected: 717 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const 718 { 719 if (U_SUCCESS(status)) { 720 return _ids; 721 } 722 return NULL; 723 } 724 725 virtual UnicodeString& 726 getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const; 727}; 728 729CFactory::~CFactory() 730{ 731 delete _delegate; 732 delete _ids; 733} 734 735UObject* 736CFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const 737{ 738 if (handlesKey(key, status)) { 739 const LocaleKey& lkey = (const LocaleKey&)key; 740 Locale validLoc; 741 lkey.currentLocale(validLoc); 742 return _delegate->createCollator(validLoc); 743 } 744 return NULL; 745} 746 747UnicodeString& 748CFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const 749{ 750 if ((_coverage & 0x1) == 0) { 751 UErrorCode status = U_ZERO_ERROR; 752 const Hashtable* ids = getSupportedIDs(status); 753 if (ids && (ids->get(id) != NULL)) { 754 Locale loc; 755 LocaleUtility::initLocaleFromName(id, loc); 756 return _delegate->getDisplayName(loc, locale, result); 757 } 758 } 759 result.setToBogus(); 760 return result; 761} 762 763URegistryKey U_EXPORT2 764Collator::registerFactory(CollatorFactory* toAdopt, UErrorCode& status) 765{ 766 if (U_SUCCESS(status)) { 767 CFactory* f = new CFactory(toAdopt, status); 768 if (f) { 769 return getService()->registerFactory(f, status); 770 } 771 status = U_MEMORY_ALLOCATION_ERROR; 772 } 773 return NULL; 774} 775 776// ------------------------------------- 777 778UBool U_EXPORT2 779Collator::unregister(URegistryKey key, UErrorCode& status) 780{ 781 if (U_SUCCESS(status)) { 782 if (hasService()) { 783 return gService->unregister(key, status); 784 } 785 status = U_ILLEGAL_ARGUMENT_ERROR; 786 } 787 return FALSE; 788} 789#endif /* UCONFIG_NO_SERVICE */ 790 791class CollationLocaleListEnumeration : public StringEnumeration { 792private: 793 int32_t index; 794public: 795 static UClassID U_EXPORT2 getStaticClassID(void); 796 virtual UClassID getDynamicClassID(void) const; 797public: 798 CollationLocaleListEnumeration() 799 : index(0) 800 { 801 // The global variables should already be initialized. 802 //isAvailableLocaleListInitialized(status); 803 } 804 805 virtual ~CollationLocaleListEnumeration(); 806 807 virtual StringEnumeration * clone() const 808 { 809 CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration(); 810 if (result) { 811 result->index = index; 812 } 813 return result; 814 } 815 816 virtual int32_t count(UErrorCode &/*status*/) const { 817 return availableLocaleListCount; 818 } 819 820 virtual const char* next(int32_t* resultLength, UErrorCode& /*status*/) { 821 const char* result; 822 if(index < availableLocaleListCount) { 823 result = availableLocaleList[index++].getName(); 824 if(resultLength != NULL) { 825 *resultLength = (int32_t)uprv_strlen(result); 826 } 827 } else { 828 if(resultLength != NULL) { 829 *resultLength = 0; 830 } 831 result = NULL; 832 } 833 return result; 834 } 835 836 virtual const UnicodeString* snext(UErrorCode& status) { 837 int32_t resultLength = 0; 838 const char *s = next(&resultLength, status); 839 return setChars(s, resultLength, status); 840 } 841 842 virtual void reset(UErrorCode& /*status*/) { 843 index = 0; 844 } 845}; 846 847CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {} 848 849UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration) 850 851 852// ------------------------------------- 853 854StringEnumeration* U_EXPORT2 855Collator::getAvailableLocales(void) 856{ 857#if !UCONFIG_NO_SERVICE 858 if (hasService()) { 859 return getService()->getAvailableLocales(); 860 } 861#endif /* UCONFIG_NO_SERVICE */ 862 UErrorCode status = U_ZERO_ERROR; 863 if (isAvailableLocaleListInitialized(status)) { 864 return new CollationLocaleListEnumeration(); 865 } 866 return NULL; 867} 868 869StringEnumeration* U_EXPORT2 870Collator::getKeywords(UErrorCode& status) { 871 // This is a wrapper over ucol_getKeywords 872 UEnumeration* uenum = ucol_getKeywords(&status); 873 if (U_FAILURE(status)) { 874 uenum_close(uenum); 875 return NULL; 876 } 877 return new UStringEnumeration(uenum); 878} 879 880StringEnumeration* U_EXPORT2 881Collator::getKeywordValues(const char *keyword, UErrorCode& status) { 882 // This is a wrapper over ucol_getKeywordValues 883 UEnumeration* uenum = ucol_getKeywordValues(keyword, &status); 884 if (U_FAILURE(status)) { 885 uenum_close(uenum); 886 return NULL; 887 } 888 return new UStringEnumeration(uenum); 889} 890 891StringEnumeration* U_EXPORT2 892Collator::getKeywordValuesForLocale(const char* key, const Locale& locale, 893 UBool commonlyUsed, UErrorCode& status) { 894 // This is a wrapper over ucol_getKeywordValuesForLocale 895 UEnumeration *uenum = ucol_getKeywordValuesForLocale(key, locale.getName(), 896 commonlyUsed, &status); 897 if (U_FAILURE(status)) { 898 uenum_close(uenum); 899 return NULL; 900 } 901 return new UStringEnumeration(uenum); 902} 903 904Locale U_EXPORT2 905Collator::getFunctionalEquivalent(const char* keyword, const Locale& locale, 906 UBool& isAvailable, UErrorCode& status) { 907 // This is a wrapper over ucol_getFunctionalEquivalent 908 char loc[ULOC_FULLNAME_CAPACITY]; 909 /*int32_t len =*/ ucol_getFunctionalEquivalent(loc, sizeof(loc), 910 keyword, locale.getName(), &isAvailable, &status); 911 if (U_FAILURE(status)) { 912 *loc = 0; // root 913 } 914 return Locale::createFromName(loc); 915} 916 917Collator::ECollationStrength 918Collator::getStrength(void) const { 919 UErrorCode intStatus = U_ZERO_ERROR; 920 return (ECollationStrength)getAttribute(UCOL_STRENGTH, intStatus); 921} 922 923void 924Collator::setStrength(ECollationStrength newStrength) { 925 UErrorCode intStatus = U_ZERO_ERROR; 926 setAttribute(UCOL_STRENGTH, (UColAttributeValue)newStrength, intStatus); 927} 928 929Collator & 930Collator::setMaxVariable(UColReorderCode /*group*/, UErrorCode &errorCode) { 931 if (U_SUCCESS(errorCode)) { 932 errorCode = U_UNSUPPORTED_ERROR; 933 } 934 return *this; 935} 936 937UColReorderCode 938Collator::getMaxVariable() const { 939 return UCOL_REORDER_CODE_PUNCTUATION; 940} 941 942int32_t 943Collator::getReorderCodes(int32_t* /* dest*/, 944 int32_t /* destCapacity*/, 945 UErrorCode& status) const 946{ 947 if (U_SUCCESS(status)) { 948 status = U_UNSUPPORTED_ERROR; 949 } 950 return 0; 951} 952 953void 954Collator::setReorderCodes(const int32_t* /* reorderCodes */, 955 int32_t /* reorderCodesLength */, 956 UErrorCode& status) 957{ 958 if (U_SUCCESS(status)) { 959 status = U_UNSUPPORTED_ERROR; 960 } 961} 962 963int32_t 964Collator::getEquivalentReorderCodes(int32_t reorderCode, 965 int32_t *dest, int32_t capacity, 966 UErrorCode &errorCode) { 967 if(U_FAILURE(errorCode)) { return 0; } 968 if(capacity < 0 || (dest == NULL && capacity > 0)) { 969 errorCode = U_ILLEGAL_ARGUMENT_ERROR; 970 return 0; 971 } 972 const CollationData *baseData = CollationRoot::getData(errorCode); 973 if(U_FAILURE(errorCode)) { return 0; } 974 return baseData->getEquivalentScripts(reorderCode, dest, capacity, errorCode); 975} 976 977int32_t 978Collator::internalGetShortDefinitionString(const char * /*locale*/, 979 char * /*buffer*/, 980 int32_t /*capacity*/, 981 UErrorCode &status) const { 982 if(U_SUCCESS(status)) { 983 status = U_UNSUPPORTED_ERROR; /* Shouldn't happen, internal function */ 984 } 985 return 0; 986} 987 988UCollationResult 989Collator::internalCompareUTF8(const char *left, int32_t leftLength, 990 const char *right, int32_t rightLength, 991 UErrorCode &errorCode) const { 992 if(U_FAILURE(errorCode)) { return UCOL_EQUAL; } 993 if((left == NULL && leftLength != 0) || (right == NULL && rightLength != 0)) { 994 errorCode = U_ILLEGAL_ARGUMENT_ERROR; 995 return UCOL_EQUAL; 996 } 997 return compareUTF8( 998 StringPiece(left, (leftLength < 0) ? uprv_strlen(left) : leftLength), 999 StringPiece(right, (rightLength < 0) ? uprv_strlen(right) : rightLength), 1000 errorCode); 1001} 1002 1003int32_t 1004Collator::internalNextSortKeyPart(UCharIterator * /*iter*/, uint32_t /*state*/[2], 1005 uint8_t * /*dest*/, int32_t /*count*/, UErrorCode &errorCode) const { 1006 if (U_SUCCESS(errorCode)) { 1007 errorCode = U_UNSUPPORTED_ERROR; 1008 } 1009 return 0; 1010} 1011 1012// UCollator private data members ---------------------------------------- 1013 1014/* This is useless information */ 1015/*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/ 1016 1017// ------------------------------------- 1018 1019U_NAMESPACE_END 1020 1021#endif /* #if !UCONFIG_NO_COLLATION */ 1022 1023/* eof */ 1024