1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/coll.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,911 @@ 1.4 +/* 1.5 + ****************************************************************************** 1.6 + * Copyright (C) 1996-2013, International Business Machines Corporation and 1.7 + * others. All Rights Reserved. 1.8 + ****************************************************************************** 1.9 + */ 1.10 + 1.11 +/** 1.12 + * File coll.cpp 1.13 + * 1.14 + * Created by: Helena Shih 1.15 + * 1.16 + * Modification History: 1.17 + * 1.18 + * Date Name Description 1.19 + * 2/5/97 aliu Modified createDefault to load collation data from 1.20 + * binary files when possible. Added related methods 1.21 + * createCollationFromFile, chopLocale, createPathName. 1.22 + * 2/11/97 aliu Added methods addToCache, findInCache, which implement 1.23 + * a Collation cache. Modified createDefault to look in 1.24 + * cache first, and also to store newly created Collation 1.25 + * objects in the cache. Modified to not use gLocPath. 1.26 + * 2/12/97 aliu Modified to create objects from RuleBasedCollator cache. 1.27 + * Moved cache out of Collation class. 1.28 + * 2/13/97 aliu Moved several methods out of this class and into 1.29 + * RuleBasedCollator, with modifications. Modified 1.30 + * createDefault() to call new RuleBasedCollator(Locale&) 1.31 + * constructor. General clean up and documentation. 1.32 + * 2/20/97 helena Added clone, operator==, operator!=, operator=, and copy 1.33 + * constructor. 1.34 + * 05/06/97 helena Added memory allocation error detection. 1.35 + * 05/08/97 helena Added createInstance(). 1.36 + * 6/20/97 helena Java class name change. 1.37 + * 04/23/99 stephen Removed EDecompositionMode, merged with 1.38 + * Normalizer::EMode 1.39 + * 11/23/9 srl Inlining of some critical functions 1.40 + * 01/29/01 synwee Modified into a C++ wrapper calling C APIs (ucol.h) 1.41 + */ 1.42 + 1.43 +#include "utypeinfo.h" // for 'typeid' to work 1.44 + 1.45 +#include "unicode/utypes.h" 1.46 + 1.47 +#if !UCONFIG_NO_COLLATION 1.48 + 1.49 +#include "unicode/coll.h" 1.50 +#include "unicode/tblcoll.h" 1.51 +#include "ucol_imp.h" 1.52 +#include "cstring.h" 1.53 +#include "cmemory.h" 1.54 +#include "umutex.h" 1.55 +#include "servloc.h" 1.56 +#include "uassert.h" 1.57 +#include "ustrenum.h" 1.58 +#include "uresimp.h" 1.59 +#include "ucln_in.h" 1.60 + 1.61 +static icu::Locale* availableLocaleList = NULL; 1.62 +static int32_t availableLocaleListCount; 1.63 +static icu::ICULocaleService* gService = NULL; 1.64 +static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER; 1.65 +static icu::UInitOnce gAvailableLocaleListInitOnce; 1.66 + 1.67 +/** 1.68 + * Release all static memory held by collator. 1.69 + */ 1.70 +U_CDECL_BEGIN 1.71 +static UBool U_CALLCONV collator_cleanup(void) { 1.72 +#if !UCONFIG_NO_SERVICE 1.73 + if (gService) { 1.74 + delete gService; 1.75 + gService = NULL; 1.76 + } 1.77 + gServiceInitOnce.reset(); 1.78 +#endif 1.79 + if (availableLocaleList) { 1.80 + delete []availableLocaleList; 1.81 + availableLocaleList = NULL; 1.82 + } 1.83 + availableLocaleListCount = 0; 1.84 + gAvailableLocaleListInitOnce.reset(); 1.85 + return TRUE; 1.86 +} 1.87 + 1.88 +U_CDECL_END 1.89 + 1.90 +U_NAMESPACE_BEGIN 1.91 + 1.92 +#if !UCONFIG_NO_SERVICE 1.93 + 1.94 +// ------------------------------------------ 1.95 +// 1.96 +// Registration 1.97 +// 1.98 + 1.99 +//------------------------------------------- 1.100 + 1.101 +CollatorFactory::~CollatorFactory() {} 1.102 + 1.103 +//------------------------------------------- 1.104 + 1.105 +UBool 1.106 +CollatorFactory::visible(void) const { 1.107 + return TRUE; 1.108 +} 1.109 + 1.110 +//------------------------------------------- 1.111 + 1.112 +UnicodeString& 1.113 +CollatorFactory::getDisplayName(const Locale& objectLocale, 1.114 + const Locale& displayLocale, 1.115 + UnicodeString& result) 1.116 +{ 1.117 + return objectLocale.getDisplayName(displayLocale, result); 1.118 +} 1.119 + 1.120 +// ------------------------------------- 1.121 + 1.122 +class ICUCollatorFactory : public ICUResourceBundleFactory { 1.123 + public: 1.124 + ICUCollatorFactory() : ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL, -1, US_INV)) { } 1.125 + virtual ~ICUCollatorFactory(); 1.126 + protected: 1.127 + virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; 1.128 +}; 1.129 + 1.130 +ICUCollatorFactory::~ICUCollatorFactory() {} 1.131 + 1.132 +UObject* 1.133 +ICUCollatorFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const { 1.134 + if (handlesKey(key, status)) { 1.135 + const LocaleKey& lkey = (const LocaleKey&)key; 1.136 + Locale loc; 1.137 + // make sure the requested locale is correct 1.138 + // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey 1.139 + // but for ICU rb resources we use the actual one since it will fallback again 1.140 + lkey.canonicalLocale(loc); 1.141 + 1.142 + return Collator::makeInstance(loc, status); 1.143 + } 1.144 + return NULL; 1.145 +} 1.146 + 1.147 +// ------------------------------------- 1.148 + 1.149 +class ICUCollatorService : public ICULocaleService { 1.150 +public: 1.151 + ICUCollatorService() 1.152 + : ICULocaleService(UNICODE_STRING_SIMPLE("Collator")) 1.153 + { 1.154 + UErrorCode status = U_ZERO_ERROR; 1.155 + registerFactory(new ICUCollatorFactory(), status); 1.156 + } 1.157 + 1.158 + virtual ~ICUCollatorService(); 1.159 + 1.160 + virtual UObject* cloneInstance(UObject* instance) const { 1.161 + return ((Collator*)instance)->clone(); 1.162 + } 1.163 + 1.164 + virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const { 1.165 + LocaleKey& lkey = (LocaleKey&)key; 1.166 + if (actualID) { 1.167 + // Ugly Hack Alert! We return an empty actualID to signal 1.168 + // to callers that this is a default object, not a "real" 1.169 + // service-created object. (TODO remove in 3.0) [aliu] 1.170 + actualID->truncate(0); 1.171 + } 1.172 + Locale loc(""); 1.173 + lkey.canonicalLocale(loc); 1.174 + return Collator::makeInstance(loc, status); 1.175 + } 1.176 + 1.177 + virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const { 1.178 + UnicodeString ar; 1.179 + if (actualReturn == NULL) { 1.180 + actualReturn = &ar; 1.181 + } 1.182 + Collator* result = (Collator*)ICULocaleService::getKey(key, actualReturn, status); 1.183 + // Ugly Hack Alert! If the actualReturn length is zero, this 1.184 + // means we got a default object, not a "real" service-created 1.185 + // object. We don't call setLocales() on a default object, 1.186 + // because that will overwrite its correct built-in locale 1.187 + // metadata (valid & actual) with our incorrect data (all we 1.188 + // have is the requested locale). (TODO remove in 3.0) [aliu] 1.189 + if (result && actualReturn->length() > 0) { 1.190 + const LocaleKey& lkey = (const LocaleKey&)key; 1.191 + Locale canonicalLocale(""); 1.192 + Locale currentLocale(""); 1.193 + 1.194 + LocaleUtility::initLocaleFromName(*actualReturn, currentLocale); 1.195 + result->setLocales(lkey.canonicalLocale(canonicalLocale), currentLocale, currentLocale); 1.196 + } 1.197 + return result; 1.198 + } 1.199 + 1.200 + virtual UBool isDefault() const { 1.201 + return countFactories() == 1; 1.202 + } 1.203 +}; 1.204 + 1.205 +ICUCollatorService::~ICUCollatorService() {} 1.206 + 1.207 +// ------------------------------------- 1.208 + 1.209 +static void U_CALLCONV initService() { 1.210 + gService = new ICUCollatorService(); 1.211 + ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); 1.212 +} 1.213 + 1.214 + 1.215 +static ICULocaleService* 1.216 +getService(void) 1.217 +{ 1.218 + umtx_initOnce(gServiceInitOnce, &initService); 1.219 + return gService; 1.220 +} 1.221 + 1.222 +// ------------------------------------- 1.223 + 1.224 +static inline UBool 1.225 +hasService(void) 1.226 +{ 1.227 + UBool retVal = !gServiceInitOnce.isReset() && (getService() != NULL); 1.228 + return retVal; 1.229 +} 1.230 + 1.231 +// ------------------------------------- 1.232 + 1.233 +UCollator* 1.234 +Collator::createUCollator(const char *loc, 1.235 + UErrorCode *status) 1.236 +{ 1.237 + UCollator *result = 0; 1.238 + if (status && U_SUCCESS(*status) && hasService()) { 1.239 + Locale desiredLocale(loc); 1.240 + Collator *col = (Collator*)gService->get(desiredLocale, *status); 1.241 + RuleBasedCollator *rbc; 1.242 + if (col && (rbc = dynamic_cast<RuleBasedCollator *>(col))) { 1.243 + if (!rbc->dataIsOwned) { 1.244 + result = ucol_safeClone(rbc->ucollator, NULL, NULL, status); 1.245 + } else { 1.246 + result = rbc->ucollator; 1.247 + rbc->ucollator = NULL; // to prevent free on delete 1.248 + } 1.249 + } else { 1.250 + // should go in a function- ucol_initDelegate(delegate) 1.251 + result = (UCollator *)uprv_malloc(sizeof(UCollator)); 1.252 + if(result == NULL) { 1.253 + *status = U_MEMORY_ALLOCATION_ERROR; 1.254 + } else { 1.255 + uprv_memset(result, 0, sizeof(UCollator)); 1.256 + result->delegate = col; 1.257 + result->freeOnClose = TRUE; // do free on close. 1.258 + col = NULL; // to prevent free on delete. 1.259 + } 1.260 + } 1.261 + delete col; 1.262 + } 1.263 + return result; 1.264 +} 1.265 +#endif /* UCONFIG_NO_SERVICE */ 1.266 + 1.267 +static void U_CALLCONV 1.268 +initAvailableLocaleList(UErrorCode &status) { 1.269 + U_ASSERT(availableLocaleListCount == 0); 1.270 + U_ASSERT(availableLocaleList == NULL); 1.271 + // for now, there is a hardcoded list, so just walk through that list and set it up. 1.272 + UResourceBundle *index = NULL; 1.273 + UResourceBundle installed; 1.274 + int32_t i = 0; 1.275 + 1.276 + ures_initStackObject(&installed); 1.277 + index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status); 1.278 + ures_getByKey(index, "InstalledLocales", &installed, &status); 1.279 + 1.280 + if(U_SUCCESS(status)) { 1.281 + availableLocaleListCount = ures_getSize(&installed); 1.282 + availableLocaleList = new Locale[availableLocaleListCount]; 1.283 + 1.284 + if (availableLocaleList != NULL) { 1.285 + ures_resetIterator(&installed); 1.286 + while(ures_hasNext(&installed)) { 1.287 + const char *tempKey = NULL; 1.288 + ures_getNextString(&installed, NULL, &tempKey, &status); 1.289 + availableLocaleList[i++] = Locale(tempKey); 1.290 + } 1.291 + } 1.292 + U_ASSERT(availableLocaleListCount == i); 1.293 + ures_close(&installed); 1.294 + } 1.295 + ures_close(index); 1.296 + ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); 1.297 +} 1.298 + 1.299 +static UBool isAvailableLocaleListInitialized(UErrorCode &status) { 1.300 + umtx_initOnce(gAvailableLocaleListInitOnce, &initAvailableLocaleList, status); 1.301 + return U_SUCCESS(status); 1.302 +} 1.303 + 1.304 + 1.305 +// Collator public methods ----------------------------------------------- 1.306 + 1.307 +Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success) 1.308 +{ 1.309 + return createInstance(Locale::getDefault(), success); 1.310 +} 1.311 + 1.312 +Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale, 1.313 + UErrorCode& status) 1.314 +{ 1.315 + if (U_FAILURE(status)) 1.316 + return 0; 1.317 + 1.318 +#if !UCONFIG_NO_SERVICE 1.319 + if (hasService()) { 1.320 + Locale actualLoc; 1.321 + Collator *result = 1.322 + (Collator*)gService->get(desiredLocale, &actualLoc, status); 1.323 + 1.324 + // Ugly Hack Alert! If the returned locale is empty (not root, 1.325 + // but empty -- getName() == "") then that means the service 1.326 + // returned a default object, not a "real" service object. In 1.327 + // that case, the locale metadata (valid & actual) is setup 1.328 + // correctly already, and we don't want to overwrite it. (TODO 1.329 + // remove in 3.0) [aliu] 1.330 + if (*actualLoc.getName() != 0) { 1.331 + result->setLocales(desiredLocale, actualLoc, actualLoc); 1.332 + } 1.333 + return result; 1.334 + } 1.335 +#endif 1.336 + return makeInstance(desiredLocale, status); 1.337 +} 1.338 + 1.339 + 1.340 +Collator* Collator::makeInstance(const Locale& desiredLocale, 1.341 + UErrorCode& status) 1.342 +{ 1.343 + // A bit of explanation is required here. Although in the current 1.344 + // implementation 1.345 + // Collator::createInstance() is just turning around and calling 1.346 + // RuleBasedCollator(Locale&), this will not necessarily always be the 1.347 + // case. For example, suppose we modify this code to handle a 1.348 + // non-table-based Collator, such as that for Thai. In this case, 1.349 + // createInstance() will have to be modified to somehow determine this fact 1.350 + // (perhaps a field in the resource bundle). Then it can construct the 1.351 + // non-table-based Collator in some other way, when it sees that it needs 1.352 + // to. 1.353 + // The specific caution is this: RuleBasedCollator(Locale&) will ALWAYS 1.354 + // return a valid collation object, if the system is functioning properly. 1.355 + // The reason is that it will fall back, use the default locale, and even 1.356 + // use the built-in default collation rules. THEREFORE, createInstance() 1.357 + // should in general ONLY CALL RuleBasedCollator(Locale&) IF IT KNOWS IN 1.358 + // ADVANCE that the given locale's collation is properly implemented as a 1.359 + // RuleBasedCollator. 1.360 + // Currently, we don't do this...we always return a RuleBasedCollator, 1.361 + // whether it is strictly correct to do so or not, without checking, because 1.362 + // we currently have no way of checking. 1.363 + 1.364 + RuleBasedCollator* collation = new RuleBasedCollator(desiredLocale, 1.365 + status); 1.366 + /* test for NULL */ 1.367 + if (collation == 0) { 1.368 + status = U_MEMORY_ALLOCATION_ERROR; 1.369 + return 0; 1.370 + } 1.371 + if (U_FAILURE(status)) 1.372 + { 1.373 + delete collation; 1.374 + collation = 0; 1.375 + } 1.376 + return collation; 1.377 +} 1.378 + 1.379 +#ifdef U_USE_COLLATION_OBSOLETE_2_6 1.380 +// !!! dlf the following is obsolete, ignore registration for this 1.381 + 1.382 +Collator * 1.383 +Collator::createInstance(const Locale &loc, 1.384 + UVersionInfo version, 1.385 + UErrorCode &status) 1.386 +{ 1.387 + Collator *collator; 1.388 + UVersionInfo info; 1.389 + 1.390 + collator=new RuleBasedCollator(loc, status); 1.391 + /* test for NULL */ 1.392 + if (collator == 0) { 1.393 + status = U_MEMORY_ALLOCATION_ERROR; 1.394 + return 0; 1.395 + } 1.396 + 1.397 + if(U_SUCCESS(status)) { 1.398 + collator->getVersion(info); 1.399 + if(0!=uprv_memcmp(version, info, sizeof(UVersionInfo))) { 1.400 + delete collator; 1.401 + status=U_MISSING_RESOURCE_ERROR; 1.402 + return 0; 1.403 + } 1.404 + } 1.405 + return collator; 1.406 +} 1.407 +#endif 1.408 + 1.409 +Collator * 1.410 +Collator::safeClone() const { 1.411 + return clone(); 1.412 +} 1.413 + 1.414 +// implement deprecated, previously abstract method 1.415 +Collator::EComparisonResult Collator::compare(const UnicodeString& source, 1.416 + const UnicodeString& target) const 1.417 +{ 1.418 + UErrorCode ec = U_ZERO_ERROR; 1.419 + return (EComparisonResult)compare(source, target, ec); 1.420 +} 1.421 + 1.422 +// implement deprecated, previously abstract method 1.423 +Collator::EComparisonResult Collator::compare(const UnicodeString& source, 1.424 + const UnicodeString& target, 1.425 + int32_t length) const 1.426 +{ 1.427 + UErrorCode ec = U_ZERO_ERROR; 1.428 + return (EComparisonResult)compare(source, target, length, ec); 1.429 +} 1.430 + 1.431 +// implement deprecated, previously abstract method 1.432 +Collator::EComparisonResult Collator::compare(const UChar* source, int32_t sourceLength, 1.433 + const UChar* target, int32_t targetLength) 1.434 + const 1.435 +{ 1.436 + UErrorCode ec = U_ZERO_ERROR; 1.437 + return (EComparisonResult)compare(source, sourceLength, target, targetLength, ec); 1.438 +} 1.439 + 1.440 +UCollationResult Collator::compare(UCharIterator &/*sIter*/, 1.441 + UCharIterator &/*tIter*/, 1.442 + UErrorCode &status) const { 1.443 + if(U_SUCCESS(status)) { 1.444 + // Not implemented in the base class. 1.445 + status = U_UNSUPPORTED_ERROR; 1.446 + } 1.447 + return UCOL_EQUAL; 1.448 +} 1.449 + 1.450 +UCollationResult Collator::compareUTF8(const StringPiece &source, 1.451 + const StringPiece &target, 1.452 + UErrorCode &status) const { 1.453 + if(U_FAILURE(status)) { 1.454 + return UCOL_EQUAL; 1.455 + } 1.456 + UCharIterator sIter, tIter; 1.457 + uiter_setUTF8(&sIter, source.data(), source.length()); 1.458 + uiter_setUTF8(&tIter, target.data(), target.length()); 1.459 + return compare(sIter, tIter, status); 1.460 +} 1.461 + 1.462 +UBool Collator::equals(const UnicodeString& source, 1.463 + const UnicodeString& target) const 1.464 +{ 1.465 + UErrorCode ec = U_ZERO_ERROR; 1.466 + return (compare(source, target, ec) == UCOL_EQUAL); 1.467 +} 1.468 + 1.469 +UBool Collator::greaterOrEqual(const UnicodeString& source, 1.470 + const UnicodeString& target) const 1.471 +{ 1.472 + UErrorCode ec = U_ZERO_ERROR; 1.473 + return (compare(source, target, ec) != UCOL_LESS); 1.474 +} 1.475 + 1.476 +UBool Collator::greater(const UnicodeString& source, 1.477 + const UnicodeString& target) const 1.478 +{ 1.479 + UErrorCode ec = U_ZERO_ERROR; 1.480 + return (compare(source, target, ec) == UCOL_GREATER); 1.481 +} 1.482 + 1.483 +// this API ignores registered collators, since it returns an 1.484 +// array of indefinite lifetime 1.485 +const Locale* U_EXPORT2 Collator::getAvailableLocales(int32_t& count) 1.486 +{ 1.487 + UErrorCode status = U_ZERO_ERROR; 1.488 + Locale *result = NULL; 1.489 + count = 0; 1.490 + if (isAvailableLocaleListInitialized(status)) 1.491 + { 1.492 + result = availableLocaleList; 1.493 + count = availableLocaleListCount; 1.494 + } 1.495 + return result; 1.496 +} 1.497 + 1.498 +UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale, 1.499 + const Locale& displayLocale, 1.500 + UnicodeString& name) 1.501 +{ 1.502 +#if !UCONFIG_NO_SERVICE 1.503 + if (hasService()) { 1.504 + UnicodeString locNameStr; 1.505 + LocaleUtility::initNameFromLocale(objectLocale, locNameStr); 1.506 + return gService->getDisplayName(locNameStr, name, displayLocale); 1.507 + } 1.508 +#endif 1.509 + return objectLocale.getDisplayName(displayLocale, name); 1.510 +} 1.511 + 1.512 +UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale, 1.513 + UnicodeString& name) 1.514 +{ 1.515 + return getDisplayName(objectLocale, Locale::getDefault(), name); 1.516 +} 1.517 + 1.518 +/* This is useless information */ 1.519 +/*void Collator::getVersion(UVersionInfo versionInfo) const 1.520 +{ 1.521 + if (versionInfo!=NULL) 1.522 + uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH); 1.523 +} 1.524 +*/ 1.525 + 1.526 +// UCollator protected constructor destructor ---------------------------- 1.527 + 1.528 +/** 1.529 +* Default constructor. 1.530 +* Constructor is different from the old default Collator constructor. 1.531 +* The task for determing the default collation strength and normalization mode 1.532 +* is left to the child class. 1.533 +*/ 1.534 +Collator::Collator() 1.535 +: UObject() 1.536 +{ 1.537 +} 1.538 + 1.539 +/** 1.540 +* Constructor. 1.541 +* Empty constructor, does not handle the arguments. 1.542 +* This constructor is done for backward compatibility with 1.7 and 1.8. 1.543 +* The task for handling the argument collation strength and normalization 1.544 +* mode is left to the child class. 1.545 +* @param collationStrength collation strength 1.546 +* @param decompositionMode 1.547 +* @deprecated 2.4 use the default constructor instead 1.548 +*/ 1.549 +Collator::Collator(UCollationStrength, UNormalizationMode ) 1.550 +: UObject() 1.551 +{ 1.552 +} 1.553 + 1.554 +Collator::~Collator() 1.555 +{ 1.556 +} 1.557 + 1.558 +Collator::Collator(const Collator &other) 1.559 + : UObject(other) 1.560 +{ 1.561 +} 1.562 + 1.563 +UBool Collator::operator==(const Collator& other) const 1.564 +{ 1.565 + // Subclasses: Call this method and then add more specific checks. 1.566 + return typeid(*this) == typeid(other); 1.567 +} 1.568 + 1.569 +UBool Collator::operator!=(const Collator& other) const 1.570 +{ 1.571 + return (UBool)!(*this == other); 1.572 +} 1.573 + 1.574 +int32_t U_EXPORT2 Collator::getBound(const uint8_t *source, 1.575 + int32_t sourceLength, 1.576 + UColBoundMode boundType, 1.577 + uint32_t noOfLevels, 1.578 + uint8_t *result, 1.579 + int32_t resultLength, 1.580 + UErrorCode &status) 1.581 +{ 1.582 + return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status); 1.583 +} 1.584 + 1.585 +void 1.586 +Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) { 1.587 +} 1.588 + 1.589 +UnicodeSet *Collator::getTailoredSet(UErrorCode &status) const 1.590 +{ 1.591 + if(U_FAILURE(status)) { 1.592 + return NULL; 1.593 + } 1.594 + // everything can be changed 1.595 + return new UnicodeSet(0, 0x10FFFF); 1.596 +} 1.597 + 1.598 +// ------------------------------------- 1.599 + 1.600 +#if !UCONFIG_NO_SERVICE 1.601 +URegistryKey U_EXPORT2 1.602 +Collator::registerInstance(Collator* toAdopt, const Locale& locale, UErrorCode& status) 1.603 +{ 1.604 + if (U_SUCCESS(status)) { 1.605 + return getService()->registerInstance(toAdopt, locale, status); 1.606 + } 1.607 + return NULL; 1.608 +} 1.609 + 1.610 +// ------------------------------------- 1.611 + 1.612 +class CFactory : public LocaleKeyFactory { 1.613 +private: 1.614 + CollatorFactory* _delegate; 1.615 + Hashtable* _ids; 1.616 + 1.617 +public: 1.618 + CFactory(CollatorFactory* delegate, UErrorCode& status) 1.619 + : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE) 1.620 + , _delegate(delegate) 1.621 + , _ids(NULL) 1.622 + { 1.623 + if (U_SUCCESS(status)) { 1.624 + int32_t count = 0; 1.625 + _ids = new Hashtable(status); 1.626 + if (_ids) { 1.627 + const UnicodeString * idlist = _delegate->getSupportedIDs(count, status); 1.628 + for (int i = 0; i < count; ++i) { 1.629 + _ids->put(idlist[i], (void*)this, status); 1.630 + if (U_FAILURE(status)) { 1.631 + delete _ids; 1.632 + _ids = NULL; 1.633 + return; 1.634 + } 1.635 + } 1.636 + } else { 1.637 + status = U_MEMORY_ALLOCATION_ERROR; 1.638 + } 1.639 + } 1.640 + } 1.641 + 1.642 + virtual ~CFactory(); 1.643 + 1.644 + virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; 1.645 + 1.646 +protected: 1.647 + virtual const Hashtable* getSupportedIDs(UErrorCode& status) const 1.648 + { 1.649 + if (U_SUCCESS(status)) { 1.650 + return _ids; 1.651 + } 1.652 + return NULL; 1.653 + } 1.654 + 1.655 + virtual UnicodeString& 1.656 + getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const; 1.657 +}; 1.658 + 1.659 +CFactory::~CFactory() 1.660 +{ 1.661 + delete _delegate; 1.662 + delete _ids; 1.663 +} 1.664 + 1.665 +UObject* 1.666 +CFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const 1.667 +{ 1.668 + if (handlesKey(key, status)) { 1.669 + const LocaleKey& lkey = (const LocaleKey&)key; 1.670 + Locale validLoc; 1.671 + lkey.currentLocale(validLoc); 1.672 + return _delegate->createCollator(validLoc); 1.673 + } 1.674 + return NULL; 1.675 +} 1.676 + 1.677 +UnicodeString& 1.678 +CFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const 1.679 +{ 1.680 + if ((_coverage & 0x1) == 0) { 1.681 + UErrorCode status = U_ZERO_ERROR; 1.682 + const Hashtable* ids = getSupportedIDs(status); 1.683 + if (ids && (ids->get(id) != NULL)) { 1.684 + Locale loc; 1.685 + LocaleUtility::initLocaleFromName(id, loc); 1.686 + return _delegate->getDisplayName(loc, locale, result); 1.687 + } 1.688 + } 1.689 + result.setToBogus(); 1.690 + return result; 1.691 +} 1.692 + 1.693 +URegistryKey U_EXPORT2 1.694 +Collator::registerFactory(CollatorFactory* toAdopt, UErrorCode& status) 1.695 +{ 1.696 + if (U_SUCCESS(status)) { 1.697 + CFactory* f = new CFactory(toAdopt, status); 1.698 + if (f) { 1.699 + return getService()->registerFactory(f, status); 1.700 + } 1.701 + status = U_MEMORY_ALLOCATION_ERROR; 1.702 + } 1.703 + return NULL; 1.704 +} 1.705 + 1.706 +// ------------------------------------- 1.707 + 1.708 +UBool U_EXPORT2 1.709 +Collator::unregister(URegistryKey key, UErrorCode& status) 1.710 +{ 1.711 + if (U_SUCCESS(status)) { 1.712 + if (hasService()) { 1.713 + return gService->unregister(key, status); 1.714 + } 1.715 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.716 + } 1.717 + return FALSE; 1.718 +} 1.719 +#endif /* UCONFIG_NO_SERVICE */ 1.720 + 1.721 +class CollationLocaleListEnumeration : public StringEnumeration { 1.722 +private: 1.723 + int32_t index; 1.724 +public: 1.725 + static UClassID U_EXPORT2 getStaticClassID(void); 1.726 + virtual UClassID getDynamicClassID(void) const; 1.727 +public: 1.728 + CollationLocaleListEnumeration() 1.729 + : index(0) 1.730 + { 1.731 + // The global variables should already be initialized. 1.732 + //isAvailableLocaleListInitialized(status); 1.733 + } 1.734 + 1.735 + virtual ~CollationLocaleListEnumeration(); 1.736 + 1.737 + virtual StringEnumeration * clone() const 1.738 + { 1.739 + CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration(); 1.740 + if (result) { 1.741 + result->index = index; 1.742 + } 1.743 + return result; 1.744 + } 1.745 + 1.746 + virtual int32_t count(UErrorCode &/*status*/) const { 1.747 + return availableLocaleListCount; 1.748 + } 1.749 + 1.750 + virtual const char* next(int32_t* resultLength, UErrorCode& /*status*/) { 1.751 + const char* result; 1.752 + if(index < availableLocaleListCount) { 1.753 + result = availableLocaleList[index++].getName(); 1.754 + if(resultLength != NULL) { 1.755 + *resultLength = (int32_t)uprv_strlen(result); 1.756 + } 1.757 + } else { 1.758 + if(resultLength != NULL) { 1.759 + *resultLength = 0; 1.760 + } 1.761 + result = NULL; 1.762 + } 1.763 + return result; 1.764 + } 1.765 + 1.766 + virtual const UnicodeString* snext(UErrorCode& status) { 1.767 + int32_t resultLength = 0; 1.768 + const char *s = next(&resultLength, status); 1.769 + return setChars(s, resultLength, status); 1.770 + } 1.771 + 1.772 + virtual void reset(UErrorCode& /*status*/) { 1.773 + index = 0; 1.774 + } 1.775 +}; 1.776 + 1.777 +CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {} 1.778 + 1.779 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration) 1.780 + 1.781 + 1.782 +// ------------------------------------- 1.783 + 1.784 +StringEnumeration* U_EXPORT2 1.785 +Collator::getAvailableLocales(void) 1.786 +{ 1.787 +#if !UCONFIG_NO_SERVICE 1.788 + if (hasService()) { 1.789 + return getService()->getAvailableLocales(); 1.790 + } 1.791 +#endif /* UCONFIG_NO_SERVICE */ 1.792 + UErrorCode status = U_ZERO_ERROR; 1.793 + if (isAvailableLocaleListInitialized(status)) { 1.794 + return new CollationLocaleListEnumeration(); 1.795 + } 1.796 + return NULL; 1.797 +} 1.798 + 1.799 +StringEnumeration* U_EXPORT2 1.800 +Collator::getKeywords(UErrorCode& status) { 1.801 + // This is a wrapper over ucol_getKeywords 1.802 + UEnumeration* uenum = ucol_getKeywords(&status); 1.803 + if (U_FAILURE(status)) { 1.804 + uenum_close(uenum); 1.805 + return NULL; 1.806 + } 1.807 + return new UStringEnumeration(uenum); 1.808 +} 1.809 + 1.810 +StringEnumeration* U_EXPORT2 1.811 +Collator::getKeywordValues(const char *keyword, UErrorCode& status) { 1.812 + // This is a wrapper over ucol_getKeywordValues 1.813 + UEnumeration* uenum = ucol_getKeywordValues(keyword, &status); 1.814 + if (U_FAILURE(status)) { 1.815 + uenum_close(uenum); 1.816 + return NULL; 1.817 + } 1.818 + return new UStringEnumeration(uenum); 1.819 +} 1.820 + 1.821 +StringEnumeration* U_EXPORT2 1.822 +Collator::getKeywordValuesForLocale(const char* key, const Locale& locale, 1.823 + UBool commonlyUsed, UErrorCode& status) { 1.824 + // This is a wrapper over ucol_getKeywordValuesForLocale 1.825 + UEnumeration *uenum = ucol_getKeywordValuesForLocale(key, locale.getName(), 1.826 + commonlyUsed, &status); 1.827 + if (U_FAILURE(status)) { 1.828 + uenum_close(uenum); 1.829 + return NULL; 1.830 + } 1.831 + return new UStringEnumeration(uenum); 1.832 +} 1.833 + 1.834 +Locale U_EXPORT2 1.835 +Collator::getFunctionalEquivalent(const char* keyword, const Locale& locale, 1.836 + UBool& isAvailable, UErrorCode& status) { 1.837 + // This is a wrapper over ucol_getFunctionalEquivalent 1.838 + char loc[ULOC_FULLNAME_CAPACITY]; 1.839 + /*int32_t len =*/ ucol_getFunctionalEquivalent(loc, sizeof(loc), 1.840 + keyword, locale.getName(), &isAvailable, &status); 1.841 + if (U_FAILURE(status)) { 1.842 + *loc = 0; // root 1.843 + } 1.844 + return Locale::createFromName(loc); 1.845 +} 1.846 + 1.847 +Collator::ECollationStrength 1.848 +Collator::getStrength(void) const { 1.849 + UErrorCode intStatus = U_ZERO_ERROR; 1.850 + return (ECollationStrength)getAttribute(UCOL_STRENGTH, intStatus); 1.851 +} 1.852 + 1.853 +void 1.854 +Collator::setStrength(ECollationStrength newStrength) { 1.855 + UErrorCode intStatus = U_ZERO_ERROR; 1.856 + setAttribute(UCOL_STRENGTH, (UColAttributeValue)newStrength, intStatus); 1.857 +} 1.858 + 1.859 +int32_t 1.860 +Collator::getReorderCodes(int32_t* /* dest*/, 1.861 + int32_t /* destCapacity*/, 1.862 + UErrorCode& status) const 1.863 +{ 1.864 + if (U_SUCCESS(status)) { 1.865 + status = U_UNSUPPORTED_ERROR; 1.866 + } 1.867 + return 0; 1.868 +} 1.869 + 1.870 +void 1.871 +Collator::setReorderCodes(const int32_t* /* reorderCodes */, 1.872 + int32_t /* reorderCodesLength */, 1.873 + UErrorCode& status) 1.874 +{ 1.875 + if (U_SUCCESS(status)) { 1.876 + status = U_UNSUPPORTED_ERROR; 1.877 + } 1.878 +} 1.879 + 1.880 +int32_t U_EXPORT2 1.881 +Collator::getEquivalentReorderCodes(int32_t /* reorderCode */, 1.882 + int32_t* /* dest */, 1.883 + int32_t /* destCapacity */, 1.884 + UErrorCode& status) 1.885 +{ 1.886 + if (U_SUCCESS(status)) { 1.887 + status = U_UNSUPPORTED_ERROR; 1.888 + } 1.889 + return 0; 1.890 +} 1.891 + 1.892 +int32_t 1.893 +Collator::internalGetShortDefinitionString(const char * /*locale*/, 1.894 + char * /*buffer*/, 1.895 + int32_t /*capacity*/, 1.896 + UErrorCode &status) const { 1.897 + if(U_SUCCESS(status)) { 1.898 + status = U_UNSUPPORTED_ERROR; /* Shouldn't happen, internal function */ 1.899 + } 1.900 + return 0; 1.901 +} 1.902 + 1.903 +// UCollator private data members ---------------------------------------- 1.904 + 1.905 +/* This is useless information */ 1.906 +/*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/ 1.907 + 1.908 +// ------------------------------------- 1.909 + 1.910 +U_NAMESPACE_END 1.911 + 1.912 +#endif /* #if !UCONFIG_NO_COLLATION */ 1.913 + 1.914 +/* eof */