blob: d4224ba39e5a5ed94ae5135e9b2805fbb51918e3 [file] [log] [blame]
jshin@chromium.org6f31ac32014-03-26 22:15:14 +00001/*
2 ******************************************************************************
3 * Copyright (C) 1996-2013, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ******************************************************************************
6 */
7
8/**
9 * File coll.cpp
10 *
11 * Created by: Helena Shih
12 *
13 * Modification History:
14 *
15 * Date Name Description
16 * 2/5/97 aliu Modified createDefault to load collation data from
17 * binary files when possible. Added related methods
18 * createCollationFromFile, chopLocale, createPathName.
19 * 2/11/97 aliu Added methods addToCache, findInCache, which implement
20 * a Collation cache. Modified createDefault to look in
21 * cache first, and also to store newly created Collation
22 * objects in the cache. Modified to not use gLocPath.
23 * 2/12/97 aliu Modified to create objects from RuleBasedCollator cache.
24 * Moved cache out of Collation class.
25 * 2/13/97 aliu Moved several methods out of this class and into
26 * RuleBasedCollator, with modifications. Modified
27 * createDefault() to call new RuleBasedCollator(Locale&)
28 * constructor. General clean up and documentation.
29 * 2/20/97 helena Added clone, operator==, operator!=, operator=, and copy
30 * constructor.
31 * 05/06/97 helena Added memory allocation error detection.
32 * 05/08/97 helena Added createInstance().
33 * 6/20/97 helena Java class name change.
34 * 04/23/99 stephen Removed EDecompositionMode, merged with
35 * Normalizer::EMode
36 * 11/23/9 srl Inlining of some critical functions
37 * 01/29/01 synwee Modified into a C++ wrapper calling C APIs (ucol.h)
38 */
39
40#include "utypeinfo.h" // for 'typeid' to work
41
42#include "unicode/utypes.h"
43
44#if !UCONFIG_NO_COLLATION
45
46#include "unicode/coll.h"
47#include "unicode/tblcoll.h"
48#include "ucol_imp.h"
49#include "cstring.h"
50#include "cmemory.h"
51#include "umutex.h"
52#include "servloc.h"
53#include "uassert.h"
54#include "ustrenum.h"
55#include "uresimp.h"
56#include "ucln_in.h"
57
58static icu::Locale* availableLocaleList = NULL;
59static int32_t availableLocaleListCount;
60static icu::ICULocaleService* gService = NULL;
61static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
62static icu::UInitOnce gAvailableLocaleListInitOnce;
63
64/**
65 * Release all static memory held by collator.
66 */
67U_CDECL_BEGIN
68static UBool U_CALLCONV collator_cleanup(void) {
69#if !UCONFIG_NO_SERVICE
70 if (gService) {
71 delete gService;
72 gService = NULL;
73 }
74 gServiceInitOnce.reset();
75#endif
76 if (availableLocaleList) {
77 delete []availableLocaleList;
78 availableLocaleList = NULL;
79 }
80 availableLocaleListCount = 0;
81 gAvailableLocaleListInitOnce.reset();
82 return TRUE;
83}
84
85U_CDECL_END
86
87U_NAMESPACE_BEGIN
88
89#if !UCONFIG_NO_SERVICE
90
91// ------------------------------------------
92//
93// Registration
94//
95
96//-------------------------------------------
97
98CollatorFactory::~CollatorFactory() {}
99
100//-------------------------------------------
101
102UBool
103CollatorFactory::visible(void) const {
104 return TRUE;
105}
106
107//-------------------------------------------
108
109UnicodeString&
110CollatorFactory::getDisplayName(const Locale& objectLocale,
111 const Locale& displayLocale,
112 UnicodeString& result)
113{
114 return objectLocale.getDisplayName(displayLocale, result);
115}
116
117// -------------------------------------
118
119class ICUCollatorFactory : public ICUResourceBundleFactory {
120 public:
121 ICUCollatorFactory() : ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL, -1, US_INV)) { }
122 virtual ~ICUCollatorFactory();
123 protected:
124 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
125};
126
127ICUCollatorFactory::~ICUCollatorFactory() {}
128
129UObject*
130ICUCollatorFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const {
131 if (handlesKey(key, status)) {
132 const LocaleKey& lkey = (const LocaleKey&)key;
133 Locale loc;
134 // make sure the requested locale is correct
135 // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey
136 // but for ICU rb resources we use the actual one since it will fallback again
137 lkey.canonicalLocale(loc);
138
139 return Collator::makeInstance(loc, status);
140 }
141 return NULL;
142}
143
144// -------------------------------------
145
146class ICUCollatorService : public ICULocaleService {
147public:
148 ICUCollatorService()
149 : ICULocaleService(UNICODE_STRING_SIMPLE("Collator"))
150 {
151 UErrorCode status = U_ZERO_ERROR;
152 registerFactory(new ICUCollatorFactory(), status);
153 }
154
155 virtual ~ICUCollatorService();
156
157 virtual UObject* cloneInstance(UObject* instance) const {
158 return ((Collator*)instance)->clone();
159 }
160
161 virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const {
162 LocaleKey& lkey = (LocaleKey&)key;
163 if (actualID) {
164 // Ugly Hack Alert! We return an empty actualID to signal
165 // to callers that this is a default object, not a "real"
166 // service-created object. (TODO remove in 3.0) [aliu]
167 actualID->truncate(0);
168 }
169 Locale loc("");
170 lkey.canonicalLocale(loc);
171 return Collator::makeInstance(loc, status);
172 }
173
174 virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const {
175 UnicodeString ar;
176 if (actualReturn == NULL) {
177 actualReturn = &ar;
178 }
179 Collator* result = (Collator*)ICULocaleService::getKey(key, actualReturn, status);
180 // Ugly Hack Alert! If the actualReturn length is zero, this
181 // means we got a default object, not a "real" service-created
182 // object. We don't call setLocales() on a default object,
183 // because that will overwrite its correct built-in locale
184 // metadata (valid & actual) with our incorrect data (all we
185 // have is the requested locale). (TODO remove in 3.0) [aliu]
186 if (result && actualReturn->length() > 0) {
187 const LocaleKey& lkey = (const LocaleKey&)key;
188 Locale canonicalLocale("");
189 Locale currentLocale("");
190
191 LocaleUtility::initLocaleFromName(*actualReturn, currentLocale);
192 result->setLocales(lkey.canonicalLocale(canonicalLocale), currentLocale, currentLocale);
193 }
194 return result;
195 }
196
197 virtual UBool isDefault() const {
198 return countFactories() == 1;
199 }
200};
201
202ICUCollatorService::~ICUCollatorService() {}
203
204// -------------------------------------
205
206static void U_CALLCONV initService() {
207 gService = new ICUCollatorService();
208 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
209}
210
211
212static ICULocaleService*
213getService(void)
214{
215 umtx_initOnce(gServiceInitOnce, &initService);
216 return gService;
217}
218
219// -------------------------------------
220
221static inline UBool
222hasService(void)
223{
224 UBool retVal = !gServiceInitOnce.isReset() && (getService() != NULL);
225 return retVal;
226}
227
228// -------------------------------------
229
230UCollator*
231Collator::createUCollator(const char *loc,
232 UErrorCode *status)
233{
234 UCollator *result = 0;
235 if (status && U_SUCCESS(*status) && hasService()) {
236 Locale desiredLocale(loc);
237 Collator *col = (Collator*)gService->get(desiredLocale, *status);
238 RuleBasedCollator *rbc;
239 if (col && (rbc = dynamic_cast<RuleBasedCollator *>(col))) {
240 if (!rbc->dataIsOwned) {
241 result = ucol_safeClone(rbc->ucollator, NULL, NULL, status);
242 } else {
243 result = rbc->ucollator;
244 rbc->ucollator = NULL; // to prevent free on delete
245 }
246 } else {
247 // should go in a function- ucol_initDelegate(delegate)
248 result = (UCollator *)uprv_malloc(sizeof(UCollator));
249 if(result == NULL) {
250 *status = U_MEMORY_ALLOCATION_ERROR;
251 } else {
252 uprv_memset(result, 0, sizeof(UCollator));
253 result->delegate = col;
254 result->freeOnClose = TRUE; // do free on close.
255 col = NULL; // to prevent free on delete.
256 }
257 }
258 delete col;
259 }
260 return result;
261}
262#endif /* UCONFIG_NO_SERVICE */
263
264static void U_CALLCONV
265initAvailableLocaleList(UErrorCode &status) {
266 U_ASSERT(availableLocaleListCount == 0);
267 U_ASSERT(availableLocaleList == NULL);
268 // for now, there is a hardcoded list, so just walk through that list and set it up.
269 UResourceBundle *index = NULL;
270 UResourceBundle installed;
271 int32_t i = 0;
272
273 ures_initStackObject(&installed);
274 index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
275 ures_getByKey(index, "InstalledLocales", &installed, &status);
276
277 if(U_SUCCESS(status)) {
278 availableLocaleListCount = ures_getSize(&installed);
279 availableLocaleList = new Locale[availableLocaleListCount];
280
281 if (availableLocaleList != NULL) {
282 ures_resetIterator(&installed);
283 while(ures_hasNext(&installed)) {
284 const char *tempKey = NULL;
285 ures_getNextString(&installed, NULL, &tempKey, &status);
286 availableLocaleList[i++] = Locale(tempKey);
287 }
288 }
289 U_ASSERT(availableLocaleListCount == i);
290 ures_close(&installed);
291 }
292 ures_close(index);
293 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
294}
295
296static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
297 umtx_initOnce(gAvailableLocaleListInitOnce, &initAvailableLocaleList, status);
298 return U_SUCCESS(status);
299}
300
301
302// Collator public methods -----------------------------------------------
303
304Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success)
305{
306 return createInstance(Locale::getDefault(), success);
307}
308
309Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale,
310 UErrorCode& status)
311{
312 if (U_FAILURE(status))
313 return 0;
314
315#if !UCONFIG_NO_SERVICE
316 if (hasService()) {
317 Locale actualLoc;
318 Collator *result =
319 (Collator*)gService->get(desiredLocale, &actualLoc, status);
320
321 // Ugly Hack Alert! If the returned locale is empty (not root,
322 // but empty -- getName() == "") then that means the service
323 // returned a default object, not a "real" service object. In
324 // that case, the locale metadata (valid & actual) is setup
325 // correctly already, and we don't want to overwrite it. (TODO
326 // remove in 3.0) [aliu]
327 if (*actualLoc.getName() != 0) {
328 result->setLocales(desiredLocale, actualLoc, actualLoc);
329 }
330 return result;
331 }
332#endif
333 return makeInstance(desiredLocale, status);
334}
335
336
337Collator* Collator::makeInstance(const Locale& desiredLocale,
338 UErrorCode& status)
339{
340 // A bit of explanation is required here. Although in the current
341 // implementation
342 // Collator::createInstance() is just turning around and calling
343 // RuleBasedCollator(Locale&), this will not necessarily always be the
344 // case. For example, suppose we modify this code to handle a
345 // non-table-based Collator, such as that for Thai. In this case,
346 // createInstance() will have to be modified to somehow determine this fact
347 // (perhaps a field in the resource bundle). Then it can construct the
348 // non-table-based Collator in some other way, when it sees that it needs
349 // to.
350 // The specific caution is this: RuleBasedCollator(Locale&) will ALWAYS
351 // return a valid collation object, if the system is functioning properly.
352 // The reason is that it will fall back, use the default locale, and even
353 // use the built-in default collation rules. THEREFORE, createInstance()
354 // should in general ONLY CALL RuleBasedCollator(Locale&) IF IT KNOWS IN
355 // ADVANCE that the given locale's collation is properly implemented as a
356 // RuleBasedCollator.
357 // Currently, we don't do this...we always return a RuleBasedCollator,
358 // whether it is strictly correct to do so or not, without checking, because
359 // we currently have no way of checking.
360
361 RuleBasedCollator* collation = new RuleBasedCollator(desiredLocale,
362 status);
363 /* test for NULL */
364 if (collation == 0) {
365 status = U_MEMORY_ALLOCATION_ERROR;
366 return 0;
367 }
368 if (U_FAILURE(status))
369 {
370 delete collation;
371 collation = 0;
372 }
373 return collation;
374}
375
376#ifdef U_USE_COLLATION_OBSOLETE_2_6
377// !!! dlf the following is obsolete, ignore registration for this
378
379Collator *
380Collator::createInstance(const Locale &loc,
381 UVersionInfo version,
382 UErrorCode &status)
383{
384 Collator *collator;
385 UVersionInfo info;
386
387 collator=new RuleBasedCollator(loc, status);
388 /* test for NULL */
389 if (collator == 0) {
390 status = U_MEMORY_ALLOCATION_ERROR;
391 return 0;
392 }
393
394 if(U_SUCCESS(status)) {
395 collator->getVersion(info);
396 if(0!=uprv_memcmp(version, info, sizeof(UVersionInfo))) {
397 delete collator;
398 status=U_MISSING_RESOURCE_ERROR;
399 return 0;
400 }
401 }
402 return collator;
403}
404#endif
405
406Collator *
407Collator::safeClone() const {
408 return clone();
409}
410
411// implement deprecated, previously abstract method
412Collator::EComparisonResult Collator::compare(const UnicodeString& source,
413 const UnicodeString& target) const
414{
415 UErrorCode ec = U_ZERO_ERROR;
416 return (EComparisonResult)compare(source, target, ec);
417}
418
419// implement deprecated, previously abstract method
420Collator::EComparisonResult Collator::compare(const UnicodeString& source,
421 const UnicodeString& target,
422 int32_t length) const
423{
424 UErrorCode ec = U_ZERO_ERROR;
425 return (EComparisonResult)compare(source, target, length, ec);
426}
427
428// implement deprecated, previously abstract method
429Collator::EComparisonResult Collator::compare(const UChar* source, int32_t sourceLength,
430 const UChar* target, int32_t targetLength)
431 const
432{
433 UErrorCode ec = U_ZERO_ERROR;
434 return (EComparisonResult)compare(source, sourceLength, target, targetLength, ec);
435}
436
437UCollationResult Collator::compare(UCharIterator &/*sIter*/,
438 UCharIterator &/*tIter*/,
439 UErrorCode &status) const {
440 if(U_SUCCESS(status)) {
441 // Not implemented in the base class.
442 status = U_UNSUPPORTED_ERROR;
443 }
444 return UCOL_EQUAL;
445}
446
447UCollationResult Collator::compareUTF8(const StringPiece &source,
448 const StringPiece &target,
449 UErrorCode &status) const {
450 if(U_FAILURE(status)) {
451 return UCOL_EQUAL;
452 }
453 UCharIterator sIter, tIter;
454 uiter_setUTF8(&sIter, source.data(), source.length());
455 uiter_setUTF8(&tIter, target.data(), target.length());
456 return compare(sIter, tIter, status);
457}
458
459UBool Collator::equals(const UnicodeString& source,
460 const UnicodeString& target) const
461{
462 UErrorCode ec = U_ZERO_ERROR;
463 return (compare(source, target, ec) == UCOL_EQUAL);
464}
465
466UBool Collator::greaterOrEqual(const UnicodeString& source,
467 const UnicodeString& target) const
468{
469 UErrorCode ec = U_ZERO_ERROR;
470 return (compare(source, target, ec) != UCOL_LESS);
471}
472
473UBool Collator::greater(const UnicodeString& source,
474 const UnicodeString& target) const
475{
476 UErrorCode ec = U_ZERO_ERROR;
477 return (compare(source, target, ec) == UCOL_GREATER);
478}
479
480// this API ignores registered collators, since it returns an
481// array of indefinite lifetime
482const Locale* U_EXPORT2 Collator::getAvailableLocales(int32_t& count)
483{
484 UErrorCode status = U_ZERO_ERROR;
485 Locale *result = NULL;
486 count = 0;
487 if (isAvailableLocaleListInitialized(status))
488 {
489 result = availableLocaleList;
490 count = availableLocaleListCount;
491 }
492 return result;
493}
494
495UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale,
496 const Locale& displayLocale,
497 UnicodeString& name)
498{
499#if !UCONFIG_NO_SERVICE
500 if (hasService()) {
501 UnicodeString locNameStr;
502 LocaleUtility::initNameFromLocale(objectLocale, locNameStr);
503 return gService->getDisplayName(locNameStr, name, displayLocale);
504 }
505#endif
506 return objectLocale.getDisplayName(displayLocale, name);
507}
508
509UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale,
510 UnicodeString& name)
511{
512 return getDisplayName(objectLocale, Locale::getDefault(), name);
513}
514
515/* This is useless information */
516/*void Collator::getVersion(UVersionInfo versionInfo) const
517{
518 if (versionInfo!=NULL)
519 uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH);
520}
521*/
522
523// UCollator protected constructor destructor ----------------------------
524
525/**
526* Default constructor.
527* Constructor is different from the old default Collator constructor.
528* The task for determing the default collation strength and normalization mode
529* is left to the child class.
530*/
531Collator::Collator()
532: UObject()
533{
534}
535
536/**
537* Constructor.
538* Empty constructor, does not handle the arguments.
539* This constructor is done for backward compatibility with 1.7 and 1.8.
540* The task for handling the argument collation strength and normalization
541* mode is left to the child class.
542* @param collationStrength collation strength
543* @param decompositionMode
544* @deprecated 2.4 use the default constructor instead
545*/
546Collator::Collator(UCollationStrength, UNormalizationMode )
547: UObject()
548{
549}
550
551Collator::~Collator()
552{
553}
554
555Collator::Collator(const Collator &other)
556 : UObject(other)
557{
558}
559
560UBool Collator::operator==(const Collator& other) const
561{
562 // Subclasses: Call this method and then add more specific checks.
563 return typeid(*this) == typeid(other);
564}
565
566UBool Collator::operator!=(const Collator& other) const
567{
568 return (UBool)!(*this == other);
569}
570
571int32_t U_EXPORT2 Collator::getBound(const uint8_t *source,
572 int32_t sourceLength,
573 UColBoundMode boundType,
574 uint32_t noOfLevels,
575 uint8_t *result,
576 int32_t resultLength,
577 UErrorCode &status)
578{
579 return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status);
580}
581
582void
583Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) {
584}
585
586UnicodeSet *Collator::getTailoredSet(UErrorCode &status) const
587{
588 if(U_FAILURE(status)) {
589 return NULL;
590 }
591 // everything can be changed
592 return new UnicodeSet(0, 0x10FFFF);
593}
594
595// -------------------------------------
596
597#if !UCONFIG_NO_SERVICE
598URegistryKey U_EXPORT2
599Collator::registerInstance(Collator* toAdopt, const Locale& locale, UErrorCode& status)
600{
601 if (U_SUCCESS(status)) {
602 return getService()->registerInstance(toAdopt, locale, status);
603 }
604 return NULL;
605}
606
607// -------------------------------------
608
609class CFactory : public LocaleKeyFactory {
610private:
611 CollatorFactory* _delegate;
612 Hashtable* _ids;
613
614public:
615 CFactory(CollatorFactory* delegate, UErrorCode& status)
616 : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
617 , _delegate(delegate)
618 , _ids(NULL)
619 {
620 if (U_SUCCESS(status)) {
621 int32_t count = 0;
622 _ids = new Hashtable(status);
623 if (_ids) {
624 const UnicodeString * idlist = _delegate->getSupportedIDs(count, status);
625 for (int i = 0; i < count; ++i) {
626 _ids->put(idlist[i], (void*)this, status);
627 if (U_FAILURE(status)) {
628 delete _ids;
629 _ids = NULL;
630 return;
631 }
632 }
633 } else {
634 status = U_MEMORY_ALLOCATION_ERROR;
635 }
636 }
637 }
638
639 virtual ~CFactory();
640
641 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
642
643protected:
644 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
645 {
646 if (U_SUCCESS(status)) {
647 return _ids;
648 }
649 return NULL;
650 }
651
652 virtual UnicodeString&
653 getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const;
654};
655
656CFactory::~CFactory()
657{
658 delete _delegate;
659 delete _ids;
660}
661
662UObject*
663CFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const
664{
665 if (handlesKey(key, status)) {
666 const LocaleKey& lkey = (const LocaleKey&)key;
667 Locale validLoc;
668 lkey.currentLocale(validLoc);
669 return _delegate->createCollator(validLoc);
670 }
671 return NULL;
672}
673
674UnicodeString&
675CFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const
676{
677 if ((_coverage & 0x1) == 0) {
678 UErrorCode status = U_ZERO_ERROR;
679 const Hashtable* ids = getSupportedIDs(status);
680 if (ids && (ids->get(id) != NULL)) {
681 Locale loc;
682 LocaleUtility::initLocaleFromName(id, loc);
683 return _delegate->getDisplayName(loc, locale, result);
684 }
685 }
686 result.setToBogus();
687 return result;
688}
689
690URegistryKey U_EXPORT2
691Collator::registerFactory(CollatorFactory* toAdopt, UErrorCode& status)
692{
693 if (U_SUCCESS(status)) {
694 CFactory* f = new CFactory(toAdopt, status);
695 if (f) {
696 return getService()->registerFactory(f, status);
697 }
698 status = U_MEMORY_ALLOCATION_ERROR;
699 }
700 return NULL;
701}
702
703// -------------------------------------
704
705UBool U_EXPORT2
706Collator::unregister(URegistryKey key, UErrorCode& status)
707{
708 if (U_SUCCESS(status)) {
709 if (hasService()) {
710 return gService->unregister(key, status);
711 }
712 status = U_ILLEGAL_ARGUMENT_ERROR;
713 }
714 return FALSE;
715}
716#endif /* UCONFIG_NO_SERVICE */
717
718class CollationLocaleListEnumeration : public StringEnumeration {
719private:
720 int32_t index;
721public:
722 static UClassID U_EXPORT2 getStaticClassID(void);
723 virtual UClassID getDynamicClassID(void) const;
724public:
725 CollationLocaleListEnumeration()
726 : index(0)
727 {
728 // The global variables should already be initialized.
729 //isAvailableLocaleListInitialized(status);
730 }
731
732 virtual ~CollationLocaleListEnumeration();
733
734 virtual StringEnumeration * clone() const
735 {
736 CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration();
737 if (result) {
738 result->index = index;
739 }
740 return result;
741 }
742
743 virtual int32_t count(UErrorCode &/*status*/) const {
744 return availableLocaleListCount;
745 }
746
747 virtual const char* next(int32_t* resultLength, UErrorCode& /*status*/) {
748 const char* result;
749 if(index < availableLocaleListCount) {
750 result = availableLocaleList[index++].getName();
751 if(resultLength != NULL) {
752 *resultLength = (int32_t)uprv_strlen(result);
753 }
754 } else {
755 if(resultLength != NULL) {
756 *resultLength = 0;
757 }
758 result = NULL;
759 }
760 return result;
761 }
762
763 virtual const UnicodeString* snext(UErrorCode& status) {
764 int32_t resultLength = 0;
765 const char *s = next(&resultLength, status);
766 return setChars(s, resultLength, status);
767 }
768
769 virtual void reset(UErrorCode& /*status*/) {
770 index = 0;
771 }
772};
773
774CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {}
775
776UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration)
777
778
779// -------------------------------------
780
781StringEnumeration* U_EXPORT2
782Collator::getAvailableLocales(void)
783{
784#if !UCONFIG_NO_SERVICE
785 if (hasService()) {
786 return getService()->getAvailableLocales();
787 }
788#endif /* UCONFIG_NO_SERVICE */
789 UErrorCode status = U_ZERO_ERROR;
790 if (isAvailableLocaleListInitialized(status)) {
791 return new CollationLocaleListEnumeration();
792 }
793 return NULL;
794}
795
796StringEnumeration* U_EXPORT2
797Collator::getKeywords(UErrorCode& status) {
798 // This is a wrapper over ucol_getKeywords
799 UEnumeration* uenum = ucol_getKeywords(&status);
800 if (U_FAILURE(status)) {
801 uenum_close(uenum);
802 return NULL;
803 }
804 return new UStringEnumeration(uenum);
805}
806
807StringEnumeration* U_EXPORT2
808Collator::getKeywordValues(const char *keyword, UErrorCode& status) {
809 // This is a wrapper over ucol_getKeywordValues
810 UEnumeration* uenum = ucol_getKeywordValues(keyword, &status);
811 if (U_FAILURE(status)) {
812 uenum_close(uenum);
813 return NULL;
814 }
815 return new UStringEnumeration(uenum);
816}
817
818StringEnumeration* U_EXPORT2
819Collator::getKeywordValuesForLocale(const char* key, const Locale& locale,
820 UBool commonlyUsed, UErrorCode& status) {
821 // This is a wrapper over ucol_getKeywordValuesForLocale
822 UEnumeration *uenum = ucol_getKeywordValuesForLocale(key, locale.getName(),
823 commonlyUsed, &status);
824 if (U_FAILURE(status)) {
825 uenum_close(uenum);
826 return NULL;
827 }
828 return new UStringEnumeration(uenum);
829}
830
831Locale U_EXPORT2
832Collator::getFunctionalEquivalent(const char* keyword, const Locale& locale,
833 UBool& isAvailable, UErrorCode& status) {
834 // This is a wrapper over ucol_getFunctionalEquivalent
835 char loc[ULOC_FULLNAME_CAPACITY];
836 /*int32_t len =*/ ucol_getFunctionalEquivalent(loc, sizeof(loc),
837 keyword, locale.getName(), &isAvailable, &status);
838 if (U_FAILURE(status)) {
839 *loc = 0; // root
840 }
841 return Locale::createFromName(loc);
842}
843
844Collator::ECollationStrength
845Collator::getStrength(void) const {
846 UErrorCode intStatus = U_ZERO_ERROR;
847 return (ECollationStrength)getAttribute(UCOL_STRENGTH, intStatus);
848}
849
850void
851Collator::setStrength(ECollationStrength newStrength) {
852 UErrorCode intStatus = U_ZERO_ERROR;
853 setAttribute(UCOL_STRENGTH, (UColAttributeValue)newStrength, intStatus);
854}
855
856int32_t
857Collator::getReorderCodes(int32_t* /* dest*/,
858 int32_t /* destCapacity*/,
859 UErrorCode& status) const
860{
861 if (U_SUCCESS(status)) {
862 status = U_UNSUPPORTED_ERROR;
863 }
864 return 0;
865}
866
867void
868Collator::setReorderCodes(const int32_t* /* reorderCodes */,
869 int32_t /* reorderCodesLength */,
870 UErrorCode& status)
871{
872 if (U_SUCCESS(status)) {
873 status = U_UNSUPPORTED_ERROR;
874 }
875}
876
877int32_t U_EXPORT2
878Collator::getEquivalentReorderCodes(int32_t /* reorderCode */,
879 int32_t* /* dest */,
880 int32_t /* destCapacity */,
881 UErrorCode& status)
882{
883 if (U_SUCCESS(status)) {
884 status = U_UNSUPPORTED_ERROR;
885 }
886 return 0;
887}
888
889int32_t
890Collator::internalGetShortDefinitionString(const char * /*locale*/,
891 char * /*buffer*/,
892 int32_t /*capacity*/,
893 UErrorCode &status) const {
894 if(U_SUCCESS(status)) {
895 status = U_UNSUPPORTED_ERROR; /* Shouldn't happen, internal function */
896 }
897 return 0;
898}
899
900// UCollator private data members ----------------------------------------
901
902/* This is useless information */
903/*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/
904
905// -------------------------------------
906
907U_NAMESPACE_END
908
909#endif /* #if !UCONFIG_NO_COLLATION */
910
911/* eof */