1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ******************************************************************************
5 * Copyright (C) 1996-2014, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ******************************************************************************
13 * Created by: Helena Shih
15 * Modification History:
17 * Date Name Description
18 * 2/5/97 aliu Modified createDefault to load collation data from
19 * binary files when possible. Added related methods
20 * createCollationFromFile, chopLocale, createPathName.
21 * 2/11/97 aliu Added methods addToCache, findInCache, which implement
22 * a Collation cache. Modified createDefault to look in
23 * cache first, and also to store newly created Collation
24 * objects in the cache. Modified to not use gLocPath.
25 * 2/12/97 aliu Modified to create objects from RuleBasedCollator cache.
26 * Moved cache out of Collation class.
27 * 2/13/97 aliu Moved several methods out of this class and into
28 * RuleBasedCollator, with modifications. Modified
29 * createDefault() to call new RuleBasedCollator(Locale&)
30 * constructor. General clean up and documentation.
31 * 2/20/97 helena Added clone, operator==, operator!=, operator=, and copy
33 * 05/06/97 helena Added memory allocation error detection.
34 * 05/08/97 helena Added createInstance().
35 * 6/20/97 helena Java class name change.
36 * 04/23/99 stephen Removed EDecompositionMode, merged with
38 * 11/23/9 srl Inlining of some critical functions
39 * 01/29/01 synwee Modified into a C++ wrapper calling C APIs (ucol.h)
40 * 2012-2014 markus Rewritten in C++ again.
43 #include "utypeinfo.h" // for 'typeid' to work
45 #include "unicode/utypes.h"
47 #if !UCONFIG_NO_COLLATION
49 #include "unicode/coll.h"
50 #include "unicode/tblcoll.h"
51 #include "collationdata.h"
52 #include "collationroot.h"
53 #include "collationtailoring.h"
64 static icu::Locale
* availableLocaleList
= NULL
;
65 static int32_t availableLocaleListCount
;
66 #if !UCONFIG_NO_SERVICE
67 static icu::ICULocaleService
* gService
= NULL
;
68 static icu::UInitOnce gServiceInitOnce
= U_INITONCE_INITIALIZER
;
70 static icu::UInitOnce gAvailableLocaleListInitOnce
;
73 * Release all static memory held by collator.
76 static UBool U_CALLCONV
collator_cleanup(void) {
77 #if !UCONFIG_NO_SERVICE
82 gServiceInitOnce
.reset();
84 if (availableLocaleList
) {
85 delete []availableLocaleList
;
86 availableLocaleList
= NULL
;
88 availableLocaleListCount
= 0;
89 gAvailableLocaleListInitOnce
.reset();
97 #if !UCONFIG_NO_SERVICE
99 // ------------------------------------------
104 //-------------------------------------------
106 CollatorFactory::~CollatorFactory() {}
108 //-------------------------------------------
111 CollatorFactory::visible(void) const {
115 //-------------------------------------------
118 CollatorFactory::getDisplayName(const Locale
& objectLocale
,
119 const Locale
& displayLocale
,
120 UnicodeString
& result
)
122 return objectLocale
.getDisplayName(displayLocale
, result
);
125 // -------------------------------------
127 class ICUCollatorFactory
: public ICUResourceBundleFactory
{
129 ICUCollatorFactory() : ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL
, -1, US_INV
)) { }
130 virtual ~ICUCollatorFactory();
132 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const;
135 ICUCollatorFactory::~ICUCollatorFactory() {}
138 ICUCollatorFactory::create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& status
) const {
139 if (handlesKey(key
, status
)) {
140 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
142 // make sure the requested locale is correct
143 // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey
144 // but for ICU rb resources we use the actual one since it will fallback again
145 lkey
.canonicalLocale(loc
);
147 return Collator::makeInstance(loc
, status
);
152 // -------------------------------------
154 class ICUCollatorService
: public ICULocaleService
{
157 : ICULocaleService(UNICODE_STRING_SIMPLE("Collator"))
159 UErrorCode status
= U_ZERO_ERROR
;
160 registerFactory(new ICUCollatorFactory(), status
);
163 virtual ~ICUCollatorService();
165 virtual UObject
* cloneInstance(UObject
* instance
) const {
166 return ((Collator
*)instance
)->clone();
169 virtual UObject
* handleDefault(const ICUServiceKey
& key
, UnicodeString
* actualID
, UErrorCode
& status
) const {
170 LocaleKey
& lkey
= (LocaleKey
&)key
;
172 // Ugly Hack Alert! We return an empty actualID to signal
173 // to callers that this is a default object, not a "real"
174 // service-created object. (TODO remove in 3.0) [aliu]
175 actualID
->truncate(0);
178 lkey
.canonicalLocale(loc
);
179 return Collator::makeInstance(loc
, status
);
182 virtual UObject
* getKey(ICUServiceKey
& key
, UnicodeString
* actualReturn
, UErrorCode
& status
) const {
184 if (actualReturn
== NULL
) {
187 return (Collator
*)ICULocaleService::getKey(key
, actualReturn
, status
);
190 virtual UBool
isDefault() const {
191 return countFactories() == 1;
195 ICUCollatorService::~ICUCollatorService() {}
197 // -------------------------------------
199 static void U_CALLCONV
initService() {
200 gService
= new ICUCollatorService();
201 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR
, collator_cleanup
);
205 static ICULocaleService
*
208 umtx_initOnce(gServiceInitOnce
, &initService
);
212 // -------------------------------------
217 UBool retVal
= !gServiceInitOnce
.isReset() && (getService() != NULL
);
221 #endif /* UCONFIG_NO_SERVICE */
223 static void U_CALLCONV
224 initAvailableLocaleList(UErrorCode
&status
) {
225 U_ASSERT(availableLocaleListCount
== 0);
226 U_ASSERT(availableLocaleList
== NULL
);
227 // for now, there is a hardcoded list, so just walk through that list and set it up.
228 UResourceBundle
*index
= NULL
;
229 UResourceBundle installed
;
232 ures_initStackObject(&installed
);
233 index
= ures_openDirect(U_ICUDATA_COLL
, "res_index", &status
);
234 ures_getByKey(index
, "InstalledLocales", &installed
, &status
);
236 if(U_SUCCESS(status
)) {
237 availableLocaleListCount
= ures_getSize(&installed
);
238 availableLocaleList
= new Locale
[availableLocaleListCount
];
240 if (availableLocaleList
!= NULL
) {
241 ures_resetIterator(&installed
);
242 while(ures_hasNext(&installed
)) {
243 const char *tempKey
= NULL
;
244 ures_getNextString(&installed
, NULL
, &tempKey
, &status
);
245 availableLocaleList
[i
++] = Locale(tempKey
);
248 U_ASSERT(availableLocaleListCount
== i
);
249 ures_close(&installed
);
252 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR
, collator_cleanup
);
255 static UBool
isAvailableLocaleListInitialized(UErrorCode
&status
) {
256 umtx_initOnce(gAvailableLocaleListInitOnce
, &initAvailableLocaleList
, status
);
257 return U_SUCCESS(status
);
261 // Collator public methods -----------------------------------------------
265 static const struct {
268 } collAttributes
[] = {
269 { "colStrength", UCOL_STRENGTH
},
270 { "colBackwards", UCOL_FRENCH_COLLATION
},
271 { "colCaseLevel", UCOL_CASE_LEVEL
},
272 { "colCaseFirst", UCOL_CASE_FIRST
},
273 { "colAlternate", UCOL_ALTERNATE_HANDLING
},
274 { "colNormalization", UCOL_NORMALIZATION_MODE
},
275 { "colNumeric", UCOL_NUMERIC_COLLATION
}
278 static const struct {
280 UColAttributeValue value
;
281 } collAttributeValues
[] = {
282 { "primary", UCOL_PRIMARY
},
283 { "secondary", UCOL_SECONDARY
},
284 { "tertiary", UCOL_TERTIARY
},
285 { "quaternary", UCOL_QUATERNARY
},
286 // Note: Not supporting typo "quarternary" because it was never supported in locale IDs.
287 { "identical", UCOL_IDENTICAL
},
290 { "shifted", UCOL_SHIFTED
},
291 { "non-ignorable", UCOL_NON_IGNORABLE
},
292 { "lower", UCOL_LOWER_FIRST
},
293 { "upper", UCOL_UPPER_FIRST
}
296 static const char *collReorderCodes
[UCOL_REORDER_CODE_LIMIT
- UCOL_REORDER_CODE_FIRST
] = {
297 "space", "punct", "symbol", "currency", "digit"
300 int32_t getReorderCode(const char *s
) {
301 for (int32_t i
= 0; i
< UPRV_LENGTHOF(collReorderCodes
); ++i
) {
302 if (uprv_stricmp(s
, collReorderCodes
[i
]) == 0) {
303 return UCOL_REORDER_CODE_FIRST
+ i
;
306 // Not supporting "others" = UCOL_REORDER_CODE_OTHERS
307 // as a synonym for Zzzz = USCRIPT_UNKNOWN for now:
308 // Avoid introducing synonyms/aliases.
313 * Sets collation attributes according to locale keywords. See
314 * http://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Settings
316 * Using "alias" keywords and values where defined:
317 * http://www.unicode.org/reports/tr35/tr35.html#Old_Locale_Extension_Syntax
318 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml
320 void setAttributesFromKeywords(const Locale
&loc
, Collator
&coll
, UErrorCode
&errorCode
) {
321 if (U_FAILURE(errorCode
)) {
324 if (uprv_strcmp(loc
.getName(), loc
.getBaseName()) == 0) {
328 char value
[1024]; // The reordering value could be long.
329 // Check for collation keywords that were already deprecated
330 // before any were supported in createInstance() (except for "collation").
331 int32_t length
= loc
.getKeywordValue("colHiraganaQuaternary", value
, UPRV_LENGTHOF(value
), errorCode
);
332 if (U_FAILURE(errorCode
)) {
333 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
337 errorCode
= U_UNSUPPORTED_ERROR
;
340 length
= loc
.getKeywordValue("variableTop", value
, UPRV_LENGTHOF(value
), errorCode
);
341 if (U_FAILURE(errorCode
)) {
342 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
346 errorCode
= U_UNSUPPORTED_ERROR
;
349 // Parse known collation keywords, ignore others.
350 if (errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
351 errorCode
= U_ZERO_ERROR
;
353 for (int32_t i
= 0; i
< UPRV_LENGTHOF(collAttributes
); ++i
) {
354 length
= loc
.getKeywordValue(collAttributes
[i
].name
, value
, UPRV_LENGTHOF(value
), errorCode
);
355 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
356 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
359 if (length
== 0) { continue; }
360 for (int32_t j
= 0;; ++j
) {
361 if (j
== UPRV_LENGTHOF(collAttributeValues
)) {
362 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
365 if (uprv_stricmp(value
, collAttributeValues
[j
].name
) == 0) {
366 coll
.setAttribute(collAttributes
[i
].attr
, collAttributeValues
[j
].value
, errorCode
);
371 length
= loc
.getKeywordValue("colReorder", value
, UPRV_LENGTHOF(value
), errorCode
);
372 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
373 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
377 int32_t codes
[USCRIPT_CODE_LIMIT
+ UCOL_REORDER_CODE_LIMIT
- UCOL_REORDER_CODE_FIRST
];
378 int32_t codesLength
= 0;
379 char *scriptName
= value
;
381 if (codesLength
== UPRV_LENGTHOF(codes
)) {
382 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
385 char *limit
= scriptName
;
387 while ((c
= *limit
) != 0 && c
!= '-') { ++limit
; }
390 if ((limit
- scriptName
) == 4) {
391 // Strict parsing, accept only 4-letter script codes, not long names.
392 code
= u_getPropertyValueEnum(UCHAR_SCRIPT
, scriptName
);
394 code
= getReorderCode(scriptName
);
397 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
400 codes
[codesLength
++] = code
;
401 if (c
== 0) { break; }
402 scriptName
= limit
+ 1;
404 coll
.setReorderCodes(codes
, codesLength
, errorCode
);
406 length
= loc
.getKeywordValue("kv", value
, UPRV_LENGTHOF(value
), errorCode
);
407 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
408 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
412 int32_t code
= getReorderCode(value
);
414 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
417 coll
.setMaxVariable((UColReorderCode
)code
, errorCode
);
419 if (U_FAILURE(errorCode
)) {
420 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
426 Collator
* U_EXPORT2
Collator::createInstance(UErrorCode
& success
)
428 return createInstance(Locale::getDefault(), success
);
431 Collator
* U_EXPORT2
Collator::createInstance(const Locale
& desiredLocale
,
434 if (U_FAILURE(status
))
436 if (desiredLocale
.isBogus()) {
437 // Locale constructed from malformed locale ID or language tag.
438 status
= U_ILLEGAL_ARGUMENT_ERROR
;
443 #if !UCONFIG_NO_SERVICE
446 coll
= (Collator
*)gService
->get(desiredLocale
, &actualLoc
, status
);
450 coll
= makeInstance(desiredLocale
, status
);
452 setAttributesFromKeywords(desiredLocale
, *coll
, status
);
453 if (U_FAILURE(status
)) {
461 Collator
* Collator::makeInstance(const Locale
& desiredLocale
, UErrorCode
& status
) {
462 const CollationCacheEntry
*entry
= CollationLoader::loadTailoring(desiredLocale
, status
);
463 if (U_SUCCESS(status
)) {
464 Collator
*result
= new RuleBasedCollator(entry
);
465 if (result
!= NULL
) {
466 // Both the unified cache's get() and the RBC constructor
467 // did addRef(). Undo one of them.
471 status
= U_MEMORY_ALLOCATION_ERROR
;
474 // Undo the addRef() from the cache.get().
481 Collator::safeClone() const {
485 // implement deprecated, previously abstract method
486 Collator::EComparisonResult
Collator::compare(const UnicodeString
& source
,
487 const UnicodeString
& target
) const
489 UErrorCode ec
= U_ZERO_ERROR
;
490 return (EComparisonResult
)compare(source
, target
, ec
);
493 // implement deprecated, previously abstract method
494 Collator::EComparisonResult
Collator::compare(const UnicodeString
& source
,
495 const UnicodeString
& target
,
496 int32_t length
) const
498 UErrorCode ec
= U_ZERO_ERROR
;
499 return (EComparisonResult
)compare(source
, target
, length
, ec
);
502 // implement deprecated, previously abstract method
503 Collator::EComparisonResult
Collator::compare(const UChar
* source
, int32_t sourceLength
,
504 const UChar
* target
, int32_t targetLength
)
507 UErrorCode ec
= U_ZERO_ERROR
;
508 return (EComparisonResult
)compare(source
, sourceLength
, target
, targetLength
, ec
);
511 UCollationResult
Collator::compare(UCharIterator
&/*sIter*/,
512 UCharIterator
&/*tIter*/,
513 UErrorCode
&status
) const {
514 if(U_SUCCESS(status
)) {
515 // Not implemented in the base class.
516 status
= U_UNSUPPORTED_ERROR
;
521 UCollationResult
Collator::compareUTF8(const StringPiece
&source
,
522 const StringPiece
&target
,
523 UErrorCode
&status
) const {
524 if(U_FAILURE(status
)) {
527 UCharIterator sIter
, tIter
;
528 uiter_setUTF8(&sIter
, source
.data(), source
.length());
529 uiter_setUTF8(&tIter
, target
.data(), target
.length());
530 return compare(sIter
, tIter
, status
);
533 UBool
Collator::equals(const UnicodeString
& source
,
534 const UnicodeString
& target
) const
536 UErrorCode ec
= U_ZERO_ERROR
;
537 return (compare(source
, target
, ec
) == UCOL_EQUAL
);
540 UBool
Collator::greaterOrEqual(const UnicodeString
& source
,
541 const UnicodeString
& target
) const
543 UErrorCode ec
= U_ZERO_ERROR
;
544 return (compare(source
, target
, ec
) != UCOL_LESS
);
547 UBool
Collator::greater(const UnicodeString
& source
,
548 const UnicodeString
& target
) const
550 UErrorCode ec
= U_ZERO_ERROR
;
551 return (compare(source
, target
, ec
) == UCOL_GREATER
);
554 // this API ignores registered collators, since it returns an
555 // array of indefinite lifetime
556 const Locale
* U_EXPORT2
Collator::getAvailableLocales(int32_t& count
)
558 UErrorCode status
= U_ZERO_ERROR
;
559 Locale
*result
= NULL
;
561 if (isAvailableLocaleListInitialized(status
))
563 result
= availableLocaleList
;
564 count
= availableLocaleListCount
;
569 UnicodeString
& U_EXPORT2
Collator::getDisplayName(const Locale
& objectLocale
,
570 const Locale
& displayLocale
,
573 #if !UCONFIG_NO_SERVICE
575 UnicodeString locNameStr
;
576 LocaleUtility::initNameFromLocale(objectLocale
, locNameStr
);
577 return gService
->getDisplayName(locNameStr
, name
, displayLocale
);
580 return objectLocale
.getDisplayName(displayLocale
, name
);
583 UnicodeString
& U_EXPORT2
Collator::getDisplayName(const Locale
& objectLocale
,
586 return getDisplayName(objectLocale
, Locale::getDefault(), name
);
589 /* This is useless information */
590 /*void Collator::getVersion(UVersionInfo versionInfo) const
592 if (versionInfo!=NULL)
593 uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH);
597 // UCollator protected constructor destructor ----------------------------
600 * Default constructor.
601 * Constructor is different from the old default Collator constructor.
602 * The task for determing the default collation strength and normalization mode
603 * is left to the child class.
612 * Empty constructor, does not handle the arguments.
613 * This constructor is done for backward compatibility with 1.7 and 1.8.
614 * The task for handling the argument collation strength and normalization
615 * mode is left to the child class.
616 * @param collationStrength collation strength
617 * @param decompositionMode
618 * @deprecated 2.4 use the default constructor instead
620 Collator::Collator(UCollationStrength
, UNormalizationMode
)
625 Collator::~Collator()
629 Collator::Collator(const Collator
&other
)
634 UBool
Collator::operator==(const Collator
& other
) const
636 // Subclasses: Call this method and then add more specific checks.
637 return typeid(*this) == typeid(other
);
640 UBool
Collator::operator!=(const Collator
& other
) const
642 return (UBool
)!(*this == other
);
645 int32_t U_EXPORT2
Collator::getBound(const uint8_t *source
,
646 int32_t sourceLength
,
647 UColBoundMode boundType
,
650 int32_t resultLength
,
653 return ucol_getBound(source
, sourceLength
, boundType
, noOfLevels
, result
, resultLength
, &status
);
657 Collator::setLocales(const Locale
& /* requestedLocale */, const Locale
& /* validLocale */, const Locale
& /*actualLocale*/) {
660 UnicodeSet
*Collator::getTailoredSet(UErrorCode
&status
) const
662 if(U_FAILURE(status
)) {
665 // everything can be changed
666 return new UnicodeSet(0, 0x10FFFF);
669 // -------------------------------------
671 #if !UCONFIG_NO_SERVICE
672 URegistryKey U_EXPORT2
673 Collator::registerInstance(Collator
* toAdopt
, const Locale
& locale
, UErrorCode
& status
)
675 if (U_SUCCESS(status
)) {
676 // Set the collator locales while registering so that createInstance()
677 // need not guess whether the collator's locales are already set properly
678 // (as they are by the data loader).
679 toAdopt
->setLocales(locale
, locale
, locale
);
680 return getService()->registerInstance(toAdopt
, locale
, status
);
685 // -------------------------------------
687 class CFactory
: public LocaleKeyFactory
{
689 CollatorFactory
* _delegate
;
693 CFactory(CollatorFactory
* delegate
, UErrorCode
& status
)
694 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
695 , _delegate(delegate
)
698 if (U_SUCCESS(status
)) {
700 _ids
= new Hashtable(status
);
702 const UnicodeString
* idlist
= _delegate
->getSupportedIDs(count
, status
);
703 for (int i
= 0; i
< count
; ++i
) {
704 _ids
->put(idlist
[i
], (void*)this, status
);
705 if (U_FAILURE(status
)) {
712 status
= U_MEMORY_ALLOCATION_ERROR
;
719 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const;
722 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
724 if (U_SUCCESS(status
)) {
730 virtual UnicodeString
&
731 getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const;
734 CFactory::~CFactory()
741 CFactory::create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& status
) const
743 if (handlesKey(key
, status
)) {
744 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
746 lkey
.currentLocale(validLoc
);
747 return _delegate
->createCollator(validLoc
);
753 CFactory::getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const
755 if ((_coverage
& 0x1) == 0) {
756 UErrorCode status
= U_ZERO_ERROR
;
757 const Hashtable
* ids
= getSupportedIDs(status
);
758 if (ids
&& (ids
->get(id
) != NULL
)) {
760 LocaleUtility::initLocaleFromName(id
, loc
);
761 return _delegate
->getDisplayName(loc
, locale
, result
);
768 URegistryKey U_EXPORT2
769 Collator::registerFactory(CollatorFactory
* toAdopt
, UErrorCode
& status
)
771 if (U_SUCCESS(status
)) {
772 CFactory
* f
= new CFactory(toAdopt
, status
);
774 return getService()->registerFactory(f
, status
);
776 status
= U_MEMORY_ALLOCATION_ERROR
;
781 // -------------------------------------
784 Collator::unregister(URegistryKey key
, UErrorCode
& status
)
786 if (U_SUCCESS(status
)) {
788 return gService
->unregister(key
, status
);
790 status
= U_ILLEGAL_ARGUMENT_ERROR
;
794 #endif /* UCONFIG_NO_SERVICE */
796 class CollationLocaleListEnumeration
: public StringEnumeration
{
800 static UClassID U_EXPORT2
getStaticClassID(void);
801 virtual UClassID
getDynamicClassID(void) const;
803 CollationLocaleListEnumeration()
806 // The global variables should already be initialized.
807 //isAvailableLocaleListInitialized(status);
810 virtual ~CollationLocaleListEnumeration();
812 virtual StringEnumeration
* clone() const
814 CollationLocaleListEnumeration
*result
= new CollationLocaleListEnumeration();
816 result
->index
= index
;
821 virtual int32_t count(UErrorCode
&/*status*/) const {
822 return availableLocaleListCount
;
825 virtual const char* next(int32_t* resultLength
, UErrorCode
& /*status*/) {
827 if(index
< availableLocaleListCount
) {
828 result
= availableLocaleList
[index
++].getName();
829 if(resultLength
!= NULL
) {
830 *resultLength
= (int32_t)uprv_strlen(result
);
833 if(resultLength
!= NULL
) {
841 virtual const UnicodeString
* snext(UErrorCode
& status
) {
842 int32_t resultLength
= 0;
843 const char *s
= next(&resultLength
, status
);
844 return setChars(s
, resultLength
, status
);
847 virtual void reset(UErrorCode
& /*status*/) {
852 CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {}
854 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration
)
857 // -------------------------------------
859 StringEnumeration
* U_EXPORT2
860 Collator::getAvailableLocales(void)
862 #if !UCONFIG_NO_SERVICE
864 return getService()->getAvailableLocales();
866 #endif /* UCONFIG_NO_SERVICE */
867 UErrorCode status
= U_ZERO_ERROR
;
868 if (isAvailableLocaleListInitialized(status
)) {
869 return new CollationLocaleListEnumeration();
874 StringEnumeration
* U_EXPORT2
875 Collator::getKeywords(UErrorCode
& status
) {
876 return UStringEnumeration::fromUEnumeration(
877 ucol_getKeywords(&status
), status
);
880 StringEnumeration
* U_EXPORT2
881 Collator::getKeywordValues(const char *keyword
, UErrorCode
& status
) {
882 return UStringEnumeration::fromUEnumeration(
883 ucol_getKeywordValues(keyword
, &status
), status
);
886 StringEnumeration
* U_EXPORT2
887 Collator::getKeywordValuesForLocale(const char* key
, const Locale
& locale
,
888 UBool commonlyUsed
, UErrorCode
& status
) {
889 return UStringEnumeration::fromUEnumeration(
890 ucol_getKeywordValuesForLocale(
891 key
, locale
.getName(), commonlyUsed
, &status
),
896 Collator::getFunctionalEquivalent(const char* keyword
, const Locale
& locale
,
897 UBool
& isAvailable
, UErrorCode
& status
) {
898 // This is a wrapper over ucol_getFunctionalEquivalent
899 char loc
[ULOC_FULLNAME_CAPACITY
];
900 /*int32_t len =*/ ucol_getFunctionalEquivalent(loc
, sizeof(loc
),
901 keyword
, locale
.getName(), &isAvailable
, &status
);
902 if (U_FAILURE(status
)) {
905 return Locale::createFromName(loc
);
908 Collator::ECollationStrength
909 Collator::getStrength(void) const {
910 UErrorCode intStatus
= U_ZERO_ERROR
;
911 return (ECollationStrength
)getAttribute(UCOL_STRENGTH
, intStatus
);
915 Collator::setStrength(ECollationStrength newStrength
) {
916 UErrorCode intStatus
= U_ZERO_ERROR
;
917 setAttribute(UCOL_STRENGTH
, (UColAttributeValue
)newStrength
, intStatus
);
921 Collator::setMaxVariable(UColReorderCode
/*group*/, UErrorCode
&errorCode
) {
922 if (U_SUCCESS(errorCode
)) {
923 errorCode
= U_UNSUPPORTED_ERROR
;
929 Collator::getMaxVariable() const {
930 return UCOL_REORDER_CODE_PUNCTUATION
;
934 Collator::getReorderCodes(int32_t* /* dest*/,
935 int32_t /* destCapacity*/,
936 UErrorCode
& status
) const
938 if (U_SUCCESS(status
)) {
939 status
= U_UNSUPPORTED_ERROR
;
945 Collator::setReorderCodes(const int32_t* /* reorderCodes */,
946 int32_t /* reorderCodesLength */,
949 if (U_SUCCESS(status
)) {
950 status
= U_UNSUPPORTED_ERROR
;
955 Collator::getEquivalentReorderCodes(int32_t reorderCode
,
956 int32_t *dest
, int32_t capacity
,
957 UErrorCode
&errorCode
) {
958 if(U_FAILURE(errorCode
)) { return 0; }
959 if(capacity
< 0 || (dest
== NULL
&& capacity
> 0)) {
960 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
963 const CollationData
*baseData
= CollationRoot::getData(errorCode
);
964 if(U_FAILURE(errorCode
)) { return 0; }
965 return baseData
->getEquivalentScripts(reorderCode
, dest
, capacity
, errorCode
);
969 Collator::internalGetShortDefinitionString(const char * /*locale*/,
971 int32_t /*capacity*/,
972 UErrorCode
&status
) const {
973 if(U_SUCCESS(status
)) {
974 status
= U_UNSUPPORTED_ERROR
; /* Shouldn't happen, internal function */
980 Collator::internalCompareUTF8(const char *left
, int32_t leftLength
,
981 const char *right
, int32_t rightLength
,
982 UErrorCode
&errorCode
) const {
983 if(U_FAILURE(errorCode
)) { return UCOL_EQUAL
; }
984 if((left
== NULL
&& leftLength
!= 0) || (right
== NULL
&& rightLength
!= 0)) {
985 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
989 StringPiece(left
, (leftLength
< 0) ? uprv_strlen(left
) : leftLength
),
990 StringPiece(right
, (rightLength
< 0) ? uprv_strlen(right
) : rightLength
),
995 Collator::internalNextSortKeyPart(UCharIterator
* /*iter*/, uint32_t /*state*/[2],
996 uint8_t * /*dest*/, int32_t /*count*/, UErrorCode
&errorCode
) const {
997 if (U_SUCCESS(errorCode
)) {
998 errorCode
= U_UNSUPPORTED_ERROR
;
1003 // UCollator private data members ----------------------------------------
1005 /* This is useless information */
1006 /*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/
1008 // -------------------------------------
1012 #endif /* #if !UCONFIG_NO_COLLATION */