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
= U_INITONCE_INITIALIZER
;
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 StackUResourceBundle installed
;
235 index
= ures_openDirect(U_ICUDATA_COLL
, "res_index", &status
);
236 ures_getByKey(index
, "InstalledLocales", installed
.getAlias(), &status
);
238 if(U_SUCCESS(status
)) {
239 availableLocaleListCount
= ures_getSize(installed
.getAlias());
240 availableLocaleList
= new Locale
[availableLocaleListCount
];
242 if (availableLocaleList
!= NULL
) {
243 ures_resetIterator(installed
.getAlias());
244 while(ures_hasNext(installed
.getAlias())) {
245 const char *tempKey
= NULL
;
246 ures_getNextString(installed
.getAlias(), NULL
, &tempKey
, &status
);
247 availableLocaleList
[i
++] = Locale(tempKey
);
250 U_ASSERT(availableLocaleListCount
== i
);
253 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR
, collator_cleanup
);
256 static UBool
isAvailableLocaleListInitialized(UErrorCode
&status
) {
257 umtx_initOnce(gAvailableLocaleListInitOnce
, &initAvailableLocaleList
, status
);
258 return U_SUCCESS(status
);
262 // Collator public methods -----------------------------------------------
266 static const struct {
269 } collAttributes
[] = {
270 { "colStrength", UCOL_STRENGTH
},
271 { "colBackwards", UCOL_FRENCH_COLLATION
},
272 { "colCaseLevel", UCOL_CASE_LEVEL
},
273 { "colCaseFirst", UCOL_CASE_FIRST
},
274 { "colAlternate", UCOL_ALTERNATE_HANDLING
},
275 { "colNormalization", UCOL_NORMALIZATION_MODE
},
276 { "colNumeric", UCOL_NUMERIC_COLLATION
}
279 static const struct {
281 UColAttributeValue value
;
282 } collAttributeValues
[] = {
283 { "primary", UCOL_PRIMARY
},
284 { "secondary", UCOL_SECONDARY
},
285 { "tertiary", UCOL_TERTIARY
},
286 { "quaternary", UCOL_QUATERNARY
},
287 // Note: Not supporting typo "quarternary" because it was never supported in locale IDs.
288 { "identical", UCOL_IDENTICAL
},
291 { "shifted", UCOL_SHIFTED
},
292 { "non-ignorable", UCOL_NON_IGNORABLE
},
293 { "lower", UCOL_LOWER_FIRST
},
294 { "upper", UCOL_UPPER_FIRST
}
297 static const char *collReorderCodes
[UCOL_REORDER_CODE_LIMIT
- UCOL_REORDER_CODE_FIRST
] = {
298 "space", "punct", "symbol", "currency", "digit"
301 int32_t getReorderCode(const char *s
) {
302 for (int32_t i
= 0; i
< UPRV_LENGTHOF(collReorderCodes
); ++i
) {
303 if (uprv_stricmp(s
, collReorderCodes
[i
]) == 0) {
304 return UCOL_REORDER_CODE_FIRST
+ i
;
307 // Not supporting "others" = UCOL_REORDER_CODE_OTHERS
308 // as a synonym for Zzzz = USCRIPT_UNKNOWN for now:
309 // Avoid introducing synonyms/aliases.
314 * Sets collation attributes according to locale keywords. See
315 * http://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Settings
317 * Using "alias" keywords and values where defined:
318 * http://www.unicode.org/reports/tr35/tr35.html#Old_Locale_Extension_Syntax
319 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml
321 void setAttributesFromKeywords(const Locale
&loc
, Collator
&coll
, UErrorCode
&errorCode
) {
322 if (U_FAILURE(errorCode
)) {
325 if (uprv_strcmp(loc
.getName(), loc
.getBaseName()) == 0) {
329 char value
[1024]; // The reordering value could be long.
330 // Check for collation keywords that were already deprecated
331 // before any were supported in createInstance() (except for "collation").
332 int32_t length
= loc
.getKeywordValue("colHiraganaQuaternary", value
, UPRV_LENGTHOF(value
), errorCode
);
333 if (U_FAILURE(errorCode
)) {
334 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
338 errorCode
= U_UNSUPPORTED_ERROR
;
341 length
= loc
.getKeywordValue("variableTop", value
, UPRV_LENGTHOF(value
), errorCode
);
342 if (U_FAILURE(errorCode
)) {
343 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
347 errorCode
= U_UNSUPPORTED_ERROR
;
350 // Parse known collation keywords, ignore others.
351 if (errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
352 errorCode
= U_ZERO_ERROR
;
354 for (int32_t i
= 0; i
< UPRV_LENGTHOF(collAttributes
); ++i
) {
355 length
= loc
.getKeywordValue(collAttributes
[i
].name
, value
, UPRV_LENGTHOF(value
), errorCode
);
356 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
357 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
360 if (length
== 0) { continue; }
361 for (int32_t j
= 0;; ++j
) {
362 if (j
== UPRV_LENGTHOF(collAttributeValues
)) {
363 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
366 if (uprv_stricmp(value
, collAttributeValues
[j
].name
) == 0) {
367 coll
.setAttribute(collAttributes
[i
].attr
, collAttributeValues
[j
].value
, errorCode
);
372 length
= loc
.getKeywordValue("colReorder", value
, UPRV_LENGTHOF(value
), errorCode
);
373 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
374 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
378 int32_t codes
[USCRIPT_CODE_LIMIT
+ UCOL_REORDER_CODE_LIMIT
- UCOL_REORDER_CODE_FIRST
];
379 int32_t codesLength
= 0;
380 char *scriptName
= value
;
382 if (codesLength
== UPRV_LENGTHOF(codes
)) {
383 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
386 char *limit
= scriptName
;
388 while ((c
= *limit
) != 0 && c
!= '-') { ++limit
; }
391 if ((limit
- scriptName
) == 4) {
392 // Strict parsing, accept only 4-letter script codes, not long names.
393 code
= u_getPropertyValueEnum(UCHAR_SCRIPT
, scriptName
);
395 code
= getReorderCode(scriptName
);
398 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
401 codes
[codesLength
++] = code
;
402 if (c
== 0) { break; }
403 scriptName
= limit
+ 1;
405 coll
.setReorderCodes(codes
, codesLength
, errorCode
);
407 length
= loc
.getKeywordValue("kv", value
, UPRV_LENGTHOF(value
), errorCode
);
408 if (U_FAILURE(errorCode
) || errorCode
== U_STRING_NOT_TERMINATED_WARNING
) {
409 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
413 int32_t code
= getReorderCode(value
);
415 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
418 coll
.setMaxVariable((UColReorderCode
)code
, errorCode
);
420 if (U_FAILURE(errorCode
)) {
421 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
427 Collator
* U_EXPORT2
Collator::createInstance(UErrorCode
& success
)
429 return createInstance(Locale::getDefault(), success
);
432 Collator
* U_EXPORT2
Collator::createInstance(const Locale
& desiredLocale
,
435 if (U_FAILURE(status
))
437 if (desiredLocale
.isBogus()) {
438 // Locale constructed from malformed locale ID or language tag.
439 status
= U_ILLEGAL_ARGUMENT_ERROR
;
444 #if !UCONFIG_NO_SERVICE
447 coll
= (Collator
*)gService
->get(desiredLocale
, &actualLoc
, status
);
451 coll
= makeInstance(desiredLocale
, status
);
452 // Either returns NULL with U_FAILURE(status), or non-NULL with U_SUCCESS(status)
454 // The use of *coll in setAttributesFromKeywords can cause the NULL check to be
455 // optimized out of the delete even though setAttributesFromKeywords returns
456 // immediately if U_FAILURE(status), so we add a check here.
457 if (U_FAILURE(status
)) {
460 // makeInstance either returns NULL with U_FAILURE(status), or non-NULL with U_SUCCESS(status).
461 // The *coll in setAttributesFromKeywords causes the NULL check to be optimized out of the delete
462 // even though setAttributesFromKeywords returns immediately if U_FAILURE(status), so we add a
463 // check here and also log the locale name for failures. <rdar://problem/40930320>
464 if (U_FAILURE(status
)) {
465 #if U_PLATFORM_IS_DARWIN_BASED
467 // logging disabled for shipping system, can enable for internal debugging
468 const char* locname
= desiredLocale
.getName();
469 os_log(OS_LOG_DEFAULT
, "Collator::createInstance fails with locale: %{public}s", locname
? locname
: "(NULL)");
474 setAttributesFromKeywords(desiredLocale
, *coll
, status
);
475 if (U_FAILURE(status
)) {
483 Collator
* Collator::makeInstance(const Locale
& desiredLocale
, UErrorCode
& status
) {
484 const CollationCacheEntry
*entry
= CollationLoader::loadTailoring(desiredLocale
, status
);
485 if (U_SUCCESS(status
)) {
486 Collator
*result
= new RuleBasedCollator(entry
);
487 if (result
!= NULL
) {
488 // Both the unified cache's get() and the RBC constructor
489 // did addRef(). Undo one of them.
493 status
= U_MEMORY_ALLOCATION_ERROR
;
496 // Undo the addRef() from the cache.get().
503 Collator::safeClone() const {
507 // implement deprecated, previously abstract method
508 Collator::EComparisonResult
Collator::compare(const UnicodeString
& source
,
509 const UnicodeString
& target
) const
511 UErrorCode ec
= U_ZERO_ERROR
;
512 return (EComparisonResult
)compare(source
, target
, ec
);
515 // implement deprecated, previously abstract method
516 Collator::EComparisonResult
Collator::compare(const UnicodeString
& source
,
517 const UnicodeString
& target
,
518 int32_t length
) const
520 UErrorCode ec
= U_ZERO_ERROR
;
521 return (EComparisonResult
)compare(source
, target
, length
, ec
);
524 // implement deprecated, previously abstract method
525 Collator::EComparisonResult
Collator::compare(const UChar
* source
, int32_t sourceLength
,
526 const UChar
* target
, int32_t targetLength
)
529 UErrorCode ec
= U_ZERO_ERROR
;
530 return (EComparisonResult
)compare(source
, sourceLength
, target
, targetLength
, ec
);
533 UCollationResult
Collator::compare(UCharIterator
&/*sIter*/,
534 UCharIterator
&/*tIter*/,
535 UErrorCode
&status
) const {
536 if(U_SUCCESS(status
)) {
537 // Not implemented in the base class.
538 status
= U_UNSUPPORTED_ERROR
;
543 UCollationResult
Collator::compareUTF8(const StringPiece
&source
,
544 const StringPiece
&target
,
545 UErrorCode
&status
) const {
546 if(U_FAILURE(status
)) {
549 UCharIterator sIter
, tIter
;
550 uiter_setUTF8(&sIter
, source
.data(), source
.length());
551 uiter_setUTF8(&tIter
, target
.data(), target
.length());
552 return compare(sIter
, tIter
, status
);
555 UBool
Collator::equals(const UnicodeString
& source
,
556 const UnicodeString
& target
) const
558 UErrorCode ec
= U_ZERO_ERROR
;
559 return (compare(source
, target
, ec
) == UCOL_EQUAL
);
562 UBool
Collator::greaterOrEqual(const UnicodeString
& source
,
563 const UnicodeString
& target
) const
565 UErrorCode ec
= U_ZERO_ERROR
;
566 return (compare(source
, target
, ec
) != UCOL_LESS
);
569 UBool
Collator::greater(const UnicodeString
& source
,
570 const UnicodeString
& target
) const
572 UErrorCode ec
= U_ZERO_ERROR
;
573 return (compare(source
, target
, ec
) == UCOL_GREATER
);
576 // this API ignores registered collators, since it returns an
577 // array of indefinite lifetime
578 const Locale
* U_EXPORT2
Collator::getAvailableLocales(int32_t& count
)
580 UErrorCode status
= U_ZERO_ERROR
;
581 Locale
*result
= NULL
;
583 if (isAvailableLocaleListInitialized(status
))
585 result
= availableLocaleList
;
586 count
= availableLocaleListCount
;
591 UnicodeString
& U_EXPORT2
Collator::getDisplayName(const Locale
& objectLocale
,
592 const Locale
& displayLocale
,
595 #if !UCONFIG_NO_SERVICE
597 UnicodeString locNameStr
;
598 LocaleUtility::initNameFromLocale(objectLocale
, locNameStr
);
599 return gService
->getDisplayName(locNameStr
, name
, displayLocale
);
602 return objectLocale
.getDisplayName(displayLocale
, name
);
605 UnicodeString
& U_EXPORT2
Collator::getDisplayName(const Locale
& objectLocale
,
608 return getDisplayName(objectLocale
, Locale::getDefault(), name
);
611 /* This is useless information */
612 /*void Collator::getVersion(UVersionInfo versionInfo) const
614 if (versionInfo!=NULL)
615 uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH);
619 // UCollator protected constructor destructor ----------------------------
622 * Default constructor.
623 * Constructor is different from the old default Collator constructor.
624 * The task for determing the default collation strength and normalization mode
625 * is left to the child class.
634 * Empty constructor, does not handle the arguments.
635 * This constructor is done for backward compatibility with 1.7 and 1.8.
636 * The task for handling the argument collation strength and normalization
637 * mode is left to the child class.
638 * @param collationStrength collation strength
639 * @param decompositionMode
640 * @deprecated 2.4 use the default constructor instead
642 Collator::Collator(UCollationStrength
, UNormalizationMode
)
647 Collator::~Collator()
651 Collator::Collator(const Collator
&other
)
656 UBool
Collator::operator==(const Collator
& other
) const
658 // Subclasses: Call this method and then add more specific checks.
659 return typeid(*this) == typeid(other
);
662 UBool
Collator::operator!=(const Collator
& other
) const
664 return (UBool
)!(*this == other
);
667 int32_t U_EXPORT2
Collator::getBound(const uint8_t *source
,
668 int32_t sourceLength
,
669 UColBoundMode boundType
,
672 int32_t resultLength
,
675 return ucol_getBound(source
, sourceLength
, boundType
, noOfLevels
, result
, resultLength
, &status
);
679 Collator::setLocales(const Locale
& /* requestedLocale */, const Locale
& /* validLocale */, const Locale
& /*actualLocale*/) {
682 UnicodeSet
*Collator::getTailoredSet(UErrorCode
&status
) const
684 if(U_FAILURE(status
)) {
687 // everything can be changed
688 return new UnicodeSet(0, 0x10FFFF);
691 // -------------------------------------
693 #if !UCONFIG_NO_SERVICE
694 URegistryKey U_EXPORT2
695 Collator::registerInstance(Collator
* toAdopt
, const Locale
& locale
, UErrorCode
& status
)
697 if (U_SUCCESS(status
)) {
698 // Set the collator locales while registering so that createInstance()
699 // need not guess whether the collator's locales are already set properly
700 // (as they are by the data loader).
701 toAdopt
->setLocales(locale
, locale
, locale
);
702 return getService()->registerInstance(toAdopt
, locale
, status
);
707 // -------------------------------------
709 class CFactory
: public LocaleKeyFactory
{
711 CollatorFactory
* _delegate
;
715 CFactory(CollatorFactory
* delegate
, UErrorCode
& status
)
716 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
717 , _delegate(delegate
)
720 if (U_SUCCESS(status
)) {
722 _ids
= new Hashtable(status
);
724 const UnicodeString
* idlist
= _delegate
->getSupportedIDs(count
, status
);
725 for (int i
= 0; i
< count
; ++i
) {
726 _ids
->put(idlist
[i
], (void*)this, status
);
727 if (U_FAILURE(status
)) {
734 status
= U_MEMORY_ALLOCATION_ERROR
;
741 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const;
744 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
746 if (U_SUCCESS(status
)) {
752 virtual UnicodeString
&
753 getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const;
756 CFactory::~CFactory()
763 CFactory::create(const ICUServiceKey
& key
, const ICUService
* /* service */, UErrorCode
& status
) const
765 if (handlesKey(key
, status
)) {
766 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
768 lkey
.currentLocale(validLoc
);
769 return _delegate
->createCollator(validLoc
);
775 CFactory::getDisplayName(const UnicodeString
& id
, const Locale
& locale
, UnicodeString
& result
) const
777 if ((_coverage
& 0x1) == 0) {
778 UErrorCode status
= U_ZERO_ERROR
;
779 const Hashtable
* ids
= getSupportedIDs(status
);
780 if (ids
&& (ids
->get(id
) != NULL
)) {
782 LocaleUtility::initLocaleFromName(id
, loc
);
783 return _delegate
->getDisplayName(loc
, locale
, result
);
790 URegistryKey U_EXPORT2
791 Collator::registerFactory(CollatorFactory
* toAdopt
, UErrorCode
& status
)
793 if (U_SUCCESS(status
)) {
794 CFactory
* f
= new CFactory(toAdopt
, status
);
796 return getService()->registerFactory(f
, status
);
798 status
= U_MEMORY_ALLOCATION_ERROR
;
803 // -------------------------------------
806 Collator::unregister(URegistryKey key
, UErrorCode
& status
)
808 if (U_SUCCESS(status
)) {
810 return gService
->unregister(key
, status
);
812 status
= U_ILLEGAL_ARGUMENT_ERROR
;
816 #endif /* UCONFIG_NO_SERVICE */
818 class CollationLocaleListEnumeration
: public StringEnumeration
{
822 static UClassID U_EXPORT2
getStaticClassID(void);
823 virtual UClassID
getDynamicClassID(void) const;
825 CollationLocaleListEnumeration()
828 // The global variables should already be initialized.
829 //isAvailableLocaleListInitialized(status);
832 virtual ~CollationLocaleListEnumeration();
834 virtual StringEnumeration
* clone() const
836 CollationLocaleListEnumeration
*result
= new CollationLocaleListEnumeration();
838 result
->index
= index
;
843 virtual int32_t count(UErrorCode
&/*status*/) const {
844 return availableLocaleListCount
;
847 virtual const char* next(int32_t* resultLength
, UErrorCode
& /*status*/) {
849 if(index
< availableLocaleListCount
) {
850 result
= availableLocaleList
[index
++].getName();
851 if(resultLength
!= NULL
) {
852 *resultLength
= (int32_t)uprv_strlen(result
);
855 if(resultLength
!= NULL
) {
863 virtual const UnicodeString
* snext(UErrorCode
& status
) {
864 int32_t resultLength
= 0;
865 const char *s
= next(&resultLength
, status
);
866 return setChars(s
, resultLength
, status
);
869 virtual void reset(UErrorCode
& /*status*/) {
874 CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {}
876 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration
)
879 // -------------------------------------
881 StringEnumeration
* U_EXPORT2
882 Collator::getAvailableLocales(void)
884 #if !UCONFIG_NO_SERVICE
886 return getService()->getAvailableLocales();
888 #endif /* UCONFIG_NO_SERVICE */
889 UErrorCode status
= U_ZERO_ERROR
;
890 if (isAvailableLocaleListInitialized(status
)) {
891 return new CollationLocaleListEnumeration();
896 StringEnumeration
* U_EXPORT2
897 Collator::getKeywords(UErrorCode
& status
) {
898 return UStringEnumeration::fromUEnumeration(
899 ucol_getKeywords(&status
), status
);
902 StringEnumeration
* U_EXPORT2
903 Collator::getKeywordValues(const char *keyword
, UErrorCode
& status
) {
904 return UStringEnumeration::fromUEnumeration(
905 ucol_getKeywordValues(keyword
, &status
), status
);
908 StringEnumeration
* U_EXPORT2
909 Collator::getKeywordValuesForLocale(const char* key
, const Locale
& locale
,
910 UBool commonlyUsed
, UErrorCode
& status
) {
911 return UStringEnumeration::fromUEnumeration(
912 ucol_getKeywordValuesForLocale(
913 key
, locale
.getName(), commonlyUsed
, &status
),
918 Collator::getFunctionalEquivalent(const char* keyword
, const Locale
& locale
,
919 UBool
& isAvailable
, UErrorCode
& status
) {
920 // This is a wrapper over ucol_getFunctionalEquivalent
921 char loc
[ULOC_FULLNAME_CAPACITY
];
922 /*int32_t len =*/ ucol_getFunctionalEquivalent(loc
, sizeof(loc
),
923 keyword
, locale
.getName(), &isAvailable
, &status
);
924 if (U_FAILURE(status
)) {
927 return Locale::createFromName(loc
);
930 Collator::ECollationStrength
931 Collator::getStrength(void) const {
932 UErrorCode intStatus
= U_ZERO_ERROR
;
933 return (ECollationStrength
)getAttribute(UCOL_STRENGTH
, intStatus
);
937 Collator::setStrength(ECollationStrength newStrength
) {
938 UErrorCode intStatus
= U_ZERO_ERROR
;
939 setAttribute(UCOL_STRENGTH
, (UColAttributeValue
)newStrength
, intStatus
);
943 Collator::setMaxVariable(UColReorderCode
/*group*/, UErrorCode
&errorCode
) {
944 if (U_SUCCESS(errorCode
)) {
945 errorCode
= U_UNSUPPORTED_ERROR
;
951 Collator::getMaxVariable() const {
952 return UCOL_REORDER_CODE_PUNCTUATION
;
956 Collator::getReorderCodes(int32_t* /* dest*/,
957 int32_t /* destCapacity*/,
958 UErrorCode
& status
) const
960 if (U_SUCCESS(status
)) {
961 status
= U_UNSUPPORTED_ERROR
;
967 Collator::setReorderCodes(const int32_t* /* reorderCodes */,
968 int32_t /* reorderCodesLength */,
971 if (U_SUCCESS(status
)) {
972 status
= U_UNSUPPORTED_ERROR
;
977 Collator::getEquivalentReorderCodes(int32_t reorderCode
,
978 int32_t *dest
, int32_t capacity
,
979 UErrorCode
&errorCode
) {
980 if(U_FAILURE(errorCode
)) { return 0; }
981 if(capacity
< 0 || (dest
== NULL
&& capacity
> 0)) {
982 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
985 const CollationData
*baseData
= CollationRoot::getData(errorCode
);
986 if(U_FAILURE(errorCode
)) { return 0; }
987 return baseData
->getEquivalentScripts(reorderCode
, dest
, capacity
, errorCode
);
991 Collator::internalGetShortDefinitionString(const char * /*locale*/,
993 int32_t /*capacity*/,
994 UErrorCode
&status
) const {
995 if(U_SUCCESS(status
)) {
996 status
= U_UNSUPPORTED_ERROR
; /* Shouldn't happen, internal function */
1002 Collator::internalCompareUTF8(const char *left
, int32_t leftLength
,
1003 const char *right
, int32_t rightLength
,
1004 UErrorCode
&errorCode
) const {
1005 if(U_FAILURE(errorCode
)) { return UCOL_EQUAL
; }
1006 if((left
== NULL
&& leftLength
!= 0) || (right
== NULL
&& rightLength
!= 0)) {
1007 errorCode
= U_ILLEGAL_ARGUMENT_ERROR
;
1011 StringPiece(left
, (leftLength
< 0) ? static_cast<int32_t>(uprv_strlen(left
)) : leftLength
),
1012 StringPiece(right
, (rightLength
< 0) ? static_cast<int32_t>(uprv_strlen(right
)) : rightLength
),
1017 Collator::internalNextSortKeyPart(UCharIterator
* /*iter*/, uint32_t /*state*/[2],
1018 uint8_t * /*dest*/, int32_t /*count*/, UErrorCode
&errorCode
) const {
1019 if (U_SUCCESS(errorCode
)) {
1020 errorCode
= U_UNSUPPORTED_ERROR
;
1025 // UCollator private data members ----------------------------------------
1027 /* This is useless information */
1028 /*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/
1030 // -------------------------------------
1034 #endif /* #if !UCONFIG_NO_COLLATION */