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