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"
63 #if U_PLATFORM_IS_DARWIN_BASED
67 static icu::Locale
* availableLocaleList
= NULL
;
68 static int32_t availableLocaleListCount
;
69 #if !UCONFIG_NO_SERVICE
70 static icu::ICULocaleService
* gService
= NULL
;
71 static icu::UInitOnce gServiceInitOnce
= U_INITONCE_INITIALIZER
;
73 static icu::UInitOnce gAvailableLocaleListInitOnce
;
76 * Release all static memory held by collator.
79 static UBool U_CALLCONV
collator_cleanup(void) {
80 #if !UCONFIG_NO_SERVICE
85 gServiceInitOnce
.reset();
87 if (availableLocaleList
) {
88 delete []availableLocaleList
;
89 availableLocaleList
= NULL
;
91 availableLocaleListCount
= 0;
92 gAvailableLocaleListInitOnce
.reset();
100 #if !UCONFIG_NO_SERVICE
102 // ------------------------------------------
107 //-------------------------------------------
109 CollatorFactory::~CollatorFactory() {}
111 //-------------------------------------------
114 CollatorFactory::visible(void) const {
118 //-------------------------------------------
121 CollatorFactory::getDisplayName(const Locale
& objectLocale
,
122 const Locale
& displayLocale
,
123 UnicodeString
& result
)
125 return objectLocale
.getDisplayName(displayLocale
, result
);
128 // -------------------------------------
130 class ICUCollatorFactory
: public ICUResourceBundleFactory
{
132 ICUCollatorFactory() : ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL
, -1, US_INV
)) { }
133 virtual ~ICUCollatorFactory();
135 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const;
138 ICUCollatorFactory::~ICUCollatorFactory() {}
141 ICUCollatorFactory::create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& status
) const {
142 if (handlesKey(key
, status
)) {
143 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
145 // make sure the requested locale is correct
146 // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey
147 // but for ICU rb resources we use the actual one since it will fallback again
148 lkey
.canonicalLocale(loc
);
150 return Collator::makeInstance(loc
, status
);
155 // -------------------------------------
157 class ICUCollatorService
: public ICULocaleService
{
160 : ICULocaleService(UNICODE_STRING_SIMPLE("Collator"))
162 UErrorCode status
= U_ZERO_ERROR
;
163 registerFactory(new ICUCollatorFactory(), status
);
166 virtual ~ICUCollatorService();
168 virtual UObject
* cloneInstance(UObject
* instance
) const {
169 return ((Collator
*)instance
)->clone();
172 virtual UObject
* handleDefault(const ICUServiceKey
& key
, UnicodeString
* actualID
, UErrorCode
& status
) const {
173 LocaleKey
& lkey
= (LocaleKey
&)key
;
175 // Ugly Hack Alert! We return an empty actualID to signal
176 // to callers that this is a default object, not a "real"
177 // service-created object. (TODO remove in 3.0) [aliu]
178 actualID
->truncate(0);
181 lkey
.canonicalLocale(loc
);
182 return Collator::makeInstance(loc
, status
);
185 virtual UObject
* getKey(ICUServiceKey
& key
, UnicodeString
* actualReturn
, UErrorCode
& status
) const {
187 if (actualReturn
== NULL
) {
190 return (Collator
*)ICULocaleService::getKey(key
, actualReturn
, status
);
193 virtual UBool
isDefault() const {
194 return countFactories() == 1;
198 ICUCollatorService::~ICUCollatorService() {}
200 // -------------------------------------
202 static void U_CALLCONV
initService() {
203 gService
= new ICUCollatorService();
204 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR
, collator_cleanup
);
208 static ICULocaleService
*
211 umtx_initOnce(gServiceInitOnce
, &initService
);
215 // -------------------------------------
220 UBool retVal
= !gServiceInitOnce
.isReset() && (getService() != NULL
);
224 #endif /* UCONFIG_NO_SERVICE */
226 static void U_CALLCONV
227 initAvailableLocaleList(UErrorCode
&status
) {
228 U_ASSERT(availableLocaleListCount
== 0);
229 U_ASSERT(availableLocaleList
== NULL
);
230 // for now, there is a hardcoded list, so just walk through that list and set it up.
231 UResourceBundle
*index
= NULL
;
232 UResourceBundle installed
;
235 ures_initStackObject(&installed
);
236 index
= ures_openDirect(U_ICUDATA_COLL
, "res_index", &status
);
237 ures_getByKey(index
, "InstalledLocales", &installed
, &status
);
239 if(U_SUCCESS(status
)) {
240 availableLocaleListCount
= ures_getSize(&installed
);
241 availableLocaleList
= new Locale
[availableLocaleListCount
];
243 if (availableLocaleList
!= NULL
) {
244 ures_resetIterator(&installed
);
245 while(ures_hasNext(&installed
)) {
246 const char *tempKey
= NULL
;
247 ures_getNextString(&installed
, NULL
, &tempKey
, &status
);
248 availableLocaleList
[i
++] = Locale(tempKey
);
251 U_ASSERT(availableLocaleListCount
== i
);
252 ures_close(&installed
);
255 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR
, collator_cleanup
);
258 static UBool
isAvailableLocaleListInitialized(UErrorCode
&status
) {
259 umtx_initOnce(gAvailableLocaleListInitOnce
, &initAvailableLocaleList
, status
);
260 return U_SUCCESS(status
);
264 // Collator public methods -----------------------------------------------
268 static const struct {
271 } collAttributes
[] = {
272 { "colStrength", UCOL_STRENGTH
},
273 { "colBackwards", UCOL_FRENCH_COLLATION
},
274 { "colCaseLevel", UCOL_CASE_LEVEL
},
275 { "colCaseFirst", UCOL_CASE_FIRST
},
276 { "colAlternate", UCOL_ALTERNATE_HANDLING
},
277 { "colNormalization", UCOL_NORMALIZATION_MODE
},
278 { "colNumeric", UCOL_NUMERIC_COLLATION
}
281 static const struct {
283 UColAttributeValue value
;
284 } collAttributeValues
[] = {
285 { "primary", UCOL_PRIMARY
},
286 { "secondary", UCOL_SECONDARY
},
287 { "tertiary", UCOL_TERTIARY
},
288 { "quaternary", UCOL_QUATERNARY
},
289 // Note: Not supporting typo "quarternary" because it was never supported in locale IDs.
290 { "identical", UCOL_IDENTICAL
},
293 { "shifted", UCOL_SHIFTED
},
294 { "non-ignorable", UCOL_NON_IGNORABLE
},
295 { "lower", UCOL_LOWER_FIRST
},
296 { "upper", UCOL_UPPER_FIRST
}
299 static const char *collReorderCodes
[UCOL_REORDER_CODE_LIMIT
- UCOL_REORDER_CODE_FIRST
] = {
300 "space", "punct", "symbol", "currency", "digit"
303 int32_t getReorderCode(const char *s
) {
304 for (int32_t i
= 0; i
< UPRV_LENGTHOF(collReorderCodes
); ++i
) {
305 if (uprv_stricmp(s
, collReorderCodes
[i
]) == 0) {
306 return UCOL_REORDER_CODE_FIRST
+ i
;
309 // Not supporting "others" = UCOL_REORDER_CODE_OTHERS
310 // as a synonym for Zzzz = USCRIPT_UNKNOWN for now:
311 // Avoid introducing synonyms/aliases.
316 * Sets collation attributes according to locale keywords. See
317 * http://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Settings
319 * Using "alias" keywords and values where defined:
320 * http://www.unicode.org/reports/tr35/tr35.html#Old_Locale_Extension_Syntax
321 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml
323 void setAttributesFromKeywords(const Locale
&loc
, Collator
&coll
, UErrorCode
&errorCode
) {
324 if (U_FAILURE(errorCode
)) {
327 if (uprv_strcmp(loc
.getName(), loc
.getBaseName()) == 0) {
331 char value
[1024]; // The reordering value could be long.
332 // Check for collation keywords that were already deprecated
333 // before any were supported in createInstance() (except for "collation").
334 int32_t length
= loc
.getKeywordValue("colHiraganaQuaternary", value
, UPRV_LENGTHOF(value
), errorCode
);
335 if (U_FAILURE(errorCode
)) {
336 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
340 errorCode
= U_UNSUPPORTED_ERROR
;
343 length
= loc
.getKeywordValue("variableTop", value
, UPRV_LENGTHOF(value
), errorCode
);
344 if (U_FAILURE(errorCode
)) {
345 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
349 errorCode
= U_UNSUPPORTED_ERROR
;
352 // Parse known collation keywords, ignore others.
353 if (errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
354 errorCode
= U_ZERO_ERROR
;
356 for (int32_t i
= 0; i
< UPRV_LENGTHOF(collAttributes
); ++i
) {
357 length
= loc
.getKeywordValue(collAttributes
[i
].name
, value
, UPRV_LENGTHOF(value
), errorCode
);
358 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
359 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
362 if (length
== 0) { continue; }
363 for (int32_t j
= 0;; ++j
) {
364 if (j
== UPRV_LENGTHOF(collAttributeValues
)) {
365 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
368 if (uprv_stricmp(value
, collAttributeValues
[j
].name
) == 0) {
369 coll
.setAttribute(collAttributes
[i
].attr
, collAttributeValues
[j
].value
, errorCode
);
374 length
= loc
.getKeywordValue("colReorder", value
, UPRV_LENGTHOF(value
), errorCode
);
375 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
376 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
380 int32_t codes
[USCRIPT_CODE_LIMIT
+ UCOL_REORDER_CODE_LIMIT
- UCOL_REORDER_CODE_FIRST
];
381 int32_t codesLength
= 0;
382 char *scriptName
= value
;
384 if (codesLength
== UPRV_LENGTHOF(codes
)) {
385 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
388 char *limit
= scriptName
;
390 while ((c
= *limit
) != 0 && c
!= '-') { ++limit
; }
393 if ((limit
- scriptName
) == 4) {
394 // Strict parsing, accept only 4-letter script codes, not long names.
395 code
= u_getPropertyValueEnum(UCHAR_SCRIPT
, scriptName
);
397 code
= getReorderCode(scriptName
);
400 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
403 codes
[codesLength
++] = code
;
404 if (c
== 0) { break; }
405 scriptName
= limit
+ 1;
407 coll
.setReorderCodes(codes
, codesLength
, errorCode
);
409 length
= loc
.getKeywordValue("kv", value
, UPRV_LENGTHOF(value
), errorCode
);
410 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
411 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
415 int32_t code
= getReorderCode(value
);
417 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
420 coll
.setMaxVariable((UColReorderCode
)code
, errorCode
);
422 if (U_FAILURE(errorCode
)) {
423 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
429 Collator
* U_EXPORT2
Collator::createInstance(UErrorCode
& success
)
431 return createInstance(Locale::getDefault(), success
);
434 Collator
* U_EXPORT2
Collator::createInstance(const Locale
& desiredLocale
,
437 if (U_FAILURE(status
))
439 if (desiredLocale
.isBogus()) {
440 // Locale constructed from malformed locale ID or language tag.
441 status
= U_ILLEGAL_ARGUMENT_ERROR
;
446 #if !UCONFIG_NO_SERVICE
449 coll
= (Collator
*)gService
->get(desiredLocale
, &actualLoc
, status
);
453 coll
= makeInstance(desiredLocale
, status
);
455 // makeInstance either returns NULL with U_FAILURE(status), or non-NULL with U_SUCCESS(status).
456 // The *coll in setAttributesFromKeywords causes the NULL check to be optimized out of the delete
457 // even though setAttributesFromKeywords returns immediately if U_FAILURE(status), so we add a
458 // check here and also log the locale name for failures. <rdar://problem/40930320>
459 if (U_FAILURE(status
)) {
460 #if U_PLATFORM_IS_DARWIN_BASED
462 // logging disabled for shipping system, can enable for internal debugging
463 const char* locname
= desiredLocale
.getName();
464 os_log(OS_LOG_DEFAULT
, "Collator::createInstance fails with locale: %{public}s", locname
? locname
: "(NULL)");
469 setAttributesFromKeywords(desiredLocale
, *coll
, status
);
470 if (U_FAILURE(status
)) {
478 Collator
* Collator::makeInstance(const Locale
& desiredLocale
, UErrorCode
& status
) {
479 const CollationCacheEntry
*entry
= CollationLoader::loadTailoring(desiredLocale
, status
);
480 if (U_SUCCESS(status
)) {
481 Collator
*result
= new RuleBasedCollator(entry
);
482 if (result
!= NULL
) {
483 // Both the unified cache's get() and the RBC constructor
484 // did addRef(). Undo one of them.
488 status
= U_MEMORY_ALLOCATION_ERROR
;
491 // Undo the addRef() from the cache.get().
498 Collator::safeClone() const {
502 // implement deprecated, previously abstract method
503 Collator::EComparisonResult
Collator::compare(const UnicodeString
& source
,
504 const UnicodeString
& target
) const
506 UErrorCode ec
= U_ZERO_ERROR
;
507 return (EComparisonResult
)compare(source
, target
, ec
);
510 // implement deprecated, previously abstract method
511 Collator::EComparisonResult
Collator::compare(const UnicodeString
& source
,
512 const UnicodeString
& target
,
513 int32_t length
) const
515 UErrorCode ec
= U_ZERO_ERROR
;
516 return (EComparisonResult
)compare(source
, target
, length
, ec
);
519 // implement deprecated, previously abstract method
520 Collator::EComparisonResult
Collator::compare(const UChar
* source
, int32_t sourceLength
,
521 const UChar
* target
, int32_t targetLength
)
524 UErrorCode ec
= U_ZERO_ERROR
;
525 return (EComparisonResult
)compare(source
, sourceLength
, target
, targetLength
, ec
);
528 UCollationResult
Collator::compare(UCharIterator
&/*sIter*/,
529 UCharIterator
&/*tIter*/,
530 UErrorCode
&status
) const {
531 if(U_SUCCESS(status
)) {
532 // Not implemented in the base class.
533 status
= U_UNSUPPORTED_ERROR
;
538 UCollationResult
Collator::compareUTF8(const StringPiece
&source
,
539 const StringPiece
&target
,
540 UErrorCode
&status
) const {
541 if(U_FAILURE(status
)) {
544 UCharIterator sIter
, tIter
;
545 uiter_setUTF8(&sIter
, source
.data(), source
.length());
546 uiter_setUTF8(&tIter
, target
.data(), target
.length());
547 return compare(sIter
, tIter
, status
);
550 UBool
Collator::equals(const UnicodeString
& source
,
551 const UnicodeString
& target
) const
553 UErrorCode ec
= U_ZERO_ERROR
;
554 return (compare(source
, target
, ec
) == UCOL_EQUAL
);
557 UBool
Collator::greaterOrEqual(const UnicodeString
& source
,
558 const UnicodeString
& target
) const
560 UErrorCode ec
= U_ZERO_ERROR
;
561 return (compare(source
, target
, ec
) != UCOL_LESS
);
564 UBool
Collator::greater(const UnicodeString
& source
,
565 const UnicodeString
& target
) const
567 UErrorCode ec
= U_ZERO_ERROR
;
568 return (compare(source
, target
, ec
) == UCOL_GREATER
);
571 // this API ignores registered collators, since it returns an
572 // array of indefinite lifetime
573 const Locale
* U_EXPORT2
Collator::getAvailableLocales(int32_t& count
)
575 UErrorCode status
= U_ZERO_ERROR
;
576 Locale
*result
= NULL
;
578 if (isAvailableLocaleListInitialized(status
))
580 result
= availableLocaleList
;
581 count
= availableLocaleListCount
;
586 UnicodeString
& U_EXPORT2
Collator::getDisplayName(const Locale
& objectLocale
,
587 const Locale
& displayLocale
,
590 #if !UCONFIG_NO_SERVICE
592 UnicodeString locNameStr
;
593 LocaleUtility::initNameFromLocale(objectLocale
, locNameStr
);
594 return gService
->getDisplayName(locNameStr
, name
, displayLocale
);
597 return objectLocale
.getDisplayName(displayLocale
, name
);
600 UnicodeString
& U_EXPORT2
Collator::getDisplayName(const Locale
& objectLocale
,
603 return getDisplayName(objectLocale
, Locale::getDefault(), name
);
606 /* This is useless information */
607 /*void Collator::getVersion(UVersionInfo versionInfo) const
609 if (versionInfo!=NULL)
610 uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH);
614 // UCollator protected constructor destructor ----------------------------
617 * Default constructor.
618 * Constructor is different from the old default Collator constructor.
619 * The task for determing the default collation strength and normalization mode
620 * is left to the child class.
629 * Empty constructor, does not handle the arguments.
630 * This constructor is done for backward compatibility with 1.7 and 1.8.
631 * The task for handling the argument collation strength and normalization
632 * mode is left to the child class.
633 * @param collationStrength collation strength
634 * @param decompositionMode
635 * @deprecated 2.4 use the default constructor instead
637 Collator::Collator(UCollationStrength
, UNormalizationMode
)
642 Collator::~Collator()
646 Collator::Collator(const Collator
&other
)
651 UBool
Collator::operator==(const Collator
& other
) const
653 // Subclasses: Call this method and then add more specific checks.
654 return typeid(*this) == typeid(other
);
657 UBool
Collator::operator!=(const Collator
& other
) const
659 return (UBool
)!(*this == other
);
662 int32_t U_EXPORT2
Collator::getBound(const uint8_t *source
,
663 int32_t sourceLength
,
664 UColBoundMode boundType
,
667 int32_t resultLength
,
670 return ucol_getBound(source
, sourceLength
, boundType
, noOfLevels
, result
, resultLength
, &status
);
674 Collator::setLocales(const Locale
& /* requestedLocale */, const Locale
& /* validLocale */, const Locale
& /*actualLocale*/) {
677 UnicodeSet
*Collator::getTailoredSet(UErrorCode
&status
) const
679 if(U_FAILURE(status
)) {
682 // everything can be changed
683 return new UnicodeSet(0, 0x10FFFF);
686 // -------------------------------------
688 #if !UCONFIG_NO_SERVICE
689 URegistryKey U_EXPORT2
690 Collator::registerInstance(Collator
* toAdopt
, const Locale
& locale
, UErrorCode
& status
)
692 if (U_SUCCESS(status
)) {
693 // Set the collator locales while registering so that createInstance()
694 // need not guess whether the collator's locales are already set properly
695 // (as they are by the data loader).
696 toAdopt
->setLocales(locale
, locale
, locale
);
697 return getService()->registerInstance(toAdopt
, locale
, status
);
702 // -------------------------------------
704 class CFactory
: public LocaleKeyFactory
{
706 CollatorFactory
* _delegate
;
710 CFactory(CollatorFactory
* delegate
, UErrorCode
& status
)
711 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
712 , _delegate(delegate
)
715 if (U_SUCCESS(status
)) {
717 _ids
= new Hashtable(status
);
719 const UnicodeString
* idlist
= _delegate
->getSupportedIDs(count
, status
);
720 for (int i
= 0; i
< count
; ++i
) {
721 _ids
->put(idlist
[i
], (void*)this, status
);
722 if (U_FAILURE(status
)) {
729 status
= U_MEMORY_ALLOCATION_ERROR
;
736 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const;
739 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
741 if (U_SUCCESS(status
)) {
747 virtual UnicodeString
&
748 getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const;
751 CFactory::~CFactory()
758 CFactory::create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& status
) const
760 if (handlesKey(key
, status
)) {
761 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
763 lkey
.currentLocale(validLoc
);
764 return _delegate
->createCollator(validLoc
);
770 CFactory::getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const
772 if ((_coverage
& 0x1) == 0) {
773 UErrorCode status
= U_ZERO_ERROR
;
774 const Hashtable
* ids
= getSupportedIDs(status
);
775 if (ids
&& (ids
->get(id
) != NULL
)) {
777 LocaleUtility::initLocaleFromName(id
, loc
);
778 return _delegate
->getDisplayName(loc
, locale
, result
);
785 URegistryKey U_EXPORT2
786 Collator::registerFactory(CollatorFactory
* toAdopt
, UErrorCode
& status
)
788 if (U_SUCCESS(status
)) {
789 CFactory
* f
= new CFactory(toAdopt
, status
);
791 return getService()->registerFactory(f
, status
);
793 status
= U_MEMORY_ALLOCATION_ERROR
;
798 // -------------------------------------
801 Collator::unregister(URegistryKey key
, UErrorCode
& status
)
803 if (U_SUCCESS(status
)) {
805 return gService
->unregister(key
, status
);
807 status
= U_ILLEGAL_ARGUMENT_ERROR
;
811 #endif /* UCONFIG_NO_SERVICE */
813 class CollationLocaleListEnumeration
: public StringEnumeration
{
817 static UClassID U_EXPORT2
getStaticClassID(void);
818 virtual UClassID
getDynamicClassID(void) const;
820 CollationLocaleListEnumeration()
823 // The global variables should already be initialized.
824 //isAvailableLocaleListInitialized(status);
827 virtual ~CollationLocaleListEnumeration();
829 virtual StringEnumeration
* clone() const
831 CollationLocaleListEnumeration
*result
= new CollationLocaleListEnumeration();
833 result
->index
= index
;
838 virtual int32_t count(UErrorCode
&/*status*/) const {
839 return availableLocaleListCount
;
842 virtual const char* next(int32_t* resultLength
, UErrorCode
& /*status*/) {
844 if(index
< availableLocaleListCount
) {
845 result
= availableLocaleList
[index
++].getName();
846 if(resultLength
!= NULL
) {
847 *resultLength
= (int32_t)uprv_strlen(result
);
850 if(resultLength
!= NULL
) {
858 virtual const UnicodeString
* snext(UErrorCode
& status
) {
859 int32_t resultLength
= 0;
860 const char *s
= next(&resultLength
, status
);
861 return setChars(s
, resultLength
, status
);
864 virtual void reset(UErrorCode
& /*status*/) {
869 CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {}
871 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration
)
874 // -------------------------------------
876 StringEnumeration
* U_EXPORT2
877 Collator::getAvailableLocales(void)
879 #if !UCONFIG_NO_SERVICE
881 return getService()->getAvailableLocales();
883 #endif /* UCONFIG_NO_SERVICE */
884 UErrorCode status
= U_ZERO_ERROR
;
885 if (isAvailableLocaleListInitialized(status
)) {
886 return new CollationLocaleListEnumeration();
891 StringEnumeration
* U_EXPORT2
892 Collator::getKeywords(UErrorCode
& status
) {
893 return UStringEnumeration::fromUEnumeration(
894 ucol_getKeywords(&status
), status
);
897 StringEnumeration
* U_EXPORT2
898 Collator::getKeywordValues(const char *keyword
, UErrorCode
& status
) {
899 return UStringEnumeration::fromUEnumeration(
900 ucol_getKeywordValues(keyword
, &status
), status
);
903 StringEnumeration
* U_EXPORT2
904 Collator::getKeywordValuesForLocale(const char* key
, const Locale
& locale
,
905 UBool commonlyUsed
, UErrorCode
& status
) {
906 return UStringEnumeration::fromUEnumeration(
907 ucol_getKeywordValuesForLocale(
908 key
, locale
.getName(), commonlyUsed
, &status
),
913 Collator::getFunctionalEquivalent(const char* keyword
, const Locale
& locale
,
914 UBool
& isAvailable
, UErrorCode
& status
) {
915 // This is a wrapper over ucol_getFunctionalEquivalent
916 char loc
[ULOC_FULLNAME_CAPACITY
];
917 /*int32_t len =*/ ucol_getFunctionalEquivalent(loc
, sizeof(loc
),
918 keyword
, locale
.getName(), &isAvailable
, &status
);
919 if (U_FAILURE(status
)) {
922 return Locale::createFromName(loc
);
925 Collator::ECollationStrength
926 Collator::getStrength(void) const {
927 UErrorCode intStatus
= U_ZERO_ERROR
;
928 return (ECollationStrength
)getAttribute(UCOL_STRENGTH
, intStatus
);
932 Collator::setStrength(ECollationStrength newStrength
) {
933 UErrorCode intStatus
= U_ZERO_ERROR
;
934 setAttribute(UCOL_STRENGTH
, (UColAttributeValue
)newStrength
, intStatus
);
938 Collator::setMaxVariable(UColReorderCode
/*group*/, UErrorCode
&errorCode
) {
939 if (U_SUCCESS(errorCode
)) {
940 errorCode
= U_UNSUPPORTED_ERROR
;
946 Collator::getMaxVariable() const {
947 return UCOL_REORDER_CODE_PUNCTUATION
;
951 Collator::getReorderCodes(int32_t* /* dest*/,
952 int32_t /* destCapacity*/,
953 UErrorCode
& status
) const
955 if (U_SUCCESS(status
)) {
956 status
= U_UNSUPPORTED_ERROR
;
962 Collator::setReorderCodes(const int32_t* /* reorderCodes */,
963 int32_t /* reorderCodesLength */,
966 if (U_SUCCESS(status
)) {
967 status
= U_UNSUPPORTED_ERROR
;
972 Collator::getEquivalentReorderCodes(int32_t reorderCode
,
973 int32_t *dest
, int32_t capacity
,
974 UErrorCode
&errorCode
) {
975 if(U_FAILURE(errorCode
)) { return 0; }
976 if(capacity
< 0 || (dest
== NULL
&& capacity
> 0)) {
977 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
980 const CollationData
*baseData
= CollationRoot::getData(errorCode
);
981 if(U_FAILURE(errorCode
)) { return 0; }
982 return baseData
->getEquivalentScripts(reorderCode
, dest
, capacity
, errorCode
);
986 Collator::internalGetShortDefinitionString(const char * /*locale*/,
988 int32_t /*capacity*/,
989 UErrorCode
&status
) const {
990 if(U_SUCCESS(status
)) {
991 status
= U_UNSUPPORTED_ERROR
; /* Shouldn't happen, internal function */
997 Collator::internalCompareUTF8(const char *left
, int32_t leftLength
,
998 const char *right
, int32_t rightLength
,
999 UErrorCode
&errorCode
) const {
1000 if(U_FAILURE(errorCode
)) { return UCOL_EQUAL
; }
1001 if((left
== NULL
&& leftLength
!= 0) || (right
== NULL
&& rightLength
!= 0)) {
1002 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
1006 StringPiece(left
, (leftLength
< 0) ? uprv_strlen(left
) : leftLength
),
1007 StringPiece(right
, (rightLength
< 0) ? uprv_strlen(right
) : rightLength
),
1012 Collator::internalNextSortKeyPart(UCharIterator
* /*iter*/, uint32_t /*state*/[2],
1013 uint8_t * /*dest*/, int32_t /*count*/, UErrorCode
&errorCode
) const {
1014 if (U_SUCCESS(errorCode
)) {
1015 errorCode
= U_UNSUPPORTED_ERROR
;
1020 // UCollator private data members ----------------------------------------
1022 /* This is useless information */
1023 /*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/
1025 // -------------------------------------
1029 #endif /* #if !UCONFIG_NO_COLLATION */