| /* |
| ****************************************************************************** |
| * Copyright (C) 1996-2010, International Business Machines Corporation and |
| * others. All Rights Reserved. |
| ****************************************************************************** |
| */ |
| |
| /** |
| * File coll.cpp |
| * |
| * Created by: Helena Shih |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 2/5/97 aliu Modified createDefault to load collation data from |
| * binary files when possible. Added related methods |
| * createCollationFromFile, chopLocale, createPathName. |
| * 2/11/97 aliu Added methods addToCache, findInCache, which implement |
| * a Collation cache. Modified createDefault to look in |
| * cache first, and also to store newly created Collation |
| * objects in the cache. Modified to not use gLocPath. |
| * 2/12/97 aliu Modified to create objects from RuleBasedCollator cache. |
| * Moved cache out of Collation class. |
| * 2/13/97 aliu Moved several methods out of this class and into |
| * RuleBasedCollator, with modifications. Modified |
| * createDefault() to call new RuleBasedCollator(Locale&) |
| * constructor. General clean up and documentation. |
| * 2/20/97 helena Added clone, operator==, operator!=, operator=, and copy |
| * constructor. |
| * 05/06/97 helena Added memory allocation error detection. |
| * 05/08/97 helena Added createInstance(). |
| * 6/20/97 helena Java class name change. |
| * 04/23/99 stephen Removed EDecompositionMode, merged with |
| * Normalizer::EMode |
| * 11/23/9 srl Inlining of some critical functions |
| * 01/29/01 synwee Modified into a C++ wrapper calling C APIs (ucol.h) |
| */ |
| |
| #include "unicode/utypes.h" |
| |
| #if !UCONFIG_NO_COLLATION |
| |
| #include "unicode/coll.h" |
| #include "unicode/tblcoll.h" |
| #include "ucol_imp.h" |
| #include "cstring.h" |
| #include "cmemory.h" |
| #include "umutex.h" |
| #include "servloc.h" |
| #include "ustrenum.h" |
| #include "uresimp.h" |
| #include "ucln_in.h" |
| |
| static U_NAMESPACE_QUALIFIER Locale* availableLocaleList = NULL; |
| static int32_t availableLocaleListCount; |
| static U_NAMESPACE_QUALIFIER ICULocaleService* gService = NULL; |
| |
| /** |
| * Release all static memory held by collator. |
| */ |
| U_CDECL_BEGIN |
| static UBool U_CALLCONV collator_cleanup(void) { |
| #if !UCONFIG_NO_SERVICE |
| if (gService) { |
| delete gService; |
| gService = NULL; |
| } |
| #endif |
| if (availableLocaleList) { |
| delete []availableLocaleList; |
| availableLocaleList = NULL; |
| } |
| availableLocaleListCount = 0; |
| |
| return TRUE; |
| } |
| |
| U_CDECL_END |
| |
| U_NAMESPACE_BEGIN |
| |
| #if !UCONFIG_NO_SERVICE |
| |
| // ------------------------------------------ |
| // |
| // Registration |
| // |
| |
| //------------------------------------------- |
| |
| CollatorFactory::~CollatorFactory() {} |
| |
| //------------------------------------------- |
| |
| UBool |
| CollatorFactory::visible(void) const { |
| return TRUE; |
| } |
| |
| //------------------------------------------- |
| |
| UnicodeString& |
| CollatorFactory::getDisplayName(const Locale& objectLocale, |
| const Locale& displayLocale, |
| UnicodeString& result) |
| { |
| return objectLocale.getDisplayName(displayLocale, result); |
| } |
| |
| // ------------------------------------- |
| |
| class ICUCollatorFactory : public ICUResourceBundleFactory { |
| public: |
| ICUCollatorFactory(): ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL, -1, US_INV)) { } |
| protected: |
| virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; |
| }; |
| |
| UObject* |
| ICUCollatorFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const { |
| if (handlesKey(key, status)) { |
| const LocaleKey& lkey = (const LocaleKey&)key; |
| Locale loc; |
| // make sure the requested locale is correct |
| // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey |
| // but for ICU rb resources we use the actual one since it will fallback again |
| lkey.canonicalLocale(loc); |
| |
| return Collator::makeInstance(loc, status); |
| } |
| return NULL; |
| } |
| |
| // ------------------------------------- |
| |
| class ICUCollatorService : public ICULocaleService { |
| public: |
| ICUCollatorService() |
| : ICULocaleService(UNICODE_STRING_SIMPLE("Collator")) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| registerFactory(new ICUCollatorFactory(), status); |
| } |
| |
| virtual UObject* cloneInstance(UObject* instance) const { |
| return ((Collator*)instance)->clone(); |
| } |
| |
| virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const { |
| LocaleKey& lkey = (LocaleKey&)key; |
| if (actualID) { |
| // Ugly Hack Alert! We return an empty actualID to signal |
| // to callers that this is a default object, not a "real" |
| // service-created object. (TODO remove in 3.0) [aliu] |
| actualID->truncate(0); |
| } |
| Locale loc(""); |
| lkey.canonicalLocale(loc); |
| return Collator::makeInstance(loc, status); |
| } |
| |
| virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const { |
| UnicodeString ar; |
| if (actualReturn == NULL) { |
| actualReturn = &ar; |
| } |
| Collator* result = (Collator*)ICULocaleService::getKey(key, actualReturn, status); |
| // Ugly Hack Alert! If the actualReturn length is zero, this |
| // means we got a default object, not a "real" service-created |
| // object. We don't call setLocales() on a default object, |
| // because that will overwrite its correct built-in locale |
| // metadata (valid & actual) with our incorrect data (all we |
| // have is the requested locale). (TODO remove in 3.0) [aliu] |
| if (result && actualReturn->length() > 0) { |
| const LocaleKey& lkey = (const LocaleKey&)key; |
| Locale canonicalLocale(""); |
| Locale currentLocale(""); |
| |
| LocaleUtility::initLocaleFromName(*actualReturn, currentLocale); |
| result->setLocales(lkey.canonicalLocale(canonicalLocale), currentLocale, currentLocale); |
| } |
| return result; |
| } |
| |
| virtual UBool isDefault() const { |
| return countFactories() == 1; |
| } |
| }; |
| |
| // ------------------------------------- |
| |
| static ICULocaleService* |
| getService(void) |
| { |
| UBool needInit; |
| UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit); |
| if(needInit) { |
| ICULocaleService *newservice = new ICUCollatorService(); |
| if(newservice) { |
| umtx_lock(NULL); |
| if(gService == NULL) { |
| gService = newservice; |
| newservice = NULL; |
| } |
| umtx_unlock(NULL); |
| } |
| if(newservice) { |
| delete newservice; |
| } |
| else { |
| ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); |
| } |
| } |
| return gService; |
| } |
| |
| // ------------------------------------- |
| |
| static inline UBool |
| hasService(void) |
| { |
| UBool retVal; |
| UMTX_CHECK(NULL, gService != NULL, retVal); |
| return retVal; |
| } |
| |
| // ------------------------------------- |
| |
| UCollator* |
| Collator::createUCollator(const char *loc, |
| UErrorCode *status) |
| { |
| UCollator *result = 0; |
| if (status && U_SUCCESS(*status) && hasService()) { |
| Locale desiredLocale(loc); |
| Collator *col = (Collator*)gService->get(desiredLocale, *status); |
| RuleBasedCollator *rbc; |
| if (col && (rbc = dynamic_cast<RuleBasedCollator *>(col))) { |
| if (!rbc->dataIsOwned) { |
| result = ucol_safeClone(rbc->ucollator, NULL, NULL, status); |
| } else { |
| result = rbc->ucollator; |
| rbc->ucollator = NULL; // to prevent free on delete |
| } |
| } |
| delete col; |
| } |
| return result; |
| } |
| #endif /* UCONFIG_NO_SERVICE */ |
| |
| static UBool isAvailableLocaleListInitialized(UErrorCode &status) { |
| // for now, there is a hardcoded list, so just walk through that list and set it up. |
| UBool needInit; |
| UMTX_CHECK(NULL, availableLocaleList == NULL, needInit); |
| |
| if (needInit) { |
| UResourceBundle *index = NULL; |
| UResourceBundle installed; |
| Locale * temp; |
| int32_t i = 0; |
| int32_t localeCount; |
| |
| ures_initStackObject(&installed); |
| index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status); |
| ures_getByKey(index, "InstalledLocales", &installed, &status); |
| |
| if(U_SUCCESS(status)) { |
| localeCount = ures_getSize(&installed); |
| temp = new Locale[localeCount]; |
| |
| if (temp != NULL) { |
| ures_resetIterator(&installed); |
| while(ures_hasNext(&installed)) { |
| const char *tempKey = NULL; |
| ures_getNextString(&installed, NULL, &tempKey, &status); |
| temp[i++] = Locale(tempKey); |
| } |
| |
| umtx_lock(NULL); |
| if (availableLocaleList == NULL) |
| { |
| availableLocaleListCount = localeCount; |
| availableLocaleList = temp; |
| temp = NULL; |
| ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); |
| } |
| umtx_unlock(NULL); |
| |
| needInit = FALSE; |
| if (temp) { |
| delete []temp; |
| } |
| } |
| |
| ures_close(&installed); |
| } |
| ures_close(index); |
| } |
| return !needInit; |
| } |
| |
| // Collator public methods ----------------------------------------------- |
| |
| Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success) |
| { |
| return createInstance(Locale::getDefault(), success); |
| } |
| |
| Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale, |
| UErrorCode& status) |
| { |
| if (U_FAILURE(status)) |
| return 0; |
| |
| #if !UCONFIG_NO_SERVICE |
| if (hasService()) { |
| Locale actualLoc; |
| Collator *result = |
| (Collator*)gService->get(desiredLocale, &actualLoc, status); |
| // Ugly Hack Alert! If the returned locale is empty (not root, |
| // but empty -- getName() == "") then that means the service |
| // returned a default object, not a "real" service object. In |
| // that case, the locale metadata (valid & actual) is setup |
| // correctly already, and we don't want to overwrite it. (TODO |
| // remove in 3.0) [aliu] |
| if (*actualLoc.getName() != 0) { |
| result->setLocales(desiredLocale, actualLoc, actualLoc); |
| } |
| return result; |
| } |
| #endif |
| return makeInstance(desiredLocale, status); |
| } |
| |
| |
| Collator* Collator::makeInstance(const Locale& desiredLocale, |
| UErrorCode& status) |
| { |
| // A bit of explanation is required here. Although in the current |
| // implementation |
| // Collator::createInstance() is just turning around and calling |
| // RuleBasedCollator(Locale&), this will not necessarily always be the |
| // case. For example, suppose we modify this code to handle a |
| // non-table-based Collator, such as that for Thai. In this case, |
| // createInstance() will have to be modified to somehow determine this fact |
| // (perhaps a field in the resource bundle). Then it can construct the |
| // non-table-based Collator in some other way, when it sees that it needs |
| // to. |
| // The specific caution is this: RuleBasedCollator(Locale&) will ALWAYS |
| // return a valid collation object, if the system is functioning properly. |
| // The reason is that it will fall back, use the default locale, and even |
| // use the built-in default collation rules. THEREFORE, createInstance() |
| // should in general ONLY CALL RuleBasedCollator(Locale&) IF IT KNOWS IN |
| // ADVANCE that the given locale's collation is properly implemented as a |
| // RuleBasedCollator. |
| // Currently, we don't do this...we always return a RuleBasedCollator, |
| // whether it is strictly correct to do so or not, without checking, because |
| // we currently have no way of checking. |
| |
| RuleBasedCollator* collation = new RuleBasedCollator(desiredLocale, |
| status); |
| /* test for NULL */ |
| if (collation == 0) { |
| status = U_MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| if (U_FAILURE(status)) |
| { |
| delete collation; |
| collation = 0; |
| } |
| return collation; |
| } |
| |
| #ifdef U_USE_COLLATION_OBSOLETE_2_6 |
| // !!! dlf the following is obsolete, ignore registration for this |
| |
| Collator * |
| Collator::createInstance(const Locale &loc, |
| UVersionInfo version, |
| UErrorCode &status) |
| { |
| Collator *collator; |
| UVersionInfo info; |
| |
| collator=new RuleBasedCollator(loc, status); |
| /* test for NULL */ |
| if (collator == 0) { |
| status = U_MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| |
| if(U_SUCCESS(status)) { |
| collator->getVersion(info); |
| if(0!=uprv_memcmp(version, info, sizeof(UVersionInfo))) { |
| delete collator; |
| status=U_MISSING_RESOURCE_ERROR; |
| return 0; |
| } |
| } |
| return collator; |
| } |
| #endif |
| |
| // implement deprecated, previously abstract method |
| Collator::EComparisonResult Collator::compare(const UnicodeString& source, |
| const UnicodeString& target) const |
| { |
| UErrorCode ec = U_ZERO_ERROR; |
| return (Collator::EComparisonResult)compare(source, target, ec); |
| } |
| |
| // implement deprecated, previously abstract method |
| Collator::EComparisonResult Collator::compare(const UnicodeString& source, |
| const UnicodeString& target, |
| int32_t length) const |
| { |
| UErrorCode ec = U_ZERO_ERROR; |
| return (Collator::EComparisonResult)compare(source, target, length, ec); |
| } |
| |
| // implement deprecated, previously abstract method |
| Collator::EComparisonResult Collator::compare(const UChar* source, int32_t sourceLength, |
| const UChar* target, int32_t targetLength) |
| const |
| { |
| UErrorCode ec = U_ZERO_ERROR; |
| return (Collator::EComparisonResult)compare(source, sourceLength, target, targetLength, ec); |
| } |
| |
| UCollationResult Collator::compare(UCharIterator &/*sIter*/, |
| UCharIterator &/*tIter*/, |
| UErrorCode &status) const { |
| if(U_SUCCESS(status)) { |
| // Not implemented in the base class. |
| status = U_UNSUPPORTED_ERROR; |
| } |
| return UCOL_EQUAL; |
| } |
| |
| UCollationResult Collator::compareUTF8(const StringPiece &source, |
| const StringPiece &target, |
| UErrorCode &status) const { |
| if(U_FAILURE(status)) { |
| return UCOL_EQUAL; |
| } |
| UCharIterator sIter, tIter; |
| uiter_setUTF8(&sIter, source.data(), source.length()); |
| uiter_setUTF8(&tIter, target.data(), target.length()); |
| return compare(sIter, tIter, status); |
| } |
| |
| UBool Collator::equals(const UnicodeString& source, |
| const UnicodeString& target) const |
| { |
| UErrorCode ec = U_ZERO_ERROR; |
| return (compare(source, target, ec) == UCOL_EQUAL); |
| } |
| |
| UBool Collator::greaterOrEqual(const UnicodeString& source, |
| const UnicodeString& target) const |
| { |
| UErrorCode ec = U_ZERO_ERROR; |
| return (compare(source, target, ec) != UCOL_LESS); |
| } |
| |
| UBool Collator::greater(const UnicodeString& source, |
| const UnicodeString& target) const |
| { |
| UErrorCode ec = U_ZERO_ERROR; |
| return (compare(source, target, ec) == UCOL_GREATER); |
| } |
| |
| // this API ignores registered collators, since it returns an |
| // array of indefinite lifetime |
| const Locale* U_EXPORT2 Collator::getAvailableLocales(int32_t& count) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| Locale *result = NULL; |
| count = 0; |
| if (isAvailableLocaleListInitialized(status)) |
| { |
| result = availableLocaleList; |
| count = availableLocaleListCount; |
| } |
| return result; |
| } |
| |
| UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale, |
| const Locale& displayLocale, |
| UnicodeString& name) |
| { |
| #if !UCONFIG_NO_SERVICE |
| if (hasService()) { |
| UnicodeString locNameStr; |
| LocaleUtility::initNameFromLocale(objectLocale, locNameStr); |
| return gService->getDisplayName(locNameStr, name, displayLocale); |
| } |
| #endif |
| return objectLocale.getDisplayName(displayLocale, name); |
| } |
| |
| UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale, |
| UnicodeString& name) |
| { |
| return getDisplayName(objectLocale, Locale::getDefault(), name); |
| } |
| |
| /* This is useless information */ |
| /*void Collator::getVersion(UVersionInfo versionInfo) const |
| { |
| if (versionInfo!=NULL) |
| uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH); |
| } |
| */ |
| |
| // UCollator protected constructor destructor ---------------------------- |
| |
| /** |
| * Default constructor. |
| * Constructor is different from the old default Collator constructor. |
| * The task for determing the default collation strength and normalization mode |
| * is left to the child class. |
| */ |
| Collator::Collator() |
| : UObject() |
| { |
| } |
| |
| /** |
| * Constructor. |
| * Empty constructor, does not handle the arguments. |
| * This constructor is done for backward compatibility with 1.7 and 1.8. |
| * The task for handling the argument collation strength and normalization |
| * mode is left to the child class. |
| * @param collationStrength collation strength |
| * @param decompositionMode |
| * @deprecated 2.4 use the default constructor instead |
| */ |
| Collator::Collator(UCollationStrength, UNormalizationMode ) |
| : UObject() |
| { |
| } |
| |
| Collator::~Collator() |
| { |
| } |
| |
| Collator::Collator(const Collator &other) |
| : UObject(other) |
| { |
| } |
| |
| UBool Collator::operator==(const Collator& other) const |
| { |
| return (UBool)(this == &other); |
| } |
| |
| UBool Collator::operator!=(const Collator& other) const |
| { |
| return (UBool)!(*this == other); |
| } |
| |
| int32_t U_EXPORT2 Collator::getBound(const uint8_t *source, |
| int32_t sourceLength, |
| UColBoundMode boundType, |
| uint32_t noOfLevels, |
| uint8_t *result, |
| int32_t resultLength, |
| UErrorCode &status) |
| { |
| return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status); |
| } |
| |
| void |
| Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) { |
| } |
| |
| UnicodeSet *Collator::getTailoredSet(UErrorCode &status) const |
| { |
| if(U_FAILURE(status)) { |
| return NULL; |
| } |
| // everything can be changed |
| return new UnicodeSet(0, 0x10FFFF); |
| } |
| |
| // ------------------------------------- |
| |
| #if !UCONFIG_NO_SERVICE |
| URegistryKey U_EXPORT2 |
| Collator::registerInstance(Collator* toAdopt, const Locale& locale, UErrorCode& status) |
| { |
| if (U_SUCCESS(status)) { |
| return getService()->registerInstance(toAdopt, locale, status); |
| } |
| return NULL; |
| } |
| |
| // ------------------------------------- |
| |
| class CFactory : public LocaleKeyFactory { |
| private: |
| CollatorFactory* _delegate; |
| Hashtable* _ids; |
| |
| public: |
| CFactory(CollatorFactory* delegate, UErrorCode& status) |
| : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE) |
| , _delegate(delegate) |
| , _ids(NULL) |
| { |
| if (U_SUCCESS(status)) { |
| int32_t count = 0; |
| _ids = new Hashtable(status); |
| if (_ids) { |
| const UnicodeString * idlist = _delegate->getSupportedIDs(count, status); |
| for (int i = 0; i < count; ++i) { |
| _ids->put(idlist[i], (void*)this, status); |
| if (U_FAILURE(status)) { |
| delete _ids; |
| _ids = NULL; |
| return; |
| } |
| } |
| } else { |
| status = U_MEMORY_ALLOCATION_ERROR; |
| } |
| } |
| } |
| |
| virtual ~CFactory() |
| { |
| delete _delegate; |
| delete _ids; |
| } |
| |
| virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const; |
| |
| protected: |
| virtual const Hashtable* getSupportedIDs(UErrorCode& status) const |
| { |
| if (U_SUCCESS(status)) { |
| return _ids; |
| } |
| return NULL; |
| } |
| |
| virtual UnicodeString& |
| getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const; |
| }; |
| |
| UObject* |
| CFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const |
| { |
| if (handlesKey(key, status)) { |
| const LocaleKey& lkey = (const LocaleKey&)key; |
| Locale validLoc; |
| lkey.currentLocale(validLoc); |
| return _delegate->createCollator(validLoc); |
| } |
| return NULL; |
| } |
| |
| UnicodeString& |
| CFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const |
| { |
| if ((_coverage & 0x1) == 0) { |
| UErrorCode status = U_ZERO_ERROR; |
| const Hashtable* ids = getSupportedIDs(status); |
| if (ids && (ids->get(id) != NULL)) { |
| Locale loc; |
| LocaleUtility::initLocaleFromName(id, loc); |
| return _delegate->getDisplayName(loc, locale, result); |
| } |
| } |
| result.setToBogus(); |
| return result; |
| } |
| |
| URegistryKey U_EXPORT2 |
| Collator::registerFactory(CollatorFactory* toAdopt, UErrorCode& status) |
| { |
| if (U_SUCCESS(status)) { |
| CFactory* f = new CFactory(toAdopt, status); |
| if (f) { |
| return getService()->registerFactory(f, status); |
| } |
| status = U_MEMORY_ALLOCATION_ERROR; |
| } |
| return NULL; |
| } |
| |
| // ------------------------------------- |
| |
| UBool U_EXPORT2 |
| Collator::unregister(URegistryKey key, UErrorCode& status) |
| { |
| if (U_SUCCESS(status)) { |
| if (hasService()) { |
| return gService->unregister(key, status); |
| } |
| status = U_ILLEGAL_ARGUMENT_ERROR; |
| } |
| return FALSE; |
| } |
| #endif /* UCONFIG_NO_SERVICE */ |
| |
| class CollationLocaleListEnumeration : public StringEnumeration { |
| private: |
| int32_t index; |
| public: |
| static UClassID U_EXPORT2 getStaticClassID(void); |
| virtual UClassID getDynamicClassID(void) const; |
| public: |
| CollationLocaleListEnumeration() |
| : index(0) |
| { |
| // The global variables should already be initialized. |
| //isAvailableLocaleListInitialized(status); |
| } |
| |
| virtual ~CollationLocaleListEnumeration() { |
| } |
| |
| virtual StringEnumeration * clone() const |
| { |
| CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration(); |
| if (result) { |
| result->index = index; |
| } |
| return result; |
| } |
| |
| virtual int32_t count(UErrorCode &/*status*/) const { |
| return availableLocaleListCount; |
| } |
| |
| virtual const char* next(int32_t* resultLength, UErrorCode& /*status*/) { |
| const char* result; |
| if(index < availableLocaleListCount) { |
| result = availableLocaleList[index++].getName(); |
| if(resultLength != NULL) { |
| *resultLength = (int32_t)uprv_strlen(result); |
| } |
| } else { |
| if(resultLength != NULL) { |
| *resultLength = 0; |
| } |
| result = NULL; |
| } |
| return result; |
| } |
| |
| virtual const UnicodeString* snext(UErrorCode& status) { |
| int32_t resultLength = 0; |
| const char *s = next(&resultLength, status); |
| return setChars(s, resultLength, status); |
| } |
| |
| virtual void reset(UErrorCode& /*status*/) { |
| index = 0; |
| } |
| }; |
| |
| UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration) |
| |
| |
| // ------------------------------------- |
| |
| StringEnumeration* U_EXPORT2 |
| Collator::getAvailableLocales(void) |
| { |
| #if !UCONFIG_NO_SERVICE |
| if (hasService()) { |
| return getService()->getAvailableLocales(); |
| } |
| #endif /* UCONFIG_NO_SERVICE */ |
| UErrorCode status = U_ZERO_ERROR; |
| if (isAvailableLocaleListInitialized(status)) { |
| return new CollationLocaleListEnumeration(); |
| } |
| return NULL; |
| } |
| |
| StringEnumeration* U_EXPORT2 |
| Collator::getKeywords(UErrorCode& status) { |
| // This is a wrapper over ucol_getKeywords |
| UEnumeration* uenum = ucol_getKeywords(&status); |
| if (U_FAILURE(status)) { |
| uenum_close(uenum); |
| return NULL; |
| } |
| return new UStringEnumeration(uenum); |
| } |
| |
| StringEnumeration* U_EXPORT2 |
| Collator::getKeywordValues(const char *keyword, UErrorCode& status) { |
| // This is a wrapper over ucol_getKeywordValues |
| UEnumeration* uenum = ucol_getKeywordValues(keyword, &status); |
| if (U_FAILURE(status)) { |
| uenum_close(uenum); |
| return NULL; |
| } |
| return new UStringEnumeration(uenum); |
| } |
| |
| StringEnumeration* U_EXPORT2 |
| Collator::getKeywordValuesForLocale(const char* key, const Locale& locale, |
| UBool commonlyUsed, UErrorCode& status) { |
| // This is a wrapper over ucol_getKeywordValuesForLocale |
| UEnumeration *uenum = ucol_getKeywordValuesForLocale(key, locale.getName(), |
| commonlyUsed, &status); |
| if (U_FAILURE(status)) { |
| uenum_close(uenum); |
| return NULL; |
| } |
| return new UStringEnumeration(uenum); |
| } |
| |
| Locale U_EXPORT2 |
| Collator::getFunctionalEquivalent(const char* keyword, const Locale& locale, |
| UBool& isAvailable, UErrorCode& status) { |
| // This is a wrapper over ucol_getFunctionalEquivalent |
| char loc[ULOC_FULLNAME_CAPACITY]; |
| /*int32_t len =*/ ucol_getFunctionalEquivalent(loc, sizeof(loc), |
| keyword, locale.getName(), &isAvailable, &status); |
| if (U_FAILURE(status)) { |
| *loc = 0; // root |
| } |
| return Locale::createFromName(loc); |
| } |
| |
| int32_t Collator::getReorderCodes(int32_t *dest, |
| int32_t destCapacity, |
| UErrorCode& status) const |
| { |
| if (U_SUCCESS(status)) { |
| status = U_UNSUPPORTED_ERROR; |
| } |
| return 0; |
| } |
| |
| void Collator::setReorderCodes(const int32_t *reorderCodes, |
| int32_t reorderCodesLength, |
| UErrorCode& status) |
| { |
| if (U_SUCCESS(status)) { |
| status = U_UNSUPPORTED_ERROR; |
| } |
| } |
| |
| // UCollator private data members ---------------------------------------- |
| |
| /* This is useless information */ |
| /*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/ |
| |
| // ------------------------------------- |
| |
| U_NAMESPACE_END |
| |
| #endif /* #if !UCONFIG_NO_COLLATION */ |
| |
| /* eof */ |